mirror of
https://github.com/hashicorp/packer.git
synced 2026-09-19 14:31:40 -04:00
Packer can only install plugins from github.com, with releases.hashicorp.com consulted first for HashiCorp-published plugins. This has been a long-standing gap for air-gapped and policy-restricted environments (#11164): the source address parser already accepts any hostname, but both existing getters reject non-github.com sources at install time. Add a remote plugin getter that installs plugins from the host named in a required_plugins source address. The host serves the directory structure of releases.hashicorp.com under the source's path: an index.json listing versions, and per version a SHA256SUMS file, the zips it lists, and - when the zip names carry no plugin protocol version - the version's manifest.json. A plugin published on releases.hashicorp.com is therefore mirrored as a verbatim copy of its tree, with every checksum file and signature upstream-authored. A plugin published as GitHub release assets is mirrored by copying each release's assets into a version directory, renaming their SHA256SUMS file to the unprefixed convention with content unchanged, and writing an index.json listing the versions. Both kinds of content can be served side by side by one host. Getter selection happens per source address: github.com sources keep the release and github getters unchanged, while any other host is served by the remote getter over HTTPS. Sources with three or more components are supported, up to the existing 16-component limit, so nested artifact-repository paths and hosts that embed the upstream origin in their path all resolve. Version discovery, constraint solving, checksum verification, and the binary naming rules match the existing getters. The installed filename is rebuilt from validated checksum-file fields and never taken from the server's response, checksum entries matching neither known naming shape are rejected rather than guessed at, and nothing the remote metadata supplies is used to fetch from another origin or path. index.json parsing is covered by fixtures captured from the live releases API, so a format change there fails tests rather than user installs. Closes #11164
47 lines
1.4 KiB
Go
47 lines
1.4 KiB
Go
// Copyright IBM Corp. 2024, 2026
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package command
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/hashicorp/packer/hcl2template/addrs"
|
|
"github.com/hashicorp/packer/packer/plugin-getter/github"
|
|
"github.com/hashicorp/packer/packer/plugin-getter/release"
|
|
"github.com/hashicorp/packer/packer/plugin-getter/remote"
|
|
)
|
|
|
|
func TestPluginGetters(t *testing.T) {
|
|
githubSource, err := addrs.ParsePluginSourceString("github.com/hashicorp/happycloud")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
getters := pluginGetters(githubSource)
|
|
if len(getters) != 2 {
|
|
t.Fatalf("expected the release and github getters for a github.com source, got %d getters", len(getters))
|
|
}
|
|
if _, ok := getters[0].(*release.Getter); !ok {
|
|
t.Fatalf("expected the release getter first, got %T", getters[0])
|
|
}
|
|
if _, ok := getters[1].(*github.Getter); !ok {
|
|
t.Fatalf("expected the github getter second, got %T", getters[1])
|
|
}
|
|
|
|
remoteSource, err := addrs.ParsePluginSourceString("plugins.example.com/mirror/hashicorp/happycloud")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
getters = pluginGetters(remoteSource)
|
|
if len(getters) != 1 {
|
|
t.Fatalf("expected a single remote getter for a non-github.com source, got %d getters", len(getters))
|
|
}
|
|
remoteGetter, ok := getters[0].(*remote.Getter)
|
|
if !ok {
|
|
t.Fatalf("expected a remote getter, got %T", getters[0])
|
|
}
|
|
if remoteGetter.BaseURL != "https://plugins.example.com" {
|
|
t.Fatalf("wrong base URL: %s", remoteGetter.BaseURL)
|
|
}
|
|
}
|