-
Notifications
You must be signed in to change notification settings - Fork 2
/
stack-delete.go
158 lines (126 loc) · 3.94 KB
/
stack-delete.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package cmd
import (
"errors"
"fmt"
"strings"
"github.com/aws/aws-sdk-go/aws"
cf "github.com/aws/aws-sdk-go/service/cloudformation"
ctlaws "github.com/liangrog/cfctl/pkg/aws"
"github.com/liangrog/cfctl/pkg/conf"
"github.com/liangrog/cfctl/pkg/utils"
"github.com/liangrog/cfctl/pkg/utils/i18n"
"github.com/liangrog/cfctl/pkg/utils/templates"
"github.com/spf13/cobra"
)
var (
stackDeleteShort = i18n.T("Delete one or more stacks.")
stackDeleteLong = templates.LongDesc(i18n.T(`Delete one or more stacks.`))
stackDeleteExample = templates.Examples(i18n.T(`
# Delete a stack with name 'stack-1'
$ cfctl stack delete stack-1
# Delete multiple stacks with name 'stack-1' and 'stack-2'
$ cfctl stack delete stack-1 stack-2
# Delete all stacks from a specific stack file
$ cfctl stack delete --file stack-file.yaml --all
# Delete stacks that have specific tag values
$ cfctl sack delete --tags Name=stack-1,Type=frontend`))
)
// Register sub commands
func init() {
cmd := getCmdStackDelete()
addFlagsStackDelete(cmd)
CmdStack.AddCommand(cmd)
}
func addFlagsStackDelete(cmd *cobra.Command) {
cmd.Flags().BoolP(CMD_STACK_DELETE_ALL, "", false, "delete all the stacks in the stack configuration file")
cmd.Flags().String(CMD_STACK_DELETE_RETAIN_RESOURCES, "", "retain resources during stack delete, e.g. S3 buckets that are not empty. Multiple resources seperated by comma.")
}
// cmd: delete
func getCmdStackDelete() *cobra.Command {
cmd := &cobra.Command{
Use: "delete",
Short: stackDeleteShort,
Long: stackDeleteLong,
Example: fmt.Sprintf(stackDeleteExample),
Args: func(cmd *cobra.Command, args []string) error {
all, _ := cmd.Flags().GetBool(CMD_STACK_DELETE_ALL)
tags := cmd.Flags().Lookup(CMD_STACK_DEPLOY_TAGS).Value.String()
if !all && len(tags) == 0 && len(args) < 1 {
return errors.New(fmt.Sprintf("Please provide either stack name or using '--%s' or '--%s' flag", CMD_STACK_DELETE_ALL, CMD_STACK_DEPLOY_TAGS))
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
all, _ := cmd.Flags().GetBool(CMD_STACK_DELETE_ALL)
err := stackDelete(
args,
all,
cmd.Flags().Lookup(CMD_STACK_DEPLOY_FILE).Value.String(),
cmd.Flags().Lookup(CMD_STACK_DEPLOY_TAGS).Value.String(),
cmd.Flags().Lookup(CMD_STACK_DELETE_RETAIN_RESOURCES).Value.String(),
)
silenceUsageOnError(cmd, err)
return err
},
}
return cmd
}
// Delete stacks.
func stackDelete(stackNames []string, all bool, stackConf, tags, retainRes string) error {
var err error
stacks := make(map[string]*conf.StackConfig)
// Load deploy configuration file.
dc, err := conf.NewDeployConfig(stackConf)
if err != nil {
return err
}
// If flag is set to all stacks, get
// stacks from configuration file.
if all {
stacks = dc.GetStackList(nil)
} else {
filters := make(map[string]string)
if len(tags) > 0 {
filters["tag"] = tags
}
if len(stackNames) > 0 {
filters["name"] = strings.Join(stackNames, ",")
}
stacks = dc.GetStackList(filters)
}
if len(stacks) == 0 {
return errors.New(fmt.Sprintf("No stack found for given filters.\n"))
}
stack := ctlaws.NewStack(cf.New(ctlaws.AWSSess))
for sn, _ := range stacks {
fmt.Println("")
// If stack name given
if !stack.Exist(sn) {
utils.StdoutError(fmt.Sprintf("Failed to find stack %s", sn))
continue
}
// Find retaining resources
var srr []string
if len(retainRes) > 0 {
// Get stack resources
resources, err := stack.GetStackResources(sn)
if err != nil {
return err
}
// If logical ids exsits in the given retain resources list
for _, sr := range resources {
if strings.Contains(retainRes, aws.StringValue(sr.LogicalResourceId)) {
srr = append(srr, aws.StringValue(sr.LogicalResourceId))
}
}
}
_, err = stack.DeleteStack(sn, srr...)
if err != nil {
return err
}
if err := stack.PollStackEvents(sn, ctlaws.StackWaiterTypeDelete); err != nil {
return err
}
}
return nil
}