// Copyright 2016-2018, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "sort" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/pulumi/pulumi/pkg/backend" "github.com/pulumi/pulumi/pkg/backend/display" "github.com/pulumi/pulumi/sdk/go/common/apitype" "github.com/pulumi/pulumi/sdk/go/common/util/cmdutil" ) func newStackTagCmd() *cobra.Command { var stack string cmd := &cobra.Command{ Use: "tag", Short: "Manage stack tags", Long: "Manage stack tags\n" + "\n" + "Stacks have associated metadata in the form of tags. Each tag consists of a name\n" + "and value. The `get`, `ls`, `rm`, and `set` commands can be used to manage tags.\n" + "Some tags are automatically assigned based on the environment each time a stack\n" + "is updated.\n", Args: cmdutil.NoArgs, } cmd.PersistentFlags().StringVarP( &stack, "stack", "s", "", "The name of the stack to operate on. Defaults to the current stack") cmd.AddCommand(newStackTagGetCmd(&stack)) cmd.AddCommand(newStackTagLsCmd(&stack)) cmd.AddCommand(newStackTagRmCmd(&stack)) cmd.AddCommand(newStackTagSetCmd(&stack)) return cmd } func newStackTagGetCmd(stack *string) *cobra.Command { return &cobra.Command{ Use: "get ", Short: "Get a single stack tag value", Args: cmdutil.SpecificArgs([]string{"name"}), Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error { name := args[0] opts := display.Options{ Color: cmdutil.GetGlobalColorization(), } s, err := requireStack(*stack, false, opts, true /*setCurrent*/) if err != nil { return err } tags, err := backend.GetStackTags(commandContext(), s) if err != nil { return err } if value, ok := tags[name]; ok { fmt.Printf("%v\n", value) return nil } return errors.Errorf( "stack tag '%s' not found for stack '%s'", name, s.Ref()) }), } } func newStackTagLsCmd(stack *string) *cobra.Command { var jsonOut bool cmd := &cobra.Command{ Use: "ls", Short: "List all stack tags", Args: cmdutil.NoArgs, Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error { opts := display.Options{ Color: cmdutil.GetGlobalColorization(), } s, err := requireStack(*stack, false, opts, true /*setCurrent*/) if err != nil { return err } tags, err := backend.GetStackTags(commandContext(), s) if err != nil { return err } if jsonOut { return printJSON(tags) } printStackTags(tags) return nil }), } cmd.PersistentFlags().BoolVarP( &jsonOut, "json", "j", false, "Emit output as JSON") return cmd } func printStackTags(tags map[apitype.StackTagName]string) { var names []string for n := range tags { names = append(names, n) } sort.Strings(names) rows := []cmdutil.TableRow{} for _, name := range names { rows = append(rows, cmdutil.TableRow{Columns: []string{name, tags[name]}}) } cmdutil.PrintTable(cmdutil.Table{ Headers: []string{"NAME", "VALUE"}, Rows: rows, }) } func newStackTagRmCmd(stack *string) *cobra.Command { return &cobra.Command{ Use: "rm ", Short: "Remove a stack tag", Args: cmdutil.SpecificArgs([]string{"name"}), Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error { name := args[0] opts := display.Options{ Color: cmdutil.GetGlobalColorization(), } s, err := requireStack(*stack, false, opts, true /*setCurrent*/) if err != nil { return err } ctx := commandContext() tags, err := backend.GetStackTags(ctx, s) if err != nil { return err } delete(tags, name) return backend.UpdateStackTags(ctx, s, tags) }), } } func newStackTagSetCmd(stack *string) *cobra.Command { return &cobra.Command{ Use: "set ", Short: "Set a stack tag", Args: cmdutil.SpecificArgs([]string{"name", "value"}), Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error { name := args[0] value := args[1] opts := display.Options{ Color: cmdutil.GetGlobalColorization(), } s, err := requireStack(*stack, false, opts, true /*setCurrent*/) if err != nil { return err } ctx := commandContext() tags, err := backend.GetStackTags(ctx, s) if err != nil { return err } if tags == nil { tags = make(map[apitype.StackTagName]string) } tags[name] = value return backend.UpdateStackTags(ctx, s, tags) }), } }