Attini runner (Beta)

Attini::Deploy::Runner

Attini runner is based on Amazon ECS and uses the ECS RunTask API call to start the runner.

The Attini::Deploy::Runner resource only works in conjunction with the Attini deployment plan. See AttiniRunnerJob for more information.

The Attini::Deploy::Runner can ONLY be created in the Attini init deploy stack.

The DeploymentPlan template requires the AttiniDeploymentPlan Transform configuration:

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

Resources:
  HelloWorldRunner:
    Type: Attini::Deploy::Runner
    Properties:
      TaskDefinitionArn: String
      ContainerName: String
      EcsCluster: String
      RunnerConfiguration:
        MaxConcurrentJobs: Number
        IdleTimeToLive: Number
        JobTimeout: Number
        LogLevel: String
      AwsVpcConfiguration:
        Subnets: String,String
        SecurityGroups: String,String
        AssignPublicIp: Sting
TaskDefinitionArn

Type: String

The ECS task definition that the Attini runner should use.

Note

The container image ENTRYPOINT or ECS task definition Entrypoint, must NOT be configured. If the ENTRYPOINT is configured, it will cause the runner to not start properly.

Depending on the ENTRYPOINT content it can cause zombie ECS tasks.

Container image CMD and ECS task definition Command will be overwritten by the RunTask API call that Attini will call on your behalf.

To run commands from the Attini runner, use the Attini::Deploy::DeploymentPlan AttiniRunnerJob type.

If you want to use CloudFormation to define the task definition, see AWS::ECS::TaskDefinition for more information.

Required: Yes

Default: None

ContainerName

Type: String

The name of the container in the task definition. This is not mandatory if there is only one container definition in the specified task definition.

Required: No

Default: None

EcsCluster

Type: String

The name of the Ecs cluster to start the container in. This is not mandatory if there is a default cluster in the account.

Note

If there is no default cluster, you can create on with the AWS CLI command aws ecs create-cluster (omit all flags).

Required: No

Default: None

AwsVpcConfiguration

AwsVpcConfiguration Subnets

Type: Comma seperated String

A comma seperated list of the subnet ids associated to the ECS task. For more information see the AWS ECS VPC documentation

Required: Yes

Default: None

AwsVpcConfiguration SecurityGroups

Type: Comma seperated String

A comma seperated list of the security group ids associated to the ECS task. For more information see the AWS ECS VPC documentation

Required: No

Default: None

AwsVpcConfiguration AssignPublicIp

Type: String

For more information see the AWS ECS VPC documentation.

Required: Yes

Default: None

Allowed Values: ENABLED | DISABLED

RunnerConfiguration

RunnerConfiguration MaxConcurrentJobs

Type: Number

The max amount of concurrent jobs the Attini runner will execute.

Required: No

Default: 5

Allowed Range: 1-20

RunnerConfiguration IdleTimeToLive

Type: Number

The number of seconds the Attini runner will stay alive without any jobs executing. New jobs will reset the countdown.

Required: No

Default: 900

Allowed Range: 60-86400

RunnerConfiguration JobTimeout

Type: Number

The number of seconds a job can execute before the Attini runner will abort the execution.

Required: No

Default: 3600

Allowed Range: 5-172800

RunnerConfiguration LogLevel

Type: String

The log level of the Attini runner.

Required: No

Default: INFO

Allowed Values: DEBUG | INFO | WARN | ERROR | OFF | ALL


Environment variables

You can configure any environment variables you need on the Attini runner via the image build process (ex Dockerfile) or using the ECS task definition.

However, the Attini framework will automatically populate these environment variables:

ATTINI_ENVIRONMENT_NAME

The environment from the payload

ATTINI_DISTRIBUTION_NAME

The distributionName from the payload

ATTINI_DISTRIBUTION_ID

The distributionId from the payload

ATTINI_ARTIFACT_STORE

The deploymentSource.deploymentSourceBucket from the payload

ATTINI_DISTRIBUTION_ARTIFACTS_PREFIX

The deploymentSource.deploymentSourcePrefix from the payload

ATTINI_INPUT

The location of a JSON file that contains the input payload. Find more information here.

ATTINI_OUTPUT

The location of a JSON file that the Attini runner will pass as output to the payload. Find more information here.

ATTINI_SOURCE_DIR

The working from where the AttiniRunnerJob is executed. This directory will also contain all the original files from the Attini distribution.

ATTINI_STEP_NAME

The name of the deployment plan step name.


Payload input and output

Input

Within the Attini runner job, you can access the deployment plan payload input via a JSON file available on the runner. The path to the JSON file is available to the job commands via the ATTINI_INPUT environment variable.

Output

If you want later steps in the deployment plan to access information from your job, you can save that data (in JSON format) to a file on the runner. That file path is available through the ATTINI_OUTPUT environment variable.

The ATTINI_OUTPUT JSON file will be passed to the deployment plan payload under the path output.[StepName].

Hint: jq is a good tool when you work with JSON using bash.

Example

StepName:
  Type: AttiniRunnerJob
  Properties:
    Runner: HelloWorldRunner
    Commands:
      - cat ${ATTINI_INPUT} # This will print the input as a sting.
      - echo '{"MyKey":"MyValue"}' > ${ATTINI_OUTPUT} # This will ad the JSON object to the output

Install the Attini runner

The Attini runner will automatically be installed at boot if it’s not installed. However, it is recommended to install it on your own build image. This will decrease startup time, give you better control over software versions and decrease the risk of other failures. Installing the Attini runner at boot also required internet access.

