fix: honor plugins custom directory for http and local installers

Signed-off-by: Florian Rey <nervo@nervo.net>
pull/31756/head
Florian Rey 6 months ago
parent b3fbf8d0f7
commit d73846c93f
No known key found for this signature in database

@ -14,32 +14,52 @@ limitations under the License.
package installer // import "helm.sh/helm/v4/internal/plugin/installer"
import (
"path/filepath"
"testing"
"helm.sh/helm/v4/pkg/helmpath"
)
func TestPath(t *testing.T) {
tests := []struct {
name string
source string
helmPluginsDir string
expectPath string
}{
{
name: "empty source default helm plugins dir",
source: "",
helmPluginsDir: "",
expectPath: "",
}, {
name: "default helm plugins dir",
source: "https://github.com/adamreese/helm-env",
helmPluginsDir: "",
expectPath: helmpath.DataPath("plugins", "helm-env"),
}, {
name: "empty source custom helm plugins dir",
source: "",
helmPluginsDir: "/helm/data/plugins",
helmPluginsDir: "/foo/bar",
expectPath: "",
}, {
source: "https://github.com/jkroepke/helm-secrets",
helmPluginsDir: "/helm/data/plugins",
expectPath: "/helm/data/plugins/helm-secrets",
name: "custom helm plugins dir",
source: "https://github.com/adamreese/helm-env",
helmPluginsDir: "/foo/bar",
expectPath: filepath.Join("/foo/bar", "helm-env"),
},
}
for _, tt := range tests {
t.Setenv("HELM_PLUGINS", tt.helmPluginsDir)
baseIns := newBase(tt.source)
baseInsPath := baseIns.Path()
if baseInsPath != tt.expectPath {
t.Errorf("expected name %s, got %s", tt.expectPath, baseInsPath)
}
t.Run(tt.name, func(t *testing.T) {
if tt.helmPluginsDir != "" {
t.Setenv("HELM_PLUGINS", tt.helmPluginsDir)
}
installer := newBase(tt.source)
path := installer.Path()
if path != tt.expectPath {
t.Errorf("expected path %s, got %s", tt.expectPath, path)
}
})
}
}

