From edfd8b6ac2e0dfa54a4a9b84d1ed975479f063b6 Mon Sep 17 00:00:00 2001 From: Ryan VanGundy <85766511+rmvangun@users.noreply.github.com> Date: Sun, 30 Nov 2025 17:21:49 -0500 Subject: [PATCH] chore(terraform): Place terraform module shims in context specific folder The terraform module shims that were once in the `.tf_modules` folder are now placed at `.windsor/contexts//terraform/**`. This ensures namepacing for stateful module shims folders on a per-context basis. Signed-off-by: Ryan VanGundy <85766511+rmvangun@users.noreply.github.com> --- docs/guides/terraform.md | 25 ++++---- pkg/composer/blueprint/blueprint_handler.go | 2 +- .../blueprint_handler_private_test.go | 10 +-- .../blueprint_handler_public_test.go | 8 ++- .../terraform/archive_module_resolver_test.go | 16 ++--- .../composite_module_resolver_test.go | 8 ++- pkg/composer/terraform/module_resolver.go | 8 +-- .../terraform/module_resolver_test.go | 63 ++++++++++--------- pkg/project/project.go | 13 ++-- pkg/provisioner/terraform/stack.go | 2 +- pkg/provisioner/terraform/stack_test.go | 14 ++--- pkg/runtime/env/azure_env_test.go | 3 + pkg/runtime/env/docker_env_test.go | 11 +++- pkg/runtime/env/env_test.go | 4 +- pkg/runtime/env/terraform_env.go | 6 +- pkg/runtime/env/terraform_env_test.go | 38 +++++------ pkg/runtime/runtime.go | 18 +----- 17 files changed, 126 insertions(+), 123 deletions(-) diff --git a/docs/guides/terraform.md b/docs/guides/terraform.md index e98ef9b1c..6cc19043d 100644 --- a/docs/guides/terraform.md +++ b/docs/guides/terraform.md @@ -10,15 +10,16 @@ To ensure compatibility with Windsor, your Terraform project should adhere to a ```plaintext .windsor/ -└── .tf_modules/ - ├── cluster/ - │ └── talos/ - │ ├── main.tf - │ └── variables.tf - └── gitops/ - └── flux/ - ├── main.tf - └── variables.tf +└── contexts/ + └── local/ + ├── cluster/ + │ └── talos/ + │ ├── main.tf + │ └── variables.tf + └── gitops/ + └── flux/ + ├── main.tf + └── variables.tf contexts/ └── local/ ├── .terraform/ @@ -69,7 +70,7 @@ kustomize: path: "" ``` -Modules like `cluster/talos` and `gitops/flux` are remote, with shims in `.windsor/.tf_modules/cluster/talos` and `.windsor/.tf_modules/gitops/flux`. Running `windsor up` applies these modules sequentially. +Modules like `cluster/talos` and `gitops/flux` are remote, with shims in `.windsor/contexts//cluster/talos` and `.windsor/contexts//gitops/flux`. Running `windsor up` applies these modules sequentially. Store your Terraform code in a `terraform/` folder within your project. To reference it in `blueprint.yaml`, add a section without a `source` field. For example, if your code is in `terraform/example/my-app`, add: @@ -85,9 +86,9 @@ terraform: Now, running `windsor up` will execute your module after the `gitops/flux` module. ## Importing Resources -The Windsor CLI offers a unique method for importing and using remote Terraform modules. Running `windsor init local` unpacks shims that reference basic modules from Windsor's [core blueprint](https://github.com/windsorcli/core), stored in `.windsor/.tf_modules`. +The Windsor CLI offers a unique method for importing and using remote Terraform modules. Running `windsor init local` unpacks shims that reference basic modules from Windsor's [core blueprint](https://github.com/windsorcli/core), stored in `.windsor/contexts//`. -Think of the `tf_modules` folder as the remote module counterpart to the local `terraform` folder. Variables for these modules are located in `contexts//terraform/path/to/module.tfvars`. +Think of the `contexts//` folder as the remote module counterpart to the local `terraform` folder. Variables for these modules are located in `.windsor/contexts//path/to/module/terraform.tfvars`. ## Terraform CLI Assistance diff --git a/pkg/composer/blueprint/blueprint_handler.go b/pkg/composer/blueprint/blueprint_handler.go index 8bdbf0a48..550c7ddfb 100644 --- a/pkg/composer/blueprint/blueprint_handler.go +++ b/pkg/composer/blueprint/blueprint_handler.go @@ -1266,7 +1266,7 @@ func (b *BaseBlueprintHandler) resolveComponentPaths(blueprint *blueprintv1alpha componentCopy := component if b.isValidTerraformRemoteSource(componentCopy.Source) || b.isOCISource(componentCopy.Source) || strings.HasPrefix(componentCopy.Source, "file://") { - componentCopy.FullPath = filepath.Join(projectRoot, ".windsor", ".tf_modules", componentCopy.Path) + componentCopy.FullPath = filepath.Join(projectRoot, ".windsor", "contexts", b.runtime.ContextName, "terraform", componentCopy.Path) } else { componentCopy.FullPath = filepath.Join(projectRoot, "terraform", componentCopy.Path) } diff --git a/pkg/composer/blueprint/blueprint_handler_private_test.go b/pkg/composer/blueprint/blueprint_handler_private_test.go index 85a96f8cd..a5096b9ce 100644 --- a/pkg/composer/blueprint/blueprint_handler_private_test.go +++ b/pkg/composer/blueprint/blueprint_handler_private_test.go @@ -536,6 +536,7 @@ func TestBaseBlueprintHandler_resolveComponentPaths(t *testing.T) { // Given a handler with components using remote sources handler := setup(t) handler.runtime.ProjectRoot = "/test/project" + handler.runtime.ContextName = "local" blueprint := &blueprintv1alpha1.Blueprint{ TerraformComponents: []blueprintv1alpha1.TerraformComponent{ { @@ -548,8 +549,8 @@ func TestBaseBlueprintHandler_resolveComponentPaths(t *testing.T) { // When resolving component paths handler.resolveComponentPaths(blueprint) - // Then remote source components should use .windsor/.tf_modules path - if blueprint.TerraformComponents[0].FullPath != filepath.Join("/test/project", ".windsor", ".tf_modules", "test-module") { + // Then remote source components should use .windsor/contexts/ path + if blueprint.TerraformComponents[0].FullPath != filepath.Join("/test/project", ".windsor", "contexts", "local", "terraform", "test-module") { t.Errorf("Expected FullPath for remote source, got: %s", blueprint.TerraformComponents[0].FullPath) } }) @@ -558,6 +559,7 @@ func TestBaseBlueprintHandler_resolveComponentPaths(t *testing.T) { // Given a handler with components using OCI sources handler := setup(t) handler.runtime.ProjectRoot = "/test/project" + handler.runtime.ContextName = "local" handler.blueprint = blueprintv1alpha1.Blueprint{ Sources: []blueprintv1alpha1.Source{ { @@ -578,8 +580,8 @@ func TestBaseBlueprintHandler_resolveComponentPaths(t *testing.T) { // When resolving component paths handler.resolveComponentPaths(blueprint) - // Then OCI source components should use .windsor/.tf_modules path - if blueprint.TerraformComponents[0].FullPath != filepath.Join("/test/project", ".windsor", ".tf_modules", "test-module") { + // Then OCI source components should use .windsor/contexts/ path + if blueprint.TerraformComponents[0].FullPath != filepath.Join("/test/project", ".windsor", "contexts", "local", "terraform", "test-module") { t.Errorf("Expected FullPath for OCI source, got: %s", blueprint.TerraformComponents[0].FullPath) } }) diff --git a/pkg/composer/blueprint/blueprint_handler_public_test.go b/pkg/composer/blueprint/blueprint_handler_public_test.go index 72265cc2b..b8f770952 100644 --- a/pkg/composer/blueprint/blueprint_handler_public_test.go +++ b/pkg/composer/blueprint/blueprint_handler_public_test.go @@ -392,6 +392,7 @@ func setupBlueprintMocks(t *testing.T, opts ...func(*BlueprintTestMocks)) *Bluep TemplateRoot: filepath.Join(tmpDir, "contexts", "_template"), ConfigHandler: configHandler, Shell: mockShell, + ContextName: "local", } // Create mocks struct @@ -605,7 +606,7 @@ func TestBlueprintHandler_GetTerraformComponents(t *testing.T) { } // And the component should have the correct full path - expectedPath := filepath.FromSlash(filepath.Join(projectRoot, ".windsor", ".tf_modules", "path/to/module")) + expectedPath := filepath.FromSlash(filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "path/to/module")) if resolvedComponents[0].FullPath != expectedPath { t.Errorf("Expected path %q, got %q", expectedPath, resolvedComponents[0].FullPath) } @@ -679,7 +680,7 @@ func TestBlueprintHandler_GetTerraformComponents(t *testing.T) { } // And the component should have the correct full path with backslashes preserved - expectedPath := filepath.Join(projectRoot, ".windsor", ".tf_modules", "path\\to\\module") + expectedPath := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "path\\to\\module") if resolvedComponents[0].FullPath != expectedPath { t.Errorf("Expected path %q, got %q", expectedPath, resolvedComponents[0].FullPath) } @@ -692,6 +693,7 @@ func TestBlueprintHandler_GetTerraformComponents(t *testing.T) { // And a project root directory projectRoot := "/test/project" handler.runtime.ProjectRoot = projectRoot + handler.runtime.ContextName = "local" // And an OCI source sources := []blueprintv1alpha1.Source{ @@ -729,7 +731,7 @@ func TestBlueprintHandler_GetTerraformComponents(t *testing.T) { } // And the component should have the correct full path - expectedPath := filepath.FromSlash(filepath.Join(projectRoot, ".windsor", ".tf_modules", "cluster/talos")) + expectedPath := filepath.FromSlash(filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "cluster/talos")) if resolvedComponents[0].FullPath != expectedPath { t.Errorf("Expected path %q, got %q", expectedPath, resolvedComponents[0].FullPath) } diff --git a/pkg/composer/terraform/archive_module_resolver_test.go b/pkg/composer/terraform/archive_module_resolver_test.go index f8adaa8c6..b96ee86cd 100644 --- a/pkg/composer/terraform/archive_module_resolver_test.go +++ b/pkg/composer/terraform/archive_module_resolver_test.go @@ -120,7 +120,7 @@ func TestArchiveModuleResolver_ProcessModules(t *testing.T) { { Path: "test-module", Source: "file://" + archivePath + "//terraform/test-module", - FullPath: filepath.Join(tmpDir, ".windsor", ".tf_modules", "test-module"), + FullPath: filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "test-module"), }, } } @@ -134,7 +134,7 @@ func TestArchiveModuleResolver_ProcessModules(t *testing.T) { } // And the module directory should be created - moduleDir := filepath.Join(tmpDir, ".windsor", ".tf_modules", "test-module") + moduleDir := filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "test-module") if _, err := os.Stat(moduleDir); err != nil { t.Errorf("Expected module directory to be created, got error: %v", err) } @@ -180,7 +180,7 @@ func TestArchiveModuleResolver_ProcessModules(t *testing.T) { { Path: "test-module", Source: "file:///invalid/path.tar.gz//terraform/test-module", - FullPath: filepath.Join(tmpDir, ".windsor", ".tf_modules", "test-module"), + FullPath: filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "test-module"), }, } } @@ -1130,7 +1130,7 @@ func TestArchiveModuleResolver_processComponent(t *testing.T) { component := blueprintv1alpha1.TerraformComponent{ Path: "test-module", Source: "file:///invalid/path.tar.gz//terraform/test-module", - FullPath: filepath.Join(tmpDir, ".windsor", ".tf_modules", "test-module"), + FullPath: filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "test-module"), } // Override MkdirAll to succeed @@ -1159,7 +1159,7 @@ func TestArchiveModuleResolver_processComponent(t *testing.T) { component := blueprintv1alpha1.TerraformComponent{ Path: "test-module", Source: "file://" + archivePath + "//terraform/test-module", - FullPath: filepath.Join(tmpDir, ".windsor", ".tf_modules", "test-module"), + FullPath: filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "test-module"), } // Override shims for real file operations @@ -1200,7 +1200,7 @@ func TestArchiveModuleResolver_processComponent(t *testing.T) { component := blueprintv1alpha1.TerraformComponent{ Path: "test-module", Source: "file://" + archivePath + "//terraform/test-module", - FullPath: filepath.Join(tmpDir, ".windsor", ".tf_modules", "test-module"), + FullPath: filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "test-module"), } // Override shims for real file operations @@ -1246,7 +1246,7 @@ func TestArchiveModuleResolver_processComponent(t *testing.T) { component := blueprintv1alpha1.TerraformComponent{ Path: "test-module", Source: "file://" + archivePath + "//terraform/test-module", - FullPath: filepath.Join(tmpDir, ".windsor", ".tf_modules", "test-module"), + FullPath: filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "test-module"), } // Override shims for real file operations @@ -1293,7 +1293,7 @@ func TestArchiveModuleResolver_processComponent(t *testing.T) { component := blueprintv1alpha1.TerraformComponent{ Path: "test-module", Source: "file://" + archivePath + "//terraform/test-module", - FullPath: filepath.Join(tmpDir, ".windsor", ".tf_modules", "test-module"), + FullPath: filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "test-module"), } // Override shims for real file operations diff --git a/pkg/composer/terraform/composite_module_resolver_test.go b/pkg/composer/terraform/composite_module_resolver_test.go index a75ab91d6..e73b0e686 100644 --- a/pkg/composer/terraform/composite_module_resolver_test.go +++ b/pkg/composer/terraform/composite_module_resolver_test.go @@ -68,7 +68,7 @@ func TestCompositeModuleResolver_ProcessModules(t *testing.T) { { Path: "oci-module", Source: "oci://registry.example.com/module:latest//terraform/oci-module", - FullPath: filepath.Join(tmpDir, ".windsor", ".tf_modules", "oci-module"), + FullPath: filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "oci-module"), }, { Path: "standard-module", @@ -287,8 +287,9 @@ func TestCompositeModuleResolver_GenerateTfvars(t *testing.T) { resolver, mocks := setup(t) tmpDir := t.TempDir() mocks.Runtime.ProjectRoot = tmpDir + mocks.Runtime.ContextName = "local" - moduleDir := filepath.Join(tmpDir, ".windsor", ".tf_modules", "test-module") + moduleDir := filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(moduleDir, 0755); err != nil { t.Fatalf("Failed to create module directory: %v", err) } @@ -332,8 +333,9 @@ func TestCompositeModuleResolver_GenerateTfvars(t *testing.T) { resolver, mocks := setup(t) tmpDir := t.TempDir() mocks.Runtime.ProjectRoot = tmpDir + mocks.Runtime.ContextName = "local" - moduleDir := filepath.Join(tmpDir, ".windsor", ".tf_modules", "test-module") + moduleDir := filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(moduleDir, 0755); err != nil { t.Fatalf("Failed to create module directory: %v", err) } diff --git a/pkg/composer/terraform/module_resolver.go b/pkg/composer/terraform/module_resolver.go index f875e49e5..64ba60606 100644 --- a/pkg/composer/terraform/module_resolver.go +++ b/pkg/composer/terraform/module_resolver.go @@ -190,7 +190,7 @@ func (h *BaseModuleResolver) parseVariablesFile(variablesTfPath string, protecte } // generateComponentTfvars generates tfvars files for a single Terraform component. -// All components write tfvars files to .windsor/.tf_modules//terraform.tfvars, +// All components write tfvars files to .windsor/contexts//terraform//terraform.tfvars, // regardless of whether they have a Source (remote) or not (local). This unifies the behavior // between local templates and OCI artifacts, preventing writes to the contexts folder. // Returns an error if variables.tf cannot be found or if tfvars file generation fails. @@ -200,7 +200,7 @@ func (h *BaseModuleResolver) generateComponentTfvars(projectRoot string, compone return fmt.Errorf("failed to find variables.tf for component %s: %w", component.Path, err) } - moduleTfvarsPath := filepath.Join(projectRoot, ".windsor", ".tf_modules", component.Path, "terraform.tfvars") + moduleTfvarsPath := filepath.Join(projectRoot, ".windsor", "contexts", h.runtime.ContextName, "terraform", component.Path, "terraform.tfvars") if err := h.removeTfvarsFiles(filepath.Dir(moduleTfvarsPath)); err != nil { return fmt.Errorf("failed cleaning existing .tfvars in module dir %s: %w", filepath.Dir(moduleTfvarsPath), err) } @@ -212,14 +212,14 @@ func (h *BaseModuleResolver) generateComponentTfvars(projectRoot string, compone } // findVariablesTfFileForComponent returns the path to the variables.tf file for the specified Terraform component. -// If the component has a non-empty Source, the path is .windsor/.tf_modules//variables.tf under the project root. +// If the component has a non-empty Source, the path is .windsor/contexts//terraform//variables.tf under the project root. // If the component has an empty Source, the path is terraform//variables.tf under the project root. // Returns the variables.tf file path if it exists, or an error if not found. func (h *BaseModuleResolver) findVariablesTfFileForComponent(projectRoot string, component blueprintv1alpha1.TerraformComponent) (string, error) { var variablesTfPath string if component.Source != "" { - variablesTfPath = filepath.Join(projectRoot, ".windsor", ".tf_modules", component.Path, "variables.tf") + variablesTfPath = filepath.Join(projectRoot, ".windsor", "contexts", h.runtime.ContextName, "terraform", component.Path, "variables.tf") } else { variablesTfPath = filepath.Join(projectRoot, "terraform", component.Path, "variables.tf") } diff --git a/pkg/composer/terraform/module_resolver_test.go b/pkg/composer/terraform/module_resolver_test.go index 25ea70c97..fa6122396 100644 --- a/pkg/composer/terraform/module_resolver_test.go +++ b/pkg/composer/terraform/module_resolver_test.go @@ -100,6 +100,7 @@ contexts: ConfigHandler: configHandler, Shell: mockShell, ProjectRoot: tmpDir, + ContextName: "local", } mocks := &TerraformTestMocks{ @@ -860,7 +861,7 @@ func TestBaseModuleResolver_GenerateTfvars(t *testing.T) { resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -896,7 +897,7 @@ func TestBaseModuleResolver_GenerateTfvars(t *testing.T) { } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -935,7 +936,7 @@ func TestBaseModuleResolver_GenerateTfvars(t *testing.T) { } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -979,7 +980,7 @@ func TestBaseModuleResolver_GenerateTfvars(t *testing.T) { } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1015,7 +1016,7 @@ func TestBaseModuleResolver_GenerateTfvars(t *testing.T) { } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1061,7 +1062,7 @@ func TestBaseModuleResolver_GenerateTfvars(t *testing.T) { } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1090,7 +1091,7 @@ variable "metadata" { type = object({ nested = object({ value = string }) }) }` resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1121,7 +1122,7 @@ variable "metadata" { type = object({ nested = object({ value = string }) }) }` resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1179,7 +1180,7 @@ variable "list" { } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1219,7 +1220,7 @@ variable "list" { } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1260,7 +1261,7 @@ variable "empty_map" { type = map(string) }` } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1286,7 +1287,7 @@ variable "disabled" { type = bool }` resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1366,7 +1367,7 @@ variable "disabled" { type = bool }` t.Fatalf("Failed to write variables.tf: %v", err) } - moduleDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "local-module") + moduleDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "local-module") if err := os.MkdirAll(moduleDir, 0755); err != nil { t.Fatalf("Failed to create module dir: %v", err) } @@ -1419,7 +1420,7 @@ variable "disabled" { type = bool }` t.Fatalf("Failed to write variables.tf: %v", err) } - moduleDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "local-module") + moduleDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "local-module") // Mock Stat to return non-NotExist error for the module directory originalStat := resolver.shims.Stat @@ -1449,7 +1450,7 @@ variable "disabled" { type = bool }` resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1459,7 +1460,7 @@ variable "disabled" { type = bool }` // Mock ReadDir to return error resolver.shims.ReadDir = func(name string) ([]os.DirEntry, error) { - if strings.Contains(name, ".tf_modules") { + if strings.Contains(name, "contexts") { return nil, fmt.Errorf("readdir error") } return setupDefaultShims().ReadDir(name) @@ -1479,7 +1480,7 @@ variable "disabled" { type = bool }` resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1536,7 +1537,7 @@ variable "disabled" { type = bool }` } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1577,7 +1578,7 @@ variable "nested_map" { type = object({ inner = object({ deep = object({ value = } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1603,7 +1604,7 @@ variable "nested_map" { type = object({ inner = object({ deep = object({ value = resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1626,7 +1627,7 @@ variable "nested_map" { type = object({ inner = object({ deep = object({ value = resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1662,7 +1663,7 @@ variable "nested_map" { type = object({ inner = object({ deep = object({ value = resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1692,7 +1693,7 @@ variable "nested_map" { type = object({ inner = object({ deep = object({ value = resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1718,7 +1719,7 @@ variable "cluster_name" { type = string }` resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1778,7 +1779,7 @@ variable "cluster_name" { type = string }` } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1811,7 +1812,7 @@ variable "cluster_name" { type = string }` resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1875,7 +1876,7 @@ variable "cluster_name" { type = string }` resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1917,7 +1918,7 @@ variable "cluster_name" { type = string }` } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1957,7 +1958,7 @@ variable "cluster_name" { type = string }` } projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -1979,7 +1980,7 @@ variable "cluster_name" { type = string }` resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } @@ -2005,7 +2006,7 @@ variable "cluster_name" { type = string }` resolver, mocks := setup(t) projectRoot, _ := mocks.Shell.GetProjectRootFunc() - variablesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "test-module") + variablesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "test-module") if err := os.MkdirAll(variablesDir, 0755); err != nil { t.Fatalf("Failed to create dir: %v", err) } diff --git a/pkg/project/project.go b/pkg/project/project.go index 7df71204d..296a263dd 100644 --- a/pkg/project/project.go +++ b/pkg/project/project.go @@ -99,12 +99,7 @@ func NewProject(contextName string, opts ...*Project) (*Project, error) { // This should be called after NewProject if command flags need to override // configuration values. Returns an error if loading or applying overrides fails. func (p *Project) Configure(flagOverrides map[string]any) error { - contextName := p.Runtime.ContextName - if contextName == "" { - contextName = "local" - } - - if p.Runtime.ConfigHandler.IsDevMode(contextName) { + if p.Runtime.ConfigHandler.IsDevMode(p.Runtime.ContextName) { if flagOverrides == nil { flagOverrides = make(map[string]any) } @@ -189,7 +184,7 @@ func (p *Project) Initialize(overwrite bool, blueprintURL ...string) error { // PerformCleanup removes context-specific artifacts including volumes, terraform modules, // and generated configuration files. It calls the config handler's Clean method to remove -// saved state, then deletes the .volumes directory, .windsor/.tf_modules directory, +// saved state, then deletes the .volumes directory, .windsor/contexts/ directory, // .windsor/Corefile, and .windsor/docker-compose.yaml. Returns an error if any cleanup step fails. func (p *Project) PerformCleanup() error { if err := p.Runtime.ConfigHandler.Clean(); err != nil { @@ -201,9 +196,9 @@ func (p *Project) PerformCleanup() error { return fmt.Errorf("error deleting .volumes folder: %w", err) } - tfModulesPath := filepath.Join(p.Runtime.ProjectRoot, ".windsor", ".tf_modules") + tfModulesPath := filepath.Join(p.Runtime.ProjectRoot, ".windsor", "contexts", p.Runtime.ContextName) if err := os.RemoveAll(tfModulesPath); err != nil { - return fmt.Errorf("error deleting .windsor/.tf_modules folder: %w", err) + return fmt.Errorf("error deleting .windsor/contexts/%s folder: %w", p.Runtime.ContextName, err) } corefilePath := filepath.Join(p.Runtime.ProjectRoot, ".windsor", "Corefile") diff --git a/pkg/provisioner/terraform/stack.go b/pkg/provisioner/terraform/stack.go index 21dbdda68..3d8517cb2 100644 --- a/pkg/provisioner/terraform/stack.go +++ b/pkg/provisioner/terraform/stack.go @@ -314,7 +314,7 @@ func (s *TerraformStack) resolveComponentPaths(blueprint *blueprintv1alpha1.Blue componentCopy := component if s.isValidTerraformRemoteSource(componentCopy.Source) || s.isOCISource(componentCopy.Source, blueprint) || strings.HasPrefix(componentCopy.Source, "file://") { - componentCopy.FullPath = filepath.Join(projectRoot, ".windsor", ".tf_modules", componentCopy.Path) + componentCopy.FullPath = filepath.Join(projectRoot, ".windsor", "contexts", s.runtime.ContextName, "terraform", componentCopy.Path) } else { componentCopy.FullPath = filepath.Join(projectRoot, "terraform", componentCopy.Path) } diff --git a/pkg/provisioner/terraform/stack_test.go b/pkg/provisioner/terraform/stack_test.go index 9c2ae174b..0a328604b 100644 --- a/pkg/provisioner/terraform/stack_test.go +++ b/pkg/provisioner/terraform/stack_test.go @@ -99,7 +99,7 @@ func setupTerraformMocks(t *testing.T, opts ...*SetupOptions) *TerraformTestMock { Source: "git::https://github.com/terraform-aws-modules/terraform-aws-vpc.git//terraform/remote/path@v1.0.0", Path: "remote/path", - FullPath: filepath.Join(tmpDir, ".windsor", ".tf_modules", "remote", "path"), + FullPath: filepath.Join(tmpDir, ".windsor", "contexts", "local", "terraform", "remote", "path"), Inputs: map[string]any{ "remote_variable1": "default_value", }, @@ -193,7 +193,7 @@ func setupWindsorStackMocks(t *testing.T, opts ...*SetupOptions) *TerraformTestM mocks := setupTerraformMocks(t, opts...) projectRoot := os.Getenv("WINDSOR_PROJECT_ROOT") - tfModulesDir := filepath.Join(projectRoot, ".windsor", ".tf_modules", "remote", "path") + tfModulesDir := filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "remote", "path") if err := os.MkdirAll(tfModulesDir, 0755); err != nil { t.Fatalf("Failed to create tf modules directory: %v", err) } @@ -425,7 +425,7 @@ func TestStack_Up(t *testing.T) { t.Run("ErrorRemovingBackendOverride", func(t *testing.T) { stack, mocks := setup(t) projectRoot := os.Getenv("WINDSOR_PROJECT_ROOT") - backendOverridePath := filepath.Join(projectRoot, ".windsor", ".tf_modules", "remote", "path", "backend_override.tf") + backendOverridePath := filepath.Join(projectRoot, ".windsor", "contexts", "local", "remote", "path", "backend_override.tf") if err := os.MkdirAll(filepath.Dir(backendOverridePath), 0755); err != nil { t.Fatalf("Failed to create directory: %v", err) } @@ -458,7 +458,7 @@ func TestStack_Down(t *testing.T) { { Source: "source1", Path: "module/path1", - FullPath: filepath.Join(os.Getenv("WINDSOR_PROJECT_ROOT"), ".windsor", ".tf_modules", "remote", "path"), + FullPath: filepath.Join(os.Getenv("WINDSOR_PROJECT_ROOT"), ".windsor", "contexts", "local", "terraform", "remote", "path"), }, } } @@ -541,13 +541,13 @@ func TestStack_Down(t *testing.T) { { Source: "source1", Path: "module/path1", - FullPath: filepath.Join(projectRoot, ".windsor", ".tf_modules", "remote", "path1"), + FullPath: filepath.Join(projectRoot, ".windsor", "contexts", "local", "remote", "path1"), Destroy: &destroyFalse, }, { Source: "source2", Path: "module/path2", - FullPath: filepath.Join(projectRoot, ".windsor", ".tf_modules", "remote", "path2"), + FullPath: filepath.Join(projectRoot, ".windsor", "contexts", "local", "remote", "path2"), }, } @@ -678,7 +678,7 @@ func TestStack_Down(t *testing.T) { t.Run("ErrorRemovingBackendOverride", func(t *testing.T) { stack, mocks := setup(t) projectRoot := os.Getenv("WINDSOR_PROJECT_ROOT") - backendOverridePath := filepath.Join(projectRoot, ".windsor", ".tf_modules", "remote", "path", "backend_override.tf") + backendOverridePath := filepath.Join(projectRoot, ".windsor", "contexts", "local", "remote", "path", "backend_override.tf") if err := os.MkdirAll(filepath.Dir(backendOverridePath), 0755); err != nil { t.Fatalf("Failed to create directory: %v", err) } diff --git a/pkg/runtime/env/azure_env_test.go b/pkg/runtime/env/azure_env_test.go index 12e9abd0d..27f8929f2 100644 --- a/pkg/runtime/env/azure_env_test.go +++ b/pkg/runtime/env/azure_env_test.go @@ -21,6 +21,9 @@ func setupAzureEnvMocks(t *testing.T, overrides ...*EnvTestMocks) *EnvTestMocks // Only load default config if ConfigHandler wasn't overridden // If ConfigHandler was injected via overrides, assume test wants to control it if len(overrides) == 0 || overrides[0] == nil || overrides[0].ConfigHandler == nil { + // Set the context environment variable first, before loading config + os.Setenv("WINDSOR_CONTEXT", "test-context") + configStr := ` version: v1alpha1 contexts: diff --git a/pkg/runtime/env/docker_env_test.go b/pkg/runtime/env/docker_env_test.go index 96938ae8b..4e994452a 100644 --- a/pkg/runtime/env/docker_env_test.go +++ b/pkg/runtime/env/docker_env_test.go @@ -30,6 +30,9 @@ func setupDockerEnvMocks(t *testing.T, overrides ...*EnvTestMocks) *EnvTestMocks // Only load default config if ConfigHandler wasn't overridden // If ConfigHandler was injected via overrides, assume test wants to control it if len(overrides) == 0 || overrides[0] == nil || overrides[0].ConfigHandler == nil { + // Set the context environment variable first, before loading config + os.Setenv("WINDSOR_CONTEXT", "test-context") + configStr := ` version: v1alpha1 contexts: @@ -45,7 +48,7 @@ contexts: t.Fatalf("Failed to load config: %v", err) } - // Set the context + // Set the context (this also updates the environment variable) mocks.ConfigHandler.SetContext("test-context") } @@ -1262,6 +1265,9 @@ contexts: mocks := setupDockerEnvMocks(t, &EnvTestMocks{ ConfigHandler: config.NewConfigHandler(baseMocks.Shell), }) + // Set the context environment variable after setup (setupDockerEnvMocks may have reset it) + os.Setenv("WINDSOR_CONTEXT", "test-context") + configStr := ` version: v1alpha1 contexts: @@ -1276,6 +1282,9 @@ contexts: if err := mocks.ConfigHandler.LoadConfigString(configStr); err != nil { t.Fatalf("Failed to load config: %v", err) } + // Set the context to ensure GetConfig() returns the right config + mocks.ConfigHandler.SetContext("test-context") + printer := NewDockerEnvPrinter(mocks.Shell, mocks.ConfigHandler) printer.shims = mocks.Shims diff --git a/pkg/runtime/env/env_test.go b/pkg/runtime/env/env_test.go index 1bb406252..0b49515b2 100644 --- a/pkg/runtime/env/env_test.go +++ b/pkg/runtime/env/env_test.go @@ -49,8 +49,8 @@ func setupEnvMocks(t *testing.T, overrides ...*EnvTestMocks) *EnvTestMocks { // Set project root environment variable os.Setenv("WINDSOR_PROJECT_ROOT", tmpDir) - // Set context default to test-context - os.Setenv("WINDSOR_CONTEXT", "test-context") + // Set context default to local + os.Setenv("WINDSOR_CONTEXT", "local") // Create shell with project root matching temp dir mockShell := shell.NewMockShell() diff --git a/pkg/runtime/env/terraform_env.go b/pkg/runtime/env/terraform_env.go index 91cdc2b99..0cd4339c0 100644 --- a/pkg/runtime/env/terraform_env.go +++ b/pkg/runtime/env/terraform_env.go @@ -123,8 +123,10 @@ func (e *TerraformEnvPrinter) GenerateTerraformArgs(projectPath, modulePath stri return nil, fmt.Errorf("error getting project root: %w", err) } + contextName := e.configHandler.GetContext() + patterns := []string{ - filepath.Join(projectRoot, ".windsor", ".tf_modules", projectPath, "terraform.tfvars"), + filepath.Join(projectRoot, ".windsor", "contexts", contextName, "terraform", projectPath, "terraform.tfvars"), filepath.Join(configRoot, "terraform", projectPath+".tfvars"), filepath.Join(configRoot, "terraform", projectPath+".tfvars.json"), } @@ -673,7 +675,7 @@ func (e *TerraformEnvPrinter) findRelativeTerraformProjectPath(directory ...stri pathParts := strings.Split(currentPath, string(os.PathSeparator)) for i := len(pathParts) - 1; i >= 0; i-- { - if strings.EqualFold(pathParts[i], "terraform") || strings.EqualFold(pathParts[i], ".tf_modules") { + if strings.EqualFold(pathParts[i], "terraform") || strings.EqualFold(pathParts[i], "contexts") { relativePath := filepath.Join(pathParts[i+1:]...) return filepath.ToSlash(relativePath), nil } diff --git a/pkg/runtime/env/terraform_env_test.go b/pkg/runtime/env/terraform_env_test.go index 9f0a568d9..804859fbb 100644 --- a/pkg/runtime/env/terraform_env_test.go +++ b/pkg/runtime/env/terraform_env_test.go @@ -49,7 +49,7 @@ func setupTerraformEnvMocks(t *testing.T, overrides ...*EnvTestMocks) *EnvTestMo strings.Contains(nameSlash, "project/path.tfvars.json") || strings.Contains(nameSlash, "project\\path.tfvars") || strings.Contains(nameSlash, "project\\path.tfvars.json") || - strings.Contains(nameSlash, ".windsor/.tf_modules/project/path/terraform.tfvars") { + strings.Contains(nameSlash, ".windsor/contexts/local/terraform/project/path/terraform.tfvars") { return nil, nil } return nil, os.ErrNotExist @@ -97,16 +97,16 @@ func TestTerraformEnv_GetEnvVars(t *testing.T) { "TF_CLI_ARGS_init": fmt.Sprintf(`-backend=true -force-copy -upgrade -backend-config="path=%s"`, filepath.ToSlash(filepath.Join(configRoot, ".tfstate/project/path/terraform.tfstate"))), "TF_CLI_ARGS_plan": fmt.Sprintf(`-out="%s" -var-file="%s" -var-file="%s" -var-file="%s"`, filepath.ToSlash(filepath.Join(configRoot, ".terraform/project/path/terraform.tfplan")), - filepath.ToSlash(filepath.Join(projectRoot, ".windsor", ".tf_modules", "project/path", "terraform.tfvars")), + filepath.ToSlash(filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "project/path", "terraform.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars.json"))), "TF_CLI_ARGS_apply": fmt.Sprintf(`"%s"`, filepath.ToSlash(filepath.Join(configRoot, ".terraform/project/path/terraform.tfplan"))), "TF_CLI_ARGS_import": fmt.Sprintf(`-var-file="%s" -var-file="%s" -var-file="%s"`, - filepath.ToSlash(filepath.Join(projectRoot, ".windsor", ".tf_modules", "project/path", "terraform.tfvars")), + filepath.ToSlash(filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "project/path", "terraform.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars.json"))), "TF_CLI_ARGS_destroy": fmt.Sprintf(`-var-file="%s" -var-file="%s" -var-file="%s"`, - filepath.ToSlash(filepath.Join(projectRoot, ".windsor", ".tf_modules", "project/path", "terraform.tfvars")), + filepath.ToSlash(filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "project/path", "terraform.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars.json"))), "TF_VAR_context_path": filepath.ToSlash(configRoot), @@ -300,7 +300,7 @@ func TestTerraformEnv_GetEnvVars(t *testing.T) { strings.Contains(nameSlash, "project/path.tfvars.json") || strings.Contains(nameSlash, "project\\path.tfvars") || strings.Contains(nameSlash, "project\\path.tfvars.json") || - strings.Contains(nameSlash, ".windsor/.tf_modules/project/path/terraform.tfvars") { + strings.Contains(nameSlash, ".windsor/contexts/local/terraform/project/path/terraform.tfvars") { return nil, nil } return nil, os.ErrNotExist @@ -320,16 +320,16 @@ func TestTerraformEnv_GetEnvVars(t *testing.T) { "TF_CLI_ARGS_init": fmt.Sprintf(`-backend=true -force-copy -upgrade -backend-config="path=%s"`, filepath.ToSlash(filepath.Join(configRoot, ".tfstate/project/path/terraform.tfstate"))), "TF_CLI_ARGS_plan": fmt.Sprintf(`-out="%s" -var-file="%s" -var-file="%s" -var-file="%s"`, filepath.ToSlash(filepath.Join(configRoot, ".terraform/project/path/terraform.tfplan")), - filepath.ToSlash(filepath.Join(projectRoot, ".windsor", ".tf_modules", "project/path", "terraform.tfvars")), + filepath.ToSlash(filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "project/path", "terraform.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars.json"))), "TF_CLI_ARGS_apply": fmt.Sprintf(`"%s"`, filepath.ToSlash(filepath.Join(configRoot, ".terraform/project/path/terraform.tfplan"))), "TF_CLI_ARGS_import": fmt.Sprintf(`-var-file="%s" -var-file="%s" -var-file="%s"`, - filepath.ToSlash(filepath.Join(projectRoot, ".windsor", ".tf_modules", "project/path", "terraform.tfvars")), + filepath.ToSlash(filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "project/path", "terraform.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars.json"))), "TF_CLI_ARGS_destroy": fmt.Sprintf(`-var-file="%s" -var-file="%s" -var-file="%s"`, - filepath.ToSlash(filepath.Join(projectRoot, ".windsor", ".tf_modules", "project/path", "terraform.tfvars")), + filepath.ToSlash(filepath.Join(projectRoot, ".windsor", "contexts", "local", "terraform", "project/path", "terraform.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars")), filepath.ToSlash(filepath.Join(configRoot, "terraform/project/path.tfvars.json"))), "TF_VAR_context_path": filepath.ToSlash(configRoot), @@ -1273,13 +1273,13 @@ metadata: name: test-blueprint terraform: - path: vpc - fullPath: /project/.windsor/.tf_modules/vpc + fullPath: /project/.windsor/contexts/local/terraform/vpc dependsOn: [] - path: subnets - fullPath: /project/.windsor/.tf_modules/subnets + fullPath: /project/.windsor/contexts/local/terraform/subnets dependsOn: [vpc] - path: app - fullPath: /project/.windsor/.tf_modules/app + fullPath: /project/.windsor/contexts/local/terraform/app dependsOn: [subnets]` // Mock ReadFile to return blueprint.yaml content @@ -1357,13 +1357,13 @@ metadata: name: test-blueprint terraform: - path: a - fullPath: /project/.windsor/.tf_modules/a + fullPath: /project/.windsor/contexts/local/terraform/a dependsOn: [b] - path: b - fullPath: /project/.windsor/.tf_modules/b + fullPath: /project/.windsor/contexts/local/terraform/b dependsOn: [c] - path: c - fullPath: /project/.windsor/.tf_modules/c + fullPath: /project/.windsor/contexts/local/terraform/c dependsOn: [a]` // Mock ReadFile to return blueprint.yaml content @@ -1402,7 +1402,7 @@ metadata: name: test-blueprint terraform: - path: app - fullPath: /project/.windsor/.tf_modules/app + fullPath: /project/.windsor/contexts/local/terraform/app dependsOn: [nonexistent]` // Mock ReadFile to return blueprint.yaml content @@ -1441,10 +1441,10 @@ metadata: name: test-blueprint terraform: - path: vpc/main - fullPath: /project/.windsor/.tf_modules/vpc/main + fullPath: /project/.windsor/contexts/local/terraform/vpc/main dependsOn: [] - path: app/frontend - fullPath: /project/.windsor/.tf_modules/app/frontend + fullPath: /project/.windsor/contexts/local/terraform/app/frontend dependsOn: [vpc/main]` // Mock ReadFile to return blueprint.yaml content @@ -1498,10 +1498,10 @@ metadata: name: test-blueprint terraform: - path: base - fullPath: /project/.windsor/.tf_modules/base + fullPath: /project/.windsor/contexts/local/terraform/base dependsOn: [] - path: app - fullPath: /project/.windsor/.tf_modules/app + fullPath: /project/.windsor/contexts/local/terraform/app dependsOn: [base]` originalReadFile := mocks.Shims.ReadFile mocks.Shims.ReadFile = func(filename string) ([]byte, error) { diff --git a/pkg/runtime/runtime.go b/pkg/runtime/runtime.go index 5d31e6d20..d2c3a84fb 100644 --- a/pkg/runtime/runtime.go +++ b/pkg/runtime/runtime.go @@ -634,22 +634,13 @@ func (rt *Runtime) incrementBuildID(existingBuildID, currentDate string) (string // defaults depending on provider, dev mode, and vm.driver. // This must be called before loading from disk to ensure proper defaulting. Returns error on config operation failure. func (rt *Runtime) ApplyConfigDefaults(flagOverrides ...map[string]any) error { - contextName := rt.ContextName - if contextName == "" { - contextName = "local" - } - if rt.ConfigHandler == nil { return fmt.Errorf("config handler not available") } if !rt.ConfigHandler.IsLoaded() { existingProvider := rt.ConfigHandler.GetString("provider") - contextName := rt.ContextName - if contextName == "" { - contextName = "local" - } - isDevMode := rt.ConfigHandler.IsDevMode(contextName) + isDevMode := rt.ConfigHandler.IsDevMode(rt.ContextName) if isDevMode { if err := rt.ConfigHandler.Set("dev", true); err != nil { @@ -718,11 +709,6 @@ func (rt *Runtime) ApplyProviderDefaults(providerOverride string) error { return fmt.Errorf("config handler not available") } - contextName := rt.ContextName - if contextName == "" { - contextName = "local" - } - provider := providerOverride if provider == "" { provider = rt.ConfigHandler.GetString("provider") @@ -749,7 +735,7 @@ func (rt *Runtime) ApplyProviderDefaults(providerOverride string) error { return fmt.Errorf("failed to set cluster.driver: %w", err) } } - } else if rt.ConfigHandler.IsDevMode(contextName) { + } else if rt.ConfigHandler.IsDevMode(rt.ContextName) { if rt.ConfigHandler.GetString("cluster.driver") == "" { if err := rt.ConfigHandler.Set("cluster.driver", "talos"); err != nil { return fmt.Errorf("failed to set cluster.driver: %w", err)