package cmd import ( "context" "fmt" "os" v2 "github.com/porter-dev/porter/cli/cmd/v2" "github.com/fatih/color" api "github.com/porter-dev/porter/api/client" "github.com/porter-dev/porter/api/types" "github.com/spf13/cobra" ) var linkedApps []string // stackCmd represents the "porter stack" base command when called // without any subcommands var stackCmd = &cobra.Command{ Use: "stack", Aliases: []string{"stacks"}, Short: "Commands that control Porter Stacks", } var stackEnvGroupCmd = &cobra.Command{ Use: "env-group", Aliases: []string{"eg", "envgroup", "env-groups", "envgroups"}, Short: "Commands to add or remove an env group in a stack", Run: func(cmd *cobra.Command, args []string) { color.New(color.FgRed).Fprintln(os.Stderr, "need to specify an operation to continue") }, } var stackEnvGroupAddCmd = &cobra.Command{ Use: "add [name]", Args: cobra.ExactArgs(1), Short: "Add an env group to a stack", Run: func(cmd *cobra.Command, args []string) { err := checkLoginAndRun(args, stackAddEnvGroup) if err != nil { os.Exit(1) } }, } var stackEnvGroupRemoveCmd = &cobra.Command{ Use: "remove [name]", Args: cobra.ExactArgs(1), Short: "Remove an existing env group from a stack", Run: func(cmd *cobra.Command, args []string) { err := checkLoginAndRun(args, stackRemoveEnvGroup) if err != nil { os.Exit(1) } }, } func init() { rootCmd.AddCommand(stackCmd) stackCmd.AddCommand(stackEnvGroupCmd) stackCmd.PersistentFlags().StringVar( &name, "name", "", "the name of the stack", ) stackCmd.PersistentFlags().StringVar( &namespace, "namespace", "default", "the namespace of the stack", ) stackEnvGroupAddCmd.PersistentFlags().StringArrayVarP( &normalEnvGroupVars, "normal", "n", []string{}, "list of variables to set, in the form VAR=VALUE", ) stackEnvGroupAddCmd.PersistentFlags().StringArrayVarP( &secretEnvGroupVars, "secret", "s", []string{}, "list of secret variables to set, in the form VAR=VALUE", ) stackEnvGroupAddCmd.PersistentFlags().StringArrayVar( &linkedApps, "linked-apps", []string{}, "list of stack apps to link this env group with", ) stackEnvGroupCmd.AddCommand(stackEnvGroupAddCmd) stackEnvGroupCmd.AddCommand(stackEnvGroupRemoveCmd) } func stackAddEnvGroup(_ *types.GetAuthenticatedUserResponse, client *api.Client, args []string) error { ctx := context.Background() project, err := client.GetProject(ctx, cliConf.Project) if err != nil { return fmt.Errorf("could not retrieve project from Porter API. Please contact support@porter.run") } if project.ValidateApplyV2 { err = v2.StackAddEnvGroup(ctx) if err != nil { return err } return nil } envGroupName := args[0] if len(envGroupName) == 0 { return fmt.Errorf("empty env group name") } else if len(name) == 0 { return fmt.Errorf("empty stack name") } else if len(normalEnvGroupVars) == 0 && len(secretEnvGroupVars) == 0 { return fmt.Errorf("one or more variables are required to create the env group") } listStacks, err := client.ListStacks(context.Background(), cliConf.Project, cliConf.Cluster, namespace) if err != nil { return err } stacks := *listStacks var stackID string for _, stk := range stacks { if stk.Name == name { stackID = stk.ID } } if len(stackID) == 0 { return fmt.Errorf("stack not found") } normalVariables := make(map[string]string) secretVariables := make(map[string]string) for _, v := range normalEnvGroupVars { key, val, err := validateVarValue(v) if err != nil { return err } normalVariables[key] = val } for _, v := range secretEnvGroupVars { key, val, err := validateVarValue(v) if err != nil { return err } secretVariables[key] = val } err = client.AddEnvGroupToStack( context.Background(), cliConf.Project, cliConf.Cluster, namespace, stackID, &types.CreateStackEnvGroupRequest{ Name: envGroupName, Variables: normalVariables, SecretVariables: secretVariables, LinkedApplications: linkedApps, }, ) if err != nil { return err } color.New(color.FgGreen).Println("successfully added env group") return nil } func stackRemoveEnvGroup(_ *types.GetAuthenticatedUserResponse, client *api.Client, args []string) error { ctx := context.Background() project, err := client.GetProject(ctx, cliConf.Project) if err != nil { return fmt.Errorf("could not retrieve project from Porter API. Please contact support@porter.run") } if project.ValidateApplyV2 { err = v2.StackRemoveEnvGroup(ctx) if err != nil { return err } return nil } envGroupName := args[0] if len(envGroupName) == 0 { return fmt.Errorf("empty env group name") } else if len(name) == 0 { return fmt.Errorf("empty stack name") } listStacks, err := client.ListStacks(context.Background(), cliConf.Project, cliConf.Cluster, namespace) if err != nil { return err } stacks := *listStacks var stackID string for _, stk := range stacks { if stk.Name == name { stackID = stk.ID } } if len(stackID) == 0 { return fmt.Errorf("stack not found") } err = client.RemoveEnvGroupFromStack(context.Background(), cliConf.Project, cliConf.Cluster, namespace, stackID, envGroupName) if err != nil { return err } color.New(color.FgGreen).Println("successfully removed env group") return nil }