From e35032ac8e90a446b52786428a1e083a7f35eb06 Mon Sep 17 00:00:00 2001 From: tvijay-akamai Date: Tue, 7 Apr 2026 17:04:40 +0530 Subject: [PATCH 1/2] fix:[UIE-10720] fixed lke version upgrade logic --- .../src/features/Kubernetes/kubeUtils.test.ts | 115 ++++++++++++++---- .../src/features/Kubernetes/kubeUtils.ts | 27 ++-- 2 files changed, 105 insertions(+), 37 deletions(-) diff --git a/packages/manager/src/features/Kubernetes/kubeUtils.test.ts b/packages/manager/src/features/Kubernetes/kubeUtils.test.ts index a3a7fcc59f2..b3ab0a4633a 100644 --- a/packages/manager/src/features/Kubernetes/kubeUtils.test.ts +++ b/packages/manager/src/features/Kubernetes/kubeUtils.test.ts @@ -307,31 +307,102 @@ describe('helper functions', () => { const result = getNextVersion(currentVersion, versions); expect(result).toEqual('2.00'); }); - }); - it('should get the next version when given a current enterprise version', () => { - const versions: KubernetesTieredVersion[] = [ - { id: 'v1.31.1+lke4', tier: 'enterprise' }, - { id: 'v1.31.6+lke2', tier: 'enterprise' }, - { id: 'v1.31.6+lke3', tier: 'enterprise' }, - { id: 'v1.31.8+lke1', tier: 'enterprise' }, - ]; - const currentVersion = 'v1.31.6+lke2'; - - const result = getNextVersion(currentVersion, versions); - expect(result).toEqual('v1.31.6+lke3'); - }); + it('should get the next version when given a current enterprise version', () => { + const versions: KubernetesTieredVersion[] = [ + { id: 'v1.31.1+lke4', tier: 'enterprise' }, + { id: 'v1.31.6+lke2', tier: 'enterprise' }, + { id: 'v1.31.6+lke3', tier: 'enterprise' }, + { id: 'v1.31.8+lke1', tier: 'enterprise' }, + ]; + const currentVersion = 'v1.31.6+lke2'; + + const result = getNextVersion(currentVersion, versions); + expect(result).toEqual('v1.31.6+lke3'); + }); + + it('should get the next version when given an obsolete current version', () => { + const versions: KubernetesVersion[] = [ + { id: '1.16' }, + { id: '1.17' }, + { id: '1.18' }, + ]; + const currentVersion = '1.15'; + + const result = getNextVersion(currentVersion, versions); + expect(result).toEqual('1.16'); + }); + + it('should correctly sort enterprise versions across different minor versions', () => { + const versions: KubernetesTieredVersion[] = [ + { id: 'v1.31.8+lke5', tier: 'enterprise' }, + { id: 'v1.32.9+lke1', tier: 'enterprise' }, + ]; + const currentVersion = 'v1.31.8+lke5'; + + const result = getNextVersion(currentVersion, versions); + expect(result).toEqual('v1.32.9+lke1'); + }); + + it('should not suggest a downgrade when cluster version is higher than all available versions', () => { + const versions: KubernetesTieredVersion[] = [ + { id: 'v1.31.8+lke5', tier: 'enterprise' }, + ]; + const currentVersion = 'v1.32.9+lke1'; + + const result = getNextVersion(currentVersion, versions); + expect(result).toBeNull(); + }); + + it('should handle multi-digit lke release numbers correctly', () => { + const versions: KubernetesTieredVersion[] = [ + { id: 'v1.31.8+lke2', tier: 'enterprise' }, + { id: 'v1.31.8+lke5', tier: 'enterprise' }, + { id: 'v1.31.8+lke10', tier: 'enterprise' }, + ]; + const currentVersion = 'v1.31.8+lke5'; - it('should get the next version when given an obsolete current version', () => { - const versions: KubernetesVersion[] = [ - { id: '1.16' }, - { id: '1.17' }, - { id: '1.18' }, - ]; - const currentVersion = '1.15'; + const result = getNextVersion(currentVersion, versions); + expect(result).toEqual('v1.31.8+lke10'); + }); - const result = getNextVersion(currentVersion, versions); - expect(result).toEqual('1.16'); + it('should handle multi-digit patch versions correctly', () => { + const versions: KubernetesTieredVersion[] = [ + { id: 'v1.32.9+lke1', tier: 'enterprise' }, + { id: 'v1.32.10+lke1', tier: 'enterprise' }, + ]; + const currentVersion = 'v1.32.9+lke1'; + + const result = getNextVersion(currentVersion, versions); + expect(result).toEqual('v1.32.10+lke1'); + }); + + it('should return null when the cluster is already on the latest version', () => { + const versions: KubernetesTieredVersion[] = [ + { id: 'v1.31.8+lke5', tier: 'enterprise' }, + { id: 'v1.32.9+lke1', tier: 'enterprise' }, + ]; + const currentVersion = 'v1.32.9+lke1'; + + const result = getNextVersion(currentVersion, versions); + expect(result).toBeNull(); + }); + + it('should return the correct next version for an obsolete enterprise version', () => { + const versions: KubernetesTieredVersion[] = [ + { id: 'v1.31.8+lke5', tier: 'enterprise' }, + { id: 'v1.32.9+lke1', tier: 'enterprise' }, + ]; + const currentVersion = 'v1.30.0+lke1'; + + const result = getNextVersion(currentVersion, versions); + expect(result).toEqual('v1.31.8+lke5'); + }); + + it('should return null when there are no versions available', () => { + const result = getNextVersion('v1.32.9+lke1', []); + expect(result).toBeNull(); + }); }); }); diff --git a/packages/manager/src/features/Kubernetes/kubeUtils.ts b/packages/manager/src/features/Kubernetes/kubeUtils.ts index eb5570f3927..36ed44ed23e 100644 --- a/packages/manager/src/features/Kubernetes/kubeUtils.ts +++ b/packages/manager/src/features/Kubernetes/kubeUtils.ts @@ -137,26 +137,23 @@ export const getNextVersion = ( if (versions.length === 0) { return null; } - const versionStrings = versions.map((v) => v.id).sort(); + const versionStrings = versions + .map((v) => v.id) + .sort((a, b) => compareByKubernetesVersion(a, b, 'asc')); const currentIdx = versionStrings.findIndex( (thisVersion) => currentVersion === thisVersion ); if (currentIdx < 0) { - // For now, assume that if nothing matches the user is on an obsolete version. - // According to the LKE team's deprecation policy, there will only ever be - // one such obsolete version, so this is safe. However, we'll eventually - // have a version.deprecated field to work with, which will be cleaner - // and safer. - // - // Example: - // API returns [1.16, 1.17, 1.18]. - // You haven't upgraded in ages and your cluster is on 1.15. - // The next available upgrade would be 1.16, which is the first item in the list. - // Return that. - // - return versionStrings[0]; + // The current version is not in the available versions list. + // This typically means the user is on an obsolete/deprecated version. + // Return the first available version that is actually newer than the current version + // to avoid suggesting a downgrade. + const nextHigherVersion = versionStrings.find( + (v) => compareByKubernetesVersion(v, currentVersion, 'asc') > 0 + ); + return nextHigherVersion ?? null; } - if (currentIdx === versions.length - 1) { + if (currentIdx === versionStrings.length - 1) { return null; } return versionStrings[currentIdx + 1]; From e172b026219fb9406fab31d7f8a35702665208e2 Mon Sep 17 00:00:00 2001 From: tvijay-akamai Date: Wed, 8 Apr 2026 16:38:26 +0530 Subject: [PATCH 2/2] fix:[UIE-10720] added changeset --- packages/manager/.changeset/pr-13562-fixed-1775692362893.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/manager/.changeset/pr-13562-fixed-1775692362893.md diff --git a/packages/manager/.changeset/pr-13562-fixed-1775692362893.md b/packages/manager/.changeset/pr-13562-fixed-1775692362893.md new file mode 100644 index 00000000000..4be1981c38d --- /dev/null +++ b/packages/manager/.changeset/pr-13562-fixed-1775692362893.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +LKE version upgrade logic ([#13562](https://github.com/linode/manager/pull/13562))