diff --git a/.github/workflows/acceptance-test.yml b/.github/workflows/acceptance-test.yml index 4755e6a15..50e92ecfb 100644 --- a/.github/workflows/acceptance-test.yml +++ b/.github/workflows/acceptance-test.yml @@ -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: diff --git a/CHANGELOG.md b/CHANGELOG.md index be1089002..b5d615375 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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: diff --git a/go.mod b/go.mod index d994a84cf..4bcd95959 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 5e66270a5..ef4d7b882 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/hcl2template/types.build.go b/hcl2template/types.build.go index 648305ee2..6a3300eec 100644 --- a/hcl2template/types.build.go +++ b/hcl2template/types.build.go @@ -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(), }) diff --git a/internal/hcp/api/client.go b/internal/hcp/api/client.go index 78f8ee37c..95a6d55ae 100644 --- a/internal/hcp/api/client.go +++ b/internal/hcp/api/client.go @@ -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), } } diff --git a/internal/hcp/api/deprecated_client.go b/internal/hcp/api/deprecated_client.go index 6f5c06b89..baab80cd3 100644 --- a/internal/hcp/api/deprecated_client.go +++ b/internal/hcp/api/deprecated_client.go @@ -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. diff --git a/internal/hcp/env/env.go b/internal/hcp/env/env.go index 972fd68f7..4d8059371 100644 --- a/internal/hcp/env/env.go +++ b/internal/hcp/env/env.go @@ -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 +} diff --git a/internal/hcp/env/env_test.go b/internal/hcp/env/env_test.go index a773b41c9..82d2dec13 100644 --- a/internal/hcp/env/env_test.go +++ b/internal/hcp/env/env_test.go @@ -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) + } + } +} diff --git a/internal/hcp/env/variables.go b/internal/hcp/env/variables.go index a8c1a493e..79ba92919 100644 --- a/internal/hcp/env/variables.go +++ b/internal/hcp/env/variables.go @@ -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" ) diff --git a/internal/hcp/registry/hcp.go b/internal/hcp/registry/hcp.go index 6204abe08..305990135 100644 --- a/internal/hcp/registry/hcp.go +++ b/internal/hcp/registry/hcp.go @@ -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", diff --git a/packer_test/common/plugin_tester/go.mod b/packer_test/common/plugin_tester/go.mod index 8bd9a3679..f21f5b795 100644 --- a/packer_test/common/plugin_tester/go.mod +++ b/packer_test/common/plugin_tester/go.mod @@ -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 diff --git a/packer_test/common/plugin_tester/go.sum b/packer_test/common/plugin_tester/go.sum index 06781999b..12a010acd 100644 --- a/packer_test/common/plugin_tester/go.sum +++ b/packer_test/common/plugin_tester/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= @@ -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= diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index a74a790a7..ea54c7576 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -58,8 +58,6 @@ const wrapPowershellString string = ` if ($LASTEXITCODE -ne $null -and $LASTEXITCODE -ne 0) { $exitCode = $LASTEXITCODE } - - Write-Host $result exit $exitCode ` diff --git a/provisioner/powershell/provisioner_test.go b/provisioner/powershell/provisioner_test.go index 7c9069ee9..67dc49f45 100644 --- a/provisioner/powershell/provisioner_test.go +++ b/provisioner/powershell/provisioner_test.go @@ -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) diff --git a/version/VERSION b/version/VERSION index 63e799cf4..a32d5a6ad 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.14.1 +1.14.2 \ No newline at end of file diff --git a/website/.nvmrc b/website/.nvmrc index 3f430af82..53d1c14db 100644 --- a/website/.nvmrc +++ b/website/.nvmrc @@ -1 +1 @@ -v18 +v22 diff --git a/website/Dockerfile b/website/Dockerfile index ef0a51433..374e3b141 100644 --- a/website/Dockerfile +++ b/website/Dockerfile @@ -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 diff --git a/website/README.md b/website/README.md index fcd3f0c56..e12bde1f4 100644 --- a/website/README.md +++ b/website/README.md @@ -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` diff --git a/website/content/docs/commands/build.mdx b/website/content/docs/commands/build.mdx index c8d7f74d8..208e9abf6 100644 --- a/website/content/docs/commands/build.mdx +++ b/website/content/docs/commands/build.mdx @@ -6,6 +6,12 @@ page_title: packer build - Commands # `packer build` command reference + + +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. + + + 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 diff --git a/website/content/docs/commands/init.mdx b/website/content/docs/commands/init.mdx index e8e5498b4..d99afdf2c 100644 --- a/website/content/docs/commands/init.mdx +++ b/website/content/docs/commands/init.mdx @@ -6,6 +6,13 @@ page_title: packer init command reference # `packer init` command reference + + +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. + + + + 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 diff --git a/website/content/docs/commands/plugins/install.mdx b/website/content/docs/commands/plugins/install.mdx index a73af1669..79079b3de 100644 --- a/website/content/docs/commands/plugins/install.mdx +++ b/website/content/docs/commands/plugins/install.mdx @@ -6,6 +6,12 @@ page_title: packer plugins install command reference # `packer plugins install` command reference + + +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. + + + 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 diff --git a/website/content/docs/hcp/index.mdx b/website/content/docs/hcp/index.mdx index 27e3f0975..7143b2ba0 100644 --- a/website/content/docs/hcp/index.mdx +++ b/website/content/docs/hcp/index.mdx @@ -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 diff --git a/website/content/docs/plugins/index.mdx b/website/content/docs/plugins/index.mdx index df51b45e9..54684f6b9 100644 --- a/website/content/docs/plugins/index.mdx +++ b/website/content/docs/plugins/index.mdx @@ -6,6 +6,12 @@ page_title: Plugins # Plugin installation overview + + +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. + + + This topic provides overview information about installing and loading Packer plugins. Plugins are standalone applications that perform additional tasks during each build. ## Introduction diff --git a/website/content/docs/plugins/install.mdx b/website/content/docs/plugins/install.mdx index 6200514bc..fba5e25e3 100644 --- a/website/content/docs/plugins/install.mdx +++ b/website/content/docs/plugins/install.mdx @@ -6,6 +6,12 @@ page_title: Install Plugins # Install Plugins + + +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. + + + 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. + + +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. + + ## 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: