Skip to content

Commit

Permalink
[8.12][Fleet] fix API not allowing to upgrade to a newer version when…
Browse files Browse the repository at this point in the history
… version differs only in patch (#175765)

Fixes #175766

[8.12][Fleet] Partial backport of
#175198

To verify:
- add a fleet-server version 8.12.0
- enroll an agent version 8.12.0-SNAPSHOT
- take the agent id and in console run this API request
```
POST kbn:/api/fleet/agents/6a56f865-a611-4921-9f24-87757259223e/upgrade
  {
    "version": "8.12.1-SNAPSHOT"
  }
```
- verify that the API returns 200 

Relates #168502
  • Loading branch information
juliaElastic authored Jan 29, 2024
1 parent 0b4ecdb commit 92960c4
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 22 deletions.
13 changes: 13 additions & 0 deletions x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,16 @@ export function isAgentUpgrading(agent: Agent) {
}
return agent.upgrade_started_at && !agent.upgraded_at;
}

export const differsOnlyInPatch = (
versionA: string,
versionB: string,
allowEqualPatch: boolean = true
): boolean => {
const [majorA, minorA, patchA] = versionA.split('.');
const [majorB, minorB, patchB] = versionB.split('.');

return (
majorA === majorB && minorA === minorB && (allowEqualPatch ? patchA >= patchB : patchA > patchB)
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ import type { EuiComboBoxOptionOption } from '@elastic/eui';
import semverGt from 'semver/functions/gt';
import semverLt from 'semver/functions/lt';

import { AGENT_UPGRADE_COOLDOWN_IN_MIN } from '../../../../../../../common/services';
import {
AGENT_UPGRADE_COOLDOWN_IN_MIN,
differsOnlyInPatch,
} from '../../../../../../../common/services';

import { getMinVersion } from '../../../../../../../common/services/get_min_max_version';
import {
Expand All @@ -44,7 +47,6 @@ import {
useConfig,
sendGetAgentStatus,
useAgentVersion,
differsOnlyInPatch,
} from '../../../../hooks';

import { sendGetAgentsAvailableVersions } from '../../../../hooks';
Expand Down
15 changes: 2 additions & 13 deletions x-pack/plugins/fleet/public/hooks/use_agent_version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { useEffect, useState } from 'react';
import semverRcompare from 'semver/functions/rcompare';
import semverLt from 'semver/functions/lt';

import { differsOnlyInPatch } from '../../common/services';

import { useKibanaVersion } from './use_kibana_version';
import { sendGetAgentsAvailableVersions } from './use_request';

Expand Down Expand Up @@ -50,16 +52,3 @@ export const useAgentVersion = (): string | undefined => {

return agentVersion;
};

export const differsOnlyInPatch = (
versionA: string,
versionB: string,
allowEqualPatch: boolean = true
): boolean => {
const [majorA, minorA, patchA] = versionA.split('.');
const [majorB, minorB, patchB] = versionB.split('.');

return (
majorA === majorB && minorA === minorB && (allowEqualPatch ? patchA >= patchB : patchA > patchB)
);
};
22 changes: 20 additions & 2 deletions x-pack/plugins/fleet/server/routes/agent/upgrade_handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { checkKibanaVersion } from './upgrade_handler';
import { checkFleetServerVersion, checkKibanaVersion } from './upgrade_handler';

describe('upgrade handler', () => {
describe('checkKibanaVersion', () => {
Expand All @@ -15,7 +15,7 @@ describe('upgrade handler', () => {

it('should throw if upgrade version is higher than kibana version', () => {
expect(() => checkKibanaVersion('8.5.0', '8.4.0')).toThrowError(
'cannot upgrade agent to 8.5.0 because it is higher than the installed kibana version 8.4.0'
'Cannot upgrade agent to 8.5.0 because it is higher than the installed kibana version 8.4.0'
);
});

Expand All @@ -28,6 +28,11 @@ describe('upgrade handler', () => {
expect(() => checkKibanaVersion('8.4.1-SNAPSHOT', '8.4.0', true)).not.toThrowError();
});

it('should not throw if not force is specified and patch is newer', () => {
expect(() => checkKibanaVersion('8.4.1', '8.4.0', false)).not.toThrowError();
expect(() => checkKibanaVersion('8.4.1-SNAPSHOT', '8.4.0', false)).not.toThrowError();
});

it('should throw if force is specified and minor is newer', () => {
expect(() => checkKibanaVersion('8.5.0', '8.4.0', true)).toThrowError();
});
Expand All @@ -37,4 +42,17 @@ describe('upgrade handler', () => {
expect(() => checkKibanaVersion('8.4.0', '8.4.0', true)).not.toThrowError();
});
});

describe('checkFleetServerVersion', () => {
it('should not throw if no force is specified and patch is newer', () => {
const fleetServers = [
{ local_metadata: { elastic: { agent: { version: '8.3.0' } } } },
{ local_metadata: { elastic: { agent: { version: '8.4.0' } } } },
] as any;
expect(() => checkFleetServerVersion('8.4.1', fleetServers, false)).not.toThrowError();
expect(() =>
checkFleetServerVersion('8.4.1-SNAPSHOT', fleetServers, false)
).not.toThrowError();
});
});
});
17 changes: 13 additions & 4 deletions x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
isAgentUpgradeable,
AGENT_UPGRADE_COOLDOWN_IN_MIN,
isAgentUpgrading,
differsOnlyInPatch,
} from '../../../common/services';
import { getMaxVersion } from '../../../common/services/get_min_max_version';
import { getAgentById } from '../../services/agents';
Expand Down Expand Up @@ -192,9 +193,13 @@ export const checkKibanaVersion = (version: string, kibanaVersion: string, force
if (!versionToUpgradeNumber)
throw new Error(`version to upgrade ${versionToUpgradeNumber} is not valid`);

if (!force && semverGt(versionToUpgradeNumber, kibanaVersionNumber)) {
if (
!force &&
semverGt(versionToUpgradeNumber, kibanaVersionNumber) &&
!differsOnlyInPatch(versionToUpgradeNumber, kibanaVersionNumber)
) {
throw new Error(
`cannot upgrade agent to ${versionToUpgradeNumber} because it is higher than the installed kibana version ${kibanaVersionNumber}`
`Cannot upgrade agent to ${versionToUpgradeNumber} because it is higher than the installed kibana version ${kibanaVersionNumber}`
);
}

Expand All @@ -212,7 +217,7 @@ export const checkKibanaVersion = (version: string, kibanaVersion: string, force
};

// Check the installed fleet server version
const checkFleetServerVersion = (
export const checkFleetServerVersion = (
versionToUpgradeNumber: string,
fleetServerAgents: Agent[],
force = false
Expand All @@ -227,7 +232,11 @@ const checkFleetServerVersion = (
return;
}

if (!force && semverGt(versionToUpgradeNumber, maxFleetServerVersion)) {
if (
!force &&
semverGt(versionToUpgradeNumber, maxFleetServerVersion) &&
!differsOnlyInPatch(versionToUpgradeNumber, maxFleetServerVersion)
) {
throw new Error(
`cannot upgrade agent to ${versionToUpgradeNumber} because it is higher than the latest fleet server version ${maxFleetServerVersion}`
);
Expand Down
2 changes: 1 addition & 1 deletion x-pack/test/fleet_api_integration/apis/agents/upgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1226,7 +1226,7 @@ export default function (providerContext: FtrProviderContext) {
});

it('should respond 400 if trying to bulk upgrade to a version that is higher than the latest fleet server version', async () => {
const higherVersion = semver.inc(fleetServerVersion, 'patch');
const higherVersion = '7.17.0';
await es.update({
id: 'agent1',
refresh: 'wait_for',
Expand Down

0 comments on commit 92960c4

Please sign in to comment.