github.com/grafana/tanka@v0.26.1-0.20240506093700-c22cfc35c21a/pkg/tanka/prune.go (about) 1 package tanka 2 3 import ( 4 "fmt" 5 "os" 6 7 "github.com/fatih/color" 8 9 "github.com/grafana/tanka/pkg/kubernetes" 10 "github.com/grafana/tanka/pkg/term" 11 ) 12 13 // PruneOpts specify additional properties for the Prune action 14 type PruneOpts struct { 15 ApplyBaseOpts 16 } 17 18 // Prune deletes all resources from the cluster, that are no longer present in 19 // Jsonnet. It uses the `tanka.dev/environment` label to identify those. 20 func Prune(baseDir string, opts PruneOpts) error { 21 // parse jsonnet, init k8s client 22 p, err := Load(baseDir, opts.Opts) 23 if err != nil { 24 return err 25 } 26 kube, err := p.Connect() 27 if err != nil { 28 return err 29 } 30 defer kube.Close() 31 32 // find orphaned resources 33 orphaned, err := kube.Orphaned(p.Resources) 34 if err != nil { 35 return err 36 } 37 38 if len(orphaned) == 0 { 39 fmt.Fprintln(os.Stderr, "Nothing found to prune.") 40 return nil 41 } 42 43 // print diff 44 diff, err := kubernetes.StaticDiffer(false)(orphaned) 45 if err != nil { 46 // static diff can't fail normally, so unlike in apply, this is fatal 47 // here 48 return err 49 } 50 fmt.Print(term.Colordiff(*diff).String()) 51 52 // print namespace removal warning 53 namespaces := []string{} 54 for _, obj := range orphaned { 55 if obj.Kind() == "Namespace" { 56 namespaces = append(namespaces, obj.Metadata().Name()) 57 } 58 } 59 if len(namespaces) > 0 { 60 warning := color.New(color.FgHiYellow, color.Bold).FprintfFunc() 61 warning(color.Error, "WARNING: This will delete following namespaces and all resources in them:\n") 62 for _, ns := range namespaces { 63 fmt.Fprintf(os.Stderr, " - %s\n", ns) 64 } 65 fmt.Fprintln(os.Stderr, "") 66 } 67 68 // prompt for confirm 69 if opts.AutoApprove != AutoApproveAlways { 70 if err := confirmPrompt("Pruning from", p.Env.Spec.Namespace, kube.Info()); err != nil { 71 return err 72 } 73 } 74 75 // delete resources 76 return kube.Delete(orphaned, kubernetes.DeleteOpts{ 77 Force: opts.Force, 78 DryRun: opts.DryRun, 79 }) 80 }