@ -37,6 +37,7 @@ type HTTPInstaller struct {
CacheDir string
PluginName string
base
settings *cli.EnvSettings
extractor Extractor
getter getter.Getter
// Cached data to avoid duplicate downloads
@ -51,6 +52,8 @@ func NewHTTPInstaller(source string) (*HTTPInstaller, error) {
return nil, err
}
settings := cli.New()
extractor, err := NewExtractor(source)
if err != nil {
return nil, err
@ -65,6 +68,7 @@ func NewHTTPInstaller(source string) (*HTTPInstaller, error) {
CacheDir: helmpath.CachePath("plugins", key),
PluginName: stripPluginName(filepath.Base(source)),
base: newBase(source),
settings: settings,
extractor: extractor,
getter: get,
}
@ -152,7 +156,7 @@ func (i HTTPInstaller) Path() string {
if i.Source == "" {
return ""
}
return helmpath.DataPath("plugins", i.PluginName)
return filepath.Join(i.settings.PluginsDirectory, i.PluginName)
}
// SupportsVerification returns true if the HTTP installer can verify plugins

@ -32,6 +32,7 @@ import (
"testing"
"helm.sh/helm/v4/internal/test/ensure"
"helm.sh/helm/v4/pkg/cli"
"helm.sh/helm/v4/pkg/getter"
"helm.sh/helm/v4/pkg/helmpath"
)
@ -562,6 +563,7 @@ func TestExtractPluginInSubdirectory(t *testing.T) {
CacheDir: tempDir,
PluginName: "subdir-plugin",
base: newBase(source),
settings: cli.New(),
extractor: &TarGzExtractor{},
}
@ -594,3 +596,40 @@ func TestExtractPluginInSubdirectory(t *testing.T) {
t.Errorf("Expected plugin root to be %s but got %s", expectedRoot, pluginRoot)
}
}
func TestHTTPInstaller_Path(t *testing.T) {
tests := []struct {
name string
source string
helmPluginsDir string
expectPath string
}{
{
name: "default helm plugins dir",
source: "https://example.com/fake-plugin-0.0.1.tar.gz",
helmPluginsDir: "",
expectPath: helmpath.DataPath("plugins", "fake-plugin"),
}, {
name: "custom helm plugins dir",
source: "https://example.com/fake-plugin-0.0.1.tar.gz",
helmPluginsDir: "/foo/bar",
expectPath: filepath.Join("/foo/bar", "fake-plugin"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.helmPluginsDir != "" {
t.Setenv("HELM_PLUGINS", tt.helmPluginsDir)
}
installer, err := NewHTTPInstaller(tt.source)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
path := installer.Path()
if path != tt.expectPath {
t.Errorf("expected path %s, got %s", tt.expectPath, path)
}
})
}
}

@ -26,6 +26,7 @@ import (
"helm.sh/helm/v4/internal/plugin"
"helm.sh/helm/v4/internal/third_party/dep/fs"
"helm.sh/helm/v4/pkg/cli"
"helm.sh/helm/v4/pkg/helmpath"
)
@ -35,6 +36,7 @@ var ErrPluginNotADirectory = errors.New("expected plugin to be a directory (cont
// LocalInstaller installs plugins from the filesystem.
type LocalInstaller struct {
base
settings *cli.EnvSettings
isArchive bool
extractor Extractor
pluginData []byte // Cached plugin data
@ -47,8 +49,12 @@ func NewLocalInstaller(source string) (*LocalInstaller, error) {
if err != nil {
return nil, fmt.Errorf("unable to get absolute path to plugin: %w", err)
}
settings := cli.New()
i := &LocalInstaller{
base: newBase(src),
base: newBase(src),
settings: settings,
}
// Check if source is an archive
@ -176,7 +182,7 @@ func (i *LocalInstaller) Path() string {
pluginName = stripPluginName(pluginName)
}
return helmpath.DataPath("plugins", pluginName)
return filepath.Join(i.settings.PluginsDirectory, pluginName)
}
// SupportsVerification returns true if the local installer can verify plugins

@ -147,3 +147,50 @@ func TestLocalInstallerTarball(t *testing.T) {
t.Fatalf("plugin not found at %s: %v", i.Path(), err)
}
}
func TestLocalInstaller_Path(t *testing.T) {
tests := []struct {
name string
source string
helmPluginsDir string
expectPath string
}{
{
name: "default helm plugins dir",
source: "../testdata/plugdir/good/echo-v1",
helmPluginsDir: "",
expectPath: helmpath.DataPath("plugins", "echo-v1"),
}, {
name: "archive default helm plugins dir",
source: "../testdata/plugdir/good/archive-1.2.3.tar.gz",
helmPluginsDir: "",
expectPath: helmpath.DataPath("plugins", "archive"),
}, {
name: "custom helm plugins dir",
source: "../testdata/plugdir/good/echo-v1",
helmPluginsDir: "/foo/bar",
expectPath: filepath.Join("/foo/bar", "echo-v1"),
}, {
name: "archive custom helm plugins dir",
source: "../testdata/plugdir/good/archive-1.2.3.tar.gz",
helmPluginsDir: "/foo/bar",
expectPath: filepath.Join("/foo/bar", "archive"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.helmPluginsDir != "" {
t.Setenv("HELM_PLUGINS", tt.helmPluginsDir)
}
installer, err := NewLocalInstaller(tt.source)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
path := installer.Path()
if path != tt.expectPath {
t.Errorf("expected path %s, got %s", tt.expectPath, path)
}
})
}
}

@ -35,7 +35,6 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"helm.sh/helm/v4/internal/test/ensure"
"helm.sh/helm/v4/pkg/cli"
"helm.sh/helm/v4/pkg/getter"
"helm.sh/helm/v4/pkg/helmpath"
)
@ -281,33 +280,33 @@ func TestNewOCIInstaller(t *testing.T) {
func TestOCIInstaller_Path(t *testing.T) {
tests := []struct {
name string
source string
pluginName string
expectPath string
name string
source string
helmPluginsDir string
expectPath string
}{
{
name: "valid plugin name",
source: "oci://ghcr.io/user/plugin-name:v1.0.0",
pluginName: "plugin-name",
expectPath: helmpath.DataPath("plugins", "plugin-name"),
},
{
name: "empty source",
source: "",
pluginName: "",
expectPath: "",
name: "default helm plugins dir",
source: "oci://ghcr.io/user/plugin-name:v1.0.0",
helmPluginsDir: "",
expectPath: helmpath.DataPath("plugins", "plugin-name"),
}, {
name: "custom helm plugins dir",
source: "oci://ghcr.io/user/plugin-name:v1.0.0",
helmPluginsDir: "/foo/bar",
expectPath: filepath.Join("/foo/bar", "plugin-name"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
installer := &OCIInstaller{
PluginName: tt.pluginName,
base: newBase(tt.source),
settings: cli.New(),
if tt.helmPluginsDir != "" {
t.Setenv("HELM_PLUGINS", tt.helmPluginsDir)
}
installer, err := NewOCIInstaller(tt.source)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
path := installer.Path()
if path != tt.expectPath {
t.Errorf("expected path %s, got %s", tt.expectPath, path)

@ -186,3 +186,43 @@ func TestVCSInstallerUpdate(t *testing.T) {
t.Fatalf("expected error for plugin modified, got (%v)", err)
}
}
func TestVCSInstaller_Path(t *testing.T) {
tests := []struct {
name string
source string
version string
helmPluginsDir string
expectPath string
}{
{
name: "default helm plugins dir",
source: "https://github.com/adamreese/helm-env",
version: "0.2.0",
helmPluginsDir: "",
expectPath: helmpath.DataPath("plugins", "helm-env"),
}, {
name: "custom helm plugins dir",
source: "https://github.com/adamreese/helm-env",
version: "0.2.0",
helmPluginsDir: "/foo/bar",
expectPath: filepath.Join("/foo/bar", "helm-env"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.helmPluginsDir != "" {
t.Setenv("HELM_PLUGINS", tt.helmPluginsDir)
}
installer, err := NewVCSInstaller(tt.source, tt.version)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
path := installer.Path()
if path != tt.expectPath {
t.Errorf("expected path %s, got %s", tt.expectPath, path)
}
})
}
}

Loading…
Cancel
Save