예제 #1
0
파일: stacks.go 프로젝트: zombor/galaxy
// create our base stack
func stackInit(c *cli.Context) {
	stackName := c.Args().First()
	if stackName == "" {
		log.Fatal("ERROR: stack name required")
	}

	if c.String("region") != "" {
		stack.Region = c.String("region")
	}

	exists, err := stack.Exists(stackName)
	if exists {
		log.Fatalf("ERROR: stack %s already exists", stackName)
	} else if err != nil {
		fmt.Println("EXISTS ERROR")
		log.Fatal(err)
	}

	params := getInitOpts(c)
	stackTmpl, err := stack.GalaxyTemplate(params)
	if err != nil {
		log.Fatalf("ERROR: %s", err)
	}

	if c.Bool("print") {
		fmt.Println(string(stackTmpl))
		return
	}

	opts := make(map[string]string)
	opts["tag.galaxy"] = "base"

	_, err = stack.Create(stackName, stackTmpl, opts)
	if err != nil {
		log.Fatalf("ERROR: %s", err)
	}
	log.Println("Initializing stack", stackName)
}
예제 #2
0
파일: stacks.go 프로젝트: zombor/galaxy
func stackCreatePool(c *cli.Context) {
	var err error
	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 := stack.NewPool()

	// get the resources we need from the base stack
	// TODO: this may search for the base stack a second time
	resources := sharedResources(c, baseStack)

	desiredCap := c.Int("desired-size")
	if desiredCap == 0 {
		desiredCap = 1
	}

	numZones := c.Int("availability-zones")
	if numZones == 0 {
		// default to running one host per zone
		numZones = desiredCap
	}

	minSize := c.Int("min-size")
	maxSize := c.Int("max-size")
	httpPort := c.Int("http-port")
	if httpPort == 0 {
		httpPort = 80
	}

	sslCert := ""
	if cert := c.String("ssl-cert"); cert != "" {
		sslCert = resources.ServerCerts[cert]
		if sslCert == "" {
			log.Fatalf("Could not find certificate '%s'", cert)
		}
	}

	// Create our Launch Config
	lc := pool.LCTemplate
	lcName := "lc" + poolEnv + poolName

	if amiID := c.String("ami"); amiID != "" {
		lc.Properties.ImageId = amiID
	} else {
		lc.Properties.ImageId = resources.Parameters["PoolImageId"]
	}

	if insType := c.String("instance-type"); insType != "" {
		lc.Properties.InstanceType = insType
	} else {
		lc.Properties.InstanceType = resources.Parameters["PoolInstanceType"]
	}

	if keyName := c.String("keyname"); keyName != "" {
		lc.Properties.KeyName = keyName
	} else {
		lc.Properties.KeyName = resources.Parameters["KeyName"]
	}

	lc.Properties.IamInstanceProfile = resources.Roles["galaxyInstanceProfile"]

	lc.Properties.SecurityGroups = []string{
		resources.SecurityGroups["sshSG"],
		resources.SecurityGroups["defaultSG"],
	}

	lc.SetVolumeSize(c.Int("volume-size"))

	pool.Resources[lcName] = lc

	// Create the Auto Scaling Group
	asg := pool.ASGTemplate
	asgName := "asg" + poolEnv + poolName

	asg.AddTag("Name", fmt.Sprintf("%s-%s-%s", baseStack, poolEnv, poolName), true)
	asg.AddTag("env", poolEnv, true)
	asg.AddTag("pool", poolName, true)
	asg.AddTag("galaxy", "pool", true)

	asg.Properties.DesiredCapacity = desiredCap

	// Don't always run in all zones
	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))
	}

	// break the subnets info into separate subnet and AZ slices for the template
	subnetIDs := []string{}
	azIDs := []string{}
	for _, sn := range subnets {
		subnetIDs = append(subnetIDs, sn.ID)
		azIDs = append(azIDs, sn.AvailabilityZone)
	}

	asg.SetLaunchConfiguration(lcName)
	asg.Properties.AvailabilityZones = azIDs
	asg.Properties.VPCZoneIdentifier = subnetIDs
	if maxSize > 0 {
		asg.Properties.MaxSize = maxSize
	}
	if minSize > 0 {
		asg.Properties.MinSize = minSize
	}

	if c.Bool("auto-update") {
		asg.SetASGUpdatePolicy(c.Int("update-min"), c.Int("update-batch"), c.Duration("update-pause"))
	}

	pool.Resources[asgName] = asg

	// Optionally create the Elastic Load Balancer
	if c.Bool("elb") {
		elb := pool.ELBTemplate
		elbName := "elb" + poolEnv + poolName

		// make sure to add this to the ASG
		asg.AddLoadBalancer(elbName)

		elb.Properties.Subnets = subnetIDs

		elb.Properties.SecurityGroups = []string{
			resources.SecurityGroups["webSG"],
			resources.SecurityGroups["defaultSG"],
		}

		elb.Properties.HealthCheck.Target = c.String("http-health-check")

		elb.AddListener(80, "HTTP", httpPort, "HTTP", "", nil)

		if sslCert != "" {
			elb.AddListener(443, "HTTPS", httpPort, "HTTP", sslCert, nil)
		}

		pool.Resources[elbName] = elb
	}

	// 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
	}

	opts := make(map[string]string)
	opts["tag.env"] = poolEnv
	opts["tag.pool"] = poolName
	opts["tag.galaxy"] = "pool"

	_, err = stack.Create(stackName, poolTmpl, opts)
	if err != nil {
		log.Fatal(err)
	}

	log.Println("Creating stack:", stackName)

	// do we want to wait on this by default?
	if err := stack.Wait(stackName, 5*time.Minute); err != nil {
		log.Error(err)
		log.Error("CreateStack Failed, attempting to delete")

		waitAndDelete(stackName)
		return
	}

	log.Println("CreateStack complete")
}