github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/terraform/data_source_state.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/hashicorp/terraform/backend" 9 backendinit "github.com/hashicorp/terraform/backend/init" 10 "github.com/hashicorp/terraform/config" 11 "github.com/hashicorp/terraform/helper/schema" 12 "github.com/hashicorp/terraform/terraform" 13 ) 14 15 func dataSourceRemoteState() *schema.Resource { 16 return &schema.Resource{ 17 Read: dataSourceRemoteStateRead, 18 19 Schema: map[string]*schema.Schema{ 20 "backend": { 21 Type: schema.TypeString, 22 Required: true, 23 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 24 if vStr, ok := v.(string); ok && vStr == "_local" { 25 ws = append(ws, "Use of the %q backend is now officially "+ 26 "supported as %q. Please update your configuration to ensure "+ 27 "compatibility with future versions of Terraform.", 28 "_local", "local") 29 } 30 31 return 32 }, 33 }, 34 35 "config": { 36 Type: schema.TypeMap, 37 Optional: true, 38 }, 39 40 "environment": { 41 Type: schema.TypeString, 42 Optional: true, 43 Default: backend.DefaultStateName, 44 }, 45 46 "__has_dynamic_attributes": { 47 Type: schema.TypeString, 48 Optional: true, 49 }, 50 }, 51 } 52 } 53 54 func dataSourceRemoteStateRead(d *schema.ResourceData, meta interface{}) error { 55 backend := d.Get("backend").(string) 56 57 // Get the configuration in a type we want. 58 rawConfig, err := config.NewRawConfig(d.Get("config").(map[string]interface{})) 59 if err != nil { 60 return fmt.Errorf("error initializing backend: %s", err) 61 } 62 63 // Don't break people using the old _local syntax - but note warning above 64 if backend == "_local" { 65 log.Println(`[INFO] Switching old (unsupported) backend "_local" to "local"`) 66 backend = "local" 67 } 68 69 // Create the client to access our remote state 70 log.Printf("[DEBUG] Initializing remote state backend: %s", backend) 71 f := backendinit.Backend(backend) 72 if f == nil { 73 return fmt.Errorf("Unknown backend type: %s", backend) 74 } 75 b := f() 76 77 // Configure the backend 78 if err := b.Configure(terraform.NewResourceConfig(rawConfig)); err != nil { 79 return fmt.Errorf("error initializing backend: %s", err) 80 } 81 82 // Get the state 83 env := d.Get("environment").(string) 84 state, err := b.State(env) 85 if err != nil { 86 return fmt.Errorf("error loading the remote state: %s", err) 87 } 88 if err := state.RefreshState(); err != nil { 89 return err 90 } 91 92 d.SetId(time.Now().UTC().String()) 93 94 outputMap := make(map[string]interface{}) 95 96 remoteState := state.State() 97 if remoteState.Empty() { 98 log.Println("[DEBUG] empty remote state") 99 return nil 100 } 101 102 for key, val := range remoteState.RootModule().Outputs { 103 outputMap[key] = val.Value 104 } 105 106 mappedOutputs := remoteStateFlatten(outputMap) 107 108 for key, val := range mappedOutputs { 109 d.UnsafeSetFieldRaw(key, val) 110 } 111 return nil 112 }