Lokasi ngalangkungan proxy:   [ UP ]  
[Ngawartoskeun bug]   [Panyetelan cookie]                
Skip to content

Commit ab50781

Browse files
committed
config: support for provider configs
1 parent 87b3046 commit ab50781

7 files changed

Lines changed: 153 additions & 2 deletions

File tree

config/config.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,18 @@ import (
1212
// Config is the configuration that comes from loading a collection
1313
// of Terraform templates.
1414
type Config struct {
15-
Variables map[string]Variable
16-
Resources []*Resource
15+
ProviderConfigs map[string]*ProviderConfig
16+
Resources []*Resource
17+
Variables map[string]Variable
18+
}
19+
20+
// ProviderConfig is the configuration for a resource provider.
21+
//
22+
// For example, Terraform needs to set the AWS access keys for the AWS
23+
// resource provider.
24+
type ProviderConfig struct {
25+
Config map[string]interface{}
26+
Variables map[string]InterpolatedVariable
1727
}
1828

1929
// A resource represents a single Terraform resource in the configuration.

config/config_tree.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ func mergeConfig(c1, c2 *Config) (*Config, error) {
6666
c.Variables[k] = v2
6767
}
6868

69+
// Merge provider configs: If they collide, we just take the latest one
70+
// for now. In the future, we might provide smarter merge functionality.
71+
c.ProviderConfigs = make(map[string]*ProviderConfig)
72+
for k, v := range c1.ProviderConfigs {
73+
c.ProviderConfigs[k] = v
74+
}
75+
for k, v := range c2.ProviderConfigs {
76+
c.ProviderConfigs[k] = v
77+
}
78+
6979
// Merge resources: If they collide, we just take the latest one
7080
// for now. In the future, we might provide smarter merge functionality.
7181
resources := make(map[string]*Resource)

config/loader_libucl.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,17 @@ func (t *libuclConfigurable) Config() (*Config, error) {
3636
config := new(Config)
3737
config.Variables = rawConfig.Variable
3838

39+
// Build the provider configs
40+
providers := t.Object.Get("provider")
41+
if providers != nil {
42+
var err error
43+
config.ProviderConfigs, err = loadProvidersLibucl(providers)
44+
providers.Close()
45+
if err != nil {
46+
return nil, err
47+
}
48+
}
49+
3950
// Build the resources
4051
resources := t.Object.Get("resource")
4152
if resources != nil {
@@ -114,6 +125,52 @@ func loadFileLibucl(root string) (configurable, []string, error) {
114125
return result, importPaths, nil
115126
}
116127

128+
// LoadProvidersLibucl recurses into the given libucl object and turns
129+
// it into a mapping of provider configs.
130+
func loadProvidersLibucl(o *libucl.Object) (map[string]*ProviderConfig, error) {
131+
objects := make(map[string]*libucl.Object)
132+
133+
// Iterate over all the "provider" blocks and get the keys along with
134+
// their raw configuration objects. We'll parse those later.
135+
iter := o.Iterate(false)
136+
for o1 := iter.Next(); o1 != nil; o1 = iter.Next() {
137+
iter2 := o1.Iterate(true)
138+
for o2 := iter2.Next(); o2 != nil; o2 = iter2.Next() {
139+
objects[o2.Key()] = o2
140+
defer o2.Close()
141+
}
142+
143+
o1.Close()
144+
iter2.Close()
145+
}
146+
iter.Close()
147+
148+
// Go through each object and turn it into an actual result.
149+
result := make(map[string]*ProviderConfig)
150+
for n, o := range objects {
151+
var config map[string]interface{}
152+
153+
if err := o.Decode(&config); err != nil {
154+
return nil, err
155+
}
156+
157+
walker := new(variableDetectWalker)
158+
if err := reflectwalk.Walk(config, walker); err != nil {
159+
return nil, fmt.Errorf(
160+
"Error reading config for provider config %s: %s",
161+
n,
162+
err)
163+
}
164+
165+
result[n] = &ProviderConfig{
166+
Config: config,
167+
Variables: walker.Variables,
168+
}
169+
}
170+
171+
return result, nil
172+
}
173+
117174
// Given a handle to a libucl object, this recurses into the structure
118175
// and pulls out a list of resources.
119176
//

config/loader_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ func TestLoadBasic(t *testing.T) {
2929
t.Fatalf("bad:\n%s", actual)
3030
}
3131

32+
actual = providerConfigsStr(c.ProviderConfigs)
33+
if actual != strings.TrimSpace(basicProvidersStr) {
34+
t.Fatalf("bad:\n%s", actual)
35+
}
36+
3237
actual = resourcesStr(c.Resources)
3338
if actual != strings.TrimSpace(basicResourcesStr) {
3439
t.Fatalf("bad:\n%s", actual)
@@ -50,12 +55,49 @@ func TestLoadBasic_import(t *testing.T) {
5055
t.Fatalf("bad:\n%s", actual)
5156
}
5257

58+
actual = providerConfigsStr(c.ProviderConfigs)
59+
if actual != strings.TrimSpace(importProvidersStr) {
60+
t.Fatalf("bad:\n%s", actual)
61+
}
62+
5363
actual = resourcesStr(c.Resources)
5464
if actual != strings.TrimSpace(importResourcesStr) {
5565
t.Fatalf("bad:\n%s", actual)
5666
}
5767
}
5868

69+
// This helper turns a provider configs field into a deterministic
70+
// string value for comparison in tests.
71+
func providerConfigsStr(pcs map[string]*ProviderConfig) string {
72+
result := ""
73+
for n, pc := range pcs {
74+
result += fmt.Sprintf("%s\n", n)
75+
76+
for k, _ := range pc.Config {
77+
result += fmt.Sprintf(" %s\n", k)
78+
}
79+
80+
if len(pc.Variables) > 0 {
81+
result += fmt.Sprintf(" vars\n")
82+
for _, rawV := range pc.Variables {
83+
kind := "unknown"
84+
str := rawV.FullKey()
85+
86+
switch rawV.(type) {
87+
case *ResourceVariable:
88+
kind = "resource"
89+
case *UserVariable:
90+
kind = "user"
91+
}
92+
93+
result += fmt.Sprintf(" %s: %s\n", kind, str)
94+
}
95+
}
96+
}
97+
98+
return strings.TrimSpace(result)
99+
}
100+
59101
// This helper turns a resources field into a deterministic
60102
// string value for comparison in tests.
61103
func resourcesStr(rs []*Resource) string {
@@ -113,6 +155,16 @@ func variablesStr(vs map[string]Variable) string {
113155
return strings.TrimSpace(result)
114156
}
115157

158+
const basicProvidersStr = `
159+
aws
160+
access_key
161+
secret_key
162+
do
163+
api_key
164+
vars
165+
user: var.foo
166+
`
167+
116168
const basicResourcesStr = `
117169
aws_security_group[firewall]
118170
aws_instance[web]
@@ -129,6 +181,11 @@ foo
129181
bar
130182
`
131183

184+
const importProvidersStr = `
185+
aws
186+
foo
187+
`
188+
132189
const importResourcesStr = `
133190
aws_security_group[db]
134191
aws_security_group[web]

config/test-fixtures/basic.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@ variable "foo" {
33
description = "bar";
44
}
55

6+
provider "aws" {
7+
access_key = "foo";
8+
secret_key = "bar";
9+
}
10+
11+
provider "do" {
12+
api_key = "${var.foo}";
13+
}
14+
615
resource "aws_security_group" "firewall" {
716
}
817

config/test-fixtures/import.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@ variable "foo" {
55
description = "bar";
66
}
77

8+
provider "aws" {
9+
foo = "bar";
10+
}
11+
812
resource "aws_security_group" "web" {}

config/test-fixtures/import/one.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
variable "bar" {}
22

3+
provider "aws" {
4+
bar = "baz";
5+
}
6+
37
resource "aws_security_group" "db" {}

0 commit comments

Comments
 (0)