ecspresso

package module
v2.3.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2024 License: MIT Imports: 68 Imported by: 0

README

ecspresso

ecspresso is a deployment tool for Amazon ECS.

(pronounced same as "espresso")

Documents

Install

Homebrew (macOS and Linux)
$ brew install kayac/tap/ecspresso
asdf (macOS and Linux)
$ asdf plugin add ecspresso
# or
$ asdf plugin add ecspresso https://github.com/kayac/asdf-ecspresso.git

$ asdf install ecspresso 2.3.0
$ asdf global ecspresso 2.3.0
aqua (macOS and Linux)

aqua is a CLI Version Manager.

$ aqua g -i kayac/ecspresso
Binary packages

Releases

CircleCI Orbs

https://circleci.com/orbs/registry/orb/fujiwara/ecspresso

version: 2.1
orbs:
  ecspresso: fujiwara/ecspresso@2.0.4
jobs:
  install:
    steps:
      - checkout
      - ecspresso/install:
          version: v2.3.0 # or latest
          # version-file: .ecspresso-version
          os: linux # or windows or darwin
          arch: amd64 # or arm64
      - run:
          command: |
            ecspresso version

version: latest installs different versions of ecspresso for each Orb version.

version: latest is not recommended because it may cause unexpected behavior when the new version of ecspresso is released.

Orb fujiwara/ecspresso@2.0.2 supports version-file: path/to/file installs ecspresso that version written in the file. This version number does not have v prefix, For example, 2.0.0.

GitHub Actions

Action kayac/ecspresso@v2 installs an ecspresso binary for Linux(x86_64) into /usr/local/bin. This action runs install only.

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: kayac/ecspresso@v2
        with:
          version: v2.3.0 # or latest
          # version-file: .ecspresso-version
      - run: |
          ecspresso deploy --config ecspresso.yml

Pass the parameter "latest" to use the latest version of ecspresso.

      - uses: kayac/ecspresso@v2
        with:
          version: latest

version: latest installs different versions of ecspresso for each Action version.

  • kayac/ecspresso@v1
    • The latest version of v1.x
  • kayac/ecspresso@v2
    • The latest version of v2.x

version: latest is not recommended because it may cause unexpected behavior when the new version of ecspresso is released.

GitHub Action kayac/ecspresso@v2 supports version-file: path/to/file installs ecspresso that version written in the file. This version number does not have v prefix, For example 2.3.0.

Usage

Usage: ecspresso <command>

Flags:
  -h, --help                      Show context-sensitive help.
      --envfile=ENVFILE,...       environment files ($ECSPRESSO_ENVFILE)
      --debug                     enable debug log ($ECSPRESSO_DEBUG)
      --ext-str=KEY=VALUE;...     external string values for Jsonnet ($ECSPRESSO_EXT_STR)
      --ext-code=KEY=VALUE;...    external code values for Jsonnet ($ECSPRESSO_EXT_CODE)
      --config="ecspresso.yml"    config file ($ECSPRESSO_CONFIG)
      --assume-role-arn=""        the ARN of the role to assume ($ECSPRESSO_ASSUME_ROLE_ARN)
      --timeout=TIMEOUT           timeout. Override in a configuration file ($ECSPRESSO_TIMEOUT).
      --filter-command=STRING     filter command ($ECSPRESSO_FILTER_COMMAND)

Commands:
  appspec
    output AppSpec YAML for CodeDeploy to STDOUT

  delete
    delete service

  deploy
    deploy service

  deregister
    deregister task definition

  diff
    show diff between task definition, service definition with current running
    service and task definition

  exec
    execute command on task

  init --service=SERVICE
    create configuration files from existing ECS service

  refresh
    refresh service. equivalent to deploy --skip-task-definition
    --force-new-deployment --no-update-service

  register
    register task definition

  render <targets>
    render config, service definition or task definition file to STDOUT

  revisions
    show revisions of task definitions

  rollback
    rollback service

  run
    run task

  scale
    scale service. equivalent to deploy --skip-task-definition
    --no-update-service

  status
    show status of service

  tasks
    list tasks that are in a service or having the same family

  verify
    verify resources in configurations

  wait
    wait until service stable

  version
    show version

For more options for sub-commands, See ecspresso sub-command --help.

Quick Start

ecspresso can easily manage your existing/running ECS service by codes.

Try ecspresso init for your ECS service with option --region, --cluster and --service.

$ ecspresso init --region ap-northeast-1 --cluster default --service myservice --config ecspresso.yml
2019/10/12 01:31:48 myservice/default save service definition to ecs-service-def.json
2019/10/12 01:31:48 myservice/default save task definition to ecs-task-def.json
2019/10/12 01:31:48 myservice/default save config to ecspresso.yml

Let me see the generated files ecspresso.yml, ecs-service-def.json, and ecs-task-def.json.

And then, you already can deploy the service by ecspresso!

$ ecspresso deploy --config ecspresso.yml
Next step

ecspresso can read service and task definition files as a template. A typical use case is to replace the image's tag in the task definition file.

Modify ecs-task-def.json as below.

-  "image": "nginx:latest",
+  "image": "nginx:{{ must_env `IMAGE_TAG` }}",

And then, deploy the service with environment variable IMAGE_TAG.

$ IMAGE_TAG=stable ecspresso deploy --config ecspresso.yml

See also Configuration file and Template syntax section.

Configuration file

A configuration file of ecspresso (YAML or JSON, or Jsonnet format).

region: ap-northeast-1 # or AWS_REGION environment variable
cluster: default
service: myservice
task_definition: taskdef.json
timeout: 5m # default 10m

ecspresso deploy works as below.

  • Register a new task definition from task-definition file (JSON or Jsonnet).
    • Replace {{ env `FOO` `bar` }} syntax in the JSON file to environment variable "FOO".
      • If "FOO" is not defined, replaced by "bar"
    • Replace {{ must_env `FOO` }} syntax in the JSON file to environment variable "FOO".
      • If "FOO" is not defined, abort immediately.
  • Update service tasks by the service_definition file (JSON or Jsonnet).
  • Wait for the service to be stable.

Configuration files and task/service definition files are read by go-config. go-config has template functions env, must_env and json_escape.

Template syntax

