Merge pull request #13467 from hashicorp/karthik/release_1.14.2

release 1.14.2.
This commit is contained in:
kp2099 2025-09-09 16:13:43 +05:30 committed by GitHub
commit e703473a9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 388 additions and 57 deletions

View file

@ -6,6 +6,8 @@
name: "Acceptance Test"
on:
# workflow_dispatch allows manual triggering of the workflow
workflow_dispatch:
schedule:
# Runs against the default branch every day at midnight
- cron: "0 0 * * *"
@ -54,11 +56,14 @@ jobs:
role-duration-seconds: 3600
- name: Install gotestsum
run: go install gotest.tools/gotestsum@latest
# we set the ACC_TEST_BUILDERS="amazon-ebs" since we want to test against the amazon-ebs tests (e.g. Powershell
# provisioner acceptance tests)
- name: Run acceptance tests per module
run: |
mkdir -p /tmp/test-results
make dev
PACKER_ACC=1 gotestsum --format=short-verbose --junitfile /tmp/test-results/gotestsum-report.xml -- -timeout=120m -p 2 $(go list ./... | grep -v inspec | grep -v profitbricks | grep -v oneandone)
ACC_TEST_BUILDERS="amazon-ebs" PACKER_ACC=1 gotestsum --format=short-verbose --junitfile /tmp/test-results/gotestsum-report.xml -- -timeout=120m -p 2 $(go list ./... | grep -v inspec | grep -v profitbricks | grep -v oneandone)
# Send a slack notification if either job defined above fails
slack-notify:
permissions:

View file

