Deployment plan types

AWS Step Functions have a lot of great integrations with other AWS services ex Lambda and ECS Tasks. However, to use AWS Step Functions as a deployment pipeline, it was missing some important features, that is why we built some additional State Types.


Attini::Deploy::DeploymentPlan AttiniCfn

Type: AttiniCfn
Properties:
  Template: String
  StackName: String
  ConfigFile: String
  Parameters: Map<String,String>
  StackRoleArn: String
  ExecutionRoleArn: String
  Region: String
  OutputPath: String
  Variables: Map<String,String>
  Action: String
  EnableTerminationProtection: Boolean

AttiniCfn will create, update or delete a CloudFormation stack.

See more information about the configuration options here.

Note

If the stack is in state “ROLLBACK_COMPLETE” and you run the deployment plan, the stack will be deleted and recreated. The “ROLLBACK_COMPLETE” state only occurs after a failed creation, and the rollback has deleted all the resources in the stack.

Template

Type: String

This has to point towards a CloudFormation template stored in S3. It can either be a URL to a public template, or a reference to a template in the distribution. If the template is in the distribution, the reference has to start with a “/”, ex “/path/to/my/template.yaml”

Required: Conditional | Required unless it’s configured in the ConfigFile.

Default: None

StackName

Type: String

AWS API compatibility: This property is passed directly to the StackName property of the CreateStack or UpdateStack API call.

Required: Conditional | Required unless it’s configured in the ConfigFile.

Default: None

ConfigFile

Type: String

This is a reference to a JSON or a YAML file in the distribution. The reference has to start with a “/”, ex “/path/to/my/parameters.json”

Note

Public HTTPS endpoints ex https://path/to/my/parameters.json does not work for configuration files.

Find more info CloudFormation configuration

Required: No

Default: None

Parameters

Type: Map<String, String>

The CloudFormation parameters, find more info CloudFormation configuration.

Required: No

Default: None

StackRoleArn

Type: String

Arn of the StackRole, find more info here: AWS CloudFormation service role

Note

This IAM Role has to be in the same AWS Account that the Cloud​Formation stack is deployed in, so if “ExecutionRoleArn” is in a different AWS Account this “StackRoleArn” has to be in the same account as the “ExecutionRoleArn”. If the “StackRoleArn” is in a different AWS Account then the “ExecutionRoleArn” you will receive a “Cross-account pass role is not allowed.” error.

Find more information about the security aspects of StackRoles here.

Required: Conditional

If the parameter “UseAdministratorAccessForDeployingCloudformation” in attini-setup CloudFormation stack is false, this parameter or ExecutionRoleArn is required.

Default: None

ExecutionRoleArn

Type: String

The role that you want to be assumed when the Attini Framework deploys the CloudFormation stack. This can be useful if you are:

The ExecutionRole have to trust the default role arn:aws:iam::{AccountId}:role/attini/attini-action-role-{Region} so that it can be assumed.

Example trust relationship policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::111111111111:role/attini/attini-action-role-eu-west-1"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Note

If you configure an execution role in another account or region the Attini Framework will use a polling pattern to verify the state of the stack, this makes the deployment plan execution slower and it can lead to throttling issues if it’s used a lot.

Find more information about the security aspects of ExecutionRoles here.

Required: No

Default: arn:aws:iam::{AccountId}:role/attini/attini-action-role-{Region}

Region

Type: String

Configure the region you want the CloudFormation stack in.

Note

If you configure a Region other then the current region the Attini Framework will use a polling pattern to verify the state of the stack, this makes the deployment plan execution slower and it can lead to throttling issues if it’s used a lot.

Required: No

Default: Current region

OutputPath

Type: String

If you need an extra level of separation for your output, you can use OutputPath. This is useful if you need to have multiple output sections from one step, example when you use AttiniMap type.

If you for example have a State name buzz and an OutputPath: foo the output payload will look like this:

{
  "output": {
    "buzz": {
      "foo": {
        "OutputKey": "OutputValue"
      }
    }
  }
}

Required: No

Default: None

Variables

Type: Map<String,String>

If your step has a ConfigFile configured, you can use Variables to pass values from your deployment plan payload into the file.

If you for example have an AttiniCfn State with the following config:

StateName:
  Type: AttiniCfn
  Properties:
    Template: /ecs-service.yaml
    ConfigFile: /ecs-config.yaml
    Variables:
      Environment: !Ref AttiniEnvironmentName
      DatabasePort.$: $.output.Database.Port
      StackRoleArn.$: $.output.StackRoles.EcsStackRole
    StackName: ecs-service

Your ConfigFile can look like this:

