コード例 #1
0
def get_template_summary(req_params):
    stack_name = req_params.get('StackName')
    stack = None
    if stack_name:
        stack = find_stack(stack_name)
        if not stack:
            return stack_not_found_error(stack_name)
    template_deployer.prepare_template_body(req_params)
    template = template_preparer.parse_template(req_params['TemplateBody'])
    req_params['StackName'] = 'tmp-stack'
    stack = Stack(req_params, template)
    result = stack.describe_details()
    id_summaries = {}
    for resource_id, resource in stack.template_resources.items():
        res_type = resource['Type']
        id_summaries[res_type] = id_summaries.get(res_type) or []
        id_summaries[res_type].append(resource_id)
    result['ResourceTypes'] = list(id_summaries.keys())
    result['ResourceIdentifierSummaries'] = [{
        'ResourceType': key,
        'LogicalResourceIds': {
            'member': values
        }
    } for key, values in id_summaries.items()]
    return result
コード例 #2
0
def create_stack(req_params):
    state = CloudFormationRegion.get()
    template_deployer.prepare_template_body(req_params)
    template = template_preparer.parse_template(req_params['TemplateBody'])
    stack_name = template['StackName'] = req_params.get('StackName')
    stack = Stack(req_params, template)

    # find existing stack with same name, and remove it if this stack is in DELETED state
    existing = ([s for s in state.stacks.values() if s.stack_name == stack_name] or [None])[0]
    if existing:
        if 'DELETE' not in existing.status:
            return error_response('Stack named "%s" already exists with status "%s"' % (
                stack_name, existing.status), code=400, code_string='ValidationError')
        state.stacks.pop(existing.stack_id)

    state.stacks[stack.stack_id] = stack
    LOG.debug('Creating stack "%s" with %s resources ...' % (stack.stack_name, len(stack.template_resources)))
    deployer = template_deployer.TemplateDeployer(stack)
    try:
        deployer.deploy_stack()
    except Exception as e:
        stack.set_stack_status('CREATE_FAILED')
        msg = 'Unable to create stack "%s": %s' % (stack.stack_name, e)
        LOG.debug('%s %s' % (msg, traceback.format_exc()))
        return error_response(msg, code=400, code_string='ValidationError')
    result = {'StackId': stack.stack_id}
    return result
コード例 #3
0
def create_change_set(req_params):
    stack_name = req_params.get('StackName')
    template_deployer.prepare_template_body(req_params)
    template = template_preparer.parse_template(req_params.pop('TemplateBody'))
    template['StackName'] = stack_name
    template['ChangeSetName'] = req_params.get('ChangeSetName')
    stack = existing = find_stack(stack_name)
    if not existing:
        # automatically create (empty) stack if none exists yet
        state = CloudFormationRegion.get()
        empty_stack_template = dict(template)
        empty_stack_template['Resources'] = {}
        req_params_copy = clone_stack_params(req_params)
        stack = Stack(req_params_copy, empty_stack_template)
        state.stacks[stack.stack_id] = stack
        stack.set_stack_status('CREATE_COMPLETE')
    change_set = StackChangeSet(req_params, template)
    deployer = template_deployer.TemplateDeployer(stack)
    deployer.construct_changes(stack,
                               change_set,
                               change_set_id=change_set.change_set_id,
                               append_to_changeset=True)
    stack.change_sets.append(change_set)
    change_set.metadata['Status'] = 'CREATE_COMPLETE'
    change_set.metadata['ExecutionStatus'] = 'AVAILABLE'
    change_set.metadata['StatusReason'] = 'Changeset created'
    return {'StackId': change_set.stack_id, 'Id': change_set.change_set_id}
