def deploy_resource(resource_id, resources, stack_name): resource = resources[resource_id] client = get_client(resource) if not client: return False resource_type = get_resource_type(resource) func_details = RESOURCE_TO_FUNCTION.get(resource_type) if not func_details: LOGGER.warning('Resource type not yet implemented: %s' % resource['Type']) return func_details = func_details[ACTION_CREATE] function = getattr(client, func_details['function']) params = dict(func_details['parameters']) defaults = func_details.get('defaults', {}) if 'Properties' not in resource: resource['Properties'] = {} # print('deploying', resource_id, resource_type) for param_key, prop_keys in iteritems(dict(params)): params.pop(param_key, None) if not isinstance(prop_keys, list): prop_keys = [prop_keys] for prop_key in prop_keys: if prop_key == PLACEHOLDER_RESOURCE_NAME: # obtain physical resource name from stack resources params[param_key] = resolve_ref(stack_name, resource_id, resources, attribute='PhysicalResourceId') else: prop_value = resource['Properties'].get(prop_key) if prop_value is not None: params[param_key] = prop_value tmp_value = params.get(param_key) if tmp_value is not None: params[param_key] = resolve_refs_recursively( stack_name, tmp_value, resources) break # hack: convert to boolean if params.get(param_key) in ['True', 'False']: params[param_key] = params.get(param_key) == 'True' # assign default value if empty params = common.merge_recursive(defaults, params) # invoke function try: result = function(**params) except Exception as e: LOGGER.warning('Error calling %s with params: %s for resource: %s' % (function, params, resource)) raise e # update status set_status_deployed(resource_id, resource, stack_name) return result
def on_get(self, request): path = request.path reload = "reload" in path # get service state if reload: self.service_manager.check_all() services = { service: state.value for service, state in self.service_manager.get_states().items() } # build state dict from internal state and merge into it the service states result = dict(self.state) result = merge_recursive({"services": services}, result) return result
def on_put(self, request): data = json.loads(to_str(request.data or "{}")) # keys like "features:initScripts" should be interpreted as ['features']['initScripts'] state = defaultdict(dict) for k, v in data.items(): if ":" in k: path = k.split(":") else: path = [k] d = state for p in path[:-1]: d = state[p] d[path[-1]] = v self.state = merge_recursive(state, self.state, overwrite=True) return {"status": "OK"}
def deploy_resource(resource_id, resources, stack_name): resource = resources[resource_id] client = get_client(resource) if not client: return False resource_type = get_resource_type(resource) func_details = RESOURCE_TO_FUNCTION.get(resource_type) if not func_details: LOGGER.warning('Resource type not yet implemented: %s' % resource['Type']) return LOGGER.debug('Deploying resource type "%s" id "%s"' % (resource_type, resource_id)) func_details = func_details[ACTION_CREATE] function = getattr(client, func_details['function']) params = dict(func_details['parameters']) defaults = func_details.get('defaults', {}) if 'Properties' not in resource: resource['Properties'] = {} resource_props = resource['Properties'] for param_key, prop_keys in iteritems(dict(params)): params.pop(param_key, None) if not isinstance(prop_keys, list): prop_keys = [prop_keys] for prop_key in prop_keys: if prop_key == PLACEHOLDER_RESOURCE_NAME: # obtain physical resource name from stack resources params[param_key] = resolve_ref(stack_name, resource_id, resources, attribute='PhysicalResourceId') else: prop_value = resource_props.get(prop_key) if prop_value is not None: params[param_key] = prop_value tmp_value = params.get(param_key) if tmp_value is not None: params[param_key] = resolve_refs_recursively( stack_name, tmp_value, resources) break # hack: convert to boolean if params.get(param_key) in ['True', 'False']: params[param_key] = params.get(param_key) == 'True' # assign default value if empty params = common.merge_recursive(defaults, params) # invoke function try: result = function(**params) except Exception as e: LOGGER.warning('Error calling %s with params: %s for resource: %s' % (function, params, resource)) raise e # some resources have attached/nested resources which we need to create recursively now if resource_type == 'ApiGateway::Method': integration = resource_props.get('Integration') if integration: api_id = resolve_refs_recursively(stack_name, resource_props['RestApiId'], resources) res_id = resolve_refs_recursively(stack_name, resource_props['ResourceId'], resources) uri = integration.get('Uri') if uri: uri = resolve_refs_recursively(stack_name, uri, resources) aws_stack.connect_to_service('apigateway').put_integration( restApiId=api_id, resourceId=res_id, httpMethod=resource_props['HttpMethod'], type=integration['Type'], integrationHttpMethod=integration['IntegrationHttpMethod'], uri=uri) # update status set_status_deployed(resource_id, resource, stack_name) return result
def configure_resource_via_sdk(resource_id, resources, resource_type, func_details, stack_name): resource = resources[resource_id] client = get_client(resource, func_details) function = getattr(client, func_details['function']) params = func_details.get('parameters') or lambda_get_params() defaults = func_details.get('defaults', {}) if 'Properties' not in resource: resource['Properties'] = {} resource_props = resource['Properties'] if callable(params): params = params(resource_props, stack_name=stack_name, resources=resources) else: params = dict(params) for param_key, prop_keys in dict(params).items(): params.pop(param_key, None) if not isinstance(prop_keys, list): prop_keys = [prop_keys] for prop_key in prop_keys: if prop_key == PLACEHOLDER_RESOURCE_NAME: params[param_key] = resource_id resource_name = get_resource_name(resource) if resource_name: params[param_key] = resource_name else: # try to obtain physical resource name from stack resources try: return resolve_ref(stack_name, resource_id, resources, attribute='PhysicalResourceId') except Exception as e: LOG.debug( 'Unable to extract physical id for resource %s: %s' % (resource_id, e)) else: if callable(prop_key): prop_value = prop_key(resource_props, stack_name=stack_name, resources=resources) else: prop_value = resource_props.get(prop_key) if prop_value is not None: params[param_key] = prop_value # assign default value if empty params = common.merge_recursive(defaults, params) # convert refs and boolean strings for param_key, param_value in dict(params).items(): if param_value is not None: param_value = params[param_key] = resolve_refs_recursively( stack_name, param_value, resources) # Convert to boolean (TODO: do this recursively?) if str(param_value).lower() in ['true', 'false']: params[param_key] = str(param_value).lower() == 'true' # convert any moto account IDs (123456789012) in ARNs to our format (000000000000) params = fix_account_id_in_arns(params) # convert data types (e.g., boolean strings to bool) params = convert_data_types(func_details, params) # remove None values, as they usually raise boto3 errors params = remove_none_values(params) # invoke function try: LOG.debug('Request for resource type "%s" in region %s: %s %s' % (resource_type, aws_stack.get_region(), func_details['function'], params)) result = function(**params) except Exception as e: LOG.warning('Error calling %s with params: %s for resource: %s' % (function, params, resource)) raise e # some resources have attached/nested resources which we need to create recursively now if resource_type == 'ApiGateway::Method': integration = resource_props.get('Integration') if integration: api_id = resolve_refs_recursively(stack_name, resource_props['RestApiId'], resources) res_id = resolve_refs_recursively(stack_name, resource_props['ResourceId'], resources) uri = integration.get('Uri') if uri: uri = resolve_refs_recursively(stack_name, uri, resources) aws_stack.connect_to_service('apigateway').put_integration( restApiId=api_id, resourceId=res_id, httpMethod=resource_props['HttpMethod'], type=integration['Type'], integrationHttpMethod=integration['IntegrationHttpMethod'], uri=uri) elif resource_type == 'SNS::Topic': subscriptions = resource_props.get('Subscription', []) for subscription in subscriptions: endpoint = resolve_refs_recursively(stack_name, subscription['Endpoint'], resources) topic_arn = retrieve_topic_arn(params['Name']) aws_stack.connect_to_service('sns').subscribe( TopicArn=topic_arn, Protocol=subscription['Protocol'], Endpoint=endpoint) elif resource_type == 'S3::Bucket': tags = resource_props.get('Tags') if tags: aws_stack.connect_to_service('s3').put_bucket_tagging( Bucket=params['Bucket'], Tagging={'TagSet': tags}) return result
def deploy_resource(resource_id, resources, stack_name): resource = resources[resource_id] client = get_client(resource) if not client: return False resource_type = get_resource_type(resource) func_details = RESOURCE_TO_FUNCTION.get(resource_type) if not func_details: LOG.warning('Resource type not yet implemented: %s' % resource_type) return LOG.debug('Deploying resource type "%s" id "%s"' % (resource_type, resource_id)) func_details = func_details[ACTION_CREATE] function = getattr(client, func_details['function']) params = dict(func_details['parameters']) defaults = func_details.get('defaults', {}) if 'Properties' not in resource: resource['Properties'] = {} resource_props = resource['Properties'] for param_key, prop_keys in iteritems(dict(params)): params.pop(param_key, None) if not isinstance(prop_keys, list): prop_keys = [prop_keys] for prop_key in prop_keys: if prop_key == PLACEHOLDER_RESOURCE_NAME: params[param_key] = resource_id resource_name = get_resource_name(resource) if resource_name: params[param_key] = resource_name else: # try to obtain physical resource name from stack resources try: return resolve_ref(stack_name, resource_id, resources, attribute='PhysicalResourceId') except Exception as e: LOG.debug( 'Unable to extract physical id for resource %s: %s' % (resource_id, e)) else: if callable(prop_key): prop_value = prop_key(resource_props, stack_name=stack_name, resources=resources) else: prop_value = resource_props.get(prop_key) if prop_value is not None: params[param_key] = prop_value tmp_value = params.get(param_key) if tmp_value is not None: params[param_key] = resolve_refs_recursively( stack_name, tmp_value, resources) break # hack: convert to boolean if params.get(param_key) in ['True', 'False']: params[param_key] = params.get(param_key) == 'True' # assign default value if empty params = common.merge_recursive(defaults, params) # convert data types (e.g., boolean strings to bool) params = convert_data_types(func_details, params) # invoke function try: LOG.debug('Request for creating resource type "%s": %s' % (resource_type, params)) result = function(**params) except Exception as e: LOG.warning('Error calling %s with params: %s for resource: %s' % (function, params, resource)) raise e # some resources have attached/nested resources which we need to create recursively now if resource_type == 'ApiGateway::Method': integration = resource_props.get('Integration') if integration: api_id = resolve_refs_recursively(stack_name, resource_props['RestApiId'], resources) res_id = resolve_refs_recursively(stack_name, resource_props['ResourceId'], resources) uri = integration.get('Uri') if uri: uri = resolve_refs_recursively(stack_name, uri, resources) aws_stack.connect_to_service('apigateway').put_integration( restApiId=api_id, resourceId=res_id, httpMethod=resource_props['HttpMethod'], type=integration['Type'], integrationHttpMethod=integration['IntegrationHttpMethod'], uri=uri) elif resource_type == 'SNS::Topic': subscriptions = resource_props.get('Subscription', []) for subscription in subscriptions: endpoint = resolve_refs_recursively(stack_name, subscription['Endpoint'], resources) topic_arn = retrieve_topic_arn(params['Name']) aws_stack.connect_to_service('sns').subscribe( TopicArn=topic_arn, Protocol=subscription['Protocol'], Endpoint=endpoint) elif resource_type == 'S3::Bucket': tags = resource_props.get('Tags') if tags: aws_stack.connect_to_service('s3').put_bucket_tagging( Bucket=params['Bucket'], Tagging={'TagSet': tags}) return result
def deploy_resource(resource_id, resources, stack_name): resource = resources[resource_id] client = get_client(resource) if not client: return False resource_type = get_resource_type(resource) func_details = RESOURCE_TO_FUNCTION.get(resource_type) if not func_details: LOGGER.warning('Resource type not yet implemented: %s' % resource['Type']) return LOGGER.debug('Deploying resource type "%s" id "%s"' % (resource_type, resource_id)) func_details = func_details[ACTION_CREATE] function = getattr(client, func_details['function']) params = dict(func_details['parameters']) defaults = func_details.get('defaults', {}) if 'Properties' not in resource: resource['Properties'] = {} resource_props = resource['Properties'] for param_key, prop_keys in iteritems(dict(params)): params.pop(param_key, None) if not isinstance(prop_keys, list): prop_keys = [prop_keys] for prop_key in prop_keys: if prop_key == PLACEHOLDER_RESOURCE_NAME: # obtain physical resource name from stack resources params[param_key] = resolve_ref(stack_name, resource_id, resources, attribute='PhysicalResourceId') else: if callable(prop_key): prop_value = prop_key(resource_props) else: prop_value = resource_props.get(prop_key) if prop_value is not None: params[param_key] = prop_value tmp_value = params.get(param_key) if tmp_value is not None: params[param_key] = resolve_refs_recursively(stack_name, tmp_value, resources) break # hack: convert to boolean if params.get(param_key) in ['True', 'False']: params[param_key] = params.get(param_key) == 'True' # assign default value if empty params = common.merge_recursive(defaults, params) # invoke function try: result = function(**params) except Exception as e: LOGGER.warning('Error calling %s with params: %s for resource: %s' % (function, params, resource)) raise e # some resources have attached/nested resources which we need to create recursively now if resource_type == 'ApiGateway::Method': integration = resource_props.get('Integration') if integration: api_id = resolve_refs_recursively(stack_name, resource_props['RestApiId'], resources) res_id = resolve_refs_recursively(stack_name, resource_props['ResourceId'], resources) uri = integration.get('Uri') if uri: uri = resolve_refs_recursively(stack_name, uri, resources) aws_stack.connect_to_service('apigateway').put_integration(restApiId=api_id, resourceId=res_id, httpMethod=resource_props['HttpMethod'], type=integration['Type'], integrationHttpMethod=integration['IntegrationHttpMethod'], uri=uri ) # update status set_status_deployed(resource_id, resource, stack_name) return result