github.com/pluralsh/plural-cli@v0.9.5/pkg/wkspace/actions.go (about) 1 package wkspace 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 "time" 9 10 "go.mercari.io/hcledit" 11 "helm.sh/helm/v3/pkg/action" 12 13 "github.com/pluralsh/plural-cli/pkg/executor" 14 "github.com/pluralsh/plural-cli/pkg/helm" 15 "github.com/pluralsh/plural-cli/pkg/kubernetes" 16 "github.com/pluralsh/plural-cli/pkg/utils" 17 "github.com/pluralsh/plural-cli/pkg/utils/git" 18 "github.com/pluralsh/plural-cli/pkg/utils/pathing" 19 ) 20 21 type checker func(s string) bool 22 23 var alwaysErr checker = func(s string) bool { return false } 24 25 func (c checker) execSuppressed(command string, args ...string) (err error) { 26 for retry := 2; retry >= 0; retry-- { 27 utils.Highlight("%s %s ~> ", command, strings.Join(args, " ")) 28 cmd, out := executor.SuppressedCommand(command, args...) 29 err = executor.RunCommand(cmd, out) 30 if err == nil || c(out.Format()) { 31 break 32 } 33 fmt.Printf("retrying command, number of retries remaining: %d\n", retry) 34 } 35 36 return 37 } 38 39 func (w *Workspace) DestroyHelm() error { 40 // ensure current kubeconfig is correct before destroying stuff 41 if err := w.Provider.KubeConfig(); err != nil { 42 return err 43 } 44 45 name := w.Installation.Repository.Name 46 namespace := w.Config.Namespace(name) 47 var err error 48 for retry := 2; retry >= 0; retry-- { 49 err = uninstallHelm(name, namespace) 50 if err == nil { 51 break 52 } 53 fmt.Printf("retrying command, number of retries remaining: %d\n", retry) 54 } 55 56 return err 57 58 } 59 60 func (w *Workspace) Bounce() error { 61 return w.ToMinimal().BounceHelm(false, nil, nil, nil) 62 } 63 64 func (w *Workspace) HelmDiff() error { 65 return w.ToMinimal().DiffHelm() 66 } 67 68 func (w *Workspace) Destroy() error { 69 if err := w.DestroyHelm(); err != nil { 70 return err 71 } 72 73 if err := w.DestroyTerraform(); err != nil { 74 return err 75 } 76 77 return w.Reset() 78 } 79 80 func (w *Workspace) Reset() error { 81 repo := w.Installation.Repository 82 repoRoot, err := git.Root() 83 if err != nil { 84 return err 85 } 86 87 deployFile := pathing.SanitizeFilepath(filepath.Join(repoRoot, repo.Name, "deploy.hcl")) 88 editor, err := hcledit.ReadFile(deployFile) 89 if err != nil { 90 return err 91 } 92 if err := editor.Update("step.*.sha", ""); err != nil { 93 return err 94 } 95 if err := editor.OverWriteFile(); err != nil { 96 return err 97 } 98 99 return nil 100 } 101 102 func (w *Workspace) DestroyTerraform() error { 103 repo := w.Installation.Repository 104 repoRoot, err := git.Root() 105 if err != nil { 106 return err 107 } 108 path, err := filepath.Abs(pathing.SanitizeFilepath(filepath.Join(repoRoot, repo.Name, "terraform"))) 109 if err != nil { 110 return err 111 } 112 113 time.AfterFunc(1*time.Minute, func() { 114 kube, err := kubernetes.Kubernetes() 115 if err != nil { 116 fmt.Printf("Could not set up k8s client due to %s\n", err) 117 return 118 } 119 120 ns := w.Config.Namespace(repo.Name) 121 if err := kube.FinalizeNamespace(ns); err != nil { 122 return 123 } 124 }) 125 126 if err := os.Chdir(path); err != nil { 127 return err 128 } 129 if err := alwaysErr.execSuppressed("terraform", "init", "-upgrade"); err != nil { 130 return err 131 } 132 133 return alwaysErr.execSuppressed("terraform", "destroy", "-auto-approve") 134 } 135 136 func uninstallHelm(name, namespace string) error { 137 exists, err := isReleaseAvailable(name, namespace) 138 if err != nil { 139 return err 140 } 141 if exists { 142 actionConfig, err := helm.GetActionConfig(namespace) 143 if err != nil { 144 return err 145 } 146 client := action.NewUninstall(actionConfig) 147 148 _, err = client.Run(name) 149 if err != nil { 150 return err 151 } 152 } 153 return nil 154 } 155 156 func isReleaseAvailable(name, namespace string) (bool, error) { 157 actionConfig, err := helm.GetActionConfig(namespace) 158 if err != nil { 159 return false, err 160 } 161 client := action.NewList(actionConfig) 162 resp, err := client.Run() 163 if err != nil { 164 return false, err 165 } 166 for _, rel := range resp { 167 if rel.Name == name { 168 return true, nil 169 } 170 } 171 return false, nil 172 }