Skip to content

Commit 482c967

Browse files
authored
Merge pull request #106 from buildkite-plugins/toote_deprecate_create_service
Deprecate ECS service creation
2 parents 5912855 + 5d9c44f commit 482c967

9 files changed

+121
-449
lines changed

README.md

+13-52
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ steps:
1515
concurrency_group: "my-service-deploy"
1616
concurrency: 1
1717
plugins:
18-
- ecs-deploy#v2.1.0:
18+
- ecs-deploy#v3.0.0:
1919
cluster: "my-ecs-cluster"
2020
service: "my-service"
2121
container-definitions: "examples/hello-world.json"
@@ -96,87 +96,50 @@ Example: `"my-task"`
9696

9797
### Optional
9898

99-
#### `deployment-configuration` (optional)
99+
#### `env` (array)
100100

101-
The minimum and maximum percentage of tasks that should be maintained during a deployment. Defaults to `100/200`
101+
An array of environment variables to add to *every* image's task definition in the `NAME=VALUE` format
102102

103-
Example: `"0/100"`
104-
105-
#### `env` (optional)
106-
107-
An array of environment variables to add to *every* image's task definition
108-
109-
#### `execution-role` (optional)
103+
#### `execution-role`
110104

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

113107
Example: `"arn:aws:iam::012345678910:role/execution-role"`
114108

115109
Requires the `iam:PassRole` permission for the execution role.
116110

117-
#### `load-balancer-name` (optional)
118-
119-
The name of the Elastic Load Balancer (Application or Network) used with the ECS Service.
120-
121-
Example: `application-load-balancer`
122-
123-
#### `region` (optional)
111+
#### `region`
124112

125113
The region we deploy the ECS Service to.
126114

127-
#### `service-definition`
128-
129-
The file path to the ECS service definition JSON file. Parameters specified in this file will be overridden by other arguments if set, e.g. `cluster`, `desired-count`, etc. Note that currently this json input will only be used when creating the service, NOT when updating it.
130-
131-
Example: `"ecs/service.json"`
132-
```json
133-
{
134-
"schedulingStrategy": "DAEMON",
135-
"propagateTags": "TASK_DEFINITION"
136-
}
137-
```
138-
139-
#### `target-container-name` (optional)
140-
141-
The Container Name to forward ALB requests to.
142-
143-
#### `target-container-port` (optional)
144-
145-
The Container Port to forward requests to.
146-
147-
#### `target-group` (optional)
148-
149-
The Target Group ARN to map the service to.
150-
151-
Example: `"arn:aws:elasticloadbalancing:us-east-1:012345678910:targetgroup/alb/e987e1234cd12abc"`
152-
153-
#### `task-cpu` (optional, integer)
115+
#### `task-cpu` (integer)
154116

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

157-
#### `task-ephemeral-storage` (optional, integer)
119+
#### `task-ephemeral-storage` (integer)
158120

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

161-
#### `task-ipc-mode` (optional)
123+
#### `task-ipc-mode`
162124

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

165-
#### `task-memory` (optional, integer)
127+
#### `task-memory` (integer)
166128

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

169-
#### `task-network-mode` (optional)
131+
#### `task-network-mode`
170132

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

173-
#### `task-pid-mode` (optional)
135+
#### `task-pid-mode`
174136

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

177-
#### `task-role-arn` (optional)
139+
#### `task-role-arn`
178140

179141
An IAM ECS Task Role to assign to tasks.
142+
180143
Requires the `iam:PassRole` permission for the ARN specified.
181144

