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