github.com/jaredpalmer/terraform@v1.1.0-alpha20210908.0.20210911170307-88705c943a03/internal/configs/module_merge_test.go (about) 1 package configs 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/hashicorp/hcl/v2" 8 "github.com/hashicorp/hcl/v2/gohcl" 9 "github.com/hashicorp/terraform/internal/addrs" 10 "github.com/zclconf/go-cty/cty" 11 ) 12 13 func TestModuleOverrideVariable(t *testing.T) { 14 mod, diags := testModuleFromDir("testdata/valid-modules/override-variable") 15 assertNoDiagnostics(t, diags) 16 if mod == nil { 17 t.Fatalf("module is nil") 18 } 19 20 got := mod.Variables 21 want := map[string]*Variable{ 22 "fully_overridden": { 23 Name: "fully_overridden", 24 Description: "b_override description", 25 DescriptionSet: true, 26 Default: cty.StringVal("b_override"), 27 Type: cty.String, 28 ParsingMode: VariableParseLiteral, 29 DeclRange: hcl.Range{ 30 Filename: "testdata/valid-modules/override-variable/primary.tf", 31 Start: hcl.Pos{ 32 Line: 1, 33 Column: 1, 34 Byte: 0, 35 }, 36 End: hcl.Pos{ 37 Line: 1, 38 Column: 28, 39 Byte: 27, 40 }, 41 }, 42 }, 43 "partially_overridden": { 44 Name: "partially_overridden", 45 Description: "base description", 46 DescriptionSet: true, 47 Default: cty.StringVal("b_override partial"), 48 Type: cty.String, 49 ParsingMode: VariableParseLiteral, 50 DeclRange: hcl.Range{ 51 Filename: "testdata/valid-modules/override-variable/primary.tf", 52 Start: hcl.Pos{ 53 Line: 7, 54 Column: 1, 55 Byte: 103, 56 }, 57 End: hcl.Pos{ 58 Line: 7, 59 Column: 32, 60 Byte: 134, 61 }, 62 }, 63 }, 64 } 65 assertResultDeepEqual(t, got, want) 66 } 67 68 func TestModuleOverrideModule(t *testing.T) { 69 mod, diags := testModuleFromDir("testdata/valid-modules/override-module") 70 assertNoDiagnostics(t, diags) 71 if mod == nil { 72 t.Fatalf("module is nil") 73 } 74 75 if _, exists := mod.ModuleCalls["example"]; !exists { 76 t.Fatalf("no module 'example'") 77 } 78 if len(mod.ModuleCalls) != 1 { 79 t.Fatalf("wrong number of module calls in result %d; want 1", len(mod.ModuleCalls)) 80 } 81 82 got := mod.ModuleCalls["example"] 83 want := &ModuleCall{ 84 Name: "example", 85 SourceAddr: addrs.ModuleSourceLocal("./example2-a_override"), 86 SourceAddrRaw: "./example2-a_override", 87 SourceAddrRange: hcl.Range{ 88 Filename: "testdata/valid-modules/override-module/a_override.tf", 89 Start: hcl.Pos{ 90 Line: 3, 91 Column: 12, 92 Byte: 31, 93 }, 94 End: hcl.Pos{ 95 Line: 3, 96 Column: 35, 97 Byte: 54, 98 }, 99 }, 100 SourceSet: true, 101 DeclRange: hcl.Range{ 102 Filename: "testdata/valid-modules/override-module/primary.tf", 103 Start: hcl.Pos{ 104 Line: 2, 105 Column: 1, 106 Byte: 1, 107 }, 108 End: hcl.Pos{ 109 Line: 2, 110 Column: 17, 111 Byte: 17, 112 }, 113 }, 114 Providers: []PassedProviderConfig{ 115 { 116 InChild: &ProviderConfigRef{ 117 Name: "test", 118 NameRange: hcl.Range{ 119 Filename: "testdata/valid-modules/override-module/b_override.tf", 120 Start: hcl.Pos{Line: 7, Column: 5, Byte: 97}, 121 End: hcl.Pos{Line: 7, Column: 9, Byte: 101}, 122 }, 123 }, 124 InParent: &ProviderConfigRef{ 125 Name: "test", 126 NameRange: hcl.Range{ 127 Filename: "testdata/valid-modules/override-module/b_override.tf", 128 Start: hcl.Pos{Line: 7, Column: 12, Byte: 104}, 129 End: hcl.Pos{Line: 7, Column: 16, Byte: 108}, 130 }, 131 Alias: "b_override", 132 AliasRange: &hcl.Range{ 133 Filename: "testdata/valid-modules/override-module/b_override.tf", 134 Start: hcl.Pos{Line: 7, Column: 16, Byte: 108}, 135 End: hcl.Pos{Line: 7, Column: 27, Byte: 119}, 136 }, 137 }, 138 }, 139 }, 140 } 141 142 // We're going to extract and nil out our hcl.Body here because DeepEqual 143 // is not a useful way to assert on that. 144 gotConfig := got.Config 145 got.Config = nil 146 147 assertResultDeepEqual(t, got, want) 148 149 type content struct { 150 Kept *string `hcl:"kept"` 151 Foo *string `hcl:"foo"` 152 New *string `hcl:"new"` 153 Newer *string `hcl:"newer"` 154 } 155 var gotArgs content 156 diags = gohcl.DecodeBody(gotConfig, nil, &gotArgs) 157 assertNoDiagnostics(t, diags) 158 159 wantArgs := content{ 160 Kept: stringPtr("primary kept"), 161 Foo: stringPtr("a_override foo"), 162 New: stringPtr("b_override new"), 163 Newer: stringPtr("b_override newer"), 164 } 165 166 assertResultDeepEqual(t, gotArgs, wantArgs) 167 } 168 169 func TestModuleOverrideDynamic(t *testing.T) { 170 schema := &hcl.BodySchema{ 171 Blocks: []hcl.BlockHeaderSchema{ 172 {Type: "foo"}, 173 {Type: "dynamic", LabelNames: []string{"type"}}, 174 }, 175 } 176 177 t.Run("base is dynamic", func(t *testing.T) { 178 mod, diags := testModuleFromDir("testdata/valid-modules/override-dynamic-block-base") 179 assertNoDiagnostics(t, diags) 180 if mod == nil { 181 t.Fatalf("module is nil") 182 } 183 184 if _, exists := mod.ManagedResources["test.foo"]; !exists { 185 t.Fatalf("no module 'example'") 186 } 187 if len(mod.ManagedResources) != 1 { 188 t.Fatalf("wrong number of managed resources in result %d; want 1", len(mod.ManagedResources)) 189 } 190 191 body := mod.ManagedResources["test.foo"].Config 192 content, diags := body.Content(schema) 193 assertNoDiagnostics(t, diags) 194 195 if len(content.Blocks) != 1 { 196 t.Fatalf("wrong number of blocks in result %d; want 1", len(content.Blocks)) 197 } 198 if got, want := content.Blocks[0].Type, "foo"; got != want { 199 t.Fatalf("wrong block type %q; want %q", got, want) 200 } 201 }) 202 t.Run("override is dynamic", func(t *testing.T) { 203 mod, diags := testModuleFromDir("testdata/valid-modules/override-dynamic-block-override") 204 assertNoDiagnostics(t, diags) 205 if mod == nil { 206 t.Fatalf("module is nil") 207 } 208 209 if _, exists := mod.ManagedResources["test.foo"]; !exists { 210 t.Fatalf("no module 'example'") 211 } 212 if len(mod.ManagedResources) != 1 { 213 t.Fatalf("wrong number of managed resources in result %d; want 1", len(mod.ManagedResources)) 214 } 215 216 body := mod.ManagedResources["test.foo"].Config 217 content, diags := body.Content(schema) 218 assertNoDiagnostics(t, diags) 219 220 if len(content.Blocks) != 1 { 221 t.Fatalf("wrong number of blocks in result %d; want 1", len(content.Blocks)) 222 } 223 if got, want := content.Blocks[0].Type, "dynamic"; got != want { 224 t.Fatalf("wrong block type %q; want %q", got, want) 225 } 226 if got, want := content.Blocks[0].Labels[0], "foo"; got != want { 227 t.Fatalf("wrong dynamic block label %q; want %q", got, want) 228 } 229 }) 230 } 231 232 func TestModuleOverrideSensitiveVariable(t *testing.T) { 233 type testCase struct { 234 sensitive bool 235 sensitiveSet bool 236 } 237 cases := map[string]testCase{ 238 "false_true": { 239 sensitive: true, 240 sensitiveSet: true, 241 }, 242 "true_false": { 243 sensitive: false, 244 sensitiveSet: true, 245 }, 246 "false_false_true": { 247 sensitive: true, 248 sensitiveSet: true, 249 }, 250 "true_true_false": { 251 sensitive: false, 252 sensitiveSet: true, 253 }, 254 "false_true_false": { 255 sensitive: false, 256 sensitiveSet: true, 257 }, 258 "true_false_true": { 259 sensitive: true, 260 sensitiveSet: true, 261 }, 262 } 263 264 mod, diags := testModuleFromDir("testdata/valid-modules/override-variable-sensitive") 265 266 assertNoDiagnostics(t, diags) 267 268 if mod == nil { 269 t.Fatalf("module is nil") 270 } 271 272 got := mod.Variables 273 274 for v, want := range cases { 275 t.Run(fmt.Sprintf("variable %s", v), func(t *testing.T) { 276 if got[v].Sensitive != want.sensitive { 277 t.Errorf("wrong result for sensitive\ngot: %t want: %t", got[v].Sensitive, want.sensitive) 278 } 279 280 if got[v].SensitiveSet != want.sensitiveSet { 281 t.Errorf("wrong result for sensitive set\ngot: %t want: %t", got[v].Sensitive, want.sensitive) 282 } 283 }) 284 } 285 } 286 287 func TestModuleOverrideResourceFQNs(t *testing.T) { 288 mod, diags := testModuleFromDir("testdata/valid-modules/override-resource-provider") 289 assertNoDiagnostics(t, diags) 290 291 got := mod.ManagedResources["test_instance.explicit"] 292 wantProvider := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "bar", "test") 293 wantProviderCfg := &ProviderConfigRef{ 294 Name: "bar-test", 295 NameRange: hcl.Range{ 296 Filename: "testdata/valid-modules/override-resource-provider/a_override.tf", 297 Start: hcl.Pos{Line: 2, Column: 14, Byte: 51}, 298 End: hcl.Pos{Line: 2, Column: 22, Byte: 59}, 299 }, 300 } 301 302 if !got.Provider.Equals(wantProvider) { 303 t.Fatalf("wrong provider %s, want %s", got.Provider, wantProvider) 304 } 305 assertResultDeepEqual(t, got.ProviderConfigRef, wantProviderCfg) 306 307 // now verify that a resource with no provider config falls back to default 308 got = mod.ManagedResources["test_instance.default"] 309 wantProvider = addrs.NewDefaultProvider("test") 310 if !got.Provider.Equals(wantProvider) { 311 t.Fatalf("wrong provider %s, want %s", got.Provider, wantProvider) 312 } 313 if got.ProviderConfigRef != nil { 314 t.Fatalf("wrong result: found provider config ref %s, expected nil", got.ProviderConfigRef) 315 } 316 }