"use strict";
const assert_1 = require("@aws-cdk/assert");
const aws_cloudformation_1 = require("@aws-cdk/aws-cloudformation");
const aws_codebuild_1 = require("@aws-cdk/aws-codebuild");
const aws_codecommit_1 = require("@aws-cdk/aws-codecommit");
const aws_codepipeline_api_1 = require("@aws-cdk/aws-codepipeline-api");
const aws_iam_1 = require("@aws-cdk/aws-iam");
const cdk = require("@aws-cdk/cdk");
const cdk_1 = require("@aws-cdk/cdk");
const lib_1 = require("../lib");
/**
 * A test stack with a half-prepared pipeline ready to add CloudFormation actions to
 */
class TestFixture extends cdk.Stack {
    constructor() {
        super();
        this.pipeline = new lib_1.Pipeline(this, 'Pipeline');
        this.sourceStage = new lib_1.Stage(this.pipeline, 'Source');
        this.deployStage = new lib_1.Stage(this.pipeline, 'Deploy');
        this.repo = new aws_codecommit_1.Repository(this, 'MyVeryImportantRepo', { repositoryName: 'my-very-important-repo' });
        this.source = new aws_codecommit_1.PipelineSource(this, 'Source', {
            stage: this.sourceStage,
            artifactName: 'SourceArtifact',
            repository: this.repo,
        });
    }
}
module.exports = {
    'CreateChangeSetAction can be used to make a change set from a CodePipeline'(test) {
        const stack = new cdk.Stack();
        const pipeline = new lib_1.Pipeline(stack, 'MagicPipeline');
        const changeSetExecRole = new aws_iam_1.Role(stack, 'ChangeSetRole', {
            assumedBy: new cdk_1.ServicePrincipal('cloudformation.amazonaws.com'),
        });
        /** Source! */
        const repo = new aws_codecommit_1.Repository(stack, 'MyVeryImportantRepo', { repositoryName: 'my-very-important-repo' });
        const sourceStage = new lib_1.Stage(pipeline, 'source');
        const source = new aws_codecommit_1.PipelineSource(stack, 'source', {
            stage: sourceStage,
            artifactName: 'SourceArtifact',
            repository: repo,
        });
        /** Build! */
        const buildStage = new lib_1.Stage(pipeline, 'build');
        const buildArtifacts = new aws_codebuild_1.CodePipelineBuildArtifacts();
        const project = new aws_codebuild_1.Project(stack, 'MyBuildProject', {
            source: new aws_codebuild_1.CodePipelineSource(),
            artifacts: buildArtifacts,
        });
        const buildAction = new aws_codebuild_1.PipelineBuildAction(stack, 'build', {
            stage: buildStage,
            project,
            inputArtifact: source.artifact,
            artifactName: "OutputYo"
        });
        /** Deploy! */
        // To execute a change set - yes, you probably do need *:* 🤷‍♀️
        changeSetExecRole.addToPolicy(new cdk_1.PolicyStatement().addAllResources().addAction("*"));
        const prodStage = new lib_1.Stage(pipeline, 'prod');
        const stackName = 'BrelandsStack';
        const changeSetName = 'MyMagicalChangeSet';
        new aws_cloudformation_1.CreateReplaceChangeSet(stack, 'BuildChangeSetProd', {
            stage: prodStage,
            stackName,
            changeSetName,
            role: changeSetExecRole,
            templatePath: new aws_codepipeline_api_1.ArtifactPath(buildAction.artifact, 'template.yaml'),
            templateConfiguration: new aws_codepipeline_api_1.ArtifactPath(buildAction.artifact, 'templateConfig.json')
        });
        new aws_cloudformation_1.ExecuteChangeSet(stack, 'ExecuteChangeSetProd', {
            stage: prodStage,
            stackName,
            changeSetName,
        });
        assert_1.expect(stack).to(assert_1.haveResource('AWS::CodePipeline::Pipeline', {
            "ArtifactStore": {
                "Location": {
                    "Ref": "MagicPipelineArtifactsBucket212FE7BF"
                },
                "Type": "S3"
            }, "RoleArn": {
                "Fn::GetAtt": ["MagicPipelineRoleFB2BD6DE",
                    "Arn"
                ]
            },
            "Stages": [{
                    "Actions": [
                        {
                            "ActionTypeId": {
                                "Category": "Source",
                                "Owner": "AWS", "Provider": "CodeCommit", "Version": "1"
                            },
                            "Configuration": {
                                "RepositoryName": {
                                    "Fn::GetAtt": [
                                        "MyVeryImportantRepo11BC3EBD",
                                        "Name"
                                    ]
                                },
                                "BranchName": "master",
                                "PollForSourceChanges": true
                            },
                            "InputArtifacts": [],
                            "Name": "source",
                            "OutputArtifacts": [
                                {
                                    "Name": "SourceArtifact"
                                }
                            ],
                            "RunOrder": 1
                        }
                    ],
                    "Name": "source"
                },
                {
                    "Actions": [
                        {
                            "ActionTypeId": {
                                "Category": "Build",
                                "Owner": "AWS",
                                "Provider": "CodeBuild",
                                "Version": "1"
                            },
                            "Configuration": {
                                "ProjectName": {
                                    "Ref": "MyBuildProject30DB9D6E"
                                }
                            },
                            "InputArtifacts": [
                                {
                                    "Name": "SourceArtifact"
                                }
                            ],
                            "Name": "build",
                            "OutputArtifacts": [
                                {
                                    "Name": "OutputYo"
                                }
                            ],
                            "RunOrder": 1
                        }
                    ],
                    "Name": "build"
                },
                {
                    "Actions": [
                        {
                            "ActionTypeId": {
                                "Category": "Deploy",
                                "Owner": "AWS",
                                "Provider": "CloudFormation",
                                "Version": "1"
                            },
                            "Configuration": {
                                "ActionMode": "CHANGE_SET_REPLACE",
                                "ChangeSetName": "MyMagicalChangeSet",
                                "RoleArn": {
                                    "Fn::GetAtt": [
                                        "ChangeSetRole0BCF99E6",
                                        "Arn"
                                    ]
                                },
                                "StackName": "BrelandsStack",
                                "TemplatePath": "OutputYo::template.yaml",
                                "TemplateConfiguration": "OutputYo::templateConfig.json"
                            },
                            "InputArtifacts": [{ "Name": "OutputYo" }],
                            "Name": "BuildChangeSetProd",
                            "OutputArtifacts": [],
                            "RunOrder": 1
                        },
                        {
                            "ActionTypeId": {
                                "Category": "Deploy",
                                "Owner": "AWS",
                                "Provider": "CloudFormation",
                                "Version": "1"
                            },
                            "Configuration": {
                                "ActionMode": "CHANGE_SET_EXECUTE",
                                "ChangeSetName": "MyMagicalChangeSet"
                            },
                            "InputArtifacts": [],
                            "Name": "ExecuteChangeSetProd",
                            "OutputArtifacts": [],
                            "RunOrder": 1
                        }
                    ],
                    "Name": "prod"
                }
            ]
        }));
        test.done();
    },
    'fullPermissions leads to admin role and full IAM capabilities'(test) {
        // GIVEN
        const stack = new TestFixture();
        // WHEN
        new aws_cloudformation_1.CreateUpdateStack(stack.deployStage, 'CreateUpdate', {
            stage: stack.deployStage,
            stackName: 'MyStack',
            templatePath: stack.source.artifact.subartifact('template.yaml'),
            fullPermissions: true,
        });
        const roleId = "PipelineDeployCreateUpdateRole515CB7D4";
        // THEN: Action in Pipeline has named IAM capabilities
        assert_1.expect(stack).to(assert_1.haveResource('AWS::CodePipeline::Pipeline', {
            "Stages": [
                { "Name": "Source" /* don't care about the rest */ },
                {
                    "Name": "Deploy",
                    "Actions": [
                        {
                            "Configuration": {
                                "Capabilities": "CAPABILITY_NAMED_IAM",
                                "RoleArn": { "Fn::GetAtt": [roleId, "Arn"] },
                                "ActionMode": "CREATE_UPDATE",
                                "StackName": "MyStack",
                                "TemplatePath": "SourceArtifact::template.yaml"
                            },
                            "InputArtifacts": [{ "Name": "SourceArtifact" }],
                            "Name": "CreateUpdate",
                        },
                    ],
                }
            ]
        }));
        // THEN: Role is created with full permissions
        assert_1.expect(stack).to(assert_1.haveResource('AWS::IAM::Policy', {
            PolicyDocument: {
                Statement: [
                    {
                        Action: "*",
                        Resource: "*"
                    }
                ],
            },
            Roles: [{ Ref: roleId }]
        }));
        test.done();
    },
    'outputFileName leads to creation of output artifact'(test) {
        // GIVEN
        const stack = new TestFixture();
        // WHEN
        new aws_cloudformation_1.CreateUpdateStack(stack, 'CreateUpdate', {
            stage: stack.deployStage,
            stackName: 'MyStack',
            templatePath: stack.source.artifact.subartifact('template.yaml'),
            outputFileName: 'CreateResponse.json',
        });
        // THEN: Action has output artifacts
        assert_1.expect(stack).to(assert_1.haveResource('AWS::CodePipeline::Pipeline', {
            "Stages": [
                { "Name": "Source" /* don't care about the rest */ },
                {
                    "Name": "Deploy",
                    "Actions": [
                        {
                            "OutputArtifacts": [{ "Name": "DeployCreateUpdateArtifact" }],
                            "Name": "CreateUpdate",
                        },
                    ],
                }
            ]
        }));
        test.done();
    },
    'replaceOnFailure switches action type'(test) {
        // GIVEN
        const stack = new TestFixture();
        // WHEN
        new aws_cloudformation_1.CreateUpdateStack(stack, 'CreateUpdate', {
            stage: stack.deployStage,
            stackName: 'MyStack',
            templatePath: stack.source.artifact.subartifact('template.yaml'),
            replaceOnFailure: true,
        });
        // THEN: Action has output artifacts
        assert_1.expect(stack).to(assert_1.haveResource('AWS::CodePipeline::Pipeline', {
            "Stages": [
                { "Name": "Source" /* don't care about the rest */ },
                {
                    "Name": "Deploy",
                    "Actions": [
                        {
                            "Configuration": {
                                "ActionMode": "REPLACE_ON_FAILURE",
                            },
                            "Name": "CreateUpdate",
                        },
                    ],
                }
            ]
        }));
        test.done();
    },
    'parameterOverrides are serialized as a string'(test) {
        // GIVEN
        const stack = new TestFixture();
        // WHEN
        new aws_cloudformation_1.CreateUpdateStack(stack, 'CreateUpdate', {
            stage: stack.deployStage,
            stackName: 'MyStack',
            templatePath: stack.source.artifact.subartifact('template.yaml'),
            parameterOverrides: {
                RepoName: stack.repo.repositoryName
            }
        });
        // THEN
        assert_1.expect(stack).to(assert_1.haveResource('AWS::CodePipeline::Pipeline', {
            "Stages": [
                { "Name": "Source" /* don't care about the rest */ },
                {
                    "Name": "Deploy",
                    "Actions": [
                        {
                            "Configuration": {
                                "ParameterOverrides": { "Fn::Join": ["", [
                                            "{\"RepoName\":\"",
                                            { "Fn::GetAtt": ["MyVeryImportantRepo11BC3EBD", "Name"] },
                                            "\"}"
                                        ]] }
                            },
                            "Name": "CreateUpdate",
                        },
                    ],
                }
            ]
        }));
        test.done();
    }
};
//# sourceMappingURL=data:application/json;base64, 