// Update an existing Pool Stack func stackUpdatePool(c *cli.Context) { ensureEnvArg(c) ensurePoolArg(c) if c.String("region") != "" { stack.Region = c.String("region") } poolName := utils.GalaxyPool(c) baseStack := getBase(c) poolEnv := utils.GalaxyEnv(c) stackName := fmt.Sprintf("%s-%s-%s", baseStack, poolEnv, poolName) pool, err := stack.GetPool(stackName) if err != nil { log.Fatal(err) } options := make(map[string]string) if policy := c.String("policy"); policy != "" { policyJSON, err := jsonFromArg(policy) if err != nil { log.Fatal("policy error:", err) } options["StackPolicyDuringUpdateBody"] = string(policyJSON) } resources := sharedResources(c, baseStack) asg := pool.ASG() if asg == nil { log.Fatal("missing ASG") } if c.Int("desired-size") > 0 { asg.Properties.DesiredCapacity = c.Int("desired-size") } if c.Int("min-size") > 0 { asg.Properties.MinSize = c.Int("min-size") } if c.Int("max-size") > 0 { asg.Properties.MaxSize = c.Int("max-size") } if c.Bool("auto-update") { // note that the max pause is only PT5M30S asg.SetASGUpdatePolicy(c.Int("update-min"), c.Int("update-batch"), c.Duration("update-pause")) } numZones := c.Int("availability-zones") if numZones == 0 { numZones = len(asg.Properties.VPCZoneIdentifier) } // start with the current settings subnetIDs := []string{} azIDs := []string{} // only update the subnets/AZs if we changed the count if len(asg.Properties.VPCZoneIdentifier) != numZones { subnets := resources.Subnets if numZones <= len(subnets) { subnets = subnets[:numZones] } else { log.Fatal("ERROR: cannot run in %d zones, only %d available.", numZones, len(subnets)) } for _, sn := range subnets { subnetIDs = append(subnetIDs, sn.ID) azIDs = append(azIDs, sn.AvailabilityZone) } asg.Properties.VPCZoneIdentifier = subnetIDs asg.Properties.AvailabilityZones = azIDs } elb := pool.ELB() sslCert := "" if cert := c.String("ssl-cert"); cert != "" { sslCert = resources.ServerCerts[cert] if sslCert == "" { log.Fatalf("Could not find certificate '%s'", cert) } } httpPort := c.Int("http-port") if (sslCert != "" || httpPort > 0) && elb == nil { log.Fatal("ERROR: Pool does not have an ELB") } // we can set the default now that we've verified that elb can be nil if httpPort == 0 { httpPort = 80 } if elb != nil { certAdded := false for _, l := range elb.Properties.Listeners { if sslCert != "" && l.Protocol == "HTTPS" { l.SSLCertificateId = sslCert certAdded = true } if httpPort > 0 { l.InstancePort = httpPort } } // the elb needs a cert, but doesn't have an https listener if sslCert != "" && !certAdded { elb.AddListener(443, "HTTPS", httpPort, "HTTP", sslCert, nil) } healthCheck := c.String("http-health-check") if healthCheck != "" && healthCheck != elb.Properties.HealthCheck.Target { elb.Properties.HealthCheck.Target = healthCheck } // always make sure the ELB is in the same subnets as the ASG elb.Properties.Subnets = asg.Properties.VPCZoneIdentifier } lc := pool.LC() if amiID := c.String("ami"); amiID != "" { lc.Properties.ImageId = amiID } if insType := c.String("instance-type"); insType != "" { lc.Properties.InstanceType = insType } // add autoscaling if it's required setCPUAutoScale(c, pool) poolTmpl, err := json.MarshalIndent(pool, "", " ") if err != nil { log.Fatal(err) } if c.Bool("print") { fmt.Println(string(poolTmpl)) return } log.Println("Updating stack:", stackName) if _, err := stack.Update(stackName, poolTmpl, options); err != nil { log.Fatal(err) } // do we want to wait on this by default? if err := stack.Wait(stackName, 5*time.Minute); err != nil { log.Fatal(err) } log.Println("UpdateStack complete") }
// update the base stack func stackUpdate(c *cli.Context) { var stackTmpl []byte var err error stackName := c.Args().First() if stackName == "" { log.Fatal("ERROR: stack name required") } if c.String("region") != "" { stack.Region = c.String("region") } params := make(map[string]string) if p := c.String("parameters"); p != "" { paramJSON, err := jsonFromArg(p) if err != nil { log.Fatal("ERROR: decoding parameters:", err) } err = json.Unmarshal(paramJSON, ¶ms) if err != nil { log.Fatal(err) } } template := c.String("template") if template != "" { stackTmpl, err = jsonFromArg(template) if err != nil { log.Fatalf("ERROR: %s", err) } } if policy := c.String("policy"); policy != "" { policyJSON, err := jsonFromArg(policy) if err != nil { log.Fatal("policy error:", err) } params["StackPolicyDuringUpdateBody"] = string(policyJSON) } if len(stackTmpl) == 0 { // get the current running template stackTmpl, err = stack.GetTemplate(stackName) if err != nil { log.Fatal(err) } } // this reads the Parameters supplied for our current stack for us shared := sharedResources(c, stackName) // add any missing parameters to our for key, val := range shared.Parameters { if params[key] == "" { params[key] = val } } p, _ := json.MarshalIndent(params, "", " ") ok := promptValue(fmt.Sprintf("\nUpdate the [%s] stack with:\n%s\nAccept?", stackName, string(p)), "n") switch strings.ToLower(ok) { case "y", "yes": _, err = stack.Update(stackName, stackTmpl, params) if err != nil { log.Fatal(err) } log.Println("Updating stack:", stackName) default: log.Fatal("aborted") } }