Attini deployment plan

Attini::Deploy::DeploymentPlan

Attini DeploymentPlan is an abstraction on the AWS::Serverless::StateMachine resource. It extends the StateMachine with features that are required for the AWS::Serverless::StateMachine to function as a deployment orchestrator, for example finding the deployment source files, automatic triggers and supporting additional Attini State Types.

The DeploymentPlan can ONLY be created in the Attini init deploy stack

The DeploymentPlan template requires the following Transform configuration:

AWSTemplateFormatVersion: "2010-09-09"
Transform:
  - AttiniDeploymentPlan
  - AWS::Serverless-2016-10-31

Resource definition

Type: Attini::Deploy::DeploymentPlan
Properties:
  DefinitionSubstitutions: Map
  RoleArn: String
  Tags: List
  DeploymentPlan: DeploymentPlan
DefinitionSubstitutions

Type: Map<Sting, Sting|Map>

AWS SAM compatibility: This property is passed directly to the DefinitionSubstitutions property of an AWS::Serverless::StateMachine resource.

This is useful if you want to use AWS CloudFormation’s Condition functions when you build your deployment plan. This can also be used for Intrinsic functions but most of them (ex Fn::Sub and Ref) can also be written straight in the DeploymentPlan.

Required: No

RoleArn

Type: String

AWS SAM compatibility: This property is passed directly to the Role property of an AWS::Serverless::StateMachine resource.

Default: arn:aws:iam::{Account}:role/attini/attini-deployment-plan-default-states-service-role-{Region}

Required: Conditional

If the parameter CreateDeploymentPlanDefaultRole on the attini-setup CloudFormation stack is false, then this is required.

Tags

Type: Map<Sting, Sting>

AWS SAM compatibility: This property is passed directly to the Tags property of an AWS::Serverless::StateMachine resource.

Required: No

DeploymentPlan

Type: DeploymentPlan

DeploymentPlan

Required: Yes


DeploymentPlan

A definition using Amazon state language that describes your deployment.

In extension to the Amazon state language the DeploymentPlan can also use the Attini types.

This definition converts to a Definition.

StartAt: String
States: Map
StartAt

Type: String

The step that the Deployment Plan should start with. This is passed directly the StartAt property in the Amazon States Language

Required: Yes

States

Type: Map<Sting, Map>

This is passed to the States property in the Amazon States Language after the Attini-specific resources (ex AttiniCfn) have been converted into a valid Amazon States Language definition.

Make sure that the actions that you specify here are allowed by the DeploymentPlan Role.

This map have limited support for CloudFormation functions.

  • Simple functions like “Ref”, “Fn::GetAtt” and “Fn::Sub” works like normal CloudFormation.

  • Complex functions like “Fn::Join” will need to use the DefinitionSubstitutions property.

  • Conditions are not supported. you can often work around this limitation using logic in your definition, example by using the Choice state.

Required: Yes


Transformed resources

A Attini::Deploy::DeploymentPlan resource transforms into multiple CloudFormation resources that together creates your deployment plan.

In this example, you can see how the transformed template will look.

Original template

AWSTemplateFormatVersion: "2010-09-09"
Transform:
  - AttiniDeploymentPlan
  - AWS::Serverless-2016-10-31

Resources:
  PublicWebsite:
    Type: Attini::Deploy::DeploymentPlan
    Properties:
      DeploymentPlan:
        ...

Outputs:
  DeploymentSfnPlanArn:
    Description: The arn of the StepFunction generated by PublicWebsite
    Value: !Ref AttiniDeploymentPlanSfnPublicWebsite

Transformed template:

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "AttiniDeploymentPlanSfnTriggerPublicWebsite": {
      "Type": "Custom::AttiniDeploymentPlanTrigger",
      "Properties": {
        "...": "..."
      }
    },
    "AttiniDeploymentPlanSfnPublicWebsite": {
      "Type": "AWS::StepFunctions::StateMachine",
      "Properties": {
        "...": "..."
      }
    },
    "AttiniPostExecutionActionsPublicWebsite": {
      "Type": "AWS::Events::Rule",
      "Properties": {
        "...": "..."
      }
    }
  },
  "Outputs": {
    "DeploymentSfnPlanArn": {
      "Description": "The arn of the StepFunction generated by PublicWebsite deployment plan",
      "Value": {
        "Ref": "AttiniDeploymentPlanSfnPublicWebsite"
      }
    }
  }
}

Example: Deploy a static website

  1. StaticWebsite deploys an s3 bucket and a CloudFront distribution using CloudFormation.

  2. DeployWebsiteLambda deploys a Lambda function using CloudFormation.

  3. DeployWebsiteContent triggers the Lambda function which copy’s the files from the Attini distribution to the website bucket and invalidates the CloudFront distribution.

    Note

    that we are using Type: AttiniLambdaInvoke to trigger the Lambda which helps us to work with the Attini deployment plan payload

StaticWebsiteDeployPlan:
  Type: Attini::Deploy::DeploymentPlan
  Properties:
    DeploymentPlan:
      StartAt: StaticWebsite
      States:
        StaticWebsite:
          Type: AttiniCfn
          Properties:
            Template: /cfn-templates/static-website.yaml
            StackName: !Sub ${AttiniEnvironmentName}-public-documentation-website
            Parameters:
              AttiniEnvironmentName: !Ref AttiniEnvironmentName
          Next: DeployWebsiteLambda

        DeployWebsiteLambda:
          Type: AttiniCfn
            Properties:
            Template: /deploy-website/template.yaml
            StackName: !Sub ${AttiniEnvironmentName}-deploy-documentation-function
            ConfigFile: /config/default.json
          Parameters:
            StaticWebsiteBucketName.$: $.output.StaticWebsite.WebassetsBucket
            CloudFrontDistributionId.$: $.output.StaticWebsite.CloudFrontDistributionId
          Next: DeployWebsiteContent

        DeployWebsiteContent:
          Type: AttiniLambdaInvoke # https://docs.attini.io/api-reference/deployment-plan-types.html#attini-deploy-deploymentplan-attinilambdainvoke
          Parameters:
            FunctionName.$: !Sub $.output.DeployWebsiteLambda.DeployWebsiteFunctionName
          End: true