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
Esempio n. 2
0
    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
Esempio n. 3
0
    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