stackRoleArn: ${StackRoleArn}
parameters:
  ServiceName: ${Environment}-my-ecs-service
  DatabasePort: ${DatabasePort}

Note

By using Variables you can replace or manipulate any AttiniCfn configuration except for the ConfigFile path.

Required: No

Default: None

Action

Type: String

Specify if the stack should be created/updated or deleted.

Allowed values: Deploy | Delete

Required: No

Default: Deploy

EnableTerminationProtection

Type: Boolean

Specify if termination protection should be enabled for the stack.

Note

When first creating a stack this is an atomic operation. However when updating an existing stack the termination protection will be updated before the rest of the stack. This means that if the stack update fails and a rollback is performed the termination protection will not be rolled back with the rest of the updates.

Required: No

Default: false


Attini::Deploy::DeploymentPlan AttiniSam

To simplify the use of the AWS Serverless Application Model (SAM) Attini will automatically build and packadge your SAM Applications if they are defined in the deployment plain usig this (AttiniSam) type.

Attini will package the SAM App and use AttiniCfn to deploy it, meaning that most configurations will work the same way.

For more information on how Attini manages SAM Apps, see Attini and AWS SAM.

Type: AttiniSam
Properties:
  Project: String
  StackName: String
  ConfigFile: String
  Parameters: Map<String,String>
  StackRoleArn: String
  ExecutionRoleArn: String
  Variables: Map<String,String>
  Action: String
  EnableTerminationProtection: Boolean

Note

Region from AttiniCfn is not supported because CloudFormation requires Lambda code to be stored in the same region as its being deployed to. The Attini Framework will package the SAM Application into an S3 bucket in your current region only.

Attini does not support packaging AWS Lambda function with container images.

Project

Type: String

The path in your Attini project in which you keep the SAM App.

the reference has to start with a /, ex /sam-apps/my-public-api

Required: Yes

Default: None

StackName

See StackName in AttiniCfn.

ConfigFile

See ConfigFile in AttiniCfn.

Parameters

See Parameters in AttiniCfn.

StackRoleArn

See StackRoleArn in AttiniCfn.

ExecutionRoleArn

See ExecutionRoleArn in AttiniCfn.

Variables

See Variables in AttiniCfn.

Action

See Action in AttiniCfn.

EnableTerminationProtection

See EnableTerminationProtection in AttiniCfn.


Attini::Deploy::DeploymentPlan AttiniLambdaInvoke

Type: AttiniLambdaInvoke
Parameters:
  FunctionName: String

AttiniLambdaInvoke will call a Lambda function while preserving the payload for subsequent steps. This is an abstraction of the Amazon state language Lambda integration and all parameters are supported.

By default, the entire payment plan payload will be passed as input to the Lambda function. This can be overridden by setting the Payload parameter.

Example

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

Resources:

  ExampleDeploy:
    Type: Attini::Deploy::DeploymentPlan
    Properties:
      DeploymentPlan:
        StartAt: InvokeMyLambda
        States:
          InvokeMyLambda:
            Type: AttiniLambdaInvoke
            Parameters:
              FunctionName: some-lambda-function
            End: true

Attini::Deploy::DeploymentPlan AttiniMap

Note

Experimental feature!

Type: AttiniMap
ItemsPath: String
MaxConcurrency: Number
Iterator:
  StartAt: StateName
  States:
    StateName:
      Type: AttiniCfn

This is an abstraction of the Amazon state language Map that help you use AttiniCfn within a Map.

In an AttiniMap you AttiniCfn will need to have OutputPath configured.

For an example, see example-ecs-platform.

ATM: It requires a list of S3 Objects keys that is served as input for each iteration. We are working on improving AttiniMap to make it more user-friendly.

Note

Experimental feature!


Attini::Deploy::DeploymentPlan AttiniImport

Type: AttiniImport
Properties:
  SourceType: String
  Source: S3Source | DistributionSource
  Mapping: Map<String,String>
  ExecutionRoleArn: String

The Attini import step can be used for importing data from different sources. A common use case for this type is reading data from the output of another distribution. For example you could have a distribution responsible for setting up a network that exposes a VPC-id. Then the VPC-id can be imported by other deployment plans.

SourceType

Type: String

Specifies what kind of source should be used.

Allowed values: Distribution | S3

Required: Yes

Mapping

Type: Map<String,String>

A key/value map where the value is a path the to data to include. The path follows the JSONPath syntax. The value on the path will be included in the steps output under the same key name as the mapping.

For example the following JSON source:

{
  "my-service-endpoint" : "https://some-endpoint.com"
}

With the following mapping:

endpoint : $.my-service-endpoint

Would produce the following output for the step in the deployment plan payload.

