ecspresso

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Oct 20, 2020 License: MIT Imports: 33 Imported by: 2

README

ecspresso

ecspresso is a deployment tool for Amazon ECS.

(pronounced same as "espresso")

Install

Homebrew (macOS and Linux)
$ brew install kayac/tap/ecspresso
Binary packages

Releases

CircleCI Orbs

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

version: 2.1
orbs:
  ecspresso: fujiwara/ecspresso@0.0.3
  jobs:
    steps:
      - checkout
      - ecspresso/install:
          version: 0.13.5
      - run:
          command: |
            ecspresso deploy --config config.yaml
GitHub Actions

Action kayac/ecspresso@v0 installs ecspresso binary for Linux into /usr/local/bin. This action runs install only.

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: kayac/ecspresso@v0
        with:
          version: v0.17.3
      - run: |
          ecspresso deploy --config config.yaml

Usage

usage: ecspresso --config=CONFIG [<flags>] <command> [<args> ...]

Flags:
  --help           Show context-sensitive help (also try --help-long and --help-man).
  --config=CONFIG  config file
  --debug          enable debug log

Commands:
  help [<command>...]
    Show help.

  version
    show version

  deploy [<flags>]
    deploy service

  create [<flags>]
    create service

  status [<flags>]
    show status of service

  rollback [<flags>]
    rollback service

  delete [<flags>]
    delete service

  run [<flags>]
    run task

  register [<flags>]
    register task definition

  wait
    wait until service stable

  init --region=REGION --service=SERVICE [<flags>]
    create service/task definition files by existing ECS service

  diff [<flags>]
    display diff for task definition compared with latest one on ECS

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

Quick Start

ecspresso can easily manage for 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 config.yaml
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 config.yaml

Let me see the generated files config.yaml, ecs-service-def.json, and ecs-task-def.json.

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

$ ecspresso deploy --config config.yaml

Configuration file

YAML format.

region: ap-northeast-1
cluster: default
service: myService
task_definition: myTask.json
timeout: 5m

ecspresso deploy works as below.

  • Register a new task definition from JSON file.
    • JSON file is allowed both of formats as below.
      • aws ecs describe-task-definition output.
      • aws ecs register-task-definition --cli-input-json input.
    • 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 a service tasks.
    • When --update-service option set, update service attributes by service definition.
  • Wait a service stable.

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

Example of deployment

Rolling deployment
$ ecspresso deploy --config config.yaml
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 create can create a service having CODE_DEPLOY deployment controller. See ecs-service-def.json below.

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

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

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

$ ecspresso deploy --config config.yaml --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 desired count of the service, specify --tasks option.

If --skip-task-definition is set, task definition will not be registered.

$ ecspresso deploy --config config.yaml --tasks 10 --skip-task-definition

Example of create

escpresso can create a service by service_definition JSON file and task_definition.

$ ecspresso create --config config.yaml
...
# config.yaml
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 same format as aws ecs describe-services output.

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

Example of run task

$ ecspresso run --config config.yaml --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

Deploy to Fargate

If you want to deploy services to Fargate, task-definition and service-definition requires some settings.

For task definition,

  • 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
    }
  ],
  # ...

Plugins

tfstate

tfstate plugin introduces a template function tfstate.

config.yaml

region: ap-northeast-1
cluster: default
service: test
service_definition: ecs-service-def.json
task_definition: ecs-task-def.json
plugins:
- name: tfstate
  config:
    path: terraform.tfstate    # path to tfstate file

ecs-service-def.json

