From eb62e3eec1b4a5e23f467ebbf3a2736cef2d12cc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 10:17:05 +0100 Subject: [PATCH] Backport of Add component registry source resolution support to Terraform Stacks into v1.14 (#37983) * Add component registry source resolution support to Terraform Stacks This change implements the missing component source resolution case in the stack configuration loader, enabling Terraform Stacks to properly handle component registry sources from HCP Terraform and other component registries. The implementation mirrors the existing module registry resolution workflow, where component sources are first resolved to their versioned form using the source bundle's component metadata, then converted to final source addresses that can be used to locate the actual component code. This completes the integration between the terraform-registry-address component parsing capabilities and the go-slug sourcebundle component resolution APIs. * chore: bump go-slug to v0.18.1 * fix: add case for component final source type * chore: rm space * chore: sync module deps * chore: update testdata with separate bundle * fix: manifest file json obj with trailing comma * Add changelog entry to 1.14 * fix deps --------- Co-authored-by: James Pogran Co-authored-by: Michael Yocca Co-authored-by: Samsondeen Dare --- .../v1.14/ENHANCEMENTS-20251204-125848.yaml | 5 ++ go.mod | 2 +- go.sum | 4 +- internal/backend/remote-state/azure/go.mod | 2 +- internal/backend/remote-state/azure/go.sum | 4 +- internal/backend/remote-state/consul/go.mod | 2 +- internal/backend/remote-state/consul/go.sum | 4 +- internal/backend/remote-state/cos/go.mod | 2 +- internal/backend/remote-state/cos/go.sum | 4 +- internal/backend/remote-state/gcs/go.mod | 2 +- internal/backend/remote-state/gcs/go.sum | 4 +- .../backend/remote-state/kubernetes/go.mod | 2 +- .../backend/remote-state/kubernetes/go.sum | 4 +- internal/backend/remote-state/oci/go.mod | 2 +- internal/backend/remote-state/oci/go.sum | 4 +- internal/backend/remote-state/oss/go.mod | 2 +- internal/backend/remote-state/oss/go.sum | 4 +- internal/backend/remote-state/pg/go.mod | 2 +- internal/backend/remote-state/pg/go.sum | 4 +- internal/backend/remote-state/s3/go.mod | 2 +- internal/backend/remote-state/s3/go.sum | 4 +- internal/legacy/go.mod | 2 +- internal/legacy/go.sum | 4 +- internal/stacks/stackconfig/config.go | 27 ++++++ internal/stacks/stackconfig/config_test.go | 83 +++++++++++++++++++ .../basics-bundle/terraform-sources.json | 2 +- .../embedded-stack-bundle/component/a/main.tf | 17 ++++ .../component/comp.tfcomponent.hcl | 22 +++++ .../root/main.tfcomponent.hcl | 24 ++++++ .../terraform-sources.json | 29 +++++++ 30 files changed, 241 insertions(+), 34 deletions(-) create mode 100644 .changes/v1.14/ENHANCEMENTS-20251204-125848.yaml create mode 100644 internal/stacks/stackconfig/testdata/embedded-stack-bundle/component/a/main.tf create mode 100644 internal/stacks/stackconfig/testdata/embedded-stack-bundle/component/comp.tfcomponent.hcl create mode 100644 internal/stacks/stackconfig/testdata/embedded-stack-bundle/root/main.tfcomponent.hcl create mode 100644 internal/stacks/stackconfig/testdata/embedded-stack-bundle/terraform-sources.json diff --git a/.changes/v1.14/ENHANCEMENTS-20251204-125848.yaml b/.changes/v1.14/ENHANCEMENTS-20251204-125848.yaml new file mode 100644 index 0000000000..785f51cfb7 --- /dev/null +++ b/.changes/v1.14/ENHANCEMENTS-20251204-125848.yaml @@ -0,0 +1,5 @@ +kind: ENHANCEMENTS +body: Add component registry source resolution support to Terraform Stacks +time: 2025-12-04T12:58:48.622196-05:00 +custom: + Issue: "37888" diff --git a/go.mod b/go.mod index a65e46297b..f4a899fd08 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/go-plugin v1.7.0 github.com/hashicorp/go-retryablehttp v0.7.8 - github.com/hashicorp/go-slug v0.16.8 + github.com/hashicorp/go-slug v0.18.1 github.com/hashicorp/go-tfe v1.94.0 github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.7.0 diff --git a/go.sum b/go.sum index f2178d9e36..fec2679c16 100644 --- a/go.sum +++ b/go.sum @@ -482,8 +482,8 @@ github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3 github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-slug v0.16.8 h1:f4/sDZqRsxx006HrE6e9BE5xO9lWXydKhVoH6Kb0v1M= -github.com/hashicorp/go-slug v0.16.8/go.mod h1:hB4mUcVHl4RPu0205s0fwmB9i31MxQgeafGkko3FD+Y= +github.com/hashicorp/go-slug v0.18.1 h1:UnWIy4mq9GaDr1LhAzCPgA6RSQUn952RLFqQe3HPyCs= +github.com/hashicorp/go-slug v0.18.1/go.mod h1:Zxkkl8/LfXmhxZO3fLXQUCy3MVXAJK9pybY8WoDPgvs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-sockaddr v1.0.5 h1:dvk7TIXCZpmfOlM+9mlcrWmWjw/wlKT+VDq2wMvfPJU= diff --git a/internal/backend/remote-state/azure/go.mod b/internal/backend/remote-state/azure/go.mod index 6a4a7019fd..aca586847a 100644 --- a/internal/backend/remote-state/azure/go.mod +++ b/internal/backend/remote-state/azure/go.mod @@ -34,7 +34,7 @@ require ( github.com/hashicorp/go-cty v1.4.1 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-retryablehttp v0.7.8 // indirect - github.com/hashicorp/go-slug v0.16.8 // indirect + github.com/hashicorp/go-slug v0.18.1 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect diff --git a/internal/backend/remote-state/azure/go.sum b/internal/backend/remote-state/azure/go.sum index 93f4cdc17c..5337273e9e 100644 --- a/internal/backend/remote-state/azure/go.sum +++ b/internal/backend/remote-state/azure/go.sum @@ -241,8 +241,8 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1 github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= -github.com/hashicorp/go-slug v0.16.8 h1:f4/sDZqRsxx006HrE6e9BE5xO9lWXydKhVoH6Kb0v1M= -github.com/hashicorp/go-slug v0.16.8/go.mod h1:hB4mUcVHl4RPu0205s0fwmB9i31MxQgeafGkko3FD+Y= +github.com/hashicorp/go-slug v0.18.1 h1:UnWIy4mq9GaDr1LhAzCPgA6RSQUn952RLFqQe3HPyCs= +github.com/hashicorp/go-slug v0.18.1/go.mod h1:Zxkkl8/LfXmhxZO3fLXQUCy3MVXAJK9pybY8WoDPgvs= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= diff --git a/internal/backend/remote-state/consul/go.mod b/internal/backend/remote-state/consul/go.mod index 7c8ddd8a71..e138052eae 100644 --- a/internal/backend/remote-state/consul/go.mod +++ b/internal/backend/remote-state/consul/go.mod @@ -27,7 +27,7 @@ require ( github.com/hashicorp/go-metrics v0.5.4 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-slug v0.16.8 // indirect + github.com/hashicorp/go-slug v0.18.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect diff --git a/internal/backend/remote-state/consul/go.sum b/internal/backend/remote-state/consul/go.sum index 8bad5b13ad..127b1b1c39 100644 --- a/internal/backend/remote-state/consul/go.sum +++ b/internal/backend/remote-state/consul/go.sum @@ -252,8 +252,8 @@ github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVU github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-slug v0.16.8 h1:f4/sDZqRsxx006HrE6e9BE5xO9lWXydKhVoH6Kb0v1M= -github.com/hashicorp/go-slug v0.16.8/go.mod h1:hB4mUcVHl4RPu0205s0fwmB9i31MxQgeafGkko3FD+Y= +github.com/hashicorp/go-slug v0.18.1 h1:UnWIy4mq9GaDr1LhAzCPgA6RSQUn952RLFqQe3HPyCs= +github.com/hashicorp/go-slug v0.18.1/go.mod h1:Zxkkl8/LfXmhxZO3fLXQUCy3MVXAJK9pybY8WoDPgvs= github.com/hashicorp/go-sockaddr v1.0.5 h1:dvk7TIXCZpmfOlM+9mlcrWmWjw/wlKT+VDq2wMvfPJU= github.com/hashicorp/go-sockaddr v1.0.5/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= diff --git a/internal/backend/remote-state/cos/go.mod b/internal/backend/remote-state/cos/go.mod index e1c23757b4..c1c6f619d9 100644 --- a/internal/backend/remote-state/cos/go.mod +++ b/internal/backend/remote-state/cos/go.mod @@ -23,7 +23,7 @@ require ( github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/go-slug v0.16.8 // indirect + github.com/hashicorp/go-slug v0.18.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect diff --git a/internal/backend/remote-state/cos/go.sum b/internal/backend/remote-state/cos/go.sum index 4424c8a67a..a50527e754 100644 --- a/internal/backend/remote-state/cos/go.sum +++ b/internal/backend/remote-state/cos/go.sum @@ -210,8 +210,8 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1 github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= -github.com/hashicorp/go-slug v0.16.8 h1:f4/sDZqRsxx006HrE6e9BE5xO9lWXydKhVoH6Kb0v1M= -github.com/hashicorp/go-slug v0.16.8/go.mod h1:hB4mUcVHl4RPu0205s0fwmB9i31MxQgeafGkko3FD+Y= +github.com/hashicorp/go-slug v0.18.1 h1:UnWIy4mq9GaDr1LhAzCPgA6RSQUn952RLFqQe3HPyCs= +github.com/hashicorp/go-slug v0.18.1/go.mod h1:Zxkkl8/LfXmhxZO3fLXQUCy3MVXAJK9pybY8WoDPgvs= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= diff --git a/internal/backend/remote-state/gcs/go.mod b/internal/backend/remote-state/gcs/go.mod index 5d10568a3d..3371209270 100644 --- a/internal/backend/remote-state/gcs/go.mod +++ b/internal/backend/remote-state/gcs/go.mod @@ -34,7 +34,7 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-slug v0.16.8 // indirect + github.com/hashicorp/go-slug v0.18.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect diff --git a/internal/backend/remote-state/gcs/go.sum b/internal/backend/remote-state/gcs/go.sum index f7109b8560..6aca1e3839 100644 --- a/internal/backend/remote-state/gcs/go.sum +++ b/internal/backend/remote-state/gcs/go.sum @@ -215,8 +215,8 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1 github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= -github.com/hashicorp/go-slug v0.16.8 h1:f4/sDZqRsxx006HrE6e9BE5xO9lWXydKhVoH6Kb0v1M= -github.com/hashicorp/go-slug v0.16.8/go.mod h1:hB4mUcVHl4RPu0205s0fwmB9i31MxQgeafGkko3FD+Y= +github.com/hashicorp/go-slug v0.18.1 h1:UnWIy4mq9GaDr1LhAzCPgA6RSQUn952RLFqQe3HPyCs= +github.com/hashicorp/go-slug v0.18.1/go.mod h1:Zxkkl8/LfXmhxZO3fLXQUCy3MVXAJK9pybY8WoDPgvs= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= diff --git a/internal/backend/remote-state/kubernetes/go.mod b/internal/backend/remote-state/kubernetes/go.mod index 393f221989..c9c9d67ea6 100644 --- a/internal/backend/remote-state/kubernetes/go.mod +++ b/internal/backend/remote-state/kubernetes/go.mod @@ -29,7 +29,7 @@ require ( github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/go-slug v0.16.8 // indirect + github.com/hashicorp/go-slug v0.18.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect diff --git a/internal/backend/remote-state/kubernetes/go.sum b/internal/backend/remote-state/kubernetes/go.sum index cd21ecd9c4..a43b8f4d05 100644 --- a/internal/backend/remote-state/kubernetes/go.sum +++ b/internal/backend/remote-state/kubernetes/go.sum @@ -227,8 +227,8 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1 github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= -github.com/hashicorp/go-slug v0.16.8 h1:f4/sDZqRsxx006HrE6e9BE5xO9lWXydKhVoH6Kb0v1M= -github.com/hashicorp/go-slug v0.16.8/go.mod h1:hB4mUcVHl4RPu0205s0fwmB9i31MxQgeafGkko3FD+Y= +github.com/hashicorp/go-slug v0.18.1 h1:UnWIy4mq9GaDr1LhAzCPgA6RSQUn952RLFqQe3HPyCs= +github.com/hashicorp/go-slug v0.18.1/go.mod h1:Zxkkl8/LfXmhxZO3fLXQUCy3MVXAJK9pybY8WoDPgvs= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= diff --git a/internal/backend/remote-state/oci/go.mod b/internal/backend/remote-state/oci/go.mod index 9d528f123c..51f2cac592 100644 --- a/internal/backend/remote-state/oci/go.mod +++ b/internal/backend/remote-state/oci/go.mod @@ -21,7 +21,7 @@ require ( github.com/fatih/color v1.18.0 // indirect github.com/gofrs/flock v0.10.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/go-slug v0.16.8 // indirect + github.com/hashicorp/go-slug v0.18.1 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect github.com/hashicorp/terraform-registry-address v0.4.0 // indirect diff --git a/internal/backend/remote-state/oci/go.sum b/internal/backend/remote-state/oci/go.sum index a6e6f7e9db..4145c5aa8e 100644 --- a/internal/backend/remote-state/oci/go.sum +++ b/internal/backend/remote-state/oci/go.sum @@ -208,8 +208,8 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1 github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= -github.com/hashicorp/go-slug v0.16.8 h1:f4/sDZqRsxx006HrE6e9BE5xO9lWXydKhVoH6Kb0v1M= -github.com/hashicorp/go-slug v0.16.8/go.mod h1:hB4mUcVHl4RPu0205s0fwmB9i31MxQgeafGkko3FD+Y= +github.com/hashicorp/go-slug v0.18.1 h1:UnWIy4mq9GaDr1LhAzCPgA6RSQUn952RLFqQe3HPyCs= +github.com/hashicorp/go-slug v0.18.1/go.mod h1:Zxkkl8/LfXmhxZO3fLXQUCy3MVXAJK9pybY8WoDPgvs= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= diff --git a/internal/backend/remote-state/oss/go.mod b/internal/backend/remote-state/oss/go.mod index ddfaf91a70..4616b6f847 100644 --- a/internal/backend/remote-state/oss/go.mod +++ b/internal/backend/remote-state/oss/go.mod @@ -26,7 +26,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/go-slug v0.16.8 // indirect + github.com/hashicorp/go-slug v0.18.1 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect github.com/hashicorp/terraform-registry-address v0.4.0 // indirect diff --git a/internal/backend/remote-state/oss/go.sum b/internal/backend/remote-state/oss/go.sum index 4ca1c6f13d..1fbbc7c258 100644 --- a/internal/backend/remote-state/oss/go.sum +++ b/internal/backend/remote-state/oss/go.sum @@ -215,8 +215,8 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1 github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= -github.com/hashicorp/go-slug v0.16.8 h1:f4/sDZqRsxx006HrE6e9BE5xO9lWXydKhVoH6Kb0v1M= -github.com/hashicorp/go-slug v0.16.8/go.mod h1:hB4mUcVHl4RPu0205s0fwmB9i31MxQgeafGkko3FD+Y= +github.com/hashicorp/go-slug v0.18.1 h1:UnWIy4mq9GaDr1LhAzCPgA6RSQUn952RLFqQe3HPyCs= +github.com/hashicorp/go-slug v0.18.1/go.mod h1:Zxkkl8/LfXmhxZO3fLXQUCy3MVXAJK9pybY8WoDPgvs= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= diff --git a/internal/backend/remote-state/pg/go.mod b/internal/backend/remote-state/pg/go.mod index a396233947..81184d7083 100644 --- a/internal/backend/remote-state/pg/go.mod +++ b/internal/backend/remote-state/pg/go.mod @@ -19,7 +19,7 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/go-slug v0.16.8 // indirect + github.com/hashicorp/go-slug v0.18.1 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/terraform-registry-address v0.4.0 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect diff --git a/internal/backend/remote-state/pg/go.sum b/internal/backend/remote-state/pg/go.sum index 4da7282276..5205f422c5 100644 --- a/internal/backend/remote-state/pg/go.sum +++ b/internal/backend/remote-state/pg/go.sum @@ -203,8 +203,8 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1 github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= -github.com/hashicorp/go-slug v0.16.8 h1:f4/sDZqRsxx006HrE6e9BE5xO9lWXydKhVoH6Kb0v1M= -github.com/hashicorp/go-slug v0.16.8/go.mod h1:hB4mUcVHl4RPu0205s0fwmB9i31MxQgeafGkko3FD+Y= +github.com/hashicorp/go-slug v0.18.1 h1:UnWIy4mq9GaDr1LhAzCPgA6RSQUn952RLFqQe3HPyCs= +github.com/hashicorp/go-slug v0.18.1/go.mod h1:Zxkkl8/LfXmhxZO3fLXQUCy3MVXAJK9pybY8WoDPgvs= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= diff --git a/internal/backend/remote-state/s3/go.mod b/internal/backend/remote-state/s3/go.mod index 820e9dbd74..05911e4b47 100644 --- a/internal/backend/remote-state/s3/go.mod +++ b/internal/backend/remote-state/s3/go.mod @@ -49,7 +49,7 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-slug v0.16.8 // indirect + github.com/hashicorp/go-slug v0.18.1 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect github.com/hashicorp/terraform-registry-address v0.4.0 // indirect diff --git a/internal/backend/remote-state/s3/go.sum b/internal/backend/remote-state/s3/go.sum index daa3691575..4d11e6e726 100644 --- a/internal/backend/remote-state/s3/go.sum +++ b/internal/backend/remote-state/s3/go.sum @@ -225,8 +225,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= -github.com/hashicorp/go-slug v0.16.8 h1:f4/sDZqRsxx006HrE6e9BE5xO9lWXydKhVoH6Kb0v1M= -github.com/hashicorp/go-slug v0.16.8/go.mod h1:hB4mUcVHl4RPu0205s0fwmB9i31MxQgeafGkko3FD+Y= +github.com/hashicorp/go-slug v0.18.1 h1:UnWIy4mq9GaDr1LhAzCPgA6RSQUn952RLFqQe3HPyCs= +github.com/hashicorp/go-slug v0.18.1/go.mod h1:Zxkkl8/LfXmhxZO3fLXQUCy3MVXAJK9pybY8WoDPgvs= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= diff --git a/internal/legacy/go.mod b/internal/legacy/go.mod index 3924e5fe3a..8e5a42e60f 100644 --- a/internal/legacy/go.mod +++ b/internal/legacy/go.mod @@ -21,7 +21,7 @@ require ( github.com/apparentlymart/go-versions v1.0.2 // indirect github.com/bmatcuk/doublestar v1.1.5 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/go-slug v0.16.8 // indirect + github.com/hashicorp/go-slug v0.18.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect diff --git a/internal/legacy/go.sum b/internal/legacy/go.sum index d12c043ac3..55929f55c9 100644 --- a/internal/legacy/go.sum +++ b/internal/legacy/go.sum @@ -133,8 +133,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-slug v0.16.8 h1:f4/sDZqRsxx006HrE6e9BE5xO9lWXydKhVoH6Kb0v1M= -github.com/hashicorp/go-slug v0.16.8/go.mod h1:hB4mUcVHl4RPu0205s0fwmB9i31MxQgeafGkko3FD+Y= +github.com/hashicorp/go-slug v0.18.1 h1:UnWIy4mq9GaDr1LhAzCPgA6RSQUn952RLFqQe3HPyCs= +github.com/hashicorp/go-slug v0.18.1/go.mod h1:Zxkkl8/LfXmhxZO3fLXQUCy3MVXAJK9pybY8WoDPgvs= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= diff --git a/internal/stacks/stackconfig/config.go b/internal/stacks/stackconfig/config.go index 883b52f40e..3bfb9be5f6 100644 --- a/internal/stacks/stackconfig/config.go +++ b/internal/stacks/stackconfig/config.go @@ -369,7 +369,23 @@ func resolveFinalSourceAddr(base sourceaddrs.FinalSource, rel sourceaddrs.Source } underlyingSource = base.FinalSourceAddr(underlyingSource) return sourceaddrs.ResolveRelativeFinalSource(underlyingSource, rel) + case sourceaddrs.ComponentSourceFinal: + ret, err := sourceaddrs.ResolveRelativeFinalSource(base, rel) + if err == nil { + return ret, nil + } + // If we can't resolve relative to the registry source then + // we need to resolve relative to its underlying remote source + // instead. + underlyingSource, ok := sources.ComponentPackageSourceAddr(base.Package(), base.SelectedVersion()) + if !ok { + // If we also can't find the underlying source for some reason + // then we're stuck. + return nil, fmt.Errorf("can't find underlying source address for %s", base.Package()) + } + underlyingSource = base.FinalSourceAddr(underlyingSource) + return sourceaddrs.ResolveRelativeFinalSource(underlyingSource, rel) default: // Easy case: this source type is already a final type return sourceaddrs.ResolveRelativeFinalSource(base, rel) @@ -391,6 +407,17 @@ func resolveFinalSourceAddr(base sourceaddrs.FinalSource, rel sourceaddrs.Source } finalRel := rel.Versioned(selectedVersion) return sourceaddrs.ResolveRelativeFinalSource(base, finalRel) + + case sourceaddrs.ComponentSource: + // Component registry sources work similar to module registry sources + allowedVersions := versions.MeetingConstraints(versionConstraints) + availableVersions := sources.ComponentPackageVersions(rel.Package()) + selectedVersion := availableVersions.NewestInSet(allowedVersions) + if selectedVersion == versions.Unspecified { + return nil, fmt.Errorf("no cached versions of %s match the given version constraints", rel.Package()) + } + finalRel := rel.Versioned(selectedVersion) + return sourceaddrs.ResolveRelativeFinalSource(base, finalRel) default: // Should not get here because the above cases should be exhaustive // for all implementations of sourceaddrs.Source. diff --git a/internal/stacks/stackconfig/config_test.go b/internal/stacks/stackconfig/config_test.go index 6af08c8be0..f6cd96e51d 100644 --- a/internal/stacks/stackconfig/config_test.go +++ b/internal/stacks/stackconfig/config_test.go @@ -284,3 +284,86 @@ func TestOmittingBuiltInProviders(t *testing.T) { }) }) } + +func TestComponentSourceResolution(t *testing.T) { + stackResourceName := "pet-nulls" + bundle, err := sourcebundle.OpenDir("testdata/embedded-stack-bundle") + if err != nil { + t.Fatal(err) + } + + rootAddr := sourceaddrs.MustParseSource("git::https://example.com/root.git").(sourceaddrs.RemoteSource) + config, diags := LoadConfigDir(rootAddr, bundle) + if len(diags) != 0 { + t.Fatalf("unexpected diagnostics:\n%s", diags.NonFatalErr().Error()) + } + + t.Run("component source resolution", func(t *testing.T) { + // Verify that the component was loaded + if got, want := len(config.Root.Stack.EmbeddedStacks), 1; got != want { + t.Errorf("wrong number of components %d; want %d", got, want) + } + + t.Run("pet-nulls component", func(t *testing.T) { + cmpn, ok := config.Root.Stack.EmbeddedStacks[stackResourceName] + if !ok { + t.Fatalf("Root stack config has no component named %q.", stackResourceName) + } + + // Verify component name + if got, want := cmpn.Name, stackResourceName; got != want { + t.Errorf("wrong component name\ngot: %s\nwant: %s", got, want) + } + + // Verify that the source address was parsed correctly + componentSource, ok := cmpn.SourceAddr.(sourceaddrs.ComponentSource) + if !ok { + t.Fatalf("expected ComponentSource, got %T", cmpn.SourceAddr) + } + + expectedSourceStr := "example.com/awesomecorp/tfstack-pet-nulls" + if got := componentSource.String(); got != expectedSourceStr { + t.Errorf("wrong source address\ngot: %s\nwant: %s", got, expectedSourceStr) + } + + // Verify that version constraints were parsed + if cmpn.VersionConstraints == nil { + t.Fatal("component has no version constraints") + } + + // Verify that the final source address was resolved + if cmpn.FinalSourceAddr == nil { + t.Fatal("component FinalSourceAddr was not resolved") + } + + // The final source should be a ComponentSourceFinal + componentSourceFinal, ok := cmpn.FinalSourceAddr.(sourceaddrs.ComponentSourceFinal) + if !ok { + t.Fatalf("expected ComponentSourceFinal for FinalSourceAddr, got %T", cmpn.FinalSourceAddr) + } + + // Verify it resolved to the correct version (0.0.2) + expectedVersion := "0.0.2" + if got := componentSourceFinal.SelectedVersion().String(); got != expectedVersion { + t.Errorf("wrong selected version\ngot: %s\nwant: %s", got, expectedVersion) + } + + // Verify the unversioned component source matches + if got := componentSourceFinal.Unversioned().String(); got != expectedSourceStr { + t.Errorf("wrong unversioned source in final address\ngot: %s\nwant: %s", got, expectedSourceStr) + } + + // Verify we can get the local path from the bundle + localPath, err := bundle.LocalPathForSource(cmpn.FinalSourceAddr) + if err != nil { + t.Fatalf("failed to get local path for component source: %s", err) + } + + // The local path should point to the pet-nulls directory + if localPath == "" { + t.Error("local path is empty") + } + t.Logf("Component resolved to local path: %s", localPath) + }) + }) +} diff --git a/internal/stacks/stackconfig/testdata/basics-bundle/terraform-sources.json b/internal/stacks/stackconfig/testdata/basics-bundle/terraform-sources.json index 4d79b35dd0..a9ccf7c344 100644 --- a/internal/stacks/stackconfig/testdata/basics-bundle/terraform-sources.json +++ b/internal/stacks/stackconfig/testdata/basics-bundle/terraform-sources.json @@ -45,4 +45,4 @@ } } ] -} \ No newline at end of file +} diff --git a/internal/stacks/stackconfig/testdata/embedded-stack-bundle/component/a/main.tf b/internal/stacks/stackconfig/testdata/embedded-stack-bundle/component/a/main.tf new file mode 100644 index 0000000000..5ab385503e --- /dev/null +++ b/internal/stacks/stackconfig/testdata/embedded-stack-bundle/component/a/main.tf @@ -0,0 +1,17 @@ +variable "name" { + type = string +} + +resource "null_resource" "example" { + triggers = { + name = var.name + } +} + +output "greeting" { + value = "Hello, ${var.name}!" +} + +output "resource_id" { + value = null_resource.example.id +} diff --git a/internal/stacks/stackconfig/testdata/embedded-stack-bundle/component/comp.tfcomponent.hcl b/internal/stacks/stackconfig/testdata/embedded-stack-bundle/component/comp.tfcomponent.hcl new file mode 100644 index 0000000000..ed0ddcc141 --- /dev/null +++ b/internal/stacks/stackconfig/testdata/embedded-stack-bundle/component/comp.tfcomponent.hcl @@ -0,0 +1,22 @@ + +required_providers { + null = { + source = "hashicorp/null" + version = "3.2.1" + } +} + +variable "name" { + type = string +} + +component "a" { + source = "./a" + + inputs = { + name = var.name + } + providers = { + null = var.provider + } +} diff --git a/internal/stacks/stackconfig/testdata/embedded-stack-bundle/root/main.tfcomponent.hcl b/internal/stacks/stackconfig/testdata/embedded-stack-bundle/root/main.tfcomponent.hcl new file mode 100644 index 0000000000..9738f09039 --- /dev/null +++ b/internal/stacks/stackconfig/testdata/embedded-stack-bundle/root/main.tfcomponent.hcl @@ -0,0 +1,24 @@ +required_providers { + null = { + source = "hashicorp/null" + version = "3.2.1" + } +} + + +stack "pet-nulls" { + source = "example.com/awesomecorp/tfstack-pet-nulls" + version = "0.0.2" + + inputs = { + name = var.name + provider = provider.null.a + } +} + +provider "null" "a" { +} + +locals { + sound = "bleep bloop" +} diff --git a/internal/stacks/stackconfig/testdata/embedded-stack-bundle/terraform-sources.json b/internal/stacks/stackconfig/testdata/embedded-stack-bundle/terraform-sources.json new file mode 100644 index 0000000000..f6859add87 --- /dev/null +++ b/internal/stacks/stackconfig/testdata/embedded-stack-bundle/terraform-sources.json @@ -0,0 +1,29 @@ +{ + "terraform_source_bundle": 1, + "packages": [ + { + "source": "git::https://example.com/root.git", + "local": "root", + "meta": {} + }, + { + "source": "git::https://example.com/pet-nulls.git?ref=0.0.2", + "local": "component", + "meta": {} + } + ], + "registry": [], + "components": [ + { + "source": "example.com/awesomecorp/tfstack-pet-nulls", + "versions": { + "0.0.1": { + "source": "git::https://example.com/pet-nulls.git?ref=0.0.1" + }, + "0.0.2": { + "source": "git::https://example.com/pet-nulls.git?ref=0.0.2" + } + } + } + ] +}