-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathprovision-aws-cluster.sh
More file actions
executable file
·185 lines (158 loc) · 6.28 KB
/
provision-aws-cluster.sh
File metadata and controls
executable file
·185 lines (158 loc) · 6.28 KB
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
#!/usr/bin/env bash
#
# Usage: ./provision-aws-cluster.sh [name]
# The [name] is the CloudFormation stack name, and defaults to 'deis'
if [ -z "$1" ]
then
STACK_NAME=deis
else
STACK_NAME=$1
fi
set -e
THIS_DIR=$(cd $(dirname $0); pwd) # absolute path
CONTRIB_DIR=$(dirname $THIS_DIR)
source $CONTRIB_DIR/utils.sh
# check for AWS API tools in $PATH
if ! which aws > /dev/null; then
echo_red 'Please install the AWS command-line tool and ensure it is in your $PATH.'
exit 1
fi
if [ ! -z "$AWS_CLI_PROFILE" ]; then
EXTRA_AWS_CLI_ARGS+="--profile $AWS_CLI_PROFILE"
fi
if [ -z "$DEIS_NUM_INSTANCES" ]; then
DEIS_NUM_INSTANCES=3
fi
# make sure we have all VPC info
if [ -n "$VPC_ID" ]; then
if [ -z "$VPC_SUBNETS" ] || [ -z "$VPC_ZONES" ]; then
echo_red 'To provision Deis in a VPC, you must also specify VPC_SUBNETS and VPC_ZONES.'
exit 1
fi
fi
# check that the CoreOS user-data file is valid
$CONTRIB_DIR/util/check-user-data.sh
# Prepare bailout function to prevent us polluting the namespace
bailout() {
aws cloudformation delete-stack --stack-name $STACK_NAME
}
# create an AWS cloudformation stack based on CoreOS's default template
aws cloudformation create-stack \
--template-body "$($THIS_DIR/gen-json.py --channel $COREOS_CHANNEL --version $COREOS_VERSION)" \
--stack-name $STACK_NAME \
--parameters "$(<$THIS_DIR/cloudformation.json)" \
$EXTRA_AWS_CLI_ARGS
# loop until the instances are created
ATTEMPTS=60
SLEEPTIME=10
COUNTER=1
INSTANCE_IDS=""
until [ $(wc -w <<< $INSTANCE_IDS) -eq $DEIS_NUM_INSTANCES -a "$STACK_STATUS" = "CREATE_COMPLETE" ]; do
if [ $COUNTER -gt $ATTEMPTS ]; then
echo "Provisioning instances failed (timeout, $(wc -w <<< $INSTANCE_IDS) of $DEIS_NUM_INSTANCES provisioned after 10m)"
echo "Destroying stack $STACK_NAME"
bailout
exit 1
fi
STACK_STATUS=$(aws --output text cloudformation describe-stacks --stack-name $STACK_NAME --query 'Stacks[].StackStatus' $EXTRA_AWS_CLI_ARGS)
if [ $STACK_STATUS != "CREATE_IN_PROGRESS" -a $STACK_STATUS != "CREATE_COMPLETE" ] ; then
echo "error creating stack: "
aws --output text cloudformation describe-stack-events \
--stack-name $STACK_NAME \
--query 'StackEvents[?ResourceStatus==`CREATE_FAILED`].[LogicalResourceId,ResourceStatusReason]' \
$EXTRA_AWS_CLI_ARGS
bailout
exit 1
fi
INSTANCE_IDS=$(aws ec2 describe-instances \
--filters Name=tag:aws:cloudformation:stack-name,Values=$STACK_NAME Name=instance-state-name,Values=running \
--query 'Reservations[].Instances[].[ InstanceId ]' \
--output text \
$EXTRA_AWS_CLI_ARGS)
echo "Waiting for instances to be provisioned ($STACK_STATUS, $(expr 61 - $COUNTER)0s) ..."
sleep $SLEEPTIME
let COUNTER=COUNTER+1
done
# loop until the instances pass health checks
COUNTER=1
INSTANCE_STATUSES=""
until [ `wc -w <<< $INSTANCE_STATUSES` -eq $DEIS_NUM_INSTANCES ]; do
if [ $COUNTER -gt $ATTEMPTS ];
then echo "Health checks not passed after 10m, giving up"
echo "Destroying stack $STACK_NAME"
bailout
exit 1
fi
if [ $COUNTER -ne 1 ]; then sleep $SLEEPTIME; fi
echo "Waiting for instances to pass initial health checks ($(expr 61 - $COUNTER)0s) ..."
INSTANCE_STATUSES=$(aws ec2 describe-instance-status \
--filters Name=instance-status.reachability,Values=passed \
--instance-ids $INSTANCE_IDS \
--query 'InstanceStatuses[].[ InstanceId ]' \
--output text \
$EXTRA_AWS_CLI_ARGS)
let COUNTER=COUNTER+1
done
# print instance info
echo "Instances are available:"
aws ec2 describe-instances \
--filters Name=tag:aws:cloudformation:stack-name,Values=$STACK_NAME Name=instance-state-name,Values=running \
--query 'Reservations[].Instances[].[InstanceId,PublicIpAddress,InstanceType,Placement.AvailabilityZone,State.Name]' \
--output text \
$EXTRA_AWS_CLI_ARGS
# get ELB public DNS name through cloudformation
# TODO: is "first output value" going to be reliable enough?
export ELB_DNS_NAME=$(aws cloudformation describe-stacks \
--stack-name $STACK_NAME \
--max-items 1 \
--query 'Stacks[].[ Outputs[0].[ OutputValue ] ]' \
--output=text \
$EXTRA_AWS_CLI_ARGS)
# get ELB friendly name through aws elb
ELB_NAME=$(aws elb describe-load-balancers \
--query 'LoadBalancerDescriptions[].[ DNSName,LoadBalancerName ]' \
--output=text \
$EXTRA_AWS_CLI_ARGS | grep -F $ELB_DNS_NAME | head -n1 | cut -f2)
echo "Using ELB $ELB_NAME at $ELB_DNS_NAME"
# Instance launched into a VPC may not have a PublicIPAddress
for ip_type in PublicIpAddress PrivateIpAddress; do
FIRST_INSTANCE=$(aws ec2 describe-instances \
--filters Name=tag:aws:cloudformation:stack-name,Values=$STACK_NAME Name=instance-state-name,Values=running \
--query "Reservations[].Instances[].[$ip_type]" \
--output text \
$EXTRA_AWS_CLI_ARGS | head -1)
if [[ ! $FIRST_INSTANCE == "None" ]]; then
break
fi
done
if [[ $FIRST_INSTANCE == "None" ]]; then
echo_red "The IP of any of your instances could not be found."
echo_red "Ensure that the cloudformation stack was created successfully."
exit 1
fi
export DEISCTL_TUNNEL=$FIRST_INSTANCE
# loop until etcd2 / fleet are up and running
COUNTER=1
until deisctl list >/dev/null; do
if [ $COUNTER -gt $ATTEMPTS ]; then
echo_red "Timed out waiting for fleet, giving up"
echo_red "Ensure that the private key in cloudformation.json"
echo_red "is added to your ssh-agent."
break
fi
echo "Waiting until fleet is up and running ..."
sleep 5
let COUNTER=COUNTER+1
done
echo_green "Enabling proxy protocol"
if ! deisctl config router set proxyProtocol=1; then
echo_red "# WARNING: Enabling proxy protocol failed."
echo_red "# Ensure that the private key in cloudformation.json is added to"
echo_red "# your ssh-agent, then enable proxy protocol before continuing:"
echo_red "#"
echo_red "# deisctl config router set proxyProtocol=1\n"
fi
echo_green "Your Deis cluster was deployed to AWS CloudFormation as stack "$STACK_NAME".\n"
echo_green "Now run this command in your shell:"
echo_green "export DEISCTL_TUNNEL=$FIRST_INSTANCE"
echo_green "and continue to follow the documentation for \"Installing the Deis Platform.\""