mirror of https://github.com/helm/helm
Signed-off-by: Ashmit Bhardwaj <ashmit.bhardwaj@fmr.com>pull/31001/head
parent
a73c51ca08
commit
afed23e335
@ -0,0 +1,134 @@
|
|||||||
|
package action
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
chart "helm.sh/helm/v4/pkg/chart/v2"
|
||||||
|
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
|
||||||
|
"helm.sh/helm/v4/pkg/kube"
|
||||||
|
release "helm.sh/helm/v4/pkg/release/v1"
|
||||||
|
"helm.sh/helm/v4/pkg/storage"
|
||||||
|
"helm.sh/helm/v4/pkg/storage/driver"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewGetValues(t *testing.T) {
|
||||||
|
cfg := &Configuration{}
|
||||||
|
gv := NewGetValues(cfg)
|
||||||
|
if gv.cfg != cfg {
|
||||||
|
t.Errorf("Expected cfg to be %v, got %v", cfg, gv.cfg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetValues_Run(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
release *release.Release
|
||||||
|
allValues bool
|
||||||
|
version int
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "get default values",
|
||||||
|
release: &release.Release{
|
||||||
|
Name: "test-release",
|
||||||
|
Version: 1,
|
||||||
|
Config: map[string]interface{}{
|
||||||
|
"key": "value",
|
||||||
|
},
|
||||||
|
Chart: &chart.Chart{
|
||||||
|
Metadata: &chart.Metadata{Name: "test-chart", Version: "0.1.0"},
|
||||||
|
Values: map[string]interface{}{
|
||||||
|
"default": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Info: &release.Info{},
|
||||||
|
},
|
||||||
|
allValues: false,
|
||||||
|
version: 1,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "get all values",
|
||||||
|
release: &release.Release{
|
||||||
|
Name: "test-release",
|
||||||
|
Version: 1,
|
||||||
|
Config: map[string]interface{}{
|
||||||
|
"key": "value",
|
||||||
|
},
|
||||||
|
Chart: &chart.Chart{
|
||||||
|
Metadata: &chart.Metadata{Name: "test-chart", Version: "0.1.0"},
|
||||||
|
Values: map[string]interface{}{
|
||||||
|
"default": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Info: &release.Info{},
|
||||||
|
},
|
||||||
|
allValues: true,
|
||||||
|
version: 1,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
memDriver := driver.NewMemory()
|
||||||
|
store := storage.Init(memDriver)
|
||||||
|
// Insert the release into storage
|
||||||
|
if err := store.Create(tt.release); err != nil {
|
||||||
|
t.Fatalf("failed to insert release: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := &Configuration{
|
||||||
|
KubeClient: &MockKubeClient{},
|
||||||
|
Releases: store,
|
||||||
|
}
|
||||||
|
gv := NewGetValues(cfg)
|
||||||
|
gv.AllValues = tt.allValues
|
||||||
|
gv.Version = tt.version
|
||||||
|
|
||||||
|
got, err := gv.Run("test-release")
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("GetValues.Run() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.allValues {
|
||||||
|
expected, _ := chartutil.CoalesceValues(tt.release.Chart, tt.release.Config)
|
||||||
|
if !compareMaps(got, expected) {
|
||||||
|
t.Errorf("GetValues.Run() = %v, want %v", got, expected)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !compareMaps(got, tt.release.Config) {
|
||||||
|
t.Errorf("GetValues.Run() = %v, want %v", got, tt.release.Config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockKubeClient is a minimal mock implementation of the kube.Interface
|
||||||
|
// Only IsReachable is implemented for this test.
|
||||||
|
type MockKubeClient struct{}
|
||||||
|
|
||||||
|
func (m *MockKubeClient) IsReachable() error { return nil }
|
||||||
|
func (m *MockKubeClient) Create(kube.ResourceList) (*kube.Result, error) { return nil, nil }
|
||||||
|
func (m *MockKubeClient) Delete(kube.ResourceList) (*kube.Result, []error) { return nil, nil }
|
||||||
|
func (m *MockKubeClient) Update(kube.ResourceList, kube.ResourceList, bool) (*kube.Result, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (m *MockKubeClient) Build(io.Reader, bool) (kube.ResourceList, error) { return nil, nil }
|
||||||
|
func (m *MockKubeClient) GetWaiter(kube.WaitStrategy) (kube.Waiter, error) { return nil, nil }
|
||||||
|
|
||||||
|
// Helper function to compare maps
|
||||||
|
func compareMaps(a, b map[string]interface{}) bool {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for k, v := range a {
|
||||||
|
if b[k] != v {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
@ -0,0 +1,175 @@
|
|||||||
|
package action
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"helm.sh/helm/v4/pkg/cli"
|
||||||
|
"helm.sh/helm/v4/pkg/registry"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewPull(t *testing.T) {
|
||||||
|
cfg := &Configuration{}
|
||||||
|
p := NewPull(WithConfig(cfg))
|
||||||
|
assert.NotNil(t, p)
|
||||||
|
assert.Equal(t, cfg, p.cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPull_SetRegistryClient(t *testing.T) {
|
||||||
|
cfg := &Configuration{}
|
||||||
|
p := NewPull(WithConfig(cfg))
|
||||||
|
|
||||||
|
regClient, err := registry.NewClient()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
p.SetRegistryClient(regClient)
|
||||||
|
assert.Equal(t, regClient, p.cfg.RegistryClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPull_Run(t *testing.T) {
|
||||||
|
// Create a temporary directory for testing
|
||||||
|
tmpDir, err := os.MkdirTemp("", "helm-pull-test-*")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
// Create test settings
|
||||||
|
settings := cli.New()
|
||||||
|
settings.RepositoryConfig = filepath.Join(tmpDir, "repositories.yaml")
|
||||||
|
settings.RepositoryCache = filepath.Join(tmpDir, "cache")
|
||||||
|
|
||||||
|
// Create test configuration
|
||||||
|
cfg := &Configuration{}
|
||||||
|
regClient, err := registry.NewClient()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
cfg.RegistryClient = regClient
|
||||||
|
|
||||||
|
// Create repositories.yaml
|
||||||
|
err = os.MkdirAll(filepath.Dir(settings.RepositoryConfig), 0755)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = os.WriteFile(settings.RepositoryConfig, []byte{}, 0644)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Create cache directory
|
||||||
|
err = os.MkdirAll(settings.RepositoryCache, 0755)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
chartRef string
|
||||||
|
opts []PullOpt
|
||||||
|
wantErr bool
|
||||||
|
setupFunc func(*Pull)
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "invalid chart reference",
|
||||||
|
chartRef: "invalid-chart",
|
||||||
|
opts: []PullOpt{WithConfig(cfg)},
|
||||||
|
setupFunc: func(p *Pull) {
|
||||||
|
p.Settings = settings
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with untar option",
|
||||||
|
chartRef: "test-chart",
|
||||||
|
opts: []PullOpt{
|
||||||
|
WithConfig(cfg),
|
||||||
|
},
|
||||||
|
setupFunc: func(p *Pull) {
|
||||||
|
p.Untar = true
|
||||||
|
p.UntarDir = tmpDir
|
||||||
|
p.DestDir = tmpDir
|
||||||
|
p.Settings = settings
|
||||||
|
},
|
||||||
|
wantErr: true, // Will fail because chart doesn't exist, but we test the setup
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with verify option",
|
||||||
|
chartRef: "test-chart",
|
||||||
|
opts: []PullOpt{
|
||||||
|
WithConfig(cfg),
|
||||||
|
},
|
||||||
|
setupFunc: func(p *Pull) {
|
||||||
|
p.Verify = true
|
||||||
|
p.Settings = settings
|
||||||
|
},
|
||||||
|
wantErr: true, // Will fail because chart doesn't exist, but we test the setup
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with repo URL",
|
||||||
|
chartRef: "test-chart",
|
||||||
|
opts: []PullOpt{
|
||||||
|
WithConfig(cfg),
|
||||||
|
},
|
||||||
|
setupFunc: func(p *Pull) {
|
||||||
|
p.RepoURL = "https://example.com/charts"
|
||||||
|
p.Settings = settings
|
||||||
|
},
|
||||||
|
wantErr: true, // Will fail because repo doesn't exist, but we test the setup
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
p := NewPull(tt.opts...)
|
||||||
|
if tt.setupFunc != nil {
|
||||||
|
tt.setupFunc(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := p.Run(tt.chartRef)
|
||||||
|
if tt.wantErr {
|
||||||
|
assert.Error(t, err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPull_Run_WithValidChart(t *testing.T) {
|
||||||
|
// Create a temporary directory for testing
|
||||||
|
tmpDir, err := os.MkdirTemp("", "helm-pull-test-*")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
// Create test settings
|
||||||
|
settings := cli.New()
|
||||||
|
settings.RepositoryConfig = filepath.Join(tmpDir, "repositories.yaml")
|
||||||
|
settings.RepositoryCache = filepath.Join(tmpDir, "cache")
|
||||||
|
|
||||||
|
// Create test configuration
|
||||||
|
cfg := &Configuration{}
|
||||||
|
regClient, err := registry.NewClient()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
cfg.RegistryClient = regClient
|
||||||
|
|
||||||
|
// Create repositories.yaml
|
||||||
|
err = os.MkdirAll(filepath.Dir(settings.RepositoryConfig), 0755)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = os.WriteFile(settings.RepositoryConfig, []byte{}, 0644)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Create cache directory
|
||||||
|
err = os.MkdirAll(settings.RepositoryCache, 0755)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Create a test chart in the cache
|
||||||
|
chartDir := filepath.Join(settings.RepositoryCache, "charts")
|
||||||
|
err = os.MkdirAll(chartDir, 0755)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Create a test chart file
|
||||||
|
chartFile := filepath.Join(chartDir, "test-chart-0.1.0.tgz")
|
||||||
|
err = os.WriteFile(chartFile, []byte("test chart content"), 0644)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Test pulling the chart
|
||||||
|
p := NewPull(WithConfig(cfg))
|
||||||
|
p.Settings = settings
|
||||||
|
p.DestDir = tmpDir
|
||||||
|
|
||||||
|
_, err = p.Run("test-chart")
|
||||||
|
assert.Error(t, err) // Will fail because it's not a valid chart, but we test the setup
|
||||||
|
}
|
@ -0,0 +1,186 @@
|
|||||||
|
package action
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
chart "helm.sh/helm/v4/pkg/chart/v2"
|
||||||
|
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
|
||||||
|
"helm.sh/helm/v4/pkg/kube"
|
||||||
|
release "helm.sh/helm/v4/pkg/release/v1"
|
||||||
|
"helm.sh/helm/v4/pkg/storage"
|
||||||
|
"helm.sh/helm/v4/pkg/storage/driver"
|
||||||
|
"helm.sh/helm/v4/pkg/time"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNotReachable = errors.New("kubernetes cluster is not reachable")
|
||||||
|
ErrInvalidManifest = errors.New("invalid manifest")
|
||||||
|
ErrResourceNotFound = errors.New("resource not found")
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockKubeClient struct {
|
||||||
|
reachable bool
|
||||||
|
buildErr error
|
||||||
|
getErr error
|
||||||
|
resources kube.ResourceList
|
||||||
|
getResp map[string][]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ kube.InterfaceResources = &mockKubeClient{}
|
||||||
|
|
||||||
|
func (m *mockKubeClient) IsReachable() error {
|
||||||
|
if !m.reachable {
|
||||||
|
return ErrNotReachable
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockKubeClient) Build(manifest io.Reader, validate bool) (kube.ResourceList, error) {
|
||||||
|
if m.buildErr != nil {
|
||||||
|
return nil, m.buildErr
|
||||||
|
}
|
||||||
|
return m.resources, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockKubeClient) Get(resources kube.ResourceList, related bool) (map[string][]runtime.Object, error) {
|
||||||
|
if m.getErr != nil {
|
||||||
|
return nil, m.getErr
|
||||||
|
}
|
||||||
|
return map[string][]runtime.Object{"Service": {}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockKubeClient) BuildTable(manifest io.Reader, validate bool) (kube.ResourceList, error) {
|
||||||
|
return m.Build(manifest, validate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockKubeClient) Create(resources kube.ResourceList) (*kube.Result, error) {
|
||||||
|
return &kube.Result{Created: resources}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockKubeClient) Delete(resources kube.ResourceList) (*kube.Result, []error) {
|
||||||
|
return &kube.Result{Deleted: resources}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockKubeClient) Update(original, target kube.ResourceList, force bool) (*kube.Result, error) {
|
||||||
|
return &kube.Result{Updated: target}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockKubeClient) GetWaiter(ws kube.WaitStrategy) (kube.Waiter, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStatus(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
releaseName string
|
||||||
|
version int
|
||||||
|
reachable bool
|
||||||
|
buildErr error
|
||||||
|
getErr error
|
||||||
|
expectedErr bool
|
||||||
|
expectedStatus *release.Release
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "successful status check",
|
||||||
|
releaseName: "test-release",
|
||||||
|
version: 1,
|
||||||
|
reachable: true,
|
||||||
|
expectedStatus: &release.Release{
|
||||||
|
Name: "test-release",
|
||||||
|
Namespace: "default",
|
||||||
|
Info: &release.Info{
|
||||||
|
Status: release.StatusDeployed,
|
||||||
|
FirstDeployed: time.Now(),
|
||||||
|
LastDeployed: time.Now(),
|
||||||
|
},
|
||||||
|
Version: 1,
|
||||||
|
Chart: &chart.Chart{},
|
||||||
|
Manifest: "apiVersion: v1\nkind: Service\nmetadata:\n name: test-service",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unreachable cluster",
|
||||||
|
releaseName: "test-release",
|
||||||
|
version: 1,
|
||||||
|
reachable: false,
|
||||||
|
expectedErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "build error",
|
||||||
|
releaseName: "test-release",
|
||||||
|
version: 1,
|
||||||
|
reachable: true,
|
||||||
|
buildErr: ErrInvalidManifest,
|
||||||
|
expectedErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "get error",
|
||||||
|
releaseName: "test-release",
|
||||||
|
version: 1,
|
||||||
|
reachable: true,
|
||||||
|
getErr: ErrResourceNotFound,
|
||||||
|
expectedErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
// Create a mock storage driver
|
||||||
|
store := storage.Init(driver.NewMemory())
|
||||||
|
|
||||||
|
// Create a mock kube client
|
||||||
|
mockClient := &mockKubeClient{
|
||||||
|
reachable: tt.reachable,
|
||||||
|
buildErr: tt.buildErr,
|
||||||
|
getErr: tt.getErr,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create configuration
|
||||||
|
cfg := &Configuration{
|
||||||
|
Releases: store,
|
||||||
|
KubeClient: mockClient,
|
||||||
|
Capabilities: chartutil.DefaultCapabilities,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create status action
|
||||||
|
status := NewStatus(cfg)
|
||||||
|
status.Version = tt.version
|
||||||
|
|
||||||
|
// Store test release if needed
|
||||||
|
if tt.expectedStatus != nil {
|
||||||
|
err := store.Create(tt.expectedStatus)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test release: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run status check
|
||||||
|
got, err := status.Run(tt.releaseName)
|
||||||
|
|
||||||
|
// Check error
|
||||||
|
if tt.expectedErr {
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error but got none")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify release
|
||||||
|
if got == nil {
|
||||||
|
t.Error("expected release but got nil")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if got.Name != tt.expectedStatus.Name {
|
||||||
|
t.Errorf("expected release name %q, got %q", tt.expectedStatus.Name, got.Name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue