AWSTemplateFormatVersion: '2010-09-09'
Description: |
  Template used provision Terraform based products into accounts using ServiceCatalog-Puppet
  {"version": "{{ FACTORY_VERSION }}", "framework": "servicecatalog-factory", "role": "terraform-product-provision"}

Parameters:
  TerraformVersion:
    Description: Which version of terraform to use
    Default: '{{ PROVISIONER_VERSION }}'
    Type: String

  ComputeType:
    Description: The ComputeType for CodeBuild
    Type: String
    Default: "BUILD_GENERAL1_SMALL"

  {% for TF_VAR in TF_VARS %}
  {{TF_VAR}}:
    Type: String
  {% endfor %}


Resources:
  S3TerraformStateBucket:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      Tags:
        - Key: "ServiceCatalogFactory:Actor"
          Value: "Generated"
{% for tag in tags %}
        - Key: {{ tag.get("Key") }}
          Value: {{ tag.get("Value") }}
{% endfor %}

  S3CodePipelineBucket:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      Tags:
        - Key: "ServiceCatalogFactory:Actor"
          Value: "Generated"
{% for tag in tags %}
        - Key: {{ tag.get("Key") }}
          Value: {{ tag.get("Value") }}
{% endfor %}

  BuildProjectPlan:
    Type: AWS::CodeBuild::Project
    Properties:
      Description: !Sub "Run a terraform plan for ${AWS::StackName}"
      ServiceRole: !GetAtt CodeBuildRole.Arn
      Tags:
        - Key: "ServiceCatalogFactory:Actor"
          Value: "Generated"
{% for tag in tags %}
        - Key: {{ tag.get("Key") }}
          Value: {{ tag.get("Value") }}
{% endfor %}
      Artifacts:
        Type: CODEPIPELINE
      Environment:
        Type: linuxContainer
        ComputeType: !Ref ComputeType
        Image: aws/codebuild/python:3.6.5
        EnvironmentVariables:
          - Name: LAUNCH_NAME
            Value: !Ref AWS::StackName
          - Name: S3_BUCKET_NAME
            Value: !Ref S3CodePipelineBucket
          - Name: S3_STATE_BUCKET
            Value: !Ref S3TerraformStateBucket
          - Name: REGION
            Value: !Ref AWS::Region
  {% for TF_VAR in TF_VARS %}
          - Name: TF_VAR_{{TF_VAR}}
            Value: !Ref {{TF_VAR}}
  {% endfor %}

      Source:
        Type: CODEPIPELINE
        BuildSpec: !Sub |
            version: 0.2
            phases:
              install:
                commands:
                  - wget https://releases.hashicorp.com/terraform/${TerraformVersion}/terraform_${TerraformVersion}_linux_amd64.zip
                  - unzip terraform_${TerraformVersion}_linux_amd64.zip
                  - sudo mv terraform /bin
                  - echo "Prepare terraform provider file"
                  - cd tf
                  - echo "terraform { " >> provider-output-backend.tf
                  - echo "   backend \"s3\" { " >> provider-output-backend.tf
                  - echo "   bucket = \"$S3_STATE_BUCKET\"" >> provider-output-backend.tf
                  - echo "   key    = \"$LAUNCH_NAME/terraform.tfstate\"" >> provider-output-backend.tf
                  - echo "   region = \"$REGION\"" >> provider-output-backend.tf
                  - echo "  }" >> provider-output-backend.tf
                  - echo "}" >> provider-output-backend.tf
                  - cat provider-output-backend.tf
              build:
                commands:
                 - terraform init
                 - terraform plan -no-color
            artifacts:
              files:
                - '*'
                - '**/*'
      TimeoutInMinutes: 20
      Tags:
        - Key: Name
          Value: !Ref AWS::StackName

  BuildProjectDeploy:
    Type: AWS::CodeBuild::Project
    Properties:
      Description: !Sub "Run a terraform apply for ${AWS::StackName}"
      ServiceRole: !GetAtt CodeBuildRole.Arn
      Tags:
        - Key: "ServiceCatalogFactory:Actor"
          Value: "Generated"
{% for tag in tags %}
        - Key: {{ tag.get("Key") }}
          Value: {{ tag.get("Value") }}
{% endfor %}
      Artifacts:
        Type: CODEPIPELINE
      Environment:
        Type: linuxContainer
        ComputeType: !Ref ComputeType
        Image: aws/codebuild/python:3.6.5
        EnvironmentVariables:
          - Name: LAUNCH_NAME
            Value: !Ref AWS::StackName
          - Name: S3_BUCKET_NAME
            Value: !Ref S3CodePipelineBucket
          - Name: S3_STATE_BUCKET
            Value: !Ref S3TerraformStateBucket
          - Name: REGION
            Value: !Ref AWS::Region
  {% for TF_VAR in TF_VARS %}
          - Name: TF_VAR_{{TF_VAR}}
            Value: !Ref {{TF_VAR}}
  {% endfor %}

      Source:
        Type: CODEPIPELINE
        BuildSpec: !Sub |
            version: 0.2
            phases:
              install:
                commands:
                  - wget https://releases.hashicorp.com/terraform/${TerraformVersion}/terraform_${TerraformVersion}_linux_amd64.zip
                  - unzip terraform_${TerraformVersion}_linux_amd64.zip
                  - sudo mv terraform /bin
                  - echo "Display terraform provider file"
                  - cd tf
                  - cat provider-output-backend.tf
              build:
                commands:
                 - terraform init
                 - terraform apply -auto-approve -no-color

            artifacts:
              files: '**/*'
      TimeoutInMinutes: 20
      Tags:
        - Key: Name
          Value: !Ref AWS::StackName

  CodeBuildPolicy:
    Type: 'AWS::IAM::Policy'
    Properties:
      PolicyDocument:
        Statement:
          - Action: '*'
            Effect: Allow
            Resource: '*'
        Version: 2012-10-17
      PolicyName: terraform-app-deploy
      Roles:
        - !Ref CodeBuildRole

  CodeBuildRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - codebuild.amazonaws.com
            Action:
              - sts:AssumeRole
          - Effect: Allow
            Principal:
              AWS: !Ref AWS::AccountId
            Action:
              - sts:AssumeRole
        Version: 2012-10-17
      Tags:
        - Key: "ServiceCatalogFactory:Actor"
          Value: "Generated"
{% for tag in tags %}
        - Key: {{ tag.get("Key") }}
          Value: {{ tag.get("Value") }}
{% endfor %}

  Pipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      RoleArn: !Sub "arn:aws:iam::${AWS::AccountId}:role/servicecatalog-puppet/PuppetRoleForTerraform"
      Name: !Ref AWS::StackName
      RestartExecutionOnUpdate: false
      Stages:
        - Name: Source
          Actions:
            - Name: Source
              ActionTypeId:
                Category: Source
                Owner: AWS
                Version: 1
                Provider: S3
              Configuration:
                S3Bucket: !Sub "sc-factory-artifacts-{{ PUPPET_ACCOUNT_ID }}-${AWS::Region}"
                PollForSourceChanges: true
                S3ObjectKey: {{ UID }}/tf.zip
              OutputArtifacts:
                - Name: TemplateSource
              RunOrder: 1
        - Name: Plan-Stage
          Actions:
            - Name: Plan-Terraform
              ActionTypeId:
                Category: Build
                Owner: AWS
                Version: 1
                Provider: CodeBuild
              Configuration:
                ProjectName: !Ref BuildProjectPlan
              RunOrder: 1
              InputArtifacts:
                - Name: TemplateSource
              OutputArtifacts:
                - Name: Plan
        - Name: Deploy-Stage
          Actions:
            - Name: Deploy-Terraform
              ActionTypeId:
                Category: Build
                Owner: AWS
                Version: 1
                Provider: CodeBuild
              Configuration:
                ProjectName: !Ref BuildProjectDeploy
              RunOrder: 1
              InputArtifacts:
                - Name: Plan
              OutputArtifacts:
                - Name: Apply
      ArtifactStores:
        - Region: !Ref AWS::Region
          ArtifactStore:
            Location: !Ref S3CodePipelineBucket
            Type: S3
      Tags:
        - Key: "ServiceCatalogFactory:Actor"
          Value: "Generated"
{% for tag in tags %}
        - Key: {{ tag.get("Key") }}
          Value: {{ tag.get("Value") }}
{% endfor %}

Outputs:
  PipelineUrl:
    Value: !Sub https://console.aws.amazon.com/codepipeline/home?region=${AWS::Region}#/view/${Pipeline}