ecspresso uses the text/template standard package in Go to render template files, and parses as YAML/JSON/Jsonnet. By default, ecspresso provides the following as template functions.

env
"{{ env `NAME` `default value` }}"

If the environment variable NAME is set, it will replace with its value. If it's not set, it will replace with "default value".

must_env
"{{ must_env `NAME` }}"

It replaces with the value of the environment variable NAME. If the variable isn't set at the time of execution, ecspresso will panic and stop forcefully.

By defining values that can cause issues when running without meaningful values with must_env, you can prevent unintended deployments.

json_escape
"{{ must_env `JSON_VALUE` | json_escape }}"

It escapes values as JSON strings. Use it when you want to escape values that need to be embedded as strings and require escaping, like quotes.

Plugin provided template functions

ecspresso also adds some template functions by plugins. See Plugins section.

Example of deployment

Rolling deployment
$ ecspresso deploy --config ecspresso.yml
2017/11/09 23:20:13 myService/default Starting deploy
Service: myService
Cluster: default
TaskDefinition: myService:3
Deployments:
    PRIMARY myService:3 desired:1 pending:0 running:1
Events:
2017/11/09 23:20:13 myService/default Creating a new task definition by myTask.json
2017/11/09 23:20:13 myService/default Registering a new task definition...
2017/11/09 23:20:13 myService/default Task definition is registered myService:4
2017/11/09 23:20:13 myService/default Updating service...
2017/11/09 23:20:13 myService/default Waiting for service stable...(it will take a few minutes)
2017/11/09 23:23:23 myService/default  PRIMARY myService:4 desired:1 pending:0 running:1
2017/11/09 23:23:29 myService/default Service is stable now. Completed!
Blue/Green deployment (with AWS CodeDeploy)

ecspresso deploy can deploy service having CODE_DEPLOY deployment controller. See ecs-service-def.json below.

{
  "deploymentController": {
    "type": "CODE_DEPLOY"
  },
  // ...
}

ecspresso doesn't create and modify any resources about CodeDeploy. You must create an application and a deployment group for your ECS service on CodeDeploy in the other way.

ecspresso finds a CodeDeploy deployment setting for the ECS service automatically. But, if you have too many CodeDeploy applications, API calls of that finding process may cause throttling.

In this case, you may specify CodeDeploy application_name and deployment_group_name in a config file.

# ecspresso.yml
codedeploy:
  application_name: myapp
  deployment_group_name: mydeployment

ecspresso deploy creates a new deployment for CodeDeploy, and it continues on CodeDeploy.

$ ecspresso deploy --config ecspresso.yml --rollback-events DEPLOYMENT_FAILURE
2019/10/15 22:47:07 myService/default Starting deploy
Service: myService
Cluster: default
TaskDefinition: myService:5
TaskSets:
   PRIMARY myService:5 desired:1 pending:0 running:1
Events:
2019/10/15 22:47:08 myService/default Creating a new task definition by ecs-task-def.json
2019/10/15 22:47:08 myService/default Registering a new task definition...
2019/10/15 22:47:08 myService/default Task definition is registered myService:6
2019/10/15 22:47:08 myService/default desired count: 1
2019/10/15 22:47:09 myService/default Deployment d-XXXXXXXXX is created on CodeDeploy
2019/10/15 22:47:09 myService/default https://ap-northeast-1.console.aws.amazon.com/codesuite/codedeploy/deployments/d-XXXXXXXXX?region=ap-northeast-1

CodeDeploy appspec hooks can be defined in a config file. ecspresso creates Resources and version elements in appspec on deploy automatically.

cluster: default
service: test
service_definition: ecs-service-def.json
task_definition: ecs-task-def.json
appspec:
  Hooks:
    - BeforeInstall: "LambdaFunctionToValidateBeforeInstall"
    - AfterInstall: "LambdaFunctionToValidateAfterTraffic"
    - AfterAllowTestTraffic: "LambdaFunctionToValidateAfterTestTrafficStarts"
    - BeforeAllowTraffic: "LambdaFunctionToValidateBeforeAllowingProductionTraffic"
    - AfterAllowTraffic: "LambdaFunctionToValidateAfterAllowingProductionTraffic"

Scale out/in

To change a desired count of the service, specify scale --tasks.

$ ecspresso scale --tasks 10

scale command is equivalent to deploy --skip-task-definition --no-update-service.

Example of deploy

ecspresso can deploy a service by service_definition JSON file and task_definition.

$ ecspresso deploy --config ecspresso.yml
...
# ecspresso.yml
service_definition: service.json

example of service.json below.

{
  "role": "ecsServiceRole",
  "desiredCount": 2,
  "loadBalancers": [
    {
      "containerName": "myLoadbalancer",
      "containerPort": 80,
      "targetGroupArn": "arn:aws:elasticloadbalancing:[region]:[account-id]:targetgroup/{target-name}/201ae83c14de522d"
    }
  ]
}

Keys are in the same format as aws ecs describe-services output.

  • deploymentConfiguration
  • launchType
  • loadBalancers
  • networkConfiguration
  • placementConstraint
  • placementStrategy
  • role
  • etc.

Example of run task

$ ecspresso run --config ecspresso.yml --task-def=db-migrate.json

When --task-def is not set, use a task definition included in a service.

Other options for RunTask API are set by service attributes(CapacityProviderStrategy, LaunchType, PlacementConstraints, PlacementStrategy and PlatformVersion).

Notes

Version constraint.

required_version in the configuration file is for fixing the version of ecspresso.

required_version: ">= 2.0.0, < 3"

This description allows execution if the version is greater than or equal to 2.0.0 and less than or equal to 3. If this configuration file is read in any other version, execution will fail at that point.

This feature is implemented by go-version.

Manage Application Auto Scaling

If you're using Application Auto Scaling for your ECS service, adjusting the minimum and maximum auto-scaling settings with the ecspresso scale command is a breeze. Simply specify either scale --auto-scaling-min or scale --auto-scaling-max to modify the settings.

$ ecspresso scale --tasks 5 --auto-scaling-min 5 --auto-scaling-max 20

ecspresso deploy and scale can suspend and resume application auto scaling.

  • --suspend-auto-scaling sets suspended state to true.
  • --resume-auto-scaling sets suspended state to false.

