Code Monkey home page Code Monkey logo

ecs-deploy-buildkite-plugin's Introduction

ECS Deploy Buildkite Plugin Build status

A Buildkite plugin for deploying to Amazon ECS.

Example

steps:
  - label: ":ecs: :rocket:"
    concurrency_group: "my-service-deploy"
    concurrency: 1
    plugins:
      - ecs-deploy#v3.0.0:
          cluster: "my-ecs-cluster"
          service: "my-service"
          container-definitions: "examples/hello-world.json"
          task-family: "hello-world"
          image: "${ECR_REPOSITORY}/hello-world:${BUILDKITE_BUILD_NUMBER}"

Options

Required

cluster

The name of the ECS cluster.

Example: "my-cluster"

container-definitions

Experimental: Since version 3.0.0 you can skip this parameter and the container definitions will be obtained off the existing (latest) task definition. If this does not work for you, please open an issue in this repository.

The file path to the ECS container definition JSON file. This JSON file must be an array of objects, each corresponding to one of the images you defined in the image parameter.

Example: "ecs/containers.json"

[
    {
        "essential": true,
        "image": "amazon/amazon-ecs-sample",
        "memory": 100,
        "name": "sample",
        "portMappings": [
            {
                "containerPort": 80,
                "hostPort": 80
            }
        ]
    },
    {
        "essential": true,
        "image": "amazon/amazon-ecs-sample",
        "memory": 100,
        "name": "sample",
        "portMappings": [
            {
                "containerPort": 80,
                "hostPort": 80
            }
        ]
    }
]

image

The Docker image to deploy. This can be an array to substitute multiple images in a single container definition.

Examples: "012345.dkr.ecr.us-east-1.amazonaws.com/my-service:123"

image:
  - "012345.dkr.ecr.us-east-1.amazonaws.com/my-service:123"
  - "012345.dkr.ecr.us-east-1.amazonaws.com/nginx:123"

service

The name of the ECS service.

Example: "my-service"

task-family

The name of the task family.

Example: "my-task"

Optional

env (array)

An array of environment variables to add to every image's task definition in the NAME=VALUE format

execution-role

The Execution Role ARN used by ECS to pull container images and secrets.

Example: "arn:aws:iam::012345678910:role/execution-role"

Requires the iam:PassRole permission for the execution role.

region

The region we deploy the ECS Service to.

task-cpu (integer)

CPU Units to assign to the task (1024 constitutes a whole CPU). Example: 256 (1/4 of a CPU).

task-ephemeral-storage (integer)

Amount of GBs to assign in ephemeral storage to the task. Example: 25.

task-ipc-mode

IPC resource namespace to use in the task. If specified, should be one of host, task or none.

task-memory (integer)

Amount of memory (in Mbs) to allocate for the task. Example: 1024 (1Gb).

task-network-mode

Docker networking mode for the containers running in the task. If specified, should be one of bridge, host, awsvpc or none.

task-pid-mode

Process namespace to use for containers in the task. If specified, should be one of host or task.

task-role-arn

An IAM ECS Task Role to assign to tasks.

Requires the iam:PassRole permission for the ARN specified.

AWS Roles

At a minimum this plugin requires the following AWS permissions to be granted to the agent running this step:

Policy:
  Statement:
  - Action:
    - ecr:DescribeImages
    - ecs:DescribeServices
    - ecs:RegisterTaskDefinition
    - ecs:UpdateService
    Effect: Allow
    Resource: '*'

Developing

To run testing, shellchecks and plugin linting use use bk run with the Buildkite CLI.

bk run

Or if you want to run just the tests, you can use the docker Plugin Tester:

docker run --rm -ti -v "${PWD}":/plugin buildkite/plugin-tester:latest

License

MIT (see LICENSE)

ecs-deploy-buildkite-plugin's People

Contributors

aleksclark avatar juntaozeng avatar lox avatar nithyaasworld avatar patrobinson avatar pda avatar pzeballos avatar renovate-bot avatar renovate[bot] avatar sj26 avatar tomowatt avatar toolmantim avatar toote avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ecs-deploy-buildkite-plugin's Issues

Support multiple target groups

ECS introduced multiple target groups for a service and I now have a use case for it but this plugin doesn't currently support an array of target groups.

I've had a look through the code and it looks like I could add this support quite simply with existing functionality but would you accept a PR?

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Preset name not found within published preset config (monorepo:babel6). Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

Can I deploy to a service that wasn't created by this plugin?

We have a ECS/fargate service that's managed by terraform. The terraform config includes attaching the service to a target group so it receives traffic from an ALB.

I attempted to use this plugin to deploy a new task definition to the service, and initially I left the target group out of the plugin config as I knew the "create service" code path in the plugin wouldn't be used:

    plugins:
      - ecs-deploy#v1.4.1:
          cluster: "cluster-name"
          service: "my-service"
          task-definition: "deploy/task-container-definitions.json"
          task-family: "thing"
          image: "${ECR_REPO}:${BUILDKITE_BUILD_NUMBER}"
          execution-role: "${ECS_EXECUTION_ROLE_ARN}"

