github.com/hazelops/ize@v1.1.12-0.20230915191306-97d7c0e48f11/internal/commands/secrets_rm.go (about)

     1  package commands
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"text/template"
     7  	"time"
     8  
     9  	"github.com/aws/aws-sdk-go/service/ssm"
    10  	"github.com/hazelops/ize/internal/config"
    11  	"github.com/hazelops/ize/pkg/templates"
    12  	"github.com/hazelops/ize/pkg/terminal"
    13  	"github.com/pterm/pterm"
    14  	"github.com/spf13/cobra"
    15  )
    16  
    17  type SecretsRemoveOptions struct {
    18  	Config      *config.Project
    19  	AppName     string
    20  	Backend     string
    21  	SecretsPath string
    22  	ui          terminal.UI
    23  	Explain     bool
    24  }
    25  
    26  var explainSecretsRmTmpl = `
    27  aws ssm delete-parameters --names $(aws ssm get-parameters-by-path \
    28  	--path "/{{.Env}}/{{svc}}" \
    29  	--with-decryption \
    30  	--recursive \
    31  	--query "Parameters[*].Name" | jq -e -r '. | to_entries[] | .value')
    32  `
    33  
    34  var secretsRemoveExample = templates.Examples(`
    35  	# Remove secrets:
    36  
    37      # This will remove your secrets for "squibby" app
    38   	ize secrets rm squibby
    39  `)
    40  
    41  func NewSecretsRemoveFlags(project *config.Project) *SecretsRemoveOptions {
    42  	return &SecretsRemoveOptions{
    43  		Config: project,
    44  	}
    45  }
    46  
    47  func NewCmdSecretsRemove(project *config.Project) *cobra.Command {
    48  	o := NewSecretsRemoveFlags(project)
    49  
    50  	cmd := &cobra.Command{
    51  		Use:               "rm <app>",
    52  		Example:           secretsRemoveExample,
    53  		Short:             "Remove secrets from storage",
    54  		Long:              "This command removes secrets from storage",
    55  		TraverseChildren:  true,
    56  		ValidArgsFunction: config.GetApps,
    57  		RunE: func(cmd *cobra.Command, args []string) error {
    58  			cmd.SilenceUsage = true
    59  			err := o.Complete(cmd)
    60  			if err != nil {
    61  				return err
    62  			}
    63  
    64  			err = o.Run()
    65  			if err != nil {
    66  				return err
    67  			}
    68  
    69  			return nil
    70  		},
    71  	}
    72  
    73  	cmd.Flags().StringVar(&o.Backend, "backend", "ssm", "backend type")
    74  	cmd.Flags().BoolVar(&o.Explain, "explain", false, "bash alternative shown")
    75  	cmd.Flags().StringVar(&o.SecretsPath, "path", "", "path to secrets")
    76  
    77  	return cmd
    78  }
    79  
    80  func (o *SecretsRemoveOptions) Complete(cmd *cobra.Command) error {
    81  	o.AppName = cmd.Flags().Args()[0]
    82  
    83  	if o.SecretsPath == "" {
    84  		o.SecretsPath = fmt.Sprintf("/%s/%s", o.Config.Env, o.AppName)
    85  	}
    86  
    87  	o.ui = terminal.ConsoleUI(context.Background(), o.Config.PlainText)
    88  
    89  	return nil
    90  }
    91  
    92  func (o *SecretsRemoveOptions) Validate() error {
    93  	if len(o.Config.Env) == 0 {
    94  		return fmt.Errorf("env must be specified")
    95  	}
    96  
    97  	return nil
    98  }
    99  
   100  func (o *SecretsRemoveOptions) Run() error {
   101  	if o.Explain {
   102  		err := o.Config.Generate(explainSecretsRmTmpl, template.FuncMap{
   103  			"svc": func() string {
   104  				return o.AppName
   105  			},
   106  		})
   107  		if err != nil {
   108  			return err
   109  		}
   110  
   111  		return nil
   112  	}
   113  
   114  	s, _ := pterm.DefaultSpinner.Start(fmt.Sprintf("Removing secrets for %s...", o.AppName))
   115  	if o.Backend == "ssm" {
   116  		err := o.rm(s)
   117  		if err != nil {
   118  			pterm.DefaultSection.Sprintfln("Secrets have been removed from %s", o.SecretsPath)
   119  			return err
   120  		}
   121  	} else {
   122  		return fmt.Errorf("backend %s is not found or not supported", o.Backend)
   123  	}
   124  
   125  	s.Success("Removing secrets complete!")
   126  
   127  	return nil
   128  }
   129  
   130  func (o *SecretsRemoveOptions) rm(s *pterm.SpinnerPrinter) error {
   131  	if o.SecretsPath == "" {
   132  		s.UpdateText("Path was not set...")
   133  		time.Sleep(2 * time.Second)
   134  		return nil
   135  	}
   136  
   137  	s.UpdateText(fmt.Sprintf("Removing secrets from %s://%s...", o.Backend, o.SecretsPath))
   138  
   139  	out, err := o.Config.AWSClient.SSMClient.GetParametersByPath(&ssm.GetParametersByPathInput{
   140  		Path: &o.SecretsPath,
   141  	})
   142  	if err != nil {
   143  		return err
   144  	}
   145  
   146  	s.UpdateText("Getting secrets...")
   147  
   148  	if len(out.Parameters) == 0 {
   149  		s.UpdateText("No values found...")
   150  		time.Sleep(2 * time.Second)
   151  		s.UpdateText("Removing secrets...")
   152  		time.Sleep(1 * time.Second)
   153  		return nil
   154  	}
   155  
   156  	var names []*string
   157  
   158  	for _, p := range out.Parameters {
   159  		names = append(names, p.Name)
   160  	}
   161  
   162  	_, err = o.Config.AWSClient.SSMClient.DeleteParameters(&ssm.DeleteParametersInput{
   163  		Names: names,
   164  	})
   165  	if err != nil {
   166  		return err
   167  	}
   168  
   169  	s.UpdateText("Removing secrets...")
   170  
   171  	return nil
   172  }