When you want to change the suspended state simply, try ecspresso scale --suspend-auto-scaling or ecspresso scale --resume-auto-scaling. That operation will change suspended state only.

Use Jsonnet instead of JSON and YAML.

ecspresso v1.7 or later can use Jsonnet file format for service and task definition.

v2.0 or later can use Jsonnet for configuration file too.

If the file extension is .jsonnet, ecspresso will process Jsonnet first, convert it to JSON, and then load it.

{
  cluser: 'default',
  service: 'myservice',
  service_definition: 'ecs-service-def.jsonnet',
  task_definition: 'ecs-task-def.jsonnet',
}

ecspresso includes github.com/google/go-jsonnet as a library, we don't need the jsonnet command.

--ext-str and --ext-code flag sets Jsonnet External Variables.

$ ecspresso --ext-str Foo=foo --ext-code "Bar=1+1" ...
{
  foo: std.extVar('Foo'), // = "foo"
  bar: std.extVar('Bar'), // = 2
}
Deploy to Fargate

If you want to deploy services to Fargate, task definitions and service definitions require some settings.

For task definitions,

  • requiresCompatibilities (required "FARGATE")
  • networkMode (required "awsvpc")
  • cpu (required)
  • memory (required)
  • executionRoleArn (optional)
{
  "taskDefinition": {
    "networkMode": "awsvpc",
    "requiresCompatibilities": [
      "FARGATE"
    ],
    "cpu": "1024",
    "memory": "2048",
    // ...
}

For service-definition,

  • launchType (required "FARGATE")
  • networkConfiguration (required "awsvpcConfiguration")
{
  "launchType": "FARGATE",
  "networkConfiguration": {
    "awsvpcConfiguration": {
      "subnets": [
        "subnet-aaaaaaaa",
        "subnet-bbbbbbbb"
      ],
      "securityGroups": [
        "sg-11111111"
      ],
      "assignPublicIp": "ENABLED"
    }
  },
  // ...
}
Fargate Spot support
  1. Set capacityProviders and defaultCapacityProviderStrategy to ECS cluster.
  2. If you hope to migrate existing service to use Fargate Spot, define capacityProviderStrategy into service definition as below. ecspresso deploy --update-service applies the settings to the service.
{
  "capacityProviderStrategy": [
    {
      "base": 1,
      "capacityProvider": "FARGATE",
      "weight": 1
    },
    {
      "base": 0,
      "capacityProvider": "FARGATE_SPOT",
      "weight": 1
    }
  ],
  // ...
ECS Service Connect support

ecspresso supports ECS Service Connect.

You can define serviceConnectConfiguration in service definition files and portMappings attributes in task definition files.

For more details, see also Service Connect parameters

EBS Volume support

ecspresso supports managing Amazon EBS Volumes.

To use EBS volumes, define volumeConfigurations in service definitions, and mountPoints and volumes attributes in task definition files.

// ecs-service-def.json
  "volumeConfigurations": [
    {
      "managedEBSVolume": {
        "filesystemType": "ext4",
        "roleArn": "arn:aws:iam::123456789012:role/ecsInfrastructureRole",
        "sizeInGiB": 10,
        "tagSpecifications": [
          {
            "propagateTags": "SERVICE",
            "resourceType": "volume"
          }
        ],
        "volumeType": "gp3"
      },
      "name": "ebs"
    }
  ]
// ecs-task-def.json
// containerDefinitions[].mountPoints
      "mountPoints": [
        {
          "containerPath": "/mnt/ebs",
          "sourceVolume": "ebs"
        }
      ]
// volumes
  "volumes": [
    {
      "name": "ebs",
      "configuredAtLaunch": true
    }
  ]

ecspresso run command supports EBS volumes too.

The EBS volumes attached to the standalone tasks will be deleted when the task is stopped by default. But you can keep the volumes by --no-ebs-delete-on-termination option.

$ ecspresso run --no-ebs-delete-on-termination

The EBS volumes attached to the tasks run by ECS services will always be deleted when the task is stopped. This behavior is by the ECS specification, so ecspresso can't change it.

How to check diff and verify service/task definitions before deploy.

ecspresso supports diff and verify subcommands.

diff

Shows differences between local task/service definitions and remote (on ECS) definitions.

$ ecspresso diff
--- arn:aws:ecs:ap-northeast-1:123456789012:service/ecspresso-test/nginx-local
+++ ecs-service-def.json
@@ -38,5 +38,5 @@
   },
   "placementConstraints": [],
   "placementStrategy": [],
-  "platformVersion": "1.3.0"
+  "platformVersion": "LATEST"
 }
 
