mirror of https://github.com/helm/helm
Merge afed23e335
into 9b217506bd
commit
c0fad9a4c5
@ -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