However, deploys failed with this error:

Cannot update a service to add/remove a load balancer. First delete the service
and then run again, or rename the service to force a new one to be created.
Container config differs

I then assumed I might need to include the target group config, even though it wouldn't be used, so I tried this config:

    plugins:
      - ecs-deploy#v1.4.1:
          cluster: "cluster-name"
          service: "my-service"
          task-definition: "deploy/task-container-definitions.json"
          task-family: "thing"
          image: "${ECR_REPO}:${BUILDKITE_BUILD_NUMBER}"
          execution-role: "${ECS_EXECUTION_ROLE_ARN}"
          target-container-name: web
          target-container-port: 3000

However, deploys failed with this error:

Registering new task definition for thing
Registered thing:16
🚨 Error: The command exited with status 1

To confirm the agent running the step has the necessary IAM permissions, I tried a minimal deploy shell script with some sugar around the following commands and it seems to work:

aws ecs register-task-definition --cli-input-json ...
aws ecs update-service ...
aws ecs wait services-stable ...

Tests are inconclusive

The test stubs as currently exist are not actually validating the full parameters given, which means that things like expected_container_definition don't really expect anything. If the test behavior is fine as desired, the test file should be cleaned up, otherwise something needs to be corrected with bats-mock. I encountered this issue when updating specs for #62

Example:

