-
Notifications
You must be signed in to change notification settings - Fork 0
/
data_source_state.go
135 lines (112 loc) · 3.37 KB
/
data_source_state.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package terraform
import (
"fmt"
"log"
"time"
"github.com/hashicorp/terraform/backend"
backendInit "github.com/hashicorp/terraform/backend/init"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
func dataSourceRemoteState() *schema.Resource {
return &schema.Resource{
Read: dataSourceRemoteStateRead,
Schema: map[string]*schema.Schema{
"backend": {
Type: schema.TypeString,
Required: true,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
if vStr, ok := v.(string); ok && vStr == "_local" {
ws = append(ws, "Use of the %q backend is now officially "+
"supported as %q. Please update your configuration to ensure "+
"compatibility with future versions of Terraform.",
"_local", "local")
}
return
},
},
"config": {
Type: schema.TypeMap,
Optional: true,
},
"defaults": {
Type: schema.TypeMap,
Optional: true,
},
"environment": {
Type: schema.TypeString,
Optional: true,
Default: backend.DefaultStateName,
Deprecated: "Terraform environments are now called workspaces. Please use the workspace key instead.",
},
"workspace": {
Type: schema.TypeString,
Optional: true,
Default: backend.DefaultStateName,
},
"__has_dynamic_attributes": {
Type: schema.TypeString,
Optional: true,
},
},
}
}
func dataSourceRemoteStateRead(d *schema.ResourceData, meta interface{}) error {
backendType := d.Get("backend").(string)
// Get the configuration in a type we want.
rawConfig, err := config.NewRawConfig(d.Get("config").(map[string]interface{}))
if err != nil {
return fmt.Errorf("error initializing backend: %s", err)
}
// Don't break people using the old _local syntax - but note warning above
if backendType == "_local" {
log.Println(`[INFO] Switching old (unsupported) backend "_local" to "local"`)
backendType = "local"
}
// Create the client to access our remote state
log.Printf("[DEBUG] Initializing remote state backend: %s", backendType)
f := backendInit.Backend(backendType)
if f == nil {
return fmt.Errorf("Unknown backend type: %s", backendType)
}
b := f()
// Configure the backend
if err := b.Configure(terraform.NewResourceConfig(rawConfig)); err != nil {
return fmt.Errorf("error initializing backend: %s", err)
}
// environment is deprecated in favour of workspace.
// If both keys are set workspace should win.
name := d.Get("environment").(string)
if ws, ok := d.GetOk("workspace"); ok && ws != backend.DefaultStateName {
name = ws.(string)
}
state, err := b.State(name)
if err != nil {
return fmt.Errorf("error loading the remote state: %s", err)
}
if err := state.RefreshState(); err != nil {
return err
}
d.SetId(time.Now().UTC().String())
outputMap := make(map[string]interface{})
defaults := d.Get("defaults").(map[string]interface{})
for key, val := range defaults {
outputMap[key] = val
}
remoteState := state.State()
if remoteState.Empty() {
log.Println("[DEBUG] empty remote state")
} else {
for key, val := range remoteState.RootModule().Outputs {
if val.Value != nil {
outputMap[key] = val.Value
}
}
}
mappedOutputs := remoteStateFlatten(outputMap)
for key, val := range mappedOutputs {
d.UnsafeSetFieldRaw(key, val)
}
return nil
}