8 "github.com/hashicorp/go-multierror"
9 "github.com/mitchellh/reflectwalk"
12 // Close will close all shadow values within the given structure.
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")
26 if err := reflectwalk.Walk(v, &w); err != nil {
33 type closeWalker struct {
37 func (w *closeWalker) Struct(reflect.Value) error {
38 // Do nothing. We implement this for reflectwalk.StructWalker
42 func (w *closeWalker) StructField(f reflect.StructField, v reflect.Value) error {
43 // Not sure why this would be but lets avoid some panics
48 // Empty for exported, so don't check unexported fields
53 // Verify the io.Closer is in this package
55 if typ.PkgPath() != "github.com/hashicorp/terraform/helper/shadow" {
59 // We're looking for an io.Closer
65 closer, ok := raw.(io.Closer)
66 if !ok && v.CanAddr() {
67 closer, ok = v.Addr().Interface().(io.Closer)
70 return reflectwalk.SkipEntry
74 if err := closer.Close(); err != nil {
75 w.Err = multierror.Append(w.Err, err)
78 // Don't go into the struct field
79 return reflectwalk.SkipEntry