コード例 #4
0
ファイル: provider.py プロジェクト: localstack/localstack
    def get_template_summary(
        self,
        context: RequestContext,
        request: GetTemplateSummaryInput,
    ) -> GetTemplateSummaryOutput:
        stack_name = request.get("StackName")

        if stack_name:
            stack = find_stack(stack_name)
            if not stack:
                return stack_not_found_error(stack_name)
        else:
            template_deployer.prepare_template_body(request)
            template = template_preparer.parse_template(request["TemplateBody"])
            request["StackName"] = "tmp-stack"
            stack = Stack(request, template)

        result: GetTemplateSummaryOutput = stack.describe_details()
        id_summaries = {}
        for resource_id, resource in stack.template_resources.items():
            res_type = resource["Type"]
            id_summaries[res_type] = id_summaries.get(res_type) or []
            id_summaries[res_type].append(resource_id)

        result["ResourceTypes"] = list(id_summaries.keys())
        result["ResourceIdentifierSummaries"] = [
            {"ResourceType": key, "LogicalResourceIds": values}
            for key, values in id_summaries.items()
        ]
        return result
コード例 #5
0
ファイル: provider.py プロジェクト: localstack/localstack
    def create_stack(self, context: RequestContext, request: CreateStackInput) -> CreateStackOutput:
        state = CloudFormationRegion.get()
        template_deployer.prepare_template_body(request)  # TODO: avoid mutating request directly
        template = template_preparer.parse_template(request["TemplateBody"])
        stack_name = template["StackName"] = request.get("StackName")
        stack = Stack(request, template)

        # find existing stack with same name, and remove it if this stack is in DELETED state
        existing = ([s for s in state.stacks.values() if s.stack_name == stack_name] or [None])[0]
        if existing:
            if "DELETE" not in existing.status:
                raise ValidationError(
                    f'Stack named "{stack_name}" already exists with status "{existing.status}"'
                )
            state.stacks.pop(existing.stack_id)

        state.stacks[stack.stack_id] = stack
        LOG.debug(
            'Creating stack "%s" with %s resources ...',
            stack.stack_name,
            len(stack.template_resources),
        )
        deployer = template_deployer.TemplateDeployer(stack)
        try:
            # TODO: create separate step to first resolve parameters
            deployer.deploy_stack()
        except Exception as e:
            stack.set_stack_status("CREATE_FAILED")
            msg = 'Unable to create stack "%s": %s' % (stack.stack_name, e)
            LOG.exception("%s")
            raise ValidationError(msg) from e

        return CreateStackOutput(StackId=stack.stack_id)
コード例 #6
0
def get_template_summary(req_params):
    stack_name = req_params.get("StackName")
    stack = None
    if stack_name:
        stack = find_stack(stack_name)
        if not stack:
            return stack_not_found_error(stack_name)
    else:
        template_deployer.prepare_template_body(req_params)
        template = template_preparer.parse_template(req_params["TemplateBody"])
        req_params["StackName"] = "tmp-stack"
        stack = Stack(req_params, template)
    result = stack.describe_details()
    id_summaries = {}
    for resource_id, resource in stack.template_resources.items():
        res_type = resource["Type"]
        id_summaries[res_type] = id_summaries.get(res_type) or []
        id_summaries[res_type].append(resource_id)
    result["ResourceTypes"] = list(id_summaries.keys())
    result["ResourceIdentifierSummaries"] = [{
        "ResourceType": key,
        "LogicalResourceIds": {
            "member": values
        }
    } for key, values in id_summaries.items()]
    return result
コード例 #7
0
def create_change_set(req_params):
    stack_name = req_params.get("StackName")
    template_deployer.prepare_template_body(req_params)
    template = template_preparer.parse_template(req_params.pop("TemplateBody"))
    template["StackName"] = stack_name
    template["ChangeSetName"] = req_params.get("ChangeSetName")
    stack = existing = find_stack(stack_name)
    if not existing:
        # automatically create (empty) stack if none exists yet
        state = CloudFormationRegion.get()
        empty_stack_template = dict(template)
        empty_stack_template["Resources"] = {}
        req_params_copy = clone_stack_params(req_params)
        stack = Stack(req_params_copy, empty_stack_template)
        state.stacks[stack.stack_id] = stack
        stack.set_stack_status("CREATE_COMPLETE")
    change_set = StackChangeSet(req_params, template)
    deployer = template_deployer.TemplateDeployer(stack)
    deployer.construct_changes(
        stack,
        change_set,
        change_set_id=change_set.change_set_id,
        append_to_changeset=True,
    )
    stack.change_sets.append(change_set)
    change_set.metadata["Status"] = "CREATE_COMPLETE"
    change_set.metadata["ExecutionStatus"] = "AVAILABLE"
    change_set.metadata["StatusReason"] = "Changeset created"
    return {"StackId": change_set.stack_id, "Id": change_set.change_set_id}
