github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/terraform/eval_variable_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/terraform/config"
     8  )
     9  
    10  func TestCoerceMapVariable(t *testing.T) {
    11  	cases := map[string]struct {
    12  		Input      *EvalCoerceMapVariable
    13  		ExpectVars map[string]interface{}
    14  	}{
    15  		"a valid map is untouched": {
    16  			Input: &EvalCoerceMapVariable{
    17  				Variables: map[string]interface{}{
    18  					"amap": map[string]interface{}{"foo": "bar"},
    19  				},
    20  				ModulePath: []string{"root"},
    21  				ModuleTree: testModuleInline(t, map[string]string{
    22  					"main.tf": `
    23  						variable "amap" {
    24  							type = "map"
    25  						}
    26  					`,
    27  				}),
    28  			},
    29  			ExpectVars: map[string]interface{}{
    30  				"amap": map[string]interface{}{"foo": "bar"},
    31  			},
    32  		},
    33  		"a list w/ a single map element is coerced": {
    34  			Input: &EvalCoerceMapVariable{
    35  				Variables: map[string]interface{}{
    36  					"amap": []interface{}{
    37  						map[string]interface{}{"foo": "bar"},
    38  					},
    39  				},
    40  				ModulePath: []string{"root"},
    41  				ModuleTree: testModuleInline(t, map[string]string{
    42  					"main.tf": `
    43  						variable "amap" {
    44  							type = "map"
    45  						}
    46  					`,
    47  				}),
    48  			},
    49  			ExpectVars: map[string]interface{}{
    50  				"amap": map[string]interface{}{"foo": "bar"},
    51  			},
    52  		},
    53  		"a list w/ more than one map element is untouched": {
    54  			Input: &EvalCoerceMapVariable{
    55  				Variables: map[string]interface{}{
    56  					"amap": []interface{}{
    57  						map[string]interface{}{"foo": "bar"},
    58  						map[string]interface{}{"baz": "qux"},
    59  					},
    60  				},
    61  				ModulePath: []string{"root"},
    62  				ModuleTree: testModuleInline(t, map[string]string{
    63  					"main.tf": `
    64  						variable "amap" {
    65  							type = "map"
    66  						}
    67  					`,
    68  				}),
    69  			},
    70  			ExpectVars: map[string]interface{}{
    71  				"amap": []interface{}{
    72  					map[string]interface{}{"foo": "bar"},
    73  					map[string]interface{}{"baz": "qux"},
    74  				},
    75  			},
    76  		},
    77  		"list coercion also works in a module": {
    78  			Input: &EvalCoerceMapVariable{
    79  				Variables: map[string]interface{}{
    80  					"amap": []interface{}{
    81  						map[string]interface{}{"foo": "bar"},
    82  					},
    83  				},
    84  				ModulePath: []string{"root", "middle", "bottom"},
    85  				ModuleTree: testModuleInline(t, map[string]string{
    86  					"top.tf": `
    87  						module "middle" {
    88  							source = "./middle"
    89  						}
    90  					`,
    91  					"middle/mid.tf": `
    92  						module "bottom" {
    93  							source = "./bottom"
    94  							amap {
    95  								foo = "bar"
    96  							}
    97  						}
    98  					`,
    99  					"middle/bottom/bot.tf": `
   100  						variable "amap" {
   101  							type = "map"
   102  						}
   103  					`,
   104  				}),
   105  			},
   106  			ExpectVars: map[string]interface{}{
   107  				"amap": map[string]interface{}{"foo": "bar"},
   108  			},
   109  		},
   110  		"coercion only occurs when target var is a map": {
   111  			Input: &EvalCoerceMapVariable{
   112  				Variables: map[string]interface{}{
   113  					"alist": []interface{}{
   114  						map[string]interface{}{"foo": "bar"},
   115  					},
   116  				},
   117  				ModulePath: []string{"root"},
   118  				ModuleTree: testModuleInline(t, map[string]string{
   119  					"main.tf": `
   120  						variable "alist" {
   121  							type = "list"
   122  						}
   123  					`,
   124  				}),
   125  			},
   126  			ExpectVars: map[string]interface{}{
   127  				"alist": []interface{}{
   128  					map[string]interface{}{"foo": "bar"},
   129  				},
   130  			},
   131  		},
   132  	}
   133  
   134  	for tn, tc := range cases {
   135  		_, err := tc.Input.Eval(&MockEvalContext{})
   136  		if err != nil {
   137  			t.Fatalf("%s: Unexpected err: %s", tn, err)
   138  		}
   139  		if !reflect.DeepEqual(tc.Input.Variables, tc.ExpectVars) {
   140  			t.Fatalf("%s: Expected variables:\n\n%#v\n\nGot:\n\n%#v",
   141  				tn, tc.ExpectVars, tc.Input.Variables)
   142  		}
   143  	}
   144  }
   145  
   146  func TestEvalVariableBlock(t *testing.T) {
   147  	rc, err := config.NewRawConfig(map[string]interface{}{
   148  		"known":      "foo",
   149  		"known_list": []interface{}{"foo"},
   150  		"known_map": map[string]interface{}{
   151  			"foo": "foo",
   152  		},
   153  		"known_list_of_maps": []map[string]interface{}{
   154  			map[string]interface{}{
   155  				"foo": "foo",
   156  			},
   157  		},
   158  		"computed_map": map[string]interface{}{},
   159  		"computed_list_of_maps": []map[string]interface{}{
   160  			map[string]interface{}{},
   161  		},
   162  		// No computed_list right now, because that isn't currently supported:
   163  		// EvalVariableBlock assumes the final step of the path will always
   164  		// be a map.
   165  	})
   166  	if err != nil {
   167  		t.Fatalf("config.NewRawConfig failed: %s", err)
   168  	}
   169  
   170  	cfg := NewResourceConfig(rc)
   171  	cfg.ComputedKeys = []string{
   172  		"computed",
   173  		"computed_map.foo",
   174  		"computed_list_of_maps.0.foo",
   175  	}
   176  
   177  	n := &EvalVariableBlock{
   178  		VariableValues: map[string]interface{}{
   179  			// Should be cleared out on Eval
   180  			"should_be_deleted": true,
   181  		},
   182  		Config: &cfg,
   183  	}
   184  
   185  	ctx := &MockEvalContext{}
   186  	val, err := n.Eval(ctx)
   187  	if err != nil {
   188  		t.Fatalf("n.Eval failed: %s", err)
   189  	}
   190  	if val != nil {
   191  		t.Fatalf("n.Eval returned non-nil result: %#v", val)
   192  	}
   193  
   194  	got := n.VariableValues
   195  	want := map[string]interface{}{
   196  		"known":      "foo",
   197  		"known_list": []interface{}{"foo"},
   198  		"known_map": map[string]interface{}{
   199  			"foo": "foo",
   200  		},
   201  		"known_list_of_maps": []interface{}{
   202  			map[string]interface{}{
   203  				"foo": "foo",
   204  			},
   205  		},
   206  		"computed": config.UnknownVariableValue,
   207  		"computed_map": map[string]interface{}{
   208  			"foo": config.UnknownVariableValue,
   209  		},
   210  		"computed_list_of_maps": []interface{}{
   211  			map[string]interface{}{
   212  				"foo": config.UnknownVariableValue,
   213  			},
   214  		},
   215  	}
   216  	if !reflect.DeepEqual(got, want) {
   217  		t.Errorf("Incorrect variables\ngot:  %#v\nwant: %#v", got, want)
   218  	}
   219  }