github.com/naphatkrit/deis@v1.12.3/contrib/aws/provision-aws-cluster.sh (about) 1 #!/usr/bin/env bash 2 # 3 # Usage: ./provision-aws-cluster.sh [name] 4 # The [name] is the CloudFormation stack name, and defaults to 'deis' 5 6 if [ -z "$1" ] 7 then 8 STACK_NAME=deis 9 else 10 STACK_NAME=$1 11 fi 12 13 set -e 14 15 THIS_DIR=$(cd $(dirname $0); pwd) # absolute path 16 CONTRIB_DIR=$(dirname $THIS_DIR) 17 18 source $CONTRIB_DIR/utils.sh 19 20 # check for AWS API tools in $PATH 21 if ! which aws > /dev/null; then 22 echo_red 'Please install the AWS command-line tool and ensure it is in your $PATH.' 23 exit 1 24 fi 25 26 if [ ! -z "$AWS_CLI_PROFILE" ]; then 27 EXTRA_AWS_CLI_ARGS+="--profile $AWS_CLI_PROFILE" 28 fi 29 30 if [ -z "$DEIS_NUM_INSTANCES" ]; then 31 DEIS_NUM_INSTANCES=3 32 fi 33 34 # make sure we have all VPC info 35 if [ -n "$VPC_ID" ]; then 36 if [ -z "$VPC_SUBNETS" ] || [ -z "$VPC_ZONES" ]; then 37 echo_red 'To provision Deis in a VPC, you must also specify VPC_SUBNETS and VPC_ZONES.' 38 exit 1 39 fi 40 fi 41 42 # check that the CoreOS user-data file is valid 43 $CONTRIB_DIR/util/check-user-data.sh 44 45 # Prepare bailout function to prevent us polluting the namespace 46 bailout() { 47 aws cloudformation delete-stack --stack-name $STACK_NAME 48 } 49 50 # create an AWS cloudformation stack based on CoreOS's default template 51 aws cloudformation create-stack \ 52 --template-body "$($THIS_DIR/gen-json.py --channel $COREOS_CHANNEL --version $COREOS_VERSION)" \ 53 --stack-name $STACK_NAME \ 54 --parameters "$(<$THIS_DIR/cloudformation.json)" \ 55 --stack-policy-body "$(<$THIS_DIR/stack_policy.json)" \ 56 $EXTRA_AWS_CLI_ARGS 57 58 # loop until the instances are created 59 ATTEMPTS=60 60 SLEEPTIME=10 61 COUNTER=1 62 INSTANCE_IDS="" 63 until [ $(wc -w <<< $INSTANCE_IDS) -eq $DEIS_NUM_INSTANCES -a "$STACK_STATUS" = "CREATE_COMPLETE" ]; do 64 if [ $COUNTER -gt $ATTEMPTS ]; then 65 echo "Provisioning instances failed (timeout, $(wc -w <<< $INSTANCE_IDS) of $DEIS_NUM_INSTANCES provisioned after 10m)" 66 echo "Destroying stack $STACK_NAME" 67 bailout 68 exit 1 69 fi 70 71 STACK_STATUS=$(aws --output text cloudformation describe-stacks --stack-name $STACK_NAME --query 'Stacks[].StackStatus' $EXTRA_AWS_CLI_ARGS) 72 if [ $STACK_STATUS != "CREATE_IN_PROGRESS" -a $STACK_STATUS != "CREATE_COMPLETE" ] ; then 73 echo "error creating stack: " 74 aws --output text cloudformation describe-stack-events \ 75 --stack-name $STACK_NAME \ 76 --query 'StackEvents[?ResourceStatus==`CREATE_FAILED`].[LogicalResourceId,ResourceStatusReason]' \ 77 $EXTRA_AWS_CLI_ARGS 78 bailout 79 exit 1 80 fi 81 82 INSTANCE_IDS=$(aws ec2 describe-instances \ 83 --filters Name=tag:aws:cloudformation:stack-name,Values=$STACK_NAME Name=instance-state-name,Values=running \ 84 --query 'Reservations[].Instances[].[ InstanceId ]' \ 85 --output text \ 86 $EXTRA_AWS_CLI_ARGS) 87 88 echo "Waiting for instances to be provisioned ($STACK_STATUS, $(expr 61 - $COUNTER)0s) ..." 89 sleep $SLEEPTIME 90 91 let COUNTER=COUNTER+1 92 done 93 94 # loop until the instances pass health checks 95 COUNTER=1 96 INSTANCE_STATUSES="" 97 until [ `wc -w <<< $INSTANCE_STATUSES` -eq $DEIS_NUM_INSTANCES ]; do 98 if [ $COUNTER -gt $ATTEMPTS ]; 99 then echo "Health checks not passed after 10m, giving up" 100 echo "Destroying stack $STACK_NAME" 101 bailout 102 exit 1 103 fi 104 105 if [ $COUNTER -ne 1 ]; then sleep $SLEEPTIME; fi 106 echo "Waiting for instances to pass initial health checks ($(expr 61 - $COUNTER)0s) ..." 107 INSTANCE_STATUSES=$(aws ec2 describe-instance-status \ 108 --filters Name=instance-status.reachability,Values=passed \ 109 --instance-ids $INSTANCE_IDS \ 110 --query 'InstanceStatuses[].[ InstanceId ]' \ 111 --output text \ 112 $EXTRA_AWS_CLI_ARGS) 113 let COUNTER=COUNTER+1 114 done 115 116 # print instance info 117 echo "Instances are available:" 118 aws ec2 describe-instances \ 119 --filters Name=tag:aws:cloudformation:stack-name,Values=$STACK_NAME Name=instance-state-name,Values=running \ 120 --query 'Reservations[].Instances[].[InstanceId,PublicIpAddress,InstanceType,Placement.AvailabilityZone,State.Name]' \ 121 --output text \ 122 $EXTRA_AWS_CLI_ARGS 123 124 # get ELB public DNS name through cloudformation 125 export ELB_DNS_NAME=$(aws cloudformation describe-stacks \ 126 --stack-name $STACK_NAME \ 127 --max-items 1 \ 128 --query 'Stacks[].[ Outputs[?OutputKey==`DNSName`].OutputValue ]' \ 129 --output=text \ 130 $EXTRA_AWS_CLI_ARGS) 131 132 # get ELB friendly name through aws elb 133 ELB_NAME=$(aws elb describe-load-balancers \ 134 --query "LoadBalancerDescriptions[?DNSName=='$ELB_DNS_NAME'].[ LoadBalancerName ]" \ 135 --output=text \ 136 $EXTRA_AWS_CLI_ARGS) 137 echo "Using ELB $ELB_NAME at $ELB_DNS_NAME" 138 139 # Instance launched into a VPC may not have a PublicIPAddress 140 for ip_type in PublicIpAddress PrivateIpAddress; do 141 FIRST_INSTANCE=$(aws ec2 describe-instances \ 142 --filters Name=tag:aws:cloudformation:stack-name,Values=$STACK_NAME Name=instance-state-name,Values=running \ 143 --query "Reservations[].Instances[].[$ip_type][0]" \ 144 --output text \ 145 $EXTRA_AWS_CLI_ARGS) 146 if [[ ! $FIRST_INSTANCE == "None" ]]; then 147 break 148 fi 149 done 150 151 if [[ $FIRST_INSTANCE == "None" ]]; then 152 echo_red "The IP of any of your instances could not be found." 153 echo_red "Ensure that the cloudformation stack was created successfully." 154 exit 1 155 fi 156 157 export DEISCTL_TUNNEL=$FIRST_INSTANCE 158 159 # loop until etcd2 / fleet are up and running 160 COUNTER=1 161 until deisctl list >/dev/null; do 162 if [ $COUNTER -gt $ATTEMPTS ]; then 163 echo_red "Timed out waiting for fleet, giving up" 164 echo_red "Ensure that the private key in cloudformation.json" 165 echo_red "is added to your ssh-agent." 166 break 167 fi 168 echo "Waiting until fleet is up and running ..." 169 sleep 5 170 let COUNTER=COUNTER+1 171 done 172 173 echo_green "Enabling proxy protocol" 174 if ! deisctl config router set proxyProtocol=1; then 175 echo_red "# WARNING: Enabling proxy protocol failed." 176 echo_red "# Ensure that the private key in cloudformation.json is added to" 177 echo_red "# your ssh-agent, then enable proxy protocol before continuing:" 178 echo_red "#" 179 echo_red "# deisctl config router set proxyProtocol=1\n" 180 fi 181 182 echo_green "Your Deis cluster was deployed to AWS CloudFormation as stack "$STACK_NAME".\n" 183 echo_green "Now run this command in your shell:" 184 echo_green "export DEISCTL_TUNNEL=$FIRST_INSTANCE" 185 echo_green "and continue to follow the documentation for \"Installing the Deis Platform.\""