182145
## AWS Roles
@@ -195,8 +158,6 @@ Policy:
195158
Resource: '*'
196159
```
197160

198-
This plugin will create the ECS Service if it does not already exist, which additionally requires the `ecs:CreateService` permission.
199-
200161
## Developing
201162

202163
To run testing, shellchecks and plugin linting use use `bk run` with the [Buildkite CLI](https://github.com/buildkite/cli).

examples/service-definition.json

-4
This file was deleted.

hooks/command

+22-103
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,35 @@ if ! plugin_read_list_into_result "IMAGE"; then
1717
fi
1818
images=("${result[@]}")
1919

20-
# optional configurations
21-
desired_count=${BUILDKITE_PLUGIN_ECS_DEPLOY_DESIRED_COUNT:-"1"}
22-
target_group=${BUILDKITE_PLUGIN_ECS_DEPLOY_TARGET_GROUP:-""}
23-
load_balancer_name=${BUILDKITE_PLUGIN_ECS_DEPLOY_LOAD_BALANCER_NAME:-""}
24-
target_container=${BUILDKITE_PLUGIN_ECS_DEPLOY_TARGET_CONTAINER_NAME:-""}
25-
target_port=${BUILDKITE_PLUGIN_ECS_DEPLOY_TARGET_CONTAINER_PORT:-""}
26-
2720
if [ -n "${BUILDKITE_PLUGIN_ECS_DEPLOY_TASK_DEFINITION:-""}" ]; then
2821
echo ":boom: The task-definition parameter has been deprecated"
2922
exit 1
3023
fi
3124

25+
if [ -n "${BUILDKITE_PLUGIN_ECS_DEPLOY_SERVICE_DEFINITION:-""}" ]; then
26+
echo ":boom: The service-definition parameter has been deprecated"
27+
echo "Create the service outside of this plugin first (using CloudFormation or Terraform)"
28+
exit 1
29+
fi
30+
31+
for DEPRECATED_CONFIG in deployment-config deployment-configuration desired-count load-balancer-name target-container-name target-container-port target-group; do
32+
VAR_NAME="BUILDKITE_PLUGIN_ECS_DEPLOY_$(echo "${DEPRECATED_CONFIG}" | tr 'a-z-' 'A-Z_')"
33+
34+
if [ -n "${!VAR_NAME:-""}" ]; then
35+
echo ":warning: The ${DEPRECATED_CONFIG} parameter has been deprecated"
36+
echo "Please configure the service outside of this plugin"
37+
fi
38+
done
39+
40+
aws_default_args=()
41+
if [ -n "${BUILDKITE_PLUGIN_ECS_DEPLOY_REGION:-}" ]; then
42+
aws_default_args+=(--region "${BUILDKITE_PLUGIN_ECS_DEPLOY_REGION}")
43+
fi
44+
3245
task_file=$(mktemp)
3346
trap 'rm "${task_file}"' EXIT
3447

35-
if ! aws ecs describe-task-definition --task-definition "${task_family}" --query 'taskDefinition' >"${task_file}"; then
48+
if ! aws ecs describe-task-definition "${aws_default_args[@]+"${aws_default_args[@]}"}" --task-definition "${task_family}" --query 'taskDefinition' >"${task_file}"; then
3649
echo "Could not obtain existing task definition"
3750
fi
3851

@@ -56,15 +69,6 @@ else
5669
env_vars=()
5770
fi
5871

59-
aws_default_args=()
60-
if [ -n "${BUILDKITE_PLUGIN_ECS_DEPLOY_REGION:-}" ]; then
61-
aws_default_args+=(--region "${BUILDKITE_PLUGIN_ECS_DEPLOY_REGION}")
62-
fi
63-
64-
# Resolve any runtime environment variables it has
65-
target_group=$(eval "echo $target_group")
66-
load_balancer_name=$(eval "echo $load_balancer_name")
67-
6872
# jq has no in-place edition https://github.com/jqlang/jq/issues/105
6973
container_definitions_json=$(cat "${container_definitions}")
7074
image_idx=0
@@ -166,91 +170,6 @@ fi
166170
task_revision=$(jq '.taskDefinition.revision' <<< "$json_output")
167171
echo "Registered ${task_family}:${task_revision}"
168172

169-
# Create service if it doesn't already exist
170-
aws_describe_service_args=(
171-
--cluster "$cluster"
172-
--service "$service_name"
173-
)
174-
175-
aws_create_service_args=(
176-
--cluster "$cluster"
177-
--service-name "$service_name"
178-
--task-definition "${task_family}:${task_revision}"
179-
--desired-count "$desired_count"
180-
)
181-
182-
service_definition=${BUILDKITE_PLUGIN_ECS_DEPLOY_SERVICE_DEFINITION:-""}
183-
if [[ -n "${service_definition}" ]]; then
184-
service_definition_json=$(cat "${service_definition}")
185-
else
186-
service_definition_json="{}"
187-
fi
188-
189-
service_defined=$(
190-
aws ecs describe-services \
191-
"${aws_default_args[@]+"${aws_default_args[@]}"}" \
192-
"${aws_describe_service_args[@]}" \
193-
--query "services[?status=='ACTIVE'].status" \
194-
--output text \
195-
| wc -l
196-
)
197-
198-
deployment_config=${BUILDKITE_PLUGIN_ECS_DEPLOY_DEPLOYMENT_CONFIGURATION:-"100/200"}
199-
IFS="/" read -r -a min_max_percent <<< "${deployment_config}"
200-
min_deploy_perc=${min_max_percent[0]}
201-
max_deploy_perc=${min_max_percent[1]}
202-
203-
aws_create_service_args+=(--deployment-configuration "maximumPercent=${max_deploy_perc},minimumHealthyPercent=${min_deploy_perc}")
204-
205-
if [[ -n $target_container ]] && [[ -n $target_port ]]; then
206-
if [[ -n $target_group ]]; then
207-
load_balancer_ref="targetGroupArn=${target_group}"
208-
elif [[ -n $load_balancer_name ]]; then
209-
load_balancer_ref="loadBalancerName=${load_balancer_name}"
210-
else
211-
echo "+++ ^^^"
212-
echo '+++ You must specify either target-group or load-balancer-name'
213-
exit 1
214-
fi
215-
216-
aws_create_service_args+=(--load-balancers "${load_balancer_ref},containerName=${target_container},containerPort=${target_port}")
217-
fi
218-
219-
if [[ $service_defined -eq 0 ]]; then
220-
echo "--- :ecs: Creating a Service $service_name in cluster $cluster"
221-
222-
aws ecs create-service \
223-
"${aws_default_args[@]+"${aws_default_args[@]}"}" \
224-
"${aws_create_service_args[@]}" \
225-
--cli-input-json "$service_definition_json"
226-
fi
227-
228-
lb_config=$(aws ecs describe-services --cluster "$cluster" --services "$service_name" --query "services[?status=='ACTIVE']" | jq -r '.[0].loadBalancers[0]')
229-
error="+++ ^^^
230-
+++ 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"
231-
232-
# No easy way to tell if the target group has changed, since describe-services only returns the load balancer name
233-
if [[ "$lb_config" == "null" ]]; then
234-
if [[ -n "$target_group" ]] || [[ -n "$load_balancer_name" ]]; then
235-
echo "$error. ELB configured but none set in container"
236-
exit 1
237-
fi
238-
fi
239-
240-
if [[ "$lb_config" == "null" ]]; then
241-
# noop
242-
true
243-
elif [[ $(echo "$lb_config" | jq -r '.containerName') != "$target_container" ]] || [[ $(echo "$lb_config" | jq -r '.containerPort') -ne $target_port ]]; then
244-
echo "$error. Container config differs"
245-
exit 1
246-
elif [[ -n "$target_group" ]] && [[ $(echo "$lb_config" | jq -r '.targetGroupArn') != "$target_group" ]]; then
247-
echo "$error. ALB config differs"
248-
exit 1
249-
elif [[ -n "$load_balancer_name" ]] && [[ $(echo "$lb_config" | jq -r '.loadBalancerName') != "$load_balancer_name" ]]; then
250-
echo "$error. ELB config differs"
251-
exit 1
252-
fi
253-
254173
echo "--- :ecs: Updating service for ${service_name}"
255174
aws ecs update-service \
256175
${aws_default_args[@]+"${aws_default_args[@]}"} \
@@ -270,7 +189,7 @@ aws ecs wait services-stable \
270189
service_events=$(aws ecs describe-services \
271190
${aws_default_args[@]+"${aws_default_args[@]}"} \
272191
--cluster "${cluster}" \
273-
--service "${service_name}" \
192+
--services "${service_name}" \
274193
--query 'services[].events' --output text)
275194

276195
if [[ $deploy_exitcode -eq 0 ]]; then

plugin.yml

+4-13
Original file line numberDiff line numberDiff line change
@@ -10,42 +10,33 @@ configuration:
1010
type: string
1111
container-definitions:
1212
type: string
13-
deployment-config:
14-
type: string
15-
desired-count:
16-
type: string
1713
env:
1814
type: array
1915
execution-role:
2016
type: string
2117
image:
2218
type: [ string, array ]
23-
load-balancer-name:
19+
region:
2420
type: string
2521
service:
2622
type: string
27-
service-definition:
28-
type: string
29-
target-container-name:
30-
type: string
31-
target-container-port:
32-
type: integer
33-
target-group:
34-
type: string
3523
task-cpu:
3624
type: integer
3725
task-ephemeral-storage:
3826
type: integer
3927
task-ipc-mode:
4028
type: string
29+
enum: [ "host", "none", "task"]
4130
task-family:
4231
type: string
4332
task-memory:
4433
type: integer
4534
task-network-mode:
4635
type: string
36+
enum: [ "awsvpc", "bridge", "host", "none" ]
4737
task-pid-mode:
4838
type: string
39+
enum: [ "host", "task" ]
4940
task-role-arn:
5041
type: string
5142
required:

0 commit comments

Comments
 (0)