github.com/hooklift/terraform@v0.11.0-beta1.0.20171117000744-6786c1361ffe/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 "defaults": { 41 Type: schema.TypeMap, 42 Optional: true, 43 }, 44 45 "environment": { 46 Type: schema.TypeString, 47 Optional: true, 48 Default: backend.DefaultStateName, 49 }, 50 51 "__has_dynamic_attributes": { 52 Type: schema.TypeString, 53 Optional: true, 54 }, 55 }, 56 } 57 } 58 59 func dataSourceRemoteStateRead(d *schema.ResourceData, meta interface{}) error { 60 backend := d.Get("backend").(string) 61 62 // Get the configuration in a type we want. 63 rawConfig, err := config.NewRawConfig(d.Get("config").(map[string]interface{})) 64 if err != nil { 65 return fmt.Errorf("error initializing backend: %s", err) 66 } 67 68 // Don't break people using the old _local syntax - but note warning above 69 if backend == "_local" { 70 log.Println(`[INFO] Switching old (unsupported) backend "_local" to "local"`) 71 backend = "local" 72 } 73 74 // Create the client to access our remote state 75 log.Printf("[DEBUG] Initializing remote state backend: %s", backend) 76 f := backendinit.Backend(backend) 77 if f == nil { 78 return fmt.Errorf("Unknown backend type: %s", backend) 79 } 80 b := f() 81 82 // Configure the backend 83 if err := b.Configure(terraform.NewResourceConfig(rawConfig)); err != nil { 84 return fmt.Errorf("error initializing backend: %s", err) 85 } 86 87 // Get the state 88 env := d.Get("environment").(string) 89 state, err := b.State(env) 90 if err != nil { 91 return fmt.Errorf("error loading the remote state: %s", err) 92 } 93 if err := state.RefreshState(); err != nil { 94 return err 95 } 96 d.SetId(time.Now().UTC().String()) 97 98 outputMap := make(map[string]interface{}) 99 100 defaults := d.Get("defaults").(map[string]interface{}) 101 for key, val := range defaults { 102 outputMap[key] = val 103 } 104 105 remoteState := state.State() 106 if remoteState.Empty() { 107 log.Println("[DEBUG] empty remote state") 108 } else { 109 for key, val := range remoteState.RootModule().Outputs { 110 outputMap[key] = val.Value 111 } 112 } 113 114 mappedOutputs := remoteStateFlatten(outputMap) 115 116 for key, val := range mappedOutputs { 117 d.UnsafeSetFieldRaw(key, val) 118 } 119 120 return nil 121 }