{
  "endpoint" : "https://some-endpoint.com"
}

Required: Yes

Source

Type: S3Source | DistributionSource

Different sources require different information in order to import them. For example, S3 needs a bucket and key while a distribution needs the name of the distribution.

Required: Yes

Source S3Source

Used when the source of the import should be a file on S3. The file must be either a JSON or a YAML document.

Key: String
Bucket: String
S3Source Key

Type: String

The S3 Key of the document to import.

Required: Yes

S3Source Bucket

Type: String

The S3 Bucket where the document is located.

Required: Yes

Source DistributionSource

Used when the source of the import should be another distribution deployed in the environment. Before a distribution can import the output of another distribution it first needs to be declared as a dependency in the attini-configuration file.

Name: String
DistributionSource Name

Type: String

The name of the distribution.

Required: Yes

ExecutionRoleArn

Type: String

The arn of the execution role that should be used for accessing the source. At the moment only needed for the S3 source type if Attini does not have access to the S3 bucket.

Required: No

Default: None


Attini::Deploy::DeploymentPlan AttiniMergeOutput

Type: AttiniMergeOutput

Some AWS StepFunction types return a list instead of a object, example Parallel or Map.

To make the payload easy to work with the merge step kan merge all the data in the list into one object.

Note

The merge will remove duplicates in all lists in the payload.

Example

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

Resources:

  ExampleDeploy:
    Type: Attini::Deploy::DeploymentPlan
    Properties:
      DeploymentPlan:
        StartAt: Step1
        States:
          Step1:
            Type: Parallel
            Next: MergeOutputsFromStep1
            Branches:
              -
                StartAt: Stack1
                States:
                  Stack1:
                    Type: AttiniCfn
                    Properties:
                      Template: /template-1.yaml
                      StackName: stack-1
                    End: true
              -
                StartAt: Stack2
                States:
                  Stack2:
                    Type: AttiniCfn
                    Properties:
                      Template: /template-2.yaml
                      StackName: stack-2
                    End: true

          MergeOutputsFromStep1:
            Type: AttiniMergeOutput
            Next: Step2

          Step2:
            Type: AttiniCfn
            Properties:
              Template: /template-3.yaml
              StackName: stack-3
            End: true

Attini::Deploy::DeploymentPlan AttiniManualApproval

Type: AttiniManualApproval

The manual approval step will pause the deployment plan and wait for confirmation before continuing. The deployment can be resumed by running the attini deploy continue command with the Attini CLI.

Example

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

Resources:

  ExampleDeploy:
    Type: Attini::Deploy::DeploymentPlan
    Properties:
      DeploymentPlan:
        StartAt: WaitForApproval
        States:
          WaitForApproval: #The deployment plan will pause here until someone runs the continue command
            Type: AttiniManualApproval
            Next: InvokeALambda
          InvokeALambda:
            Type: AttiniLambdaInvoke
            Parameters:
              FunctionName: some-lambda-function
            End: true

Attini::Deploy::DeploymentPlan AttiniRunnerJob

Type: AttiniRunnerJob
Properties:
  Runner: String
  Commands:
    - String

The AttiniRunnerJob is a quick and cost efficient way to run shell commands using a container.

Find detailed information about the Attini::Deploy::Runner type here.

Find detailed information about the runners architecture here.

Runner

Type: String

Reference a Attini::Deploy::Runner recourse, find more information here.

Required: Yes

Commands

Type: List<String>

List of shell commands that runs the job.

These commands are run with set -eo pipefail configuration so that they fail quickly. To revert this configuration (and ignore errors in your scrips), begin your commands with the line: set +eo pipefail.

Note

These strings can NOT integrate with the payload through Amazon state language using the $. syntax or its intrinsic functions.

If you need these commands to integrate with the payload, see Attini runner input and output.

Required: Yes

Example

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

Resources:
  HelloWorldRunner:
    Type: Attini::Deploy::Runner
    Properties:
      TaskDefinitionArn: !Ref RunnerTaskDefinition
      Container: MyContainer
      EcsCluster: test
      AwsVpcConfiguration:
        Subnets:
            - "subnet-aaaaaaaa"
            - "subnet-bbbbbbbb"
            - "subnet-cccccccc"
        SecurityGroups:
            - 'sg-11111111'
        assignPublicIp: ENABLED


  ExampleDeploy:
    Type: Attini::Deploy::DeploymentPlan
    Properties:
      DeploymentPlan:
        StartAt: Step1
        States:
          Step1:
            Type: AttiniRunnerJob
            Properties:
              Runner: HelloWorldRunner
              Commands:
                - echo "my shell commands"
            End: true