From 1761eef06b34a04f3e8ccf68acd402bcc156e24b Mon Sep 17 00:00:00 2001 From: Ryan VanGundy <85766511+rmvangun@users.noreply.github.com> Date: Mon, 27 Oct 2025 21:34:09 -0400 Subject: [PATCH 1/2] refactor(resources): Move resource packages in to parent folder Signed-off-by: Ryan VanGundy <85766511+rmvangun@users.noreply.github.com> --- cmd/bundle_test.go | 4 ++-- cmd/push_test.go | 4 ++-- cmd/root_test.go | 2 +- pkg/environment/envvars/terraform_env_test.go | 2 +- pkg/generators/generator.go | 4 ++-- pkg/generators/generator_test.go | 4 ++-- pkg/generators/terraform_generator_test.go | 2 +- pkg/pipelines/down.go | 2 +- pkg/pipelines/down_test.go | 2 +- pkg/pipelines/init.go | 6 +++--- pkg/pipelines/init_test.go | 4 ++-- pkg/pipelines/install.go | 4 ++-- pkg/pipelines/install_test.go | 4 ++-- pkg/pipelines/pipeline.go | 6 +++--- pkg/pipelines/pipeline_test.go | 4 ++-- pkg/{ => resources}/artifact/artifact.go | 0 pkg/{ => resources}/artifact/artifact_test.go | 0 pkg/{ => resources}/artifact/mock_artifact.go | 0 pkg/{ => resources}/artifact/mock_artifact_test.go | 0 pkg/{ => resources}/artifact/shims.go | 0 pkg/{ => resources}/blueprint/blueprint_handler.go | 2 +- .../blueprint/blueprint_handler_helper_test.go | 0 .../blueprint/blueprint_handler_private_test.go | 0 .../blueprint/blueprint_handler_public_test.go | 2 +- pkg/{ => resources}/blueprint/defaults.go | 0 pkg/{ => resources}/blueprint/feature_evaluator.go | 0 pkg/{ => resources}/blueprint/feature_evaluator_test.go | 0 pkg/{ => resources}/blueprint/mock_blueprint_handler.go | 2 +- .../blueprint/mock_blueprint_handler_test.go | 2 +- pkg/{ => resources}/blueprint/shims.go | 0 pkg/{ => resources}/blueprint/templates/default.jsonnet | 0 pkg/{ => resources}/terraform/mock_module_resolver.go | 0 pkg/{ => resources}/terraform/mock_module_resolver_test.go | 0 pkg/{ => resources}/terraform/module_resolver.go | 2 +- pkg/{ => resources}/terraform/module_resolver_test.go | 4 ++-- pkg/{ => resources}/terraform/oci_module_resolver.go | 4 ++-- pkg/{ => resources}/terraform/oci_module_resolver_test.go | 2 +- pkg/{ => resources}/terraform/shims.go | 0 pkg/{ => resources}/terraform/standard_module_resolver.go | 2 +- .../terraform/standard_module_resolver_test.go | 2 +- pkg/runtime/runtime.go | 6 +++--- pkg/runtime/runtime_loaders.go | 2 +- pkg/stack/stack.go | 2 +- pkg/stack/stack_test.go | 2 +- 44 files changed, 45 insertions(+), 45 deletions(-) rename pkg/{ => resources}/artifact/artifact.go (100%) rename pkg/{ => resources}/artifact/artifact_test.go (100%) rename pkg/{ => resources}/artifact/mock_artifact.go (100%) rename pkg/{ => resources}/artifact/mock_artifact_test.go (100%) rename pkg/{ => resources}/artifact/shims.go (100%) rename pkg/{ => resources}/blueprint/blueprint_handler.go (99%) rename pkg/{ => resources}/blueprint/blueprint_handler_helper_test.go (100%) rename pkg/{ => resources}/blueprint/blueprint_handler_private_test.go (100%) rename pkg/{ => resources}/blueprint/blueprint_handler_public_test.go (99%) rename pkg/{ => resources}/blueprint/defaults.go (100%) rename pkg/{ => resources}/blueprint/feature_evaluator.go (100%) rename pkg/{ => resources}/blueprint/feature_evaluator_test.go (100%) rename pkg/{ => resources}/blueprint/mock_blueprint_handler.go (99%) rename pkg/{ => resources}/blueprint/mock_blueprint_handler_test.go (99%) rename pkg/{ => resources}/blueprint/shims.go (100%) rename pkg/{ => resources}/blueprint/templates/default.jsonnet (100%) rename pkg/{ => resources}/terraform/mock_module_resolver.go (100%) rename pkg/{ => resources}/terraform/mock_module_resolver_test.go (100%) rename pkg/{ => resources}/terraform/module_resolver.go (99%) rename pkg/{ => resources}/terraform/module_resolver_test.go (99%) rename pkg/{ => resources}/terraform/oci_module_resolver.go (99%) rename pkg/{ => resources}/terraform/oci_module_resolver_test.go (99%) rename pkg/{ => resources}/terraform/shims.go (100%) rename pkg/{ => resources}/terraform/standard_module_resolver.go (99%) rename pkg/{ => resources}/terraform/standard_module_resolver_test.go (99%) diff --git a/cmd/bundle_test.go b/cmd/bundle_test.go index 641712d76..3f6feecfe 100644 --- a/cmd/bundle_test.go +++ b/cmd/bundle_test.go @@ -9,11 +9,11 @@ import ( "testing" "github.com/spf13/cobra" - "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" "github.com/windsorcli/cli/pkg/kubernetes" + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" ) diff --git a/cmd/push_test.go b/cmd/push_test.go index da84c4dc7..44ec51c69 100644 --- a/cmd/push_test.go +++ b/cmd/push_test.go @@ -9,11 +9,11 @@ import ( "testing" "github.com/spf13/cobra" - "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" "github.com/windsorcli/cli/pkg/kubernetes" + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" ) diff --git a/cmd/root_test.go b/cmd/root_test.go index f6928f656..a0497507e 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -13,11 +13,11 @@ import ( "testing" "github.com/spf13/cobra" - blueprintpkg "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" "github.com/windsorcli/cli/pkg/environment/envvars" "github.com/windsorcli/cli/pkg/kubernetes" + blueprintpkg "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/secrets" "github.com/windsorcli/cli/pkg/shell" ) diff --git a/pkg/environment/envvars/terraform_env_test.go b/pkg/environment/envvars/terraform_env_test.go index 6c0ce731c..b4ff426d8 100644 --- a/pkg/environment/envvars/terraform_env_test.go +++ b/pkg/environment/envvars/terraform_env_test.go @@ -10,8 +10,8 @@ import ( "testing" blueprintv1alpha1 "github.com/windsorcli/cli/api/v1alpha1" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" + "github.com/windsorcli/cli/pkg/resources/blueprint" ) // ============================================================================= diff --git a/pkg/generators/generator.go b/pkg/generators/generator.go index 8baa164df..166912b68 100644 --- a/pkg/generators/generator.go +++ b/pkg/generators/generator.go @@ -3,10 +3,10 @@ package generators import ( "fmt" - bundler "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" + bundler "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" ) diff --git a/pkg/generators/generator_test.go b/pkg/generators/generator_test.go index 06da34ce1..bd5621e10 100644 --- a/pkg/generators/generator_test.go +++ b/pkg/generators/generator_test.go @@ -9,10 +9,10 @@ import ( "testing" blueprintv1alpha1 "github.com/windsorcli/cli/api/v1alpha1" - bundler "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" + bundler "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" ) diff --git a/pkg/generators/terraform_generator_test.go b/pkg/generators/terraform_generator_test.go index ca05751d4..adcfc292b 100644 --- a/pkg/generators/terraform_generator_test.go +++ b/pkg/generators/terraform_generator_test.go @@ -15,8 +15,8 @@ import ( "github.com/hashicorp/hcl/v2/hclwrite" blueprintv1alpha1 "github.com/windsorcli/cli/api/v1alpha1" - bundler "github.com/windsorcli/cli/pkg/artifact" "github.com/windsorcli/cli/pkg/config" + bundler "github.com/windsorcli/cli/pkg/resources/artifact" "github.com/zclconf/go-cty/cty" ) diff --git a/pkg/pipelines/down.go b/pkg/pipelines/down.go index edf128e54..99cd709cd 100644 --- a/pkg/pipelines/down.go +++ b/pkg/pipelines/down.go @@ -6,10 +6,10 @@ import ( "os" "path/filepath" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/di" "github.com/windsorcli/cli/pkg/environment/envvars" "github.com/windsorcli/cli/pkg/kubernetes" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" "github.com/windsorcli/cli/pkg/stack" "github.com/windsorcli/cli/pkg/workstation/network" diff --git a/pkg/pipelines/down_test.go b/pkg/pipelines/down_test.go index 109b990a0..c86c4558e 100644 --- a/pkg/pipelines/down_test.go +++ b/pkg/pipelines/down_test.go @@ -7,10 +7,10 @@ import ( "strings" "testing" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/environment/envvars" "github.com/windsorcli/cli/pkg/kubernetes" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" "github.com/windsorcli/cli/pkg/stack" "github.com/windsorcli/cli/pkg/workstation/network" diff --git a/pkg/pipelines/init.go b/pkg/pipelines/init.go index 213d7ea6b..d05bceafa 100644 --- a/pkg/pipelines/init.go +++ b/pkg/pipelines/init.go @@ -8,17 +8,17 @@ import ( "runtime" "strings" - "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/constants" "github.com/windsorcli/cli/pkg/di" "github.com/windsorcli/cli/pkg/environment/envvars" "github.com/windsorcli/cli/pkg/environment/tools" "github.com/windsorcli/cli/pkg/generators" + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" + "github.com/windsorcli/cli/pkg/resources/terraform" "github.com/windsorcli/cli/pkg/shell" "github.com/windsorcli/cli/pkg/stack" - "github.com/windsorcli/cli/pkg/terraform" "github.com/windsorcli/cli/pkg/workstation/network" "github.com/windsorcli/cli/pkg/workstation/services" "github.com/windsorcli/cli/pkg/workstation/virt" diff --git a/pkg/pipelines/init_test.go b/pkg/pipelines/init_test.go index 8bcf785ab..ab088313a 100644 --- a/pkg/pipelines/init_test.go +++ b/pkg/pipelines/init_test.go @@ -9,12 +9,12 @@ import ( "time" "github.com/windsorcli/cli/api/v1alpha1" - "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" "github.com/windsorcli/cli/pkg/environment/tools" "github.com/windsorcli/cli/pkg/kubernetes" + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" "github.com/windsorcli/cli/pkg/stack" "github.com/windsorcli/cli/pkg/workstation/virt" diff --git a/pkg/pipelines/install.go b/pkg/pipelines/install.go index fc7ad37e5..73142e2bb 100644 --- a/pkg/pipelines/install.go +++ b/pkg/pipelines/install.go @@ -4,10 +4,10 @@ import ( "context" "fmt" - "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/di" "github.com/windsorcli/cli/pkg/generators" + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" ) // The InstallPipeline is a specialized component that manages blueprint installation functionality. diff --git a/pkg/pipelines/install_test.go b/pkg/pipelines/install_test.go index aedee7e8a..8d6cc371f 100644 --- a/pkg/pipelines/install_test.go +++ b/pkg/pipelines/install_test.go @@ -6,10 +6,10 @@ import ( "strings" "testing" - "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" ) // ============================================================================= diff --git a/pkg/pipelines/pipeline.go b/pkg/pipelines/pipeline.go index dad9fdd63..21f2a601a 100644 --- a/pkg/pipelines/pipeline.go +++ b/pkg/pipelines/pipeline.go @@ -7,8 +7,6 @@ import ( "path/filepath" secretsConfigType "github.com/windsorcli/cli/api/v1alpha1/secrets" - "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/cluster" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/constants" @@ -17,11 +15,13 @@ import ( "github.com/windsorcli/cli/pkg/environment/tools" "github.com/windsorcli/cli/pkg/generators" "github.com/windsorcli/cli/pkg/kubernetes" + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" + "github.com/windsorcli/cli/pkg/resources/terraform" "github.com/windsorcli/cli/pkg/secrets" "github.com/windsorcli/cli/pkg/shell" "github.com/windsorcli/cli/pkg/shell/ssh" "github.com/windsorcli/cli/pkg/stack" - "github.com/windsorcli/cli/pkg/terraform" "github.com/windsorcli/cli/pkg/workstation/network" "github.com/windsorcli/cli/pkg/workstation/services" "github.com/windsorcli/cli/pkg/workstation/virt" diff --git a/pkg/pipelines/pipeline_test.go b/pkg/pipelines/pipeline_test.go index 7eb7cfaac..dddc32583 100644 --- a/pkg/pipelines/pipeline_test.go +++ b/pkg/pipelines/pipeline_test.go @@ -12,14 +12,14 @@ import ( "github.com/windsorcli/cli/api/v1alpha1" "github.com/windsorcli/cli/api/v1alpha1/docker" secretsConfigType "github.com/windsorcli/cli/api/v1alpha1/secrets" - "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/cluster" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" "github.com/windsorcli/cli/pkg/environment/envvars" "github.com/windsorcli/cli/pkg/environment/tools" "github.com/windsorcli/cli/pkg/kubernetes" + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" "github.com/windsorcli/cli/pkg/stack" "github.com/windsorcli/cli/pkg/workstation/virt" diff --git a/pkg/artifact/artifact.go b/pkg/resources/artifact/artifact.go similarity index 100% rename from pkg/artifact/artifact.go rename to pkg/resources/artifact/artifact.go diff --git a/pkg/artifact/artifact_test.go b/pkg/resources/artifact/artifact_test.go similarity index 100% rename from pkg/artifact/artifact_test.go rename to pkg/resources/artifact/artifact_test.go diff --git a/pkg/artifact/mock_artifact.go b/pkg/resources/artifact/mock_artifact.go similarity index 100% rename from pkg/artifact/mock_artifact.go rename to pkg/resources/artifact/mock_artifact.go diff --git a/pkg/artifact/mock_artifact_test.go b/pkg/resources/artifact/mock_artifact_test.go similarity index 100% rename from pkg/artifact/mock_artifact_test.go rename to pkg/resources/artifact/mock_artifact_test.go diff --git a/pkg/artifact/shims.go b/pkg/resources/artifact/shims.go similarity index 100% rename from pkg/artifact/shims.go rename to pkg/resources/artifact/shims.go diff --git a/pkg/blueprint/blueprint_handler.go b/pkg/resources/blueprint/blueprint_handler.go similarity index 99% rename from pkg/blueprint/blueprint_handler.go rename to pkg/resources/blueprint/blueprint_handler.go index a6af7195a..5eaf15b67 100644 --- a/pkg/blueprint/blueprint_handler.go +++ b/pkg/resources/blueprint/blueprint_handler.go @@ -18,11 +18,11 @@ import ( _ "embed" "github.com/goccy/go-yaml" - "github.com/windsorcli/cli/pkg/artifact" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/constants" "github.com/windsorcli/cli/pkg/di" "github.com/windsorcli/cli/pkg/kubernetes" + "github.com/windsorcli/cli/pkg/resources/artifact" "github.com/windsorcli/cli/pkg/shell" "github.com/briandowns/spinner" diff --git a/pkg/blueprint/blueprint_handler_helper_test.go b/pkg/resources/blueprint/blueprint_handler_helper_test.go similarity index 100% rename from pkg/blueprint/blueprint_handler_helper_test.go rename to pkg/resources/blueprint/blueprint_handler_helper_test.go diff --git a/pkg/blueprint/blueprint_handler_private_test.go b/pkg/resources/blueprint/blueprint_handler_private_test.go similarity index 100% rename from pkg/blueprint/blueprint_handler_private_test.go rename to pkg/resources/blueprint/blueprint_handler_private_test.go diff --git a/pkg/blueprint/blueprint_handler_public_test.go b/pkg/resources/blueprint/blueprint_handler_public_test.go similarity index 99% rename from pkg/blueprint/blueprint_handler_public_test.go rename to pkg/resources/blueprint/blueprint_handler_public_test.go index 4ce7e0460..c2929fe52 100644 --- a/pkg/blueprint/blueprint_handler_public_test.go +++ b/pkg/resources/blueprint/blueprint_handler_public_test.go @@ -15,11 +15,11 @@ import ( sourcev1 "github.com/fluxcd/source-controller/api/v1" "github.com/goccy/go-yaml" blueprintv1alpha1 "github.com/windsorcli/cli/api/v1alpha1" - "github.com/windsorcli/cli/pkg/artifact" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/constants" "github.com/windsorcli/cli/pkg/di" "github.com/windsorcli/cli/pkg/kubernetes" + "github.com/windsorcli/cli/pkg/resources/artifact" "github.com/windsorcli/cli/pkg/shell" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/blueprint/defaults.go b/pkg/resources/blueprint/defaults.go similarity index 100% rename from pkg/blueprint/defaults.go rename to pkg/resources/blueprint/defaults.go diff --git a/pkg/blueprint/feature_evaluator.go b/pkg/resources/blueprint/feature_evaluator.go similarity index 100% rename from pkg/blueprint/feature_evaluator.go rename to pkg/resources/blueprint/feature_evaluator.go diff --git a/pkg/blueprint/feature_evaluator_test.go b/pkg/resources/blueprint/feature_evaluator_test.go similarity index 100% rename from pkg/blueprint/feature_evaluator_test.go rename to pkg/resources/blueprint/feature_evaluator_test.go diff --git a/pkg/blueprint/mock_blueprint_handler.go b/pkg/resources/blueprint/mock_blueprint_handler.go similarity index 99% rename from pkg/blueprint/mock_blueprint_handler.go rename to pkg/resources/blueprint/mock_blueprint_handler.go index 73124cf6e..f76df4970 100644 --- a/pkg/blueprint/mock_blueprint_handler.go +++ b/pkg/resources/blueprint/mock_blueprint_handler.go @@ -2,8 +2,8 @@ package blueprint import ( blueprintv1alpha1 "github.com/windsorcli/cli/api/v1alpha1" - "github.com/windsorcli/cli/pkg/artifact" "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/resources/artifact" ) // MockBlueprintHandler is a mock implementation of BlueprintHandler interface for testing diff --git a/pkg/blueprint/mock_blueprint_handler_test.go b/pkg/resources/blueprint/mock_blueprint_handler_test.go similarity index 99% rename from pkg/blueprint/mock_blueprint_handler_test.go rename to pkg/resources/blueprint/mock_blueprint_handler_test.go index f88b2608f..6cc405303 100644 --- a/pkg/blueprint/mock_blueprint_handler_test.go +++ b/pkg/resources/blueprint/mock_blueprint_handler_test.go @@ -6,8 +6,8 @@ import ( "testing" blueprintv1alpha1 "github.com/windsorcli/cli/api/v1alpha1" - "github.com/windsorcli/cli/pkg/artifact" "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/resources/artifact" ) // ============================================================================= diff --git a/pkg/blueprint/shims.go b/pkg/resources/blueprint/shims.go similarity index 100% rename from pkg/blueprint/shims.go rename to pkg/resources/blueprint/shims.go diff --git a/pkg/blueprint/templates/default.jsonnet b/pkg/resources/blueprint/templates/default.jsonnet similarity index 100% rename from pkg/blueprint/templates/default.jsonnet rename to pkg/resources/blueprint/templates/default.jsonnet diff --git a/pkg/terraform/mock_module_resolver.go b/pkg/resources/terraform/mock_module_resolver.go similarity index 100% rename from pkg/terraform/mock_module_resolver.go rename to pkg/resources/terraform/mock_module_resolver.go diff --git a/pkg/terraform/mock_module_resolver_test.go b/pkg/resources/terraform/mock_module_resolver_test.go similarity index 100% rename from pkg/terraform/mock_module_resolver_test.go rename to pkg/resources/terraform/mock_module_resolver_test.go diff --git a/pkg/terraform/module_resolver.go b/pkg/resources/terraform/module_resolver.go similarity index 99% rename from pkg/terraform/module_resolver.go rename to pkg/resources/terraform/module_resolver.go index fac07e7a8..1a0d0fa5c 100644 --- a/pkg/terraform/module_resolver.go +++ b/pkg/resources/terraform/module_resolver.go @@ -6,8 +6,8 @@ import ( "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclwrite" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" "github.com/zclconf/go-cty/cty" ) diff --git a/pkg/terraform/module_resolver_test.go b/pkg/resources/terraform/module_resolver_test.go similarity index 99% rename from pkg/terraform/module_resolver_test.go rename to pkg/resources/terraform/module_resolver_test.go index 7a0cf6353..800edbe34 100644 --- a/pkg/terraform/module_resolver_test.go +++ b/pkg/resources/terraform/module_resolver_test.go @@ -12,10 +12,10 @@ import ( "testing" blueprintv1alpha1 "github.com/windsorcli/cli/api/v1alpha1" - "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" ) diff --git a/pkg/terraform/oci_module_resolver.go b/pkg/resources/terraform/oci_module_resolver.go similarity index 99% rename from pkg/terraform/oci_module_resolver.go rename to pkg/resources/terraform/oci_module_resolver.go index a44d22e12..ff3443309 100644 --- a/pkg/terraform/oci_module_resolver.go +++ b/pkg/resources/terraform/oci_module_resolver.go @@ -9,9 +9,9 @@ import ( "github.com/briandowns/spinner" blueprintv1alpha1 "github.com/windsorcli/cli/api/v1alpha1" - "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" ) // The OCIModuleResolver is a terraform module resolver for OCI artifact sources. diff --git a/pkg/terraform/oci_module_resolver_test.go b/pkg/resources/terraform/oci_module_resolver_test.go similarity index 99% rename from pkg/terraform/oci_module_resolver_test.go rename to pkg/resources/terraform/oci_module_resolver_test.go index 12d16a702..ef8a50cad 100644 --- a/pkg/terraform/oci_module_resolver_test.go +++ b/pkg/resources/terraform/oci_module_resolver_test.go @@ -9,8 +9,8 @@ import ( "testing" blueprintv1alpha1 "github.com/windsorcli/cli/api/v1alpha1" - "github.com/windsorcli/cli/pkg/artifact" "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/resources/artifact" "github.com/windsorcli/cli/pkg/shell" ) diff --git a/pkg/terraform/shims.go b/pkg/resources/terraform/shims.go similarity index 100% rename from pkg/terraform/shims.go rename to pkg/resources/terraform/shims.go diff --git a/pkg/terraform/standard_module_resolver.go b/pkg/resources/terraform/standard_module_resolver.go similarity index 99% rename from pkg/terraform/standard_module_resolver.go rename to pkg/resources/terraform/standard_module_resolver.go index 737f5a305..798c861d1 100644 --- a/pkg/terraform/standard_module_resolver.go +++ b/pkg/resources/terraform/standard_module_resolver.go @@ -5,9 +5,9 @@ import ( "path/filepath" "strings" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" ) diff --git a/pkg/terraform/standard_module_resolver_test.go b/pkg/resources/terraform/standard_module_resolver_test.go similarity index 99% rename from pkg/terraform/standard_module_resolver_test.go rename to pkg/resources/terraform/standard_module_resolver_test.go index 03b71dd47..c8c134b3f 100644 --- a/pkg/terraform/standard_module_resolver_test.go +++ b/pkg/resources/terraform/standard_module_resolver_test.go @@ -9,9 +9,9 @@ import ( "encoding/json" blueprintv1alpha1 "github.com/windsorcli/cli/api/v1alpha1" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" ) diff --git a/pkg/runtime/runtime.go b/pkg/runtime/runtime.go index c69ef4c2e..df9ed9bea 100644 --- a/pkg/runtime/runtime.go +++ b/pkg/runtime/runtime.go @@ -5,8 +5,6 @@ import ( "maps" "os" - "github.com/windsorcli/cli/pkg/artifact" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/cluster" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" @@ -14,10 +12,12 @@ import ( "github.com/windsorcli/cli/pkg/environment/tools" "github.com/windsorcli/cli/pkg/generators" "github.com/windsorcli/cli/pkg/kubernetes" + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" + "github.com/windsorcli/cli/pkg/resources/terraform" "github.com/windsorcli/cli/pkg/secrets" "github.com/windsorcli/cli/pkg/shell" "github.com/windsorcli/cli/pkg/shell/ssh" - "github.com/windsorcli/cli/pkg/terraform" "github.com/windsorcli/cli/pkg/types" "github.com/windsorcli/cli/pkg/workstation" "github.com/windsorcli/cli/pkg/workstation/network" diff --git a/pkg/runtime/runtime_loaders.go b/pkg/runtime/runtime_loaders.go index a939eaf1e..245a833c8 100644 --- a/pkg/runtime/runtime_loaders.go +++ b/pkg/runtime/runtime_loaders.go @@ -7,11 +7,11 @@ import ( "path/filepath" secretsConfigType "github.com/windsorcli/cli/api/v1alpha1/secrets" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/cluster" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/environment/envvars" "github.com/windsorcli/cli/pkg/kubernetes" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/secrets" "github.com/windsorcli/cli/pkg/shell" ) diff --git a/pkg/stack/stack.go b/pkg/stack/stack.go index d6179426f..0aa91b2f1 100644 --- a/pkg/stack/stack.go +++ b/pkg/stack/stack.go @@ -9,8 +9,8 @@ package stack import ( "fmt" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" ) diff --git a/pkg/stack/stack_test.go b/pkg/stack/stack_test.go index 8e4fe1475..5d41760bb 100644 --- a/pkg/stack/stack_test.go +++ b/pkg/stack/stack_test.go @@ -12,9 +12,9 @@ import ( "testing" blueprintv1alpha1 "github.com/windsorcli/cli/api/v1alpha1" - "github.com/windsorcli/cli/pkg/blueprint" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/resources/blueprint" "github.com/windsorcli/cli/pkg/shell" ) From 751fb8788048877d6a073821847f60e6f8e84ad0 Mon Sep 17 00:00:00 2001 From: Ryan VanGundy <85766511+rmvangun@users.noreply.github.com> Date: Tue, 28 Oct 2025 12:36:47 -0400 Subject: [PATCH 2/2] refactor(resources): Add resources manager The resources manager is responsible for generating all assets, including both terraform and kubernetes IaC files. Signed-off-by: Ryan VanGundy <85766511+rmvangun@users.noreply.github.com> --- pkg/resources/blueprint/blueprint_handler.go | 49 ++++ .../blueprint_handler_public_test.go | 214 +++++++++++++++++ .../blueprint/mock_blueprint_handler.go | 9 + .../blueprint/mock_blueprint_handler_test.go | 43 ++++ pkg/resources/resources.go | 152 +++++++++++++ pkg/resources/resources_test.go | 215 ++++++++++++++++++ pkg/types/context.go | 4 + 7 files changed, 686 insertions(+) create mode 100644 pkg/resources/resources.go create mode 100644 pkg/resources/resources_test.go diff --git a/pkg/resources/blueprint/blueprint_handler.go b/pkg/resources/blueprint/blueprint_handler.go index 5eaf15b67..6c18e4272 100644 --- a/pkg/resources/blueprint/blueprint_handler.go +++ b/pkg/resources/blueprint/blueprint_handler.go @@ -58,6 +58,7 @@ type BlueprintHandler interface { WaitForKustomizations(message string, names ...string) error GetDefaultTemplateData(contextName string) (map[string][]byte, error) GetLocalTemplateData() (map[string][]byte, error) + Generate() *blueprintv1alpha1.Blueprint Down() error } @@ -518,6 +519,54 @@ func (b *BaseBlueprintHandler) GetKustomizations() []blueprintv1alpha1.Kustomiza return kustomizations } +// Generate returns the fully processed blueprint with all defaults resolved, +// paths processed, and generation logic applied - equivalent to what would be deployed. +// It applies the same processing logic as GetKustomizations() but for the entire blueprint structure. +func (b *BaseBlueprintHandler) Generate() *blueprintv1alpha1.Blueprint { + generated := b.blueprint.DeepCopy() + + // Process kustomizations with the same logic as GetKustomizations() + for i := range generated.Kustomizations { + if generated.Kustomizations[i].Source == "" { + generated.Kustomizations[i].Source = generated.Metadata.Name + } + + if generated.Kustomizations[i].Path == "" { + generated.Kustomizations[i].Path = "kustomize" + } else { + generated.Kustomizations[i].Path = "kustomize/" + strings.ReplaceAll(generated.Kustomizations[i].Path, "\\", "/") + } + + if generated.Kustomizations[i].Interval == nil || generated.Kustomizations[i].Interval.Duration == 0 { + generated.Kustomizations[i].Interval = &metav1.Duration{Duration: constants.DEFAULT_FLUX_KUSTOMIZATION_INTERVAL} + } + if generated.Kustomizations[i].RetryInterval == nil || generated.Kustomizations[i].RetryInterval.Duration == 0 { + generated.Kustomizations[i].RetryInterval = &metav1.Duration{Duration: constants.DEFAULT_FLUX_KUSTOMIZATION_RETRY_INTERVAL} + } + if generated.Kustomizations[i].Timeout == nil || generated.Kustomizations[i].Timeout.Duration == 0 { + generated.Kustomizations[i].Timeout = &metav1.Duration{Duration: constants.DEFAULT_FLUX_KUSTOMIZATION_TIMEOUT} + } + if generated.Kustomizations[i].Wait == nil { + defaultWait := constants.DEFAULT_FLUX_KUSTOMIZATION_WAIT + generated.Kustomizations[i].Wait = &defaultWait + } + if generated.Kustomizations[i].Force == nil { + defaultForce := constants.DEFAULT_FLUX_KUSTOMIZATION_FORCE + generated.Kustomizations[i].Force = &defaultForce + } + if generated.Kustomizations[i].Destroy == nil { + defaultDestroy := true + generated.Kustomizations[i].Destroy = &defaultDestroy + } + } + + // Process terraform components with source resolution + b.resolveComponentSources(generated) + b.resolveComponentPaths(generated) + + return generated +} + // SetRenderedKustomizeData stores rendered kustomize data for use during install. // This includes values and patches from template processing that should be composed with user-defined files. func (b *BaseBlueprintHandler) SetRenderedKustomizeData(data map[string]any) { diff --git a/pkg/resources/blueprint/blueprint_handler_public_test.go b/pkg/resources/blueprint/blueprint_handler_public_test.go index c2929fe52..e65d845f6 100644 --- a/pkg/resources/blueprint/blueprint_handler_public_test.go +++ b/pkg/resources/blueprint/blueprint_handler_public_test.go @@ -4557,3 +4557,217 @@ metadata: } }) } + +func TestBaseBlueprintHandler_Generate(t *testing.T) { + setup := func(t *testing.T) (*BaseBlueprintHandler, *Mocks) { + t.Helper() + mocks := setupMocks(t) + handler := NewBlueprintHandler(mocks.Injector) + handler.shims = mocks.Shims + err := handler.Initialize() + if err != nil { + t.Fatalf("Failed to initialize handler: %v", err) + } + return handler, mocks + } + + t.Run("EmptyBlueprint", func(t *testing.T) { + // Given a handler with empty blueprint + handler, _ := setup(t) + handler.blueprint = blueprintv1alpha1.Blueprint{ + Metadata: blueprintv1alpha1.Metadata{ + Name: "test-blueprint", + }, + } + + // When generating blueprint + generated := handler.Generate() + + // Then should return a copy of the blueprint + if generated == nil { + t.Fatal("Expected non-nil generated blueprint") + } + if generated.Metadata.Name != "test-blueprint" { + t.Errorf("Expected name 'test-blueprint', got %s", generated.Metadata.Name) + } + }) + + t.Run("KustomizationsWithDefaults", func(t *testing.T) { + // Given a handler with kustomizations that need defaults + handler, _ := setup(t) + handler.blueprint = blueprintv1alpha1.Blueprint{ + Metadata: blueprintv1alpha1.Metadata{ + Name: "test-blueprint", + }, + Kustomizations: []blueprintv1alpha1.Kustomization{ + { + Name: "test-kustomization", + // No Source, Path, or other fields set + }, + }, + } + + // When generating blueprint + generated := handler.Generate() + + // Then kustomizations should have defaults applied + if len(generated.Kustomizations) != 1 { + t.Fatalf("Expected 1 kustomization, got %d", len(generated.Kustomizations)) + } + + kustomization := generated.Kustomizations[0] + if kustomization.Name != "test-kustomization" { + t.Errorf("Expected name 'test-kustomization', got %s", kustomization.Name) + } + if kustomization.Source != "test-blueprint" { + t.Errorf("Expected source 'test-blueprint', got %s", kustomization.Source) + } + if kustomization.Path != "kustomize" { + t.Errorf("Expected path 'kustomize', got %s", kustomization.Path) + } + if kustomization.Interval == nil || kustomization.Interval.Duration != constants.DEFAULT_FLUX_KUSTOMIZATION_INTERVAL { + t.Errorf("Expected default interval, got %v", kustomization.Interval) + } + if kustomization.RetryInterval == nil || kustomization.RetryInterval.Duration != constants.DEFAULT_FLUX_KUSTOMIZATION_RETRY_INTERVAL { + t.Errorf("Expected default retry interval, got %v", kustomization.RetryInterval) + } + if kustomization.Timeout == nil || kustomization.Timeout.Duration != constants.DEFAULT_FLUX_KUSTOMIZATION_TIMEOUT { + t.Errorf("Expected default timeout, got %v", kustomization.Timeout) + } + if kustomization.Wait == nil || *kustomization.Wait != constants.DEFAULT_FLUX_KUSTOMIZATION_WAIT { + t.Errorf("Expected default wait, got %v", kustomization.Wait) + } + if kustomization.Force == nil || *kustomization.Force != constants.DEFAULT_FLUX_KUSTOMIZATION_FORCE { + t.Errorf("Expected default force, got %v", kustomization.Force) + } + if kustomization.Destroy == nil || *kustomization.Destroy != true { + t.Errorf("Expected default destroy true, got %v", kustomization.Destroy) + } + }) + + t.Run("KustomizationsWithCustomPath", func(t *testing.T) { + // Given a handler with kustomization with custom path + handler, _ := setup(t) + handler.blueprint = blueprintv1alpha1.Blueprint{ + Metadata: blueprintv1alpha1.Metadata{ + Name: "test-blueprint", + }, + Kustomizations: []blueprintv1alpha1.Kustomization{ + { + Name: "test-kustomization", + Path: "custom/path", + }, + }, + } + + // When generating blueprint + generated := handler.Generate() + + // Then path should be prefixed with kustomize/ + if len(generated.Kustomizations) != 1 { + t.Fatalf("Expected 1 kustomization, got %d", len(generated.Kustomizations)) + } + + expectedPath := "kustomize/custom/path" + if generated.Kustomizations[0].Path != expectedPath { + t.Errorf("Expected path '%s', got '%s'", expectedPath, generated.Kustomizations[0].Path) + } + }) + + t.Run("KustomizationsWithBackslashes", func(t *testing.T) { + // Given a handler with kustomization with backslashes in path + handler, _ := setup(t) + handler.blueprint = blueprintv1alpha1.Blueprint{ + Metadata: blueprintv1alpha1.Metadata{ + Name: "test-blueprint", + }, + Kustomizations: []blueprintv1alpha1.Kustomization{ + { + Name: "test-kustomization", + Path: "custom\\path\\with\\backslashes", + }, + }, + } + + // When generating blueprint + generated := handler.Generate() + + // Then backslashes should be replaced with forward slashes + if len(generated.Kustomizations) != 1 { + t.Fatalf("Expected 1 kustomization, got %d", len(generated.Kustomizations)) + } + + expectedPath := "kustomize/custom/path/with/backslashes" + if generated.Kustomizations[0].Path != expectedPath { + t.Errorf("Expected path '%s', got '%s'", expectedPath, generated.Kustomizations[0].Path) + } + }) + + t.Run("TerraformComponentsWithSourceResolution", func(t *testing.T) { + // Given a handler with terraform components + handler, _ := setup(t) + handler.blueprint = blueprintv1alpha1.Blueprint{ + Metadata: blueprintv1alpha1.Metadata{ + Name: "test-blueprint", + }, + Sources: []blueprintv1alpha1.Source{ + { + Name: "test-source", + Url: "https://github.com/example/terraform-modules", + }, + }, + TerraformComponents: []blueprintv1alpha1.TerraformComponent{ + { + Source: "test-source", + Path: "modules/example", + }, + }, + } + + // When generating blueprint + generated := handler.Generate() + + // Then terraform components should be processed + if len(generated.TerraformComponents) != 1 { + t.Fatalf("Expected 1 terraform component, got %d", len(generated.TerraformComponents)) + } + + component := generated.TerraformComponents[0] + expectedSource := "https://github.com/example/terraform-modules//terraform/modules/example?ref=" + if component.Source != expectedSource { + t.Errorf("Expected source '%s', got %s", expectedSource, component.Source) + } + if component.Path != "modules/example" { + t.Errorf("Expected path 'modules/example', got %s", component.Path) + } + }) + + t.Run("PreservesOriginalBlueprint", func(t *testing.T) { + // Given a handler with blueprint data + handler, _ := setup(t) + originalBlueprint := blueprintv1alpha1.Blueprint{ + Metadata: blueprintv1alpha1.Metadata{ + Name: "test-blueprint", + }, + Kustomizations: []blueprintv1alpha1.Kustomization{ + { + Name: "test-kustomization", + }, + }, + } + handler.blueprint = originalBlueprint + + // When generating blueprint + generated := handler.Generate() + + // Then original blueprint should be unchanged + if handler.blueprint.Kustomizations[0].Source != "" { + t.Error("Original blueprint should not be modified") + } + + // And generated blueprint should have defaults + if generated.Kustomizations[0].Source != "test-blueprint" { + t.Error("Generated blueprint should have defaults applied") + } + }) +} diff --git a/pkg/resources/blueprint/mock_blueprint_handler.go b/pkg/resources/blueprint/mock_blueprint_handler.go index f76df4970..342ec4edc 100644 --- a/pkg/resources/blueprint/mock_blueprint_handler.go +++ b/pkg/resources/blueprint/mock_blueprint_handler.go @@ -26,6 +26,7 @@ type MockBlueprintHandler struct { DownFunc func() error SetRenderedKustomizeDataFunc func(data map[string]any) + GenerateFunc func() *blueprintv1alpha1.Blueprint } // ============================================================================= @@ -172,5 +173,13 @@ func (m *MockBlueprintHandler) GetLocalTemplateData() (map[string][]byte, error) return map[string][]byte{}, nil } +// Generate calls the mock GenerateFunc if set, otherwise returns nil +func (m *MockBlueprintHandler) Generate() *blueprintv1alpha1.Blueprint { + if m.GenerateFunc != nil { + return m.GenerateFunc() + } + return nil +} + // Ensure MockBlueprintHandler implements BlueprintHandler var _ BlueprintHandler = (*MockBlueprintHandler)(nil) diff --git a/pkg/resources/blueprint/mock_blueprint_handler_test.go b/pkg/resources/blueprint/mock_blueprint_handler_test.go index 6cc405303..9a33a3f50 100644 --- a/pkg/resources/blueprint/mock_blueprint_handler_test.go +++ b/pkg/resources/blueprint/mock_blueprint_handler_test.go @@ -706,3 +706,46 @@ func TestMockBlueprintHandler_LoadData(t *testing.T) { } }) } + +func TestMockBlueprintHandler_Generate(t *testing.T) { + setup := func(t *testing.T) *MockBlueprintHandler { + t.Helper() + injector := di.NewInjector() + handler := NewMockBlueprintHandler(injector) + return handler + } + + t.Run("WithFuncSet", func(t *testing.T) { + // Given a mock handler with generate function + handler := setup(t) + expectedBlueprint := &blueprintv1alpha1.Blueprint{ + Metadata: blueprintv1alpha1.Metadata{ + Name: "test-generated-blueprint", + }, + } + handler.GenerateFunc = func() *blueprintv1alpha1.Blueprint { + return expectedBlueprint + } + + // When generating blueprint + generated := handler.Generate() + + // Then expected blueprint should be returned + if !reflect.DeepEqual(generated, expectedBlueprint) { + t.Errorf("Expected blueprint = %v, got = %v", expectedBlueprint, generated) + } + }) + + t.Run("WithNoFuncSet", func(t *testing.T) { + // Given a mock handler without generate function + handler := setup(t) + + // When generating blueprint + generated := handler.Generate() + + // Then nil should be returned + if generated != nil { + t.Errorf("Expected nil, got %v", generated) + } + }) +} diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go new file mode 100644 index 000000000..7b8356d1a --- /dev/null +++ b/pkg/resources/resources.go @@ -0,0 +1,152 @@ +package resources + +import ( + "fmt" + + "github.com/windsorcli/cli/pkg/resources/artifact" + "github.com/windsorcli/cli/pkg/resources/blueprint" + "github.com/windsorcli/cli/pkg/resources/terraform" + "github.com/windsorcli/cli/pkg/types" +) + +// The Resources package provides high-level resource management functionality +// for artifact, blueprint, and terraform operations. It consolidates the creation +// and management of these core resources, providing a unified interface for +// resource lifecycle operations across the Windsor CLI. + +// ============================================================================= +// Types +// ============================================================================= + +// ResourcesExecutionContext holds the execution context for resource operations. +// It embeds the base ExecutionContext and includes all resource-specific dependencies. +type ResourcesExecutionContext struct { + types.ExecutionContext + + // Resource-specific dependencies + ArtifactBuilder artifact.Artifact + BlueprintHandler blueprint.BlueprintHandler + TerraformResolver terraform.ModuleResolver +} + +// Resources manages the lifecycle of all resource types (artifact, blueprint, terraform). +// It provides a unified interface for creating, initializing, and managing these resources +// with proper dependency injection and error handling. +type Resources struct { + *ResourcesExecutionContext +} + +// ============================================================================= +// Constructor +// ============================================================================= + +// NewResources creates and initializes a new Resources instance with the provided execution context. +// It sets up all required resource handlers—artifact builder, blueprint handler, and terraform resolver— +// and registers each handler with the dependency injector for use throughout the resource lifecycle. +// Returns a pointer to the fully initialized Resources struct. +func NewResources(ctx *ResourcesExecutionContext) *Resources { + resources := &Resources{ + ResourcesExecutionContext: ctx, + } + + resources.ArtifactBuilder = artifact.NewArtifactBuilder() + resources.Injector.Register("artifactBuilder", resources.ArtifactBuilder) + + resources.BlueprintHandler = blueprint.NewBlueprintHandler(resources.Injector) + resources.Injector.Register("blueprintHandler", resources.BlueprintHandler) + + resources.TerraformResolver = terraform.NewStandardModuleResolver(resources.Injector) + resources.Injector.Register("terraformResolver", resources.TerraformResolver) + + return resources +} + +// ============================================================================= +// Public Methods +// ============================================================================= + +// Bundle creates a complete artifact bundle from the project's templates, kustomize, and terraform files. +// It initializes the artifact builder and creates a distributable artifact. +// The outputPath specifies where to save the bundle file. Returns the actual output path or an error. +func (r *Resources) Bundle(outputPath, tag string) (string, error) { + if err := r.ArtifactBuilder.Initialize(r.Injector); err != nil { + return "", fmt.Errorf("failed to initialize artifact builder: %w", err) + } + + actualOutputPath, err := r.ArtifactBuilder.Write(outputPath, tag) + if err != nil { + return "", fmt.Errorf("failed to create artifact bundle: %w", err) + } + + return actualOutputPath, nil +} + +// Push creates and pushes an artifact to a container registry. +// It bundles all project files and pushes them to the specified registry with the given tag. +// Returns the registry URL or an error. +func (r *Resources) Push(registryBase, repoName, tag string) (string, error) { + if err := r.ArtifactBuilder.Initialize(r.Injector); err != nil { + return "", fmt.Errorf("failed to initialize artifact builder: %w", err) + } + + if err := r.ArtifactBuilder.Bundle(); err != nil { + return "", fmt.Errorf("failed to bundle artifacts: %w", err) + } + + if err := r.ArtifactBuilder.Push(registryBase, repoName, tag); err != nil { + return "", fmt.Errorf("failed to push artifact: %w", err) + } + + registryURL := fmt.Sprintf("%s/%s", registryBase, repoName) + if tag != "" { + registryURL = fmt.Sprintf("%s:%s", registryURL, tag) + } + + return registryURL, nil +} + +// Generate processes and deploys the complete project infrastructure. +// It initializes all core resources, processes blueprints, and handles terraform modules +// for the project. The optional overwrite parameter determines whether existing files +// should be overwritten during blueprint processing. This is the main deployment method. +// Returns an error if any initialization or processing step fails. +func (r *Resources) Generate(overwrite ...bool) error { + shouldOverwrite := false + if len(overwrite) > 0 { + shouldOverwrite = overwrite[0] + } + + if err := r.BlueprintHandler.Initialize(); err != nil { + return fmt.Errorf("failed to initialize blueprint handler: %w", err) + } + if err := r.BlueprintHandler.LoadBlueprint(); err != nil { + return fmt.Errorf("failed to load blueprint data: %w", err) + } + + r.Blueprint = r.BlueprintHandler.Generate() + + if err := r.TerraformResolver.Initialize(); err != nil { + return fmt.Errorf("failed to initialize terraform resolver: %w", err) + } + + if err := r.BlueprintHandler.Write(shouldOverwrite); err != nil { + return fmt.Errorf("failed to write blueprint files: %w", err) + } + + if err := r.TerraformResolver.ProcessModules(); err != nil { + return fmt.Errorf("failed to process terraform modules: %w", err) + } + + return nil +} + +// ============================================================================= +// Helper Functions +// ============================================================================= + +// CreateResources creates a new Resources instance with all dependencies properly initialized. +// This is a convenience function that creates a fully configured Resources +// with the provided execution context. +func CreateResources(ctx *ResourcesExecutionContext) *Resources { + return NewResources(ctx) +} diff --git a/pkg/resources/resources_test.go b/pkg/resources/resources_test.go new file mode 100644 index 000000000..520a787bf --- /dev/null +++ b/pkg/resources/resources_test.go @@ -0,0 +1,215 @@ +package resources + +import ( + "testing" + + "github.com/windsorcli/cli/pkg/config" + "github.com/windsorcli/cli/pkg/di" + "github.com/windsorcli/cli/pkg/shell" + "github.com/windsorcli/cli/pkg/types" +) + +// ============================================================================= +// Test Setup +// ============================================================================= + +// setupResourcesMocks creates mock components for testing the Resources +func setupResourcesMocks(t *testing.T) *Mocks { + t.Helper() + + injector := di.NewInjector() + configHandler := config.NewMockConfigHandler() + shell := shell.NewMockShell() + + // Create execution context + execCtx := &types.ExecutionContext{ + ContextName: "test-context", + ProjectRoot: "/test/project", + ConfigRoot: "/test/project/contexts/test-context", + TemplateRoot: "/test/project/contexts/_template", + Injector: injector, + ConfigHandler: configHandler, + Shell: shell, + } + + // Create resources execution context + resourcesCtx := &ResourcesExecutionContext{ + ExecutionContext: *execCtx, + } + + return &Mocks{ + Injector: injector, + ConfigHandler: configHandler, + Shell: shell, + ResourcesExecutionContext: resourcesCtx, + } +} + +// Mocks contains all the mock dependencies for testing +type Mocks struct { + Injector di.Injector + ConfigHandler config.ConfigHandler + Shell shell.Shell + ResourcesExecutionContext *ResourcesExecutionContext +} + +// ============================================================================= +// Test Constructor +// ============================================================================= + +func TestNewResources(t *testing.T) { + t.Run("CreatesResourcesWithDependencies", func(t *testing.T) { + mocks := setupResourcesMocks(t) + + resources := NewResources(mocks.ResourcesExecutionContext) + + if resources == nil { + t.Fatal("Expected Resources to be created") + } + + if resources.Injector != mocks.Injector { + t.Error("Expected injector to be set") + } + + if resources.Shell != mocks.Shell { + t.Error("Expected shell to be set") + } + + if resources.ConfigHandler != mocks.ConfigHandler { + t.Error("Expected config handler to be set") + } + + if resources.ArtifactBuilder == nil { + t.Error("Expected artifact builder to be initialized") + } + + if resources.BlueprintHandler == nil { + t.Error("Expected blueprint handler to be initialized") + } + + if resources.TerraformResolver == nil { + t.Error("Expected terraform resolver to be initialized") + } + }) +} + +func TestCreateResources(t *testing.T) { + t.Run("CreatesResourcesWithDependencies", func(t *testing.T) { + mocks := setupResourcesMocks(t) + + resources := CreateResources(mocks.ResourcesExecutionContext) + + if resources == nil { + t.Fatal("Expected Resources to be created") + } + + if resources.Injector != mocks.Injector { + t.Error("Expected injector to be set") + } + + if resources.ConfigHandler != mocks.ConfigHandler { + t.Error("Expected config handler to be set") + } + + if resources.Shell != mocks.Shell { + t.Error("Expected shell to be set") + } + }) +} + +// ============================================================================= +// Test Public Methods +// ============================================================================= + +func TestResources_Bundle(t *testing.T) { + t.Run("HandlesBundleSuccessfully", func(t *testing.T) { + mocks := setupResourcesMocks(t) + resources := NewResources(mocks.ResourcesExecutionContext) + + // This test would need proper mocking of the artifact builder + // For now, we'll just test that the method exists and handles errors + _, err := resources.Bundle("/test/output", "v1.0.0") + // We expect an error here because we don't have proper mocks set up + if err == nil { + t.Error("Expected error due to missing mocks, but got nil") + } + }) +} + +func TestResources_Push(t *testing.T) { + t.Run("HandlesPushSuccessfully", func(t *testing.T) { + mocks := setupResourcesMocks(t) + resources := NewResources(mocks.ResourcesExecutionContext) + + // This test would need proper mocking of the artifact builder + // For now, we'll just test that the method exists and handles errors + _, err := resources.Push("ghcr.io", "test/repo", "latest") + // We expect an error here because we don't have proper mocks set up + if err == nil { + t.Error("Expected error due to missing mocks, but got nil") + } + }) +} + +func TestResources_Generate(t *testing.T) { + t.Run("HandlesGenerateSuccessfully", func(t *testing.T) { + mocks := setupResourcesMocks(t) + resources := NewResources(mocks.ResourcesExecutionContext) + + // This test would need proper mocking of the blueprint handler and terraform resolver + // For now, we'll just test that the method exists and handles errors + err := resources.Generate() + // We expect an error here because we don't have proper mocks set up + if err == nil { + t.Error("Expected error due to missing mocks, but got nil") + } + }) + + t.Run("HandlesGenerateWithOverwrite", func(t *testing.T) { + mocks := setupResourcesMocks(t) + resources := NewResources(mocks.ResourcesExecutionContext) + + // This test would need proper mocking of the blueprint handler and terraform resolver + // For now, we'll just test that the method exists and handles errors + err := resources.Generate(true) + // We expect an error here because we don't have proper mocks set up + if err == nil { + t.Error("Expected error due to missing mocks, but got nil") + } + }) +} + +// ============================================================================= +// Test ResourcesExecutionContext +// ============================================================================= + +func TestResourcesExecutionContext(t *testing.T) { + t.Run("CreatesResourcesExecutionContext", func(t *testing.T) { + execCtx := &types.ExecutionContext{ + ContextName: "test-context", + ProjectRoot: "/test/project", + ConfigRoot: "/test/project/contexts/test-context", + TemplateRoot: "/test/project/contexts/_template", + } + + resourcesCtx := &ResourcesExecutionContext{ + ExecutionContext: *execCtx, + } + + if resourcesCtx.ContextName != "test-context" { + t.Errorf("Expected context name 'test-context', got: %s", resourcesCtx.ContextName) + } + + if resourcesCtx.ProjectRoot != "/test/project" { + t.Errorf("Expected project root '/test/project', got: %s", resourcesCtx.ProjectRoot) + } + + if resourcesCtx.ConfigRoot != "/test/project/contexts/test-context" { + t.Errorf("Expected config root '/test/project/contexts/test-context', got: %s", resourcesCtx.ConfigRoot) + } + + if resourcesCtx.TemplateRoot != "/test/project/contexts/_template" { + t.Errorf("Expected template root '/test/project/contexts/_template', got: %s", resourcesCtx.TemplateRoot) + } + }) +} diff --git a/pkg/types/context.go b/pkg/types/context.go index eafc841c3..6bd3ab993 100644 --- a/pkg/types/context.go +++ b/pkg/types/context.go @@ -1,6 +1,7 @@ package types import ( + "github.com/windsorcli/cli/api/v1alpha1" "github.com/windsorcli/cli/pkg/config" "github.com/windsorcli/cli/pkg/di" "github.com/windsorcli/cli/pkg/secrets" @@ -30,6 +31,9 @@ type ExecutionContext struct { ConfigHandler config.ConfigHandler Shell shell.Shell + // Blueprint contains the generated blueprint data from the resources package + Blueprint *v1alpha1.Blueprint + // SecretsProviders contains providers for Sops and 1Password secrets management SecretsProviders struct { Sops secrets.SecretsProvider