github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/configs/configload/loader_load_test.go (about) 1 package configload 2 3 import ( 4 "path/filepath" 5 "reflect" 6 "sort" 7 "strings" 8 "testing" 9 10 "github.com/davecgh/go-spew/spew" 11 "github.com/zclconf/go-cty/cty" 12 13 "github.com/hashicorp/terraform/internal/configs" 14 ) 15 16 func TestLoaderLoadConfig_okay(t *testing.T) { 17 fixtureDir := filepath.Clean("testdata/already-installed") 18 loader, err := NewLoader(&Config{ 19 ModulesDir: filepath.Join(fixtureDir, ".terraform/modules"), 20 }) 21 if err != nil { 22 t.Fatalf("unexpected error from NewLoader: %s", err) 23 } 24 25 cfg, diags := loader.LoadConfig(fixtureDir) 26 assertNoDiagnostics(t, diags) 27 if cfg == nil { 28 t.Fatalf("config is nil; want non-nil") 29 } 30 31 var gotPaths []string 32 cfg.DeepEach(func(c *configs.Config) { 33 gotPaths = append(gotPaths, strings.Join(c.Path, ".")) 34 }) 35 sort.Strings(gotPaths) 36 wantPaths := []string{ 37 "", // root module 38 "child_a", 39 "child_a.child_c", 40 "child_b", 41 "child_b.child_d", 42 } 43 44 if !reflect.DeepEqual(gotPaths, wantPaths) { 45 t.Fatalf("wrong module paths\ngot: %swant %s", spew.Sdump(gotPaths), spew.Sdump(wantPaths)) 46 } 47 48 t.Run("child_a.child_c output", func(t *testing.T) { 49 output := cfg.Children["child_a"].Children["child_c"].Module.Outputs["hello"] 50 got, diags := output.Expr.Value(nil) 51 assertNoDiagnostics(t, diags) 52 assertResultCtyEqual(t, got, cty.StringVal("Hello from child_c")) 53 }) 54 t.Run("child_b.child_d output", func(t *testing.T) { 55 output := cfg.Children["child_b"].Children["child_d"].Module.Outputs["hello"] 56 got, diags := output.Expr.Value(nil) 57 assertNoDiagnostics(t, diags) 58 assertResultCtyEqual(t, got, cty.StringVal("Hello from child_d")) 59 }) 60 } 61 62 func TestLoaderLoadConfig_addVersion(t *testing.T) { 63 // This test is for what happens when there is a version constraint added 64 // to a module that previously didn't have one. 65 fixtureDir := filepath.Clean("testdata/add-version-constraint") 66 loader, err := NewLoader(&Config{ 67 ModulesDir: filepath.Join(fixtureDir, ".terraform/modules"), 68 }) 69 if err != nil { 70 t.Fatalf("unexpected error from NewLoader: %s", err) 71 } 72 73 _, diags := loader.LoadConfig(fixtureDir) 74 if !diags.HasErrors() { 75 t.Fatalf("success; want error") 76 } 77 got := diags.Error() 78 want := "Module version requirements have changed" 79 if !strings.Contains(got, want) { 80 t.Fatalf("wrong error\ngot:\n%s\n\nwant: containing %q", got, want) 81 } 82 } 83 84 func TestLoaderLoadConfig_loadDiags(t *testing.T) { 85 // building a config which didn't load correctly may cause configs to panic 86 fixtureDir := filepath.Clean("testdata/invalid-names") 87 loader, err := NewLoader(&Config{ 88 ModulesDir: filepath.Join(fixtureDir, ".terraform/modules"), 89 }) 90 if err != nil { 91 t.Fatalf("unexpected error from NewLoader: %s", err) 92 } 93 94 cfg, diags := loader.LoadConfig(fixtureDir) 95 if !diags.HasErrors() { 96 t.Fatal("success; want error") 97 } 98 99 if cfg == nil { 100 t.Fatal("partial config not returned with diagnostics") 101 } 102 103 if cfg.Module == nil { 104 t.Fatal("expected config module") 105 } 106 } 107 108 func TestLoaderLoadConfig_loadDiagsFromSubmodules(t *testing.T) { 109 // building a config which didn't load correctly may cause configs to panic 110 fixtureDir := filepath.Clean("testdata/invalid-names-in-submodules") 111 loader, err := NewLoader(&Config{ 112 ModulesDir: filepath.Join(fixtureDir, ".terraform/modules"), 113 }) 114 if err != nil { 115 t.Fatalf("unexpected error from NewLoader: %s", err) 116 } 117 118 cfg, diags := loader.LoadConfig(fixtureDir) 119 if !diags.HasErrors() { 120 t.Fatalf("loading succeeded; want an error") 121 } 122 if got, want := diags.Error(), " Invalid provider local name"; !strings.Contains(got, want) { 123 t.Errorf("missing expected error\nwant substring: %s\ngot: %s", want, got) 124 } 125 126 if cfg == nil { 127 t.Fatal("partial config not returned with diagnostics") 128 } 129 130 if cfg.Module == nil { 131 t.Fatal("expected config module") 132 } 133 } 134 135 func TestLoaderLoadConfig_childProviderGrandchildCount(t *testing.T) { 136 // This test is focused on the specific situation where: 137 // - A child module contains a nested provider block, which is no longer 138 // recommended but supported for backward-compatibility. 139 // - A child of that child does _not_ contain a nested provider block, 140 // and is called with "count" (would also apply to "for_each" and 141 // "depends_on"). 142 // It isn't valid to use "count" with a module that _itself_ contains 143 // a provider configuration, but it _is_ valid for a module with a 144 // provider configuration to call another module with count. We previously 145 // botched this rule and so this is a regression test to cover the 146 // solution to that mistake: 147 // https://github.com/hashicorp/terraform/issues/31081 148 149 // Since this test is based on success rather than failure and it's 150 // covering a relatively large set of code where only a small part 151 // contributes to the test, we'll make sure to test both the success and 152 // failure cases here so that we'll have a better chance of noticing if a 153 // future change makes this succeed only because we've reorganized the code 154 // so that the check isn't happening at all anymore. 155 // 156 // If the "not okay" subtest fails, you should also be skeptical about 157 // whether the "okay" subtest is still valid, even if it happens to 158 // still be passing. 159 t.Run("okay", func(t *testing.T) { 160 fixtureDir := filepath.Clean("testdata/child-provider-grandchild-count") 161 loader, err := NewLoader(&Config{ 162 ModulesDir: filepath.Join(fixtureDir, ".terraform/modules"), 163 }) 164 if err != nil { 165 t.Fatalf("unexpected error from NewLoader: %s", err) 166 } 167 168 cfg, diags := loader.LoadConfig(fixtureDir) 169 assertNoDiagnostics(t, diags) 170 if cfg == nil { 171 t.Fatalf("config is nil; want non-nil") 172 } 173 174 var gotPaths []string 175 cfg.DeepEach(func(c *configs.Config) { 176 gotPaths = append(gotPaths, strings.Join(c.Path, ".")) 177 }) 178 sort.Strings(gotPaths) 179 wantPaths := []string{ 180 "", // root module 181 "child", 182 "child.grandchild", 183 } 184 185 if !reflect.DeepEqual(gotPaths, wantPaths) { 186 t.Fatalf("wrong module paths\ngot: %swant %s", spew.Sdump(gotPaths), spew.Sdump(wantPaths)) 187 } 188 }) 189 t.Run("not okay", func(t *testing.T) { 190 fixtureDir := filepath.Clean("testdata/child-provider-child-count") 191 loader, err := NewLoader(&Config{ 192 ModulesDir: filepath.Join(fixtureDir, ".terraform/modules"), 193 }) 194 if err != nil { 195 t.Fatalf("unexpected error from NewLoader: %s", err) 196 } 197 198 _, diags := loader.LoadConfig(fixtureDir) 199 if !diags.HasErrors() { 200 t.Fatalf("loading succeeded; want an error") 201 } 202 if got, want := diags.Error(), "Module is incompatible with count, for_each, and depends_on"; !strings.Contains(got, want) { 203 t.Errorf("missing expected error\nwant substring: %s\ngot: %s", want, got) 204 } 205 }) 206 207 }