Merging main

add_filebase64_function
karthik P 1 year ago
commit c109e73f12

@ -19,7 +19,7 @@ jobs:
outputs:
go-version: ${{ steps.get-go-version.outputs.go-version }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 'Determine Go version'
id: get-go-version
# We use .go-version as our source of truth for current Go
@ -40,8 +40,8 @@ jobs:
# Packer GH Token for API Rate Limiting
PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version: ${{ needs.get-go-version.outputs.go-version }}
- name: IAM Assume Role

@ -14,7 +14,7 @@ jobs:
pull-requests: write # for actions/stale to close stale PRs
runs-on: ubuntu-latest
steps:
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-issue-stale: 23

@ -16,7 +16,7 @@ jobs:
contents: none
if: github.event.pull_request.merged
runs-on: ubuntu-latest
container: hashicorpdev/backport-assistant:0.3.4
container: hashicorpdev/backport-assistant:0.5.3
steps:
- name: Backport changes to stable-website
run: |

@ -27,7 +27,7 @@ jobs:
outputs:
go-version: ${{ steps.get-go-version.outputs.go-version }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 'Determine Go version'
id: get-go-version
# We use .go-version as our source of truth for current Go
@ -45,7 +45,7 @@ jobs:
product-prerelease-version: ${{ steps.set-product-version.outputs.prerelease-product-version }}
set-ld-flags: ${{ steps.set-ld-flags.outputs.set-ld-flags }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: set product version
id: set-product-version
uses: hashicorp/actions-set-product-version@v1
@ -53,7 +53,7 @@ jobs:
id: set-ld-flags
run: |
T="github.com/hashicorp/packer/version"
echo "set-ld-flags=-s -w -X ${T}.GitCommit=${GITHUB_SHA::8} -X ${T}.GitDescribe=${{ steps.set-product-version.outputs.product-version }} -X ${T}.Version=${{ steps.set-product-version.outputs.base-product-version }} -X ${T}.VersionPrerelease=${{ steps.set-product-version.outputs.prerelease-product-version }} -X ${T}.VersionMetadata=" >> $GITHUB_OUTPUT
echo "set-ld-flags=-s -w -B gobuildid -X ${T}.GitCommit=${GITHUB_SHA::8} -X ${T}.GitDescribe=${{ steps.set-product-version.outputs.product-version }} -X ${T}.Version=${{ steps.set-product-version.outputs.base-product-version }} -X ${T}.VersionPrerelease=${{ steps.set-product-version.outputs.prerelease-product-version }} -X ${T}.VersionMetadata=" >> $GITHUB_OUTPUT
- name: validate outputs
run: |
echo "Product Version: ${{ steps.set-product-version.outputs.product-version }}"
@ -68,7 +68,7 @@ jobs:
filepath: ${{ steps.generate-metadata-file.outputs.filepath }}
steps:
- name: 'Checkout directory'
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Generate metadata file
id: generate-metadata-file
uses: hashicorp/actions-generate-metadata@main
@ -76,7 +76,7 @@ jobs:
version: ${{ needs.set-product-version.outputs.product-version }}
product: ${{ env.REPO_NAME }}
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
- uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: metadata.json
path: ${{ steps.generate-metadata-file.outputs.filepath }}
@ -106,7 +106,7 @@ jobs:
GOPRIVATE: "github.com/hashicorp"
GO111MODULE: on
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Go Build
env:
PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }}
@ -144,7 +144,7 @@ jobs:
GO111MODULE: on
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Go Build
env:
PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }}
@ -187,11 +187,11 @@ jobs:
run: |
echo "RPM_PACKAGE=$(basename out/*.rpm)" >> $GITHUB_ENV
echo "DEB_PACKAGE=$(basename out/*.deb)" >> $GITHUB_ENV
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
- uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ${{ env.RPM_PACKAGE }}
path: out/${{ env.RPM_PACKAGE }}
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
- uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ${{ env.DEB_PACKAGE }}
path: out/${{ env.DEB_PACKAGE }}
@ -214,7 +214,7 @@ jobs:
GO111MODULE: on
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Go Build
env:
PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }}
@ -245,7 +245,7 @@ jobs:
env:
version: ${{ needs.set-product-version.outputs.product-version }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Docker Build (Action)
uses: hashicorp/actions-docker-build@v2
with:
@ -275,7 +275,7 @@ jobs:
env:
version: ${{ needs.set-product-version.outputs.product-version }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Docker Build (Action)
uses: hashicorp/actions-docker-build@v2
with:

@ -4,7 +4,7 @@ jobs:
create-branch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: hashicorp/actions-create-release-branch@v1
with:
token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}

@ -25,7 +25,7 @@ jobs:
outputs:
go-version: ${{ steps.get-go-version.outputs.go-version }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 'Determine Go version'
id: get-go-version
run: |
@ -37,8 +37,8 @@ jobs:
runs-on: ubuntu-latest
name: Linux go tests
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version: ${{ needs.get-go-version.outputs.go-version }}
- run: TESTARGS="-coverprofile=coverage.txt -covermode=atomic" make ci
@ -48,8 +48,8 @@ jobs:
runs-on: macos-latest
name: Darwin go tests
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version: ${{ needs.get-go-version.outputs.go-version }}
- run: go test ./... -coverprofile=coverage.txt -covermode=atomic
@ -59,8 +59,8 @@ jobs:
runs-on: windows-latest
name: Windows go tests
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version: ${{ needs.get-go-version.outputs.go-version }}
- run: go test ./... -coverprofile=coverage.txt -covermode=atomic

@ -21,7 +21,7 @@ jobs:
outputs:
go-version: ${{ steps.get-go-version.outputs.go-version }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 'Determine Go version'
id: get-go-version
run: |
@ -33,8 +33,8 @@ jobs:
runs-on: ubuntu-latest
name: Go Mod Tidy
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version: ${{ needs.get-go-version.outputs.go-version }}
- run: go mod tidy
@ -44,10 +44,10 @@ jobs:
runs-on: ubuntu-latest
name: Lint
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version: ${{ needs.get-go-version.outputs.go-version }}
- run: echo "$GITHUB_SHA"
@ -60,8 +60,8 @@ jobs:
runs-on: ubuntu-latest
name: Fmt check
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version: ${{ needs.get-go-version.outputs.go-version }}
- run: make fmt-check
@ -71,8 +71,8 @@ jobs:
runs-on: ubuntu-latest
name: Generate check
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version: ${{ needs.get-go-version.outputs.go-version }}
- run: make generate-check

@ -15,7 +15,7 @@ jobs:
if: ${{contains(github.event.issue.labels.*.name, 'waiting-reply') || contains(github.event.issue.labels.*.name, 'stale')}}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 # v1.3.0
with:
github_token: "${{ secrets.GITHUB_TOKEN }}"

@ -13,7 +13,7 @@ jobs:
issues: write # for github/issue-labeler to create or remove labels
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

@ -24,7 +24,7 @@ jobs:
needs: build-artifacts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Download built artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
@ -62,7 +62,7 @@ jobs:
- name: Create a nightly GitHub prerelease
id: create_prerelease
continue-on-error: true
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
uses: ncipollo/release-action@cdcc88a9acf3ca41c16c37bb7d21b9ad48560d87 # v1.15.0
with:
name: nightly
artifacts: "${{ env.BUILD_OUTPUT_LIST }}"
@ -85,7 +85,7 @@ jobs:
- name: Retry failed nightly GitHub prerelease
id: create_prerelease_retry
if: steps.create_prerelease.outcome == 'failure'
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
uses: ncipollo/release-action@cdcc88a9acf3ca41c16c37bb7d21b9ad48560d87 # v1.15.0
with:
name: nightly
artifacts: "${{ env.BUILD_OUTPUT_LIST }}"

@ -1 +1 @@
1.22.7
1.23.2

@ -13,4 +13,14 @@ binary {
osv = true
oss_index = true
nvd = false
# Triage items that are _safe_ to ignore here. Note that this list should be
# periodically cleaned up to remove items that are no longer found by the scanner.
triage {
suppress {
vulnerabilities = [
"GO-2022-0635", // github.com/aws/aws-sdk-go@v1.55.5 TODO(dduzgun-security): remove when deps is resolved
]
}
}
}

@ -1,3 +1,131 @@
## 1.12.0 (January 22, 2025)
### FEATURES:
* core: add support for a DAG-based evaluation on locals and datasources.
A long-standing odditiy of Packer has been the order of evaluation for
locals and data sources. In previous versions of Packer, the
data sources were evaluated first, then the local variables were, making
it impossible to have a datasource that referenced a local variable as
part of its configuration.
This change introduces a Directed Acyclic Graph (DAG) to evaluate those
resources, instead of the phased approach of old, which makes the order
of evaluation not dependent on the type of resource, but instead of the
detected dependencies between them.
**Note**: While we are confident this should be robust enough for general
use, we do recognise that it is possible some users might encounter issues.
To give those users a way to continue using the old evaluation method, we
introduced a `-use-sequential-evaluation` command-line flag to the build,
validate, console and inspect subcommands, to force using the sequential
evaluation approach for those entities.
[GH-13155](https://github.com/hashicorp/packer/pull/13155)
* core/hcp: support for uploading SBOMs to HCP Packer.
Software Bill of Materials (SBOM) are a standardised way to export the various
software packages linked to an artifact. As some users have expressed a
need to produce and access those for images they build, we now add the
feature to Packer itself.
While the generation of the SBOM itself is not done directly by
Packer, instead we recommend using known scanners to produce them, we add
the capacity to upload this SBOM file to HCP Packer, and link it to a
build artifact.
[GH-13171](https://github.com/hashicorp/packer/pull/13171)
* core: support for alternate serialisation formats for plugin communication.
Packer relies on plugins to do most of the actual workload related to
building and provisioing artifacts, while Packer is mostly an orchestrator
for those plugins to perform their work.
This separation of concerns implies that both entities have to
communicate on multiple occasions during the course of a build.
Before v1.12.0 of Packer, and v0.6.0 of the plugin SDK, we used Gob to
do most of the serialisation for those steps.
This is however a bit of a problem recently, as go-cty, the library we
use for dynamic objects lifted from HCL templates, dropped support for
this a while back.
Therefore now, we introduce an alternative: protobuf/msgpack, which are
both usable and maintained by the projects around Packer, so we can begin
our transition away from gob with this change.
**Note**: as with the introduction of the DAG for locals/datasources, this
is a feature that we are reasonably confident you will not encounter bugs
with, however we cannot rule-out this possibility, therefore we introduce
a new environment variable: `PACKER_FORCE_GOB`, which if set to '1', forces
the use of Gob instead of protobuf/msgpack.
[GH-13120](https://github.com/hashicorp/packer/pull/13120)
### IMPROVEMENTS:
* hcl2/json: add `aws_secretsmanager_raw` funcion.
When using the AWS secretsmanager function with a non-text secret, one could
only get a secret once at a time.
This could get cumbersome if wanting to get multiple through one request,
which led people to encode their JSON/Object secrets as a big base64
encoded string that they could get once, and then manipulate through JSON
functions.
While the workaround works, it is one extra layer of manipulations to do so,
therefore a new function to always get the raw textual version of a secret
is now added to Packer.
[GH-13242](https://github.com/hashicorp/packer/pull/13242)
* hcl2: add `alltrue` and `anytrue` functions.
As with Terraform, Packer now supports the HCL functions `alltrue` and
`anytrue`, which returns whether or not a collection only consists of
`true` values, or if any is.
[GH-13237](https://github.com/hashicorp/packer/pull/13237)
* hcl2: add `strcontains` function.
As with Terraform, Packer now supports the HCL function `strcontains`,
which returns whether or not a string contains a substring within it.
[GH-13217](https://github.com/hashicorp/packer/pull/13217)
[GH-13222](https://github.com/hashicorp/packer/pull/13222)
* datasource/http: Support other methods than GET.
The HTTP datasource used to always use GET requests for getting data
from a remote HTTP server, which was not always enough since some endpoints
may only support other methods. This change allows for most of the HTTP
methods to perform those requests.
[GH-13190](https://github.com/hashicorp/packer/pull/13190)
* hcl2: add `base64gzip` function.
In some cases, small blobs may need to be kept in memory, and injected in
a template somewhere else, but if the blob needs to be minimised, the
base64gzip function can be invoked to compress the blob and expose it
as a valid HCL2 string for use later.
[GH-13142](https://github.com/hashicorp/packer/pull/13142)
### BUG FIXES:
* hcl2: Fix duplicate error messages on top-level HCL violations.
A parsing quirk for HCL templates caused Packer to produce the same parsing
error multiple times if the error was caused by a top-level violation.
[GH-13245](https://github.com/hashicorp/packer/pull/13245)
* build: Include LC_UUID in Darwin binaries.
A change in how Apple authorises a plugin to access the network caused
Packer to break on recent (14.7 and above) macOS versions, as Packer uses
the local network to communicate with plugins.
The fix is to include an additional UUID into the metadata of the produced
binary, so it is authorised by macOS to use the local network, which prompts
an update to the version of Go used for building Packer (1.22.9), as it is
when this addition is supported by an LDFLAG.
[GH-13214](https://github.com/hashicorp/packer/pull/13214)
* hcl2: Don't error on empty bucker slug.
As reported by members of our community, using a hcp_packer_registry
block without a bucket slug, even if provided by external means, would cause
Packer to fail with an invalid bucket slug error. This is most definitely
a bug, which is addressed in this release.
[GH-13210](https://github.com/hashicorp/packer/pull/13210)
* hcp: fix bug when trying to extract HEAD SHA from empty Git repo.
[GH-13165](https://github.com/hashicorp/packer/pull/13165)
### SECURITY:
* Bump to go-crypto v0.31.0
[GH-13233](https://github.com/hashicorp/packer/pull/13233)
### NOTES:
* docs: fix UUIDv4 example. A community user has found discrepancies in the
UUIDv4 examples which were used in our docs, as they do not match the
standard.
[GH-13229](https://github.com/hashicorp/packer/pull/13229)
* hcl2: fix slice initialisation method during variable evaluation phase.
[GH-13175](https://github.com/hashicorp/packer/pull/13175)
## 1.11.2 (July 30, 2024)
### FEATURES

@ -2,3 +2,18 @@
# release configuration
# engineering and web presence get notified of, and can approve changes to web tooling, but not content.
/website/ @hashicorp/web-presence @hashicorp/packer
/website/data/
/website/public/
/website/content/
# education and engineering get notified of, and can approve changes to web content.
/website/data/ @hashicorp/team-docs-packer-and-terraform @hashicorp/packer
/website/public/ @hashicorp/team-docs-packer-and-terraform @hashicorp/packer
/website/content/ @hashicorp/team-docs-packer-and-terraform @hashicorp/packer
/website/README.md @hashicorp/team-docs-packer-and-terraform @hashicorp/packer
/website/redirects.js @hashicorp/team-docs-packer-and-terraform @hashicorp/packer

@ -55,7 +55,7 @@ install-gen-deps: ## Install dependencies for code generation
install-lint-deps: ## Install linter dependencies
@echo "==> Updating linter dependencies..."
@curl -sSfL -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin v1.54.0
@curl -sSfL -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin v1.60.1
dev: ## Build and install a development build
@grep 'const VersionPrerelease = ""' version/version.go > /dev/null ; if [ $$? -eq 0 ]; then \

@ -105,6 +105,11 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int
diags = packerStarter.Initialize(packer.InitializeOptions{
UseSequential: cla.UseSequential,
})
if packer.PackerUseProto {
log.Printf("[TRACE] Using protobuf for communication with plugins")
}
ret = writeDiags(c.Ui, nil, diags)
if ret != 0 {
return ret
@ -157,7 +162,7 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int
packer.UiColorYellow,
packer.UiColorBlue,
}
buildUis := make(map[packersdk.Build]packersdk.Ui)
buildUis := make(map[*packer.CoreBuild]packersdk.Ui)
for i := range builds {
ui := c.Ui
if cla.Color {
@ -315,6 +320,15 @@ Check that you are using an HCP Ready integration before trying again:
artifacts.Unlock()
}
}
// If the build succeeded but uploading to HCP failed,
// Packer should exit non-zero, so we re-assign the
// error to account for this case.
if hcperr != nil && err == nil {
errs.Lock()
errs.m[name] = hcperr
errs.Unlock()
}
}()
if cla.Debug {

@ -106,6 +106,21 @@ func TestBuild(t *testing.T) {
},
fileCheck: fileCheck{expected: []string{"chocolate.txt"}},
},
{
name: "var-args: json - auto varfile sets a peanut env var",
args: []string{
testFixture("var-arg", "var-arg-test-autovar-json"),
},
fileCheck: fileCheck{expected: []string{"peanut.txt"}},
},
{
name: "var-args: hcl - auto varfile and json -auto varfile sets the value in json auto varfile",
args: []string{
testFixture("var-arg", "var-arg-tests"),
},
fileCheck: fileCheck{expected: []string{"peanut.txt"}},
},
{
name: "var-args: hcl - hcl varfile sets a apple env var",
@ -124,6 +139,24 @@ func TestBuild(t *testing.T) {
},
fileCheck: fileCheck{expected: []string{"apple.txt"}},
},
{
name: "var-args: banana json var file then hcl var file sets apple env var",
args: []string{
"-var-file=" + filepath.Join(testFixture("var-arg"), "banana.json"),
"-var-file=" + filepath.Join(testFixture("var-arg"), "apple.hcl"),
testFixture("var-arg"),
},
fileCheck: fileCheck{expected: []string{"apple.txt"}},
},
{
name: "var-args: apple hcl var file then banana json var file sets banana env var",
args: []string{
"-var-file=" + filepath.Join(testFixture("var-arg"), "apple.hcl"),
"-var-file=" + filepath.Join(testFixture("var-arg"), "banana.json"),
testFixture("var-arg"),
},
fileCheck: fileCheck{expected: []string{"banana.txt"}},
},
{
name: "var-args: hcl - arg sets a tomato env var",

@ -156,6 +156,10 @@ type PluginsRequiredArgs struct {
MetaArgs
}
func (ca *ConsoleArgs) AddFlagSets(flags *flag.FlagSet) {
flags.BoolVar(&ca.MetaArgs.UseSequential, "use-sequential-evaluation", false, "Fallback to using a sequential approach for local/datasource evaluation.")
}
// ConsoleArgs represents a parsed cli line for a `packer console`
type ConsoleArgs struct {
MetaArgs
@ -163,7 +167,6 @@ type ConsoleArgs struct {
func (fa *FixArgs) AddFlagSets(flags *flag.FlagSet) {
flags.BoolVar(&fa.Validate, "validate", true, "")
flags.BoolVar(&fa.MetaArgs.UseSequential, "use-sequential-evaluation", false, "Fallback to using a sequential approach for local/datasource evaluation.")
fa.MetaArgs.AddFlagSets(flags)
}

@ -46,6 +46,7 @@ func (c *ConsoleCommand) ParseArgs(args []string) (*ConsoleArgs, int) {
flags := c.Meta.FlagSet("console")
flags.Usage = func() { c.Ui.Say(c.Help()) }
cfg.AddFlagSets(flags)
cfg.MetaArgs.AddFlagSets(flags)
if err := flags.Parse(args); err != nil {
return &cfg, 1
}

@ -29,6 +29,7 @@ func Test_console(t *testing.T) {
}{
{"help", []string{"console"}, nil, packer.ConsoleHelp + "\n"},
{"help", []string{"console", "--config-type=hcl2"}, nil, hcl2template.PackerConsoleHelp + "\n"},
{"help", []string{"console", "--config-type=hcl2", "--use-sequential-evaluation"}, nil, hcl2template.PackerConsoleHelp + "\n"},
{"var.fruit", []string{"console", filepath.Join(testFixture("var-arg"), "fruit_builder.pkr.hcl")}, []string{"PKR_VAR_fruit=potato"}, "potato\n"},
{"upper(var.fruit)", []string{"console", filepath.Join(testFixture("var-arg"), "fruit_builder.pkr.hcl")}, []string{"PKR_VAR_fruit=potato"}, "POTATO\n"},
{"1 + 5", []string{"console", "--config-type=hcl2"}, nil, "6\n"},

@ -5,8 +5,8 @@
package command
import (
"flag"
"fmt"
"log"
"regexp"
"strings"
@ -28,6 +28,7 @@ import (
shelllocalpostprocessor "github.com/hashicorp/packer/post-processor/shell-local"
breakpointprovisioner "github.com/hashicorp/packer/provisioner/breakpoint"
fileprovisioner "github.com/hashicorp/packer/provisioner/file"
hcpsbomprovisioner "github.com/hashicorp/packer/provisioner/hcp-sbom"
powershellprovisioner "github.com/hashicorp/packer/provisioner/powershell"
shellprovisioner "github.com/hashicorp/packer/provisioner/shell"
shelllocalprovisioner "github.com/hashicorp/packer/provisioner/shell-local"
@ -48,6 +49,7 @@ var Builders = map[string]packersdk.Builder{
var Provisioners = map[string]packersdk.Provisioner{
"breakpoint": new(breakpointprovisioner.Provisioner),
"file": new(fileprovisioner.Provisioner),
"hcp-sbom": new(hcpsbomprovisioner.Provisioner),
"powershell": new(powershellprovisioner.Provisioner),
"shell": new(shellprovisioner.Provisioner),
"shell-local": new(shelllocalprovisioner.Provisioner),
@ -75,18 +77,45 @@ var Datasources = map[string]packersdk.Datasource{
var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner|datasource)-(.+)")
func (c *ExecuteCommand) Run(args []string) int {
// This is an internal call (users should not call this directly) so we're
// not going to do much input validation. If there's a problem we'll often
// just crash. Error handling should be added to facilitate debugging.
log.Printf("args: %#v", args)
type ExecuteArgs struct {
UseProtobuf bool
CommandType string
}
func (ea *ExecuteArgs) AddFlagSets(flags *flag.FlagSet) {
flags.BoolVar(&ea.UseProtobuf, "protobuf", false, "Use protobuf for serialising data over the wire instead of gob")
}
func (c *ExecuteCommand) ParseArgs(args []string) (*ExecuteArgs, int) {
var cfg ExecuteArgs
flags := c.Meta.FlagSet("")
flags.Usage = func() { c.Ui.Say(c.Help()) }
cfg.AddFlagSets(flags)
if err := flags.Parse(args); err != nil {
return &cfg, 1
}
args = flags.Args()
if len(args) != 1 {
c.Ui.Error(c.Help())
return 1
flags.Usage()
return &cfg, 1
}
cfg.CommandType = args[0]
return &cfg, 0
}
func (c *ExecuteCommand) Run(args []string) int {
cfg, ret := c.ParseArgs(args)
if ret != 0 {
return ret
}
return c.RunContext(cfg)
}
func (c *ExecuteCommand) RunContext(args *ExecuteArgs) int {
// Plugin will match something like "packer-builder-amazon-ebs"
parts := pluginRegexp.FindStringSubmatch(args[0])
parts := pluginRegexp.FindStringSubmatch(args.CommandType)
if len(parts) != 3 {
c.Ui.Error(c.Help())
return 1
@ -100,6 +129,10 @@ func (c *ExecuteCommand) Run(args []string) int {
return 1
}
if args.UseProtobuf {
server.UseProto = true
}
switch pluginType {
case "builder":
builder, found := Builders[pluginName]
@ -138,11 +171,15 @@ func (c *ExecuteCommand) Run(args []string) int {
func (*ExecuteCommand) Help() string {
helpText := `
Usage: packer execute PLUGIN
Usage: packer execute [options] PLUGIN
Runs an internally-compiled version of a plugin from the packer binary.
NOTE: this is an internal command and you should not call it yourself.
Options:
--protobuf: use protobuf for serialising data over-the-wire instead of gob.
`
return strings.TrimSpace(helpText)

@ -20,7 +20,6 @@ import (
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/hcl/v2/hclwrite"
awscommon "github.com/hashicorp/packer-plugin-amazon/builder/common"
hcl2shim "github.com/hashicorp/packer-plugin-sdk/hcl2helper"
"github.com/hashicorp/packer-plugin-sdk/template"
"github.com/hashicorp/packer/packer"
@ -1170,10 +1169,52 @@ func (p *AmazonAmiDatasourceParser) Parse(_ *template.Template) error {
return nil
}
type AssumeRoleConfig struct {
AssumeRoleARN string `mapstructure:"role_arn" required:"false"`
AssumeRoleDurationSeconds int `mapstructure:"duration_seconds" required:"false"`
AssumeRoleExternalID string `mapstructure:"external_id" required:"false"`
AssumeRolePolicy string `mapstructure:"policy" required:"false"`
AssumeRolePolicyARNs []string `mapstructure:"policy_arns" required:"false"`
AssumeRoleSessionName string `mapstructure:"session_name" required:"false"`
AssumeRoleTags map[string]string `mapstructure:"tags" required:"false"`
AssumeRoleTransitiveTagKeys []string `mapstructure:"transitive_tag_keys" required:"false"`
}
type VaultAWSEngineOptions struct {
Name string `mapstructure:"name"`
RoleARN string `mapstructure:"role_arn"`
TTL string `mapstructure:"ttl" required:"false"`
EngineName string `mapstructure:"engine_name"`
}
type AWSPollingConfig struct {
MaxAttempts int `mapstructure:"max_attempts" required:"false"`
DelaySeconds int `mapstructure:"delay_seconds" required:"false"`
}
type AwsAccessConfig struct {
AccessKey string `mapstructure:"access_key" required:"true"`
AssumeRole AssumeRoleConfig `mapstructure:"assume_role" required:"false"`
CustomEndpointEc2 string `mapstructure:"custom_endpoint_ec2" required:"false"`
CredsFilename string `mapstructure:"shared_credentials_file" required:"false"`
DecodeAuthZMessages bool `mapstructure:"decode_authorization_messages" required:"false"`
InsecureSkipTLSVerify bool `mapstructure:"insecure_skip_tls_verify" required:"false"`
MaxRetries int `mapstructure:"max_retries" required:"false"`
MFACode string `mapstructure:"mfa_code" required:"false"`
ProfileName string `mapstructure:"profile" required:"false"`
RawRegion string `mapstructure:"region" required:"true"`
SecretKey string `mapstructure:"secret_key" required:"true"`
SkipMetadataApiCheck bool `mapstructure:"skip_metadata_api_check"`
SkipCredsValidation bool `mapstructure:"skip_credential_validation"`
Token string `mapstructure:"token" required:"false"`
VaultAWSEngine VaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false"`
PollingConfig *AWSPollingConfig `mapstructure:"aws_polling" required:"false"`
}
func copyAWSAccessConfig(sourceAmi map[string]interface{}, builder map[string]interface{}) (map[string]interface{}, error) {
// Transform access config to a map
accessConfigMap := map[string]interface{}{}
if err := mapstructure.Decode(awscommon.AccessConfig{}, &accessConfigMap); err != nil {
if err := mapstructure.Decode(AwsAccessConfig{}, &accessConfigMap); err != nil {
return sourceAmi, err
}

@ -0,0 +1,4 @@
src "docker" "ubuntu" {
image = var.docker_image
commit = true
}

@ -0,0 +1,22 @@
variable "fruit" {
type = string
}
locals {
fruit = var.fruit
}
source "null" "builder" {
communicator = "none"
}
build {
sources = [
"source.null.builder",
]
provisioner "shell-local" {
inline = ["echo ${local.fruit} > ${local.fruit}.txt"]
}
}

@ -0,0 +1,22 @@
variable "fruit" {
type = string
}
locals {
fruit = var.fruit
}
source "null" "builder" {
communicator = "none"
}
build {
sources = [
"source.null.builder",
]
provisioner "shell-local" {
inline = ["echo ${local.fruit} > ${local.fruit}.txt"]
}
}

@ -5,6 +5,7 @@ package command
import (
"context"
"log"
"strings"
"github.com/hashicorp/packer/packer"
@ -76,6 +77,10 @@ func (c *ValidateCommand) RunContext(ctx context.Context, cla *ValidateArgs) int
return ret
}
if packer.PackerUseProto {
log.Printf("[TRACE] Using protobuf for communication with plugins")
}
diags = packerStarter.Initialize(packer.InitializeOptions{
SkipDatasourcesExecution: !cla.EvaluateDatasources,
UseSequential: cla.UseSequential,

@ -36,6 +36,9 @@ func TestValidateCommand(t *testing.T) {
// wrong version field
{path: filepath.Join(testFixture("version_req", "wrong_field_name")), exitCode: 1},
// wrong packer block type
{path: filepath.Join(testFixture("validate", "invalid_block_type.pkr.hcl")), exitCode: 1},
// wrong packer block
{path: filepath.Join(testFixture("validate", "invalid_packer_block.pkr.hcl")), exitCode: 1},

@ -16,10 +16,6 @@ import (
"github.com/hashicorp/packer/packer"
)
// PACKERSPACE is used to represent the spaces that separate args for a command
// without being confused with spaces in the path to the command itself.
const PACKERSPACE = "-PACKERSPACE-"
type config struct {
DisableCheckpoint bool `json:"disable_checkpoint"`
DisableCheckpointSignature bool `json:"disable_checkpoint_signature"`
@ -109,10 +105,16 @@ func (c *config) discoverInternalComponents() error {
for builder := range command.Builders {
builder := builder
if !c.Plugins.Builders.Has(builder) {
bin := fmt.Sprintf("%s%sexecute%spacker-builder-%s",
packerPath, PACKERSPACE, PACKERSPACE, builder)
c.Plugins.Builders.Set(builder, func() (packersdk.Builder, error) {
return c.Plugins.Client(bin).Builder()
args := []string{"execute"}
if packer.PackerUseProto {
args = append(args, "--protobuf")
}
args = append(args, fmt.Sprintf("packer-builder-%s", builder))
return c.Plugins.Client(packerPath, args...).Builder()
})
}
}
@ -120,10 +122,16 @@ func (c *config) discoverInternalComponents() error {
for provisioner := range command.Provisioners {
provisioner := provisioner
if !c.Plugins.Provisioners.Has(provisioner) {
bin := fmt.Sprintf("%s%sexecute%spacker-provisioner-%s",
packerPath, PACKERSPACE, PACKERSPACE, provisioner)
c.Plugins.Provisioners.Set(provisioner, func() (packersdk.Provisioner, error) {
return c.Plugins.Client(bin).Provisioner()
args := []string{"execute"}
if packer.PackerUseProto {
args = append(args, "--protobuf")
}
args = append(args, fmt.Sprintf("packer-provisioner-%s", provisioner))
return c.Plugins.Client(packerPath, args...).Provisioner()
})
}
}
@ -131,10 +139,16 @@ func (c *config) discoverInternalComponents() error {
for postProcessor := range command.PostProcessors {
postProcessor := postProcessor
if !c.Plugins.PostProcessors.Has(postProcessor) {
bin := fmt.Sprintf("%s%sexecute%spacker-post-processor-%s",
packerPath, PACKERSPACE, PACKERSPACE, postProcessor)
c.Plugins.PostProcessors.Set(postProcessor, func() (packersdk.PostProcessor, error) {
return c.Plugins.Client(bin).PostProcessor()
args := []string{"execute"}
if packer.PackerUseProto {
args = append(args, "--protobuf")
}
args = append(args, fmt.Sprintf("packer-post-processor-%s", postProcessor))
return c.Plugins.Client(packerPath, args...).PostProcessor()
})
}
}
@ -142,10 +156,16 @@ func (c *config) discoverInternalComponents() error {
for dataSource := range command.Datasources {
dataSource := dataSource
if !c.Plugins.DataSources.Has(dataSource) {
bin := fmt.Sprintf("%s%sexecute%spacker-datasource-%s",
packerPath, PACKERSPACE, PACKERSPACE, dataSource)
c.Plugins.DataSources.Set(dataSource, func() (packersdk.Datasource, error) {
return c.Plugins.Client(bin).Datasource()
args := []string{"execute"}
if packer.PackerUseProto {
args = append(args, "--protobuf")
}
args = append(args, fmt.Sprintf("packer-datasource-%s", dataSource))
return c.Plugins.Client(packerPath, args...).Datasource()
})
}
}

@ -6,7 +6,7 @@ require (
github.com/cheggaaa/pb v1.0.27
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
github.com/dsnet/compress v0.0.1
github.com/go-git/go-git/v5 v5.11.0
github.com/go-git/go-git/v5 v5.13.0
github.com/go-openapi/runtime v0.26.2
github.com/gobwas/glob v0.2.3
github.com/gofrs/flock v0.8.1 // indirect
@ -22,11 +22,10 @@ require (
github.com/hashicorp/go-uuid v1.0.3
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hcl/v2 v2.19.1
github.com/hashicorp/hcp-sdk-go v0.112.0
github.com/hashicorp/packer-plugin-amazon v1.2.1
github.com/hashicorp/packer-plugin-sdk v0.5.4
github.com/hashicorp/hcp-sdk-go v0.136.0
github.com/hashicorp/packer-plugin-sdk v0.6.0
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869
github.com/klauspost/compress v1.13.6 // indirect
github.com/klauspost/compress v1.13.6
github.com/klauspost/pgzip v1.2.5
github.com/masterzen/winrm v0.0.0-20210623064412-3b76017826b0
github.com/mattn/go-runewidth v0.0.13 // indirect
@ -40,33 +39,34 @@ require (
github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db // indirect
github.com/pkg/sftp v1.13.2 // indirect
github.com/posener/complete v1.2.3
github.com/stretchr/testify v1.8.4
github.com/stretchr/testify v1.10.0
github.com/ulikunitz/xz v0.5.10
github.com/zclconf/go-cty v1.13.3
github.com/zclconf/go-cty-yaml v1.0.1
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/mod v0.13.0
golang.org/x/net v0.25.0
golang.org/x/oauth2 v0.15.0
golang.org/x/sync v0.5.0
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/text v0.15.0
golang.org/x/tools v0.14.0
golang.org/x/crypto v0.35.0 // indirect
golang.org/x/mod v0.19.0
golang.org/x/net v0.36.0
golang.org/x/oauth2 v0.27.0
golang.org/x/sync v0.11.0
golang.org/x/sys v0.30.0 // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.22.0
golang.org/x/tools v0.23.0
google.golang.org/api v0.150.0 // indirect
google.golang.org/grpc v1.59.0
)
require (
github.com/CycloneDX/cyclonedx-go v0.9.1
github.com/go-openapi/strfmt v0.21.10
github.com/oklog/ulid v1.3.1
github.com/pierrec/lz4/v4 v4.1.18
github.com/shirou/gopsutil/v3 v3.23.4
github.com/spdx/tools-golang v0.5.5
)
require (
cloud.google.com/go/compute v1.23.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/iam v1.1.3 // indirect
cloud.google.com/go/storage v1.35.1 // indirect
dario.cat/mergo v1.0.0 // indirect
@ -76,29 +76,30 @@ require (
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.1 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
github.com/ProtonMail/go-crypto v1.1.3 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
github.com/apparentlymart/go-cidr v1.0.1 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aws/aws-sdk-go v1.44.114 // indirect
github.com/aws/aws-sdk-go v1.45.6 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/bgentry/speakeasy v0.2.0 // indirect
github.com/bmatcuk/doublestar v1.1.5 // indirect
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
github.com/chzyer/test v1.0.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dylanmei/iso8601 v0.1.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
github.com/go-git/go-billy/v5 v5.6.0 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
@ -116,7 +117,6 @@ require (
github.com/google/uuid v1.4.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/hashicorp/aws-sdk-go-base v0.7.1 // indirect
github.com/hashicorp/consul/api v1.25.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
@ -129,7 +129,7 @@ require (
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/serf v0.10.1 // indirect
@ -160,15 +160,17 @@ require (
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/shoenig/go-m1cpu v0.1.5 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect
github.com/skeema/knownhosts v1.3.0 // indirect
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/ugorji/go/codec v1.2.6 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
@ -177,10 +179,9 @@ require (
go.opentelemetry.io/otel v1.17.0 // indirect
go.opentelemetry.io/otel/metric v1.17.0 // indirect
go.opentelemetry.io/otel/trace v1.17.0 // indirect
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect
@ -190,6 +191,6 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)
go 1.21.0
go 1.23.0
replace github.com/zclconf/go-cty => github.com/nywilken/go-cty v1.13.3 // added by packer-sdc fix as noted in github.com/hashicorp/packer-plugin-sdk/issues/187

164
go.sum

@ -1,10 +1,8 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME=
cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk=
cloud.google.com/go/compute v1.23.1 h1:V97tBoDaZHb6leicZ1G6DLK2BAaZLJ/7+9BB/En3hR0=
cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/iam v1.1.3 h1:18tKG7DzydKWUnLjonWcJO6wjSCAtzh4GcRKlH/Hrzc=
cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE=
cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w=
@ -20,6 +18,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4=
github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 h1:w0E0fgc1YafGEh5cROhlROMWXiNoZqApk2PDN0M1+Ns=
github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4=
github.com/CycloneDX/cyclonedx-go v0.9.1 h1:yffaWOZsv77oTJa/SdVZYdgAgFioCeycBUKkqS2qzQM=
github.com/CycloneDX/cyclonedx-go v0.9.1/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
@ -30,14 +30,16 @@ github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFP
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk=
github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/antchfx/xmlquery v1.3.5 h1:I7TuBRqsnfFuL11ruavGm911Awx9IqSdiU6W/ztSmVw=
@ -63,22 +65,23 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-sdk-go v1.31.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.44.114 h1:plIkWc/RsHr3DXBj4MEw9sEW4CcL/e2ryokc+CKyq1I=
github.com/aws/aws-sdk-go v1.44.114/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go v1.45.6 h1:Y2isQQBZsnO15dzUQo9YQRThtHgrV200XCH05BRHVJI=
github.com/aws/aws-sdk-go v1.45.6/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E=
github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/biogo/boom v0.0.0-20150317015657-28119bc1ffc1/go.mod h1:fwtxkutinkQcME9Zlywh66T0jZLLjgrwSLY2WxH2N3U=
github.com/biogo/hts v1.4.3 h1:vir2yUTiRkPvtp6ZTpzh9lWTKQJZXJKZ563rpAQAsRM=
github.com/biogo/hts v1.4.3/go.mod h1:eW40HJ1l2ExK9C+yvvoRSftInqWsf3ue+zAEjzCGWjA=
github.com/bmatcuk/doublestar v1.1.5 h1:2bNwBOmhyFEFcoB3tGvTD5xanq+4kyOZlB8wFYbMjkk=
github.com/bmatcuk/doublestar v1.1.5/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@ -94,12 +97,11 @@ github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo=
github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@ -111,8 +113,8 @@ github.com/dylanmei/iso8601 v0.1.0 h1:812NGQDBcqquTfH5Yeo7lwR0nzx/cKdsmf3qMjPURU
github.com/dylanmei/iso8601 v0.1.0/go.mod h1:w9KhXSgIyROl1DefbMYIE7UVSIvELTbMrCfx+QkYnoQ=
github.com/dylanmei/winrmtest v0.0.0-20210303004826-fbc9ae56efb6 h1:zWydSUQBJApHwpQ4guHi+mGyQN/8yN6xbKWdDtL3ZNM=
github.com/dylanmei/winrmtest v0.0.0-20210303004826-fbc9ae56efb6/go.mod h1:6BLLhzn1VEiJ4veuAGhINBTrBlV889Wd+aU4auxKOww=
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy v1.2.1 h1:njjgvO6cRG9rIqN2ebkqy6cQz2Njkx7Fsfv/zIZqgug=
github.com/elazarl/goproxy v1.2.1/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -124,19 +126,19 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8=
github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E=
github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@ -168,7 +170,6 @@ github.com/go-openapi/swag v0.22.5 h1:fVS63IE3M0lsuWRzuom3RLwUMVI2peDH01s6M70ugy
github.com/go-openapi/swag v0.22.5/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0=
github.com/go-openapi/validate v0.22.4 h1:5v3jmMyIPKTR8Lv9syBAIRxG6lY0RqeBPB1LKEijzk8=
github.com/go-openapi/validate v0.22.4/go.mod h1:qm6O8ZIcPVdSY5219468Jv7kBdGvkiZLPOmqnqTUZ2A=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
@ -234,8 +235,6 @@ github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ=
github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE=
github.com/hashicorp/aws-sdk-go-base v0.7.1 h1:7s/aR3hFn74tYPVihzDyZe7y/+BorN70rr9ZvpV3j3o=
github.com/hashicorp/aws-sdk-go-base v0.7.1/go.mod h1:2fRjWDv3jJBeN6mVWFHV6hFTNeFBx2gpDLQaZNxUVAY=
github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE=
github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g=
github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs=
@ -281,8 +280,9 @@ github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7ml
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw=
github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
@ -297,16 +297,14 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI=
github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
github.com/hashicorp/hcp-sdk-go v0.112.0 h1:gKzxaPhzJj4NobFw7Sc1rGf3nMSqUKBgTtsbZ6bzd14=
github.com/hashicorp/hcp-sdk-go v0.112.0/go.mod h1:vQ4fzdL1AmhIAbCw+4zmFe5Hbpajj3NvRWkJoVuxmAk=
github.com/hashicorp/hcp-sdk-go v0.136.0 h1:NNtb/dYoj7YrVQVvWZ2T7PY2Pwn8vQ5YKIAgaqaKk6A=
github.com/hashicorp/hcp-sdk-go v0.136.0/go.mod h1:vQ4fzdL1AmhIAbCw+4zmFe5Hbpajj3NvRWkJoVuxmAk=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM=
github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=
github.com/hashicorp/packer-plugin-amazon v1.2.1 h1:0Xqr8KsTJJhIo0vvjqPYrVMgyVxNRuYH4DeB5m/WAtw=
github.com/hashicorp/packer-plugin-amazon v1.2.1/go.mod h1:qlp0h5TWVGgcPzN9mSxPiEAwOUOW3XU/zep0pGd0ZsM=
github.com/hashicorp/packer-plugin-sdk v0.5.4 h1:5Bl5DMEa//G4gBNcl842JopM9L4KSSsxpvB4W1lEwIA=
github.com/hashicorp/packer-plugin-sdk v0.5.4/go.mod h1:ALm0ZIK3c/F4iOqPNi7xVuHTgrR5dxzOK+DhFN5DHj4=
github.com/hashicorp/packer-plugin-sdk v0.6.0 h1:v8JdmM1PkkHu3gIUs63UcsgGlD0U3m/7DWG6PxcmOPw=
github.com/hashicorp/packer-plugin-sdk v0.6.0/go.mod h1:bDCCzvZ6lUJjrY7eI+i9lYmGs9NSymdFFQiGluF8dEg=
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
@ -323,7 +321,6 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4=
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
@ -431,8 +428,8 @@ github.com/nywilken/go-cty v1.13.3 h1:03U99oXf3j3g9xgqAE3YGpixCjM8Mg09KZ0Ji9LzX0
github.com/nywilken/go-cty v1.13.3/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db h1:9uViuKtx1jrlXLBW/pMnhOfzn3iSEdLase/But/IZRU=
@ -480,8 +477,8 @@ github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkB
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shirou/gopsutil/v3 v3.23.4 h1:hZwmDxZs7Ewt75DV81r4pFMqbq+di2cbt9FsQBqLD2o=
github.com/shirou/gopsutil/v3 v3.23.4/go.mod h1:ZcGxyfzAMRevhUR2+cfhXDH6gQdFYE/t8j1nsU4mPI8=
github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ=
@ -493,17 +490,21 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk=
github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@ -515,8 +516,12 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo=
github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
@ -528,7 +533,9 @@ github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxW
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
@ -537,6 +544,10 @@ github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3k
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
@ -569,15 +580,13 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -586,34 +595,28 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -621,9 +624,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -651,27 +653,23 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -680,9 +678,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -694,9 +691,8 @@ golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
@ -705,8 +701,6 @@ google.golang.org/api v0.150.0 h1:Z9k22qD289SZ8gCJrk4DrWXkNjtfvKAUo/l1ma8eBYE=
google.golang.org/api v0.150.0/go.mod h1:ccy+MJ6nrYFgE3WgRx/AMXOxOmU8Q4hSa+jjibzhxcg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
@ -751,10 +745,12 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

@ -72,9 +72,17 @@ type parseTest struct {
parseWantDiags bool
parseWantDiagHasErrors bool
getBuildsWantBuilds []packersdk.Build
getBuildsWantBuilds []*packer.CoreBuild
getBuildsWantDiags bool
// getBuildsWantDiagHasErrors bool
getHCPPackerRegistry *getHCPPackerRegistry
}
type getHCPPackerRegistry struct {
wantBlock *HCPPackerRegistryBlock
wantDiag bool
wantDiagHasError bool
}
func testParse(t *testing.T, tests []parseTest) {
@ -116,6 +124,31 @@ func testParse(t *testing.T, tests []parseTest) {
if diff := cmp.Diff(tt.getBuildsWantBuilds, gotBuilds, cmpOpts...); diff != "" {
t.Fatalf("Parser.getBuilds() wrong packer builds. %s", diff)
}
gotGetHCPPackerRegistry, gotDiags := gotCfg.GetHCPPackerRegistryBlock()
if tt.getHCPPackerRegistry != nil {
if tt.getHCPPackerRegistry.wantDiag && len(gotDiags) == 0 {
t.Fatal("Parser.getHCPPackerRegistry() expected diagostics, got 0")
}
if !tt.getHCPPackerRegistry.wantDiag && len(gotDiags) != 0 {
t.Fatalf("Parser.getHCPPackerRegistry() does not expect diagostics, got %v", gotDiags)
}
if tt.getHCPPackerRegistry.wantDiagHasError && !gotDiags.HasErrors() {
t.Fatalf("Parser.getHCPPackerRegistry() expected error diagostics, got %v", gotDiags)
}
if !tt.getHCPPackerRegistry.wantDiagHasError && gotDiags.HasErrors() {
t.Fatalf("Parser.getHCPPackerRegistry() did not expect error diagostics, got %v", gotDiags)
}
if diff := cmp.Diff(tt.getHCPPackerRegistry.wantBlock, gotGetHCPPackerRegistry, cmpOpts...); diff != "" {
t.Fatalf("Parser.parse() wrong HCPPackerRegistry block. %s", diff)
}
}
if tt.getHCPPackerRegistry == nil {
if gotGetHCPPackerRegistry != nil {
t.Fatalf("Parser.getHCPPackerRegistry() expected nil, got %v", gotGetHCPPackerRegistry)
}
}
})
}
}

@ -0,0 +1,39 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package function
import (
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
)
// AllTrue constructs a function that returns true if all elements of the
// list are true. If the list is empty, return true.
var AllTrue = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "list",
Type: cty.List(cty.Bool),
},
},
Type: function.StaticReturnType(cty.Bool),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
result := cty.True
for it := args[0].ElementIterator(); it.Next(); {
_, v := it.Element()
if !v.IsKnown() {
return cty.UnknownVal(cty.Bool), nil
}
if v.IsNull() {
return cty.False, nil
}
result = result.And(v)
if result.False() {
return cty.False, nil
}
}
return result, nil
},
})

@ -0,0 +1,89 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package function
import (
"fmt"
"testing"
"github.com/zclconf/go-cty/cty"
)
func TestAllTrue(t *testing.T) {
tests := []struct {
Collection cty.Value
Want cty.Value
Err bool
}{
{
cty.ListValEmpty(cty.Bool),
cty.True,
false,
},
{
cty.ListVal([]cty.Value{cty.True}),
cty.True,
false,
},
{
cty.ListVal([]cty.Value{cty.False}),
cty.False,
false,
},
{
cty.ListVal([]cty.Value{cty.True, cty.False}),
cty.False,
false,
},
{
cty.ListVal([]cty.Value{cty.False, cty.True}),
cty.False,
false,
},
{
cty.ListVal([]cty.Value{cty.True, cty.NullVal(cty.Bool)}),
cty.False,
false,
},
{
cty.ListVal([]cty.Value{cty.UnknownVal(cty.Bool)}),
cty.UnknownVal(cty.Bool).RefineNotNull(),
false,
},
{
cty.ListVal([]cty.Value{
cty.UnknownVal(cty.Bool),
cty.UnknownVal(cty.Bool),
}),
cty.UnknownVal(cty.Bool).RefineNotNull(),
false,
},
{
cty.UnknownVal(cty.List(cty.Bool)),
cty.UnknownVal(cty.Bool).RefineNotNull(),
false,
},
{
cty.NullVal(cty.List(cty.Bool)),
cty.NilVal,
true,
},
}
for _, tc := range tests {
t.Run(fmt.Sprintf("alltrue(%#v)", tc.Collection), func(t *testing.T) {
got, err := AllTrue.Call([]cty.Value{tc.Collection})
if tc.Err && err == nil {
t.Fatal("succeeded; want error")
}
if !tc.Err && err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !got.RawEquals(tc.Want) {
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, tc.Want)
}
})
}
}

@ -0,0 +1,44 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package function
import (
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
)
// AnyTrue constructs a function that returns true if a single element of
// the list is true. If the list is empty, return false.
var AnyTrue = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "list",
Type: cty.List(cty.Bool),
},
},
Type: function.StaticReturnType(cty.Bool),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
result := cty.False
var hasUnknown bool
for it := args[0].ElementIterator(); it.Next(); {
_, v := it.Element()
if !v.IsKnown() {
hasUnknown = true
continue
}
if v.IsNull() {
continue
}
result = result.Or(v)
if result.True() {
return cty.True, nil
}
}
if hasUnknown {
return cty.UnknownVal(cty.Bool), nil
}
return result, nil
},
})

@ -0,0 +1,89 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package function
import (
"fmt"
"testing"
"github.com/zclconf/go-cty/cty"
)
func TestAnyTrue(t *testing.T) {
tests := []struct {
Collection cty.Value
Want cty.Value
Err bool
}{
{
cty.ListValEmpty(cty.Bool),
cty.False,
false,
},
{
cty.ListVal([]cty.Value{cty.True}),
cty.True,
false,
},
{
cty.ListVal([]cty.Value{cty.False}),
cty.False,
false,
},
{
cty.ListVal([]cty.Value{cty.True, cty.False}),
cty.True,
false,
},
{
cty.ListVal([]cty.Value{cty.False, cty.True}),
cty.True,
false,
},
{
cty.ListVal([]cty.Value{cty.True, cty.NullVal(cty.Bool)}),
cty.True,
false,
},
{
cty.ListVal([]cty.Value{cty.UnknownVal(cty.Bool)}),
cty.UnknownVal(cty.Bool).RefineNotNull(),
false,
},
{
cty.ListVal([]cty.Value{
cty.UnknownVal(cty.Bool),
cty.UnknownVal(cty.Bool),
}),
cty.UnknownVal(cty.Bool).RefineNotNull(),
false,
},
{
cty.UnknownVal(cty.List(cty.Bool)),
cty.UnknownVal(cty.Bool).RefineNotNull(),
false,
},
{
cty.NullVal(cty.List(cty.Bool)),
cty.NilVal,
true,
},
}
for _, tc := range tests {
t.Run(fmt.Sprintf("anytrue(%#v)", tc.Collection), func(t *testing.T) {
got, err := AnyTrue.Call([]cty.Value{tc.Collection})
if tc.Err && err == nil {
t.Fatal("succeeded; want error")
}
if !tc.Err && err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !got.RawEquals(tc.Want) {
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, tc.Want)
}
})
}
}

@ -40,3 +40,30 @@ var AWSSecret = function.New(&function.Spec{
return cty.StringVal(val), err
},
})
// AWSSecret constructs a function that retrieves secrets from aws secrets
// manager.
//
// Contrary to AWSSecret, it does not accept a key, and instead returns the raw
// value of the secret at all times, i.e. if it's plaintext it will return the
// value, and if it's a key/value secret, the raw JSON will be returned.
var AWSSecretRaw = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "name",
Description: "The name of the secret to fetch",
Type: cty.String,
AllowNull: false,
AllowUnknown: false,
},
},
Type: function.StaticReturnType(cty.String),
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
name := args[0].AsString()
val, err := commontpl.GetRawAWSSecret(name)
if err != nil {
return cty.NullVal(cty.String), err
}
return cty.StringVal(val), nil
},
})

@ -0,0 +1,31 @@
package function
import (
"strings"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
)
// EndsWithFunc constructs a function that checks if a string ends with
// a specific suffix using strings.HasSuffix
var EndsWithFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "str",
Type: cty.String,
},
{
Name: "suffix",
Type: cty.String,
},
},
Type: function.StaticReturnType(cty.Bool),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
str := args[0].AsString()
suffix := args[1].AsString()
return cty.BoolVal(strings.HasSuffix(str, suffix)), nil
},
})

@ -0,0 +1,83 @@
package function
import (
"fmt"
"testing"
"github.com/zclconf/go-cty/cty"
)
func TestEndsWith(t *testing.T) {
tests := []struct {
String, Suffix cty.Value
Want cty.Value
}{
{
cty.StringVal("hello world"),
cty.StringVal("world"),
cty.True,
},
{
cty.StringVal("hey world"),
cty.StringVal("worldss"),
cty.False,
},
{
cty.StringVal(""),
cty.StringVal(""),
cty.True,
},
{
cty.StringVal("a"),
cty.StringVal(""),
cty.True,
},
{
cty.StringVal("hello world"),
cty.StringVal(" "),
cty.False,
},
{
cty.StringVal(" "),
cty.StringVal(""),
cty.True,
},
{
cty.StringVal(" "),
cty.StringVal("hello"),
cty.False,
},
{
cty.StringVal(""),
cty.StringVal("a"),
cty.False,
},
{
cty.UnknownVal(cty.String),
cty.StringVal("a"),
cty.UnknownVal(cty.Bool).RefineNotNull(),
},
{
cty.UnknownVal(cty.String),
cty.StringVal(""),
cty.UnknownVal(cty.Bool).RefineNotNull(),
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("EndsWith(%#v, %#v)", test.String, test.Suffix), func(t *testing.T) {
got, err := EndsWithFunc.Call([]cty.Value{test.String, test.Suffix})
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !got.RawEquals(test.Want) {
t.Errorf(
"wrong result\nstring: %#v\nsuffix: %#v\ngot: %#v\nwant: %#v",
test.String, test.Suffix, got, test.Want,
)
}
})
}
}

@ -0,0 +1,32 @@
package function
import (
"strings"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
)
// StartsWithFunc constructs a function that checks if a string starts with
// a specific prefix using strings.HasPrefix
var StartsWithFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "str",
Type: cty.String,
AllowUnknown: false,
},
{
Name: "prefix",
Type: cty.String,
},
},
Type: function.StaticReturnType(cty.Bool),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
str := args[0].AsString()
prefix := args[1].AsString()
return cty.BoolVal(strings.HasPrefix(str, prefix)), nil
},
})

@ -0,0 +1,98 @@
package function
import (
"fmt"
"testing"
"github.com/zclconf/go-cty/cty"
)
func TestStartsWith(t *testing.T) {
tests := []struct {
String, Prefix cty.Value
Want cty.Value
}{
{
cty.StringVal("hello world"),
cty.StringVal("hello"),
cty.True,
},
{
cty.StringVal("hey world"),
cty.StringVal("hello"),
cty.False,
},
{
cty.StringVal(""),
cty.StringVal(""),
cty.True,
},
{
cty.StringVal(""),
cty.StringVal(" "),
cty.False,
},
{
cty.StringVal("a"),
cty.StringVal(""),
cty.True,
},
{
cty.StringVal(""),
cty.StringVal("a"),
cty.False,
},
{
// Unicode combining characters edge-case: we match the prefix
// in terms of unicode code units rather than grapheme clusters,
// which is inconsistent with our string processing elsewhere but
// would be a breaking change to fix that bug now.
cty.StringVal("\U0001f937\u200d\u2642"), // "Man Shrugging" is encoded as "Person Shrugging" followed by zero-width joiner and then the masculine gender presentation modifier
cty.StringVal("\U0001f937"), // Just the "Person Shrugging" character without any modifiers
cty.True,
},
{
cty.StringVal("hello world"),
cty.StringVal(" "),
cty.False,
},
{
cty.StringVal(" "),
cty.StringVal(""),
cty.True,
},
{
cty.StringVal(" "),
cty.StringVal("hello"),
cty.False,
},
{
cty.UnknownVal(cty.String),
cty.StringVal("a"),
cty.UnknownVal(cty.Bool).RefineNotNull(),
},
{
cty.UnknownVal(cty.String),
cty.StringVal(""),
cty.UnknownVal(cty.Bool).RefineNotNull(),
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("StartsWith(%#v, %#v)", test.String, test.Prefix), func(t *testing.T) {
got, err := StartsWithFunc.Call([]cty.Value{test.String, test.Prefix})
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !got.RawEquals(test.Want) {
t.Errorf(
"wrong result\nstring: %#v\nprefix: %#v\ngot: %#v\nwant: %#v",
test.String, test.Prefix, got, test.Want,
)
}
})
}
}

@ -0,0 +1,32 @@
package function
import (
"strings"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
)
var StrContains = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "str",
Type: cty.String,
},
{
Name: "substr",
Type: cty.String,
},
},
Type: function.StaticReturnType(cty.Bool),
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
str := args[0].AsString()
substr := args[1].AsString()
if strings.Contains(str, substr) {
return cty.True, nil
}
return cty.False, nil
},
})

@ -0,0 +1,76 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package function
import (
"fmt"
"testing"
"github.com/zclconf/go-cty/cty"
)
func TestStrContains(t *testing.T) {
tests := []struct {
String cty.Value
Substr cty.Value
Want cty.Value
ExpectErr bool
}{
{
cty.StringVal("hello"),
cty.StringVal("hel"),
cty.BoolVal(true),
false,
},
{
cty.StringVal("hello"),
cty.StringVal("lo"),
cty.BoolVal(true),
false,
},
{
cty.StringVal("hello1"),
cty.StringVal("1"),
cty.BoolVal(true),
false,
},
{
cty.StringVal("hello1"),
cty.StringVal("heo"),
cty.BoolVal(false),
false,
},
{
cty.StringVal("hello1"),
cty.NumberIntVal(1),
cty.UnknownVal(cty.Bool),
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("includes(%#v, %#v)", test.String, test.Substr), func(t *testing.T) {
got, err := StrContains.Call([]cty.Value{
test.String,
test.Substr,
})
if test.ExpectErr && err == nil {
t.Fatal("succeeded; want error")
}
if test.ExpectErr && err != nil {
return
}
if !test.ExpectErr && err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !got.RawEquals(test.Want) {
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
}
})
}
}

@ -0,0 +1,83 @@
package function
import (
"fmt"
"math/big"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert"
"github.com/zclconf/go-cty/cty/function"
)
var SumFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "list",
Type: cty.DynamicPseudoType,
},
},
Type: function.StaticReturnType(cty.Number),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
if !args[0].CanIterateElements() {
return cty.NilVal, function.NewArgErrorf(0, "cannot sum noniterable")
}
if args[0].LengthInt() == 0 { // Easy path
return cty.NilVal, function.NewArgErrorf(0, "cannot sum an empty list")
}
arg := args[0].AsValueSlice()
ty := args[0].Type()
if !ty.IsListType() && !ty.IsSetType() && !ty.IsTupleType() {
return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple. Received %s", ty.FriendlyName())
}
if !args[0].IsWhollyKnown() {
return cty.UnknownVal(cty.Number), nil
}
// big.Float.Add can panic if the input values are opposing infinities,
// so we must catch that here in order to remain within
// the cty Function abstraction.
defer func() {
if r := recover(); r != nil {
if _, ok := r.(big.ErrNaN); ok {
ret = cty.NilVal
err = fmt.Errorf("can't compute sum of opposing infinities")
} else {
// not a panic we recognize
panic(r)
}
}
}()
s := arg[0]
if s.IsNull() {
return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
}
s, err = convert.Convert(s, cty.Number)
if err != nil {
return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
}
for _, v := range arg[1:] {
if v.IsNull() {
return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
}
v, err = convert.Convert(v, cty.Number)
if err != nil {
return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
}
s = s.Add(v)
}
return s, nil
},
})
// Sum adds numbers in a list, set, or tuple
func Sum(list cty.Value) (cty.Value, error) {
return SumFunc.Call([]cty.Value{list})
}

@ -0,0 +1,226 @@
package function
import (
"fmt"
"math"
"testing"
"github.com/zclconf/go-cty/cty"
)
func TestSum(t *testing.T) {
tests := []struct {
List cty.Value
Want cty.Value
Err string
}{
{
cty.ListVal([]cty.Value{
cty.NumberIntVal(1),
cty.NumberIntVal(2),
cty.NumberIntVal(3),
}),
cty.NumberIntVal(6),
"",
},
{
cty.ListVal([]cty.Value{
cty.NumberIntVal(1476),
cty.NumberIntVal(2093),
cty.NumberIntVal(2092495),
cty.NumberIntVal(64589234),
cty.NumberIntVal(234),
}),
cty.NumberIntVal(66685532),
"",
},
{
cty.ListVal([]cty.Value{
cty.StringVal("a"),
cty.StringVal("b"),
cty.StringVal("c"),
}),
cty.UnknownVal(cty.String),
"argument must be list, set, or tuple of number values",
},
{
cty.ListVal([]cty.Value{
cty.NumberIntVal(10),
cty.NumberIntVal(-19),
cty.NumberIntVal(5),
}),
cty.NumberIntVal(-4),
"",
},
{
cty.ListVal([]cty.Value{
cty.NumberFloatVal(10.2),
cty.NumberFloatVal(19.4),
cty.NumberFloatVal(5.7),
}),
cty.NumberFloatVal(35.3),
"",
},
{
cty.ListVal([]cty.Value{
cty.NumberFloatVal(-10.2),
cty.NumberFloatVal(-19.4),
cty.NumberFloatVal(-5.7),
}),
cty.NumberFloatVal(-35.3),
"",
},
{
cty.ListVal([]cty.Value{cty.NullVal(cty.Number)}),
cty.NilVal,
"argument must be list, set, or tuple of number values",
},
{
cty.ListVal([]cty.Value{
cty.NumberIntVal(5),
cty.NullVal(cty.Number),
}),
cty.NilVal,
"argument must be list, set, or tuple of number values",
},
{
cty.SetVal([]cty.Value{
cty.StringVal("a"),
cty.StringVal("b"),
cty.StringVal("c"),
}),
cty.UnknownVal(cty.String).RefineNotNull(),
"argument must be list, set, or tuple of number values",
},
{
cty.SetVal([]cty.Value{
cty.NumberIntVal(10),
cty.NumberIntVal(-19),
cty.NumberIntVal(5),
}),
cty.NumberIntVal(-4),
"",
},
{
cty.SetVal([]cty.Value{
cty.NumberIntVal(10),
cty.NumberIntVal(25),
cty.NumberIntVal(30),
}),
cty.NumberIntVal(65),
"",
},
{
cty.SetVal([]cty.Value{
cty.NumberFloatVal(2340.8),
cty.NumberFloatVal(10.2),
cty.NumberFloatVal(3),
}),
cty.NumberFloatVal(2354),
"",
},
{
cty.SetVal([]cty.Value{
cty.NumberFloatVal(2),
}),
cty.NumberFloatVal(2),
"",
},
{
cty.SetVal([]cty.Value{
cty.NumberFloatVal(-2),
cty.NumberFloatVal(-50),
cty.NumberFloatVal(-20),
cty.NumberFloatVal(-123),
cty.NumberFloatVal(-4),
}),
cty.NumberFloatVal(-199),
"",
},
{
cty.TupleVal([]cty.Value{
cty.NumberIntVal(12),
cty.StringVal("a"),
cty.NumberIntVal(38),
}),
cty.UnknownVal(cty.String).RefineNotNull(),
"argument must be list, set, or tuple of number values",
},
{
cty.NumberIntVal(12),
cty.NilVal,
"cannot sum noniterable",
},
{
cty.ListValEmpty(cty.Number),
cty.NilVal,
"cannot sum an empty list",
},
{
cty.MapVal(map[string]cty.Value{"hello": cty.True}),
cty.NilVal,
"argument must be list, set, or tuple. Received map of bool",
},
{
cty.UnknownVal(cty.Number),
cty.UnknownVal(cty.Number).RefineNotNull(),
"",
},
{
cty.UnknownVal(cty.List(cty.Number)),
cty.UnknownVal(cty.Number).RefineNotNull(),
"",
},
{ // known list containing unknown values
cty.ListVal([]cty.Value{cty.UnknownVal(cty.Number)}),
cty.UnknownVal(cty.Number).RefineNotNull(),
"",
},
{ // numbers too large to represent as float64
cty.ListVal([]cty.Value{
cty.MustParseNumberVal("1e+500"),
cty.MustParseNumberVal("1e+500"),
}),
cty.MustParseNumberVal("2e+500"),
"",
},
{ // edge case we have a special error handler for
cty.ListVal([]cty.Value{
cty.NumberFloatVal(math.Inf(1)),
cty.NumberFloatVal(math.Inf(-1)),
}),
cty.NilVal,
"can't compute sum of opposing infinities",
},
{
cty.ListVal([]cty.Value{
cty.StringVal("1"),
cty.StringVal("2"),
cty.StringVal("3"),
}),
cty.NumberIntVal(6),
"",
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("sum(%#v)", test.List), func(t *testing.T) {
got, err := Sum(test.List)
if test.Err != "" {
if err == nil {
t.Fatal("succeeded; want error")
} else if got, want := err.Error(), test.Err; got != want {
t.Fatalf("wrong error\n got: %s\nwant: %s", got, want)
}
return
} else if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !got.RawEquals(test.Want) {
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
}
})
}
}

@ -32,99 +32,106 @@ import (
func Functions(basedir string) map[string]function.Function {
funcs := map[string]function.Function{
"abs": stdlib.AbsoluteFunc,
"abspath": filesystem.AbsPathFunc,
"aws_secretsmanager": pkrfunction.AWSSecret,
"basename": filesystem.BasenameFunc,
"base64decode": encoding.Base64DecodeFunc,
"base64encode": encoding.Base64EncodeFunc,
"base64gzip": pkrfunction.Base64GzipFunc,
"bcrypt": crypto.BcryptFunc,
"can": tryfunc.CanFunc,
"ceil": stdlib.CeilFunc,
"chomp": stdlib.ChompFunc,
"chunklist": stdlib.ChunklistFunc,
"cidrhost": cidr.HostFunc,
"cidrnetmask": cidr.NetmaskFunc,
"cidrsubnet": cidr.SubnetFunc,
"cidrsubnets": cidr.SubnetsFunc,
"coalesce": collection.CoalesceFunc,
"coalescelist": stdlib.CoalesceListFunc,
"compact": stdlib.CompactFunc,
"concat": stdlib.ConcatFunc,
"consul_key": pkrfunction.ConsulFunc,
"contains": stdlib.ContainsFunc,
"convert": typeexpr.ConvertFunc,
"csvdecode": stdlib.CSVDecodeFunc,
"dirname": filesystem.DirnameFunc,
"distinct": stdlib.DistinctFunc,
"element": stdlib.ElementFunc,
"file": filesystem.MakeFileFunc(basedir, false),
"filebase64": pkrfunction.Filebase64,
"fileexists": filesystem.MakeFileExistsFunc(basedir),
"fileset": filesystem.MakeFileSetFunc(basedir),
"flatten": stdlib.FlattenFunc,
"floor": stdlib.FloorFunc,
"format": stdlib.FormatFunc,
"formatdate": stdlib.FormatDateFunc,
"formatlist": stdlib.FormatListFunc,
"indent": stdlib.IndentFunc,
"index": pkrfunction.IndexFunc, // stdlib.IndexFunc is not compatible
"join": stdlib.JoinFunc,
"jsondecode": stdlib.JSONDecodeFunc,
"jsonencode": stdlib.JSONEncodeFunc,
"keys": stdlib.KeysFunc,
"legacy_isotime": pkrfunction.LegacyIsotimeFunc,
"legacy_strftime": pkrfunction.LegacyStrftimeFunc,
"length": pkrfunction.LengthFunc,
"log": stdlib.LogFunc,
"lookup": stdlib.LookupFunc,
"lower": stdlib.LowerFunc,
"max": stdlib.MaxFunc,
"md5": crypto.Md5Func,
"merge": stdlib.MergeFunc,
"min": stdlib.MinFunc,
"parseint": stdlib.ParseIntFunc,
"pathexpand": filesystem.PathExpandFunc,
"pow": stdlib.PowFunc,
"range": stdlib.RangeFunc,
"reverse": stdlib.ReverseListFunc,
"replace": stdlib.ReplaceFunc,
"regex": stdlib.RegexFunc,
"regexall": stdlib.RegexAllFunc,
"regex_replace": stdlib.RegexReplaceFunc,
"rsadecrypt": crypto.RsaDecryptFunc,
"setintersection": stdlib.SetIntersectionFunc,
"setproduct": stdlib.SetProductFunc,
"setunion": stdlib.SetUnionFunc,
"sha1": crypto.Sha1Func,
"sha256": crypto.Sha256Func,
"sha512": crypto.Sha512Func,
"signum": stdlib.SignumFunc,
"slice": stdlib.SliceFunc,
"sort": stdlib.SortFunc,
"split": stdlib.SplitFunc,
"strrev": stdlib.ReverseFunc,
"substr": stdlib.SubstrFunc,
"textdecodebase64": TextDecodeBase64Func,
"textencodebase64": TextEncodeBase64Func,
"timestamp": pkrfunction.TimestampFunc,
"timeadd": stdlib.TimeAddFunc,
"title": stdlib.TitleFunc,
"trim": stdlib.TrimFunc,
"trimprefix": stdlib.TrimPrefixFunc,
"trimspace": stdlib.TrimSpaceFunc,
"trimsuffix": stdlib.TrimSuffixFunc,
"try": tryfunc.TryFunc,
"upper": stdlib.UpperFunc,
"urlencode": encoding.URLEncodeFunc,
"uuidv4": uuid.V4Func,
"uuidv5": uuid.V5Func,
"values": stdlib.ValuesFunc,
"vault": pkrfunction.VaultFunc,
"yamldecode": ctyyaml.YAMLDecodeFunc,
"yamlencode": ctyyaml.YAMLEncodeFunc,
"zipmap": stdlib.ZipmapFunc,
"abs": stdlib.AbsoluteFunc,
"abspath": filesystem.AbsPathFunc,
"alltrue": pkrfunction.AllTrue,
"anytrue": pkrfunction.AnyTrue,
"aws_secretsmanager": pkrfunction.AWSSecret,
"aws_secretsmanager_raw": pkrfunction.AWSSecretRaw,
"basename": filesystem.BasenameFunc,
"base64decode": encoding.Base64DecodeFunc,
"base64encode": encoding.Base64EncodeFunc,
"base64gzip": pkrfunction.Base64GzipFunc,
"bcrypt": crypto.BcryptFunc,
"can": tryfunc.CanFunc,
"ceil": stdlib.CeilFunc,
"chomp": stdlib.ChompFunc,
"chunklist": stdlib.ChunklistFunc,
"cidrhost": cidr.HostFunc,
"cidrnetmask": cidr.NetmaskFunc,
"cidrsubnet": cidr.SubnetFunc,
"cidrsubnets": cidr.SubnetsFunc,
"coalesce": collection.CoalesceFunc,
"coalescelist": stdlib.CoalesceListFunc,
"compact": stdlib.CompactFunc,
"concat": stdlib.ConcatFunc,
"consul_key": pkrfunction.ConsulFunc,
"contains": stdlib.ContainsFunc,
"convert": typeexpr.ConvertFunc,
"csvdecode": stdlib.CSVDecodeFunc,
"dirname": filesystem.DirnameFunc,
"distinct": stdlib.DistinctFunc,
"element": stdlib.ElementFunc,
"endswith": pkrfunction.EndsWithFunc,
"file": filesystem.MakeFileFunc(basedir, false),
"filebase64": pkrfunction.Filebase64,
"fileexists": filesystem.MakeFileExistsFunc(basedir),
"fileset": filesystem.MakeFileSetFunc(basedir),
"flatten": stdlib.FlattenFunc,
"floor": stdlib.FloorFunc,
"format": stdlib.FormatFunc,
"formatdate": stdlib.FormatDateFunc,
"formatlist": stdlib.FormatListFunc,
"indent": stdlib.IndentFunc,
"index": pkrfunction.IndexFunc, // stdlib.IndexFunc is not compatible
"join": stdlib.JoinFunc,
"jsondecode": stdlib.JSONDecodeFunc,
"jsonencode": stdlib.JSONEncodeFunc,
"keys": stdlib.KeysFunc,
"legacy_isotime": pkrfunction.LegacyIsotimeFunc,
"legacy_strftime": pkrfunction.LegacyStrftimeFunc,
"length": pkrfunction.LengthFunc,
"log": stdlib.LogFunc,
"lookup": stdlib.LookupFunc,
"lower": stdlib.LowerFunc,
"max": stdlib.MaxFunc,
"md5": crypto.Md5Func,
"merge": stdlib.MergeFunc,
"min": stdlib.MinFunc,
"parseint": stdlib.ParseIntFunc,
"pathexpand": filesystem.PathExpandFunc,
"pow": stdlib.PowFunc,
"range": stdlib.RangeFunc,
"reverse": stdlib.ReverseListFunc,
"replace": stdlib.ReplaceFunc,
"regex": stdlib.RegexFunc,
"regexall": stdlib.RegexAllFunc,
"regex_replace": stdlib.RegexReplaceFunc,
"rsadecrypt": crypto.RsaDecryptFunc,
"setintersection": stdlib.SetIntersectionFunc,
"setproduct": stdlib.SetProductFunc,
"setunion": stdlib.SetUnionFunc,
"sha1": crypto.Sha1Func,
"sha256": crypto.Sha256Func,
"sha512": crypto.Sha512Func,
"signum": stdlib.SignumFunc,
"slice": stdlib.SliceFunc,
"sort": stdlib.SortFunc,
"split": stdlib.SplitFunc,
"startswith": pkrfunction.StartsWithFunc,
"strcontains": pkrfunction.StrContains,
"strrev": stdlib.ReverseFunc,
"substr": stdlib.SubstrFunc,
"sum": pkrfunction.SumFunc,
"textdecodebase64": TextDecodeBase64Func,
"textencodebase64": TextEncodeBase64Func,
"timestamp": pkrfunction.TimestampFunc,
"timeadd": stdlib.TimeAddFunc,
"title": stdlib.TitleFunc,
"trim": stdlib.TrimFunc,
"trimprefix": stdlib.TrimPrefixFunc,
"trimspace": stdlib.TrimSpaceFunc,
"trimsuffix": stdlib.TrimSuffixFunc,
"try": tryfunc.TryFunc,
"upper": stdlib.UpperFunc,
"urlencode": encoding.URLEncodeFunc,
"uuidv4": uuid.V4Func,
"uuidv5": uuid.V5Func,
"values": stdlib.ValuesFunc,
"vault": pkrfunction.VaultFunc,
"yamldecode": ctyyaml.YAMLDecodeFunc,
"yamlencode": ctyyaml.YAMLEncodeFunc,
"zipmap": stdlib.ZipmapFunc,
}
funcs["templatefile"] = pkrfunction.MakeTemplateFileFunc(basedir, func() map[string]function.Function {

@ -20,15 +20,16 @@ import (
)
const (
packerLabel = "packer"
sourceLabel = "source"
variablesLabel = "variables"
variableLabel = "variable"
localsLabel = "locals"
localLabel = "local"
dataSourceLabel = "data"
buildLabel = "build"
communicatorLabel = "communicator"
packerLabel = "packer"
sourceLabel = "source"
variablesLabel = "variables"
variableLabel = "variable"
localsLabel = "locals"
localLabel = "local"
dataSourceLabel = "data"
buildLabel = "build"
hcpPackerRegistryLabel = "hcp_packer_registry"
communicatorLabel = "communicator"
)
var configSchema = &hcl.BodySchema{
@ -41,6 +42,7 @@ var configSchema = &hcl.BodySchema{
{Type: localLabel, LabelNames: []string{"name"}},
{Type: dataSourceLabel, LabelNames: []string{"type", "name"}},
{Type: buildLabel},
{Type: hcpPackerRegistryLabel},
{Type: communicatorLabel, LabelNames: []string{"type", "name"}},
},
}
@ -165,6 +167,14 @@ func (p *Parser) Parse(filename string, varFiles []string, argVars map[string]st
return cfg, diags
}
// Looks for invalid arguments or unsupported block types
{
for _, file := range files {
_, moreDiags := file.Body.Content(configSchema)
diags = append(diags, moreDiags...)
}
}
// Decode required_plugins blocks.
//
// Note: using `latest` ( or actually an empty string ) in a config file
@ -200,39 +210,44 @@ func (p *Parser) Parse(filename string, varFiles []string, argVars map[string]st
{
hclVarFiles, jsonVarFiles, moreDiags := GetHCL2Files(filename, hcl2AutoVarFileExt, hcl2AutoVarJsonFileExt)
diags = append(diags, moreDiags...)
for _, file := range varFiles {
// Combine all variable files into a single list, preserving the intended precedence and order.
// The order is: auto-loaded HCL files, auto-loaded JSON files, followed by user-specified varFiles.
// This ensures that user-specified files can override values from auto-loaded files,
// and that their relative order is preserved exactly as specified by the user.
variableFileNames := append(append(hclVarFiles, jsonVarFiles...), varFiles...)
var variableFiles []*hcl.File
for _, file := range variableFileNames {
var (
f *hcl.File
moreDiags hcl.Diagnostics
)
switch filepath.Ext(file) {
case ".hcl":
hclVarFiles = append(hclVarFiles, file)
f, moreDiags = p.ParseHCLFile(file)
case ".json":
jsonVarFiles = append(jsonVarFiles, file)
f, moreDiags = p.ParseJSONFile(file)
default:
diags = append(moreDiags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Could not guess format of " + file,
Detail: "A var file must be suffixed with `.hcl` or `.json`.",
})
}
}
var varFiles []*hcl.File
for _, filename := range hclVarFiles {
f, moreDiags := p.ParseHCLFile(filename)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
continue
moreDiags = hcl.Diagnostics{
&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Could not guess format of " + file,
Detail: "A var file must be suffixed with `.hcl` or `.json`.",
},
}
}
varFiles = append(varFiles, f)
}
for _, filename := range jsonVarFiles {
f, moreDiags := p.ParseJSONFile(filename)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
continue
}
varFiles = append(varFiles, f)
variableFiles = append(variableFiles, f)
}
diags = append(diags, cfg.collectInputVariableValues(os.Environ(), varFiles, argVars)...)
diags = append(diags, cfg.collectInputVariableValues(os.Environ(), variableFiles, argVars)...)
}
return cfg, diags
@ -541,6 +556,22 @@ func (p *Parser) parseConfig(f *hcl.File, cfg *PackerConfig) hcl.Diagnostics {
for _, block := range content.Blocks {
switch block.Type {
case buildHCPPackerRegistryLabel:
if cfg.HCPPackerRegistry != nil {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Only one " + buildHCPPackerRegistryLabel + " is allowed",
Subject: block.DefRange.Ptr(),
})
continue
}
hcpPackerRegistry, moreDiags := p.decodeHCPRegistry(block, cfg)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
continue
}
cfg.HCPPackerRegistry = hcpPackerRegistry
case sourceLabel:
source, moreDiags := p.decodeSource(block)
diags = append(diags, moreDiags...)
@ -585,8 +616,7 @@ func (p *Parser) decodeDatasources(file *hcl.File, cfg *PackerConfig) hcl.Diagno
var diags hcl.Diagnostics
body := file.Body
content, moreDiags := body.Content(configSchema)
diags = append(diags, moreDiags...)
content, _ := body.Content(configSchema)
for _, block := range content.Blocks {
switch block.Type {

@ -0,0 +1,21 @@
source "null" "test" {
communicator = "none"
}
build {
name = "build1"
hcp_packer_registry {
bucket_name = "ok-Bucket-name-1"
}
sources = ["null.test"]
}
build {
name = "build2"
hcp_packer_registry {
bucket_name = "ok-Bucket-name-1"
}
sources = ["null.test"]
}

@ -0,0 +1,18 @@
source "null" "test" {
communicator = "none"
}
build {
name = "build1"
sources = ["null.test"]
}
build {
name = "build2"
hcp_packer_registry {
bucket_name = "ok-Bucket-name-1"
}
sources = ["null.test"]
}

@ -0,0 +1,17 @@
source "null" "test" {
communicator = "none"
}
build {
name = "build1"
hcp_packer_registry {
bucket_name = "ok-Bucket-name-1"
}
sources = ["null.test"]
}
build {
name = "build2"
sources = ["null.test"]
}

@ -1,6 +0,0 @@
build {
name = "bucket-slug"
hcp_packer_registry {
labels = ""
}
}

@ -2,10 +2,14 @@ source "null" "test" {
communicator = "none"
}
hcp_packer_registry {
bucket_name = "ok-Bucket-name-1"
}
build {
name = "bucket-slug"
hcp_packer_registry {
bucket_name = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
bucket_name = "ok-Bucket-name-1"
}
sources = ["null.test"]

@ -2,11 +2,10 @@ source "null" "test" {
communicator = "none"
}
hcp_packer_registry {
}
build {
name = "bucket-slug"
hcp_packer_registry {
bucket_name = "ba"
}
sources = ["null.test"]
}

@ -2,11 +2,11 @@ source "null" "test" {
communicator = "none"
}
hcp_packer_registry {
bucket_name = "invalid_bucket"
}
build {
name = "bucket-slug"
hcp_packer_registry {
bucket_name = "invalid_bucket"
}
sources = ["null.test"]
}

@ -0,0 +1,7 @@
hcp_packer_registry {
labels = ""
}
build {
name = "bucket-slug"
}

@ -0,0 +1,11 @@
source "null" "test" {
communicator = "none"
}
hcp_packer_registry {
bucket_name = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
}
build {
name = "bucket-slug"
sources = ["null.test"]
}

@ -2,15 +2,15 @@ source "null" "test" {
communicator = "none"
}
build {
name = "bucket-slug"
hcp_packer_registry {
description = <<EOT
hcp_packer_registry {
description = <<EOT
This is a super super super super super super super super super super super super super super super super super super
super super super super super super super super super super super super super super super super super super super super
super super super long description
EOT
}
EOT
}
build {
name = "bucket-slug"
sources = ["null.test"]
}

@ -0,0 +1,12 @@
source "null" "test" {
communicator = "none"
}
hcp_packer_registry {
bucket_name = "ok-Bucket-name-1"
}
build {
name = "bucket-slug"
sources = ["null.test"]
}

@ -0,0 +1,12 @@
source "null" "test" {
communicator = "none"
}
hcp_packer_registry {
bucket_name = "ba"
}
build {
name = "bucket-slug"
sources = ["null.test"]
}

@ -2,10 +2,12 @@ variable "bucket" {
type = string
default = "variable-bucket-slug"
}
hcp_packer_registry {
bucket_name = var.bucket
}
build {
hcp_packer_registry {
bucket_name = var.bucket
}
sources = [
"source.virtualbox-iso.ubuntu-1204",
]

@ -14,12 +14,13 @@ variable "build_labels" {
}
}
hcp_packer_registry {
bucket_name = "bucket-slug"
bucket_labels = var.bucket_labels
build_labels = var.build_labels
}
build {
hcp_packer_registry {
bucket_name = "bucket-slug"
bucket_labels = var.bucket_labels
build_labels = var.build_labels
}
sources = [
"source.virtualbox-iso.ubuntu-1204",
]

@ -54,7 +54,12 @@ func (p *Parser) decodeHCPRegistry(block *hcl.Block, cfg *PackerConfig) (*HCPPac
return nil, diags
}
if !bucketNameRegexp.MatchString(b.Slug) {
// No need to check the bucket name here if it's empty, since it can
// be set through the `HCP_PACKER_BUCKET_NAME` environment var.
//
// If both are unset, creating the build on HCP Packer will fail, and
// so will the packer build command.
if b.Slug != "" && !bucketNameRegexp.MatchString(b.Slug) {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: fmt.Sprintf("%s.bucket_name can only contain between 3 and 36 ASCII letters, numbers and hyphens", buildHCPPackerRegistryLabel),

@ -8,7 +8,6 @@ import (
"testing"
"github.com/hashicorp/hcl/v2"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/builder/null"
"github.com/hashicorp/packer/packer"
"github.com/zclconf/go-cty/cty"
@ -20,12 +19,297 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
defaultParser := getBasicParser()
tests := []parseTest{
{"build block level deprecated",
defaultParser,
parseTestArgs{"testdata/hcp_par/build-block-ok-bucket.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
Sources: map[SourceRef]SourceBlock{
refNull: {
Type: "null",
Name: "test",
block: &hcl.Block{
Type: "source",
},
},
},
Builds: Builds{
{
Name: "bucket-slug",
HCPPackerRegistry: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
},
},
false, false,
[]*packer.CoreBuild{
&packer.CoreBuild{
BuildName: "bucket-slug",
Type: "null.test",
Builder: &null.Builder{},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
Prepared: true,
BuilderType: "null",
},
},
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
wantDiag: true,
wantDiagHasError: false,
},
},
{"bucket name OK multiple block",
defaultParser,
parseTestArgs{"testdata/hcp_par/build-block-ok-multiple-build-block.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
Sources: map[SourceRef]SourceBlock{
refNull: {
Type: "null",
Name: "test",
block: &hcl.Block{
Type: "source",
},
},
},
Builds: Builds{
{
Name: "build1",
HCPPackerRegistry: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
{
Name: "build2",
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
},
},
false, false,
[]*packer.CoreBuild{
&packer.CoreBuild{
BuildName: "build1",
Type: "null.test",
Builder: &null.Builder{},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
Prepared: true,
BuilderType: "null",
},
&packer.CoreBuild{
BuildName: "build2",
Type: "null.test",
Builder: &null.Builder{},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
Prepared: true,
BuilderType: "null",
},
},
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
wantDiag: true,
wantDiagHasError: false,
},
},
{"bucket name OK multiple block second build block",
defaultParser,
parseTestArgs{"testdata/hcp_par/build-block-ok-multiple-build-block-second-block.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
Sources: map[SourceRef]SourceBlock{
refNull: {
Type: "null",
Name: "test",
block: &hcl.Block{
Type: "source",
},
},
},
Builds: Builds{
{
Name: "build1",
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
{
Name: "build2",
HCPPackerRegistry: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
},
},
false, false,
[]*packer.CoreBuild{
&packer.CoreBuild{
BuildName: "build1",
Type: "null.test",
Builder: &null.Builder{},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
Prepared: true,
BuilderType: "null",
},
&packer.CoreBuild{
BuildName: "build2",
Type: "null.test",
Builder: &null.Builder{},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
Prepared: true,
BuilderType: "null",
},
},
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
wantDiag: true,
wantDiagHasError: false,
},
},
{"bucket name OK multiple block multiple declaration",
defaultParser,
parseTestArgs{"testdata/hcp_par/build-block-error-multiple-hcp-declaration.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
Sources: map[SourceRef]SourceBlock{
refNull: {
Type: "null",
Name: "test",
block: &hcl.Block{
Type: "source",
},
},
},
Builds: Builds{
{
Name: "build1",
HCPPackerRegistry: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
{
Name: "build2",
HCPPackerRegistry: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
},
},
false, false,
[]*packer.CoreBuild{
&packer.CoreBuild{
BuildName: "build1",
Type: "null.test",
Builder: &null.Builder{},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
Prepared: true,
BuilderType: "null",
},
&packer.CoreBuild{
BuildName: "build2",
Type: "null.test",
Builder: &null.Builder{},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
Prepared: true,
BuilderType: "null",
},
},
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
wantDiag: true,
wantDiagHasError: true,
},
},
{"bucket_name left empty",
defaultParser,
parseTestArgs{"testdata/hcp_par/top-level-empty-bucket.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
HCPPackerRegistry: &HCPPackerRegistryBlock{Slug: ""},
Sources: map[SourceRef]SourceBlock{
refNull: {
Type: "null",
Name: "test",
block: &hcl.Block{
Type: "source",
},
},
},
Builds: Builds{
{
Name: "bucket-slug",
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
},
},
false, false,
[]*packer.CoreBuild{
&packer.CoreBuild{
BuildName: "bucket-slug",
Type: "null.test",
Builder: &null.Builder{},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
Prepared: true,
BuilderType: "null",
},
},
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{Slug: ""},
wantDiag: false,
wantDiagHasError: false,
},
},
{"bucket_name as variable",
defaultParser,
parseTestArgs{"testdata/hcp_par/variable-for-bucket_name.pkr.hcl", nil, nil},
parseTestArgs{"testdata/hcp_par/top-level-variable-for-bucket-name.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
HCPPackerRegistry: &HCPPackerRegistryBlock{
Slug: "variable-bucket-slug",
},
InputVariables: Variables{
"bucket": &Variable{
Name: "bucket",
@ -38,9 +322,6 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
Builds: Builds{
&BuildBlock{
HCPPackerRegistry: &HCPPackerRegistryBlock{
Slug: "variable-bucket-slug",
},
Sources: []SourceUseBlock{
{
SourceRef: refVBIsoUbuntu1204,
@ -50,7 +331,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "virtualbox-iso.ubuntu-1204",
Prepared: true,
@ -61,13 +342,24 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
},
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{Slug: "variable-bucket-slug"},
wantDiag: false,
wantDiagHasError: false,
},
},
{"bucket_labels and build_labels as variables",
defaultParser,
parseTestArgs{"testdata/hcp_par/variables-for-labels.pkr.hcl", nil, nil},
parseTestArgs{"testdata/hcp_par/top-level-variables-for-labels.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
HCPPackerRegistry: &HCPPackerRegistryBlock{
Slug: "bucket-slug",
BucketLabels: map[string]string{"team": "development"},
BuildLabels: map[string]string{"packageA": "v3.17.5", "packageZ": "v0.6"},
},
InputVariables: Variables{
"bucket_labels": &Variable{
Name: "bucket_labels",
@ -90,11 +382,6 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
Builds: Builds{
&BuildBlock{
HCPPackerRegistry: &HCPPackerRegistryBlock{
Slug: "bucket-slug",
BucketLabels: map[string]string{"team": "development"},
BuildLabels: map[string]string{"packageA": "v3.17.5", "packageZ": "v0.6"},
},
Sources: []SourceUseBlock{
{
SourceRef: refVBIsoUbuntu1204,
@ -104,7 +391,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "virtualbox-iso.ubuntu-1204",
Prepared: true,
@ -115,10 +402,19 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
},
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{
Slug: "bucket-slug",
BucketLabels: map[string]string{"team": "development"},
BuildLabels: map[string]string{"packageA": "v3.17.5", "packageZ": "v0.6"},
},
wantDiag: false,
wantDiagHasError: false,
},
},
{"invalid hcp_packer_registry config",
defaultParser,
parseTestArgs{"testdata/hcp_par/invalid.pkr.hcl", nil, nil},
parseTestArgs{"testdata/hcp_par/top-level-invalid.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
@ -126,10 +422,15 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
true, true,
nil,
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{},
wantDiag: false,
wantDiagHasError: false,
},
},
{"long hcp_packer_registry.description",
defaultParser,
parseTestArgs{"testdata/hcp_par/long-description.pkr.hcl", nil, nil},
parseTestArgs{"testdata/hcp_par/top-level-long-description.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
@ -142,14 +443,29 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
},
},
Builds: Builds{
{
Name: "bucket-slug",
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
},
},
true, true,
nil,
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{},
wantDiag: false,
wantDiagHasError: false,
},
},
{"bucket name too short",
defaultParser,
parseTestArgs{"testdata/hcp_par/short_bucket.pkr.hcl", nil, nil},
parseTestArgs{"testdata/hcp_par/top-level-short-bucket.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
@ -162,14 +478,29 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
},
},
Builds: Builds{
{
Name: "bucket-slug",
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
},
},
true, true,
nil,
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{},
wantDiag: false,
wantDiagHasError: false,
},
},
{"bucket name too long",
defaultParser,
parseTestArgs{"testdata/hcp_par/long_bucket.pkr.hcl", nil, nil},
parseTestArgs{"testdata/hcp_par/top-level-long-bucket.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
@ -182,14 +513,29 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
},
},
Builds: Builds{
{
Name: "bucket-slug",
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
},
},
true, true,
nil,
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{},
wantDiag: false,
wantDiagHasError: false,
},
},
{"bucket name invalid chars",
defaultParser,
parseTestArgs{"testdata/hcp_par/invalid_bucket.pkr.hcl", nil, nil},
parseTestArgs{"testdata/hcp_par/top-level-invalid-bucket.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
@ -202,17 +548,79 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
},
},
Builds: Builds{
{
Name: "bucket-slug",
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
},
},
true, true,
nil,
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{},
wantDiag: false,
wantDiagHasError: false,
},
},
{"bucket name OK",
defaultParser,
parseTestArgs{"testdata/hcp_par/ok_bucket.pkr.hcl", nil, nil},
parseTestArgs{"testdata/hcp_par/top-level-ok-bucket.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
HCPPackerRegistry: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
Sources: map[SourceRef]SourceBlock{
refNull: {
Type: "null",
Name: "test",
block: &hcl.Block{
Type: "source",
},
},
},
Builds: Builds{
{
Name: "bucket-slug",
Sources: []SourceUseBlock{
{
SourceRef: refNull,
},
},
},
},
},
false, false,
[]*packer.CoreBuild{
&packer.CoreBuild{
BuildName: "bucket-slug",
Type: "null.test",
Builder: &null.Builder{},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
Prepared: true,
BuilderType: "null",
},
},
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
wantDiag: false,
wantDiagHasError: false,
},
},
{"top level and build block",
defaultParser,
parseTestArgs{"testdata/hcp_par/top-level-and-build-block.pkr.hcl", nil, nil},
&PackerConfig{
CorePackerVersionString: lockedVersion,
Basedir: filepath.Join("testdata", "hcp_par"),
HCPPackerRegistry: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
Sources: map[SourceRef]SourceBlock{
refNull: {
Type: "null",
@ -235,7 +643,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
BuildName: "bucket-slug",
Type: "null.test",
@ -247,6 +655,11 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
},
},
false,
&getHCPPackerRegistry{
wantBlock: &HCPPackerRegistryBlock{Slug: "ok-Bucket-name-1"},
wantDiag: true,
wantDiagHasError: true,
},
},
}
testParse(t, tests)

@ -7,7 +7,6 @@ import (
"path/filepath"
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
. "github.com/hashicorp/packer/hcl2template/internal"
"github.com/hashicorp/packer/packer"
"github.com/zclconf/go-cty/cty"
@ -55,8 +54,9 @@ func TestParse_build(t *testing.T) {
},
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
true,
nil,
},
{"untyped provisioner",
defaultParser,
@ -69,6 +69,7 @@ func TestParse_build(t *testing.T) {
true, true,
nil,
false,
nil,
},
{"nonexistent provisioner",
defaultParser,
@ -104,10 +105,11 @@ func TestParse_build(t *testing.T) {
},
},
true, true,
[]packersdk.Build{&packer.CoreBuild{
[]*packer.CoreBuild{&packer.CoreBuild{
Provisioners: []packer.CoreBuildProvisioner{},
}},
false,
nil,
},
{"two error-cleanup-provisioner",
defaultParser,
@ -120,7 +122,7 @@ func TestParse_build(t *testing.T) {
},
},
true, true,
[]packersdk.Build{&packer.CoreBuild{
[]*packer.CoreBuild{&packer.CoreBuild{
Builder: emptyMockBuilder,
CleanupProvisioner: packer.CoreBuildProvisioner{
PType: "shell-local",
@ -135,6 +137,7 @@ func TestParse_build(t *testing.T) {
},
}},
false,
nil,
},
{"untyped post-processor",
defaultParser,
@ -145,8 +148,9 @@ func TestParse_build(t *testing.T) {
Builds: nil,
},
true, true,
[]packersdk.Build{&packer.CoreBuild{}},
[]*packer.CoreBuild{&packer.CoreBuild{}},
false,
nil,
},
{"nonexistent post-processor",
defaultParser,
@ -184,10 +188,11 @@ func TestParse_build(t *testing.T) {
},
},
true, true,
[]packersdk.Build{&packer.CoreBuild{
[]*packer.CoreBuild{&packer.CoreBuild{
PostProcessors: [][]packer.CoreBuildPostProcessor{},
}},
true,
nil,
},
{"invalid source",
defaultParser,
@ -198,8 +203,9 @@ func TestParse_build(t *testing.T) {
Builds: nil,
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"named build",
defaultParser,
@ -225,8 +231,9 @@ func TestParse_build(t *testing.T) {
},
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
true,
nil,
},
{"post-processor with only and except",
defaultParser,
@ -280,7 +287,7 @@ func TestParse_build(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "virtualbox-iso.ubuntu-1204",
BuilderType: "virtualbox-iso",
@ -353,6 +360,7 @@ func TestParse_build(t *testing.T) {
},
},
false,
nil,
},
{"provisioner with only and except",
defaultParser,
@ -397,7 +405,7 @@ func TestParse_build(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "virtualbox-iso.ubuntu-1204",
BuilderType: "virtualbox-iso",
@ -462,6 +470,7 @@ func TestParse_build(t *testing.T) {
},
},
false,
nil,
},
{"provisioner with packer_version interpolation",
defaultParser,
@ -488,7 +497,7 @@ func TestParse_build(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "virtualbox-iso.ubuntu-1204",
BuilderType: "virtualbox-iso",
@ -514,6 +523,7 @@ func TestParse_build(t *testing.T) {
},
},
false,
nil,
},
{"variable interpolation for build name and description",
defaultParser,
@ -551,7 +561,7 @@ func TestParse_build(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
BuildName: "build-name",
Type: "virtualbox-iso.ubuntu-1204",
@ -563,6 +573,7 @@ func TestParse_build(t *testing.T) {
},
},
false,
nil,
},
{"invalid variable for build name",
defaultParser,
@ -574,8 +585,9 @@ func TestParse_build(t *testing.T) {
Builds: nil,
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"use build.name in post-processor block",
defaultParser,
@ -606,7 +618,7 @@ func TestParse_build(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
BuildName: "test-build",
Type: "virtualbox-iso.ubuntu-1204",
@ -636,6 +648,7 @@ func TestParse_build(t *testing.T) {
},
},
false,
nil,
},
{"use build.name in provisioner block",
defaultParser,
@ -664,7 +677,7 @@ func TestParse_build(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
BuildName: "build-name-test",
Type: "virtualbox-iso.ubuntu-1204",
@ -692,6 +705,7 @@ func TestParse_build(t *testing.T) {
},
},
false,
nil,
},
}
testParse(t, tests)

@ -7,7 +7,6 @@ import (
"path/filepath"
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/builder/null"
"github.com/hashicorp/packer/packer"
)
@ -54,7 +53,7 @@ func TestParse_datasource(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "null.test",
BuilderType: "null",
@ -65,6 +64,7 @@ func TestParse_datasource(t *testing.T) {
},
},
false,
nil,
},
{"recursive datasources",
defaultParser,
@ -142,7 +142,7 @@ func TestParse_datasource(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "null.test",
BuilderType: "null",
@ -153,6 +153,7 @@ func TestParse_datasource(t *testing.T) {
},
},
false,
nil,
},
{"untyped datasource",
defaultParser,
@ -164,6 +165,7 @@ func TestParse_datasource(t *testing.T) {
true, true,
nil,
false,
nil,
},
{"unnamed source",
defaultParser,
@ -175,6 +177,7 @@ func TestParse_datasource(t *testing.T) {
true, true,
nil,
false,
nil,
},
{"nonexistent source",
defaultParser,
@ -195,6 +198,7 @@ func TestParse_datasource(t *testing.T) {
true, true,
nil,
false,
nil,
},
{"duplicate source",
defaultParser,
@ -215,6 +219,7 @@ func TestParse_datasource(t *testing.T) {
true, true,
nil,
false,
nil,
},
{"cyclic dependency between data sources",
defaultParser,
@ -248,6 +253,7 @@ func TestParse_datasource(t *testing.T) {
true, true,
nil,
false,
nil,
},
}

@ -12,7 +12,6 @@ import (
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/hcl/v2/hclsyntax"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
pkrfunction "github.com/hashicorp/packer/hcl2template/function"
"github.com/hashicorp/packer/packer"
"github.com/zclconf/go-cty/cty"
@ -55,6 +54,9 @@ type PackerConfig struct {
// Builds is the list of Build blocks defined in the config files.
Builds Builds
// HCPPackerRegistry contains the configuration for publishing the artifacts to the HCP Packer Registry.
HCPPackerRegistry *HCPPackerRegistryBlock
// HCPVars is the list of HCP-set variables for use later in a template
HCPVars map[string]cty.Value
@ -156,8 +158,7 @@ func (cfg *PackerConfig) EvalContext(ctx BlockContext, variables map[string]cty.
func (c *PackerConfig) decodeInputVariables(f *hcl.File) hcl.Diagnostics {
var diags hcl.Diagnostics
content, moreDiags := f.Body.Content(configSchema)
diags = append(diags, moreDiags...)
content, _ := f.Body.Content(configSchema)
// for input variables we allow to use env in the default value section.
ectx := &hcl.EvalContext{
@ -188,8 +189,7 @@ func (c *PackerConfig) decodeInputVariables(f *hcl.File) hcl.Diagnostics {
func parseLocalVariableBlocks(f *hcl.File) ([]*LocalBlock, hcl.Diagnostics) {
var diags hcl.Diagnostics
content, moreDiags := f.Body.Content(configSchema)
diags = append(diags, moreDiags...)
content, _ := f.Body.Content(configSchema)
var locals []*LocalBlock
@ -575,6 +575,12 @@ func (cfg *PackerConfig) getCoreBuildProvisioner(source SourceUseBlock, pb *Prov
}
}
if pb.PType == "hcp-sbom" {
provisioner = &packer.SBOMInternalProvisioner{
Provisioner: provisioner,
}
}
return packer.CoreBuildProvisioner{
PType: pb.PType,
PName: pb.PName,
@ -636,11 +642,59 @@ func (cfg *PackerConfig) getCoreBuildPostProcessors(source SourceUseBlock, block
return res, diags
}
// GetHCPPackerRegistryBlock return the HCP registry configuration block
// that can should be used for the current build. Right now, it should
// use the block at the top level but support the block inside the first
// build block with a deprecation diagnostic
func (cfg *PackerConfig) GetHCPPackerRegistryBlock() (*HCPPackerRegistryBlock, hcl.Diagnostics) {
var block *HCPPackerRegistryBlock
var diags hcl.Diagnostics
multipleRegistryDiag := func(block *HCPPackerRegistryBlock) *hcl.Diagnostic {
return &hcl.Diagnostic{
Summary: "Multiple HCP Packer registry block declaration",
Subject: block.HCL2Ref.DefRange.Ptr(),
Severity: hcl.DiagError,
Detail: "Multiple " + buildHCPPackerRegistryLabel + " blocks have been found, only one can be defined " +
"in HCL2 templates. Starting with Packer 1.12.1, it is recommended to move it to the " +
"top-level configuration instead of within a build block.",
}
}
// We start by looking in the build blocks
for _, build := range cfg.Builds {
if build.HCPPackerRegistry != nil {
if block != nil {
// error multiple build block
diags = diags.Append(multipleRegistryDiag(build.HCPPackerRegistry))
continue
}
block = build.HCPPackerRegistry
diags = diags.Append(&hcl.Diagnostic{
Summary: "Build block level " + buildHCPPackerRegistryLabel + " are deprecated",
Subject: &block.DefRange,
Severity: hcl.DiagWarning,
Detail: "Starting with Packer 1.12.1, it is recommended to move it to the " +
"top-level configuration instead of within a build block.",
})
}
}
if block != nil && cfg.HCPPackerRegistry != nil {
diags = diags.Append(multipleRegistryDiag(block))
}
if cfg.HCPPackerRegistry != nil {
block = cfg.HCPPackerRegistry
}
return block, diags
}
// GetBuilds returns a list of packer Build based on the HCL2 parsed build
// blocks. All Builders, Provisioners and Post Processors will be started and
// configured.
func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packersdk.Build, hcl.Diagnostics) {
res := []packersdk.Build{}
func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]*packer.CoreBuild, hcl.Diagnostics) {
res := []*packer.CoreBuild{}
var diags hcl.Diagnostics
possibleBuildNames := []string{}

@ -9,7 +9,6 @@ import (
"time"
"github.com/hashicorp/go-version"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/template/config"
"github.com/hashicorp/packer/hcl2template/addrs"
. "github.com/hashicorp/packer/hcl2template/internal"
@ -205,7 +204,7 @@ func TestParser_complete(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "virtualbox-iso.ubuntu-1204",
BuilderType: "virtualbox-iso",
@ -422,6 +421,7 @@ func TestParser_complete(t *testing.T) {
},
},
false,
nil,
},
}
testParse(t, tests)
@ -569,8 +569,9 @@ func TestParser_no_init(t *testing.T) {
Builds: nil,
},
false, false,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"duplicate required plugin accessor fails",
@ -578,8 +579,9 @@ func TestParser_no_init(t *testing.T) {
parseTestArgs{"testdata/init/duplicate_required_plugins", nil, nil},
nil,
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"invalid_inexplicit_source.pkr.hcl",
defaultParser,
@ -598,8 +600,9 @@ func TestParser_no_init(t *testing.T) {
Basedir: filepath.Clean("testdata/init"),
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"invalid_short_source.pkr.hcl",
defaultParser,
@ -618,8 +621,9 @@ func TestParser_no_init(t *testing.T) {
Basedir: filepath.Clean("testdata/init"),
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"invalid_inexplicit_source_2.pkr.hcl",
defaultParser,
@ -638,8 +642,9 @@ func TestParser_no_init(t *testing.T) {
Basedir: filepath.Clean("testdata/init"),
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
}
testParse_only_Parse(t, tests)

@ -15,8 +15,7 @@ import (
func (cfg *PackerConfig) decodeRequiredPluginsBlock(f *hcl.File) hcl.Diagnostics {
var diags hcl.Diagnostics
content, moreDiags := f.Body.Content(configSchema)
diags = append(diags, moreDiags...)
content, _ := f.Body.Content(configSchema)
for _, block := range content.Blocks {
switch block.Type {

@ -7,7 +7,6 @@ import (
"path/filepath"
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/builder/null"
"github.com/hashicorp/packer/packer"
)
@ -52,7 +51,7 @@ func TestParse_source(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "null.test",
BuilderType: "null",
@ -63,6 +62,7 @@ func TestParse_source(t *testing.T) {
},
},
false,
nil,
},
{"untyped source",
defaultParser,
@ -74,6 +74,7 @@ func TestParse_source(t *testing.T) {
true, true,
nil,
false,
nil,
},
{"unnamed source",
defaultParser,
@ -85,6 +86,7 @@ func TestParse_source(t *testing.T) {
true, true,
nil,
false,
nil,
},
{"unused source with unknown type fails",
defaultParser,
@ -98,8 +100,9 @@ func TestParse_source(t *testing.T) {
},
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"used source with unknown type fails",
defaultParser,
@ -123,6 +126,7 @@ func TestParse_source(t *testing.T) {
true, true,
nil,
false,
nil,
},
{"duplicate source",
defaultParser,
@ -143,6 +147,7 @@ func TestParse_source(t *testing.T) {
true, true,
nil,
false,
nil,
},
}
testParse(t, tests)

@ -10,7 +10,6 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/hcl/v2"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/builder/null"
. "github.com/hashicorp/packer/hcl2template/internal"
"github.com/hashicorp/packer/packer"
@ -126,7 +125,7 @@ func TestParse_variables(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "null.test",
BuilderType: "null",
@ -137,6 +136,7 @@ func TestParse_variables(t *testing.T) {
},
},
false,
nil,
},
{"duplicate variable",
defaultParser,
@ -156,8 +156,9 @@ func TestParse_variables(t *testing.T) {
},
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"duplicate variable in variables",
defaultParser,
@ -177,8 +178,9 @@ func TestParse_variables(t *testing.T) {
},
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"duplicate local block",
defaultParser,
@ -200,8 +202,9 @@ func TestParse_variables(t *testing.T) {
},
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"invalid default type",
defaultParser,
@ -221,8 +224,9 @@ func TestParse_variables(t *testing.T) {
},
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"unknown key",
@ -240,8 +244,9 @@ func TestParse_variables(t *testing.T) {
},
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"unset used variable",
@ -258,8 +263,9 @@ func TestParse_variables(t *testing.T) {
},
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
true,
nil,
},
{"unset unused variable",
@ -291,7 +297,7 @@ func TestParse_variables(t *testing.T) {
},
},
true, true,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "null",
BuilderType: "null",
@ -302,6 +308,7 @@ func TestParse_variables(t *testing.T) {
},
},
false,
nil,
},
{"locals within another locals usage in different files",
@ -378,7 +385,7 @@ func TestParse_variables(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "null.test",
BuilderType: "null",
@ -389,6 +396,7 @@ func TestParse_variables(t *testing.T) {
},
},
false,
nil,
},
{"recursive locals",
defaultParser,
@ -399,8 +407,9 @@ func TestParse_variables(t *testing.T) {
LocalVariables: nil,
},
true, true,
[]packersdk.Build{},
[]*packer.CoreBuild{},
false,
nil,
},
{"set variable from var-file",
@ -442,7 +451,7 @@ func TestParse_variables(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "null.test",
BuilderType: "null",
@ -453,6 +462,7 @@ func TestParse_variables(t *testing.T) {
},
},
false,
nil,
},
{"unknown variable from var-file",
@ -484,7 +494,7 @@ func TestParse_variables(t *testing.T) {
Basedir: filepath.Join("testdata", "variables"),
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "null.test",
BuilderType: "null",
@ -495,6 +505,7 @@ func TestParse_variables(t *testing.T) {
},
},
false,
nil,
},
{"provisioner variable decoding",
@ -542,49 +553,51 @@ func TestParse_variables(t *testing.T) {
},
},
false, false,
[]packersdk.Build{&packer.CoreBuild{
Type: "null.null-builder",
BuilderType: "null",
Prepared: true,
Builder: &null.Builder{},
Provisioners: []packer.CoreBuildProvisioner{
{
PType: "shell",
Provisioner: &packer.RetriedProvisioner{
MaxRetries: 1,
Provisioner: &HCL2Provisioner{
Provisioner: &MockProvisioner{
Config: MockConfig{
NestedMockConfig: NestedMockConfig{
Tags: []MockTag{},
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "null.null-builder",
BuilderType: "null",
Prepared: true,
Builder: &null.Builder{},
Provisioners: []packer.CoreBuildProvisioner{
{
PType: "shell",
Provisioner: &packer.RetriedProvisioner{
MaxRetries: 1,
Provisioner: &HCL2Provisioner{
Provisioner: &MockProvisioner{
Config: MockConfig{
NestedMockConfig: NestedMockConfig{
Tags: []MockTag{},
},
NestedSlice: []NestedMockConfig{},
},
NestedSlice: []NestedMockConfig{},
},
},
},
},
},
{
PType: "shell",
Provisioner: &packer.RetriedProvisioner{
MaxRetries: 1,
Provisioner: &HCL2Provisioner{
Provisioner: &MockProvisioner{
Config: MockConfig{
NestedMockConfig: NestedMockConfig{
Tags: []MockTag{},
{
PType: "shell",
Provisioner: &packer.RetriedProvisioner{
MaxRetries: 1,
Provisioner: &HCL2Provisioner{
Provisioner: &MockProvisioner{
Config: MockConfig{
NestedMockConfig: NestedMockConfig{
Tags: []MockTag{},
},
NestedSlice: []NestedMockConfig{},
},
NestedSlice: []NestedMockConfig{},
},
},
},
},
},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
},
},
false,
nil,
},
{"valid validation block",
@ -630,7 +643,7 @@ func TestParse_variables(t *testing.T) {
},
},
false, false,
[]packersdk.Build{
[]*packer.CoreBuild{
&packer.CoreBuild{
Type: "null.test",
BuilderType: "null",
@ -641,6 +654,7 @@ func TestParse_variables(t *testing.T) {
},
},
false,
nil,
},
{"valid validation block - invalid default",
@ -665,6 +679,7 @@ func TestParse_variables(t *testing.T) {
true, true,
nil,
false,
nil,
},
}
testParse(t, tests)

@ -5,7 +5,8 @@ package api
import (
"fmt"
"strings"
"regexp"
"strconv"
"google.golang.org/grpc/codes"
)
@ -26,6 +27,8 @@ func (c *ClientError) Error() string {
return fmt.Sprintf("status %d: err %v", c.StatusCode, c.Err)
}
var errCodeRegex = regexp.MustCompilePOSIX(`[Cc]ode"?:([0-9]+)`)
// CheckErrorCode checks the error string for err for some code and returns true
// if the code is found. Ideally this function should use status.FromError
// https://pkg.go.dev/google.golang.org/grpc/status#pkg-functions but that
@ -35,5 +38,15 @@ func CheckErrorCode(err error, code codes.Code) bool {
return false
}
return strings.Contains(err.Error(), fmt.Sprintf("Code:%d", code))
// If the error string doesn't match the code we're looking for, we
// can ignore it and return false immediately.
matches := errCodeRegex.FindStringSubmatch(err.Error())
if len(matches) == 0 {
return false
}
// Safe to ignore the error here since the regex's submatch is always a
// valid integer given the format ([0-9]+)
errCode, _ := strconv.Atoi(matches[1])
return errCode == int(code)
}

@ -0,0 +1,57 @@
package api
import (
"fmt"
"testing"
"google.golang.org/grpc/codes"
)
func TestCheckErrorCode(t *testing.T) {
tests := []struct {
name string
codeString string
expectCode codes.Code
expectSuccess bool
}{
{
"old format, code matches what is looked for",
`{Code:5,"details":[],"message":"Error: The bucket etc."}`,
codes.Code(5),
true,
},
{
"old format, code doesn't match what is looked for",
`{Code:55,"details":[],"message":"Error: The bucket etc."}`,
codes.Code(5),
false,
},
{
"new format, code matches what is looked for",
`{"code":5,"details":[],"message":"Error: The bucket etc."}`,
codes.Code(5),
true,
},
{
"new format, code doesn't match what is looked for",
`{"code":55,"details":[],"message":"Error: The bucket etc."}`,
codes.Code(5),
false,
},
{
"bad format, should always be false",
`"ceod":55`,
codes.Code(5),
false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
found := CheckErrorCode(fmt.Errorf(tt.codeString), tt.expectCode)
if found != tt.expectSuccess {
t.Errorf("check error code returned %t, expected %t", found, tt.expectSuccess)
}
})
}
}

@ -6,6 +6,7 @@ import (
hcpPackerAPI "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2023-01-01/client/packer_service"
hcpPackerModels "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2023-01-01/models"
"github.com/hashicorp/packer/packer"
)
func (c *Client) CreateBuild(
@ -93,3 +94,27 @@ func (c *Client) UpdateBuild(
return resp.Payload.Build.ID, nil
}
func (c *Client) UploadSbom(
ctx context.Context,
bucketName, fingerprint string,
buildID string,
sbom packer.SBOM,
) error {
params := hcpPackerAPI.NewPackerServiceUploadSbomParamsWithContext(ctx)
params.BuildID = buildID
params.LocationOrganizationID = c.OrganizationID
params.LocationProjectID = c.ProjectID
params.BucketName = bucketName
params.Fingerprint = fingerprint
params.Body = &hcpPackerModels.HashicorpCloudPacker20230101UploadSbomBody{
CompressedSbom: sbom.CompressedData,
Format: &sbom.Format,
Name: sbom.Name,
}
_, err := c.Packer.PackerServiceUploadSbom(params, nil)
return err
}

@ -22,6 +22,7 @@ type HCLRegistry struct {
bucket *Bucket
ui sdkpacker.Ui
metadata *MetadataStore
buildNames map[string]struct{}
}
const (
@ -65,30 +66,19 @@ func (h *HCLRegistry) PopulateVersion(ctx context.Context) error {
}
// StartBuild is invoked when one build for the configuration is starting to be processed
func (h *HCLRegistry) StartBuild(ctx context.Context, build sdkpacker.Build) error {
name := build.Name()
cb, ok := build.(*packer.CoreBuild)
if ok {
name = cb.Type
}
return h.bucket.startBuild(ctx, name)
func (h *HCLRegistry) StartBuild(ctx context.Context, build *packer.CoreBuild) error {
return h.bucket.startBuild(ctx, h.HCPBuildName(build))
}
// CompleteBuild is invoked when one build for the configuration has finished
func (h *HCLRegistry) CompleteBuild(
ctx context.Context,
build sdkpacker.Build,
build *packer.CoreBuild,
artifacts []sdkpacker.Artifact,
buildErr error,
) ([]sdkpacker.Artifact, error) {
buildName := build.Name()
cb, ok := build.(*packer.CoreBuild)
if ok {
buildName = cb.Type
}
buildMetadata, envMetadata := cb.GetMetadata(), h.metadata
buildName := h.HCPBuildName(build)
buildMetadata, envMetadata := build.GetMetadata(), h.metadata
err := h.bucket.Version.AddMetadataToBuild(ctx, buildName, buildMetadata, envMetadata)
if err != nil {
return nil, err
@ -116,8 +106,22 @@ func NewHCLRegistry(config *hcl2template.PackerConfig, ui sdkpacker.Ui) (*HCLReg
return nil, diags
}
withHCLBucketConfiguration := func(bb *hcl2template.BuildBlock) bucketConfigurationOpts {
return func(bucket *Bucket) hcl.Diagnostics {
registryConfig, rcDiags := config.GetHCPPackerRegistryBlock()
diags = diags.Extend(rcDiags)
if diags.HasErrors() {
return nil, diags
}
withHCLBucketConfiguration := func(bucket *Bucket) hcl.Diagnostics {
bucket.ReadFromHCPPackerRegistryBlock(registryConfig)
return nil
}
// we must use the old strategy when there is only a single build block because
// we used to rely on the parent build block for setting some default data
if len(config.Builds) == 1 && config.HCPPackerRegistry == nil {
withHCLBucketConfiguration = func(bucket *Bucket) hcl.Diagnostics {
bb := config.Builds[0]
bucket.ReadFromHCLBuildBlock(bb)
// If at this point the bucket.Name is still empty,
// last try is to use the build.Name if present
@ -139,11 +143,10 @@ func NewHCLRegistry(config *hcl2template.PackerConfig, ui sdkpacker.Ui) (*HCLReg
diags = append(diags, dsDiags...)
}
build := config.Builds[0]
bucket, bucketDiags := createConfiguredBucket(
config.Basedir,
withPackerEnvConfiguration,
withHCLBucketConfiguration(build),
withHCLBucketConfiguration,
withDeprecatedDatasourceConfiguration(vals, ui),
withDatasourceConfiguration(vals),
)
@ -155,20 +158,96 @@ func NewHCLRegistry(config *hcl2template.PackerConfig, ui sdkpacker.Ui) (*HCLReg
return nil, diags
}
for _, source := range build.Sources {
bucket.RegisterBuildForComponent(source.String())
}
ui.Say(fmt.Sprintf("Tracking build on HCP Packer with fingerprint %q", bucket.Version.Fingerprint))
return &HCLRegistry{
registry := &HCLRegistry{
configuration: config,
bucket: bucket,
ui: ui,
metadata: &MetadataStore{},
}, nil
buildNames: map[string]struct{}{},
}
ui.Say(fmt.Sprintf("Tracking build on HCP Packer with fingerprint %q", bucket.Version.Fingerprint))
return registry, diags.Extend(registry.registerAllComponents())
}
func (h *HCLRegistry) registerAllComponents() hcl.Diagnostics {
var diags hcl.Diagnostics
conflictSources := map[string]struct{}{}
// we currently support only one build block but it will change in the near future
for _, build := range h.configuration.Builds {
for _, source := range build.Sources {
// If we encounter the same source twice, we'll defer
// its addition to later, using both the build name
// and the source type as the name used for HCP Packer.
_, ok := h.buildNames[source.String()]
if !ok {
h.buildNames[source.String()] = struct{}{}
continue
}
conflictSources[source.String()] = struct{}{}
// We need to delete it to avoid having a false-positive
// when returning the name, since we'll be using
// the combination of build name + source.String()
delete(h.buildNames, source.String())
}
}
// Second pass is to take care of conflicting sources
//
// If the same source is used twice in the configuration, we need to
// have a way to differentiate the two on HCP, as each build should have
// a locally unique name.
//
// If that happens, we then use a combination of both the build name, and
// the source type.
for _, build := range h.configuration.Builds {
for _, source := range build.Sources {
if _, ok := conflictSources[source.String()]; !ok {
continue
}
buildName := source.String()
if build.Name != "" {
buildName = fmt.Sprintf("%s.%s", build.Name, buildName)
}
if _, ok := h.buildNames[buildName]; ok {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Build name conflicts",
Subject: &build.HCL2Ref.DefRange,
Detail: fmt.Sprintf("Two sources are used in the same build block, causing "+
"a conflict, there must only be one instance of %s", source.String()),
})
}
h.buildNames[buildName] = struct{}{}
}
}
if diags.HasErrors() {
return diags
}
for buildName := range h.buildNames {
h.bucket.RegisterBuildForComponent(buildName)
}
return diags
}
func (h *HCLRegistry) Metadata() Metadata {
return h.metadata
}
// HCPBuildName will return the properly formatted string taking name conflict into account
func (h *HCLRegistry) HCPBuildName(build *packer.CoreBuild) string {
_, ok := h.buildNames[build.Type]
if ok {
return build.Type
}
return fmt.Sprintf("%s.%s", build.BuildName, build.Type)
}

@ -0,0 +1,319 @@
package registry
import (
"reflect"
"slices"
"strings"
"testing"
"github.com/hashicorp/packer/hcl2template"
)
func TestNewRegisterProperBuildName(t *testing.T) {
cases := map[string]struct {
expectedBuilds []string
expectErr bool
diagsSummaryContains string
builds hcl2template.Builds
}{
"single build block with single source": {
expectErr: false,
expectedBuilds: []string{"docker.ubuntu"},
builds: hcl2template.Builds{
&hcl2template.BuildBlock{
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
},
},
},
},
"single build block with name and with single source": {
expectErr: false,
expectedBuilds: []string{"docker.ubuntu"},
builds: hcl2template.Builds{
&hcl2template.BuildBlock{
Name: "my-build-block",
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
},
},
},
},
"single build block with 2 sources": {
expectErr: false,
expectedBuilds: []string{"docker.alpine", "docker.ubuntu"},
builds: hcl2template.Builds{
&hcl2template.BuildBlock{
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "alpine",
},
},
},
},
},
},
"single build block with 3 sources": {
expectErr: false,
expectedBuilds: []string{"docker.alpine", "docker.ubuntu", "docker.arch"},
builds: hcl2template.Builds{
&hcl2template.BuildBlock{
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "alpine",
},
},
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "arch",
},
},
},
},
},
},
"single build block with name and multiple sources": {
expectErr: false,
expectedBuilds: []string{"docker.alpine", "docker.ubuntu"},
builds: hcl2template.Builds{
&hcl2template.BuildBlock{
Name: "my-build-block",
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "alpine",
},
},
},
},
},
},
"single build block with multiple identical sources create conflict": {
expectErr: true,
diagsSummaryContains: "conflict",
builds: hcl2template.Builds{
&hcl2template.BuildBlock{
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
},
},
},
},
"multiple build block with different source": {
expectErr: false,
expectedBuilds: []string{"docker.alpine", "docker.ubuntu"},
builds: hcl2template.Builds{
&hcl2template.BuildBlock{
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
},
},
&hcl2template.BuildBlock{
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "alpine",
},
},
},
},
},
},
"multiple build block with same source create conflict": {
expectErr: true,
diagsSummaryContains: "conflict",
builds: hcl2template.Builds{
&hcl2template.BuildBlock{
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "alpine",
},
},
},
},
&hcl2template.BuildBlock{
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "alpine",
},
},
},
},
},
},
"multiple build block with same source but with different build name": {
expectErr: false,
expectedBuilds: []string{"build1.docker.ubuntu", "build2.docker.ubuntu"},
builds: hcl2template.Builds{
&hcl2template.BuildBlock{
Name: "build1",
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
},
},
&hcl2template.BuildBlock{
Name: "build2",
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
},
},
},
},
"multiple build block with same source but with only one declared build name": {
expectErr: false,
expectedBuilds: []string{"docker.ubuntu", "build.docker.ubuntu"},
builds: hcl2template.Builds{
&hcl2template.BuildBlock{
Name: "build",
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
},
},
&hcl2template.BuildBlock{
Sources: []hcl2template.SourceUseBlock{
{
SourceRef: hcl2template.SourceRef{
Type: "docker",
Name: "ubuntu",
},
},
},
},
},
},
}
for desc, tc := range cases {
t.Run(desc, func(t *testing.T) {
config := &hcl2template.PackerConfig{
Builds: tc.builds,
}
registry := HCLRegistry{
configuration: config,
bucket: &Bucket{
Name: "test-bucket-" + desc,
Version: &Version{},
},
buildNames: map[string]struct{}{},
}
diags := registry.registerAllComponents()
if tc.diagsSummaryContains != "" {
containsMsg := false
for _, diag := range diags {
if strings.Contains(diag.Summary, tc.diagsSummaryContains) {
containsMsg = true
}
}
if !containsMsg {
t.Fatalf("diagnostics should contains '%s' in summary", tc.diagsSummaryContains)
}
}
if !tc.expectErr {
if diags.HasErrors() {
t.Fatalf("should not report error diagnostic: %v", diags)
}
}
if tc.expectErr {
if !diags.HasErrors() {
t.Fatal("should report error in this case")
}
return
}
actualExpectedBuilds := registry.bucket.Version.expectedBuilds
slices.Sort(tc.expectedBuilds)
slices.Sort(actualExpectedBuilds)
if !reflect.DeepEqual(tc.expectedBuilds, actualExpectedBuilds) {
t.Fatalf("expectedBuilds registered: %v, got: %v", tc.expectedBuilds, actualExpectedBuilds)
}
})
}
}

@ -44,6 +44,9 @@ func IsHCPEnabled(cfg packer.Handler) bool {
mode = HCPConfigEnabled
}
}
if config.HCPPackerRegistry != nil {
mode = HCPConfigEnabled
}
}
// HCP_PACKER_BUCKET_NAME is set or HCP_PACKER_REGISTRY not toggled off

@ -84,20 +84,19 @@ func (h *JSONRegistry) PopulateVersion(ctx context.Context) error {
}
// StartBuild is invoked when one build for the configuration is starting to be processed
func (h *JSONRegistry) StartBuild(ctx context.Context, build sdkpacker.Build) error {
name := build.Name()
return h.bucket.startBuild(ctx, name)
func (h *JSONRegistry) StartBuild(ctx context.Context, build *packer.CoreBuild) error {
return h.bucket.startBuild(ctx, build.Name())
}
// CompleteBuild is invoked when one build for the configuration has finished
func (h *JSONRegistry) CompleteBuild(
ctx context.Context,
build sdkpacker.Build,
build *packer.CoreBuild,
artifacts []sdkpacker.Artifact,
buildErr error,
) ([]sdkpacker.Artifact, error) {
buildName := build.Name()
buildMetadata, envMetadata := build.(*packer.CoreBuild).GetMetadata(), h.metadata
buildMetadata, envMetadata := build.GetMetadata(), h.metadata
err := h.bucket.Version.AddMetadataToBuild(ctx, buildName, buildMetadata, envMetadata)
if err != nil {
return nil, err

@ -7,6 +7,7 @@ import (
"context"
sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/packer"
)
// nullRegistry is a special handler that does nothing
@ -16,13 +17,13 @@ func (r nullRegistry) PopulateVersion(context.Context) error {
return nil
}
func (r nullRegistry) StartBuild(context.Context, sdkpacker.Build) error {
func (r nullRegistry) StartBuild(context.Context, *packer.CoreBuild) error {
return nil
}
func (r nullRegistry) CompleteBuild(
ctx context.Context,
build sdkpacker.Build,
build *packer.CoreBuild,
artifacts []sdkpacker.Artifact,
buildErr error,
) ([]sdkpacker.Artifact, error) {

@ -16,8 +16,8 @@ import (
// Registry is an entity capable to orchestrate a Packer build and upload metadata to HCP
type Registry interface {
PopulateVersion(context.Context) error
StartBuild(context.Context, sdkpacker.Build) error
CompleteBuild(ctx context.Context, build sdkpacker.Build, artifacts []sdkpacker.Artifact, buildErr error) ([]sdkpacker.Artifact, error)
StartBuild(context.Context, *packer.CoreBuild) error
CompleteBuild(ctx context.Context, build *packer.CoreBuild, artifacts []sdkpacker.Artifact, buildErr error) ([]sdkpacker.Artifact, error)
VersionStatusSummary()
Metadata() Metadata
}

@ -12,6 +12,8 @@ import (
"sync"
"time"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/go-multierror"
hcpPackerModels "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2023-01-01/models"
packerSDK "github.com/hashicorp/packer-plugin-sdk/packer"
@ -72,11 +74,19 @@ func (bucket *Bucket) Validate() error {
// ReadFromHCLBuildBlock reads the information for initialising a Bucket from a HCL2 build block
func (bucket *Bucket) ReadFromHCLBuildBlock(build *hcl2template.BuildBlock) {
registryBlock := build.HCPPackerRegistry
if registryBlock == nil {
return
}
bucket.ReadFromHCPPackerRegistryBlock(build.HCPPackerRegistry)
}
// ReadFromHCPPackerRegistryBlock reads the information for initialising a Bucket from a HCL2 Packer registry block
func (bucket *Bucket) ReadFromHCPPackerRegistryBlock(registryBlock *hcl2template.HCPPackerRegistryBlock) {
if bucket == nil {
return
}
registryBlock := build.HCPPackerRegistry
if registryBlock == nil {
return
}
@ -222,6 +232,18 @@ func (bucket *Bucket) UpdateBuildStatus(
return nil
}
func (bucket *Bucket) uploadSbom(ctx context.Context, buildName string, sbom packer.SBOM) error {
buildToUpdate, err := bucket.Version.Build(buildName)
if err != nil {
return err
}
if buildToUpdate.ID == "" {
return fmt.Errorf("the build for the component %q does not have a valid id", buildName)
}
return bucket.client.UploadSbom(ctx, bucket.Name, bucket.Version.Fingerprint, buildToUpdate.ID, sbom)
}
// markBuildComplete should be called to set a build on the HCP Packer registry to DONE.
// Upon a successful call markBuildComplete will publish all artifacts created by the named build,
// and set the build to done. A build with no artifacts can not be set to DONE.
@ -610,7 +632,6 @@ func (bucket *Bucket) completeBuild(
doneCh, ok := bucket.RunningBuilds[buildName]
if !ok {
log.Print("[ERROR] done build does not have an entry in the heartbeat table, state will be inconsistent.")
} else {
log.Printf("[TRACE] signal stopping heartbeats")
// Stop heartbeating
@ -630,6 +651,23 @@ func (bucket *Bucket) completeBuild(
return packerSDKArtifacts, fmt.Errorf("build failed, not uploading artifacts")
}
artifacts, err := bucket.doCompleteBuild(ctx, buildName, packerSDKArtifacts, buildErr)
if err != nil {
err := bucket.UpdateBuildStatus(ctx, buildName, hcpPackerModels.HashicorpCloudPacker20230101BuildStatusBUILDFAILED)
if err != nil {
log.Printf("[ERROR] failed to update build %q status to FAILED: %s", buildName, err)
}
}
return artifacts, err
}
func (bucket *Bucket) doCompleteBuild(
ctx context.Context,
buildName string,
packerSDKArtifacts []packerSDK.Artifact,
buildErr error,
) ([]packerSDK.Artifact, error) {
for _, art := range packerSDKArtifacts {
var sdkImages []packerSDKRegistry.Image
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
@ -673,6 +711,13 @@ func (bucket *Bucket) completeBuild(
}
}
for _, sbom := range build.CompressedSboms {
err = bucket.uploadSbom(ctx, buildName, sbom)
if err != nil {
return packerSDKArtifacts, fmt.Errorf("Failed to upload sboms %s", err)
}
}
parErr := bucket.markBuildComplete(ctx, buildName)
if parErr != nil {
return packerSDKArtifacts, fmt.Errorf(

@ -380,7 +380,7 @@ func TestReadFromHCLBuildBlock(t *testing.T) {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
bucket := &Bucket{}
bucket.ReadFromHCLBuildBlock(tt.buildBlock)
bucket.ReadFromHCPPackerRegistryBlock(tt.buildBlock.HCPPackerRegistry)
diff := cmp.Diff(bucket, tt.expectedBucket, cmp.AllowUnexported(Bucket{}))
if diff != "" {

@ -6,6 +6,8 @@ package registry
import (
"fmt"
"github.com/hashicorp/packer/packer"
hcpPackerModels "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2023-01-01/models"
packerSDKRegistry "github.com/hashicorp/packer-plugin-sdk/packer/registry/image"
)
@ -20,6 +22,8 @@ type Build struct {
Artifacts map[string]packerSDKRegistry.Image
Status hcpPackerModels.HashicorpCloudPacker20230101BuildStatus
Metadata hcpPackerModels.HashicorpCloudPacker20230101BuildMetadata
CompressedSboms []packer.SBOM
}
// NewBuildFromCloudPackerBuild converts a HashicorpCloudPackerBuild to a local build that can be tracked and

@ -205,5 +205,8 @@ func (version *Version) AddMetadataToBuild(
buildToUpdate.Metadata.Vcs = globalMetadata.Vcs
buildToUpdate.Metadata.Cicd = globalMetadata.Cicd
// TODO IMO this shouldn't be metadata
buildToUpdate.CompressedSboms = buildMetadata.SBOMs
return nil
}

@ -9,6 +9,7 @@ import (
"log"
"sync"
hcpPackerModels "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2023-01-01/models"
"github.com/hashicorp/packer-plugin-sdk/common"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/packerbuilderdata"
@ -50,11 +51,20 @@ type CoreBuild struct {
onError string
l sync.Mutex
prepareCalled bool
SBOMs []SBOM
}
type SBOM struct {
Name string
Format hcpPackerModels.HashicorpCloudPacker20230101SbomFormat
CompressedData []byte
}
type BuildMetadata struct {
PackerVersion string
Plugins map[string]PluginDetails
SBOMs []SBOM
}
func (b *CoreBuild) getPluginsMetadata() map[string]PluginDetails {
@ -88,6 +98,7 @@ func (b *CoreBuild) GetMetadata() BuildMetadata {
metadata := BuildMetadata{
PackerVersion: version.FormattedVersion(),
Plugins: b.getPluginsMetadata(),
SBOMs: b.SBOMs,
}
return metadata
}
@ -300,6 +311,18 @@ func (b *CoreBuild) Run(ctx context.Context, originalUi packersdk.Ui) ([]packers
return nil, err
}
for _, p := range b.Provisioners {
sbomInternalProvisioner, ok := p.Provisioner.(*SBOMInternalProvisioner)
if ok {
sbom := SBOM{
Name: sbomInternalProvisioner.SBOMName,
Format: sbomInternalProvisioner.SBOMFormat,
CompressedData: sbomInternalProvisioner.CompressedData,
}
b.SBOMs = append(b.SBOMs, sbom)
}
}
// If there was no result, don't worry about running post-processors
// because there is nothing they can do, just return.
if builderArtifact == nil {

@ -296,6 +296,13 @@ func (c *Core) generateCoreBuildProvisioner(rawP *template.Provisioner, rawName
Provisioner: provisioner,
}
}
if rawP.Type == "hcp-sbom" {
provisioner = &SBOMInternalProvisioner{
Provisioner: provisioner,
}
}
cbp = CoreBuildProvisioner{
PType: rawP.Type,
Provisioner: provisioner,
@ -307,9 +314,9 @@ func (c *Core) generateCoreBuildProvisioner(rawP *template.Provisioner, rawName
// This is used for json templates to launch the build plugins.
// They will be prepared via b.Prepare() later.
func (c *Core) GetBuilds(opts GetBuildsOptions) ([]packersdk.Build, hcl.Diagnostics) {
func (c *Core) GetBuilds(opts GetBuildsOptions) ([]*CoreBuild, hcl.Diagnostics) {
buildNames := c.BuildNames(opts.Only, opts.Except)
builds := []packersdk.Build{}
builds := []*CoreBuild{}
diags := hcl.Diagnostics{}
for _, n := range buildNames {
b, err := c.Build(n)
@ -355,7 +362,7 @@ func (c *Core) GetBuilds(opts GetBuildsOptions) ([]packersdk.Build, hcl.Diagnost
}
// Build returns the Build object for the given name.
func (c *Core) Build(n string) (packersdk.Build, error) {
func (c *Core) Build(n string) (*CoreBuild, error) {
// Setup the builder
configBuilder, ok := c.builds[n]
if !ok {

@ -30,6 +30,9 @@ type PluginConfig struct {
PostProcessors PostProcessorSet
DataSources DatasourceSet
ReleasesOnly bool
// UseProtobuf is set if all the plugin candidates support protobuf, and
// the user has not forced usage of gob for serialisation.
UseProtobuf bool
}
// PACKERSPACE is used to represent the spaces that separate args for a command
@ -118,6 +121,10 @@ func (c *PluginConfig) Discover() error {
return nil
}
const ForceGobEnvvar = "PACKER_FORCE_GOB"
var PackerUseProto = true
// DiscoverMultiPlugin takes the description from a multi-component plugin
// binary and makes the plugins available to use in Packer. Each plugin found in the
// binary will be addressable using `${pluginName}-${builderName}` for example.
@ -131,6 +138,18 @@ func (c *PluginConfig) DiscoverMultiPlugin(pluginName, pluginPath string) error
return fmt.Errorf("failed to get plugin description from executable %q: %s", pluginPath, err)
}
canProto := desc.ProtocolVersion == "v2"
if os.Getenv(ForceGobEnvvar) != "" && os.Getenv(ForceGobEnvvar) != "0" {
canProto = false
}
// Keeps track of whether or not the plugin had components registered
//
// If no components are registered, we don't need to clamp usage of
// protobuf regardless if the plugin supports it or not, as we won't
// use it at all.
registered := false
pluginPrefix := pluginName + "-"
pluginDetails := PluginDetails{
Name: pluginName,
@ -147,8 +166,17 @@ func (c *PluginConfig) DiscoverMultiPlugin(pluginName, pluginPath string) error
if c.Builders.Has(key) {
continue
}
registered = true
c.Builders.Set(key, func() (packersdk.Builder, error) {
return c.Client(pluginPath, "start", "builder", builderName).Builder()
args := []string{"start", "builder"}
if PackerUseProto {
args = append(args, "--protobuf")
}
args = append(args, builderName)
return c.Client(pluginPath, args...).Builder()
})
GlobalPluginsDetailsStore.SetBuilder(key, pluginDetails)
}
@ -166,8 +194,17 @@ func (c *PluginConfig) DiscoverMultiPlugin(pluginName, pluginPath string) error
if c.PostProcessors.Has(key) {
continue
}
registered = true
c.PostProcessors.Set(key, func() (packersdk.PostProcessor, error) {
return c.Client(pluginPath, "start", "post-processor", postProcessorName).PostProcessor()
args := []string{"start", "post-processor"}
if PackerUseProto {
args = append(args, "--protobuf")
}
args = append(args, postProcessorName)
return c.Client(pluginPath, args...).PostProcessor()
})
GlobalPluginsDetailsStore.SetPostProcessor(key, pluginDetails)
}
@ -185,8 +222,17 @@ func (c *PluginConfig) DiscoverMultiPlugin(pluginName, pluginPath string) error
if c.Provisioners.Has(key) {
continue
}
registered = true
c.Provisioners.Set(key, func() (packersdk.Provisioner, error) {
return c.Client(pluginPath, "start", "provisioner", provisionerName).Provisioner()
args := []string{"start", "provisioner"}
if PackerUseProto {
args = append(args, "--protobuf")
}
args = append(args, provisionerName)
return c.Client(pluginPath, args...).Provisioner()
})
GlobalPluginsDetailsStore.SetProvisioner(key, pluginDetails)
@ -204,8 +250,17 @@ func (c *PluginConfig) DiscoverMultiPlugin(pluginName, pluginPath string) error
if c.DataSources.Has(key) {
continue
}
registered = true
c.DataSources.Set(key, func() (packersdk.Datasource, error) {
return c.Client(pluginPath, "start", "datasource", datasourceName).Datasource()
args := []string{"start", "datasource"}
if PackerUseProto {
args = append(args, "--protobuf")
}
args = append(args, datasourceName)
return c.Client(pluginPath, args...).Datasource()
})
GlobalPluginsDetailsStore.SetDataSource(key, pluginDetails)
}
@ -213,6 +268,14 @@ func (c *PluginConfig) DiscoverMultiPlugin(pluginName, pluginPath string) error
log.Printf("found external %v datasource from %s plugin", desc.Datasources, pluginName)
}
// Only print the log once, for the plugin that triggers that
// limitation in functionality. Otherwise this could be a bit
// verbose to print it for each non-compatible plugin.
if registered && !canProto && PackerUseProto {
log.Printf("plugin %q does not support Protobuf, forcing use of Gob", pluginPath)
PackerUseProto = false
}
return nil
}

@ -417,6 +417,7 @@ func (c *PluginClient) Client() (*packerrpc.Client, error) {
conn.Close()
return nil, err
}
client.UseProto = PackerUseProto
return client, nil
}

@ -5,8 +5,16 @@ package packer
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
hcpSbomProvisioner "github.com/hashicorp/packer/provisioner/hcp-sbom"
hcpPackerModels "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2023-01-01/models"
"github.com/klauspost/compress/zstd"
"time"
"github.com/hashicorp/hcl/v2/hcldec"
@ -234,3 +242,75 @@ func (p *DebuggedProvisioner) Provision(ctx context.Context, ui packersdk.Ui, co
return p.Provisioner.Provision(ctx, ui, comm, generatedData)
}
// SBOMInternalProvisioner is a wrapper provisioner for the `hcp-sbom` provisioner
// that sets the path for SBOM file download and, after the successful execution of
// the `hcp-sbom` provisioner, compresses the SBOM and prepares the data for API
// integration.
type SBOMInternalProvisioner struct {
Provisioner packersdk.Provisioner
CompressedData []byte
SBOMFormat hcpPackerModels.HashicorpCloudPacker20230101SbomFormat
SBOMName string
}
func (p *SBOMInternalProvisioner) ConfigSpec() hcldec.ObjectSpec { return p.ConfigSpec() }
func (p *SBOMInternalProvisioner) FlatConfig() interface{} { return p.FlatConfig() }
func (p *SBOMInternalProvisioner) Prepare(raws ...interface{}) error {
return p.Provisioner.Prepare(raws...)
}
func (p *SBOMInternalProvisioner) Provision(
ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator,
generatedData map[string]interface{},
) error {
cwd, err := os.Getwd()
if err != nil {
return fmt.Errorf("failed to get current working directory for Packer SBOM: %s", err)
}
tmpFile, err := os.CreateTemp(cwd, "packer-sbom-*.json")
if err != nil {
return fmt.Errorf("failed to create internal temporary file for Packer SBOM: %s", err)
}
tmpFileName := tmpFile.Name()
if err = tmpFile.Close(); err != nil {
return fmt.Errorf("failed to close temporary file for Packer SBOM %s: %s", tmpFileName, err)
}
defer func(name string) {
fileRemoveErr := os.Remove(name)
if fileRemoveErr != nil {
log.Printf("Error removing SBOM temporary file %s: %s", name, fileRemoveErr)
}
}(tmpFile.Name())
generatedData["dst"] = tmpFile.Name()
err = p.Provisioner.Provision(ctx, ui, comm, generatedData)
if err != nil {
return err
}
packerSbom, err := os.Open(tmpFileName)
if err != nil {
return fmt.Errorf("failed to open Packer SBOM file %q: %s", tmpFileName, err)
}
provisionerOut := &hcpSbomProvisioner.PackerSBOM{}
err = json.NewDecoder(packerSbom).Decode(provisionerOut)
if err != nil {
return fmt.Errorf("malformed packer SBOM output from file %q: %s", tmpFileName, err)
}
encoder, err := zstd.NewWriter(nil, zstd.WithEncoderLevel(zstd.SpeedBestCompression))
if err != nil {
return fmt.Errorf("failed to create zstd encoder: %s", err)
}
p.CompressedData = encoder.EncodeAll(provisionerOut.RawSBOM, nil)
p.SBOMFormat = provisionerOut.Format
p.SBOMName = provisionerOut.Name
return nil
}

@ -24,7 +24,7 @@ type BuildGetter interface {
// GetBuilds return all possible builds for a config. It also starts all
// builders.
// TODO(azr): rename to builder starter ?
GetBuilds(GetBuildsOptions) ([]packersdk.Build, hcl.Diagnostics)
GetBuilds(GetBuildsOptions) ([]*CoreBuild, hcl.Diagnostics)
}
type Evaluator interface {

@ -0,0 +1,59 @@
package check
import (
"fmt"
"os"
"path/filepath"
)
type fileExists struct {
filepath string
isDir bool
}
func (fe fileExists) Check(_, _ string, _ error) error {
st, err := os.Stat(fe.filepath)
if err != nil {
return fmt.Errorf("failed to stat %q: %s", fe.filepath, err)
}
if st.IsDir() && !fe.isDir {
return fmt.Errorf("file %q is a directory, wasn't supposed to be", fe.filepath)
}
if !st.IsDir() && fe.isDir {
return fmt.Errorf("file %q is not a directory, was supposed to be", fe.filepath)
}
return nil
}
func FileExists(filePath string, isDir bool) Checker {
return fileExists{
filepath: filePath,
isDir: isDir,
}
}
type fileGlob struct {
filepath string
}
func (fe fileGlob) Check(_, _ string, _ error) error {
matches, err := filepath.Glob(fe.filepath)
if err != nil {
return fmt.Errorf("error evaluating file glob pattern %q: %v", fe.filepath, err)
}
if len(matches) == 0 {
return fmt.Errorf("no matches found for file glob pattern %q", fe.filepath)
}
return nil
}
func FileGlob(filename string) Checker {
return fileGlob{
filepath: filename,
}
}

@ -2,6 +2,7 @@ package common
import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
@ -62,6 +63,59 @@ func ExpectedInstalledName(versionStr string) string {
runtime.GOOS, runtime.GOARCH, ext)
}
// BuildCustomisation is a function that allows you to change things on a plugin's
// local files, with a way to rollback those changes after the fact.
//
// The function is meant to take a path parameter to the directory for the plugin,
// and returns a function that unravels those changes once the build process is done.
type BuildCustomisation func(string) (error, func())
const SDKModule = "github.com/hashicorp/packer-plugin-sdk"
// UseDependency invokes go get and go mod tidy to update a package required
// by the plugin, and use it to build the plugin with that change.
func UseDependency(remoteModule, ref string) BuildCustomisation {
return func(path string) (error, func()) {
modPath := filepath.Join(path, "go.mod")
stat, err := os.Stat(modPath)
if err != nil {
return fmt.Errorf("cannot stat mod file %q: %s", modPath, err), nil
}
// Save old go.mod file from dir
oldGoMod, err := os.ReadFile(modPath)
if err != nil {
return fmt.Errorf("failed to read current mod file %q: %s", modPath, err), nil
}
modSpec := fmt.Sprintf("%s@%s", remoteModule, ref)
cmd := exec.Command("go", "get", modSpec)
cmd.Dir = path
err = cmd.Run()
if err != nil {
return fmt.Errorf("failed to run go get %s: %s", modSpec, err), nil
}
cmd = exec.Command("go", "mod", "tidy")
cmd.Dir = path
err = cmd.Run()
if err != nil {
return fmt.Errorf("failed to run go mod tidy: %s", err), nil
}
return nil, func() {
err = os.WriteFile(modPath, oldGoMod, stat.Mode())
if err != nil {
fmt.Fprintf(os.Stderr, "failed to reset modfile %q: %s; manual cleanup may be needed", modPath, err)
}
cmd := exec.Command("go", "mod", "tidy")
cmd.Dir = path
_ = cmd.Run()
}
}
}
// GetPluginPath gets the path for a pre-compiled plugin in the current test suite.
//
// The version only is needed, as the path to a compiled version of the tester
@ -77,6 +131,49 @@ func (ts *PackerTestSuite) GetPluginPath(t *testing.T, version string) string {
return path.(string)
}
type CompilationResult struct {
Error error
Version string
}
// Ready processes a series of CompilationResults, as returned by CompilePlugin
//
// If any of the jobs requested failed, the test will fail also.
func Ready(t *testing.T, results []chan CompilationResult) {
for _, res := range results {
jobErr := <-res
empty := CompilationResult{}
if jobErr != empty {
t.Errorf("failed to compile plugin at version %s: %s", jobErr.Version, jobErr.Error)
}
}
if t.Failed() {
t.Fatalf("some plugins failed to be compiled, see logs for more info")
}
}
type compilationJob struct {
versionString string
suite *PackerTestSuite
done bool
resultCh chan CompilationResult
customisations []BuildCustomisation
}
// CompilationJobs keeps a queue of compilation jobs for plugins
//
// This approach allows us to avoid conflicts between compilation jobs.
// Typically building the plugin with different ldflags is safe to perform
// in parallel on the same file set, however customisations tend to be more
// conflictual, as two concurrent compilation jobs may end-up compiling the
// wrong plugin, which may cause some tests to misbehave, or even compilation
// jobs to fail.
//
// The solution to this approach is to have a global queue for every plugin
// compilation to be performed safely.
var CompilationJobs = make(chan compilationJob, 10)
// CompilePlugin builds a tester plugin with the specified version.
//
// The plugin's code is contained in a subdirectory of this file, and lets us
@ -93,7 +190,49 @@ func (ts *PackerTestSuite) GetPluginPath(t *testing.T, version string) string {
// Note: each tester plugin may only be compiled once for a specific version in
// a test suite. The version may include core (mandatory), pre-release and
// metadata. Unlike Packer core, metadata does matter for the version being built.
func (ts *PackerTestSuite) CompilePlugin(t *testing.T, versionString string) {
//
// Note: the compilation will process asynchronously, and should be waited upon
// before tests that use this plugin may proceed. Refer to the `Ready` function
// for doing that.
func (ts *PackerTestSuite) CompilePlugin(versionString string, customisations ...BuildCustomisation) chan CompilationResult {
resultCh := make(chan CompilationResult)
CompilationJobs <- compilationJob{
versionString: versionString,
suite: ts,
customisations: customisations,
done: false,
resultCh: resultCh,
}
return resultCh
}
func init() {
// Run a processor coroutine for the duration of the test.
//
// It's simpler to have this occurring on the side at all times, without
// trying to manage its lifecycle based on the current amount of queued
// tasks, since this is linked to the test lifecycle, and as it's a single
// coroutine, we can leave it run until the process exits.
go func() {
for job := range CompilationJobs {
log.Printf("compiling plugin on version %s", job.versionString)
err := compilePlugin(job.suite, job.versionString, job.customisations...)
if err != nil {
job.resultCh <- CompilationResult{
Error: err,
Version: job.versionString,
}
}
close(job.resultCh)
}
}()
}
// compilePlugin performs the actual compilation procedure for the plugin, and
// registers it to the test suite instance passed as a parameter.
func compilePlugin(ts *PackerTestSuite, versionString string, customisations ...BuildCustomisation) error {
// Fail to build plugin if already built.
//
// Especially with customisations being a thing, relying on cache to get and
@ -101,28 +240,35 @@ func (ts *PackerTestSuite) CompilePlugin(t *testing.T, versionString string) {
// and therefore we cannot rely on it being called twice and producing the
// same result, so we forbid it.
if _, ok := ts.compiledPlugins.Load(versionString); ok {
t.Fatalf("plugin version %q was already built, use GetTestPlugin instead", versionString)
return fmt.Errorf("plugin version %q was already built, use GetTestPlugin instead", versionString)
}
v := version.Must(version.NewSemver(versionString))
t.Logf("Building tester plugin in version %v", v)
testDir, err := currentDir()
if err != nil {
t.Fatalf("failed to compile plugin binary: %s", err)
return fmt.Errorf("failed to compile plugin binary: %s", err)
}
testerPluginDir := filepath.Join(testDir, "plugin_tester")
for _, custom := range customisations {
err, cleanup := custom(testerPluginDir)
if err != nil {
return fmt.Errorf("failed to prepare plugin workdir: %s", err)
}
defer cleanup()
}
outBin := filepath.Join(ts.pluginsDirectory, BinaryName(v))
compileCommand := exec.Command("go", "build", "-C", testerPluginDir, "-o", outBin, "-ldflags", LDFlags(v), ".")
logs, err := compileCommand.CombinedOutput()
if err != nil {
t.Fatalf("failed to compile plugin binary: %s\ncompiler logs: %s", err, logs)
return fmt.Errorf("failed to compile plugin binary: %s\ncompiler logs: %s", err, logs)
}
ts.compiledPlugins.Store(v.String(), outBin)
return nil
}
type PluginDirSpec struct {

@ -1,19 +1,19 @@
module github.com/hashicorp/packer-plugin-tester
go 1.20
go 1.21.0
require (
github.com/hashicorp/hcl/v2 v2.19.1
github.com/hashicorp/packer-plugin-sdk v0.5.3
github.com/hashicorp/packer-plugin-sdk v0.5.4
github.com/zclconf/go-cty v1.13.3
)
require (
cloud.google.com/go v0.110.0 // indirect
cloud.google.com/go/compute v1.19.1 // indirect
cloud.google.com/go v0.110.8 // indirect
cloud.google.com/go/compute v1.23.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v0.13.0 // indirect
cloud.google.com/go/storage v1.28.1 // indirect
cloud.google.com/go/iam v1.1.3 // indirect
cloud.google.com/go/storage v1.35.1 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
@ -25,21 +25,21 @@ require (
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
github.com/dylanmei/iso8601 v0.1.0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gofrs/uuid v4.0.0+incompatible // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/googleapis/gax-go/v2 v2.7.1 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/hashicorp/consul/api v1.25.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-getter/gcs/v2 v2.2.1 // indirect
github.com/hashicorp/go-getter/s3/v2 v2.2.1 // indirect
github.com/hashicorp/go-getter/v2 v2.2.1 // indirect
github.com/hashicorp/go-getter/gcs/v2 v2.2.2 // indirect
github.com/hashicorp/go-getter/s3/v2 v2.2.2 // indirect
github.com/hashicorp/go-getter/v2 v2.2.2 // indirect
github.com/hashicorp/go-hclog v1.6.3 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
@ -48,12 +48,12 @@ require (
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/serf v0.10.1 // indirect
github.com/hashicorp/vault/api v1.10.0 // indirect
github.com/hashicorp/vault/api v1.14.0 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
@ -77,19 +77,22 @@ require (
github.com/ugorji/go/codec v1.2.6 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/term v0.27.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.114.0 // indirect
google.golang.org/api v0.150.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/grpc v1.56.3 // indirect
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect
google.golang.org/grpc v1.59.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
)

@ -1,15 +1,14 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME=
cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk=
cloud.google.com/go/compute v1.23.1 h1:V97tBoDaZHb6leicZ1G6DLK2BAaZLJ/7+9BB/En3hR0=
cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k=
cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0=
cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM=
cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI=
cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y=
cloud.google.com/go/iam v1.1.3 h1:18tKG7DzydKWUnLjonWcJO6wjSCAtzh4GcRKlH/Hrzc=
cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE=
cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w=
cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
@ -25,8 +24,11 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/antchfx/xmlquery v1.3.5 h1:I7TuBRqsnfFuL11ruavGm911Awx9IqSdiU6W/ztSmVw=
github.com/antchfx/xmlquery v1.3.5/go.mod h1:64w0Xesg2sTaawIdNqMB+7qaW/bSqkQm+ssPaCMWNnc=
github.com/antchfx/xpath v1.1.11 h1:WOFtK8TVAjLm3lbgqeP0arlHpvCEeTANeWZ/csPpJkQ=
github.com/antchfx/xpath v1.1.11/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3 h1:ZSTrOEhiM5J5RFxEaFvMZVEAM1KvT1YzbEOwB2EAGjA=
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
@ -56,9 +58,11 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dylanmei/iso8601 v0.1.0 h1:812NGQDBcqquTfH5Yeo7lwR0nzx/cKdsmf3qMjPURUI=
github.com/dylanmei/iso8601 v0.1.0/go.mod h1:w9KhXSgIyROl1DefbMYIE7UVSIvELTbMrCfx+QkYnoQ=
github.com/dylanmei/winrmtest v0.0.0-20210303004826-fbc9ae56efb6 h1:zWydSUQBJApHwpQ4guHi+mGyQN/8yN6xbKWdDtL3ZNM=
github.com/dylanmei/winrmtest v0.0.0-20210303004826-fbc9ae56efb6/go.mod h1:6BLLhzn1VEiJ4veuAGhINBTrBlV889Wd+aU4auxKOww=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@ -68,14 +72,15 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
@ -102,6 +107,7 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@ -109,32 +115,36 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A=
github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE=
github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g=
github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs=
github.com/hashicorp/consul/sdk v0.14.1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-getter/gcs/v2 v2.2.1 h1:yZgDXYy5m4xogJV8hXzX5S/fM/rjJnBz+EzTeFrfLEM=
github.com/hashicorp/go-getter/gcs/v2 v2.2.1/go.mod h1:xzT3sNmGRipCRMpWz24fYHMvgb4MRn/smg5k2mhJ7Bo=
github.com/hashicorp/go-getter/s3/v2 v2.2.1 h1:Psuhz6iuCxJOd3kGinK46x+4BzcJgwff8BId7CuGPYU=
github.com/hashicorp/go-getter/s3/v2 v2.2.1/go.mod h1:KDqfEPgpwZIy+1sAplFX231CE+M6wdL5Q/j6OMbKSnw=
github.com/hashicorp/go-getter/v2 v2.2.1 h1:2JXqPZs1Jej67RtdTi0YZaEB2hEFB3fkBA4cPYKQwFQ=
github.com/hashicorp/go-getter/v2 v2.2.1/go.mod h1:EcJx6oZE8hmGuRR1l38QrfnyiujQbwsEAn11eHv6l2M=
github.com/hashicorp/go-getter/gcs/v2 v2.2.2 h1:KDbsz44Clh+qpsskK9EnlhWki8NMH18jlAjEseJXIco=
github.com/hashicorp/go-getter/gcs/v2 v2.2.2/go.mod h1:reRiCTBtE1ANT92nMmjwbDzoB6KMJ5azAoMOvQRGGH0=
github.com/hashicorp/go-getter/s3/v2 v2.2.2 h1:ProI1SMBNRt17gC3I8XCMdh35sXN68IUieYnWXwfwew=
github.com/hashicorp/go-getter/s3/v2 v2.2.2/go.mod h1:5MRjeGjI4DqzkRYa+g6OuNJDR0MamdE5VqDPdI42+vQ=
github.com/hashicorp/go-getter/v2 v2.2.2 h1:Al5bzCNW5DrlZMK6TumGrSue7Xz8beyLcen+4N4erwo=
github.com/hashicorp/go-getter/v2 v2.2.2/go.mod h1:hp5Yy0GMQvwWVUmwLs3ygivz1JSLI323hdIE9J9m7TY=
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-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
@ -142,6 +152,7 @@ github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJ
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI=
github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
@ -159,12 +170,14 @@ github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7ml
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw=
github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
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.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@ -178,12 +191,12 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM=
github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=
github.com/hashicorp/packer-plugin-sdk v0.5.3 h1:rWQuRgUUnkf1O3UYymQZz/nJErLh4NFkuarOVEQK+Rs=
github.com/hashicorp/packer-plugin-sdk v0.5.3/go.mod h1:ntdZSJnc1LGGdMEXsYOxopZL1311QOTIbzVZH2EbN0U=
github.com/hashicorp/packer-plugin-sdk v0.5.4 h1:5Bl5DMEa//G4gBNcl842JopM9L4KSSsxpvB4W1lEwIA=
github.com/hashicorp/packer-plugin-sdk v0.5.4/go.mod h1:ALm0ZIK3c/F4iOqPNi7xVuHTgrR5dxzOK+DhFN5DHj4=
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
github.com/hashicorp/vault/api v1.10.0 h1:/US7sIjWN6Imp4o/Rj1Ce2Nr5bki/AXi9vAW3p2tOJQ=
github.com/hashicorp/vault/api v1.10.0/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8=
github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4=
@ -203,9 +216,11 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 h1:2ZKn+w/BJeL43sCxI2jhPLRv73oVVOjEKZjKkflyqxg=
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
@ -271,6 +286,7 @@ github.com/pkg/sftp v1.13.2 h1:taJnKntsWgU+qae21Rx52lIwndAdKrj0mfUNQsz1z4Q=
github.com/pkg/sftp v1.13.2/go.mod h1:LzqnAvaD5TWeNBsZpfKxSYn1MbjWwOsCIAFFJbpIsK8=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@ -306,7 +322,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
@ -315,6 +332,7 @@ github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -324,9 +342,8 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
@ -334,7 +351,6 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -350,13 +366,11 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -364,8 +378,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -394,32 +408,24 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -428,13 +434,12 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE=
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
google.golang.org/api v0.150.0 h1:Z9k22qD289SZ8gCJrk4DrWXkNjtfvKAUo/l1ma8eBYE=
google.golang.org/api v0.150.0/go.mod h1:ccy+MJ6nrYFgE3WgRx/AMXOxOmU8Q4hSa+jjibzhxcg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
@ -442,15 +447,19 @@ google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA=
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI=
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k=
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

@ -30,22 +30,14 @@ type PackerTestSuite struct {
compiledPlugins sync.Map
}
func (ts *PackerTestSuite) buildPluginVersion(waitgroup *sync.WaitGroup, versionString string, t *testing.T) {
waitgroup.Add(1)
go func() {
defer waitgroup.Done()
ts.CompilePlugin(t, versionString)
}()
}
// CompileTestPluginVersions batch compiles a series of plugins
func (ts *PackerTestSuite) CompileTestPluginVersions(t *testing.T, versions ...string) {
wg := &sync.WaitGroup{}
results := []chan CompilationResult{}
for _, ver := range versions {
ts.buildPluginVersion(wg, ver, t)
results = append(results, ts.CompilePlugin(ver))
}
wg.Wait()
Ready(t, results)
}
// SkipNoAcc is a pre-condition that skips the test if the PACKER_ACC environment

@ -0,0 +1,179 @@
package plugin_tests
import "github.com/hashicorp/packer/packer_test/common/check"
const pbPluginName = "github.com/hashicorp/pbtester"
func CheckPBUsed(expect bool) check.Checker {
const strToLookFor = "protobuf for communication with plugins"
var opts []check.GrepOpts
if !expect {
opts = append(opts, check.GrepInvert)
}
return check.Grep(strToLookFor, opts...)
}
// Two different plugins installed locally, one with gob, one with protobuf.
// Both should have different sources so Packer will discover and fallback to using only gob.
func (ts *PackerGobTestSuite) TestTwoPluginsDifferentPB() {
pluginDir := ts.MakePluginDir().InstallPluginVersions("1.0.0+gob")
defer pluginDir.Cleanup()
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("plugins", "install", "--path", ts.GetPluginPath(ts.T(), "1.0.0+pb"), pbPluginName).
Assert(check.MustSucceed())
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/test_both_plugins.pkr.hcl").
Assert(CheckPBUsed(false))
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/test_one_plugin.pkr.hcl").
Assert(CheckPBUsed(false))
}
// Two plugins, both with protobuf supported
// Both installed plugins will support protobuf, so Packer will use Protobuf for all its communications.
func (ts *PackerGobTestSuite) TestTwoPluginsBothPB() {
pluginDir := ts.MakePluginDir().InstallPluginVersions("1.0.0+pb")
defer pluginDir.Cleanup()
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("plugins", "install", "--path", ts.GetPluginPath(ts.T(), "1.0.0+pb"), pbPluginName).
Assert(check.MustSucceed())
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/test_both_plugins.pkr.hcl").
Assert(CheckPBUsed(true))
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/test_one_plugin.pkr.hcl").
Assert(CheckPBUsed(true))
}
// Two plugins, both with protobuf supported, force gob
// Both installed plugins support protobuf, but the environment variable PACKER_FORCE_GOB is
// set to 1 (or on), so Packer must use gob despite protobuf being supported all around.
func (ts *PackerGobTestSuite) TestTwoPluginsBothPBForceGob() {
pluginDir := ts.MakePluginDir().InstallPluginVersions("1.0.0+pb")
defer pluginDir.Cleanup()
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("plugins", "install", "--path", ts.GetPluginPath(ts.T(), "1.0.0+pb"), pbPluginName).
Assert(check.MustSucceed())
ts.PackerCommand().UsePluginDir(pluginDir).
AddEnv("PACKER_FORCE_GOB", "1").
SetArgs("build", "./templates/test_both_plugins.pkr.hcl").
Assert(check.MustSucceed(), CheckPBUsed(false))
ts.PackerCommand().UsePluginDir(pluginDir).
AddEnv("PACKER_FORCE_GOB", "1").
SetArgs("build", "./templates/test_one_plugin.pkr.hcl").
Assert(check.MustSucceed(), CheckPBUsed(false))
}
// Two plugins installed, one with two versions: one version supporting pb,
// one older with gob only. The other with only protobuf.
// The template used pins the older version of the first plugin.
// In this case, gob should be the one used, as the selected version supports
// gob only, despite a newer version supporting protobuf, and the other plugin
// also being compatible.
func (ts *PackerGobTestSuite) TestTwoPluginsLatestPBOlderGob_OlderPinned() {
pluginDir := ts.MakePluginDir().InstallPluginVersions("1.0.0+gob", "1.1.0+pb")
defer pluginDir.Cleanup()
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("plugins", "install", "--path", ts.GetPluginPath(ts.T(), "1.1.0+pb"), pbPluginName).
Assert(check.MustSucceed(), check.MustSucceed())
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/test_one_pinned_plugin.pkr.hcl").
Assert(check.MustSucceed(), CheckPBUsed(false))
}
// One plugin installed, one version supporting pb, one older with gob only
// The template used pins the older version.
// In this case, gob should be the one used, as the selected version supports
// gob only, despite a newer version supporting protobuf.
func (ts *PackerGobTestSuite) TestOnePluginLatestPBOlderGob_OlderPinned() {
pluginDir := ts.MakePluginDir().InstallPluginVersions("1.0.0+gob", "1.1.0+pb")
defer pluginDir.Cleanup()
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/test_one_pinned_plugin.pkr.hcl").
Assert(check.MustSucceed(), CheckPBUsed(false))
}
// One plugin, with latest version supporting gob, but the older supporting protobuf
// In this case, Packer will default to using the latest version, and should
// default to using gob.
func (ts *PackerGobTestSuite) TestOnePluginWithLatestOnlyGob() {
pluginDir := ts.MakePluginDir().InstallPluginVersions("1.0.0+pb", "1.1.0+gob")
defer pluginDir.Cleanup()
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/test_one_plugin.pkr.hcl").
Assert(check.MustSucceed(), CheckPBUsed(false))
}
// One plugin, gob only supported
// Packer will load the only plugin available there, and will use it, and use gob for comms
func (ts PackerGobTestSuite) TestOnePluginWithOnlyGob() {
pluginDir := ts.MakePluginDir().InstallPluginVersions("1.0.0+gob")
defer pluginDir.Cleanup()
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/test_one_plugin.pkr.hcl").
Assert(check.MustSucceed(), CheckPBUsed(false))
}
// One plugin, protobuf supported
// Packer will load the only plugin available there, and use protobuf for comms
func (ts PackerGobTestSuite) TestOnePluginWithPB() {
pluginDir := ts.MakePluginDir().InstallPluginVersions("1.0.0+pb")
defer pluginDir.Cleanup()
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/test_one_plugin.pkr.hcl").
Assert(check.MustSucceed(), CheckPBUsed(true))
}
// No plugin installed, only internal components
// In this test, Packer must use Protobuf for internal components as nothing installed will prevent it.
func (ts PackerGobTestSuite) TestInternalOnly() {
pluginDir := ts.MakePluginDir().InstallPluginVersions()
defer pluginDir.Cleanup()
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/internal_only.pkr.hcl").
Assert(check.MustSucceed(), CheckPBUsed(true))
}
// One plugin with gob only installed, use only internal components
//
// Packer in this case will fallback to Gob, even if the template uses internal
// components only, as this is determined at loading time.
func (ts PackerGobTestSuite) TestInternalOnlyWithGobPluginInstalled() {
pluginDir := ts.MakePluginDir().InstallPluginVersions("1.0.0+gob")
defer pluginDir.Cleanup()
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/internal_only.pkr.hcl").
Assert(check.MustSucceed(), CheckPBUsed(false))
}
// One plugin with pb support installed, use only internal components
//
// Packer in this case will fallback to Gob, even if the template uses internal
// components only, as this is determined at loading time.
func (ts PackerGobTestSuite) TestInternalOnlyWithPBPluginInstalled() {
pluginDir := ts.MakePluginDir().InstallPluginVersions("1.0.0+pb")
defer pluginDir.Cleanup()
ts.PackerCommand().UsePluginDir(pluginDir).
SetArgs("build", "./templates/internal_only.pkr.hcl").
Assert(check.MustSucceed(), CheckPBUsed(true))
}

@ -0,0 +1,38 @@
package plugin_tests
import (
"testing"
"github.com/hashicorp/packer/packer_test/common"
"github.com/stretchr/testify/suite"
)
type PackerGobTestSuite struct {
*common.PackerTestSuite
}
func Test_PackerGobPBSuite(t *testing.T) {
baseSuite, cleanup := common.InitBaseSuite(t)
defer cleanup()
ts := &PackerGobTestSuite{
baseSuite,
}
var compilationJobs []chan common.CompilationResult
// Build two versions of each plugin, one with gob only, one with protobuf only
//
// We'll install them manually in tests, as they'll need to be installed as
// different plugin sources in order for discovery to trigger the
// gob-only/pb-supported behaviours we want to test.
compilationJobs = append(compilationJobs, ts.CompilePlugin("1.1.0+pb", common.UseDependency(common.SDKModule, "v0.6.0")))
compilationJobs = append(compilationJobs, ts.CompilePlugin("1.0.0+pb", common.UseDependency(common.SDKModule, "v0.6.0")))
compilationJobs = append(compilationJobs, ts.CompilePlugin("1.0.0+gob"))
compilationJobs = append(compilationJobs, ts.CompilePlugin("1.1.0+gob"))
common.Ready(t, compilationJobs)
suite.Run(t, ts)
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save