{
  "networkConfiguration": {
    "awsvpcConfiguration": {
      "subnets": [
        "{{ tfstate `aws_subnet.private-a.id` }}"
      ],
      "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.

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 DefaultDesiredCount = -1

Variables

View Source
var CreateFileMode = os.FileMode(0644)
View Source
var TerminalWidth = 90

Functions

func MarshalJSON added in v0.11.0

func MarshalJSON(s interface{}) ([]byte, error)

func MarshalJSONString added in v0.16.0

func MarshalJSONString(s interface{}) string

Types

type App added in v0.0.2

type App struct {
	Service string
	Cluster string

	Debug bool
	// contains filtered or unexported fields
}

func NewApp added in v0.1.0

func NewApp(conf *Config) (*App, error)

func (*App) AppSpec added in v0.99.7

func (d *App) AppSpec(opt AppSpecOption) error

func (*App) Create added in v0.2.0

func (d *App) Create(opt CreateOption) error

func (*App) DebugLog added in v0.10.0

func (d *App) DebugLog(v ...interface{})

func (*App) Delete added in v0.4.0

func (d *App) Delete(opt DeleteOption) error

func (*App) Deploy added in v0.1.0

func (d *App) Deploy(opt DeployOption) error

func (*App) DeployByCodeDeploy added in v0.12.0

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

func (*App) DescribeService added in v0.16.0

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

func (*App) DescribeServiceDeployments added in v0.0.2

func (d *App) DescribeServiceDeployments(ctx context.Context, startedAt time.Time) (int, error)

func (*App) DescribeServiceStatus added in v0.1.0

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

func (*App) DescribeServicesInput added in v0.0.2

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

func (*App) DescribeTaskDefinition added in v0.8.1

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

func (*App) DescribeTaskStatus added in v0.15.0

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

func (*App) DescribeTasksInput added in v0.5.0

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

func (*App) Diff added in v0.16.0

func (d *App) Diff(opt DiffOption) error

func (*App) FindRollbackTarget added in v0.1.0

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

func (*App) GetLogEvents added in v0.5.0

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

func (*App) GetLogEventsInput added in v0.5.0

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

func (*App) GetLogInfo added in v0.5.0

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

func (*App) Init added in v0.11.0

func (d *App) Init(opt InitOption) error

func (*App) LoadServiceDefinition added in v0.2.0

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

func (*App) LoadTaskDefinition added in v0.0.2

func (d *App) LoadTaskDefinition(path string) (*ecs.TaskDefinition, error)

func (*App) Log added in v0.0.2

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

func (*App) LogJSON added in v0.16.0

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

func (*App) Name added in v0.0.2

func (d *App) Name() string

func (*App) Register added in v0.10.0

func (d *App) Register(opt RegisterOption) error

func (*App) RegisterTaskDefinition added in v0.0.2

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

func (*App) Rollback added in v0.1.0

func (d *App) Rollback(opt RollbackOption) error

func (*App) Run added in v0.5.0

func (d *App) Run(opt RunOption) error

func (*App) RunTask added in v0.5.0

func (d *App) RunTask(ctx context.Context, tdArn string, sv *ecs.Service, ov *ecs.TaskOverride, count int64) (*ecs.Task, error)

func (*App) Start added in v0.1.0

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

func (*App) Status added in v0.1.0

func (d *App) Status(opt StatusOption) error

func (*App) UpdateServiceAttributes added in v0.13.3

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

func (*App) UpdateServiceTasks added in v0.13.3

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

func (*App) Wait added in v0.9.0

func (d *App) Wait(opt WaitOption) error

func (*App) WaitForCodeDeploy added in v0.99.1

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

func (*App) WaitRunTask added in v0.5.0

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

func (*App) WaitServiceStable added in v0.0.2

func (d *App) WaitServiceStable(ctx context.Context, startedAt time.Time) error

func (*App) WaitUntilTaskStopped added in v0.15.1

func (d *App) WaitUntilTaskStopped(ctx context.Context, task *ecs.Task) error

type AppSpecOption added in v0.99.7

type AppSpecOption struct {
	TaskDefinition *string
}

type Config added in v0.0.2

type Config struct {
	Region                string           `yaml:"region"`
	Cluster               string           `yaml:"cluster"`
	Service               string           `yaml:"service"`
	ServiceDefinitionPath string           `yaml:"service_definition"`
	TaskDefinitionPath    string           `yaml:"task_definition"`
	Timeout               time.Duration    `yaml:"timeout"`
	Plugins               []ConfigPlugin   `yaml:"plugins"`
	AppSpec               *appspec.AppSpec `yaml:"appspec"`
	// contains filtered or unexported fields
}

func NewDefaultConfig added in v0.1.0

func NewDefaultConfig() *Config

func (*Config) Load added in v0.99.0

func (c *Config) Load(p string) error

Load loads configuration file from file path.

func (*Config) Restrict added in v0.99.0

func (c *Config) Restrict() error

Restrict restricts a configuration.

type ConfigPlugin added in v0.14.0

type ConfigPlugin struct {
	Name   string                 `yaml:"name"`
	Config map[string]interface{} `yaml:"config"`
}

func (ConfigPlugin) Setup added in v0.14.0

func (p ConfigPlugin) Setup(c *Config) error

type CreateOption added in v0.2.0

type CreateOption struct {
	DryRun       *bool
	DesiredCount *int64
	NoWait       *bool
}

func (CreateOption) DryRunString added in v0.13.3

func (opt CreateOption) DryRunString() string

type DeleteOption added in v0.4.0

type DeleteOption struct {
	DryRun *bool
	Force  *bool
}

func (DeleteOption) DryRunString added in v0.13.3

func (opt DeleteOption) DryRunString() string

type DeployOption added in v0.2.0

type DeployOption struct {
	DryRun               *bool
	DesiredCount         *int64
	SkipTaskDefinition   *bool
	ForceNewDeployment   *bool
	NoWait               *bool
	SuspendAutoScaling   *bool
	RollbackEvents       *string
	UpdateService        *bool
	LatestTaskDefinition *bool
}

func (DeployOption) DryRunString added in v0.13.3

func (opt DeployOption) DryRunString() string

type DiffOption added in v0.16.0

type DiffOption struct {
}

type DryRunnable added in v0.13.3

type DryRunnable interface {
	DryRunString() bool
}

type InitOption added in v0.11.0

type InitOption struct {
	Region                *string
	Cluster               *string
	Service               *string
	TaskDefinitionPath    *string
	ServiceDefinitionPath *string
	ConfigFilePath        *string
}

type RegisterOption added in v0.10.0

type RegisterOption struct {
	DryRun *bool
	Output *bool
}

func (RegisterOption) DryRunString added in v0.13.3

func (opt RegisterOption) DryRunString() string

type RollbackOption added in v0.2.0

type RollbackOption struct {
	DryRun                   *bool
	DeregisterTaskDefinition *bool
	NoWait                   *bool
}

func (RollbackOption) DryRunString added in v0.13.3

func (opt RollbackOption) DryRunString() string

type RunOption added in v0.5.0

type RunOption struct {
	DryRun             *bool
	TaskDefinition     *string
	NoWait             *bool
	TaskOverrideStr    *string
	SkipTaskDefinition *bool
	Count              *int64
	WatchContainer     *string
}

func (RunOption) DryRunString added in v0.13.3

func (opt RunOption) DryRunString() string

type StatusOption added in v0.2.0

type StatusOption struct {
	Events *int
}

type WaitOption added in v0.9.0

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