github.com/apex/up@v1.7.1/internal/cli/stack/stack.go (about) 1 package stack 2 3 import ( 4 "fmt" 5 6 "github.com/pkg/errors" 7 "github.com/tj/kingpin" 8 "github.com/tj/survey" 9 10 "github.com/apex/up/internal/cli/root" 11 "github.com/apex/up/internal/stats" 12 "github.com/apex/up/internal/util" 13 ) 14 15 func init() { 16 cmd := root.Command("stack", "Stack resource management.") 17 18 cmd.Example(`up stack`, "Show status of the stack resources.") 19 cmd.Example(`up stack plan`, "Show resource changes.") 20 cmd.Example(`up stack apply`, "Apply resource changes.") 21 cmd.Example(`up stack delete`, "Delete the stack resources.") 22 23 plan(cmd) 24 apply(cmd) 25 delete(cmd) 26 status(cmd) 27 } 28 29 // plan changes. 30 func plan(cmd *kingpin.Cmd) { 31 c := cmd.Command("plan", "Plan configuration changes.") 32 c.Example(`up stack plan`, "Show changes planned.") 33 34 c.Action(func(_ *kingpin.ParseContext) error { 35 c, p, err := root.Init() 36 if err != nil { 37 return errors.Wrap(err, "initializing") 38 } 39 40 stats.Track("Plan Stack", nil) 41 region := c.Regions[0] 42 43 ok, err := p.Exists(region) 44 if err != nil { 45 return errors.Wrap(err, "checking if app exists") 46 } 47 48 if !ok { 49 return errors.New("Application does not exist, please run `$ up` initially to create it.") 50 } 51 52 // TODO: multi-region 53 return p.PlanStack(region) 54 }) 55 } 56 57 // apply changes. 58 func apply(cmd *kingpin.Cmd) { 59 c := cmd.Command("apply", "Apply configuration changes.") 60 c.Example(`up stack apply`, "Apply the changes of the previous plan.") 61 62 c.Action(func(_ *kingpin.ParseContext) error { 63 c, p, err := root.Init() 64 if err != nil { 65 return errors.Wrap(err, "initializing") 66 } 67 68 stats.Track("Apply Stack", map[string]interface{}{ 69 "dns_zone_count": len(c.DNS.Zones), 70 "stage_count": len(c.Stages.List()), 71 "stage_domain_count": len(c.Stages.Domains()), 72 }) 73 74 // TODO: multi-region 75 return p.ApplyStack(c.Regions[0]) 76 }) 77 } 78 79 // delete resources. 80 func delete(cmd *kingpin.Cmd) { 81 c := cmd.Command("delete", "Delete configured resources.") 82 c.Example(`up stack delete`, "Delete stack with confirmation prompt.") 83 c.Example(`up stack delete --force`, "Delete stack without confirmation prompt.") 84 c.Example(`up stack delete --async`, "Don't wait for deletion to complete.") 85 c.Example(`up stack delete -fa`, "Force asynchronous deletion.") 86 87 force := c.Flag("force", "Skip the confirmation prompt.").Short('f').Bool() 88 async := c.Flag("async", "Perform deletion asynchronously.").Short('a').Bool() 89 90 c.Action(func(_ *kingpin.ParseContext) error { 91 c, p, err := root.Init() 92 if err != nil { 93 return errors.Wrap(err, "initializing") 94 } 95 96 wait := !*async 97 defer util.Pad()() 98 99 stats.Track("Delete Stack", map[string]interface{}{ 100 "force": *force, 101 "wait": wait, 102 }) 103 104 if *force { 105 // TODO: multi-region 106 return p.DeleteStack(c.Regions[0], wait) 107 } 108 109 prompt := &survey.Confirm{ 110 Message: fmt.Sprintf("Really destroy stack %q?", c.Name), 111 } 112 113 var ok bool 114 if err := survey.AskOne(prompt, &ok, nil); err != nil { 115 return err 116 } 117 118 if !ok { 119 util.LogPad("Aborted") 120 return nil 121 } 122 123 return p.DeleteStack(c.Regions[0], wait) 124 }) 125 } 126 127 // status of the stack. 128 func status(cmd *kingpin.Cmd) { 129 c := cmd.Command("status", "Show status of resources.").Default() 130 131 c.Action(func(_ *kingpin.ParseContext) error { 132 c, p, err := root.Init() 133 if err != nil { 134 return errors.Wrap(err, "initializing") 135 } 136 137 stats.Track("Show Stack", nil) 138 139 // TODO: multi-region 140 return p.ShowStack(c.Regions[0]) 141 }) 142 }