Skip to content

Commit ea27b45

Browse files
sgalsalehemosbaugh
authored andcommitted
feat(v3): Sort charts by the weight field in the HelmChart custom resource (#2749)
1 parent 6b5dc0c commit ea27b45

File tree

3 files changed

+120
-10
lines changed

3 files changed

+120
-10
lines changed

api/internal/managers/app/install/install_test.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,16 @@ func TestAppInstallManager_Install(t *testing.T) {
6363
},
6464
}
6565

66-
// Create InstallableHelmCharts with pre-processed values
66+
// Create InstallableHelmCharts with weights - should already be sorted at this stage
6767
installableCharts := []types.InstallableHelmChart{
68-
createTestInstallableHelmChart(t, "nginx-chart", "1.0.0", "web-server", "web", map[string]any{
68+
createTestInstallableHelmChart(t, "nginx-chart", "1.0.0", "web-server", "web", 10, map[string]any{
6969
"image": map[string]any{
7070
"repository": "nginx",
7171
"tag": "latest",
7272
},
7373
"replicas": 3,
7474
}),
75-
createTestInstallableHelmChart(t, "postgres-chart", "2.0.0", "database", "data", map[string]any{
75+
createTestInstallableHelmChart(t, "postgres-chart", "2.0.0", "database", "data", 20, map[string]any{
7676
"database": map[string]any{
7777
"host": "postgres.example.com",
7878
"password": "secret",
@@ -84,7 +84,7 @@ func TestAppInstallManager_Install(t *testing.T) {
8484
mockHelmClient := &helm.MockClient{}
8585

8686
// Chart 1 installation (nginx chart)
87-
mockHelmClient.On("Install", mock.Anything, mock.MatchedBy(func(opts helm.InstallOptions) bool {
87+
nginxCall := mockHelmClient.On("Install", mock.Anything, mock.MatchedBy(func(opts helm.InstallOptions) bool {
8888
if opts.ReleaseName != "web-server" {
8989
return false
9090
}
@@ -99,7 +99,7 @@ func TestAppInstallManager_Install(t *testing.T) {
9999
})).Return(&helmrelease.Release{Name: "web-server"}, nil)
100100

101101
// Chart 2 installation (database chart)
102-
mockHelmClient.On("Install", mock.Anything, mock.MatchedBy(func(opts helm.InstallOptions) bool {
102+
databaseCall := mockHelmClient.On("Install", mock.Anything, mock.MatchedBy(func(opts helm.InstallOptions) bool {
103103
if opts.ReleaseName != "database" {
104104
return false
105105
}
@@ -113,6 +113,12 @@ func TestAppInstallManager_Install(t *testing.T) {
113113
return false
114114
})).Return(&helmrelease.Release{Name: "database"}, nil)
115115

116+
// Verify installation order
117+
mock.InOrder(
118+
nginxCall,
119+
databaseCall,
120+
)
121+
116122
// Create mock installer with detailed verification of config values
117123
mockInstaller := &MockKotsCLIInstaller{}
118124
mockInstaller.On("Install", mock.MatchedBy(func(opts kotscli.InstallOptions) bool {
@@ -190,7 +196,7 @@ func TestAppInstallManager_Install(t *testing.T) {
190196

191197
t.Run("Install updates status correctly", func(t *testing.T) {
192198
installableCharts := []types.InstallableHelmChart{
193-
createTestInstallableHelmChart(t, "monitoring-chart", "1.0.0", "prometheus", "monitoring", map[string]any{"key": "value"}),
199+
createTestInstallableHelmChart(t, "monitoring-chart", "1.0.0", "prometheus", "monitoring", 0, map[string]any{"key": "value"}),
194200
}
195201

196202
// Create mock helm client
@@ -239,7 +245,7 @@ func TestAppInstallManager_Install(t *testing.T) {
239245

240246
t.Run("Install handles errors correctly", func(t *testing.T) {
241247
installableCharts := []types.InstallableHelmChart{
242-
createTestInstallableHelmChart(t, "logging-chart", "1.0.0", "fluentd", "logging", map[string]any{"key": "value"}),
248+
createTestInstallableHelmChart(t, "logging-chart", "1.0.0", "fluentd", "logging", 0, map[string]any{"key": "value"}),
243249
}
244250

245251
// Create mock helm client that fails
@@ -372,7 +378,7 @@ type: application
372378
}
373379

374380
// Helper functions to create test data that can be reused across test cases
375-
func createTestHelmChartCR(name, releaseName, namespace string) *kotsv1beta2.HelmChart {
381+
func createTestHelmChartCR(name, releaseName, namespace string, weight int64) *kotsv1beta2.HelmChart {
376382
return &kotsv1beta2.HelmChart{
377383
TypeMeta: metav1.TypeMeta{
378384
APIVersion: "kots.io/v1beta2",
@@ -384,14 +390,15 @@ func createTestHelmChartCR(name, releaseName, namespace string) *kotsv1beta2.Hel
384390
Spec: kotsv1beta2.HelmChartSpec{
385391
ReleaseName: releaseName,
386392
Namespace: namespace,
393+
Weight: weight,
387394
},
388395
}
389396
}
390397

391-
func createTestInstallableHelmChart(t *testing.T, chartName, chartVersion, releaseName, namespace string, values map[string]any) types.InstallableHelmChart {
398+
func createTestInstallableHelmChart(t *testing.T, chartName, chartVersion, releaseName, namespace string, weight int64, values map[string]any) types.InstallableHelmChart {
392399
return types.InstallableHelmChart{
393400
Archive: createTestChartArchive(t, chartName, chartVersion),
394401
Values: values,
395-
CR: createTestHelmChartCR(chartName, releaseName, namespace),
402+
CR: createTestHelmChartCR(chartName, releaseName, namespace, weight),
396403
}
397404
}

api/internal/managers/app/release/template.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"maps"
77
"os"
8+
"sort"
89
"strconv"
910

1011
"github.com/replicatedhq/embedded-cluster/api/pkg/template"
@@ -101,6 +102,11 @@ func (m *appReleaseManager) ExtractInstallableHelmCharts(ctx context.Context, co
101102
installableCharts = append(installableCharts, installableChart)
102103
}
103104

105+
// Sort charts by weight field before returning
106+
sort.Slice(installableCharts, func(i, j int) bool {
107+
return installableCharts[i].CR.GetWeight() < installableCharts[j].CR.GetWeight()
108+
})
109+
104110
return installableCharts, nil
105111
}
106112

api/internal/managers/app/release/template_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,6 +2396,103 @@ spec:
23962396
},
23972397
},
23982398
},
2399+
{
2400+
name: "charts sorted by weight - negative, zero, positive",
2401+
helmChartCRs: [][]byte{
2402+
[]byte(`apiVersion: kots.io/v1beta2
2403+
kind: HelmChart
2404+
metadata:
2405+
name: positive-weight-chart
2406+
spec:
2407+
chart:
2408+
name: nginx
2409+
chartVersion: "1.0.0"
2410+
weight: 100
2411+
values:
2412+
name: "positive"`),
2413+
[]byte(`apiVersion: kots.io/v1beta2
2414+
kind: HelmChart
2415+
metadata:
2416+
name: no-weight-chart
2417+
spec:
2418+
chart:
2419+
name: redis
2420+
chartVersion: "2.0.0"
2421+
values:
2422+
name: "zero"`), // No weight specified, defaults to 0
2423+
[]byte(`apiVersion: kots.io/v1beta2
2424+
kind: HelmChart
2425+
metadata:
2426+
name: negative-weight-chart
2427+
spec:
2428+
chart:
2429+
name: postgresql
2430+
chartVersion: "1.0.0"
2431+
weight: -10
2432+
values:
2433+
name: "negative"`),
2434+
},
2435+
chartArchives: [][]byte{
2436+
createTestChartArchive(t, "nginx", "1.0.0"),
2437+
createTestChartArchive(t, "redis", "2.0.0"),
2438+
createTestChartArchive(t, "postgresql", "1.0.0"),
2439+
},
2440+
configValues: types.AppConfigValues{},
2441+
expectError: false,
2442+
expected: []types.InstallableHelmChart{
2443+
// Should be sorted by weight: postgresql (-10), redis (0), nginx (100)
2444+
{
2445+
Archive: createTestChartArchive(t, "postgresql", "1.0.0"),
2446+
Values: map[string]any{
2447+
"name": "negative",
2448+
},
2449+
CR: createHelmChartCRFromYAML(`apiVersion: kots.io/v1beta2
2450+
kind: HelmChart
2451+
metadata:
2452+
name: negative-weight-chart
2453+
spec:
2454+
chart:
2455+
name: postgresql
2456+
chartVersion: "1.0.0"
2457+
weight: -10
2458+
values:
2459+
name: "negative"`),
2460+
},
2461+
{
2462+
Archive: createTestChartArchive(t, "redis", "2.0.0"),
2463+
Values: map[string]any{
2464+
"name": "zero",
2465+
},
2466+
CR: createHelmChartCRFromYAML(`apiVersion: kots.io/v1beta2
2467+
kind: HelmChart
2468+
metadata:
2469+
name: no-weight-chart
2470+
spec:
2471+
chart:
2472+
name: redis
2473+
chartVersion: "2.0.0"
2474+
values:
2475+
name: "zero"`),
2476+
},
2477+
{
2478+
Archive: createTestChartArchive(t, "nginx", "1.0.0"),
2479+
Values: map[string]any{
2480+
"name": "positive",
2481+
},
2482+
CR: createHelmChartCRFromYAML(`apiVersion: kots.io/v1beta2
2483+
kind: HelmChart
2484+
metadata:
2485+
name: positive-weight-chart
2486+
spec:
2487+
chart:
2488+
name: nginx
2489+
chartVersion: "1.0.0"
2490+
weight: 100
2491+
values:
2492+
name: "positive"`),
2493+
},
2494+
},
2495+
},
23992496
}
24002497

24012498
for _, tt := range tests {

0 commit comments

Comments
 (0)