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