@ -1,3 +1,44 @@
# 📦 Changelog
## 1.14.2 (September 9, 2025)
## ✨ Features
- **HCP Certificate Authentication Support** by @JenGoldstrich ([#13435](https://github.com/hashicorp/packer/pull/13435))
Adds support for the `HCP_CRED_FILE` environment variable and removes restrictions on `HCP_CLIENT_ID` and `HCP_CLIENT_SECRET` when connecting builds to an HCP Packer registry.
- **Upgrade Node.js to v22** by @LeahMarieBush ([#13450](https://github.com/hashicorp/packer/pull/13450))
Updates the Node.js version used for Packer website builds.
---
## 🐛 Bug Fixes
- **fix(winrm): catch cmd err from winrm** by @anurag5sh in ([#298](https://github.com/hashicorp/packer-plugin-sdk/pull/298))
Improved reliability by catching WinRM remote shell failures during provisioning
- **PowerShell wrapper cleanup** by @kp2099 ([#13451](https://github.com/hashicorp/packer/pull/13451))
Removed the unused `$result` variable from the wrapper string.
- **fix tests for shell and shell-local** by @kp2099 in ([#300](https://github.com/hashicorp/packer-plugin-sdk/pull/300))
Acceptance test fixes for shell and shell-local
---
## 🛠 Improvements
- Added workflow-dispatch and set `PACKER_ACC_BUILDERS` for acceptance tests by @kp2099 ([#13444](https://github.com/hashicorp/packer/pull/13444))
- Improved spacing in `hcl2template` error messages by @sbraz ([#13453](https://github.com/hashicorp/packer/pull/13453))
- Added callouts for HashiCorp-maintained plugins moving to [releases.hashicorp.com](https://releases.hashicorp.com) by @BrianMMcClain ([#13438](https://github.com/hashicorp/packer/pull/13438))
---
## 📦 Dependencies
- Bump `github.com/ulikunitz/xz` from **0.5.10 → 0.5.14** by @dependabot ([#13459](https://github.com/hashicorp/packer/pull/13459))
- Bump `golang.org/x/oauth2` from **0.13.0 → 0.27.0** by @dependabot ([#13460](https://github.com/hashicorp/packer/pull/13460))
- Bump `github.com/ulikunitz/xz` from **0.5.10 → 0.5.15** by @kp2099 ([#13461](https://github.com/hashicorp/packer/pull/13461))
- Bump `github.com/hashicorp/packer-plugin-sdk` from **0.6.2 → 0.6.3** by @kp2099 ([#13462](https://github.com/hashicorp/packer/pull/13462))
---
## 👩‍💻 New Contributors
- @LeahMarieBush made their first contribution in [#13450](https://github.com/hashicorp/packer/pull/13450) 🎉
## 1.14.1 (August 5, 2025)
### BUG FIXES:

4
go.mod
View file

@ -23,7 +23,7 @@ require (
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hcl/v2 v2.19.1
github.com/hashicorp/hcp-sdk-go v0.136.0
github.com/hashicorp/packer-plugin-sdk v0.6.2
github.com/hashicorp/packer-plugin-sdk v0.6.3
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869
github.com/klauspost/compress v1.13.6
github.com/klauspost/pgzip v1.2.5
@ -40,7 +40,7 @@ require (
github.com/pkg/sftp v1.13.2 // indirect
github.com/posener/complete v1.2.3
github.com/stretchr/testify v1.10.0
github.com/ulikunitz/xz v0.5.10
github.com/ulikunitz/xz v0.5.15
github.com/zclconf/go-cty v1.13.3
github.com/zclconf/go-cty-yaml v1.0.1
golang.org/x/crypto v0.37.0 // indirect

4
go.sum
View file

@ -304,6 +304,8 @@ github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR
github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=
github.com/hashicorp/packer-plugin-sdk v0.6.2 h1:XRIJTcHa9AN13ZvVjL+RpwxEz+yYT7qJ5PA2REViJZ0=
github.com/hashicorp/packer-plugin-sdk v0.6.2/go.mod h1:mOuey53XeLIIpdOQnREjEBYCndipO7piU+EJAstQq1k=
github.com/hashicorp/packer-plugin-sdk v0.6.3 h1:WEZQxQVvcoM0KoeuhJQ/hIPd0g117jwnf//vXZoNAbk=
github.com/hashicorp/packer-plugin-sdk v0.6.3/go.mod h1:mOuey53XeLIIpdOQnREjEBYCndipO7piU+EJAstQq1k=
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=
@ -532,6 +534,8 @@ 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/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
github.com/ulikunitz/xz v0.5.15/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=

View file

@ -135,9 +135,9 @@ func (p *Parser) decodeBuildConfig(block *hcl.Block, cfg *PackerConfig) (*BuildB
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid " + sourceLabel + " reference",
Detail: "A " + sourceLabel + " type is made of three parts that are" +
Detail: "A " + sourceLabel + " type is made of three parts that are " +
"split by a dot `.`; each part must start with a letter and " +
"may contain only letters, digits, underscores, and dashes." +
"may contain only letters, digits, underscores, and dashes. " +
"A valid source reference looks like: `source.type.name`",
Subject: block.DefRange.Ptr(),
})

View file

@ -34,13 +34,19 @@ type Client struct {
}
// NewClient returns an authenticated client to a HCP Packer Registry.
// Client authentication requires the following environment variables be set HCP_CLIENT_ID and HCP_CLIENT_SECRET.
// Upon error a HCPClientError will be returned.
func NewClient() (*Client, error) {
if !env.HasHCPCredentials() {
hasAuth, err := env.HasHCPAuth()
if err != nil {
return nil, &ClientError{
StatusCode: InvalidClientConfig,
Err: fmt.Errorf("the client authentication requires both %s and %s environment variables to be set", env.HCPClientID, env.HCPClientSecret),
Err: fmt.Errorf("Failed to check for HCP auth, error: %s", err.Error()),
}
}
if !hasAuth {
return nil, &ClientError{
StatusCode: InvalidClientConfig,
Err: fmt.Errorf("HCP Authentication not configured, either set an HCP Client ID and secret using the environment variables %s and %s, place an HCP credential file in the default path (%s), or at a different path specified in the %s environment variable.", env.HCPClientID, env.HCPClientSecret, env.HCPDefaultCredFilePathFull, env.HCPCredFile),
}
}

View file

@ -24,7 +24,6 @@ type DeprecatedClient struct {
}
// NewDeprecatedClient returns an authenticated client to a HCP Packer Registry.
// Client authentication requires the following environment variables be set HCP_CLIENT_ID and HCP_CLIENT_SECRET.
// Upon error a HCPClientError will be returned.
func NewDeprecatedClient() (*DeprecatedClient, error) {
// Use NewClient to validate HCP configuration provided by user.

View file

@ -5,10 +5,28 @@
package env
import (
"errors"
"fmt"
"log"
"os"
"path/filepath"
"strings"
)
func HasHCPAuth() (bool, error) {
// Client crendential authentication requires the following environment variables be set; `HCP_CLIENT_ID` and `HCP_CLIENT_SECRET`.
hasClientCredentials := HasHCPClientCredentials()
// Client certificate authentication requires a valid HCP certificate file placed in either the default location (~/.config/hcp/cred_file.json) or at a location specified in the `HCP_CRED_FILE` env var
hasCertificate, err := HasHCPCertificateFile()
if err != nil {
return false, err
}
if hasClientCredentials && hasCertificate {
fmt.Printf("HCP Client Credentials (HCP_CLIENT_ID/HCP_CLIENT_SECRET environment variables) and certificate (HCP_CRED_FILE environment variable, or certificate located at default path (%s) are both supplied, only one is required. The HCP SDK will determine which authentication mechanism to configure here, it is reccomended to only configure one authentication method", HCPDefaultCredFilePathFull)
}
return (hasClientCredentials || hasCertificate), nil
}
func HasProjectID() bool {
return hasEnvVar(HCPProjectID)
}
@ -37,7 +55,7 @@ func hasEnvVar(varName string) bool {
return val != ""
}
func HasHCPCredentials() bool {
func HasHCPClientCredentials() bool {
checks := []func() bool{
HasClientID,
HasClientSecret,
@ -52,6 +70,39 @@ func HasHCPCredentials() bool {
return true
}
func HasHCPCertificateFile() (bool, error) {
envVarCredFile, _ := os.LookupEnv(HCPCredFile)
var envVarCertExists bool
var err error
if envVarCredFile != "" {
envVarCertExists, err = fileExists(envVarCredFile)
if err != nil {
return false, err
}
}
// Get the user's home directory.
userHome, err := os.UserHomeDir()
if err != nil {
return false, fmt.Errorf("failed to retrieve user's home directory path: %v", err)
}
// builds file path ~/.config/hcp/cred_file.json, if we don't parse the home directory os.Stat can't find the default credential path
defaultCredFilePath := filepath.Join(userHome, HCPDefaultCredFilePath, HCPDefaultCredFile)
log.Printf("Checking for default HCP credential file at path %s", defaultCredFilePath)
defaultPathCertExists, err := fileExists(defaultCredFilePath)
if err != nil {
return false, err
}
log.Printf("Default file found status - %t", defaultPathCertExists)
if envVarCertExists && defaultPathCertExists {
fmt.Println("A HCP credential file was found at the default path, and an HCP_CRED_FILE was specified, the HCP SDK will use the HCP_CRED_FILE")
}
if envVarCertExists || defaultPathCertExists {
return true, nil
}
return false, nil
}
func IsHCPDisabled() bool {
hcp, ok := os.LookupEnv(HCPPackerRegistry)
return ok && strings.ToLower(hcp) == "off" || hcp == "0"
@ -62,3 +113,14 @@ func IsHCPExplicitelyEnabled() bool {
_, ok := os.LookupEnv(HCPPackerRegistry)
return ok && !IsHCPDisabled()
}
func fileExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil // Path exists, no error
}
if errors.Is(err, os.ErrNotExist) {
return false, nil // Path does not exist
}
return false, err // Another error occurred
}

View file

@ -4,6 +4,8 @@
package env
import (
"os"
"path/filepath"
"testing"
)
@ -50,3 +52,167 @@ func Test_IsHCPDisabled(t *testing.T) {
})
}
}
func Test_HasHCPAuth(t *testing.T) {
origClientID := os.Getenv(HCPClientID)
origClientSecret := os.Getenv(HCPClientSecret)
origCredFile := os.Getenv(HCPCredFile)
origDefaultCredFilePath := ""
// Save and restore default cred file at ~/.config/hcp/cred_file.json
homeDir, err := os.UserHomeDir()
if err != nil {
t.Fatalf("failed to get home dir: %v", err)
}
credDir := filepath.Join(homeDir, HCPDefaultCredFilePath)
defaultCredPath := filepath.Join(credDir, HCPDefaultCredFile)
if _, err := os.Stat(defaultCredPath); err == nil {
tmpFile, err := os.CreateTemp("", "orig_cred_file.json")
if err != nil {
t.Fatalf("failed to create temp file for original cred file: %v", err)
}
tmpFile.Close()
origDefaultCredFilePath = tmpFile.Name()
if err := os.Rename(defaultCredPath, origDefaultCredFilePath); err != nil {
t.Fatalf("failed to move original cred file: %v", err)
}
}
type setupFunc func(t *testing.T)
tmpCredFile := func(t *testing.T) string {
f, err := os.CreateTemp("", "cred_file.json")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
f.Close()
t.Cleanup(func() { os.Remove(f.Name()) })
return f.Name()
}
tmpDefaultCredFile := func(t *testing.T) string {
homeDir, err := os.UserHomeDir()
if err != nil {
t.Fatalf("failed to get home dir: %v", err)
}
credDir := filepath.Join(homeDir, HCPDefaultCredFilePath)
os.MkdirAll(credDir, 0755)
credPath := filepath.Join(credDir, HCPDefaultCredFile)
f, err := os.Create(credPath)
if err != nil {
t.Fatalf("failed to create default cred file: %v", err)
}
f.Close()
t.Cleanup(func() { os.Remove(credPath) })
return credPath
}
tcs := []struct {
name string
setup setupFunc
want bool
wantErr bool
}{
{
name: "neither credentials nor certificate present",
setup: func(t *testing.T) {
os.Unsetenv(HCPClientID)
os.Unsetenv(HCPClientSecret)
os.Unsetenv(HCPCredFile)
},
want: false,
wantErr: false,
},
{
name: "only credentials present",
setup: func(t *testing.T) {
os.Unsetenv(HCPCredFile)
os.Setenv(HCPClientID, "foo")
os.Setenv(HCPClientSecret, "bar")
},
want: true,
wantErr: false,
},
{
name: "only certificate present via env var",
setup: func(t *testing.T) {
os.Unsetenv(HCPClientID)
os.Unsetenv(HCPClientSecret)
os.Setenv(HCPCredFile, tmpCredFile(t))
},
want: true,
wantErr: false,
},
{
name: "only certificate present via default path",
setup: func(t *testing.T) {
os.Unsetenv(HCPClientID)
os.Unsetenv(HCPClientSecret)
os.Unsetenv(HCPCredFile)
tmpDefaultCredFile(t)
},
want: true,
wantErr: false,
},
{
name: "both credentials and certificate present",
setup: func(t *testing.T) {
os.Setenv(HCPClientID, "foo")
os.Setenv(HCPClientSecret, "bar")
os.Setenv(HCPCredFile, tmpCredFile(t))
},
want: true,
wantErr: false,
},
{
name: "certificate file doesn't exist",
setup: func(t *testing.T) {
os.Unsetenv(HCPClientID)
os.Unsetenv(HCPClientSecret)
os.Setenv(HCPCredFile, "/my_fake_file") // Invalid path to trigger error
},
want: false,
wantErr: false,
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
tc.setup(t)
got, err := HasHCPAuth()
if got != tc.want {
t.Fatalf("expected %v, got %v", tc.want, got)
}
if tc.wantErr && err == nil {
t.Fatalf("expected error, got nil")
}
if !tc.wantErr && err != nil {
t.Fatalf("unexpected error: %v", err)
}
})
}
// Restore original env vars
if origClientID != "" {
os.Setenv(HCPClientID, origClientID)
} else {
os.Unsetenv(HCPClientID)
}
if origClientSecret != "" {
os.Setenv(HCPClientSecret, origClientSecret)
} else {
os.Unsetenv(HCPClientSecret)
}
if origCredFile != "" {
os.Setenv(HCPCredFile, origCredFile)
} else {
os.Unsetenv(HCPCredFile)
}
os.Remove(defaultCredPath)
// Restore original default cred file if it was present before test run
if origDefaultCredFilePath != "" {
if err := os.Rename(origDefaultCredFilePath, defaultCredPath); err != nil {
t.Fatalf("failed to replace temp default cred file: %v", err)
}
}
}

View file

@ -4,11 +4,15 @@
package env
const (
HCPClientID = "HCP_CLIENT_ID"
HCPClientSecret = "HCP_CLIENT_SECRET"
HCPProjectID = "HCP_PROJECT_ID"
HCPOrganizationID = "HCP_ORGANIZATION_ID"
HCPPackerRegistry = "HCP_PACKER_REGISTRY"
HCPPackerBucket = "HCP_PACKER_BUCKET_NAME"
HCPPackerBuildFingerprint = "HCP_PACKER_BUILD_FINGERPRINT"
HCPClientID = "HCP_CLIENT_ID"
HCPClientSecret = "HCP_CLIENT_SECRET"
HCPCredFile = "HCP_CRED_FILE"
HCPDefaultCredFilePath = ".config/hcp/"
HCPDefaultCredFilePathFull = "~/.config/hcp/cred_file.json"
HCPDefaultCredFile = "cred_file.json"
HCPProjectID = "HCP_PROJECT_ID"
HCPOrganizationID = "HCP_ORGANIZATION_ID"
HCPPackerRegistry = "HCP_PACKER_REGISTRY"
HCPPackerBucket = "HCP_PACKER_BUCKET_NAME"
HCPPackerBuildFingerprint = "HCP_PACKER_BUILD_FINGERPRINT"
)

View file

@ -63,13 +63,17 @@ func IsHCPEnabled(cfg packer.Handler) bool {
func createConfiguredBucket(templateDir string, opts ...bucketConfigurationOpts) (*Bucket, hcl.Diagnostics) {
var diags hcl.Diagnostics
if !env.HasHCPCredentials() {
hasAuth, err := env.HasHCPAuth()
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: "HCP authentication information required",
Detail: fmt.Sprintf("The client authentication requires both %s and %s environment "+
"variables to be set for authenticating with HCP.",
env.HCPClientID,
env.HCPClientSecret),
Summary: "HCP authentication check failed",
Detail: fmt.Sprintf("Failed to check for HCP authentication, error: %s", err.Error()),
Severity: hcl.DiagError,
})
} else if !hasAuth {
diags = append(diags, &hcl.Diagnostic{
Summary: "HCP authentication information required",
Detail: fmt.Sprintf("HCP Authentication not configured, either set an HCP Client ID and secret using the environment variables %s and %s, place an HCP credential file in the default path (%s), or at a different path specified in the %s environment variable.", env.HCPClientID, env.HCPClientSecret, env.HCPDefaultCredFilePath, env.HCPCredFile),
Severity: hcl.DiagError,
})
}
@ -94,7 +98,7 @@ func createConfiguredBucket(templateDir string, opts ...bucketConfigurationOpts)
})
}
err := bucket.Version.Initialize()
err = bucket.Version.Initialize()
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: "Version initialization failed",

View file

@ -10,8 +10,7 @@ require (
require (
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/compute/metadata v0.3.0 // 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
@ -75,14 +74,14 @@ require (
github.com/pkg/sftp v1.13.2 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/ugorji/go/codec v1.2.6 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/ulikunitz/xz v0.5.14 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect
golang.org/x/oauth2 v0.27.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/term v0.30.0 // indirect
@ -90,7 +89,6 @@ require (
golang.org/x/time v0.11.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.150.0 // 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

View file

@ -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=
@ -329,8 +327,8 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
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/ulikunitz/xz v0.5.14 h1:uv/0Bq533iFdnMHZdRBTOlaNMdb1+ZxXIlHDZHIHcvg=
github.com/ulikunitz/xz v0.5.14/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=
@ -362,7 +360,6 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r
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=
@ -374,8 +371,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
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/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=
@ -447,8 +444,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=

View file

@ -58,8 +58,6 @@ const wrapPowershellString string = `
if ($LASTEXITCODE -ne $null -and $LASTEXITCODE -ne 0) {
$exitCode = $LASTEXITCODE
}
Write-Host $result
exit $exitCode
`

View file

@ -36,7 +36,7 @@ func TestProvisionerPrepare_extractScript(t *testing.T) {
// File contents should contain 2 lines concatenated by newlines: foo\nbar
readFile, err := os.ReadFile(file)
expectedContents := " \n\tif (Test-Path variable:global:ProgressPreference) {\n\t set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'\n\t}\n\t\n\t$exitCode = 0\n\ttry {\n\t$env:PACKER_BUILDER_TYPE=\"\"; $env:PACKER_BUILD_NAME=\"\"; \n\tfoo\n\tbar\n\t\n\t$exitCode = 0\n\t} catch {\n\tWrite-Error \"An error occurred: $_\"\n\t$exitCode = 1\n\t}\n\t\n\tif ($LASTEXITCODE -ne $null -and $LASTEXITCODE -ne 0) {\n\t\t$exitCode = $LASTEXITCODE\n\t}\n\t\n\tWrite-Host $result\n\texit $exitCode\n\n"
expectedContents := "if (Test-Path variable:global:ProgressPreference) {\n set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'\n }\n \n $exitCode = 0\n try {\n $env:PACKER_BUILDER_TYPE=\"\"; $env:PACKER_BUILD_NAME=\"\"; \n foo\n bar\n \n $exitCode = 0\n } catch {\n Write-Error \"An error occurred: $_\"\n $exitCode = 1\n }\n \n if ($LASTEXITCODE -ne $null -and $LASTEXITCODE -ne 0) {\n $exitCode = $LASTEXITCODE\n }\n exit $exitCode"
normalizedExpectedContent := normalizeWhiteSpace(expectedContents)
if err != nil {
t.Fatalf("Should not be error: %s", err)

View file

@ -1 +1 @@
1.14.1
1.14.2

View file

@ -1 +1 @@
v18
v22

View file

@ -1,4 +1,4 @@
FROM docker.mirror.hashicorp.services/node:18.18.2-alpine
FROM docker.mirror.hashicorp.services/node:22.17.1-alpine
RUN apk add --update --no-cache git make g++ automake autoconf libtool nasm libpng-dev
COPY ./package.json /website/package.json

View file

@ -49,7 +49,7 @@ The Docker image is pre-built with all the website dependencies installed, which
### With Node
If your local development environment has a supported version (v18+) of [node installed](https://nodejs.org/en/) you can run:
If your local development environment has a supported version (v22+) of [node installed](https://nodejs.org/en/) you can run:
- `npm install`
- `npm start`

View file

@ -6,6 +6,12 @@ page_title: packer build - Commands
# `packer build` command reference
<Note>
Starting August 1st, 2025, the source for many official HashiCorp-maintained Packer plugins is moving from GitHub releases to the official HashiCorp release site, [releases.hashicorp.com](https://releases.hashicorp.com). Refer to [Install HashiCorp-maintained plugins](/packer/docs/plugins/install#install-hashicorp-maintained-plugins) for more information.
</Note>
The `packer build` command takes a template and runs all the builds within it
in order to generate a set of artifacts. The various builds specified within a
template are executed in parallel, unless otherwise specified. And the

View file

@ -6,6 +6,13 @@ page_title: packer init command reference
# `packer init` command reference
<Note>
Starting August 1st, 2025, the source for many official HashiCorp-maintained Packer plugins is moving from GitHub releases to the official HashiCorp release site, [releases.hashicorp.com](https://releases.hashicorp.com). Refer to [Install HashiCorp-maintained plugins](/packer/docs/plugins/install#install-hashicorp-maintained-plugins) for more information.
</Note>
The `packer init` command initializes Packer according to an HCL template configuration. Refer to [Installing Plugins](/packer/docs/plugins/install) for additional information about installing plugins.
## Description

View file

@ -6,6 +6,12 @@ page_title: packer plugins install command reference
# `packer plugins install` command reference
<Note>
Starting August 1st, 2025, the source for many official HashiCorp-maintained Packer plugins is moving from GitHub releases to the official HashiCorp release site, [releases.hashicorp.com](https://releases.hashicorp.com). Refer to [Install HashiCorp-maintained plugins](/packer/docs/plugins/install#install-hashicorp-maintained-plugins) for more information.
</Note>
The `packer plugins install` command downloads and installs the most recent version of a plugin binary. Refer to [Installing Plugins](/packer/docs/plugins/install) for additional information about installing plugins.
## Description

View file

@ -24,7 +24,7 @@ configurations.
You can use HCP Packer with both JSON and HCL2 templates. If you are using JSON templates, we recommend getting started with
the [HCP Packer environment variables](#hcp-packer-environment-variables) and then migrating to HCL when possible.
## Requirements
## Requirements
Packer version 1.9.1 or newer is required to use the `HCP_PROJECT_ID` environment variable, which lets Packer connect to specific projects in HCP. Your builds will fail if you configure them to send mulit-project metadata using Packer versions older than 1.9.1.
@ -35,7 +35,9 @@ changing your template. You can use environment variables with both JSON and HCL
Refer to [Basic Configuration With Environment Variables](/hcp/docs/packer/store-image-metadata/packer-template-configuration#basic-configuration-with-environment-variables)
in the HCP Packer documentation for complete instructions and examples.
You must set the following environment variables to enable Packer to push metadata to a registry.
You must set authentication environment variables to connect to HCP Packer, you can either directly set a client ID and secret, or (on Packer versions 1.14.2 and later) use an HCP certificate file
For client ID and secret, you set the following environemnt variables
- `HCP_CLIENT_ID` - The HCP client ID of a HashiCorp Cloud Platform service principle that Packer can use to
authenticate to an HCP Packer Registry.
@ -43,6 +45,10 @@ authenticate to an HCP Packer Registry.
- `HCP_CLIENT_SECRET` - The HCP client secret of the HashiCorp Cloud Platform service principle that Packer
can use to authenticate to an HCP Packer Registry.
For certificate based auth simply specify the location of the valid HCP certificate file in the `HCP_CRED_FILE` environment variable, or place it in the default location for the HCP SDK, `~/.config/hcp/cred_file.json`
See the following HCP docs for more information on [Workload Identity Federation](https://developer.hashicorp.com/hcp/docs/hcp/iam/service-principal/workload-identity-federation) and certificate authentication
- `HCP_PACKER_BUCKET_NAME` - The name of the HCP Packer Bucket where you want HCP Packer to store artifact metadata
from builds associated with your template. HCP Packer automatically creates the bucket if it does not already exist.
If your HCL2 template contains an `hcp_packer_registry` block, the bucket name specified in the configuration will be

View file

@ -6,6 +6,12 @@ page_title: Plugins
# Plugin installation overview
<Note>
Starting August 1st, 2025, the source for many official HashiCorp-maintained Packer plugins is moving from GitHub releases to the official HashiCorp release site, [releases.hashicorp.com](https://releases.hashicorp.com). Refer to [Install HashiCorp-maintained plugins](/packer/docs/plugins/install#install-hashicorp-maintained-plugins) for more information.
</Note>
This topic provides overview information about installing and loading Packer plugins. Plugins are standalone applications that perform additional tasks during each build.
## Introduction

View file

@ -6,6 +6,12 @@ page_title: Install Plugins
# Install Plugins
<Note>
Starting August 1st, 2025, the source for many official HashiCorp-maintained Packer plugins is moving from GitHub releases to the official HashiCorp release site, [releases.hashicorp.com](https://releases.hashicorp.com). Refer to [Install HashiCorp-maintained plugins](#install-hashicorp-maintained-plugins) for more information.
</Note>
This topic describes how to install external plugins for Packer. Refer to [Packer Plugins Overview](/packer/docs/plugins) for additional information about plugins.
## Overview
@ -29,9 +35,13 @@ Note that Packer checks the plugin installation directory against the `required_
By default, Packer installs plugins into the plugins directory at `$HOME/.config/packer/plugins` on Unix and `%APPDATA%\packer.d\plugins` on Windows, but you can specify a different directory using the `PACKER_PLUGIN_PATH` environment variable.
~> Note: Plugin installation requires access to temporary files under `TMPDIR`. If the system's temp directory is non-writable or non-executable, use TMPDIR to override the location of the temporary file store used by Packer.
<Note>
Plugin installation requires access to temporary files under `TMPDIR`. If the system's temp directory is non-writable or non-executable, use TMPDIR to override the location of the temporary file store used by Packer.
Refer to the [Packer configuration reference](/packer/docs/configure) for additional information.
</Note>
## Requirements
To install a plugin from a remote source, the plugin must meet the following requirements:
@ -69,11 +79,22 @@ pinning plugin versions for build reproducibility. Refer to the [`packer` block
1. Run the `packer init` command. Packer lists all installed plugins then installs the latest plugin version matching the version constraints specified in the `required_plugins` block. Refer to the [`init` command reference](/packer/docs/commands/init) for additional information.
~> Note: With the new Packer release starting from version 1.14.0, the packer init command will automatically install official (Amazon, Ansible, Azure, Docker, GoogleCloudPlatform, Qemu, Vagrant, VirtualBox) plugins from the [HashiCorp release site](https://releases.hashicorp.com/).
These official plugins will now be released through the official release site only.
## Install HashiCorp-maintained plugins
Going forward, to use newer versions of official Packer plugins, you'll need to upgrade to Packer version 1.14.0 or later. If you're using an older version, you can still install plugins, but as a workaround, you'll need to [manually install them using the CLI](https://developer.hashicorp.com/packer/docs/plugins/install#manually-install-plugins-using-the-cli).
There is no change to the syntax or commands for installing plugins.
HashiCorp now makes the following official HashiCorp-maintained plugins available through the [HashiCorp release site](https://releases.hashicorp.com/).
These plugins include:
- [Amazon](https://developer.hashicorp.com/packer/integrations/hashicorp/amazon)
- [Ansible](https://developer.hashicorp.com/packer/integrations/hashicorp/ansible)
- [Azure](https://developer.hashicorp.com/packer/integrations/hashicorp/azure)
- [Docker](https://developer.hashicorp.com/packer/integrations/hashicorp/docker)
- [Google Cloud Platform](https://developer.hashicorp.com/packer/integrations/hashicorp/googlecompute)
- [QEMU](https://developer.hashicorp.com/packer/integrations/hashicorp/qemu)
- [Vagrant](https://developer.hashicorp.com/packer/integrations/hashicorp/vagrant)
- [VirtualBox](https://developer.hashicorp.com/packer/integrations/hashicorp/virtualbox)
Starting in Packer 1.14.0, Packer automatically installs these plugins from the new release source, and you do not need to make any changes to your Packer templates. To continue to automatically receive updates to these plugins, you must upgrade to Packer 1.14.0 or newer. If you cannot upgrade your version of Packer, you can still install new versions of these plugins manually. Refer to [Manually install plugins using the CLI](#manually-install-plugins-using-the-cli) for more information.
## Manually install plugins using the CLI
@ -95,7 +116,6 @@ $ packer plugins install --path happycloud github.com/hashicorp/happycloud
Refer to the [`packer plugins install`](/packer/docs/commands/plugins/install) reference for additional information.
## Upgrade plugins
To upgrade plugins that are already installed, run the `packer init` with the `--upgrade` flag. Packer retrieves the latest versions of installed plugins specified in the template configuration.
@ -110,7 +130,6 @@ Refer to [`packer init` command](/packer/docs/commands/init) for additional info
## Use a plugin under development
If a development binary, such as a manually-built binary, is available at the specified source, Packer uses it in the build if it is the highest compatible version installed and if no final plugin version with the same version number is installed alongside it.
In the following example, version `1.1.0` or newer is required:
@ -155,7 +174,6 @@ When a non-development version of 1.1.1 becomes available, the binary takes prec
└── packer-plugin-amazon_v1.1.1_x5.0_darwin_arm64_SHA256SUM
```
### Example Docker plugin
Complete the following steps to build and install a custom version of the Docker plugin as an example: