diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/shadow/closer.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/helper/shadow/closer.go | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/helper/shadow/closer.go b/vendor/github.com/hashicorp/terraform/helper/shadow/closer.go new file mode 100644 index 0000000..7edd5e7 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/helper/shadow/closer.go | |||
@@ -0,0 +1,80 @@ | |||
1 | package shadow | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "io" | ||
6 | "reflect" | ||
7 | |||
8 | "github.com/hashicorp/go-multierror" | ||
9 | "github.com/mitchellh/reflectwalk" | ||
10 | ) | ||
11 | |||
12 | // Close will close all shadow values within the given structure. | ||
13 | // | ||
14 | // This uses reflection to walk the structure, find all shadow elements, | ||
15 | // and close them. Currently this will only find struct fields that are | ||
16 | // shadow values, and not slice elements, etc. | ||
17 | func Close(v interface{}) error { | ||
18 | // We require a pointer so we can address the internal fields | ||
19 | val := reflect.ValueOf(v) | ||
20 | if val.Kind() != reflect.Ptr { | ||
21 | return fmt.Errorf("value must be a pointer") | ||
22 | } | ||
23 | |||
24 | // Walk and close | ||
25 | var w closeWalker | ||
26 | if err := reflectwalk.Walk(v, &w); err != nil { | ||
27 | return err | ||
28 | } | ||
29 | |||
30 | return w.Err | ||
31 | } | ||
32 | |||
33 | type closeWalker struct { | ||
34 | Err error | ||
35 | } | ||
36 | |||
37 | func (w *closeWalker) Struct(reflect.Value) error { | ||
38 | // Do nothing. We implement this for reflectwalk.StructWalker | ||
39 | return nil | ||
40 | } | ||
41 | |||
42 | func (w *closeWalker) StructField(f reflect.StructField, v reflect.Value) error { | ||
43 | // Not sure why this would be but lets avoid some panics | ||
44 | if !v.IsValid() { | ||
45 | return nil | ||
46 | } | ||
47 | |||
48 | // Empty for exported, so don't check unexported fields | ||
49 | if f.PkgPath != "" { | ||
50 | return nil | ||
51 | } | ||
52 | |||
53 | // Verify the io.Closer is in this package | ||
54 | typ := v.Type() | ||
55 | if typ.PkgPath() != "github.com/hashicorp/terraform/helper/shadow" { | ||
56 | return nil | ||
57 | } | ||
58 | |||
59 | // We're looking for an io.Closer | ||
60 | raw := v.Interface() | ||
61 | if raw == nil { | ||
62 | return nil | ||
63 | } | ||
64 | |||
65 | closer, ok := raw.(io.Closer) | ||
66 | if !ok && v.CanAddr() { | ||
67 | closer, ok = v.Addr().Interface().(io.Closer) | ||
68 | } | ||
69 | if !ok { | ||
70 | return reflectwalk.SkipEntry | ||
71 | } | ||
72 | |||
73 | // Close it | ||
74 | if err := closer.Close(); err != nil { | ||
75 | w.Err = multierror.Append(w.Err, err) | ||
76 | } | ||
77 | |||
78 | // Don't go into the struct field | ||
79 | return reflectwalk.SkipEntry | ||
80 | } | ||