Current Contents of "Run a deploy with multiple images" stub:

  stub aws \
    "ecs register-task-definition --family hello-world --container-definitions '\'$expected_container_definition\'' : echo '{\"taskDefinition\":{\"revision\":1}}'" \
    "ecs describe-services --cluster my-cluster --service my-service --query 'services[?status==\`ACTIVE\`].status' --output text : echo '1'" \
    "ecs describe-services --cluster my-cluster --services my-service --query 'services[?status==\`ACTIVE\`]' : echo 'null'" \
    "ecs update-service --cluster my-cluster --service my-service --task-definition hello-world:1 : echo ok" \
    "ecs wait services-stable --cluster my-cluster --services my-service : echo ok" \
    "ecs describe-services --cluster my-cluster --service my-service : echo ok"```

Tests also pass with the following (note the munging of the first stub in each):

  stub aws \
    "ecs 1register-task-definition --family hello-world --container-definitions '\'$expected_container_definition\'' : echo '{\"taskDefinition\":{\"revision\":1}}'" \
    "ecs describe-services --cluster my-cluster --service my-service --query 'services[?status==\`ACTIVE\`].status' --output text : echo '1'" \
    "ecs describe-services --cluster my-cluster --services my-service --query 'services[?status==\`ACTIVE\`]' : echo 'null'" \
    "ecs update-service --cluster my-cluster --service my-service --task-definition hello-world:1 : echo ok" \
    "ecs wait services-stable --cluster my-cluster --services my-service : echo ok" \
    "ecs describe-services --cluster my-cluster --service my-service : echo ok"
  stub aws \
    "ecs register-task-definition : echo '{\"taskDefinition\":{\"revision\":1}}'" \
    "ecs describe-services --cluster my-cluster --service my-service --query 'services[?status==\`ACTIVE\`].status' --output text : echo '1'" \
    "ecs describe-services --cluster my-cluster --services my-service --query 'services[?status==\`ACTIVE\`]' : echo 'null'" \
    "ecs update-service --cluster my-cluster --service my-service --task-definition hello-world:1 : echo ok" \
    "ecs wait services-stable --cluster my-cluster --services my-service : echo ok" \
    "ecs describe-services --cluster my-cluster --service my-service : echo ok"
  stub aws \
    "argity blar blar --container-definitions '\'$expected_container_definition\'' : echo '{\"taskDefinition\":{\"revision\":1}}'" \
    "ecs describe-services --cluster my-cluster --service my-service --query 'services[?status==\`ACTIVE\`].status' --output text : echo '1'" \
    "ecs describe-services --cluster my-cluster --services my-service --query 'services[?status==\`ACTIVE\`]' : echo 'null'" \
    "ecs update-service --cluster my-cluster --service my-service --task-definition hello-world:1 : echo ok" \
    "ecs wait services-stable --cluster my-cluster --services my-service : echo ok" \
    "ecs describe-services --cluster my-cluster --service my-service : echo ok"

This one finally fails:

  stub aws \
    "what is this: echo '{\"taskDefinition\":{\"revision\":1}}'" \
    "ecs describe-services --cluster my-cluster --service my-service --query 'services[?status==\`ACTIVE\`].status' --output text : echo '1'" \
    "ecs describe-services --cluster my-cluster --services my-service --query 'services[?status==\`ACTIVE\`]' : echo 'null'" \
    "ecs update-service --cluster my-cluster --service my-service --task-definition hello-world:1 : echo ok" \
    "ecs wait services-stable --cluster my-cluster --services my-service : echo ok" \
    "ecs describe-services --cluster my-cluster --service my-service : echo ok"

Remote task fetching

Heya, is it possible to not have to include tasks in your source code and instead fetch them remotely? I have one that's defined in ECS and would like to use it

Disable aws cli pager

When using the following step:

- label: Deploy
    concurrency_group: "cicd-eval-deploy"
    concurrency: 1
    plugins:
      - ecs-deploy#v3.0.0:
          cluster: "cicd-eval"
          service: "cicd-eval-buildkite"
          task-family: "cicd-eval-buildkite"
          image: "xxx.dkr.ecr.us-west-2.amazonaws.com/cicd-eval:${BUILDKITE_BUILD_NUMBER}"

deployment stalls:

Updating service for cicd-eval-buildkite | 4m 20s
-- | --
  | {
  | "service": {
  | "serviceArn": "arn:aws:ecs:us-west-2:xxx:service/cicd-eval/cicd-eval-buildkite",
  | "serviceName": "cicd-eval-buildkite",
  | "clusterArn": "arn:aws:ecs:us-west-2:xxx:cluster/cicd-eval",
  | "loadBalancers": [],
  | "serviceRegistries": [],
  | "status": "ACTIVE",
  | "desiredCount": 1,
  | "runningCount": 1,
  | "pendingCount": 0,
  | "capacityProviderStrategy": [
  | {
  | "capacityProvider": "FARGATE",
  | "weight": 1,
  | "base": 0
  | }
  | ],
  | "platformVersion": "LATEST",
  | "platformFamily": "Linux",
  | "taskDefinition": "arn:aws:ecs:us-west-2:xxx:task-definition/cicd-eval-buildkite:8",
  | :

This is caused by paginated output of task definition json, to mitigate I've added:

[default]
cli_pager=

to ~/.aws/config of buildkite-agent user home but this should be addressed by adding --no-paginate to all AWS CLI commands.

Unbound variable aws_default_args

While trying to use this plugin I'm getting an error:

image

https://buildkite.com/sj26-test/buildkite-ecs-oidc-example/builds/28#01870c6d-495b-4747-9afb-2382a87f3c4a

~/.buildkite-agent/plugins/github-com-buildkite-plugins-ecs-deploy-buildkite-plugin/hooks/command: line 147: aws_default_args[@]: unbound variable
🚨 Error: The command exited with status 1
user command error: The plugin ecs-deploy command hook exited with status 1

Seems to be around here:

https://github.com/buildkite-plugins/ecs-deploy-buildkite-plugin/blob/master/hooks/command#L144-L148

I can see that it's defined earlier in the file, and so should be available:

https://github.com/buildkite-plugins/ecs-deploy-buildkite-plugin/blob/master/hooks/command#L35

My bash-fu is weak, though, so is this something weird to do with arrays? I remember something about bash 5 causing issues?

I'm running an agent on macOS:

bash --version
GNU bash, version 5.2.2(1)-release (aarch64-apple-darwin21.6.0)
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Anyway to just perform update image and not define new definition?

When I deploy to fargate instance it throws:

Cannot update a service to add/remove a load balancer. First delete the service and then run again, or rename the service to force a new one to be created. Container config differs | 0s

This is overkill for most folks who just want to deploy new image. Also why is the json require in buildkite different to the one on AWS? I try to copy task definition JSON as "task-definition" and it complained that format is different. Do you expect customer we redefine new definition under your format?

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

buildkite
.buildkite/pipeline.yml
  • docker-compose v4.5.0
  • plugin-linter v3.0.0
  • shellcheck v1.3.0
docker-compose
docker-compose.yml
  • buildkite/plugin-tester v3.0.1

  • Check this box to trigger a request for Renovate to run again on this repository

Trying to deploy to an existing cluster, recieving an 'unbound variable' error

Full error: /var/lib/buildkite-agent/plugins/github-com-buildkite-plugins-ecs-deploy-buildkite-plugin-v2-0-0/hooks/command: line 136: env_vars[@]: unbound variable

  - label: ":ecs: :rocket:"

    concurrency_group: "my-service-deploy"
    
    concurrency: 1
    
    plugins:
    
      - ecs-deploy#v1.4.1:
      
          cluster: "<existing cluster>"
          
          service: "<non-existent service>"
          
          task-definition: "deploy/containers.json"
          
          task-family: "<task family>"
          
          image: "<arn>/<image>:latest"
          
          target-group: "<existing targetgroup-arn>"
          
          target-container-port: 3000
          

containers.json



[
{ 
"essential": true,
    
    "image": "<taskdef arn>",
    
    "memory": 1024,
    
    "name": "sample",
    
    "portMappings": [
    
      {
        "containerPort": 3000,
        
        "hostPort": 3000
        
      }
      
    ]
  }
]

I have tried pointing to a different service without a target group and ALB in front of it and still get the same sort of issue. I think Im missing some information on the launching of the fargate containers.

Failed ECS deployment feedback

Would it be possible to return specific feedback from ECS in the case that the task failed to launch (i.e. could not find image, etc)?

When running a service update that fails, the logs will return Service failed to deploy (image attached).
image

Having this directly in the Buildkite logs would be very handy as it may negate needing to go into the AWS console & dig around as to why the deployment failed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.