def upload_apigateway(self, json, dryrun): """ This function uploads an apigateway json to aws, and creates needed changes :param json: the json object :type json: json object :param dryrun: a boolean object if changes need to be made :type dryrun: bool :return: None """ from wrapper.apigateway import Apigateway apigateway = Apigateway(session=self.session, dryrun=dryrun) logger.debug("Testing if rest api exists") if apigateway.apigateway_exists(name=json['name']): logger.debug("Need to test if description needs to be updated") rest_api = apigateway.get_rest_api_by_name(name=json['name']) rest_api_id = rest_api['id'] if rest_api['description'] != json['description']: logger.info("Need to update the description") resp = apigateway.update_rest_api(restid=rest_api_id, operation=[{ 'op': 'replace', 'path': '/description', 'value': json['description'] }]) else: rest_api_create_resp = apigateway.create_rest_api( name=json['name'], desc=json['description']) rest_api_id = rest_api_create_resp['id'] if dryrun: logger.warning( "Whole resource needs to be created, no point in continue") return None logger.info("The rest api id we are going to work on: %s" % rest_api_id) resource_hash = apigateway.generate_resourcehash(restid=rest_api_id) root_id = resource_hash['/'] for resource in json['resources']: if resource['path'] not in resource_hash: logger.info("Need to create path in apigateway") resource_data = apigateway.create_resource( restid=rest_api_id, parentid=root_id, pathpart=resource['pathPart']) resource_hash[resource['path']] = resource_data['id'] for method in resource['resourceMethods']: apigateway.compare_method( restid=rest_api_id, resourceid=resource_hash[resource['path']], method=method, json_data=resource['resourceMethods'][method]) resource_hash.pop(resource['path']) for remaining_resource in resource_hash: logger.warning( "Need to delete following resources since not defined") apigateway.delete_resource( restid=rest_api_id, resourceid=resource_hash[remaining_resource])
def query_information(self, query): ''' This function is used to print debug information about a query, to see if it was succesful or not :param query: The boto3 query :return: Query with removed metadata ''' if query['ResponseMetadata']['HTTPStatusCode'] == 201: logger.debug("Resource was succesfully created") logger.info("Query RequestID: %s, HTTPStatusCode: %s" % ( query['ResponseMetadata']['RequestId'], query['ResponseMetadata']['HTTPStatusCode'])) elif query['ResponseMetadata']['HTTPStatusCode'] == 202: logger.debug('Request accepted but processing later.') logger.info("Query RequestID: %s, HTTPStatusCode: %s" % ( query['ResponseMetadata']['RequestId'], query['ResponseMetadata']['HTTPStatusCode'])) elif query['ResponseMetadata']['HTTPStatusCode'] == 204: logger.debug('Request done but no content returned.') logger.info("Query RequestID: %s, HTTPStatusCode: %s" % ( query['ResponseMetadata']['RequestId'], query['ResponseMetadata']['HTTPStatusCode'])) elif query['ResponseMetadata']['HTTPStatusCode'] != 200: logger.warning('There was an issue with request.') logger.warning("Query RequestID: %s, HTTPStatusCode: %s" % ( query['ResponseMetadata']['RequestId'], query['ResponseMetadata']['HTTPStatusCode'])) else: logger.debug("Request had no issues") logger.debug("Query RequestID: %s, HTTPStatusCode: %s" % ( query['ResponseMetadata']['RequestId'], query['ResponseMetadata']['HTTPStatusCode'])) query.pop('ResponseMetadata') if 'NextToken' in query: logger.error("Token is present. Paging needs to be implemented") return query
def gather_information_for_cloudofrmation_parameters(stack_data, vpc, ami): parameters = [] env = Misc.get_value_from_array_hash(dictlist=vpc.get('Tags'), key="Environment") if 'cloudformation_parameters' in stack_data: for parameter in stack_data['cloudformation_parameters']: if parameter["ParameterKey"] == "Environment": parameters.append({"ParameterKey": "Environment", "ParameterValue": env, "UsePreviousValue": False}) elif parameter["ParameterKey"] == "InstanceType": instance = None if 'instance_type' in stack_data and env in stack_data['instance_type']: instance = stack_data["instance_type"][env] else: instance = Misc.get_value_from_array_hash(dictlist=ami.get('Tags'), key="Instancetype") parameters.append( {"ParameterKey": "InstanceType", "ParameterValue": instance, "UsePreviousValue": False}) elif parameter["ParameterKey"] == "Puppetrole": parameters.append({"ParameterKey": "Puppetrole", "ParameterValue": stack_data['puppet_role'], "UsePreviousValue": False}) elif parameter["ParameterKey"] == "XivelyService": parameters.append({"ParameterKey": "XivelyService", "ParameterValue": stack_data['xively_service'], "UsePreviousValue": False}) elif parameter["ParameterKey"] == "Ami": parameters.append( {"ParameterKey": "Ami", "ParameterValue": stack_data['ami'], "UsePreviousValue": False}) elif parameter["ParameterKey"] == "KeyName": key = Misc.get_value_from_array_hash(dictlist=vpc.get('Tags'), key="Keypair") parameters.append({"ParameterKey": "KeyName", "ParameterValue": key, "UsePreviousValue": False}) else: parameter["UsePreviousValue"] = False parameters.append(parameter) else: logger.warning(msg="No cloudformation parameter object in json") logger.debug(msg="Cloudformation parameters is: %s" % (parameters,)) return parameters
def query_information(self, query): ''' This function is used to print debug information about a query, to see if it was succesful or not :param query: The boto3 query :return: Query with removed metadata ''' if query['ResponseMetadata']['HTTPStatusCode'] == 201: logger.debug("Resource was succesfully created") logger.info("Query RequestID: %s, HTTPStatusCode: %s" % (query['ResponseMetadata']['RequestId'], query['ResponseMetadata']['HTTPStatusCode'])) elif query['ResponseMetadata']['HTTPStatusCode'] == 202: logger.debug('Request accepted but processing later.') logger.info("Query RequestID: %s, HTTPStatusCode: %s" % (query['ResponseMetadata']['RequestId'], query['ResponseMetadata']['HTTPStatusCode'])) elif query['ResponseMetadata']['HTTPStatusCode'] == 204: logger.debug('Request done but no content returned.') logger.info("Query RequestID: %s, HTTPStatusCode: %s" % (query['ResponseMetadata']['RequestId'], query['ResponseMetadata']['HTTPStatusCode'])) elif query['ResponseMetadata']['HTTPStatusCode'] != 200: logger.warning('There was an issue with request.') logger.warning("Query RequestID: %s, HTTPStatusCode: %s" % (query['ResponseMetadata']['RequestId'], query['ResponseMetadata']['HTTPStatusCode'])) else: logger.debug("Request had no issues") logger.debug("Query RequestID: %s, HTTPStatusCode: %s" % (query['ResponseMetadata']['RequestId'], query['ResponseMetadata']['HTTPStatusCode'])) query.pop('ResponseMetadata') if 'NextToken' in query: logger.error("Token is present. Paging needs to be implemented") return query
def get_method_response(self, restid, resourceid, method, statuscode): """ This function returns a method response object :param method: the method that is requested :type method: basestring :param restid: the id of the rest api object :type restid: basestring :param resourceid: id of a single resource object :type resourceid: basestring :param statuscode: the statuscode requested :type statuscode: basestring :return: None if not found, else the object """ try: ret = self.apigateway_client.get_method_response(restApiId=restid, resourceId=resourceid, httpMethod=method, statusCode=statuscode) super(Apigateway, self).query_information(query=ret) logger.debug("We found the method response") except Exception as e: # https://github.com/aws/aws-cli/issues/1620 if e.response['Error']['Code'] == "NotFoundException": logger.warning("Method response %s for resource %s does not exist" % (statuscode, resourceid)) else: logger.error("%s" % e, ) ret = None return ret
def create_policy_version(self, arn, statement, dryrun, setasdefault=True): if dryrun: logger.warning("Dryrun requested for creating policy version %s" % (arn,)) return None document = {'Version': '2012-10-17', 'Statement': statement} document = Misc.convert_to_json(document) resp = self.iam.create_policy_version(PolicyArn=arn, PolicyDocument=document, SetAsDefault=setasdefault) return resp['PolicyVersion']
def create_policy(self, name, statement, description, dryrun, path="/"): if dryrun: logger.warning("Dryrun requested, not creating %s resource: %s" % (name, str(statement))) return None document = {'Version': '2012-10-17', 'Statement': statement} document = Misc.convert_to_json(document) print document resp = self.iam.create_policy(PolicyName=name, Path=path, PolicyDocument=document, Description=description) return resp['Policy']
def get_bucket_tagging(self, name): try: resp = self.s3.get_bucket_tagging(Bucket=name) except Exception as e: if "An error occurred (NoSuchTagSet)" in e: logger.warning("Bucket %s has no Tag configuration" % (name,)) else: logger.error("%s" % e, ) return None return resp['TagSet']
def change_record_for_zoneid(self, zoneid=None, changebatch=None, dryrun=None): if dryrun: logger.debug("Dryrun requested") logger.warning("Not running changebatch: %s" % changebatch, ) return True ret = self.boto3.change_resource_record_sets(HostedZoneId=zoneid, ChangeBatch=changebatch) if ret['ResponseMetadata']['HTTPStatusCode'] == 200: logger.info("Change was succesful") else: logger.error("There was an issue with the change")
def get_policy(self, arn=None): try: resp = self.iam.get_policy(PolicyArn=arn) except Exception as e: if "An error occurred (NoSuchEntity) when calling the GetPolicy operation" in e: logger.warning("Policy does not exist %s" % arn, ) else: logger.error("%s" % e, ) return None return resp['Policy']
def get_object(self, bucket_name, key): try: resp = self.s3.get_object(Bucket=bucket_name, Key=key) except Exception as e: if "An error occurred (NoSuchKey)" in e: logger.warning("Object %s in s3 bucket %s does not exist" % (key, bucket_name)) else: logger.error("%s" % e, ) return None return resp
def get_elb_tags(self, name=None): while True: try: resp = self.elb.describe_tags(LoadBalancerNames=[name]) except Exception as e: logger.warning("ELB describeTags through an error, retrying") continue break tags = resp['TagDescriptions'][0]['Tags'] return tags
def get_bucket_lifecycle(self, name): try: resp = self.s3.get_bucket_lifecycle(Bucket=name) except Exception as e: if "An error occurred (NoSuchLifecycleConfiguration)" in e: logger.warning("Bucket %s has no Lifecycle configuration" % (name,)) else: logger.error("%s" % e, ) return None return resp['Rules']
def get_bucket_policy(self, name): try: resp = self.s3.get_bucket_policy(Bucket=name) except Exception as e: if "An error occurred (NoSuchBucketPolicy)" in e: logger.warning("Bucket %s has no policy configuration" % (name,)) else: logger.error("%s" % e, ) return None return resp
def get_bucket_replication(self, name): try: resp = self.s3.get_bucket_replication(Bucket=name) except Exception as e: if "An error occurred (ReplicationConfigurationNotFoundError)" in e: logger.warning("Bucket %s has no replication configuration" % (name,)) else: logger.error("%s" % e, ) return None return resp
def get_elb_tags(self, name): while True: try: resp = self.elb_client.describe_tags(LoadBalancerNames=[name]) except Exception as e: logger.warning("ELB describeTags through an error, retrying") continue break super(Elb, self).query_information(query=resp) tags = resp['TagDescriptions'][0]['Tags'] return tags
def stop_instances(self,instanceids,dryrun): try: resp = self.ec2_client.stop_instances(DryRun=dryrun, InstanceIds=instanceids) super(Ec2, self).query_information(query=resp) except Exception as e: logger.warning("Exception for Stopping %s" % (e)) return True ret = [] for i in resp['StoppingInstances']: ret.append({'id': i['InstanceId'], 'cur_state': i['CurrentState']['Name'], 'prev_state': i['PreviousState']['Name']}) return ret
def get_server_cert_for_env(self, env=None): certs = self.get_server_certs() v = Vpc() vpc = v.get_vpc_from_env(env=env) domain = Misc.get_value_from_array_hash(dictlist=vpc['Tags'], key='Domain') cert_name = "star." + domain logger.debug("Searching for cert domain %s" % cert_name, ) for c in certs: logger.debug("Investigateing Cert %s" % c, ) if c['ServerCertificateName'] == cert_name: logger.debug("We found the server certificate we are looking for") return c logger.warning("Could not find the certificate for %s" % env, ) return None
def create_iam_user(self, username, dryrun, path="/"): """ This function creates an iam user :param username: The requeted username for the usre :param dryrun: No changes should be done :param path: The pathin IAM to create the user :return: a boto3.user object with the created user details """ if dryrun: logger.warning("Dryrun requested for creating user %s" % (username,)) return None resp = self.iam_client.create_user(Path=path, UserName=username) super(Iam, self).query_information(query=resp) return resp['User']
def create_iam_user(self, username, dryrun, path="/"): """ This function creates an iam user :param username: The requeted username for the usre :param dryrun: No changes should be done :param path: The pathin IAM to create the user :return: a boto3.user object with the created user details """ if dryrun: logger.warning("Dryrun requested for creating user %s" % (username, )) return None resp = self.iam_client.create_user(Path=path, UserName=username) super(Iam, self).query_information(query=resp) return resp['User']
def get_stream_tags(self, streamname): """ This function queries a streams tags :param streamname: The requested streams name :return: the requested streams tags """ while True: try: resp = self.kinesis_client.list_tags_for_stream(StreamName=streamname) except Exception as e: logger.warning("Kinesis list_tags_for_stream through an error, retrying") continue break super(Kinesis, self).query_information(query=resp) tags = resp['Tags'] return tags
def stop_instances(self, instanceids, dryrun): try: resp = self.ec2_client.stop_instances(DryRun=dryrun, InstanceIds=instanceids) super(Ec2, self).query_information(query=resp) except Exception as e: logger.warning("Exception for Stopping %s" % (e)) return True ret = [] for i in resp['StoppingInstances']: ret.append({ 'id': i['InstanceId'], 'cur_state': i['CurrentState']['Name'], 'prev_state': i['PreviousState']['Name'] }) return ret
def update_stack(self, stackname, parameters, dryrun, templatebody=None, templateurl=None): if dryrun: logger.warning("Dryrun requested not updateing stack: %s" % (stackname,)) return None args = {'StackName': stackname, "Capabilities": ['CAPABILITY_IAM' ]} if parameters: args['Parameters'] = parameters if templatebody: args['TemplateBody'] = json.dumps(templatebody) elif templateurl: args['TemplateUrl'] = templateurl else: logger.error("No body or URL given for stack") raise ValueError resp = self.cloudformation_client.update_stack(**args) super(Cloudformation, self).query_information(query=resp) return resp['StackId']
def start_instances(self, environment=None, puppet_role=None, xively_service=None, dry_run=None): filters = [{ 'Name': 'tag:Environment', 'Values': [environment] }, { 'Name': 'tag:Puppet_role', 'Values': [puppet_role] }] if xively_service: filters.append({ 'Name': 'tag:Xively_service', 'Values': [xively_service] }) e = Ec2() res = e.get_all_instances(filters=filters) candidate_ids = [] for instance in res: if instance['State']['Name'] == 'stopped': candidate_ids.append(instance['InstanceId']) if len(candidate_ids) == 0: logger.warning("Couldn't find any instances to start") return [] if not dry_run: logger.info("Instances would start: {0}".format(candidate_ids)) res = e.start_instances(instance_ids=candidate_ids) if not ('StartingInstances' in res): logger.error( "No instance started, error happened, result:{0}".format( res)) return [] result = [] for instance in res['StartingInstances']: result.append({ 'InstanceId': instance['InstanceId'], 'State': instance['CurrentState']['Name'] }) return result else: logger.info("Instances would start: {0}".format(candidate_ids)) return []
def get_stream_tags(self, streamname): """ This function queries a streams tags :param streamname: The requested streams name :return: the requested streams tags """ while True: try: resp = self.kinesis_client.list_tags_for_stream( StreamName=streamname) except Exception as e: logger.warning( "Kinesis list_tags_for_stream through an error, retrying") continue break super(Kinesis, self).query_information(query=resp) tags = resp['Tags'] return tags
def create_bucket(self, name, location=None,dryrun=False): """ This function creates an s3 bucket :param name: This should be the name of the bucket :type name: basestring :param location: the location where the bucket should be constrained to, not used if us-east-1 value :type location: basestring :return: """ if dryrun: logger.warning("Dryrun requested for creating bucket %s" % (name,)) return None if location and location != "us-east-1": resp = self.s3_client.create_bucket(Bucket=name, CreateBucketConfiguration={'LocationConstraint': location}) else: resp = self.s3_client.create_bucket(Bucket=name) super(S3, self).query_information(query=resp) resp.pop('ResponseMetadata') return resp
def get_active_envs(self, env=None): """ This function returns an array with the active environemnts in the account :param env: a comma seperated list of environments that should be validated :type env: basestring :return: An array with active environments :rtype: list """ vpcs = self.get_all_vpcs() envs = [] for vpc in vpcs: cur = Misc.get_value_from_array_hash(dictlist=vpc['Tags'], key='Environment') if cur != "": envs.append(cur) else: logger.warning("Vpc has no Environment tag: %s" % (vpc.id)) if env: envs = [env] logger.debug("Current envs: " + str(envs)) return envs
def parse_service_columns(service, columns): """ This function parses requested columns, and only returns supported columns :param service: The service that should be used :param columns: The requested columns :return: a list of keys that are supported and requested :rtype: list """ supported_columns = get_supported_columns(service=service) ret = [] if isinstance(columns, basestring) and columns: list_from_array = string_to_array(string=columns, split_char=",") for l in list_from_array: if supported_columns.has_key(l): ret.append(l) else: logger.warning("Column requested is not supported: %s" % l, ) else: ret = supported_columns.keys() return ret
def create_bucket(self, name, location=None, dryrun=False): """ This function creates an s3 bucket :param name: This should be the name of the bucket :type name: basestring :param location: the location where the bucket should be constrained to, not used if us-east-1 value :type location: basestring :return: """ if dryrun: logger.warning("Dryrun requested for creating bucket %s" % (name, )) return None if location and location != "us-east-1": resp = self.s3_client.create_bucket( Bucket=name, CreateBucketConfiguration={'LocationConstraint': location}) else: resp = self.s3_client.create_bucket(Bucket=name) super(S3, self).query_information(query=resp) resp.pop('ResponseMetadata') return resp
def get_integration(self, restid, resourceid, method): """ This function returns an integration object :param method: the method that is requested :type method: basestring :param restid: the id of the rest api object :type restid: basestring :param resourceid: id of a single resource object :type resourceid: basestring :return: None if not found, else the object """ try: ret = self.apigateway_client.get_integration(restApiId=restid, resourceId=resourceid, httpMethod=method) super(Apigateway, self).query_information(query=ret) logger.debug("Found the integration object") except Exception as e: if e.response['Error']['Code'] == "NotFoundException": logger.warning("Method integration for %s method does not exist" % (method)) else: logger.error("%s" % e, ) ret = None return ret
def update_stack(self, stackname, parameters, dryrun, templatebody=None, templateurl=None): if dryrun: logger.warning("Dryrun requested not updateing stack: %s" % (stackname, )) return None args = {'StackName': stackname, "Capabilities": ['CAPABILITY_IAM']} if parameters: args['Parameters'] = parameters if templatebody: args['TemplateBody'] = json.dumps(templatebody) elif templateurl: args['TemplateUrl'] = templateurl else: logger.error("No body or URL given for stack") raise ValueError resp = self.cloudformation_client.update_stack(**args) super(Cloudformation, self).query_information(query=resp) return resp['StackId']
def add_instance_to_elb(self, name=None, instances=None, dryrun=False): if dryrun: logger.warning("Dryrun requested: elb: %s, instances: %s" % (name, instances)) return True ret = self.elb.register_instances_with_load_balancer(LoadBalancerName=name, Instances=instances) logger.debug("Ret is: %s" % ret, )
def detach_policy_from_user(self, username, policyarn, dryrun): if dryrun: logger.warning("Dryrun requested for detaching policy %s from user %s" % (policyarn, username)) return None resp = self.iam.detach_user_policy(UserName=username, PolicyArn=policyarn) return resp
def create_user_credentials(self, username=None, dryrun=None): if dryrun: logger.warning("Dryrun requested for creation of user credentials for %s" % (username)) return None resp = self.iam.create_access_key(UserName=username) return resp['AccessKey']
def gather_information_for_cloudofrmation_parameters(stack_data, vpc, ami): parameters = [] env = Misc.get_value_from_array_hash(dictlist=vpc.get('Tags'), key="Environment") if 'cloudformation_parameters' in stack_data: for parameter in stack_data['cloudformation_parameters']: if parameter["ParameterKey"] == "Environment": parameters.append({ "ParameterKey": "Environment", "ParameterValue": env, "UsePreviousValue": False }) elif parameter["ParameterKey"] == "InstanceType": instance = None if 'instance_type' in stack_data and env in stack_data[ 'instance_type']: instance = stack_data["instance_type"][env] else: instance = Misc.get_value_from_array_hash( dictlist=ami.get('Tags'), key="Instancetype") parameters.append({ "ParameterKey": "InstanceType", "ParameterValue": instance, "UsePreviousValue": False }) elif parameter["ParameterKey"] == "Puppetrole": parameters.append({ "ParameterKey": "Puppetrole", "ParameterValue": stack_data['puppet_role'], "UsePreviousValue": False }) elif parameter["ParameterKey"] == "XivelyService": parameters.append({ "ParameterKey": "XivelyService", "ParameterValue": stack_data['xively_service'], "UsePreviousValue": False }) elif parameter["ParameterKey"] == "Ami": parameters.append({ "ParameterKey": "Ami", "ParameterValue": stack_data['ami'], "UsePreviousValue": False }) elif parameter["ParameterKey"] == "KeyName": key = Misc.get_value_from_array_hash(dictlist=vpc.get('Tags'), key="Keypair") parameters.append({ "ParameterKey": "KeyName", "ParameterValue": key, "UsePreviousValue": False }) else: parameter["UsePreviousValue"] = False parameters.append(parameter) else: logger.warning(msg="No cloudformation parameter object in json") logger.debug(msg="Cloudformation parameters is: %s" % (parameters, )) return parameters
def delete_policy_version(self, arn, version, dryrun): if dryrun: logger.warning("Dryrun requested for deleting policy %s version: %s" % (arn, version)) return None resp = self.iam.delete_policy_version(PolicyArn=arn, VersionId=version) return resp
def compare_method(self, restid, resourceid, method, json_data): """ This function compares a json data to the current method to detect an updates that need to be done :param method: the method that is requested :type method: basestring :param restid: the id of the rest api object :type restid: basestring :param resourceid: id of a single resource object :type resourceid: basestring :param json_data: the json data from the model that is the representation of the current state :type json_data: dict :return: None """ logger.info("Looking at restid: %s, resourceid: %s, and method: %s" % (restid, resourceid, method)) # First we test if the top level method is created or we need to create it if not self.method_exists(restid=restid, resourceid=resourceid, method=method): logger.info("Need to create method: %s" % method) cur_method = self.create_method(restid=restid, resourceid=resourceid, method=method, authorizationtype=json_data['authorizationType'], further_opts=json_data) else: cur_method = self.get_method(restid=restid, resourceid=resourceid, method=method) logger.info("Method existed, need to compare for changes") for element in ['authorizationType', 'apiKeyRequired', 'requestParameters', 'requestModels']: if (element in json_data and element in cur_method) and json_data[element] != cur_method[element]: logger.warning("Need to update %s" % element) self.update_method(restid=restid, resourceid=resourceid, method=method, operation=[ {'op': 'replace', 'path': "/%s" % element, 'value': json_data[element]}]) if element not in json_data: logger.debug("Upload template missing key %s, skipping" % element) if element not in cur_method and element in json_data: logger.warning("Not defined in current method need to update current method with %s" % element) # Check if method needs to be deleted if 'methodResponses' in cur_method: for statuscode in cur_method['methodResponses']: if statuscode not in json_data['methodResponses']: logger.warning("This method response needs to be deleted %s" % statuscode) self.delete_method_response(restid=restid, resourceid=resourceid, method=method, statuscode=statuscode) # iterate over status codes and check we need to create or update for statuscode in json_data['methodResponses']: if not self.method_response_exists(restid=restid, resourceid=resourceid, method=method, statuscode=statuscode): logger.debug("Creating method response %s" % statuscode) self.create_method_response(restid=restid, resourceid=resourceid, method=method, statuscode=statuscode, further_ops=json_data['methodResponses'][statuscode]) else: cur_response = self.get_method_response(restid=restid, resourceid=resourceid, method=method, statuscode=statuscode) logger.debug("Need to compare the responses") dictdiffer = DictDiffer(cur_response, json_data['methodResponses'][statuscode]) for remove_statuscode in dictdiffer.added(): logger.info("Need to remove statuscode: %s" % remove_statuscode) self.delete_method_response(restid=restid, resourceid=resourceid, method=method, statuscode=remove_statuscode) for add_statuscode in dictdiffer.removed(): logger.info("Need to add statuscode: %s" % add_statuscode) self.create_method_response(restid=restid, resourceid=resourceid, method=method, statuscode=add_statuscode, further_ops=json_data['methodResponses'][add_statuscode]) for changed_statuscode in dictdiffer.changed(): logger.info("Need to update statuscode: %s" % changed_statuscode) cur_method_statuscode = cur_method['methodResponses'][changed_statuscode] json_data_statuscode = json_data['methodmethod']['methodResponses'][changed_statuscode] for element in ['responseParameters', 'responseTemplates']: if element not in json_data_statuscode: continue change_dictdiffer = DictDiffer( cur_method_statuscode[element], json_data_statuscode[element]) for add_int_statuscode in change_dictdiffer.removed(): logger.info("method response is missing, adding: %s" % add_int_statuscode) self.update_method_response(restid=restid, resourceid=resourceid, method=method, statuscode=changed_statuscode, operation=[ {'op': 'add', 'path': "/%s/%s" % (element, add_int_statuscode), 'value': json_data_statuscode[element][add_int_statuscode]}]) for remove_int_statuscode in change_dictdiffer.added(): logger.info("Method response is present, deleting: %s" % remove_int_statuscode) self.update_method_response(restid=restid, resourceid=resourceid, method=method, statuscode=changed_statuscode, operation=[ {'op': 'remove', 'path': "/%s/%s" % (element, remove_int_statuscode)}]) for change_int_statuscode in change_dictdiffer.changed(): logger.info("There is a change in value, need to update: %s" % change_int_statuscode) self.update_method_response(restid=restid, resourceid=resourceid, method=method, statuscode=changed_statuscode, operation=[ {'op': 'replace', 'path': "/%s/%s" % (element, change_int_statuscode), 'value': json_data_statuscode[element][change_int_statuscode]}]) # method integration if self.integration_exists(restid=restid, resourceid=resourceid, method=method): cur_method_integration = self.get_integration(restid=restid, resourceid=resourceid, method=method) dictdiffer_integration_response = DictDiffer(cur_method_integration['integrationResponses'], json_data['methodIntegration']['integrationResponses']) for remove_response in dictdiffer_integration_response.added(): logger.info("Need to remove integration response: %s" % remove_response) self.delete_integration_response(restid=restid, resourceid=resourceid, method=method, statuscode=remove_response) for add_response in dictdiffer_integration_response.removed(): logger.info("Need to add integration response: %s" % add_response) self.create_integration_response(restid=restid, resourceid=resourceid, method=method, statuscode=add_response, further_opts=json_data['methodIntegration']['integrationResponses'][ add_response]) for changed_response in dictdiffer_integration_response.changed(): logger.info("Need to change response value: %s" % changed_response) cur_method_integration_response = cur_method_integration['integrationResponses'][changed_response] json_data_integration_response = json_data['methodIntegration']['integrationResponses'][ changed_response] if 'selectionPattern' in cur_method_integration_response: if (cur_method_integration_response['selectionPattern'] != json_data_integration_response['selectionPattern']): logger.debug("selectionPattern needs to be updated") self.update_integration_response(restid=restid, resourceid=resourceid, method=method, statuscode=changed_response, operation=[ {'op': 'replace', 'path': '/selectionPattern', 'value': json_data_integration_response['selectionPattern']}]) for element in ['responseParameters', 'responseTemplates']: if element not in json_data_integration_response: continue change_dictdiffer = DictDiffer( cur_method_integration_response[element], json_data_integration_response[element]) for add_int_response in change_dictdiffer.removed(): logger.debug("Need to add the integration response: %s" % add_int_response) self.update_integration_response(restid=restid, resourceid=resourceid, method=method, statuscode=changed_response, operation=[ {'op': 'add', 'path': "/%s/%s" % (element, add_int_response), 'value': json_data_integration_response[element][add_int_response]}]) for remove_int_response in change_dictdiffer.added(): logger.debug("Need to remove the integration response: %s" % remove_int_response) self.update_integration_response(restid=restid, resourceid=resourceid, method=method, statuscode=changed_response, operation=[ {'op': 'remove', 'path': "/%s/%s" % (element, remove_int_response)}]) for change_int_response in change_dictdiffer.changed(): logger.debug("Need to update the integration response: %s" % change_int_response) self.update_integration_response(restid=restid, resourceid=resourceid, method=method, statuscode=changed_response, operation=[ {'op': 'replace', 'path': "/%s/%s" % (element, change_int_response), 'value': json_data_integration_response[element][change_int_response]}]) else: logger.debug("Need to create method integration") cur_method_integration = self.create_integration(restid=restid, resourceid=resourceid, method=method, integration_type=json_data['methodIntegration'][ 'type'], further_opts=json_data['methodIntegration']) for integration_response in json_data['methodIntegration']['integrationResponses']: logger.debug("Need to create the method integrations for the new method") self.create_integration_response(restid=restid, resourceid=resourceid, method=method, statuscode=integration_response, further_opts= json_data['methodIntegration']['integrationResponses'][ integration_response]) logger.info("Done with updates") return None