Skip to content

Commit b1c9557

Browse files
fix:[UIE-10720] fixed lke version upgrade logic (#13562)
* fix:[UIE-10720] fixed lke version upgrade logic * fix:[UIE-10720] added changeset
1 parent c531474 commit b1c9557

3 files changed

Lines changed: 110 additions & 37 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Fixed
3+
---
4+
5+
LKE version upgrade logic ([#13562](https://github.com/linode/manager/pull/13562))

packages/manager/src/features/Kubernetes/kubeUtils.test.ts

Lines changed: 93 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -307,31 +307,102 @@ describe('helper functions', () => {
307307
const result = getNextVersion(currentVersion, versions);
308308
expect(result).toEqual('2.00');
309309
});
310-
});
311310

312-
it('should get the next version when given a current enterprise version', () => {
313-
const versions: KubernetesTieredVersion[] = [
314-
{ id: 'v1.31.1+lke4', tier: 'enterprise' },
315-
{ id: 'v1.31.6+lke2', tier: 'enterprise' },
316-
{ id: 'v1.31.6+lke3', tier: 'enterprise' },
317-
{ id: 'v1.31.8+lke1', tier: 'enterprise' },
318-
];
319-
const currentVersion = 'v1.31.6+lke2';
320-
321-
const result = getNextVersion(currentVersion, versions);
322-
expect(result).toEqual('v1.31.6+lke3');
323-
});
311+
it('should get the next version when given a current enterprise version', () => {
312+
const versions: KubernetesTieredVersion[] = [
313+
{ id: 'v1.31.1+lke4', tier: 'enterprise' },
314+
{ id: 'v1.31.6+lke2', tier: 'enterprise' },
315+
{ id: 'v1.31.6+lke3', tier: 'enterprise' },
316+
{ id: 'v1.31.8+lke1', tier: 'enterprise' },
317+
];
318+
const currentVersion = 'v1.31.6+lke2';
319+
320+
const result = getNextVersion(currentVersion, versions);
321+
expect(result).toEqual('v1.31.6+lke3');
322+
});
323+
324+
it('should get the next version when given an obsolete current version', () => {
325+
const versions: KubernetesVersion[] = [
326+
{ id: '1.16' },
327+
{ id: '1.17' },
328+
{ id: '1.18' },
329+
];
330+
const currentVersion = '1.15';
331+
332+
const result = getNextVersion(currentVersion, versions);
333+
expect(result).toEqual('1.16');
334+
});
335+
336+
it('should correctly sort enterprise versions across different minor versions', () => {
337+
const versions: KubernetesTieredVersion[] = [
338+
{ id: 'v1.31.8+lke5', tier: 'enterprise' },
339+
{ id: 'v1.32.9+lke1', tier: 'enterprise' },
340+
];
341+
const currentVersion = 'v1.31.8+lke5';
342+
343+
const result = getNextVersion(currentVersion, versions);
344+
expect(result).toEqual('v1.32.9+lke1');
345+
});
346+
347+
it('should not suggest a downgrade when cluster version is higher than all available versions', () => {
348+
const versions: KubernetesTieredVersion[] = [
349+
{ id: 'v1.31.8+lke5', tier: 'enterprise' },
350+
];
351+
const currentVersion = 'v1.32.9+lke1';
352+
353+
const result = getNextVersion(currentVersion, versions);
354+
expect(result).toBeNull();
355+
});
356+
357+
it('should handle multi-digit lke release numbers correctly', () => {
358+
const versions: KubernetesTieredVersion[] = [
359+
{ id: 'v1.31.8+lke2', tier: 'enterprise' },
360+
{ id: 'v1.31.8+lke5', tier: 'enterprise' },
361+
{ id: 'v1.31.8+lke10', tier: 'enterprise' },
362+
];
363+
const currentVersion = 'v1.31.8+lke5';
324364

325-
it('should get the next version when given an obsolete current version', () => {
326-
const versions: KubernetesVersion[] = [
327-
{ id: '1.16' },
328-
{ id: '1.17' },
329-
{ id: '1.18' },
330-
];
331-
const currentVersion = '1.15';
365+
const result = getNextVersion(currentVersion, versions);
366+
expect(result).toEqual('v1.31.8+lke10');
367+
});
332368

333-
const result = getNextVersion(currentVersion, versions);
334-
expect(result).toEqual('1.16');
369+
it('should handle multi-digit patch versions correctly', () => {
370+
const versions: KubernetesTieredVersion[] = [
371+
{ id: 'v1.32.9+lke1', tier: 'enterprise' },
372+
{ id: 'v1.32.10+lke1', tier: 'enterprise' },
373+
];
374+
const currentVersion = 'v1.32.9+lke1';
375+
376+
const result = getNextVersion(currentVersion, versions);
377+
expect(result).toEqual('v1.32.10+lke1');
378+
});
379+
380+
it('should return null when the cluster is already on the latest version', () => {
381+
const versions: KubernetesTieredVersion[] = [
382+
{ id: 'v1.31.8+lke5', tier: 'enterprise' },
383+
{ id: 'v1.32.9+lke1', tier: 'enterprise' },
384+
];
385+
const currentVersion = 'v1.32.9+lke1';
386+
387+
const result = getNextVersion(currentVersion, versions);
388+
expect(result).toBeNull();
389+
});
390+
391+
it('should return the correct next version for an obsolete enterprise version', () => {
392+
const versions: KubernetesTieredVersion[] = [
393+
{ id: 'v1.31.8+lke5', tier: 'enterprise' },
394+
{ id: 'v1.32.9+lke1', tier: 'enterprise' },
395+
];
396+
const currentVersion = 'v1.30.0+lke1';
397+
398+
const result = getNextVersion(currentVersion, versions);
399+
expect(result).toEqual('v1.31.8+lke5');
400+
});
401+
402+
it('should return null when there are no versions available', () => {
403+
const result = getNextVersion('v1.32.9+lke1', []);
404+
expect(result).toBeNull();
405+
});
335406
});
336407
});
337408

