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