We recommend you to configure a Linux user for security reasons. If you pre-install all the software your deployment needs, the use-cases for running jobs as root decrease significantly.

Example Dockerfile

Note

For the blow dockerfile to work, you need to autheticate with the Amazon ECR public registries using the command:

aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws

# Define the base image and update all software
FROM public.ecr.aws/amazonlinux/amazonlinux:latest
RUN yum update -y && yum clean all

# Install the attini-runner
RUN curl -sfL#o /usr/local/bin/attini-runner https://docs.attini.io/api/v1/runner/get-runner/$(uname -m)/$(uname -s)/latest; chmod +x /usr/local/bin/attini-runner

# Configure a user (recommended)
RUN yum install -y shadow-utils && yum clean all && useradd attini
USER attini

Transformed resources

A Attini::Deploy::Runner resource transforms into other CloudFormation resources and changes the DeploymentPlan state language.

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:

  HelloWorldRunner:
    Type: Attini::Deploy::Runner
    Properties:
      TaskDefinitionArn: !Ref RunnerTaskDefinition
      Container: MyRunnerContainer
      EcsCluster: MyRunnerCluster
      AwsVpcConfiguration:
        Subnets: "subnet-11111111,subnet-22222222,subnet-33333333"
        SecurityGroups:
            - 'sg-11111111'
        AssignPublicIp: ENABLED

  HelloWorldDeploymentPlan:
    Type: Attini::Deploy::DeploymentPlan
    Properties:
      DeploymentPlan:
        ...

  HelloWorldRunnerTaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      ContainerDefinitions:
        ...

Outputs:
  DeploymentPlanSfnArn:
    Description: The arn of the StepFunction generated by HelloWorldDeploymentPlan
    Value: !Ref AttiniDeploymentPlanSfnHelloWorldDeploymentPlan

Transformed template:

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "AttiniRunnerQueueHelloWorldRunner": {
      "Type": "AWS::SQS::Queue",
      "Properties": {
        "ReceiveMessageWaitTimeSeconds": "20",
        "VisibilityTimeout": "15",
        "KmsDataKeyReusePeriodSeconds": "86400",
        "FifoQueue": "True"
      }
    },
    "AttiniDeploymentPlanSfnTriggerHelloWorldDeploymentPlan": {
      "Type": "Custom::AttiniDeploymentPlanTrigger",
      "Properties": {
        "...": "..."
      }
    },
    "AttiniDeploymentPlanSfnHelloWorldDeploymentPlan": {
      "Type": "AWS::StepFunctions::StateMachine",
      "Properties": {
        "...": "..."
      }
    },
    "AttiniPostExecutionActionsHelloWorldDeploymentPlan": {
      "Type": "AWS::Events::Rule",
      "Properties": {
        "...": "..."
      }
    },
    "RunnerTaskDefinition": {
      "Type": "AWS::ECS::TaskDefinition",
      "Properties": {
        "ContainerDefinitions": [
          "..."
        ]
      }
    }
  },
  "Outputs": {
    "DeploymentSfnPlanArn": {
      "Description": "The arn of the StepFunction generated by PublicWebsite deployment plan.",
      "Value": {
        "Ref": "AttiniDeploymentPlanSfnHelloWorldDeploymentPlan"
      }
    },
    "AttiniRunnerQueueHelloWorldRunnerURL": {
      "Description": "The URL of the SQS that is used for the Attini runner.",
      "Value": {
        "Ref": "AttiniRunnerQueueHelloWorldRunner"
      }
    }
  }
}

Limitations

CloudFormation intrinsic functions

Some parts of the Attini::Deploy::Runner configuration will be moved into the deployment plan state language definition so that it can be used by when Attini runs the RunTask API Call. This means that some CloudFormation functions (ex Fn::Join or Fn::ImportValue) might not work as expected. As a workaround, your can use deployment plan definition substitutions and reference the substitutions in the Attini::Deploy::Runner.

Amazon ECS service quotas

The Attini runner is running as an ECS Task, this means that all Amazon ECS limitations also apply to the Attini Runner.


Supported operating systems and CPU architectures

Attini runner works on operating systems:

  • Linux

Attini runner works with the following CPU architectures:

  • x86_64

  • aarch64

Note

If you need support for other operating systems or CPU architectures please send an email to support@attini.io and we will try to accommodate the request.

You can find your operating system and CPU architecture by running uname -s and uname -m in a terminal. Please include this information in the support email.


Attini runner information API

List the available operating systems and CPU architectures

curl https://docs.attini.io/api/v1/runner/get-supported-platforms

Get available Attini runner versions

curl https://docs.attini.io/api/v1/runner/get-runner-versions/{cpu_architecture}/{operating_systems}

Examples

curl https://docs.attini.io/api/v1/runner/get-runner-versions/$(uname -m)/Linux
curl https://docs.attini.io/api/v1/runner/get-runner-versions/x86_64/Linux
curl https://docs.attini.io/api/v1/runner/get-runner-versions/aarch64/Linux

Get re-routed to the Attini runner location

curl https://docs.attini.io/api/v1/runner/get-runner/{cpu_architecture}/{operating_systems}/{version}

Examples

curl https://docs.attini.io/api/v1/runner/get-runner/$(uname -m)/Linux/latest
curl https://docs.attini.io/api/v1/runner/get-runner/x86_64/Linux/1.0.0
curl https://docs.attini.io/api/v1/runner/get-runner/aarch64/Linux/1.0.0