Skip to content

Commit 3145f35

Browse files
authored
Merge pull request #83 from buildkite-plugins/toote_refactor
Refactor (and minor bug correction)
2 parents a0ba261 + 0b89610 commit 3145f35

File tree

6 files changed

+247
-206
lines changed

6 files changed

+247
-206
lines changed

.buildkite/pipeline.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ steps:
1212
- label: ":shell: Shellcheck"
1313
plugins:
1414
shellcheck#v1.3.0:
15-
files: hooks/**
15+
files:
16+
- hooks/**
17+
- lib/**

hooks/command

Lines changed: 91 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,48 @@
11
#!/bin/bash
22
set -euo pipefail
33

4-
# Reads either a value or a list from plugin config
5-
function plugin_read_list() {
6-
prefix_read_list "BUILDKITE_PLUGIN_ECS_DEPLOY_$1"
7-
}
4+
DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)"
85

9-
# Reads either a value or a list from the given env prefix
10-
function prefix_read_list() {
11-
local prefix="$1"
12-
local parameter="${prefix}_0"
13-
14-
if [[ -n "${!parameter:-}" ]]; then
15-
local i=0
16-
local parameter="${prefix}_${i}"
17-
while [[ -n "${!parameter:-}" ]]; do
18-
echo "${!parameter}"
19-
i=$((i+1))
20-
parameter="${prefix}_${i}"
21-
done
22-
elif [[ -n "${!prefix:-}" ]]; then
23-
echo "${!prefix}"
24-
fi
25-
}
6+
# shellcheck source=lib/plugin.bash
7+
. "$DIR/../lib/plugin.bash"
268

27-
cluster=${BUILDKITE_PLUGIN_ECS_DEPLOY_CLUSTER?}
28-
task_family=${BUILDKITE_PLUGIN_ECS_DEPLOY_TASK_FAMILY?}
29-
service_name=${BUILDKITE_PLUGIN_ECS_DEPLOY_SERVICE?}
30-
images=()
31-
while read -r line ; do
32-
[[ -n "$line" ]] && images+=("$line")
33-
done <<< "$(plugin_read_list IMAGE)"
34-
task_definition=${BUILDKITE_PLUGIN_ECS_DEPLOY_TASK_DEFINITION:-""}
35-
service_definition=${BUILDKITE_PLUGIN_ECS_DEPLOY_SERVICE_DEFINITION:-""}
36-
container_definitions=${BUILDKITE_PLUGIN_ECS_DEPLOY_CONTAINER_DEFINITIONS?}
9+
# mandatory configurations
10+
cluster=${BUILDKITE_PLUGIN_ECS_DEPLOY_CLUSTER?Missing cluster}
11+
container_definitions=${BUILDKITE_PLUGIN_ECS_DEPLOY_CONTAINER_DEFINITIONS?Missing container definitions}
12+
task_family=${BUILDKITE_PLUGIN_ECS_DEPLOY_TASK_FAMILY?Missing task family}
13+
service_name=${BUILDKITE_PLUGIN_ECS_DEPLOY_SERVICE?Missing service name}
14+
15+
if ! plugin_read_list_into_result "IMAGE"; then
16+
echo ":boom: Missing image to use"
17+
exit 1
18+
fi
19+
images=("${result[@]}")
20+
21+
# optional configurations
3722
desired_count=${BUILDKITE_PLUGIN_ECS_DEPLOY_DESIRED_COUNT:-"1"}
38-
task_role_arn=${BUILDKITE_PLUGIN_ECS_DEPLOY_TASK_ROLE_ARN:-""}
3923
target_group=${BUILDKITE_PLUGIN_ECS_DEPLOY_TARGET_GROUP:-""}
4024
load_balancer_name=${BUILDKITE_PLUGIN_ECS_DEPLOY_LOAD_BALANCER_NAME:-""}
4125
target_container=${BUILDKITE_PLUGIN_ECS_DEPLOY_TARGET_CONTAINER_NAME:-""}
4226
target_port=${BUILDKITE_PLUGIN_ECS_DEPLOY_TARGET_CONTAINER_PORT:-""}
43-
execution_role=${BUILDKITE_PLUGIN_ECS_DEPLOY_EXECUTION_ROLE:-""}
27+
28+
# necessary for compatibility with bash 4.3
29+
if plugin_read_list_into_result "ENV"; then
30+
env_vars=("${result[@]}")
31+
else
32+
env_vars=()
33+
fi
34+
35+
aws_default_args=()
4436
region=${BUILDKITE_PLUGIN_ECS_DEPLOY_REGION:-""}
45-
env_vars=()
46-
while read -r line ; do
47-
[[ -n "$line" ]] && env_vars+=("$line")
48-
done <<< "$(plugin_read_list ENV)"
49-
50-
if [[ $region != "" ]]; then
51-
# shellcheck disable=SC2034 # Used by the aws cli
52-
AWS_DEFAULT_REGION=${region}
37+
if [[ -n "${region}" ]]; then
38+
aws_default_args+=(--region "${region}")
5339
fi
5440

5541
# Resolve any runtime environment variables it has
5642
target_group=$(eval "echo $target_group")
5743
load_balancer_name=$(eval "echo $load_balancer_name")
5844

59-
deployment_config=${BUILDKITE_PLUGIN_ECS_DEPLOY_DEPLOYMENT_CONFIGURATION:-"100/200"}
60-
# shellcheck disable=SC2206
61-
min_max_percent=(${deployment_config//\// })
62-
min_deploy_perc=${min_max_percent[0]}
63-
max_deploy_perc=${min_max_percent[1]}
64-
65-
if [[ $(jq '. | keys |first' "$container_definitions") != "0" ]]; then
45+
if [[ $(jq '. | keys | first' "$container_definitions") != "0" ]]; then
6646
echo "^^^"
6747
echo "Invalid Container Definitions"
6848
echo 'JSON definition should be in the format of [{"image": "..."}]'
@@ -74,26 +54,42 @@ function create_service() {
7454
local task_definition=$2
7555
local service_name=$3
7656
local desired_count=$4
77-
local target_group_arguments
78-
target_group_arguments=$(generate_target_group_arguments "$5" "$6" "$7")
79-
8057
local service_definition_json="{}"
58+
local target_group_arguments
59+
60+
generate_target_group_arguments "$5" "$6" "$7"
61+
target_group_arguments=("${result[@]}") # copying the array
62+
63+
service_definition=${BUILDKITE_PLUGIN_ECS_DEPLOY_SERVICE_DEFINITION:-""}
8164
if [[ -n "${service_definition}" ]]; then
8265
service_definition_json=$(cat "${service_definition}")
8366
fi
8467

85-
# shellcheck disable=SC2016
86-
service_defined=$(aws ecs describe-services --cluster "$cluster_name" --service "$service_name" --query 'services[?status==`ACTIVE`].status' --output text |wc -l)
68+
service_defined=$(
69+
aws ecs describe-services \
70+
"${aws_default_args[@]}" \
71+
--cluster "$cluster_name" \
72+
--service "$service_name" \
73+
--query 'services[?status=="ACTIVE"].status' \
74+
--output text \
75+
| wc -l
76+
)
8777
if [[ $service_defined -eq 0 ]]; then
88-
echo "--- :ecs: Creating a Service $service_name in cluster $cluster_name"
89-
# shellcheck disable=SC2086
90-
aws ecs create-service \
78+
echo "--- :ecs: Creating a Service $service_name in cluster $cluster_name"
79+
80+
deployment_config=${BUILDKITE_PLUGIN_ECS_DEPLOY_DEPLOYMENT_CONFIGURATION:-"100/200"}
81+
IFS="/" read -r -a min_max_percent <<< "${deployment_config}"
82+
min_deploy_perc=${min_max_percent[0]}
83+
max_deploy_perc=${min_max_percent[1]}
84+
85+
aws ecs create-service \
86+
"${aws_default_args[@]}" \
9187
--cluster "$cluster_name" \
9288
--service-name "$service_name" \
9389
--task-definition "$task_definition" \
9490
--desired-count "$desired_count" \
9591
--deployment-configuration "maximumPercent=${max_deploy_perc},minimumHealthyPercent=${min_deploy_perc}" \
96-
$target_group_arguments \
92+
"${target_group_arguments[@]}" \
9793
--cli-input-json "$service_definition_json"
9894
fi
9995
}
@@ -102,7 +98,7 @@ function generate_target_group_arguments() {
10298
local target_group=$1
10399
local target_container=$2
104100
local target_port=$3
105-
local target_group_arguments=""
101+
result=()
106102
if [[ -n $target_container ]] && [[ -n $target_port ]]; then
107103
local load_balancer_ref=""
108104
if [[ -n $target_group ]]; then
@@ -111,60 +107,65 @@ function generate_target_group_arguments() {
111107
load_balancer_ref="loadBalancerName=${load_balancer_name}"
112108
else
113109
echo "+++ ^^^"
114-
# shellcheck disable=SC2016
115-
echo '+++ You must specify either `target-group` or `load-balancer-name`'
110+
echo '+++ You must specify either target-group or load-balancer-name'
116111
exit 1
117112
fi
118113

119-
target_group_arguments="--load-balancers ${load_balancer_ref},containerName=${target_container},containerPort=${target_port}"
114+
result+=(--load-balancers "${load_balancer_ref},containerName=${target_container},containerPort=${target_port}")
120115
fi
121-
echo "$target_group_arguments"
116+
return 0
122117
}
123118

124119
## This is the template definition of your containers
125120
image_idx=0
126121
container_definitions_json=$(cat "${container_definitions}")
127122
for image in "${images[@]}"; do
128-
container_definitions_json=$(echo "$container_definitions_json" | jq --arg IMAGE "$image" \
129-
".[${image_idx}].image=\$IMAGE"
123+
container_definitions_json=$(
124+
echo "$container_definitions_json" \
125+
| jq --arg IMAGE "$image" ".[${image_idx}].image=\$IMAGE"
130126
)
131-
image_idx=$((image_idx+1))
132-
done
133127

134-
## This adds the env vars to each container
135-
image_idx=0
136-
for image in "${images[@]}"; do
137-
for env_var in "${env_vars[@]}"; do
138-
# shellcheck disable=SC2206
139-
var_val=(${env_var//=/ })
140-
container_definitions_json=$(echo "$container_definitions_json" | jq --arg ENVVAR "${var_val[0]}" --arg ENVVAL "${var_val[1]}" \
141-
".[${image_idx}].environment += [{\"name\": \$ENVVAR, \"value\": \$ENVVAL}]"
142-
)
143-
done
128+
# this check is only necessary to be compatible with bash 4.3 (see issue #81)
129+
if [ "${#env_vars[@]}" -gt 0 ]; then
130+
for env_var in "${env_vars[@]}"; do
131+
IFS="=" read -r -a var_val <<< "${env_var}"
132+
container_definitions_json=$(
133+
echo "$container_definitions_json" \
134+
| jq --arg ENVVAR "${var_val[0]}" --arg ENVVAL "${var_val[1]}" \
135+
".[${image_idx}].environment += [{\"name\": \$ENVVAR, \"value\": \$ENVVAL}]"
136+
)
137+
done
138+
fi
139+
144140
image_idx=$((image_idx+1))
145141
done
146142

147143
echo "--- :ecs: Registering new task definition for ${task_family}"
148-
register_command="aws ecs register-task-definition \
149-
--family ${task_family} \
150-
--container-definitions '$container_definitions_json'"
144+
register_command=(aws ecs register-task-definition
145+
"${aws_default_args[@]}"
146+
--family "${task_family}"
147+
--container-definitions "${container_definitions_json}"
148+
)
151149

150+
task_role_arn=${BUILDKITE_PLUGIN_ECS_DEPLOY_TASK_ROLE_ARN:-""}
152151
if [[ -n "${task_role_arn}" ]]; then
153-
register_command+=" --task-role-arn ${task_role_arn}"
152+
register_command+=(--task-role-arn "${task_role_arn}")
154153
fi
155154

155+
execution_role=${BUILDKITE_PLUGIN_ECS_DEPLOY_EXECUTION_ROLE:-""}
156156
if [[ -n "${execution_role}" ]]; then
157-
register_command+=" --execution-role-arn ${execution_role}"
157+
register_command+=(--execution-role-arn "${execution_role}")
158158
fi
159159

160+
task_definition=${BUILDKITE_PLUGIN_ECS_DEPLOY_TASK_DEFINITION:-""}
160161
if [[ -n "${task_definition}" ]]; then
161162
task_definition_json=$(cat "${task_definition}")
162-
register_command+=" --cli-input-json '${task_definition_json}'"
163+
register_command+=(--cli-input-json "${task_definition_json}")
163164
fi
164165

165166
echo "--- :ecs: register command:"
166167

167-
json_output=$(eval "$register_command")
168+
json_output=$("${register_command[@]}")
168169
register_exit_code=$?
169170

170171
if [[ $register_exit_code -ne 0 ]] ; then
@@ -179,8 +180,7 @@ echo "Registered ${task_family}:${task_revision}"
179180
# Create service if it doesn't already exist
180181
create_service "$cluster" "${task_family}:${task_revision}" "$service_name" "$desired_count" "$target_group" "$target_container" "$target_port"
181182

182-
# shellcheck disable=SC2016
183-
lb_config=$(aws ecs describe-services --cluster "$cluster" --services "$service_name" --query 'services[?status==`ACTIVE`]' |jq -r '.[0].loadBalancers[0]')
183+
lb_config=$(aws ecs describe-services --cluster "$cluster" --services "$service_name" --query 'services[?status=="ACTIVE"]' | jq -r '.[0].loadBalancers[0]')
184184
error="+++ ^^^
185185
+++ 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"
186186

@@ -195,19 +195,20 @@ fi
195195
if [[ "$lb_config" == "null" ]]; then
196196
# noop
197197
true
198-
elif [[ $(echo "$lb_config" |jq -r '.containerName') != "$target_container" ]] || [[ $(echo "$lb_config" |jq -r '.containerPort') -ne $target_port ]]; then
198+
elif [[ $(echo "$lb_config" | jq -r '.containerName') != "$target_container" ]] || [[ $(echo "$lb_config" | jq -r '.containerPort') -ne $target_port ]]; then
199199
echo "$error. Container config differs"
200200
exit 1
201-
elif [[ -n "$target_group" ]] && [[ $(echo "$lb_config" |jq -r '.targetGroupArn') != "$target_group" ]]; then
201+
elif [[ -n "$target_group" ]] && [[ $(echo "$lb_config" | jq -r '.targetGroupArn') != "$target_group" ]]; then
202202
echo "$error. ALB config differs"
203203
exit 1
204-
elif [[ -n "$load_balancer_name" ]] && [[ $(echo "$lb_config" |jq -r '.loadBalancerName') != "$load_balancer_name" ]]; then
204+
elif [[ -n "$load_balancer_name" ]] && [[ $(echo "$lb_config" | jq -r '.loadBalancerName') != "$load_balancer_name" ]]; then
205205
echo "$error. ELB config differs"
206206
exit 1
207207
fi
208208

209209
echo "--- :ecs: Updating service for ${service_name}"
210210
aws ecs update-service \
211+
"${aws_default_args[@]}" \
211212
--cluster "${cluster}" \
212213
--service "${service_name}" \
213214
--task-definition "${task_family}:${task_revision}"
@@ -216,11 +217,13 @@ aws ecs update-service \
216217
echo "--- :ecs: Waiting for services to stabilize"
217218
deploy_exitcode=0
218219
aws ecs wait services-stable \
220+
"${aws_default_args[@]}" \
219221
--cluster "${cluster}" \
220222
--services "${service_name}" || deploy_exitcode=$?
221223

222224

223225
service_events=$(aws ecs describe-services \
226+
"${aws_default_args[@]}" \
224227
--cluster "${cluster}" \
225228
--service "${service_name}" \
226229
--query 'services[].events' --output text)

lib/plugin.bash

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
PLUGIN_PREFIX="ECS_DEPLOY"
5+
6+
# Reads either a value or a list from the given env prefix
7+
function prefix_read_list() {
8+
local prefix="$1"
9+
local parameter="${prefix}_0"
10+
11+
if [ -n "${!parameter:-}" ]; then
12+
local i=0
13+
local parameter="${prefix}_${i}"
14+
while [ -n "${!parameter:-}" ]; do
15+
echo "${!parameter}"
16+
i=$((i+1))
17+
parameter="${prefix}_${i}"
18+
done
19+
elif [ -n "${!prefix:-}" ]; then
20+
echo "${!prefix}"
21+
fi
22+
}
23+
24+
# Reads either a value or a list from plugin config
25+
function plugin_read_list() {
26+
prefix_read_list "BUILDKITE_PLUGIN_${PLUGIN_PREFIX}_${1}"
27+
}
28+
29+
30+
# Reads either a value or a list from plugin config into a global result array
31+
# Returns success if values were read
32+
function prefix_read_list_into_result() {
33+
local prefix="$1"
34+
local parameter="${prefix}_0"
35+
result=()
36+
37+
if [ -n "${!parameter:-}" ]; then
38+
local i=0
39+
local parameter="${prefix}_${i}"
40+
while [ -n "${!parameter:-}" ]; do
41+
result+=("${!parameter}")
42+
i=$((i+1))
43+
parameter="${prefix}_${i}"
44+
done
45+
elif [ -n "${!prefix:-}" ]; then
46+
result+=("${!prefix}")
47+
fi
48+
49+
[ ${#result[@]} -gt 0 ] || return 1
50+
}
51+
52+
# Reads either a value or a list from plugin config
53+
function plugin_read_list_into_result() {
54+
prefix_read_list_into_result "BUILDKITE_PLUGIN_${PLUGIN_PREFIX}_${1}"
55+
}

renovate.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"extends": [
3-
"config:base"
3+
"config:base",
4+
":disableDependencyDashboard"
45
]
56
}

0 commit comments

Comments
 (0)