From 0000b47809bd3aab79d1daab1849cea7a513539b Mon Sep 17 00:00:00 2001 From: Jakub Kania Date: Wed, 8 Aug 2018 22:42:13 +0200 Subject: [PATCH] Add wildcard for tainting/untaining --- command/taint.go | 49 ++++++++++++++++++++++++++++------------------ command/untaint.go | 34 ++++++++++++++++++++++++-------- vendor/vendor.json | 48 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 27 deletions(-) diff --git a/command/taint.go b/command/taint.go index 4dc16e60cd5a..7126d980d568 100644 --- a/command/taint.go +++ b/command/taint.go @@ -6,6 +6,7 @@ import ( "log" "strings" + "github.com/gobwas/glob" "github.com/hashicorp/terraform/command/clistate" "github.com/hashicorp/terraform/terraform" ) @@ -52,17 +53,6 @@ func (c *TaintCommand) Run(args []string) int { module = "root." + module } - rsk, err := terraform.ParseResourceStateKey(name) - if err != nil { - c.Ui.Error(fmt.Sprintf("Failed to parse resource name: %s", err)) - return 1 - } - - if !rsk.Mode.Taintable() { - c.Ui.Error(fmt.Sprintf("Resource '%s' cannot be tainted", name)) - return 1 - } - // Load the backend b, err := c.Backend(nil) if err != nil { @@ -132,9 +122,28 @@ func (c *TaintCommand) Run(args []string) int { return 1 } - // Get the resource we're looking for - rs, ok := mod.Resources[name] - if !ok { + g, err := glob.Compile(name) + if err != nil { + //The error message should be something better + c.Ui.Error(fmt.Sprintf( + "The glob %s is not correct.", + name)) + } + resources := make(map[string]*terraform.ResourceState) + + if err == nil { + for key, rs := range mod.Resources { + if g.Match(key) { + //The rs always should be parseable + rsk, _ := terraform.ParseResourceStateKey(key) + if rsk.Mode.Taintable() { + resources[key] = rs + } + + } + } + } + if len(resources) == 0 { if allowMissing { return c.allowMissingExit(name, module) } @@ -146,8 +155,13 @@ func (c *TaintCommand) Run(args []string) int { return 1 } - // Taint the resource - rs.Taint() + for target, rs := range resources { + // Taint the resource + rs.Taint() + c.Ui.Output(fmt.Sprintf( + "The resource %s in the module %s has been marked as tainted!", + target, module)) + } log.Printf("[INFO] Writing state output to: %s", c.Meta.StateOutPath()) if err := st.WriteState(s); err != nil { @@ -159,9 +173,6 @@ func (c *TaintCommand) Run(args []string) int { return 1 } - c.Ui.Output(fmt.Sprintf( - "The resource %s in the module %s has been marked as tainted!", - name, module)) return 0 } diff --git a/command/untaint.go b/command/untaint.go index 39d047fd677d..7d80da32b146 100644 --- a/command/untaint.go +++ b/command/untaint.go @@ -6,7 +6,9 @@ import ( "log" "strings" + "github.com/gobwas/glob" "github.com/hashicorp/terraform/command/clistate" + "github.com/hashicorp/terraform/terraform" ) // UntaintCommand is a cli.Command implementation that manually untaints @@ -120,9 +122,23 @@ func (c *UntaintCommand) Run(args []string) int { return 1 } - // Get the resource we're looking for - rs, ok := mod.Resources[name] - if !ok { + g, err := glob.Compile(name) + if err != nil { + c.Ui.Error(fmt.Sprintf( + "The glob %s is not correct.", + name)) + } + + // Get the resources we're looking for + resources := make(map[string]*terraform.ResourceState) + if err == nil { + for key, rs := range mod.Resources { + if g.Match(key) { + resources[key] = rs + } + } + } + if len(resources) == 0 { if allowMissing { return c.allowMissingExit(name, module) } @@ -134,8 +150,13 @@ func (c *UntaintCommand) Run(args []string) int { return 1 } - // Untaint the resource - rs.Untaint() + for target, rs := range resources { + // Untaint the resource + rs.Untaint() + c.Ui.Output(fmt.Sprintf( + "The resource %s in the module %s has been successfully untainted!", + target, module)) + } log.Printf("[INFO] Writing state output to: %s", c.Meta.StateOutPath()) if err := st.WriteState(s); err != nil { @@ -147,9 +168,6 @@ func (c *UntaintCommand) Run(args []string) int { return 1 } - c.Ui.Output(fmt.Sprintf( - "The resource %s in the module %s has been successfully untainted!", - name, module)) return 0 } diff --git a/vendor/vendor.json b/vendor/vendor.json index 40d3646b74d6..057fd6fa9de4 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1326,6 +1326,54 @@ "revision": "6592d9cc0a499ad2d5f574fde80a2b5c5cc3b4f5", "revisionTime": "2018-01-28T22:55:04Z" }, + { + "checksumSHA1": "/RE0VzeaXdaBUNeNMUXWqzly7qY=", + "path": "github.com/gobwas/glob", + "revision": "f00a7392b43971b2fdb562418faab1f18da2067a", + "revisionTime": "2018-04-02T14:15:43Z" + }, + { + "checksumSHA1": "UIxNdlqa2kcYi5EEe79/WzyPiz4=", + "path": "github.com/gobwas/glob/compiler", + "revision": "f00a7392b43971b2fdb562418faab1f18da2067a", + "revisionTime": "2018-04-02T14:15:43Z" + }, + { + "checksumSHA1": "jNdbCxBabqjv9tREXA4Nx45Y4wg=", + "path": "github.com/gobwas/glob/match", + "revision": "f00a7392b43971b2fdb562418faab1f18da2067a", + "revisionTime": "2018-04-02T14:15:43Z" + }, + { + "checksumSHA1": "2KhDNUE98XhHnIgg2S9E4gcWoig=", + "path": "github.com/gobwas/glob/syntax", + "revision": "f00a7392b43971b2fdb562418faab1f18da2067a", + "revisionTime": "2018-04-02T14:15:43Z" + }, + { + "checksumSHA1": "FPIMdPSazNZGNU+ZmPtIeZpVHFU=", + "path": "github.com/gobwas/glob/syntax/ast", + "revision": "f00a7392b43971b2fdb562418faab1f18da2067a", + "revisionTime": "2018-04-02T14:15:43Z" + }, + { + "checksumSHA1": "umyztSrQrQIl9JgwhDDb6wrSLeI=", + "path": "github.com/gobwas/glob/syntax/lexer", + "revision": "f00a7392b43971b2fdb562418faab1f18da2067a", + "revisionTime": "2018-04-02T14:15:43Z" + }, + { + "checksumSHA1": "vux29fN5O22F3QPLOnjQ37278vg=", + "path": "github.com/gobwas/glob/util/runes", + "revision": "f00a7392b43971b2fdb562418faab1f18da2067a", + "revisionTime": "2018-04-02T14:15:43Z" + }, + { + "checksumSHA1": "Sxp2AHWkkLkIq6w9aMcLmzcwD6w=", + "path": "github.com/gobwas/glob/util/strings", + "revision": "f00a7392b43971b2fdb562418faab1f18da2067a", + "revisionTime": "2018-04-02T14:15:43Z" + }, { "checksumSHA1": "q3Bc7JpLWBqhZ4M7oreGo34RSkc=", "path": "github.com/golang/protobuf/proto",