func loadConfigOutputs(hclConfig *ast.ObjectList) ([]*tfcfg.Output, error) { hclConfig = hclConfig.Children() result := make([]*tfcfg.Output, 0, len(hclConfig.Items)) if len(hclConfig.Items) == 0 { return result, nil } for _, item := range hclConfig.Items { n := item.Keys[0].Token.Value().(string) if _, ok := item.Val.(*ast.ObjectType); !ok { return nil, fmt.Errorf("output '%s': should be a block", n) } var config map[string]interface{} if err := hcl.DecodeObject(&config, item.Val); err != nil { return nil, err } rawConfig, err := tfcfg.NewRawConfig(config) if err != nil { return nil, fmt.Errorf( "error reading output config %s: %s", n, err, ) } result = append(result, &tfcfg.Output{ Name: n, RawConfig: rawConfig, }) } return result, nil }
// GraphNodeFlattenable impl. func (n *graphNodeModuleExpanded) FlattenGraph() *Graph { graph := n.Subgraph() input := n.Original.Module.RawConfig // Go over each vertex and do some modifications to the graph for // flattening. We have to skip some nodes (graphNodeModuleSkippable) // as well as setup the variable values. for _, v := range graph.Vertices() { // If this is a variable, then look it up in the raw configuration. // If it exists in the raw configuration, set the value of it. if vn, ok := v.(*GraphNodeConfigVariable); ok && input != nil { key := vn.VariableName() if v, ok := input.Raw[key]; ok { config, err := config.NewRawConfig(map[string]interface{}{ key: v, }) if err != nil { // This shouldn't happen because it is already in // a RawConfig above meaning it worked once before. panic(err) } // Set the variable value so it is interpolated properly. // Also set the module so we set the value on it properly. vn.Module = graph.Path[len(graph.Path)-1] vn.Value = config } } } return graph }
func TestResourceProvider_Configure(t *testing.T) { rp := new(ResourceProvider) raw := map[string]interface{}{ "token": "foo", } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } err = rp.Configure(terraform.NewResourceConfig(rawConfig)) if err != nil { t.Fatalf("err: %s", err) } expected := Config{ Token: "foo", } if !reflect.DeepEqual(rp.Config, expected) { t.Fatalf("bad: %#v", rp.Config) } }
func TestProviderConfigure(t *testing.T) { p := Provider().(*schema.Provider) raw, err := config.NewRawConfig(map[string]interface{}{ "account": helpers.TestAccount, "key": helpers.TestKeyFile, "key_id": helpers.TestKeyID, "url": "https://us-east-1.api.joyentcloud.com", }) if err != nil { t.Fatal(err) } providerConfig := terraform.NewResourceConfig(raw) assert.Nil(t, p.Meta()) assert.Nil(t, p.Configure(providerConfig)) config, ok := p.Meta().(*Config) if assert.True(t, ok) { assert.NotNil(t, config) assert.Equal(t, config.Account, helpers.TestAccount) assert.Equal(t, config.Key, helpers.TestKeyFile) assert.Equal(t, config.KeyID, helpers.TestKeyID) assert.Equal(t, config.URL, "https://us-east-1.api.joyentcloud.com") } }
func TestProviderConfigure(t *testing.T) { var expectedKey string var expectedEmail string if v := os.Getenv("HEROKU_EMAIL"); v != "" { expectedEmail = v } else { expectedEmail = "foo" } if v := os.Getenv("HEROKU_API_KEY"); v != "" { expectedKey = v } else { expectedKey = "foo" } raw := map[string]interface{}{ "api_key": expectedKey, "email": expectedEmail, } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } rp := Provider() err = rp.Configure(terraform.NewResourceConfig(rawConfig)) if err != nil { t.Fatalf("err: %s", err) } }
func TestResourceProvider_Configure(t *testing.T) { rp := new(ResourceProvider) raw := map[string]interface{}{ "access_key": "foo", "secret_key": "bar", "region": "us-east-1", } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } err = rp.Configure(terraform.NewResourceConfig(rawConfig)) if err != nil { t.Fatalf("err: %s", err) } expected := Config{ AccessKey: "foo", SecretKey: "bar", Region: "us-east-1", } if !reflect.DeepEqual(rp.Config, expected) { t.Fatalf("bad: %#v", rp.Config) } }
func TestProviderValidate(t *testing.T) { cases := []struct { P *Provider Config map[string]interface{} Err bool }{ { P: &Provider{ Schema: map[string]*Schema{ "foo": &Schema{}, }, }, Config: nil, Err: true, }, } for i, tc := range cases { c, err := config.NewRawConfig(tc.Config) if err != nil { t.Fatalf("err: %s", err) } _, es := tc.P.Validate(terraform.NewResourceConfig(c)) if len(es) > 0 != tc.Err { t.Fatalf("%d: %#v", i, es) } } }
func TestProviderConfigure(t *testing.T) { var expectedKey string if v := os.Getenv("MAILGUN_API_KEY"); v != "" { expectedKey = v } else { expectedKey = "foo" } raw := map[string]interface{}{ "api_key": expectedKey, } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } rp := Provider() err = rp.Configure(terraform.NewResourceConfig(rawConfig)) if err != nil { t.Fatalf("err: %s", err) } config := rp.Meta().(*mailgun.Client) if config.ApiKey != expectedKey { t.Fatalf("bad: %#v", config) } }
func TestResourceProvider_Configure(t *testing.T) { rp := new(ResourceProvider) raw := map[string]interface{}{ "address": "demo.consul.io:80", "datacenter": "nyc1", } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } err = rp.Configure(terraform.NewResourceConfig(rawConfig)) if err != nil { t.Fatalf("err: %s", err) } expected := Config{ Address: "demo.consul.io:80", Datacenter: "nyc1", } if !reflect.DeepEqual(rp.Config, expected) { t.Fatalf("bad: %#v", rp.Config) } }
func testConfig(t *testing.T, c map[string]interface{}) *terraform.ResourceConfig { r, err := config.NewRawConfig(c) if err != nil { t.Fatalf("bad: %s", err) } return terraform.NewResourceConfig(r) }
func testResourceConfig( t *testing.T, c map[string]interface{}) *ResourceConfig { raw, err := config.NewRawConfig(c) if err != nil { t.Fatalf("err: %s", err) } return NewResourceConfig(raw) }
func loadConfigProviders(hclConfig *ast.ObjectList) ([]*tfcfg.ProviderConfig, error) { hclConfig = hclConfig.Children() result := make([]*tfcfg.ProviderConfig, 0, len(hclConfig.Items)) if len(hclConfig.Items) == 0 { return result, nil } for _, item := range hclConfig.Items { n := item.Keys[0].Token.Value().(string) var listVal *ast.ObjectList if ot, ok := item.Val.(*ast.ObjectType); ok { listVal = ot.List } else { return nil, fmt.Errorf("provider '%s': should be a block", n) } var config map[string]interface{} if err := hcl.DecodeObject(&config, item.Val); err != nil { return nil, err } delete(config, "alias") rawConfig, err := tfcfg.NewRawConfig(config) if err != nil { return nil, fmt.Errorf( "error reading provider config %s: %s", n, err, ) } // If we have an alias, add it in var alias string if a := listVal.Filter("alias"); len(a.Items) > 0 { err := hcl.DecodeObject(&alias, a.Items[0].Val) if err != nil { return nil, fmt.Errorf( "error reading provider %s alias: %s", n, err, ) } } result = append(result, &tfcfg.ProviderConfig{ Name: n, Alias: alias, RawConfig: rawConfig, }) } return result, nil }
// interpolateForce is a temporary thing. We want to get rid of interpolate // above and likewise this, but it can only be done after the f-ast-graph // refactor is complete. func (c *ResourceConfig) interpolateForce() { if c.raw == nil { var err error c.raw, err = config.NewRawConfig(make(map[string]interface{})) if err != nil { panic(err) } } c.ComputedKeys = c.raw.UnknownKeys() c.Raw = c.raw.RawMap() c.Config = c.raw.Config() }
func loadConfigModules(hclConfig *ast.ObjectList) ([]*tfcfg.Module, error) { hclConfig = hclConfig.Children() result := make([]*tfcfg.Module, 0, len(hclConfig.Items)) if len(hclConfig.Items) == 0 { return result, nil } for _, item := range hclConfig.Items { n := item.Keys[0].Token.Value().(string) var listVal *ast.ObjectList if ot, ok := item.Val.(*ast.ObjectType); ok { listVal = ot.List } else { return nil, fmt.Errorf("module '%s': should be a block", n) } var config map[string]interface{} if err := hcl.DecodeObject(&config, item.Val); err != nil { return nil, err } delete(config, "source") rawConfig, err := tfcfg.NewRawConfig(config) if err != nil { return nil, fmt.Errorf( "error reading module config %s: %s", n, err, ) } var source string if a := listVal.Filter("source"); len(a.Items) > 0 { err := hcl.DecodeObject(&source, a.Items[0].Val) if err != nil { return nil, fmt.Errorf( "error reading module %s source: %s", n, err, ) } } result = append(result, &tfcfg.Module{ Name: n, Source: source, RawConfig: rawConfig, }) } return result, nil }
func testConfigInterpolate( t *testing.T, raw map[string]interface{}, vs map[string]ast.Variable) *terraform.ResourceConfig { rc, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } if len(vs) > 0 { if err := rc.Interpolate(vs); err != nil { t.Fatalf("err: %s", err) } } return terraform.NewResourceConfig(rc) }
func TestAzure_providerConfigure(t *testing.T) { home, err := homedir.Dir() if err != nil { t.Fatalf("Error fetching homedir: %s", err) } fh, err := ioutil.TempFile(home, "tf-test-home") if err != nil { t.Fatalf("Error creating homedir-based temporary file: %s", err) } defer os.Remove(fh.Name()) _, err = io.WriteString(fh, testAzurePublishSettingsStr) if err != nil { t.Fatalf("err: %s", err) } fh.Close() r := strings.NewReplacer(home, "~") homePath := r.Replace(fh.Name()) cases := []struct { SettingsFile string // String of XML or a path to an XML file NilMeta bool // whether meta is expected to be nil }{ {testAzurePublishSettingsStr, false}, {homePath, false}, } for _, tc := range cases { rp := Provider() raw := map[string]interface{}{ "settings_file": tc.SettingsFile, } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } err = rp.Configure(terraform.NewResourceConfig(rawConfig)) meta := rp.(*schema.Provider).Meta() if (meta == nil) != tc.NilMeta { t.Fatalf("expected NilMeta: %t, got meta: %#v, settings_file: %q", tc.NilMeta, meta, tc.SettingsFile) } } }
func TestAzure_providerConfigure(t *testing.T) { rp := Provider() raw := map[string]interface{}{ "publish_settings": testAzurePublishSettingsStr, } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } err = rp.Configure(terraform.NewResourceConfig(rawConfig)) meta := rp.(*schema.Provider).Meta() if meta == nil { t.Fatalf("Expected metadata, got nil: err: %s", err) } }
func TestResourceProvider_Configure(t *testing.T) { rp := Provider() raw := map[string]interface{}{ "address": "demo.consul.io:80", "datacenter": "nyc3", } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } err = rp.Configure(terraform.NewResourceConfig(rawConfig)) if err != nil { t.Fatalf("err: %s", err) } }
func TestResourceProvider_ConfigureBadRegion(t *testing.T) { rp := new(ResourceProvider) raw := map[string]interface{}{ "access_key": "foo", "secret_key": "bar", "region": "blah", } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } err = rp.Configure(terraform.NewResourceConfig(rawConfig)) if err == nil { t.Fatalf("should have err: bad region") } }
func TestResourceProvider_Configure(t *testing.T) { rp := new(ResourceProvider) var expectedToken string var expectedEmail string if v := os.Getenv("DNSIMPLE_EMAIL"); v != "" { expectedEmail = v } else { expectedEmail = "foo" } if v := os.Getenv("DNSIMPLE_TOKEN"); v != "" { expectedToken = v } else { expectedToken = "foo" } raw := map[string]interface{}{ "token": expectedToken, "email": expectedEmail, } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } err = rp.Configure(terraform.NewResourceConfig(rawConfig)) if err != nil { t.Fatalf("err: %s", err) } expected := Config{ Token: expectedToken, Email: expectedEmail, } if !reflect.DeepEqual(rp.Config, expected) { t.Fatalf("bad: %#v", rp.Config) } }
func (s *Session) handleEval(line string) (string, error) { // Wrap the line to make it an interpolation. line = fmt.Sprintf("${%s}", line) // Parse the line raw, err := config.NewRawConfig(map[string]interface{}{ "value": line, }) if err != nil { return "", err } // Set the value raw.Key = "value" // Get the values vars, err := s.Interpolater.Values(&terraform.InterpolationScope{ Path: []string{"root"}, }, raw.Variables) if err != nil { return "", err } // Interpolate if err := raw.Interpolate(vars); err != nil { return "", err } // If we have any unknown keys, let the user know. if ks := raw.UnknownKeys(); len(ks) > 0 { return "", fmt.Errorf("unknown values referenced, can't compute value") } // Read the value result, err := FormatResult(raw.Value()) if err != nil { return "", err } return result, nil }
func TestResourceProvider_Configure(t *testing.T) { rp := new(ResourceProvider) var expectedKey string var expectedEmail string if v := os.Getenv("HEROKU_EMAIL"); v != "" { expectedEmail = v } else { expectedEmail = "foo" } if v := os.Getenv("HEROKU_API_KEY"); v != "" { expectedKey = v } else { expectedKey = "foo" } raw := map[string]interface{}{ "api_key": expectedKey, "email": expectedEmail, } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } err = rp.Configure(terraform.NewResourceConfig(rawConfig)) if err != nil { t.Fatalf("err: %s", err) } expected := Config{ APIKey: expectedKey, Email: expectedEmail, } if !reflect.DeepEqual(rp.Config, expected) { t.Fatalf("bad: %#v", rp.Config) } }
func TestResourceProvider_ConfigureTLS(t *testing.T) { rp := Provider() raw := map[string]interface{}{ "address": "demo.consul.io:80", "ca_file": "test-fixtures/cacert.pem", "cert_file": "test-fixtures/usercert.pem", "datacenter": "nyc3", "key_file": "test-fixtures/userkey.pem", "scheme": "https", } rawConfig, err := config.NewRawConfig(raw) if err != nil { t.Fatalf("err: %s", err) } err = rp.Configure(terraform.NewResourceConfig(rawConfig)) if err != nil { t.Fatalf("err: %s", err) } }
func testConfig( t *testing.T, c map[string]interface{}, vs map[string]string) *terraform.ResourceConfig { rc, err := config.NewRawConfig(c) if err != nil { t.Fatalf("err: %s", err) } if len(vs) > 0 { vars := make(map[string]ast.Variable) for k, v := range vs { vars[k] = ast.Variable{Value: v, Type: ast.TypeString} } if err := rc.Interpolate(vars); err != nil { t.Fatalf("err: %s", err) } } return terraform.NewResourceConfig(rc) }
func TestProviderValidateResource(t *testing.T) { cases := []struct { P *Provider Type string Config map[string]interface{} Err bool }{ { P: &Provider{}, Type: "foo", Config: nil, Err: true, }, { P: &Provider{ ResourcesMap: map[string]*Resource{ "foo": &Resource{}, }, }, Type: "foo", Config: nil, Err: false, }, } for i, tc := range cases { c, err := config.NewRawConfig(tc.Config) if err != nil { t.Fatalf("err: %s", err) } _, es := tc.P.ValidateResource(tc.Type, terraform.NewResourceConfig(c)) if len(es) > 0 != tc.Err { t.Fatalf("%d: %#v", i, es) } } }
func (n *EvalBuildProviderConfig) Eval(ctx EvalContext) (interface{}, error) { cfg := *n.Config // If we have a configuration set, then merge that in if input := ctx.ProviderInput(n.Provider); input != nil { rc, err := config.NewRawConfig(input) if err != nil { return nil, err } merged := cfg.raw.Merge(rc) cfg = NewResourceConfig(merged) } // Get the parent configuration if there is one if parent := ctx.ParentProviderConfig(n.Provider); parent != nil { merged := cfg.raw.Merge(parent.raw) cfg = NewResourceConfig(merged) } *n.Output = cfg return nil, nil }
func TestEvalInterpolate(t *testing.T) { config, err := config.NewRawConfig(map[string]interface{}{}) if err != nil { t.Fatalf("err: %s", err) } var actual *ResourceConfig n := &EvalInterpolate{Config: config, Output: &actual} result := testResourceConfig(t, map[string]interface{}{}) ctx := &MockEvalContext{InterpolateConfigResult: result} if _, err := n.Eval(ctx); err != nil { t.Fatalf("err: %s", err) } if actual != result { t.Fatalf("bad: %#v", actual) } if !ctx.InterpolateCalled { t.Fatal("should be called") } if !reflect.DeepEqual(ctx.InterpolateConfig, config) { t.Fatalf("bad: %#v", ctx.InterpolateConfig) } }
func TestResourceConfigGet(t *testing.T) { cases := []struct { Config map[string]interface{} Vars map[string]string Key string Value interface{} }{ { Config: nil, Key: "foo", Value: nil, }, { Config: map[string]interface{}{ "foo": "${var.foo}", }, Key: "foo", Value: "${var.foo}", }, { Config: map[string]interface{}{ "foo": "${var.foo}", }, Vars: map[string]string{"foo": "bar"}, Key: "foo", Value: "bar", }, { Config: map[string]interface{}{ "foo": []interface{}{1, 2, 5}, }, Key: "foo.0", Value: 1, }, { Config: map[string]interface{}{ "foo": []interface{}{1, 2, 5}, }, Key: "foo.5", Value: nil, }, } for i, tc := range cases { var rawC *config.RawConfig if tc.Config != nil { var err error rawC, err = config.NewRawConfig(tc.Config) if err != nil { t.Fatalf("err: %s", err) } } rc := NewResourceConfig(rawC) if tc.Vars != nil { ctx := NewContext(&ContextOpts{Variables: tc.Vars}) err := rc.interpolate( ctx.walkContext(walkInvalid, rootModulePath), nil) if err != nil { t.Fatalf("err: %s", err) } } v, _ := rc.Get(tc.Key) if !reflect.DeepEqual(v, tc.Value) { t.Fatalf("%d bad: %#v", i, v) } } }
func TestProviderConfigure(t *testing.T) { cases := []struct { P *Provider Config map[string]interface{} Err bool }{ { P: &Provider{}, Config: nil, Err: false, }, { P: &Provider{ Schema: map[string]*Schema{ "foo": &Schema{ Type: TypeInt, Optional: true, }, }, ConfigureFunc: func(d *ResourceData) (interface{}, error) { if d.Get("foo").(int) == 42 { return nil, nil } return nil, fmt.Errorf("nope") }, }, Config: map[string]interface{}{ "foo": 42, }, Err: false, }, { P: &Provider{ Schema: map[string]*Schema{ "foo": &Schema{ Type: TypeInt, Optional: true, }, }, ConfigureFunc: func(d *ResourceData) (interface{}, error) { if d.Get("foo").(int) == 42 { return nil, nil } return nil, fmt.Errorf("nope") }, }, Config: map[string]interface{}{ "foo": 52, }, Err: true, }, } for i, tc := range cases { c, err := config.NewRawConfig(tc.Config) if err != nil { t.Fatalf("err: %s", err) } err = tc.P.Configure(terraform.NewResourceConfig(c)) if err != nil != tc.Err { t.Fatalf("%d: %s", i, err) } } }
func TestResourceConfigGet(t *testing.T) { cases := []struct { Config map[string]interface{} Vars map[string]string Key string Value interface{} }{ { Config: nil, Key: "foo", Value: nil, }, { Config: map[string]interface{}{ "foo": "${var.foo}", }, Key: "foo", Value: "${var.foo}", }, { Config: map[string]interface{}{ "foo": "${var.foo}", }, Vars: map[string]string{"foo": "bar"}, Key: "foo", Value: "bar", }, { Config: map[string]interface{}{ "foo": []interface{}{1, 2, 5}, }, Key: "foo.0", Value: 1, }, { Config: map[string]interface{}{ "foo": []interface{}{1, 2, 5}, }, Key: "foo.5", Value: nil, }, // get from map { Config: map[string]interface{}{ "mapname": []map[string]interface{}{ map[string]interface{}{"key": 1}, }, }, Key: "mapname.0.key", Value: 1, }, // get from map with dot in key { Config: map[string]interface{}{ "mapname": []map[string]interface{}{ map[string]interface{}{"key.name": 1}, }, }, Key: "mapname.0.key.name", Value: 1, }, // get from map with overlapping key names { Config: map[string]interface{}{ "mapname": []map[string]interface{}{ map[string]interface{}{ "key.name": 1, "key.name.2": 2, }, }, }, Key: "mapname.0.key.name.2", Value: 2, }, { Config: map[string]interface{}{ "mapname": []map[string]interface{}{ map[string]interface{}{ "key.name": 1, "key.name.foo": 2, }, }, }, Key: "mapname.0.key.name", Value: 1, }, { Config: map[string]interface{}{ "mapname": []map[string]interface{}{ map[string]interface{}{ "listkey": []map[string]interface{}{ {"key": 3}, }, }, }, }, Key: "mapname.0.listkey.0.key", Value: 3, }, // FIXME: this is ambiguous, and matches the nested map // leaving here to catch this behaviour if it changes. { Config: map[string]interface{}{ "mapname": []map[string]interface{}{ map[string]interface{}{ "key.name": 1, "key.name.0": 2, "key": map[string]interface{}{"name": 3}, }, }, }, Key: "mapname.0.key.name", Value: 3, }, /* // TODO: can't access this nested list at all. // FIXME: key with name matching substring of nested list can panic { Config: map[string]interface{}{ "mapname": []map[string]interface{}{ map[string]interface{}{ "key.name": []map[string]interface{}{ {"subkey": 1}, }, "key": 3, }, }, }, Key: "mapname.0.key.name.0.subkey", Value: 3, }, */ } for i, tc := range cases { var rawC *config.RawConfig if tc.Config != nil { var err error rawC, err = config.NewRawConfig(tc.Config) if err != nil { t.Fatalf("err: %s", err) } } if tc.Vars != nil { vs := make(map[string]ast.Variable) for k, v := range tc.Vars { vs["var."+k] = ast.Variable{Value: v, Type: ast.TypeString} } if err := rawC.Interpolate(vs); err != nil { t.Fatalf("err: %s", err) } } rc := NewResourceConfig(rawC) rc.interpolateForce() // Test getting a key t.Run(fmt.Sprintf("get-%d", i), func(t *testing.T) { v, _ := rc.Get(tc.Key) if !reflect.DeepEqual(v, tc.Value) { t.Fatalf("%d bad: %#v", i, v) } }) // If we have vars, we don't test copying if len(tc.Vars) > 0 { continue } // Test copying and equality t.Run(fmt.Sprintf("copy-and-equal-%d", i), func(t *testing.T) { copy := rc.DeepCopy() if !reflect.DeepEqual(copy, rc) { t.Fatalf("bad:\n\n%#v\n\n%#v", copy, rc) } if !copy.Equal(rc) { t.Fatalf("copy != rc:\n\n%#v\n\n%#v", copy, rc) } if !rc.Equal(copy) { t.Fatalf("rc != copy:\n\n%#v\n\n%#v", copy, rc) } }) } }