packages/manager/src/features/Kubernetes/kubeUtils.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -137,26 +137,23 @@ export const getNextVersion = (
137137
if (versions.length === 0) {
138138
return null;
139139
}
140-
const versionStrings = versions.map((v) => v.id).sort();
140+
const versionStrings = versions
141+
.map((v) => v.id)
142+
.sort((a, b) => compareByKubernetesVersion(a, b, 'asc'));
141143
const currentIdx = versionStrings.findIndex(
142144
(thisVersion) => currentVersion === thisVersion
143145
);
144146
if (currentIdx < 0) {
145-
// For now, assume that if nothing matches the user is on an obsolete version.
146-
// According to the LKE team's deprecation policy, there will only ever be
147-
// one such obsolete version, so this is safe. However, we'll eventually
148-
// have a version.deprecated field to work with, which will be cleaner
149-
// and safer.
150-
//
151-
// Example:
152-
// API returns [1.16, 1.17, 1.18].
153-
// You haven't upgraded in ages and your cluster is on 1.15.
154-
// The next available upgrade would be 1.16, which is the first item in the list.
155-
// Return that.
156-
//
157-
return versionStrings[0];
147+
// The current version is not in the available versions list.
148+
// This typically means the user is on an obsolete/deprecated version.
149+
// Return the first available version that is actually newer than the current version
150+
// to avoid suggesting a downgrade.
151+
const nextHigherVersion = versionStrings.find(
152+
(v) => compareByKubernetesVersion(v, currentVersion, 'asc') > 0
153+
);
154+
return nextHigherVersion ?? null;
158155
}
159-
if (currentIdx === versions.length - 1) {
156+
if (currentIdx === versionStrings.length - 1) {
160157
return null;
161158
}
162159
return versionStrings[currentIdx + 1];

0 commit comments

Comments
 (0)