Skip to content

Commit 041d8ec

Browse files
committed
chore: more comments and tests
1 parent 0249e25 commit 041d8ec

File tree

3 files changed

+208
-3
lines changed

3 files changed

+208
-3
lines changed

cmd/installer/kotscli/kotscli.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -478,14 +478,23 @@ func GetCurrentAppVersion(appSlug string, namespace string) (*AppVersionInfo, er
478478
return nil, fmt.Errorf("unmarshal versions output: %w", err)
479479
}
480480

481-
// Find the deployed version
481+
version, err := getLastDeployedAppVersion(versions)
482+
if err != nil {
483+
return nil, fmt.Errorf("no deployed version found for app %s", appSlug)
484+
}
485+
return version, nil
486+
}
487+
488+
// getLastDeployedAppVersion finds the last deployed version from a slice of versions
489+
func getLastDeployedAppVersion(versions []AppVersionInfo) (*AppVersionInfo, error) {
490+
// Find the last deployed version. This can be either successful or failed deploys.
482491
for _, v := range versions {
483-
if v.Status == "deployed" {
492+
if v.Status == "deployed" || v.Status == "failed" {
484493
return &v, nil
485494
}
486495
}
487496

488-
return nil, fmt.Errorf("no deployed version found for app %s", appSlug)
497+
return nil, fmt.Errorf("no deployed version found")
489498
}
490499

491500
// GetConfigValuesOptions holds options for getting config values
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package kotscli
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func Test_getLastDeployedAppVersion(t *testing.T) {
11+
tests := []struct {
12+
name string
13+
versions []AppVersionInfo
14+
want *AppVersionInfo
15+
wantErr bool
16+
}{
17+
{
18+
name: "should return first deployed version",
19+
versions: []AppVersionInfo{
20+
{
21+
VersionLabel: "1.0.0",
22+
ChannelSequence: 1,
23+
Sequence: 1,
24+
Status: "deployed",
25+
},
26+
{
27+
VersionLabel: "0.9.0",
28+
ChannelSequence: 2,
29+
Sequence: 2,
30+
Status: "pending",
31+
},
32+
},
33+
want: &AppVersionInfo{
34+
VersionLabel: "1.0.0",
35+
ChannelSequence: 1,
36+
Sequence: 1,
37+
Status: "deployed",
38+
},
39+
wantErr: false,
40+
},
41+
{
42+
name: "should return failed deployment",
43+
versions: []AppVersionInfo{
44+
{
45+
VersionLabel: "1.0.0",
46+
ChannelSequence: 1,
47+
Sequence: 1,
48+
Status: "failed",
49+
},
50+
{
51+
VersionLabel: "0.9.0",
52+
ChannelSequence: 2,
53+
Sequence: 2,
54+
Status: "pending",
55+
},
56+
},
57+
want: &AppVersionInfo{
58+
VersionLabel: "1.0.0",
59+
ChannelSequence: 1,
60+
Sequence: 1,
61+
Status: "failed",
62+
},
63+
wantErr: false,
64+
},
65+
{
66+
name: "should return deployed before failed when both exist",
67+
versions: []AppVersionInfo{
68+
{
69+
VersionLabel: "2.0.0",
70+
ChannelSequence: 3,
71+
Sequence: 3,
72+
Status: "deployed",
73+
},
74+
{
75+
VersionLabel: "1.5.0",
76+
ChannelSequence: 2,
77+
Sequence: 2,
78+
Status: "failed",
79+
},
80+
},
81+
want: &AppVersionInfo{
82+
VersionLabel: "2.0.0",
83+
ChannelSequence: 3,
84+
Sequence: 3,
85+
Status: "deployed",
86+
},
87+
wantErr: false,
88+
},
89+
{
90+
name: "should return failed when it comes before deployed",
91+
versions: []AppVersionInfo{
92+
{
93+
VersionLabel: "2.0.0",
94+
ChannelSequence: 3,
95+
Sequence: 3,
96+
Status: "failed",
97+
},
98+
{
99+
VersionLabel: "1.5.0",
100+
ChannelSequence: 2,
101+
Sequence: 2,
102+
Status: "deployed",
103+
},
104+
},
105+
want: &AppVersionInfo{
106+
VersionLabel: "2.0.0",
107+
ChannelSequence: 3,
108+
Sequence: 3,
109+
Status: "failed",
110+
},
111+
wantErr: false,
112+
},
113+
{
114+
name: "should return error when no deployed or failed versions exist",
115+
versions: []AppVersionInfo{
116+
{
117+
VersionLabel: "1.0.0",
118+
ChannelSequence: 1,
119+
Sequence: 1,
120+
Status: "pending",
121+
},
122+
{
123+
VersionLabel: "0.9.0",
124+
ChannelSequence: 2,
125+
Sequence: 2,
126+
Status: "pending_download",
127+
},
128+
},
129+
want: nil,
130+
wantErr: true,
131+
},
132+
{
133+
name: "should return error when versions slice is empty",
134+
versions: []AppVersionInfo{},
135+
want: nil,
136+
wantErr: true,
137+
},
138+
{
139+
name: "should return error when versions slice is nil",
140+
versions: nil,
141+
want: nil,
142+
wantErr: true,
143+
},
144+
{
145+
name: "should handle versions with other statuses",
146+
versions: []AppVersionInfo{
147+
{
148+
VersionLabel: "3.0.0",
149+
ChannelSequence: 5,
150+
Sequence: 5,
151+
Status: "pending_config",
152+
},
153+
{
154+
VersionLabel: "2.5.0",
155+
ChannelSequence: 4,
156+
Sequence: 4,
157+
Status: "pending_download",
158+
},
159+
{
160+
VersionLabel: "2.0.0",
161+
ChannelSequence: 3,
162+
Sequence: 3,
163+
Status: "deployed",
164+
},
165+
{
166+
VersionLabel: "1.0.0",
167+
ChannelSequence: 1,
168+
Sequence: 1,
169+
Status: "unknown",
170+
},
171+
},
172+
want: &AppVersionInfo{
173+
VersionLabel: "2.0.0",
174+
ChannelSequence: 3,
175+
Sequence: 3,
176+
Status: "deployed",
177+
},
178+
wantErr: false,
179+
},
180+
}
181+
for _, tt := range tests {
182+
t.Run(tt.name, func(t *testing.T) {
183+
got, err := getLastDeployedAppVersion(tt.versions)
184+
if tt.wantErr {
185+
require.Error(t, err)
186+
assert.Nil(t, got)
187+
} else {
188+
require.NoError(t, err)
189+
assert.Equal(t, tt.want, got)
190+
}
191+
})
192+
}
193+
}

pkg-new/validation/upgradable.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type UpgradableOptions struct {
2727
requiredReleases []string
2828
}
2929

30+
// WithAirgapRequiredReleases extracts the required releases from airgap metadata to be used for validation
3031
func (opts *UpgradableOptions) WithAirgapRequiredReleases(metadata *airgap.AirgapMetadata) error {
3132
if metadata == nil || metadata.AirgapInfo == nil {
3233
return fmt.Errorf("airgap metadata is required for validating airgap required releases")
@@ -51,6 +52,7 @@ func (opts *UpgradableOptions) WithAirgapRequiredReleases(metadata *airgap.Airga
5152
return nil
5253
}
5354

55+
// WithOnlineRequiredReleases fetches the pending releases from the current app sequence and extracts the required releases until the target app sequence
5456
func (opts *UpgradableOptions) WithOnlineRequiredReleases(ctx context.Context, replAPIClient replicatedapi.Client) error {
5557
if opts.License == nil {
5658
return fmt.Errorf("license is required to check online upgrade required releases")
@@ -70,6 +72,7 @@ func (opts *UpgradableOptions) WithOnlineRequiredReleases(ctx context.Context, r
7072
return nil
7173
}
7274

75+
// handlePendingReleases processes the pending releases to extract required releases between current and target sequences
7376
func (opts *UpgradableOptions) handlePendingReleases(pendingReleases []replicatedapi.ChannelRelease) {
7477
// Find required releases between current and target sequence
7578
for _, release := range pendingReleases {

0 commit comments

Comments
 (0)