aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform
diff options
context:
space:
mode:
authorJake Champlin <jake@gnu.space>2017-06-09 17:54:32 +0000
committerJake Champlin <jake@gnu.space>2017-06-09 17:54:32 +0000
commit9b12e4fe6f3c95986f1f3ec791636c58ca7e7583 (patch)
tree38f5f12bec0e488a12f0459a7356e6b7de7d8f84 /vendor/github.com/hashicorp/terraform
parentcec3de8a3bcaffd21dedd1bf42da4b490cae7e16 (diff)
downloadterraform-provider-statuscake-9b12e4fe6f3c95986f1f3ec791636c58ca7e7583.tar.gz
terraform-provider-statuscake-9b12e4fe6f3c95986f1f3ec791636c58ca7e7583.tar.zst
terraform-provider-statuscake-9b12e4fe6f3c95986f1f3ec791636c58ca7e7583.zip
Transfer of provider code
Diffstat (limited to 'vendor/github.com/hashicorp/terraform')
-rw-r--r--vendor/github.com/hashicorp/terraform/config/config.go64
-rw-r--r--vendor/github.com/hashicorp/terraform/config/interpolate_funcs.go48
-rw-r--r--vendor/github.com/hashicorp/terraform/dag/set.go14
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/acctest/acctest.go2
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/acctest/random.go93
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/acctest/remotetests.go27
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/resource/testing.go148
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go30
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/schema/schema.go4
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/structure/expand_json.go11
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/structure/flatten_json.go16
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/structure/normalize_json.go24
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/structure/suppress_json_diff.go21
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/validation/validation.go108
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/graph_builder_refresh.go49
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/interpolate.go13
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/node_data_refresh.go20
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/node_output.go9
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go88
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/transform_resource_refresh_plannable.go55
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/transform_targets.go77
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/user_agent.go14
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/version.go4
23 files changed, 553 insertions, 386 deletions
diff --git a/vendor/github.com/hashicorp/terraform/config/config.go b/vendor/github.com/hashicorp/terraform/config/config.go
index 9a764ac..a157824 100644
--- a/vendor/github.com/hashicorp/terraform/config/config.go
+++ b/vendor/github.com/hashicorp/terraform/config/config.go
@@ -545,7 +545,7 @@ func (c *Config) Validate() error {
545 545
546 // Verify provisioners 546 // Verify provisioners
547 for _, p := range r.Provisioners { 547 for _, p := range r.Provisioners {
548 // This validation checks that there are now splat variables 548 // This validation checks that there are no splat variables
549 // referencing ourself. This currently is not allowed. 549 // referencing ourself. This currently is not allowed.
550 550
551 for _, v := range p.ConnInfo.Variables { 551 for _, v := range p.ConnInfo.Variables {
@@ -705,17 +705,6 @@ func (c *Config) Validate() error {
705 } 705 }
706 } 706 }
707 707
708 // Check that all variables are in the proper context
709 for source, rc := range c.rawConfigs() {
710 walker := &interpolationWalker{
711 ContextF: c.validateVarContextFn(source, &errs),
712 }
713 if err := reflectwalk.Walk(rc.Raw, walker); err != nil {
714 errs = append(errs, fmt.Errorf(
715 "%s: error reading config: %s", source, err))
716 }
717 }
718
719 // Validate the self variable 708 // Validate the self variable
720 for source, rc := range c.rawConfigs() { 709 for source, rc := range c.rawConfigs() {
721 // Ignore provisioners. This is a pretty brittle way to do this, 710 // Ignore provisioners. This is a pretty brittle way to do this,
@@ -787,57 +776,6 @@ func (c *Config) rawConfigs() map[string]*RawConfig {
787 return result 776 return result
788} 777}
789 778
790func (c *Config) validateVarContextFn(
791 source string, errs *[]error) interpolationWalkerContextFunc {
792 return func(loc reflectwalk.Location, node ast.Node) {
793 // If we're in a slice element, then its fine, since you can do
794 // anything in there.
795 if loc == reflectwalk.SliceElem {
796 return
797 }
798
799 // Otherwise, let's check if there is a splat resource variable
800 // at the top level in here. We do this by doing a transform that
801 // replaces everything with a noop node unless its a variable
802 // access or concat. This should turn the AST into a flat tree
803 // of Concat(Noop, ...). If there are any variables left that are
804 // multi-access, then its still broken.
805 node = node.Accept(func(n ast.Node) ast.Node {
806 // If it is a concat or variable access, we allow it.
807 switch n.(type) {
808 case *ast.Output:
809 return n
810 case *ast.VariableAccess:
811 return n
812 }
813
814 // Otherwise, noop
815 return &noopNode{}
816 })
817
818 vars, err := DetectVariables(node)
819 if err != nil {
820 // Ignore it since this will be caught during parse. This
821 // actually probably should never happen by the time this
822 // is called, but its okay.
823 return
824 }
825
826 for _, v := range vars {
827 rv, ok := v.(*ResourceVariable)
828 if !ok {
829 return
830 }
831
832 if rv.Multi && rv.Index == -1 {
833 *errs = append(*errs, fmt.Errorf(
834 "%s: use of the splat ('*') operator must be wrapped in a list declaration",
835 source))
836 }
837 }
838 }
839}
840
841func (c *Config) validateDependsOn( 779func (c *Config) validateDependsOn(
842 n string, 780 n string,
843 v []string, 781 v []string,
diff --git a/vendor/github.com/hashicorp/terraform/config/interpolate_funcs.go b/vendor/github.com/hashicorp/terraform/config/interpolate_funcs.go
index f1f97b0..7b7b3f2 100644
--- a/vendor/github.com/hashicorp/terraform/config/interpolate_funcs.go
+++ b/vendor/github.com/hashicorp/terraform/config/interpolate_funcs.go
@@ -24,6 +24,7 @@ import (
24 "github.com/hashicorp/hil" 24 "github.com/hashicorp/hil"
25 "github.com/hashicorp/hil/ast" 25 "github.com/hashicorp/hil/ast"
26 "github.com/mitchellh/go-homedir" 26 "github.com/mitchellh/go-homedir"
27 "golang.org/x/crypto/bcrypt"
27) 28)
28 29
29// stringSliceToVariableValue converts a string slice into the value 30// stringSliceToVariableValue converts a string slice into the value
@@ -59,6 +60,7 @@ func Funcs() map[string]ast.Function {
59 "base64encode": interpolationFuncBase64Encode(), 60 "base64encode": interpolationFuncBase64Encode(),
60 "base64sha256": interpolationFuncBase64Sha256(), 61 "base64sha256": interpolationFuncBase64Sha256(),
61 "base64sha512": interpolationFuncBase64Sha512(), 62 "base64sha512": interpolationFuncBase64Sha512(),
63 "bcrypt": interpolationFuncBcrypt(),
62 "ceil": interpolationFuncCeil(), 64 "ceil": interpolationFuncCeil(),
63 "chomp": interpolationFuncChomp(), 65 "chomp": interpolationFuncChomp(),
64 "cidrhost": interpolationFuncCidrHost(), 66 "cidrhost": interpolationFuncCidrHost(),
@@ -89,6 +91,7 @@ func Funcs() map[string]ast.Function {
89 "merge": interpolationFuncMerge(), 91 "merge": interpolationFuncMerge(),
90 "min": interpolationFuncMin(), 92 "min": interpolationFuncMin(),
91 "pathexpand": interpolationFuncPathExpand(), 93 "pathexpand": interpolationFuncPathExpand(),
94 "pow": interpolationFuncPow(),
92 "uuid": interpolationFuncUUID(), 95 "uuid": interpolationFuncUUID(),
93 "replace": interpolationFuncReplace(), 96 "replace": interpolationFuncReplace(),
94 "sha1": interpolationFuncSha1(), 97 "sha1": interpolationFuncSha1(),
@@ -394,6 +397,17 @@ func interpolationFuncConcat() ast.Function {
394 } 397 }
395} 398}
396 399
400// interpolationFuncPow returns base x exponential of y.
401func interpolationFuncPow() ast.Function {
402 return ast.Function{
403 ArgTypes: []ast.Type{ast.TypeFloat, ast.TypeFloat},
404 ReturnType: ast.TypeFloat,
405 Callback: func(args []interface{}) (interface{}, error) {
406 return math.Pow(args[0].(float64), args[1].(float64)), nil
407 },
408 }
409}
410
397// interpolationFuncFile implements the "file" function that allows 411// interpolationFuncFile implements the "file" function that allows
398// loading contents from a file. 412// loading contents from a file.
399func interpolationFuncFile() ast.Function { 413func interpolationFuncFile() ast.Function {
@@ -1310,6 +1324,40 @@ func interpolationFuncBase64Sha512() ast.Function {
1310 } 1324 }
1311} 1325}
1312 1326
1327func interpolationFuncBcrypt() ast.Function {
1328 return ast.Function{
1329 ArgTypes: []ast.Type{ast.TypeString},
1330 Variadic: true,
1331 VariadicType: ast.TypeString,
1332 ReturnType: ast.TypeString,
1333 Callback: func(args []interface{}) (interface{}, error) {
1334 defaultCost := 10
1335
1336 if len(args) > 1 {
1337 costStr := args[1].(string)
1338 cost, err := strconv.Atoi(costStr)
1339 if err != nil {
1340 return "", err
1341 }
1342
1343 defaultCost = cost
1344 }
1345
1346 if len(args) > 2 {
1347 return "", fmt.Errorf("bcrypt() takes no more than two arguments")
1348 }
1349
1350 input := args[0].(string)
1351 out, err := bcrypt.GenerateFromPassword([]byte(input), defaultCost)
1352 if err != nil {
1353 return "", fmt.Errorf("error occured generating password %s", err.Error())
1354 }
1355
1356 return string(out), nil
1357 },
1358 }
1359}
1360
1313func interpolationFuncUUID() ast.Function { 1361func interpolationFuncUUID() ast.Function {
1314 return ast.Function{ 1362 return ast.Function{
1315 ArgTypes: []ast.Type{}, 1363 ArgTypes: []ast.Type{},
diff --git a/vendor/github.com/hashicorp/terraform/dag/set.go b/vendor/github.com/hashicorp/terraform/dag/set.go
index 3929c9d..92b4215 100644
--- a/vendor/github.com/hashicorp/terraform/dag/set.go
+++ b/vendor/github.com/hashicorp/terraform/dag/set.go
@@ -81,6 +81,20 @@ func (s *Set) Difference(other *Set) *Set {
81 return result 81 return result
82} 82}
83 83
84// Filter returns a set that contains the elements from the receiver
85// where the given callback returns true.
86func (s *Set) Filter(cb func(interface{}) bool) *Set {
87 result := new(Set)
88
89 for _, v := range s.m {
90 if cb(v) {
91 result.Add(v)
92 }
93 }
94
95 return result
96}
97
84// Len is the number of items in the set. 98// Len is the number of items in the set.
85func (s *Set) Len() int { 99func (s *Set) Len() int {
86 if s == nil { 100 if s == nil {
diff --git a/vendor/github.com/hashicorp/terraform/helper/acctest/acctest.go b/vendor/github.com/hashicorp/terraform/helper/acctest/acctest.go
deleted file mode 100644
index 9d31031..0000000
--- a/vendor/github.com/hashicorp/terraform/helper/acctest/acctest.go
+++ /dev/null
@@ -1,2 +0,0 @@
1// Package acctest contains for Terraform Acceptance Tests
2package acctest
diff --git a/vendor/github.com/hashicorp/terraform/helper/acctest/random.go b/vendor/github.com/hashicorp/terraform/helper/acctest/random.go
deleted file mode 100644
index 3ddc078..0000000
--- a/vendor/github.com/hashicorp/terraform/helper/acctest/random.go
+++ /dev/null
@@ -1,93 +0,0 @@
1package acctest
2
3import (
4 "bufio"
5 "bytes"
6 crand "crypto/rand"
7 "crypto/rsa"
8 "crypto/x509"
9 "encoding/pem"
10 "fmt"
11 "math/rand"
12 "strings"
13 "time"
14
15 "golang.org/x/crypto/ssh"
16)
17
18// Helpers for generating random tidbits for use in identifiers to prevent
19// collisions in acceptance tests.
20
21// RandInt generates a random integer
22func RandInt() int {
23 reseed()
24 return rand.New(rand.NewSource(time.Now().UnixNano())).Int()
25}
26
27// RandomWithPrefix is used to generate a unique name with a prefix, for
28// randomizing names in acceptance tests
29func RandomWithPrefix(name string) string {
30 reseed()
31 return fmt.Sprintf("%s-%d", name, rand.New(rand.NewSource(time.Now().UnixNano())).Int())
32}
33
34func RandIntRange(min int, max int) int {
35 reseed()
36 source := rand.New(rand.NewSource(time.Now().UnixNano()))
37 rangeMax := max - min
38
39 return int(source.Int31n(int32(rangeMax)))
40}
41
42// RandString generates a random alphanumeric string of the length specified
43func RandString(strlen int) string {
44 return RandStringFromCharSet(strlen, CharSetAlphaNum)
45}
46
47// RandStringFromCharSet generates a random string by selecting characters from
48// the charset provided
49func RandStringFromCharSet(strlen int, charSet string) string {
50 reseed()
51 result := make([]byte, strlen)
52 for i := 0; i < strlen; i++ {
53 result[i] = charSet[rand.Intn(len(charSet))]
54 }
55 return string(result)
56}
57
58// RandSSHKeyPair generates a public and private SSH key pair. The public key is
59// returned in OpenSSH format, and the private key is PEM encoded.
60func RandSSHKeyPair(comment string) (string, string, error) {
61 privateKey, err := rsa.GenerateKey(crand.Reader, 1024)
62 if err != nil {
63 return "", "", err
64 }
65
66 var privateKeyBuffer bytes.Buffer
67 privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
68 if err := pem.Encode(bufio.NewWriter(&privateKeyBuffer), privateKeyPEM); err != nil {
69 return "", "", err
70 }
71
72 publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey)
73 if err != nil {
74 return "", "", err
75 }
76 keyMaterial := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(publicKey)))
77 return fmt.Sprintf("%s %s", keyMaterial, comment), privateKeyBuffer.String(), nil
78}
79
80// Seeds random with current timestamp
81func reseed() {
82 rand.Seed(time.Now().UTC().UnixNano())
83}
84
85const (
86 // CharSetAlphaNum is the alphanumeric character set for use with
87 // RandStringFromCharSet
88 CharSetAlphaNum = "abcdefghijklmnopqrstuvwxyz012346789"
89
90 // CharSetAlpha is the alphabetical character set for use with
91 // RandStringFromCharSet
92 CharSetAlpha = "abcdefghijklmnopqrstuvwxyz"
93)
diff --git a/vendor/github.com/hashicorp/terraform/helper/acctest/remotetests.go b/vendor/github.com/hashicorp/terraform/helper/acctest/remotetests.go
deleted file mode 100644
index 87c60b8..0000000
--- a/vendor/github.com/hashicorp/terraform/helper/acctest/remotetests.go
+++ /dev/null
@@ -1,27 +0,0 @@
1package acctest
2
3import (
4 "net/http"
5 "os"
6 "testing"
7)
8
9// SkipRemoteTestsEnvVar is an environment variable that can be set by a user
10// running the tests in an environment with limited network connectivity. By
11// default, tests requiring internet connectivity make an effort to skip if no
12// internet is available, but in some cases the smoke test will pass even
13// though the test should still be skipped.
14const SkipRemoteTestsEnvVar = "TF_SKIP_REMOTE_TESTS"
15
16// RemoteTestPrecheck is meant to be run by any unit test that requires
17// outbound internet connectivity. The test will be skipped if it's
18// unavailable.
19func RemoteTestPrecheck(t *testing.T) {
20 if os.Getenv(SkipRemoteTestsEnvVar) != "" {
21 t.Skipf("skipping test, %s was set", SkipRemoteTestsEnvVar)
22 }
23
24 if _, err := http.Get("http://google.com"); err != nil {
25 t.Skipf("skipping, internet seems to not be available: %s", err)
26 }
27}
diff --git a/vendor/github.com/hashicorp/terraform/helper/resource/testing.go b/vendor/github.com/hashicorp/terraform/helper/resource/testing.go
index 04367c5..ebdbde2 100644
--- a/vendor/github.com/hashicorp/terraform/helper/resource/testing.go
+++ b/vendor/github.com/hashicorp/terraform/helper/resource/testing.go
@@ -1,6 +1,7 @@
1package resource 1package resource
2 2
3import ( 3import (
4 "flag"
4 "fmt" 5 "fmt"
5 "io" 6 "io"
6 "io/ioutil" 7 "io/ioutil"
@@ -20,6 +21,153 @@ import (
20 "github.com/hashicorp/terraform/terraform" 21 "github.com/hashicorp/terraform/terraform"
21) 22)
22 23
24// flagSweep is a flag available when running tests on the command line. It
25// contains a comma seperated list of regions to for the sweeper functions to
26// run in. This flag bypasses the normal Test path and instead runs functions designed to
27// clean up any leaked resources a testing environment could have created. It is
28// a best effort attempt, and relies on Provider authors to implement "Sweeper"
29// methods for resources.
30
31// Adding Sweeper methods with AddTestSweepers will
32// construct a list of sweeper funcs to be called here. We iterate through
33// regions provided by the sweep flag, and for each region we iterate through the
34// tests, and exit on any errors. At time of writing, sweepers are ran
35// sequentially, however they can list dependencies to be ran first. We track
36// the sweepers that have been ran, so as to not run a sweeper twice for a given
37// region.
38//
39// WARNING:
40// Sweepers are designed to be destructive. You should not use the -sweep flag
41// in any environment that is not strictly a test environment. Resources will be
42// destroyed.
43
44var flagSweep = flag.String("sweep", "", "List of Regions to run available Sweepers")
45var flagSweepRun = flag.String("sweep-run", "", "Comma seperated list of Sweeper Tests to run")
46var sweeperFuncs map[string]*Sweeper
47
48// map of sweepers that have ran, and the success/fail status based on any error
49// raised
50var sweeperRunList map[string]bool
51
52// type SweeperFunc is a signature for a function that acts as a sweeper. It
53// accepts a string for the region that the sweeper is to be ran in. This
54// function must be able to construct a valid client for that region.
55type SweeperFunc func(r string) error
56
57type Sweeper struct {
58 // Name for sweeper. Must be unique to be ran by the Sweeper Runner
59 Name string
60
61 // Dependencies list the const names of other Sweeper functions that must be ran
62 // prior to running this Sweeper. This is an ordered list that will be invoked
63 // recursively at the helper/resource level
64 Dependencies []string
65
66 // Sweeper function that when invoked sweeps the Provider of specific
67 // resources
68 F SweeperFunc
69}
70
71func init() {
72 sweeperFuncs = make(map[string]*Sweeper)
73}
74
75// AddTestSweepers function adds a given name and Sweeper configuration
76// pair to the internal sweeperFuncs map. Invoke this function to register a
77// resource sweeper to be available for running when the -sweep flag is used
78// with `go test`. Sweeper names must be unique to help ensure a given sweeper
79// is only ran once per run.
80func AddTestSweepers(name string, s *Sweeper) {
81 if _, ok := sweeperFuncs[name]; ok {
82 log.Fatalf("[ERR] Error adding (%s) to sweeperFuncs: function already exists in map", name)
83 }
84
85 sweeperFuncs[name] = s
86}
87
88func TestMain(m *testing.M) {
89 flag.Parse()
90 if *flagSweep != "" {
91 // parse flagSweep contents for regions to run
92 regions := strings.Split(*flagSweep, ",")
93
94 // get filtered list of sweepers to run based on sweep-run flag
95 sweepers := filterSweepers(*flagSweepRun, sweeperFuncs)
96 for _, region := range regions {
97 region = strings.TrimSpace(region)
98 // reset sweeperRunList for each region
99 sweeperRunList = map[string]bool{}
100
101 log.Printf("[DEBUG] Running Sweepers for region (%s):\n", region)
102 for _, sweeper := range sweepers {
103 if err := runSweeperWithRegion(region, sweeper); err != nil {
104 log.Fatalf("[ERR] error running (%s): %s", sweeper.Name, err)
105 }
106 }
107
108 log.Printf("Sweeper Tests ran:\n")
109 for s, _ := range sweeperRunList {
110 fmt.Printf("\t- %s\n", s)
111 }
112 }
113 } else {
114 os.Exit(m.Run())
115 }
116}
117
118// filterSweepers takes a comma seperated string listing the names of sweepers
119// to be ran, and returns a filtered set from the list of all of sweepers to
120// run based on the names given.
121func filterSweepers(f string, source map[string]*Sweeper) map[string]*Sweeper {
122 filterSlice := strings.Split(strings.ToLower(f), ",")
123 if len(filterSlice) == 1 && filterSlice[0] == "" {
124 // if the filter slice is a single element of "" then no sweeper list was
125 // given, so just return the full list
126 return source
127 }
128
129 sweepers := make(map[string]*Sweeper)
130 for name, sweeper := range source {
131 for _, s := range filterSlice {
132 if strings.Contains(strings.ToLower(name), s) {
133 sweepers[name] = sweeper
134 }
135 }
136 }
137 return sweepers
138}
139
140// runSweeperWithRegion recieves a sweeper and a region, and recursively calls
141// itself with that region for every dependency found for that sweeper. If there
142// are no dependencies, invoke the contained sweeper fun with the region, and
143// add the success/fail status to the sweeperRunList.
144func runSweeperWithRegion(region string, s *Sweeper) error {
145 for _, dep := range s.Dependencies {
146 if depSweeper, ok := sweeperFuncs[dep]; ok {
147 log.Printf("[DEBUG] Sweeper (%s) has dependency (%s), running..", s.Name, dep)
148 if err := runSweeperWithRegion(region, depSweeper); err != nil {
149 return err
150 }
151 } else {
152 log.Printf("[DEBUG] Sweeper (%s) has dependency (%s), but that sweeper was not found", s.Name, dep)
153 }
154 }
155
156 if _, ok := sweeperRunList[s.Name]; ok {
157 log.Printf("[DEBUG] Sweeper (%s) already ran in region (%s)", s.Name, region)
158 return nil
159 }
160
161 runE := s.F(region)
162 if runE == nil {
163 sweeperRunList[s.Name] = true
164 } else {
165 sweeperRunList[s.Name] = false
166 }
167
168 return runE
169}
170
23const TestEnvVar = "TF_ACC" 171const TestEnvVar = "TF_ACC"
24 172
25// TestProvider can be implemented by any ResourceProvider to provide custom 173// TestProvider can be implemented by any ResourceProvider to provide custom
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go b/vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go
index c1564a2..856c675 100644
--- a/vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go
+++ b/vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go
@@ -41,6 +41,10 @@ type Provisioner struct {
41 // information. 41 // information.
42 ApplyFunc func(ctx context.Context) error 42 ApplyFunc func(ctx context.Context) error
43 43
44 // ValidateFunc is a function for extended validation. This is optional
45 // and should be used when individual field validation is not enough.
46 ValidateFunc func(*ResourceData) ([]string, []error)
47
44 stopCtx context.Context 48 stopCtx context.Context
45 stopCtxCancel context.CancelFunc 49 stopCtxCancel context.CancelFunc
46 stopOnce sync.Once 50 stopOnce sync.Once
@@ -117,8 +121,30 @@ func (p *Provisioner) Stop() error {
117 return nil 121 return nil
118} 122}
119 123
120func (p *Provisioner) Validate(c *terraform.ResourceConfig) ([]string, []error) { 124func (p *Provisioner) Validate(config *terraform.ResourceConfig) ([]string, []error) {
121 return schemaMap(p.Schema).Validate(c) 125 if err := p.InternalValidate(); err != nil {
126 return nil, []error{fmt.Errorf(
127 "Internal validation of the provisioner failed! This is always a bug\n"+
128 "with the provisioner itself, and not a user issue. Please report\n"+
129 "this bug:\n\n%s", err)}
130 }
131 w := []string{}
132 e := []error{}
133 if p.Schema != nil {
134 w2, e2 := schemaMap(p.Schema).Validate(config)
135 w = append(w, w2...)
136 e = append(e, e2...)
137 }
138 if p.ValidateFunc != nil {
139 data := &ResourceData{
140 schema: p.Schema,
141 config: config,
142 }
143 w2, e2 := p.ValidateFunc(data)
144 w = append(w, w2...)
145 e = append(e, e2...)
146 }
147 return w, e
122} 148}
123 149
124// Apply implementation of terraform.ResourceProvisioner interface. 150// Apply implementation of terraform.ResourceProvisioner interface.
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/schema.go b/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
index 32d1721..632672a 100644
--- a/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
+++ b/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
@@ -1373,8 +1373,8 @@ func (m schemaMap) validateObject(
1373 k string, 1373 k string,
1374 schema map[string]*Schema, 1374 schema map[string]*Schema,
1375 c *terraform.ResourceConfig) ([]string, []error) { 1375 c *terraform.ResourceConfig) ([]string, []error) {
1376 raw, _ := c.GetRaw(k) 1376 raw, _ := c.Get(k)
1377 if _, ok := raw.(map[string]interface{}); !ok { 1377 if _, ok := raw.(map[string]interface{}); !ok && !c.IsComputed(k) {
1378 return nil, []error{fmt.Errorf( 1378 return nil, []error{fmt.Errorf(
1379 "%s: expected object, got %s", 1379 "%s: expected object, got %s",
1380 k, reflect.ValueOf(raw).Kind())} 1380 k, reflect.ValueOf(raw).Kind())}
diff --git a/vendor/github.com/hashicorp/terraform/helper/structure/expand_json.go b/vendor/github.com/hashicorp/terraform/helper/structure/expand_json.go
deleted file mode 100644
index b3eb90f..0000000
--- a/vendor/github.com/hashicorp/terraform/helper/structure/expand_json.go
+++ /dev/null
@@ -1,11 +0,0 @@
1package structure
2
3import "encoding/json"
4
5func ExpandJsonFromString(jsonString string) (map[string]interface{}, error) {
6 var result map[string]interface{}
7
8 err := json.Unmarshal([]byte(jsonString), &result)
9
10 return result, err
11}
diff --git a/vendor/github.com/hashicorp/terraform/helper/structure/flatten_json.go b/vendor/github.com/hashicorp/terraform/helper/structure/flatten_json.go
deleted file mode 100644
index 578ad2e..0000000
--- a/vendor/github.com/hashicorp/terraform/helper/structure/flatten_json.go
+++ /dev/null
@@ -1,16 +0,0 @@
1package structure
2
3import "encoding/json"
4
5func FlattenJsonToString(input map[string]interface{}) (string, error) {
6 if len(input) == 0 {
7 return "", nil
8 }
9
10 result, err := json.Marshal(input)
11 if err != nil {
12 return "", err
13 }
14
15 return string(result), nil
16}
diff --git a/vendor/github.com/hashicorp/terraform/helper/structure/normalize_json.go b/vendor/github.com/hashicorp/terraform/helper/structure/normalize_json.go
deleted file mode 100644
index 3256b47..0000000
--- a/vendor/github.com/hashicorp/terraform/helper/structure/normalize_json.go
+++ /dev/null
@@ -1,24 +0,0 @@
1package structure
2
3import "encoding/json"
4
5// Takes a value containing JSON string and passes it through
6// the JSON parser to normalize it, returns either a parsing
7// error or normalized JSON string.
8func NormalizeJsonString(jsonString interface{}) (string, error) {
9 var j interface{}
10
11 if jsonString == nil || jsonString.(string) == "" {
12 return "", nil
13 }
14
15 s := jsonString.(string)
16
17 err := json.Unmarshal([]byte(s), &j)
18 if err != nil {
19 return s, err
20 }
21
22 bytes, _ := json.Marshal(j)
23 return string(bytes[:]), nil
24}
diff --git a/vendor/github.com/hashicorp/terraform/helper/structure/suppress_json_diff.go b/vendor/github.com/hashicorp/terraform/helper/structure/suppress_json_diff.go
deleted file mode 100644
index 46f794a..0000000
--- a/vendor/github.com/hashicorp/terraform/helper/structure/suppress_json_diff.go
+++ /dev/null
@@ -1,21 +0,0 @@
1package structure
2
3import (
4 "reflect"
5
6 "github.com/hashicorp/terraform/helper/schema"
7)
8
9func SuppressJsonDiff(k, old, new string, d *schema.ResourceData) bool {
10 oldMap, err := ExpandJsonFromString(old)
11 if err != nil {
12 return false
13 }
14
15 newMap, err := ExpandJsonFromString(new)
16 if err != nil {
17 return false
18 }
19
20 return reflect.DeepEqual(oldMap, newMap)
21}
diff --git a/vendor/github.com/hashicorp/terraform/helper/validation/validation.go b/vendor/github.com/hashicorp/terraform/helper/validation/validation.go
deleted file mode 100644
index 7b894f5..0000000
--- a/vendor/github.com/hashicorp/terraform/helper/validation/validation.go
+++ /dev/null
@@ -1,108 +0,0 @@
1package validation
2
3import (
4 "fmt"
5 "net"
6 "strings"
7
8 "github.com/hashicorp/terraform/helper/schema"
9 "github.com/hashicorp/terraform/helper/structure"
10)
11
12// IntBetween returns a SchemaValidateFunc which tests if the provided value
13// is of type int and is between min and max (inclusive)
14func IntBetween(min, max int) schema.SchemaValidateFunc {
15 return func(i interface{}, k string) (s []string, es []error) {
16 v, ok := i.(int)
17 if !ok {
18 es = append(es, fmt.Errorf("expected type of %s to be int", k))
19 return
20 }
21
22 if v < min || v > max {
23 es = append(es, fmt.Errorf("expected %s to be in the range (%d - %d), got %d", k, min, max, v))
24 return
25 }
26
27 return
28 }
29}
30
31// StringInSlice returns a SchemaValidateFunc which tests if the provided value
32// is of type string and matches the value of an element in the valid slice
33// will test with in lower case if ignoreCase is true
34func StringInSlice(valid []string, ignoreCase bool) schema.SchemaValidateFunc {
35 return func(i interface{}, k string) (s []string, es []error) {
36 v, ok := i.(string)
37 if !ok {
38 es = append(es, fmt.Errorf("expected type of %s to be string", k))
39 return
40 }
41
42 for _, str := range valid {
43 if v == str || (ignoreCase && strings.ToLower(v) == strings.ToLower(str)) {
44 return
45 }
46 }
47
48 es = append(es, fmt.Errorf("expected %s to be one of %v, got %s", k, valid, v))
49 return
50 }
51}
52
53// StringLenBetween returns a SchemaValidateFunc which tests if the provided value
54// is of type string and has length between min and max (inclusive)
55func StringLenBetween(min, max int) schema.SchemaValidateFunc {
56 return func(i interface{}, k string) (s []string, es []error) {
57 v, ok := i.(string)
58 if !ok {
59 es = append(es, fmt.Errorf("expected type of %s to be string", k))
60 return
61 }
62 if len(v) < min || len(v) > max {
63 es = append(es, fmt.Errorf("expected length of %s to be in the range (%d - %d), got %s", k, min, max, v))
64 }
65 return
66 }
67}
68
69// CIDRNetwork returns a SchemaValidateFunc which tests if the provided value
70// is of type string, is in valid CIDR network notation, and has significant bits between min and max (inclusive)
71func CIDRNetwork(min, max int) schema.SchemaValidateFunc {
72 return func(i interface{}, k string) (s []string, es []error) {
73 v, ok := i.(string)
74 if !ok {
75 es = append(es, fmt.Errorf("expected type of %s to be string", k))
76 return
77 }
78
79 _, ipnet, err := net.ParseCIDR(v)
80 if err != nil {
81 es = append(es, fmt.Errorf(
82 "expected %s to contain a valid CIDR, got: %s with err: %s", k, v, err))
83 return
84 }
85
86 if ipnet == nil || v != ipnet.String() {
87 es = append(es, fmt.Errorf(
88 "expected %s to contain a valid network CIDR, expected %s, got %s",
89 k, ipnet, v))
90 }
91
92 sigbits, _ := ipnet.Mask.Size()
93 if sigbits < min || sigbits > max {
94 es = append(es, fmt.Errorf(
95 "expected %q to contain a network CIDR with between %d and %d significant bits, got: %d",
96 k, min, max, sigbits))
97 }
98
99 return
100 }
101}
102
103func ValidateJsonString(v interface{}, k string) (ws []string, errors []error) {
104 if _, err := structure.NormalizeJsonString(v); err != nil {
105 errors = append(errors, fmt.Errorf("%q contains an invalid JSON: %s", k, err))
106 }
107 return
108}
diff --git a/vendor/github.com/hashicorp/terraform/terraform/graph_builder_refresh.go b/vendor/github.com/hashicorp/terraform/terraform/graph_builder_refresh.go
index 88ae338..0634f96 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/graph_builder_refresh.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/graph_builder_refresh.go
@@ -1,6 +1,8 @@
1package terraform 1package terraform
2 2
3import ( 3import (
4 "log"
5
4 "github.com/hashicorp/terraform/config" 6 "github.com/hashicorp/terraform/config"
5 "github.com/hashicorp/terraform/config/module" 7 "github.com/hashicorp/terraform/config/module"
6 "github.com/hashicorp/terraform/dag" 8 "github.com/hashicorp/terraform/dag"
@@ -56,8 +58,16 @@ func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
56 } 58 }
57 } 59 }
58 60
59 concreteResource := func(a *NodeAbstractResource) dag.Vertex { 61 concreteManagedResource := func(a *NodeAbstractResource) dag.Vertex {
60 return &NodeRefreshableResource{ 62 return &NodeRefreshableManagedResource{
63 NodeAbstractCountResource: &NodeAbstractCountResource{
64 NodeAbstractResource: a,
65 },
66 }
67 }
68
69 concreteManagedResourceInstance := func(a *NodeAbstractResource) dag.Vertex {
70 return &NodeRefreshableManagedResourceInstance{
61 NodeAbstractResource: a, 71 NodeAbstractResource: a,
62 } 72 }
63 } 73 }
@@ -71,13 +81,25 @@ func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
71 } 81 }
72 82
73 steps := []GraphTransformer{ 83 steps := []GraphTransformer{
74 // Creates all the resources represented in the state 84 // Creates all the managed resources that aren't in the state, but only if
75 &StateTransformer{ 85 // we have a state already. No resources in state means there's not
76 Concrete: concreteResource, 86 // anything to refresh.
77 State: b.State, 87 func() GraphTransformer {
78 }, 88 if b.State.HasResources() {
79 89 return &ConfigTransformer{
80 // Creates all the data resources that aren't in the state 90 Concrete: concreteManagedResource,
91 Module: b.Module,
92 Unique: true,
93 ModeFilter: true,
94 Mode: config.ManagedResourceMode,
95 }
96 }
97 log.Println("[TRACE] No managed resources in state during refresh, skipping managed resource transformer")
98 return nil
99 }(),
100
101 // Creates all the data resources that aren't in the state. This will also
102 // add any orphans from scaling in as destroy nodes.
81 &ConfigTransformer{ 103 &ConfigTransformer{
82 Concrete: concreteDataResource, 104 Concrete: concreteDataResource,
83 Module: b.Module, 105 Module: b.Module,
@@ -86,6 +108,15 @@ func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
86 Mode: config.DataResourceMode, 108 Mode: config.DataResourceMode,
87 }, 109 },
88 110
111 // Add any fully-orphaned resources from config (ones that have been
112 // removed completely, not ones that are just orphaned due to a scaled-in
113 // count.
114 &OrphanResourceTransformer{
115 Concrete: concreteManagedResourceInstance,
116 State: b.State,
117 Module: b.Module,
118 },
119
89 // Attach the state 120 // Attach the state
90 &AttachStateTransformer{State: b.State}, 121 &AttachStateTransformer{State: b.State},
91 122
diff --git a/vendor/github.com/hashicorp/terraform/terraform/interpolate.go b/vendor/github.com/hashicorp/terraform/terraform/interpolate.go
index 19dcf21..0def295 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/interpolate.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/interpolate.go
@@ -731,6 +731,19 @@ func (i *Interpolater) resourceCountMax(
731 return count, nil 731 return count, nil
732 } 732 }
733 733
734 // If we have no module state in the apply walk, that suggests we've hit
735 // a rather awkward edge-case: the resource this variable refers to
736 // has count = 0 and is the only resource processed so far on this walk,
737 // and so we've ended up not creating any resource states yet. We don't
738 // create a module state until the first resource is written into it,
739 // so the module state doesn't exist when we get here.
740 //
741 // In this case we act as we would if we had been passed a module
742 // with an empty resource state map.
743 if ms == nil {
744 return 0, nil
745 }
746
734 // We need to determine the list of resource keys to get values from. 747 // We need to determine the list of resource keys to get values from.
735 // This needs to be sorted so the order is deterministic. We used to 748 // This needs to be sorted so the order is deterministic. We used to
736 // use "cr.Count()" but that doesn't work if the count is interpolated 749 // use "cr.Count()" but that doesn't work if the count is interpolated
diff --git a/vendor/github.com/hashicorp/terraform/terraform/node_data_refresh.go b/vendor/github.com/hashicorp/terraform/terraform/node_data_refresh.go
index d504c89..45129b3 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/node_data_refresh.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/node_data_refresh.go
@@ -33,6 +33,17 @@ func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, er
33 } 33 }
34 } 34 }
35 35
36 // We also need a destroyable resource for orphans that are a result of a
37 // scaled-in count.
38 concreteResourceDestroyable := func(a *NodeAbstractResource) dag.Vertex {
39 // Add the config since we don't do that via transforms
40 a.Config = n.Config
41
42 return &NodeDestroyableDataResource{
43 NodeAbstractResource: a,
44 }
45 }
46
36 // Start creating the steps 47 // Start creating the steps
37 steps := []GraphTransformer{ 48 steps := []GraphTransformer{
38 // Expand the count. 49 // Expand the count.
@@ -42,6 +53,15 @@ func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, er
42 Addr: n.ResourceAddr(), 53 Addr: n.ResourceAddr(),
43 }, 54 },
44 55
56 // Add the count orphans. As these are orphaned refresh nodes, we add them
57 // directly as NodeDestroyableDataResource.
58 &OrphanResourceCountTransformer{
59 Concrete: concreteResourceDestroyable,
60 Count: count,
61 Addr: n.ResourceAddr(),
62 State: state,
63 },
64
45 // Attach the state 65 // Attach the state
46 &AttachStateTransformer{State: state}, 66 &AttachStateTransformer{State: state},
47 67
diff --git a/vendor/github.com/hashicorp/terraform/terraform/node_output.go b/vendor/github.com/hashicorp/terraform/terraform/node_output.go
index e28e6f0..9017a63 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/node_output.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/node_output.go
@@ -5,6 +5,7 @@ import (
5 "strings" 5 "strings"
6 6
7 "github.com/hashicorp/terraform/config" 7 "github.com/hashicorp/terraform/config"
8 "github.com/hashicorp/terraform/dag"
8) 9)
9 10
10// NodeApplyableOutput represents an output that is "applyable": 11// NodeApplyableOutput represents an output that is "applyable":
@@ -35,6 +36,14 @@ func (n *NodeApplyableOutput) RemoveIfNotTargeted() bool {
35 return true 36 return true
36} 37}
37 38
39// GraphNodeTargetDownstream
40func (n *NodeApplyableOutput) TargetDownstream(targetedDeps, untargetedDeps *dag.Set) bool {
41 // If any of the direct dependencies of an output are targeted then
42 // the output must always be targeted as well, so its value will always
43 // be up-to-date at the completion of an apply walk.
44 return true
45}
46
38// GraphNodeReferenceable 47// GraphNodeReferenceable
39func (n *NodeApplyableOutput) ReferenceableName() []string { 48func (n *NodeApplyableOutput) ReferenceableName() []string {
40 name := fmt.Sprintf("output.%s", n.Config.Name) 49 name := fmt.Sprintf("output.%s", n.Config.Name)
diff --git a/vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go b/vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go
index 3a44926..6ab9df7 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go
@@ -4,21 +4,99 @@ import (
4 "fmt" 4 "fmt"
5 5
6 "github.com/hashicorp/terraform/config" 6 "github.com/hashicorp/terraform/config"
7 "github.com/hashicorp/terraform/dag"
7) 8)
8 9
9// NodeRefreshableResource represents a resource that is "applyable": 10// NodeRefreshableManagedResource represents a resource that is expanabled into
11// NodeRefreshableManagedResourceInstance. Resource count orphans are also added.
12type NodeRefreshableManagedResource struct {
13 *NodeAbstractCountResource
14}
15
16// GraphNodeDynamicExpandable
17func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
18 // Grab the state which we read
19 state, lock := ctx.State()
20 lock.RLock()
21 defer lock.RUnlock()
22
23 // Expand the resource count which must be available by now from EvalTree
24 count, err := n.Config.Count()
25 if err != nil {
26 return nil, err
27 }
28
29 // The concrete resource factory we'll use
30 concreteResource := func(a *NodeAbstractResource) dag.Vertex {
31 // Add the config and state since we don't do that via transforms
32 a.Config = n.Config
33
34 return &NodeRefreshableManagedResourceInstance{
35 NodeAbstractResource: a,
36 }
37 }
38
39 // Start creating the steps
40 steps := []GraphTransformer{
41 // Expand the count.
42 &ResourceCountTransformer{
43 Concrete: concreteResource,
44 Count: count,
45 Addr: n.ResourceAddr(),
46 },
47
48 // Switch up any node missing state to a plannable resource. This helps
49 // catch cases where data sources depend on the counts from this resource
50 // during a scale out.
51 &ResourceRefreshPlannableTransformer{
52 State: state,
53 },
54
55 // Add the count orphans to make sure these resources are accounted for
56 // during a scale in.
57 &OrphanResourceCountTransformer{
58 Concrete: concreteResource,
59 Count: count,
60 Addr: n.ResourceAddr(),
61 State: state,
62 },
63
64 // Attach the state
65 &AttachStateTransformer{State: state},
66
67 // Targeting
68 &TargetsTransformer{ParsedTargets: n.Targets},
69
70 // Connect references so ordering is correct
71 &ReferenceTransformer{},
72
73 // Make sure there is a single root
74 &RootTransformer{},
75 }
76
77 // Build the graph
78 b := &BasicGraphBuilder{
79 Steps: steps,
80 Validate: true,
81 Name: "NodeRefreshableManagedResource",
82 }
83
84 return b.Build(ctx.Path())
85}
86
87// NodeRefreshableManagedResourceInstance represents a resource that is "applyable":
10// it is ready to be applied and is represented by a diff. 88// it is ready to be applied and is represented by a diff.
11type NodeRefreshableResource struct { 89type NodeRefreshableManagedResourceInstance struct {
12 *NodeAbstractResource 90 *NodeAbstractResource
13} 91}
14 92
15// GraphNodeDestroyer 93// GraphNodeDestroyer
16func (n *NodeRefreshableResource) DestroyAddr() *ResourceAddress { 94func (n *NodeRefreshableManagedResourceInstance) DestroyAddr() *ResourceAddress {
17 return n.Addr 95 return n.Addr
18} 96}
19 97
20// GraphNodeEvalable 98// GraphNodeEvalable
21func (n *NodeRefreshableResource) EvalTree() EvalNode { 99func (n *NodeRefreshableManagedResourceInstance) EvalTree() EvalNode {
22 // Eval info is different depending on what kind of resource this is 100 // Eval info is different depending on what kind of resource this is
23 switch mode := n.Addr.Mode; mode { 101 switch mode := n.Addr.Mode; mode {
24 case config.ManagedResourceMode: 102 case config.ManagedResourceMode:
@@ -44,7 +122,7 @@ func (n *NodeRefreshableResource) EvalTree() EvalNode {
44 } 122 }
45} 123}
46 124
47func (n *NodeRefreshableResource) evalTreeManagedResource() EvalNode { 125func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalNode {
48 addr := n.NodeAbstractResource.Addr 126 addr := n.NodeAbstractResource.Addr
49 127
50 // stateId is the ID to put into the state 128 // stateId is the ID to put into the state
diff --git a/vendor/github.com/hashicorp/terraform/terraform/transform_resource_refresh_plannable.go b/vendor/github.com/hashicorp/terraform/terraform/transform_resource_refresh_plannable.go
new file mode 100644
index 0000000..35358a3
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/terraform/transform_resource_refresh_plannable.go
@@ -0,0 +1,55 @@
1package terraform
2
3import (
4 "fmt"
5 "log"
6)
7
8// ResourceRefreshPlannableTransformer is a GraphTransformer that replaces any
9// nodes that don't have state yet exist in config with
10// NodePlannableResourceInstance.
11//
12// This transformer is used when expanding count on managed resource nodes
13// during the refresh phase to ensure that data sources that have
14// interpolations that depend on resources existing in the graph can be walked
15// properly.
16type ResourceRefreshPlannableTransformer struct {
17 // The full global state.
18 State *State
19}
20
21// Transform implements GraphTransformer for
22// ResourceRefreshPlannableTransformer.
23func (t *ResourceRefreshPlannableTransformer) Transform(g *Graph) error {
24nextVertex:
25 for _, v := range g.Vertices() {
26 addr := v.(*NodeRefreshableManagedResourceInstance).Addr
27
28 // Find the state for this address, if there is one
29 filter := &StateFilter{State: t.State}
30 results, err := filter.Filter(addr.String())
31 if err != nil {
32 return err
33 }
34
35 // Check to see if we have a state for this resource. If we do, skip this
36 // node.
37 for _, result := range results {
38 if _, ok := result.Value.(*ResourceState); ok {
39 continue nextVertex
40 }
41 }
42 // If we don't, convert this resource to a NodePlannableResourceInstance node
43 // with all of the data we need to make it happen.
44 log.Printf("[TRACE] No state for %s, converting to NodePlannableResourceInstance", addr.String())
45 new := &NodePlannableResourceInstance{
46 NodeAbstractResource: v.(*NodeRefreshableManagedResourceInstance).NodeAbstractResource,
47 }
48 // Replace the node in the graph
49 if !g.Replace(v, new) {
50 return fmt.Errorf("ResourceRefreshPlannableTransformer: Could not replace node %#v with %#v", v, new)
51 }
52 }
53
54 return nil
55}
diff --git a/vendor/github.com/hashicorp/terraform/terraform/transform_targets.go b/vendor/github.com/hashicorp/terraform/terraform/transform_targets.go
index 225ac4b..125f9e3 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/transform_targets.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/transform_targets.go
@@ -15,6 +15,21 @@ type GraphNodeTargetable interface {
15 SetTargets([]ResourceAddress) 15 SetTargets([]ResourceAddress)
16} 16}
17 17
18// GraphNodeTargetDownstream is an interface for graph nodes that need to
19// be remain present under targeting if any of their dependencies are targeted.
20// TargetDownstream is called with the set of vertices that are direct
21// dependencies for the node, and it should return true if the node must remain
22// in the graph in support of those dependencies.
23//
24// This is used in situations where the dependency edges are representing an
25// ordering relationship but the dependency must still be visited if its
26// dependencies are visited. This is true for outputs, for example, since
27// they must get updated if any of their dependent resources get updated,
28// which would not normally be true if one of their dependencies were targeted.
29type GraphNodeTargetDownstream interface {
30 TargetDownstream(targeted, untargeted *dag.Set) bool
31}
32
18// TargetsTransformer is a GraphTransformer that, when the user specifies a 33// TargetsTransformer is a GraphTransformer that, when the user specifies a
19// list of resources to target, limits the graph to only those resources and 34// list of resources to target, limits the graph to only those resources and
20// their dependencies. 35// their dependencies.
@@ -84,7 +99,10 @@ func (t *TargetsTransformer) parseTargetAddresses() ([]ResourceAddress, error) {
84func (t *TargetsTransformer) selectTargetedNodes( 99func (t *TargetsTransformer) selectTargetedNodes(
85 g *Graph, addrs []ResourceAddress) (*dag.Set, error) { 100 g *Graph, addrs []ResourceAddress) (*dag.Set, error) {
86 targetedNodes := new(dag.Set) 101 targetedNodes := new(dag.Set)
87 for _, v := range g.Vertices() { 102
103 vertices := g.Vertices()
104
105 for _, v := range vertices {
88 if t.nodeIsTarget(v, addrs) { 106 if t.nodeIsTarget(v, addrs) {
89 targetedNodes.Add(v) 107 targetedNodes.Add(v)
90 108
@@ -112,6 +130,63 @@ func (t *TargetsTransformer) selectTargetedNodes(
112 } 130 }
113 } 131 }
114 132
133 // Handle nodes that need to be included if their dependencies are included.
134 // This requires multiple passes since we need to catch transitive
135 // dependencies if and only if they are via other nodes that also
136 // support TargetDownstream. For example:
137 // output -> output -> targeted-resource: both outputs need to be targeted
138 // output -> non-targeted-resource -> targeted-resource: output not targeted
139 //
140 // We'll keep looping until we stop targeting more nodes.
141 queue := targetedNodes.List()
142 for len(queue) > 0 {
143 vertices := queue
144 queue = nil // ready to append for next iteration if neccessary
145 for _, v := range vertices {
146 dependers := g.UpEdges(v)
147 if dependers == nil {
148 // indicates that there are no up edges for this node, so
149 // we have nothing to do here.
150 continue
151 }
152
153 dependers = dependers.Filter(func(dv interface{}) bool {
154 // Can ignore nodes that are already targeted
155 /*if targetedNodes.Include(dv) {
156 return false
157 }*/
158
159 _, ok := dv.(GraphNodeTargetDownstream)
160 return ok
161 })
162
163 if dependers.Len() == 0 {
164 continue
165 }
166
167 for _, dv := range dependers.List() {
168 if targetedNodes.Include(dv) {
169 // Already present, so nothing to do
170 continue
171 }
172
173 // We'll give the node some information about what it's
174 // depending on in case that informs its decision about whether
175 // it is safe to be targeted.
176 deps := g.DownEdges(v)
177 depsTargeted := deps.Intersection(targetedNodes)
178 depsUntargeted := deps.Difference(depsTargeted)
179
180 if dv.(GraphNodeTargetDownstream).TargetDownstream(depsTargeted, depsUntargeted) {
181 targetedNodes.Add(dv)
182 // Need to visit this node on the next pass to see if it
183 // has any transitive dependers.
184 queue = append(queue, dv)
185 }
186 }
187 }
188 }
189
115 return targetedNodes, nil 190 return targetedNodes, nil
116} 191}
117 192
diff --git a/vendor/github.com/hashicorp/terraform/terraform/user_agent.go b/vendor/github.com/hashicorp/terraform/terraform/user_agent.go
new file mode 100644
index 0000000..700be2a
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/terraform/user_agent.go
@@ -0,0 +1,14 @@
1package terraform
2
3import (
4 "fmt"
5 "runtime"
6)
7
8// The standard Terraform User-Agent format
9const UserAgent = "Terraform %s (%s)"
10
11// Generate a UserAgent string
12func UserAgentString() string {
13 return fmt.Sprintf(UserAgent, VersionString(), runtime.Version())
14}
diff --git a/vendor/github.com/hashicorp/terraform/terraform/version.go b/vendor/github.com/hashicorp/terraform/terraform/version.go
index 93fb429..cdfb8fb 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/version.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/version.go
@@ -7,12 +7,12 @@ import (
7) 7)
8 8
9// The main version number that is being run at the moment. 9// The main version number that is being run at the moment.
10const Version = "0.9.5" 10const Version = "0.9.8"
11 11
12// A pre-release marker for the version. If this is "" (empty string) 12// A pre-release marker for the version. If this is "" (empty string)
13// then it means that it is a final release. Otherwise, this is a pre-release 13// then it means that it is a final release. Otherwise, this is a pre-release
14// such as "dev" (in development), "beta", "rc1", etc. 14// such as "dev" (in development), "beta", "rc1", etc.
15const VersionPrerelease = "" 15var VersionPrerelease = ""
16 16
17// SemVersion is an instance of version.Version. This has the secondary 17// SemVersion is an instance of version.Version. This has the secondary
18// benefit of verifying during tests and init time that our version is a 18// benefit of verifying during tests and init time that our version is a