def forward_request(self, method, path, data, headers): if method == 'OPTIONS': return 200 req_data = None if method == 'POST' and path == '/': req_data = urlparse.parse_qs(to_str(data)) req_data = dict([(k, v[0]) for k, v in req_data.items()]) action = req_data.get('Action') stack_name = req_data.get('StackName') if action == 'CreateStack': event_publisher.fire_event(event_publisher.EVENT_CLOUDFORMATION_CREATE_STACK, payload={'n': event_publisher.get_hash(stack_name)}) if action == 'DeleteStack': client = aws_stack.connect_to_service('cloudformation') stack_resources = client.list_stack_resources(StackName=stack_name)['StackResourceSummaries'] template_deployer.delete_stack(stack_name, stack_resources) if action == 'DescribeStackEvents': # fix an issue where moto cannot handle ARNs as stack names (or missing names) run_fix = not stack_name if stack_name: if stack_name.startswith('arn:aws:cloudformation'): run_fix = True pattern = r'arn:aws:cloudformation:[^:]+:[^:]+:stack/([^/]+)(/.+)?' stack_name = re.sub(pattern, r'\1', stack_name) if run_fix: stack_names = [stack_name] if stack_name else self._list_stack_names() client = aws_stack.connect_to_service('cloudformation') events = [] for stack_name in stack_names: tmp = client.describe_stack_events(StackName=stack_name)['StackEvents'][:1] events.extend(tmp) events = [{'member': e} for e in events] response_content = '<StackEvents>%s</StackEvents>' % obj_to_xml(events) return make_response('DescribeStackEvents', response_content) if req_data: if action == 'ValidateTemplate': return validate_template(req_data) if action in ['CreateStack', 'UpdateStack']: do_replace_url = is_real_s3_url(req_data.get('TemplateURL')) if do_replace_url: req_data['TemplateURL'] = convert_s3_to_local_url(req_data['TemplateURL']) url = req_data.get('TemplateURL', '') is_custom_local_endpoint = is_local_service_url(url) and '://localhost:' not in url modified_template_body = transform_template(req_data) if not modified_template_body and is_custom_local_endpoint: modified_template_body = get_template_body(req_data) if modified_template_body: req_data.pop('TemplateURL', None) req_data['TemplateBody'] = modified_template_body if modified_template_body or do_replace_url: data = urlparse.urlencode(req_data, doseq=True) return Request(data=data, headers=headers, method=method) return True
def forward_request(self, method, path, data, headers): if method == 'OPTIONS': return 200 req_data = None if method == 'POST' and path == '/': req_data = urlparse.parse_qs(to_str(data)) action = req_data.get('Action')[0] if action == 'CreateStack': stack_name = req_data.get('StackName')[0] event_publisher.fire_event( event_publisher.EVENT_CLOUDFORMATION_CREATE_STACK, payload={'n': event_publisher.get_hash(stack_name)}) if action == 'DescribeStackEvents': # fix an issue where moto cannot handle ARNs as stack names (or missing names) stack_name = req_data.get('StackName') run_fix = not stack_name if stack_name: stack_name = stack_name[0] if stack_name.startswith('arn:aws:cloudformation'): run_fix = True stack_name = re.sub( r'arn:aws:cloudformation:[^:]+:[^:]+:stack/([^/]+)(/.+)?', r'\1', stack_name) if run_fix: stack_names = [ stack_name ] if stack_name else self._list_stack_names() client = aws_stack.connect_to_service('cloudformation') events = [] for stack_name in stack_names: tmp = client.describe_stack_events( StackName=stack_name)['StackEvents'][:1] events.extend(tmp) events = [{'member': e} for e in events] response_content = '<StackEvents>%s</StackEvents>' % obj_to_xml( events) return make_response('DescribeStackEvents', response_content) if req_data: if action == 'ValidateTemplate': return validate_template(req_data) if action == 'CreateStack': modified_request = transform_template(req_data) if modified_request: req_data.pop('TemplateURL', None) req_data['TemplateBody'] = json.dumps(modified_request) data = urlparse.urlencode(req_data, doseq=True) return Request(data=data, headers=headers, method=method) return True
def forward_request(self, method, path, data, headers): req_data = None if method == 'POST' and path == '/': req_data = urlparse.parse_qs(to_str(data)) action = req_data.get('Action')[0] if action == 'DescribeStackEvents': # fix an issue where moto cannot handle ARNs as stack names (or missing names) stack_name = req_data.get('StackName') run_fix = not stack_name if stack_name: stack_name = stack_name[0] if stack_name.startswith('arn:aws:cloudformation'): run_fix = True stack_name = re.sub( r'arn:aws:cloudformation:[^:]+:[^:]+:stack/([^/]+)(/.+)?', r'\1', stack_name) if run_fix: stack_names = [ stack_name ] if stack_name else self._list_stack_names() client = aws_stack.connect_to_service('cloudformation') events = [] for stack_name in stack_names: tmp = client.describe_stack_events( StackName=stack_name)['StackEvents'][:1] events.extend(tmp) events = [{'member': e} for e in events] response_content = '<StackEvents>%s</StackEvents>' % obj_to_xml( events) return make_response('DescribeStackEvents', response_content) if req_data: if action == 'ValidateTemplate': return validate_template(req_data) return True
def forward_request(self, method, path, data, headers): if method == 'OPTIONS': return 200 data = data or '' data_orig = data data = aws_stack.fix_account_id_in_arns( data, existing='%3A{}%3Astack/'.format(TEST_AWS_ACCOUNT_ID), replace='%3A{}%3Astack/'.format(MOTO_CLOUDFORMATION_ACCOUNT_ID), colon_delimiter='') data = aws_stack.fix_account_id_in_arns( data, existing='%3A{}%3AchangeSet/'.format(TEST_AWS_ACCOUNT_ID), replace='%3A{}%3AchangeSet/'.format( MOTO_CLOUDFORMATION_ACCOUNT_ID), colon_delimiter='') data = aws_stack.fix_account_id_in_arns(data, existing=TEST_AWS_ACCOUNT_ID, replace=MOTO_ACCOUNT_ID, colon_delimiter='%3A') req_data = None if method == 'POST' and path == '/': req_data = urlparse.parse_qs(to_str(data)) req_data = dict([(k, v[0]) for k, v in req_data.items()]) action = req_data.get('Action') stack_name = req_data.get('StackName') if action == 'CreateStack': event_publisher.fire_event( event_publisher.EVENT_CLOUDFORMATION_CREATE_STACK, payload={'n': event_publisher.get_hash(stack_name)}) if action == 'DeleteStack': client = aws_stack.connect_to_service('cloudformation') stack_resources = client.list_stack_resources( StackName=stack_name)['StackResourceSummaries'] template_deployer.delete_stack(stack_name, stack_resources) if action == 'DescribeStackEvents': # fix an issue where moto cannot handle ARNs as stack names (or missing names) run_fix = not stack_name if stack_name: if stack_name.startswith('arn:aws:cloudformation'): run_fix = True pattern = r'arn:aws:cloudformation:[^:]+:[^:]+:stack/([^/]+)(/.+)?' stack_name = re.sub(pattern, r'\1', stack_name) if run_fix: stack_names = [ stack_name ] if stack_name else self._list_stack_names() client = aws_stack.connect_to_service('cloudformation') events = [] for stack_name in stack_names: tmp = client.describe_stack_events( StackName=stack_name)['StackEvents'][:1] events.extend(tmp) events = [{'member': e} for e in events] response_content = '<StackEvents>%s</StackEvents>' % obj_to_xml( events) return make_response('DescribeStackEvents', response_content) if req_data: if action == 'ValidateTemplate': return validate_template(req_data) if action in ['CreateStack', 'UpdateStack', 'CreateChangeSet']: modified = prepare_template_body(req_data) if modified: data = urlparse.urlencode(req_data, doseq=True) return Request(data=data, headers=headers, method=method) if data != data_orig or action in [ 'DescribeChangeSet', 'ExecuteChangeSet' ]: return Request(data=urlparse.urlencode(req_data, doseq=True), headers=headers, method=method) return True