Exemple #1
0
func (r *Run) runCreate(client *cf.CloudFormation, d tacks.Document, stack string) error {

	e := d.Environment

	tacks.Logger().Infof("Creating stack %s", e.StackName)

	var (
		capabilities     []*string
		onFailure        = "DO_NOTHING"
		tags             []*cf.Tag
		timeoutInMinutes uint8 = 15
	)

	if d.IsIamCapabilitiesRequired() {
		capabilities = append(capabilities, aws.String("CAPABILITY_IAM"))
	}

	if e.DeleteOnFailure {
		onFailure = "DELETE"
	}

	if e.Timeout > 0 {
		timeoutInMinutes = e.Timeout
	}

	for key, value := range e.Tags {
		tags = append(tags, &cf.Tag{
			Key:   aws.String(key),
			Value: aws.String(value),
		})
	}

	_, err := client.CreateStack(&cf.CreateStackInput{
		Capabilities:     capabilities,
		OnFailure:        aws.String(onFailure),
		StackName:        aws.String(e.StackName),
		Tags:             tags,
		TemplateBody:     aws.String(stack),
		TimeoutInMinutes: aws.Long(int64(timeoutInMinutes)),
	})

	return err

}
Exemple #2
0
func (r *Run) runUpdate(client *cf.CloudFormation, d tacks.Document, stack string) error {

	e := d.Environment

	tacks.Logger().Infof("Updating stack %s", e.StackName)

	var (
		capabilities []*string
	)

	if d.IsIamCapabilitiesRequired() {
		capabilities = append(capabilities, aws.String("CAPABILITY_IAM"))
	}

	_, err := client.UpdateStack(&cf.UpdateStackInput{
		Capabilities: capabilities,
		StackName:    aws.String(e.StackName),
		TemplateBody: aws.String(stack),
	})

	return err

}
Exemple #3
0
func (w *Watch) Run() error {

	const null = ""

	if w.Stackname == null {
		return errors.New("no stack name given")
	}

	tacks.Logger().Infof("Watching stack %s", w.Stackname)

	if w.Refresh == 0 {
		w.Refresh = DefaultRefresh
	}

	name := aws.String(w.Stackname)

	client := cf.New(&aws.Config{
		Region: w.Region,
	})

	for {

		width, height, err := term.Size()

		if err != nil {
			return err
		}

		resp, err := client.DescribeStackEvents(&cf.DescribeStackEventsInput{
			StackName: name,
		})

		if err != nil {
			return err
		}

		tw := table.NewWriter(os.Stdout)
		tw.SetColWidth(width / 4)
		tw.SetColumnSeparator(" ")

		tw.SetHeader([]string{
			"Timestamp",
			"ID Logical",
			"ID Physical",
			"Status",
			"Reason",
		})

		var max = height / 2

		if l := len(resp.StackEvents); max > l {
			max = l
		}

		for _, e := range resp.StackEvents[0:max] {

			var reason string

			if r := e.ResourceStatusReason; r != nil {
				reason = strings.Replace(*r, "\n", " ", -1)
			}

			timestamp := humanize.Time(*e.Timestamp)

			data := []string{
				timestamp,
				*e.LogicalResourceID,
				*e.ResourceType,
				term.CloudFormation.Colorize(*e.ResourceStatus),
				reason,
			}

			tw.Append(data)
			fmt.Print("\033[H\033[2J")
			tw.Render()

		}

		time.Sleep(w.Refresh)

	}

}
Exemple #4
0
func main() {

	var logger = tacks.Logger()
	exitF = logger.Fatal

	var (
		dryRun      bool
		environment string
		region      string
		refresh     time.Duration
		verbose     bool
	)

	root := &cobra.Command{
		Use:   "tacks",
		Short: "Tacks provides executable CloudFormation stacks",
	}

	root.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")

	root.PersistentPreRun = func(_ *cobra.Command, _ []string) {

		if verbose {
			logger.Level = logrus.DebugLevel
		}

	}

	run := &cobra.Command{
		Use:   "run [tacks stack filename]",
		Short: "Run a tacks stack",
		Run: func(_ *cobra.Command, args []string) {

			var filename string

			if len(args) > 0 {
				filename = args[0]
			}

			run := &command.Run{
				DryRun:      dryRun,
				Environment: environment,
				Filename:    filename,
				Region:      region,
			}

			command.Foreground(run, exitF)

			if !dryRun {

				watch := &command.Watch{
					Stackname: run.Document().Environment.StackName,
					Region:    run.Region,
				}

				command.Background(watch, exitF)

				term.Wait()

			}

		},
	}

	runFlags := run.Flags()

	runFlags.BoolVarP(&dryRun, "dry-run", "d", false, "output stack to stderr instead of sending it to CloudFormation")
	runFlags.StringVarP(&environment, "environment", "e", "", "specify the environment")

	watch := &cobra.Command{
		Use:   "watch [stack-name]",
		Short: "Watch stack events",
		Run: func(_ *cobra.Command, args []string) {

			var stackname string

			if len(args) > 0 {
				stackname = args[0]
			}

			watch := &command.Watch{
				Stackname: stackname,
				Region:    region,
				Refresh:   refresh,
			}

			command.Background(watch, exitF)

			term.Wait()

		},
	}

	for _, value := range []*cobra.Command{run, watch} {

		value.Flags().StringVarP(&region, "region", "r", DefaultRegion, "AWS region")
		value.Flags().DurationVarP(&refresh, "refresh-interval", "i", command.DefaultRefresh, "refresh interval for watching stack events")

	}

	version := &cobra.Command{
		Use:   "version",
		Short: "Print the version information of tacks",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Printf("Tacks %s (%s)\n", version, build)
		},
	}

	root.AddCommand(run)
	root.AddCommand(watch)
	root.AddCommand(version)

	if err := root.Execute(); err != nil {
		logger.Fatal(err)
	}

}