--- arn:aws:ecs:ap-northeast-1:123456789012:task-definition/ecspresso-test:202
+++ ecs-task-def.json
@@ -1,6 +1,10 @@
 {
   "containerDefinitions": [
     {
       "cpu": 0,
       "environment": [],
       "essential": true,
-      "image": "nginx:latest",
+      "image": "nginx:alpine",
       "logConfiguration": {
         "logDriver": "awslogs",
         "options": {
verify

Verify resources related with service/task definitions.

For example,

  • An ECS cluster exists.
  • The target groups in service definitions match the container name and port defined in the definitions.
  • A task role and a task execution role exist and can be assumed by ecs-tasks.amazonaws.com.
  • Container images exist at the URL defined in task definitions. (Checks only for ECR or DockerHub public images.)
  • Secrets in task definitions exist and be readable.
  • Can create log streams, can put messages to the streams in specified CloudWatch log groups.

ecspresso verify tries to assume the task execution role defined in task definitions to verify these items. If failed to assume the role, it continues to verify with the current sessions.

$ ecspresso verify
2020/12/08 11:43:10 nginx-local/ecspresso-test Starting verify
  TaskDefinition
    ExecutionRole[arn:aws:iam::123456789012:role/ecsTaskRole]
    --> [OK]
    TaskRole[arn:aws:iam::123456789012:role/ecsTaskRole]
    --> [OK]
    ContainerDefinition[nginx]
      Image[nginx:alpine]
      --> [OK]
      LogConfiguration[awslogs]
      --> [OK]
    --> [OK]
  --> [OK]
  ServiceDefinition
  --> [OK]
  Cluster
  --> [OK]
2020/12/08 11:43:14 nginx-local/ecspresso-test Verify OK!
Manipulate ECS tasks.

ecspresso can manipulate ECS tasks. Use tasks and exec command.

After v2.0, These operations are provided by ecsta as a library. ecsta CLI can manipulate any ECS tasks (not limited to deployed by ecspresso).

Consider using ecsta as a CLI command.

tasks

task command lists tasks run by a service or having the same family to a task definition.

Flags:
      --id=                       task ID
      --output=table              output format
      --find=false                find a task from tasks list and dump it as JSON
      --stop=false                stop the task
      --force=false               stop the task without confirmation
      --trace=false               trace the task

When --find option is set, you can select a task in a list of tasks and show the task as JSON.

ECSPRESSO_FILTER_COMMAND environment variable can define a command to filter tasks. For example peco, fzf and etc.

$ ECSPRESSO_FILTER_COMMAND=peco ecspresso tasks --find

When --stop option is set, you can select a task in a list of tasks and stop the task.

exec

exec command executes a command on task.

session-manager-plugin is required in PATH.

Flags:
      --id=                       task ID
      --command=sh                command to execute
      --container=                container name
      --port-forward=false        enable port forward
      --local-port=0              local port number
      --port=0                    remote port number (required for --port-forward)
      --host=                     remote host (required for --port-forward)

If --id is not set, the command shows a list of tasks to select a task to execute.

ECSPRESSO_FILTER_COMMAND environment variable works the same as tasks command.

See also the official document Using Amazon ECS Exec for debugging.

port forwarding

ecspresso exec --port-forward forwards local port to ECS tasks port.

$ ecspresso exec --port-forward --port 80 --local-port 8080
...

If --id is not set, the command shows a list of tasks to select a task to forward port.

When --local-port is not specified, use the ephemeral port for local port.

Plugins

ecspresso has some plugins to extend template functions.

tfstate

The tfstate plugin introduces template functions tfstate and tfstatef.

ecspresso.yml

region: ap-northeast-1
cluster: default
service: test
service_definition: ecs-service-def.json
task_definition: ecs-task-def.json
plugins:
  - name: tfstate
    config:
      url: s3://my-bucket/terraform.tfstate
      # or path: terraform.tfstate    # path to local file

ecs-service-def.json

{
  "networkConfiguration": {
    "awsvpcConfiguration": {
      "subnets": [
        "{{ tfstatef `aws_subnet.private['%s'].id` `az-a` }}"
      ],
      "securityGroups": [
        "{{ tfstate `data.aws_security_group.default.id` }}"
      ]
    }
  }
}

{{ tfstate "resource_type.resource_name.attr" }} will expand to an attribute value of the resource in tfstate.

{{ tfstatef "resource_type.resource_name['%s'].attr" "index" }} is similar to {{ tfstatef "resource_type.resource_name['index'].attr" }}. This function is useful to build a resource address with environment variables.

{{ tfstatef `aws_subnet.ecs['%s'].id` (must_env `SERVICE`) }}
Supported tfstate URL format
  • Local file file://path/to/terraform.tfstate
  • HTTP/HTTPS https://example.com/terraform.tfstate
  • Amazon S3 s3://{bucket}/{key}
  • Terraform Cloud remote://api.terraform.io/{organization}/{workspaces}
    • TFE_TOKEN environment variable is required.
  • Google Cloud Storage gs://{bucket}/{key}
  • Azure Blog Storage azurerm://{resource_group_name}/{storage_account_name}/{container_name}/{blob_name}

This plugin uses tfstate-lookup to load tfstate.

Multiple tfstate support

func_prefix adds a prefix to template function names for each plugin configuration.

# ecspresso.yml
plugins:
   - name: tfstate
     config:
       url: s3://tfstate/first.tfstate
     func_prefix: first_
   - name: tfstate
     config:
       url: s3://tfstate/second.tfstate
     func_prefix: second_

So in templates, functions are called with prefixes.

[
  "{{ first_tfstate `aws_s3_bucket.main.arn` }}",
  "{{ second_tfstate `aws_s3_bucket.main.arn` }}"
]
CloudFormation

The cloudformation plugin introduces template functions cfn_output and cfn_export.

An example of CloudFormation stack template defines Outputs and Exports.

# StackName: ECS-ecspresso
Outputs:
  SubnetAz1:
    Value: !Ref PublicSubnetAz1
  SubnetAz2:
    Value: !Ref PublicSubnetAz2
  EcsSecurityGroupId:
    Value: !Ref EcsSecurityGroup
    Export:
      Name: !Sub ${AWS::StackName}-EcsSecurityGroupId

Load cloudformation plugin in a config file.

ecspresso.yml

# ...
plugins:
  - name: cloudformation

cfn_output StackName OutputKey lookups OutputValue of OutputKey in the StackName. cfn_export ExportName lookups exported value by name.

ecs-service-def.json

{
  "networkConfiguration": {
    "awsvpcConfiguration": {
      "subnets": [
        "{{ cfn_output `ECS-ecspresso` `SubnetAz1` }}",
        "{{ cfn_output `ECS-ecspresso` `SubnetAz2` }}"
      ],
      "securityGroups": [
        "{{ cfn_export `ECS-ecspresso-EcsSecurityGroupId` }}"
      ]
    }
  }
}
Lookups ssm parameter store

The template function ssm reads parameters from AWS Systems Manager(SSM) Parameter Store.

Suppose ssm parameter store has the following parameters:

  • name: '/path/to/string', type: String, value: "ImString"
  • name: '/path/to/stringlist', type: StringList, value: "ImStringList0,ImStringList1"
  • name: '/path/to/securestring', type: SecureString, value: "ImSecureString"

Then this template,

{
  "string": "{{ ssm `/path/to/string` }}",
  "stringlist": "{{ ssm `/path/to/stringlist` 1 }}",  *1
  "securestring": "{{ ssm `/path/to/securestring` }}"
}

will be rendered into this.

{
  "string": "ImString",
  "stringlist": "ImStringList1",
  "securestring": "ImSecureStriing"
}
Resolve secretsmanager secret ARN

The template function secretsmanager_arn resolves secretsmanager secret ARN by secret name.

  "secrets": [
    {
      "name": "FOO",
      "valueFrom": "{{ secretsmanager_arn `foo` }}"
    }
  ]

will be rendered into this.

  "secrets": [
    {
      "name": "FOO",
      "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:foo-06XQOH"
    }
  ]

LICENCE

MIT

Author

KAYAC Inc.

Documentation

Index

Constants

View Source
const (
	DefaultClusterName = "default"
	DefaultTimeout     = 10 * time.Minute
)
View Source
const (
	CodeDeployConsoleURLFmt = "https://%s.console.aws.amazon.com/codesuite/codedeploy/deployments/%s?region=%s"
)
View Source
const DefaultConfigFilePath = "ecspresso.yml"
View Source
const DefaultDesiredCount = -1

Variables

View Source
var CreateFileMode = os.FileMode(0644)
View Source
var EventTimeFormat = "2006/01/02 15:04:05"
View Source
var Version string

Functions

func CLI

func CLI(ctx context.Context, parse CLIParseFunc) (int, error)

func CompareTags added in v2.2.0

func CompareTags(oldTags, newTags []types.Tag) (added, updated, deleted []types.Tag)

func ExportEnvFile

func ExportEnvFile(file string) error

ExportEnvFile exports envfile to environment variables.

func Log

func Log(f string, v ...interface{})

func MarshalJSONForAPI

func MarshalJSONForAPI(v interface{}, queries ...string) ([]byte, error)

func MustMarshalJSONStringForAPI

func MustMarshalJSONStringForAPI(v interface{}) string

func NormalizePlatform

func NormalizePlatform(p *types.RuntimePlatform, isFargate bool) (arch, os string)

func UnmarshalJSONForStruct added in v2.2.3

func UnmarshalJSONForStruct(src []byte, v interface{}, path string) error

Types

type App

type App struct {
	Service string
	Cluster string
	// contains filtered or unexported fields
}

func New

func New(ctx context.Context, opt *CLIOptions, newAppOptions ...AppOption) (*App, error)

func (*App) AppSpec

func (d *App) AppSpec(ctx context.Context, opt AppSpecOption) error

func (*App) Config

func (d *App) Config() *Config

func (*App) Delete

func (d *App) Delete(ctx context.Context, opt DeleteOption) error

func (*App) Deploy

func (d *App) Deploy(ctx context.Context, opt DeployOption) error

func (*App) DeployByCodeDeploy

func (d *App) DeployByCodeDeploy(ctx context.Context, taskDefinitionArn string, count *int32, sv *Service, opt DeployOption) error

func (*App) DeployFunc added in v2.0.4

func (d *App) DeployFunc(sv *Service) (deployFunc, error)

func (*App) Deregister

func (d *App) Deregister(ctx context.Context, opt DeregisterOption) error

func (*App) DescribeService

func (d *App) DescribeService(ctx context.Context) (*Service, error)

func (*App) DescribeServiceStatus

func (d *App) DescribeServiceStatus(ctx context.Context, events int) (*Service, error)

func (*App) DescribeServicesInput

func (d *App) DescribeServicesInput() *ecs.DescribeServicesInput

func (*App) DescribeTaskDefinition

func (d *App) DescribeTaskDefinition(ctx context.Context, tdArn string) (*TaskDefinitionInput, error)

func (*App) DescribeTaskStatus

func (d *App) DescribeTaskStatus(ctx context.Context, task *types.Task, watchContainer *types.ContainerDefinition) error

func (*App) DescribeTasksInput

func (d *App) DescribeTasksInput(task *types.Task) *ecs.DescribeTasksInput

func (*App) Diff

func (d *App) Diff(ctx context.Context, opt DiffOption) error

func (*App) Exec

func (d *App) Exec(ctx context.Context, opt ExecOption) error

func (*App) FilterCommand

func (d *App) FilterCommand() string

func (*App) FindRollbackTarget

func (d *App) FindRollbackTarget(ctx context.Context, taskDefinitionArn string) (string, error)

func (*App) GetLogEvents

func (d *App) GetLogEvents(ctx context.Context, logGroup string, logStream string, startedAt time.Time, nextToken *string) (*string, error)

func (*App) GetLogEventsInput

func (d *App) GetLogEventsInput(logGroup string, logStream string, startAt int64, nextToken *string) *cloudwatchlogs.GetLogEventsInput

func (*App) GetLogInfo

func (d *App) GetLogInfo(task *types.Task, c *types.ContainerDefinition) (string, string)

func (*App) Init

func (d *App) Init(ctx context.Context, opt InitOption) error

func (*App) LoadServiceDefinition

func (d *App) LoadServiceDefinition(path string) (*Service, error)

func (*App) LoadTaskDefinition

func (d *App) LoadTaskDefinition(path string) (*TaskDefinitionInput, error)

func (*App) Log

func (d *App) Log(f string, v ...interface{})

func (*App) LogJSON

func (d *App) LogJSON(v interface{})

func (*App) Name

func (d *App) Name() string

func (*App) NewEcsta

func (d *App) NewEcsta(ctx context.Context) (*ecsta.Ecsta, error)

func (*App) OutputJSONForAPI added in v2.0.5

func (d *App) OutputJSONForAPI(w io.Writer, v interface{}) error

func (*App) Register

func (d *App) Register(ctx context.Context, opt RegisterOption) error

func (*App) RegisterTaskDefinition

func (d *App) RegisterTaskDefinition(ctx context.Context, td *TaskDefinitionInput) (*TaskDefinition, error)

func (*App) Render

func (d *App) Render(ctx context.Context, opt RenderOption) error

func (*App) Revesions

func (d *App) Revesions(ctx context.Context, opt RevisionsOption) error

func (*App) Rollback

func (d *App) Rollback(ctx context.Context, opt RollbackOption) error

func (*App) RollbackByCodeDeploy

func (d *App) RollbackByCodeDeploy(ctx context.Context, sv *Service, opt RollbackOption) (string, error)

func (*App) RollbackFunc added in v2.0.4

func (d *App) RollbackFunc(sv *Service) (rollbackFunc, error)

func (*App) RollbackServiceTasks added in v2.0.4

func (d *App) RollbackServiceTasks(ctx context.Context, sv *Service, opt RollbackOption) (string, error)

func (*App) Run

func (d *App) Run(ctx context.Context, opt RunOption) error

func (*App) RunTask

func (d *App) RunTask(ctx context.Context, tdArn string, ov *types.TaskOverride, opt *RunOption) (*types.Task, error)

func (*App) Start

func (d *App) Start(ctx context.Context) (context.Context, context.CancelFunc)

func (*App) Status

func (d *App) Status(ctx context.Context, opt StatusOption) error

func (*App) Tasks

func (d *App) Tasks(ctx context.Context, opt TasksOption) error

func (*App) Timeout

func (d *App) Timeout() time.Duration

func (*App) UpdateServiceAttributes

func (d *App) UpdateServiceAttributes(ctx context.Context, sv *Service, taskDefinitionArn string, opt DeployOption) error

func (*App) UpdateServiceTags added in v2.2.0

func (d *App) UpdateServiceTags(ctx context.Context, sv *Service, added, updated, deleted []types.Tag, opt DeployOption) error

func (*App) UpdateServiceTasks

func (d *App) UpdateServiceTasks(ctx context.Context, taskDefinitionArn string, count *int32, sv *Service, opt DeployOption) error

func (*App) Verify

func (d *App) Verify(ctx context.Context, opt VerifyOption) error

Verify verifies service / task definitions related resources are valid.

func (*App) Wait

func (d *App) Wait(ctx context.Context, opt WaitOption) error

func (*App) WaitForCodeDeploy

func (d *App) WaitForCodeDeploy(ctx context.Context, sv *Service) error

func (*App) WaitFunc added in v2.0.4

func (d *App) WaitFunc(sv *Service) (waitFunc, error)

func (*App) WaitRunTask

func (d *App) WaitRunTask(ctx context.Context, task *types.Task, watchContainer *types.ContainerDefinition, startedAt time.Time, untilRunning bool) error

func (*App) WaitServiceStable

func (d *App) WaitServiceStable(ctx context.Context, sv *Service) error

func (*App) WaitTaskSetStable added in v2.0.4

func (d *App) WaitTaskSetStable(ctx context.Context, sv *Service) error

type AppOption added in v2.3.0

type AppOption func(*appOptions)

func WithConfig added in v2.3.0

func WithConfig(c *Config) AppOption

func WithConfigLoader added in v2.3.0

func WithConfigLoader(extstr, extcode map[string]string) AppOption

func WithLogger added in v2.3.0

func WithLogger(l *log.Logger) AppOption

type AppSpecOption

type AppSpecOption struct {
	TaskDefinition string `help:"use task definition arn in AppSpec (latest, current or Arn)" default:"latest"`
	UpdateService  bool   `help:"update service definition with task definition arn" default:"true" negatable:""`
}

type CLIOptions

type CLIOptions struct {
	Envfile        []string          `help:"environment files" env:"ECSPRESSO_ENVFILE"`
	Debug          bool              `help:"enable debug log" env:"ECSPRESSO_DEBUG"`
	ExtStr         map[string]string `help:"external string values for Jsonnet" env:"ECSPRESSO_EXT_STR"`
	ExtCode        map[string]string `help:"external code values for Jsonnet" env:"ECSPRESSO_EXT_CODE"`
	ConfigFilePath string            `name:"config" help:"config file" default:"ecspresso.yml" env:"ECSPRESSO_CONFIG"`
	AssumeRoleARN  string            `help:"the ARN of the role to assume" default:"" env:"ECSPRESSO_ASSUME_ROLE_ARN"`
	Timeout        *time.Duration    `help:"timeout. Override in a configuration file." env:"ECSPRESSO_TIMEOUT"`
	FilterCommand  string            `help:"filter command" env:"ECSPRESSO_FILTER_COMMAND"`

	Appspec    *AppSpecOption    `cmd:"" help:"output AppSpec YAML for CodeDeploy to STDOUT"`
	Delete     *DeleteOption     `cmd:"" help:"delete service"`
	Deploy     *DeployOption     `cmd:"" help:"deploy service"`
	Deregister *DeregisterOption `cmd:"" help:"deregister task definition"`
	Diff       *DiffOption       `cmd:"" help:"show diff between task definition, service definition with current running service and task definition"`
	Exec       *ExecOption       `cmd:"" help:"execute command on task"`
	Init       *InitOption       `cmd:"" help:"create configuration files from existing ECS service"`
	Refresh    *RefreshOption    `cmd:"" help:"refresh service. equivalent to deploy --skip-task-definition --force-new-deployment --no-update-service"`
	Register   *RegisterOption   `cmd:"" help:"register task definition"`
	Render     *RenderOption     `cmd:"" help:"render config, service definition or task definition file to STDOUT"`
	Revisions  *RevisionsOption  `cmd:"" help:"show revisions of task definitions"`
	Rollback   *RollbackOption   `cmd:"" help:"rollback service"`
	Run        *RunOption        `cmd:"" help:"run task"`
	Scale      *ScaleOption      `cmd:"" help:"scale service. equivalent to deploy --skip-task-definition --no-update-service"`
	Status     *StatusOption     `cmd:"" help:"show status of service"`
	Tasks      *TasksOption      `cmd:"" help:"list tasks that are in a service or having the same family"`
	Verify     *VerifyOption     `cmd:"" help:"verify resources in configurations"`
	Wait       *WaitOption       `cmd:"" help:"wait until service stable"`
	Version    struct{}          `cmd:"" help:"show version"`
}

func ParseCLIv2

func ParseCLIv2(args []string) (string, *CLIOptions, func(), error)

func (*CLIOptions) ForSubCommand

func (opts *CLIOptions) ForSubCommand(sub string) interface{}

type CLIParseFunc

type CLIParseFunc func([]string) (string, *CLIOptions, func(), error)

type Config

type Config struct {
	RequiredVersion       string            `yaml:"required_version,omitempty" json:"required_version,omitempty"`
	Region                string            `yaml:"region" json:"region"`
	Cluster               string            `yaml:"cluster" json:"cluster"`
	Service               string            `yaml:"service" json:"service"`
	ServiceDefinitionPath string            `yaml:"service_definition" json:"service_definition"`
	TaskDefinitionPath    string            `yaml:"task_definition" json:"task_definition"`
	Plugins               []ConfigPlugin    `yaml:"plugins,omitempty" json:"plugins,omitempty"`
	AppSpec               *appspec.AppSpec  `yaml:"appspec,omitempty" json:"appspec,omitempty"`
	FilterCommand         string            `yaml:"filter_command,omitempty" json:"filter_command,omitempty"`
	Timeout               *Duration         `yaml:"timeout,omitempty" json:"timeout,omitempty"`
	CodeDeploy            *ConfigCodeDeploy `yaml:"codedeploy,omitempty" json:"codedeploy,omitempty"`
	// contains filtered or unexported fields
}

Config represents a configuration.

func NewDefaultConfig

func NewDefaultConfig() *Config

NewDefaultConfig creates a default configuration.

func (*Config) AssumeRole added in v2.1.0

func (c *Config) AssumeRole(assumeRoleARN string)

func (*Config) OverrideByCLIOptions added in v2.3.0

func (c *Config) OverrideByCLIOptions(opt *CLIOptions)

func (*Config) Restrict

func (c *Config) Restrict(ctx context.Context) error

Restrict restricts a configuration.

func (*Config) ValidateVersion

func (c *Config) ValidateVersion(version string) error

ValidateVersion validates a version satisfies required_version.

type ConfigCodeDeploy

type ConfigCodeDeploy struct {
	ApplicationName     string `yaml:"application_name,omitempty" json:"application_name,omitempty"`
	DeploymentGroupName string `yaml:"deployment_group_name,omitempty" json:"deployment_group_name,omitempty"`
}

type ConfigPlugin

type ConfigPlugin struct {
	Name       string                 `yaml:"name" json:"name"`
	Config     map[string]interface{} `yaml:"config" json:"config"`
	FuncPrefix string                 `yaml:"func_prefix,omitempty" json:"func_prefix,omitempty"`
}

func (ConfigPlugin) AppendFuncMap

func (p ConfigPlugin) AppendFuncMap(c *Config, funcMap template.FuncMap) error

func (ConfigPlugin) Setup

func (p ConfigPlugin) Setup(ctx context.Context, c *Config) error

type DeleteOption

type DeleteOption struct {
	DryRun    bool `help:"dry-run" default:"false"`
	Force     bool `help:"delete without confirmation" default:"false"`
	Terminate bool `help:"delete with terminate tasks" default:"false"`
}

func (DeleteOption) DryRunString

func (opt DeleteOption) DryRunString() string

type DeployOption

type DeployOption struct {
	DryRun               bool   `help:"dry run" default:"false"`
	DesiredCount         *int32 `name:"tasks" help:"desired count of tasks" default:"-1"`
	SkipTaskDefinition   bool   `help:"skip register a new task definition" default:"false"`
	Revision             int64  `help:"revision of the task definition to run when --skip-task-definition" default:"0"`
	ForceNewDeployment   bool   `help:"force a new deployment of the service" default:"false"`
	Wait                 bool   `help:"wait for service stable" default:"true" negatable:""`
	SuspendAutoScaling   *bool  `help:"suspend application auto-scaling attached with the ECS service"`
	ResumeAutoScaling    *bool  `help:"resume application auto-scaling attached with the ECS service"`
	AutoScalingMin       *int32 `help:"set minimum capacity of application auto-scaling attached with the ECS service"`
	AutoScalingMax       *int32 `help:"set maximum capacity of application auto-scaling attached with the ECS service"`
	RollbackEvents       string `` /* 152-byte string literal not displayed */
	UpdateService        bool   `help:"update service attributes by service definition" default:"true" negatable:""`
	LatestTaskDefinition bool   `help:"deploy with the latest task definition without registering a new task definition" default:"false"`
}

func (DeployOption) DryRunString

func (opt DeployOption) DryRunString() string

func (DeployOption) ModifyAutoScalingParams added in v2.2.0

func (opt DeployOption) ModifyAutoScalingParams() *modifyAutoScalingParams

type DeregisterOption

type DeregisterOption struct {
	DryRun   bool   `help:"dry run" default:"false"`
	Keeps    *int   `help:"number of task definitions to keep except in-use"`
	Revision string `help:"revision number or 'latest'" default:""`
	Force    bool   `help:"force deregister without confirmation" default:"false"`
	Delete   bool   `help:"delete task definition on deregistered" default:"false"`
}

func (DeregisterOption) DryRunString

func (opt DeregisterOption) DryRunString() string

type DiffOption

type DiffOption struct {
	Unified bool `help:"unified diff format" default:"true" negatable:""`
}

type Duration

type Duration struct {
	time.Duration
}

func (*Duration) MarshalJSON

func (d *Duration) MarshalJSON() ([]byte, error)

func (*Duration) MarshalYAML

func (d *Duration) MarshalYAML() ([]byte, error)

func (*Duration) UnmarshalJSON

func (d *Duration) UnmarshalJSON(b []byte) error

func (*Duration) UnmarshalYAML

func (d *Duration) UnmarshalYAML(b []byte) error

type ErrConflictOptions added in v2.0.4

type ErrConflictOptions string

func (ErrConflictOptions) Error added in v2.0.4

func (e ErrConflictOptions) Error() string

type ErrNotFound

type ErrNotFound string

func (ErrNotFound) Error

func (e ErrNotFound) Error() string

type ErrSkipVerify

type ErrSkipVerify string

func (ErrSkipVerify) Error

func (e ErrSkipVerify) Error() string

type ExecOption

type ExecOption struct {
	ID        string `help:"task ID" default:""`
	Command   string `help:"command to execute" default:"sh"`
	Container string `help:"container name" default:""`

	PortForward bool   `help:"enable port forward" default:"false"`
	LocalPort   int    `help:"local port number" default:"0"`
	Port        int    `help:"remote port number (required for --port-forward)" default:"0"`
	Host        string `help:"remote host (required for --port-forward)" default:""`
}

type InitOption

type InitOption struct {
	Region                string `help:"AWS region" env:"AWS_REGION" default:""`
	Cluster               string `help:"ECS cluster name" default:"default"`
	Service               string `help:"ECS service name" required:"" xor:"FROM"`
	TaskDefinition        string `help:"ECS task definition name:revision" required:"" xor:"FROM"`
	TaskDefinitionPath    string `help:"path to output task definition file" default:"ecs-task-def.json"`
	ServiceDefinitionPath string `help:"path to output service definition file" default:"ecs-service-def.json"`
	Sort                  bool   `help:"sort elements in task definition" default:"false" negatable:""`
	ForceOverwrite        bool   `help:"overwrite existing files" default:"false"`
	Jsonnet               bool   `help:"output files as jsonnet format" default:"false"`
}

func (*InitOption) NewConfig

func (opt *InitOption) NewConfig(ctx context.Context, configFilePath string) (*Config, error)

type RefreshOption

type RefreshOption struct {
	DryRun bool `help:"dry run" default:"false"`
	Wait   bool `help:"wait for service stable" default:"true" negatable:""`
}

func (*RefreshOption) DeployOption

func (o *RefreshOption) DeployOption() DeployOption

type RegisterOption

type RegisterOption struct {
	DryRun bool `help:"dry run" default:"false"`
	Output bool `help:"output the registered task definition as JSON" default:"false"`
}

func (RegisterOption) DryRunString

func (opt RegisterOption) DryRunString() string

type RenderOption

type RenderOption struct {
	Targets *[]string `` /* 165-byte string literal not displayed */
	Jsonnet bool      `help:"render as jsonnet format" default:"false"`
}

type RevisionsOption

type RevisionsOption struct {
	Revision string `help:"revision number or 'current' or 'latest'" default:""`
	Output   string `help:"output format (json, table, tsv)" default:"table" enum:"json,table,tsv"`
}

type RollbackOption

type RollbackOption struct {
	DryRun                   bool   `help:"dry run" default:"false"`
	DeregisterTaskDefinition bool   `help:"deregister the rolled-back task definition. not works with --no-wait" default:"true" negatable:""`
	Wait                     bool   `help:"wait for the service stable" default:"true" negatable:""`
	RollbackEvents           string `` /* 152-byte string literal not displayed */
}

func (RollbackOption) DryRunString

func (opt RollbackOption) DryRunString() string

type RunOption

type RunOption struct {
	DryRun                 bool    `help:"dry run" default:"false"`
	TaskDefinition         string  `name:"task-def" help:"task definition file for run task" default:""`
	Wait                   bool    `help:"wait for task to complete" default:"true" negatable:""`
	TaskOverrideStr        string  `name:"overrides" help:"task override JSON string" default:""`
	TaskOverrideFile       string  `name:"overrides-file" help:"task override JSON file path" default:""`
	SkipTaskDefinition     bool    `help:"skip register a new task definition" default:"false"`
	Count                  int32   `help:"number of tasks to run (max 10)" default:"1"`
	WatchContainer         string  `help:"container name for watching exit code" default:""`
	LatestTaskDefinition   bool    `help:"use the latest task definition without registering a new task definition" default:"false"`
	PropagateTags          string  `help:"propagate the tags for the task (SERVICE or TASK_DEFINITION)" default:""`
	Tags                   string  `help:"tags for the task: format is KeyFoo=ValueFoo,KeyBar=ValueBar" default:""`
	WaitUntil              string  `help:"wait until invoked tasks status reached to (running or stopped)" default:"stopped" enum:"running,stopped"`
	Revision               *int64  `help:"revision of the task definition to run when --skip-task-definition" default:"0"`
	ClientToken            *string `help:"unique token that identifies a request, useful for idempotency"`
	EBSDeleteOnTermination *bool   `help:"whether to delete the EBS volume when the task is stopped" default:"true" negatable:""`
}

func (RunOption) DryRunString

func (opt RunOption) DryRunString() string

type ScaleOption

type ScaleOption struct {
	DryRun             bool   `help:"dry run" default:"false"`
	DesiredCount       *int32 `name:"tasks" help:"desired count of tasks" default:"-1"`
	Wait               bool   `help:"wait for service stable" default:"true" negatable:""`
	SuspendAutoScaling *bool  `help:"suspend application auto-scaling attached with the ECS service"`
	ResumeAutoScaling  *bool  `help:"resume application auto-scaling attached with the ECS service"`
	AutoScalingMin     *int32 `help:"set minimum capacity of application auto-scaling attached with the ECS service"`
	AutoScalingMax     *int32 `help:"set maximum capacity of application auto-scaling attached with the ECS service"`
}

func (*ScaleOption) DeployOption

func (o *ScaleOption) DeployOption() DeployOption

type Service

type Service struct {
	types.Service
	ServiceConnectConfiguration *types.ServiceConnectConfiguration
	VolumeConfigurations        []types.ServiceVolumeConfiguration
	DesiredCount                *int32
}

type ServiceForDiff added in v2.2.0

type ServiceForDiff struct {
	*ecs.UpdateServiceInput
	Tags []types.Tag
}

func ServiceDefinitionForDiff added in v2.2.0

func ServiceDefinitionForDiff(sv *Service) *ServiceForDiff

type StatusOption

type StatusOption struct {
	Events int `help:"show events num" default:"10"`
}

type TaskDefinition

type TaskDefinition = types.TaskDefinition

type TaskDefinitionInput

type TaskDefinitionInput = ecs.RegisterTaskDefinitionInput

type TasksOption

type TasksOption struct {
	ID     string `help:"task ID" default:""`
	Output string `help:"output format" enum:"table,json,tsv" default:"table"`
	Find   bool   `help:"find a task from tasks list and dump it as JSON" default:"false"`
	Stop   bool   `help:"stop the task" default:"false"`
	Force  bool   `help:"stop the task without confirmation" default:"false"`
	Trace  bool   `help:"trace the task" default:"false"`
}

type VerifyOption

type VerifyOption struct {
	GetSecrets bool `help:"get secrets from ParameterStore or SecretsManager" default:"true" negatable:""`
	PutLogs    bool `help:"put logs to CloudWatchLogs" default:"true" negatable:""`
	Cache      bool `help:"use cache" default:"true" negatable:""`
}

VerifyOption represents options for Verify()

type WaitOption

type WaitOption struct {
}

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL