-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathecs-cf-deploy
executable file
·242 lines (205 loc) · 7.2 KB
/
ecs-cf-deploy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#!/bin/sh
VERSION="0.1.0"
VERBOSE=false
AWS_CLI=$(which aws)
AWS_ECS="$AWS_CLI --output json ecs"
AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:-eu-west-1}
AWS_ASSUME_ROLE=true
function usage() {
cat <<EOM
-- ecs-cf-deploy --
Simple script to force a deployement of an ECS service based on a clouformation stack.
Required arguments:
-c | --cluster-name Name of cloudformation stack containing the ecs cluster to deploy
-s | --service-name Name of cloudformation stack containing the service to deploy
-a | --account ID of the account to assume the role
-ar | --assume-role-name Name of the role to assume
Optional arguments:
-k | --aws-access-key AWS Access Key ID. May also be set as environment variable AWS_ACCESS_KEY_ID
-s | --aws-secret-key AWS Secret Access Key. May also be set as environment variable AWS_SECRET_ACCESS_KEY
-r | --region AWS Region Name. May also be set as environment variable AWS_DEFAULT_REGION or use the default eu-west-1
-v | --verbose Display debugging information (basically each command)
Requirements:
aws: AWS Command Line Interface
jq: Command-line JSON processor
Example:
ecs-cf-deploy -s example-api -c example-cluster -a 1234465780 -ar assumeRoleName -r us-west-1
Author:
Nicolas Ritouet <[email protected]>
License:
MIT (check LICENSE.md)
EOM
exit 3
}
# Check requirements
function require() {
command -v "$1" > /dev/null 2>&1 || {
echo "Some of the required software is not installed:"
echo " please install $1" >&2;
exit 4;
}
}
function assumeRole() {
temp_role=$($AWS_CLI sts assume-role --role-arn "arn:aws:iam::${ACCOUNT_ID}:role/${CROSS_ACCOUNT_ROLE}" --role-session-name "$(date +"%s")")
export AWS_ACCESS_KEY_ID=$(echo $temp_role | jq .Credentials.AccessKeyId | xargs)
export AWS_SECRET_ACCESS_KEY=$(echo $temp_role | jq .Credentials.SecretAccessKey | xargs)
export AWS_SESSION_TOKEN=$(echo $temp_role | jq .Credentials.SessionToken | xargs)
}
function assumeRoleClean() {
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN
}
function getClusterName() {
export ECS_CLUSTER_NAME=$($AWS_CLI cloudformation describe-stacks \
--stack-name ${ECS_CLUSTER_STACK} \
--query 'Stacks[0].Outputs[?OutputKey==`Cluster`].OutputValue' \
--output text --region ${AWS_DEFAULT_REGION}
)
if [ -z $ECS_CLUSTER_NAME ]; then
echo "Could not find the service under the '$ECS_CLUSTER_STACK' stack"
exit 9
fi
}
function getServiceName() {
export ECS_SERVICE_NAME=$($AWS_CLI cloudformation describe-stacks \
--stack-name ${ECS_SERVICE_STACK} \
--query 'Stacks[0].Outputs[?OutputKey==`Service`].OutputValue' \
--output text --region ${AWS_DEFAULT_REGION}
)
if [ $ECS_SERVICE_NAME == $ECS_CLUSTER_NAME ]; then
echo "Long ARN bug found: using ServiceArn output to get Service name";
temp_servicename=$($AWS_CLI cloudformation describe-stacks \
--stack-name ${ECS_SERVICE_STACK} \
--query 'Stacks[0].Outputs[?OutputKey==`Service`].OutputValue' \
--output text --region ${AWS_DEFAULT_REGION}
)
echo $ECS_SERVICE_STACK
echo $temp_servicename
echo $ECS_SERVICE_NAME
export ECS_SERVICE_NAME=${temp_servicename##*/}
fi
if [ -z $ECS_SERVICE_NAME ]; then
echo "Could not find the service under the '$ECS_SERVICE_STACK' stack"
exit 10
fi
}
function updateService() {
if [ $VERBOSE == true ]; then
echo "Deploying on cluster '$ECS_CLUSTER_NAME' service '$ECS_SERVICE_NAME'";
fi
$AWS_ECS update-service --cluster $ECS_CLUSTER_NAME --service $ECS_SERVICE_NAME --force-new-deployment
}
# Check that all required variables/combinations are set
function assertRequiredArgumentsSet() {
# AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION and AWS_PROFILE can be set as environment variables
if [ -z ${AWS_ACCESS_KEY_ID+x} ]; then unset AWS_ACCESS_KEY_ID; fi
if [ -z ${AWS_SECRET_ACCESS_KEY+x} ]; then unset AWS_SECRET_ACCESS_KEY; fi
if [ -z ${AWS_DEFAULT_REGION+x} ];
then unset AWS_DEFAULT_REGION
else
AWS_ECS="$AWS_ECS --region $AWS_DEFAULT_REGION"
fi
if [ -z ${AWS_PROFILE+x} ];
then unset AWS_PROFILE
else
AWS_ECS="$AWS_ECS --profile $AWS_PROFILE"
fi
if [ -z "${ECS_SERVICE_STACK:-}" ]; then
echo "SERVICE is required. You can pass the value using -s or --service-name"
exit 5
fi
if [ ! -z "${ECS_SERVICE_STACK:-}" ] && [ -z "${ECS_CLUSTER_STACK:-}" ]; then
echo "CLUSTER is required. You can pass the value using -c or --cluster"
exit 6
fi
if [ -z "${ACCOUNT_ID:-}" ]; then
echo "ACCOUNT is required. You can pass the value using -a or --account"
exit 7
fi
if [ -z "${CROSS_ACCOUNT_ROLE:-}" ]; then
echo "ROLE_NAME is required. You can pass the value using -ar or --assume-role-name"
exit 8
fi
}
######################################################
# When not being tested, run application as expected #
######################################################
if [ -z "$TEST_ENV" ]; then
set -o errexit
set -o pipefail
set -u
set -e
# If no args are provided, display usage information
if [ $# == 0 ]; then usage; fi
# Check for AWS, AWS Command Line Interface
require aws
# Check for jq, Command-line JSON processor
require jq
# Loop through arguments, two at a time for key and value
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-c|--cluster-name)
ECS_CLUSTER_STACK="$2"
shift # past argument
;;
-s|--service-name)
ECS_SERVICE_STACK="$2"
shift # past argument
;;
-ar|--assume-role-name)
CROSS_ACCOUNT_ROLE="$2"
shift # past argument
;;
-a|--account)
ACCOUNT_ID="$2"
shift # past argument
;;
-k|--aws-access-key)
AWS_ACCESS_KEY_ID="$2"
shift # past argument
;;
-s|--aws-secret-key)
AWS_SECRET_ACCESS_KEY="$2"
shift # past argument
;;
-r|--region)
AWS_DEFAULT_REGION="$2"
shift # past argument
;;
-v|--verbose)
VERBOSE=true
;;
--version)
echo ${VERSION}
exit 0
;;
*)
echo "Found nothing, will display usage and exit"
usage
exit 2
;;
esac
shift # past argument or value
done
if [ $VERBOSE == true ]; then
set -x
fi
# Check that required arguments are provided
assertRequiredArgumentsSet
if [[ "$AWS_ASSUME_ROLE" != false ]]; then
assumeRole
fi
getClusterName
getServiceName
updateService
if [[ "$AWS_ASSUME_ROLE" != false ]]; then
assumeRoleClean
fi
exit 0
fi
#############################
# End application run logic #
#############################