コード例 #8
0
def create_stack(req_params):
    state = CloudFormationRegion.get()
    template_deployer.prepare_template_body(req_params)  # TODO: avoid mutating req_params directly
    template = template_preparer.parse_template(req_params["TemplateBody"])
    stack_name = template["StackName"] = req_params.get("StackName")
    stack = Stack(req_params, template)

    # find existing stack with same name, and remove it if this stack is in DELETED state
    existing = ([s for s in state.stacks.values() if s.stack_name == stack_name] or [None])[0]
    if existing:
        if "DELETE" not in existing.status:
            return error_response(
                'Stack named "%s" already exists with status "%s"' % (stack_name, existing.status),
                code=400,
                code_string="ValidationError",
            )
        state.stacks.pop(existing.stack_id)

    state.stacks[stack.stack_id] = stack
    LOG.debug(
        'Creating stack "%s" with %s resources ...'
        % (stack.stack_name, len(stack.template_resources))
    )
    deployer = template_deployer.TemplateDeployer(stack)
    try:
        # TODO: create separate step to first resolve parameters
        deployer.deploy_stack()
    except Exception as e:
        stack.set_stack_status("CREATE_FAILED")
        msg = 'Unable to create stack "%s": %s' % (stack.stack_name, e)
        LOG.debug("%s %s" % (msg, traceback.format_exc()))
        return error_response(msg, code=400, code_string="ValidationError")
    result = {"StackId": stack.stack_id}
    return result
コード例 #9
0
def create_stack(req_params):
    state = CloudFormationRegion.get()
    template_deployer.prepare_template_body(req_params)
    template = template_preparer.parse_template(req_params['TemplateBody'])
    template['StackName'] = req_params.get('StackName')
    stack = Stack(req_params, template)
    state.stacks[stack.stack_id] = stack
    LOG.debug('Creating stack "%s" with %s resources ...' % (stack.stack_name, len(stack.template_resources)))
    deployer = template_deployer.TemplateDeployer(stack)
    try:
        deployer.deploy_stack()
    except Exception as e:
        stack.set_stack_status('CREATE_FAILED')
        msg = 'Unable to create stack "%s": %s' % (stack.stack_name, e)
        LOG.debug('%s %s' % (msg, traceback.format_exc()))
        return error_response(msg, code=400, code_string='ValidationError')
    result = {'StackId': stack.stack_id}
    return result
コード例 #10
0
def create_change_set(req_params):
    stack_name = req_params.get('StackName')
    template_deployer.prepare_template_body(req_params)
    template = template_preparer.parse_template(req_params['TemplateBody'])
    template['StackName'] = stack_name
    template['ChangeSetName'] = req_params.get('ChangeSetName')
    stack = existing = find_stack(stack_name)
    if not existing:
        # automatically create (empty) stack if none exists yet
        state = CloudFormationRegion.get()
        empty_stack_template = dict(template)
        empty_stack_template['Resources'] = {}
        stack = Stack(clone(req_params), empty_stack_template)
        state.stacks[stack.stack_id] = stack
        stack.set_stack_status('CREATE_COMPLETE')
    change_set = StackChangeSet(req_params, template)
    stack.change_sets.append(change_set)
    change_set.metadata['Status'] = 'CREATE_COMPLETE'
    return {'StackId': change_set.stack_id, 'Id': change_set.change_set_id}
コード例 #11
0
    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']
                from localstack.utils.cloudformation import template_deployer_old
                template_deployer_old.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 template_preparer.validate_template(req_data)

            if action in ['CreateStack', 'UpdateStack', 'CreateChangeSet']:
                modified = template_deployer.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