[Fleet] Display message explaining why agent is not upgradeable (#173253)

Closes https://github.com/elastic/kibana/issues/171840
Also implements the UI part of
https://github.com/elastic/kibana/issues/173281

## Summary
When trying to upgrade a single agent that is not upgradeable, the error
message doesn't specify _why_ the agent cannot be upgraded. This PR is
introducing:
- More granular error messages in the endpoint `POST
agent/{agent_id}/upgrade`. The messages are now different depending on
which conditions are met. For the case when the agent is reported not
upgradeable from elastic agent, there is now an error message the states
it explicitly.
- When clicking on the `upgrade 1 agent` from the bulk actions, if the
agent is not upgradeable the submit button is now greyed out and a
message explaining the reason is shown:
- 
![Screenshot 2023-12-18 at 14 41
48](8e0a03b4-c8fc-4a2e-aea6-77c7cc1acdf3)

The same warning appears when clicking on other upgrade actions in the
bulk action menu, but only for a single agent. Multiple upgrades have
not been changed.

- In the agents list, reuse the existing tooltip besides the version to
show the same messages when the agent is not upgradeable:
![Screenshot 2023-12-18 at 14 40
32](ada30bc0-8c58-40d9-b7cf-c5c7a81a75f7)




### Checklist
- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Cristina Amico 2023-12-19 12:36:21 +01:00 committed by GitHub
parent 8ff91980ca
commit 63f4e38f65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 392 additions and 41 deletions

View file

@ -11,6 +11,7 @@ import {
getRecentUpgradeInfoForAgent,
isAgentUpgradeable,
isAgentUpgrading,
getNotUpgradeableMessage,
} from './is_agent_upgradeable';
const getAgent = ({
@ -241,6 +242,154 @@ describe('Fleet - isAgentUpgradeable', () => {
});
});
describe('Fleet - getNotUpgradeableMessage', () => {
it('if agent reports not upgradeable with agent version < latest agent version', () => {
expect(getNotUpgradeableMessage(getAgent({ version: '7.9.0' }), '8.0.0')).toBe(
'agent cannot be upgraded through Fleet. It may be running in a container or it is not installed as a service.'
);
});
it('if agent reports not upgradeable with agent version > latest agent version', () => {
expect(getNotUpgradeableMessage(getAgent({ version: '8.0.0' }), '7.9.0')).toBe(
'agent cannot be upgraded through Fleet. It may be running in a container or it is not installed as a service.'
);
});
it('returns false if agent reports not upgradeable with agent version === latest agent version', () => {
expect(getNotUpgradeableMessage(getAgent({ version: '8.0.0' }), '8.0.0')).toBe(
'agent cannot be upgraded through Fleet. It may be running in a container or it is not installed as a service.'
);
});
it('if agent reports upgradeable, with agent version === latest agent version', () => {
expect(
getNotUpgradeableMessage(getAgent({ version: '8.0.0', upgradeable: true }), '8.0.0')
).toBe('agent is already running on the latest available version.');
});
it('if agent reports upgradeable, with agent version > latest agent version', () => {
expect(
getNotUpgradeableMessage(getAgent({ version: '8.0.0', upgradeable: true }), '7.9.0')
).toBe('agent is running on a version greater than the latest available version.');
});
it('if agent reports upgradeable, but agent is unenrolling', () => {
expect(
getNotUpgradeableMessage(
getAgent({ version: '7.9.0', upgradeable: true, unenrolling: true }),
'8.0.0'
)
).toBe('agent is being unenrolled.');
});
it('if agent reports upgradeable, but agent is unenrolled', () => {
expect(
getNotUpgradeableMessage(
getAgent({ version: '7.9.0', upgradeable: true, unenrolled: true }),
'8.0.0'
)
).toBe('agent has been unenrolled.');
});
it('Returns no error message if agent reports upgradeable, with agent version < latest agent version', () => {
expect(
getNotUpgradeableMessage(getAgent({ version: '7.9.0', upgradeable: true }), '8.0.0')
).toBeUndefined();
});
it('if agent reports upgradeable, with agent snapshot version === latest agent version', () => {
expect(
getNotUpgradeableMessage(getAgent({ version: '7.9.0-SNAPSHOT', upgradeable: true }), '7.9.0')
).toBe('agent is already running on the latest available version.');
});
it('it does not return message if agent reports upgradeable, with upgrade to agent snapshot version newer than latest agent version', () => {
expect(
getNotUpgradeableMessage(
getAgent({ version: '8.10.2', upgradeable: true }),
'8.10.2',
'8.11.0-SNAPSHOT'
)
).toBeUndefined();
});
it('if agent reports upgradeable, with target version < current agent version ', () => {
expect(
getNotUpgradeableMessage(getAgent({ version: '7.9.0', upgradeable: true }), '8.0.0', '7.8.0')
).toBe('agent does not support downgrades.');
});
it('if agent reports upgradeable, with target version == current agent version ', () => {
expect(
getNotUpgradeableMessage(getAgent({ version: '7.9.0', upgradeable: true }), '8.0.0', '7.9.0')
).toBe('agent is already running on the selected version.');
});
it('if agent with no upgrade details reports upgradeable, but is already upgrading', () => {
expect(
getNotUpgradeableMessage(
getAgent({ version: '7.9.0', upgradeable: true, upgrading: true }),
'8.0.0'
)
).toBe('agent is already being upgraded.');
});
it('if agent reports upgradeable, but has an upgrade status other than failed', () => {
expect(
getNotUpgradeableMessage(
getAgent({
version: '7.9.0',
upgradeable: true,
upgradeDetails: {
target_version: '8.0.0',
action_id: 'XXX',
state: 'UPG_REQUESTED',
},
}),
'8.0.0'
)
).toBe('agent is already being upgraded.');
});
it('it does not return a message if agent reports upgradeable and has a failed upgrade status', () => {
expect(
getNotUpgradeableMessage(
getAgent({
version: '7.9.0',
upgradeable: true,
upgradeDetails: {
target_version: '8.0.0',
action_id: 'XXX',
state: 'UPG_FAILED',
metadata: {
error_msg: 'Upgrade timed out',
},
},
}),
'8.0.0'
)
).toBeUndefined();
});
it('if the agent reports upgradeable but was upgraded less than 10 minutes ago', () => {
expect(
getNotUpgradeableMessage(
getAgent({ version: '7.9.0', upgradeable: true, minutesSinceUpgrade: 9 }),
'8.0.0'
)
).toContain('please wait');
});
it('if agent reports upgradeable and was upgraded more than 10 minutes ago', () => {
expect(
getNotUpgradeableMessage(
getAgent({ version: '7.9.0', upgradeable: true, minutesSinceUpgrade: 11 }),
'8.0.0'
)
).toBeUndefined();
});
});
describe('hasAgentBeenUpgradedRecently', () => {
it('returns true if the agent was upgraded less than 10 minutes ago', () => {
expect(

View file

@ -8,11 +8,27 @@
import semverCoerce from 'semver/functions/coerce';
import semverLt from 'semver/functions/lt';
import semverGt from 'semver/functions/gt';
import semverEq from 'semver/functions/eq';
import moment from 'moment';
import type { Agent } from '../types';
export const AGENT_UPGRADE_COOLDOWN_IN_MIN = 10;
// Error messages for agent not upgradeable
export const VERSION_MISSING_ERROR = `agent version is missing.`;
export const UNENROLLED_ERROR = `agent has been unenrolled.`;
export const ONGOING_UNEROLLMENT_ERROR = `agent is being unenrolled.`;
export const NOT_UPGRADEABLE_ERROR = `agent cannot be upgraded through Fleet. It may be running in a container or it is not installed as a service.`;
export const ALREADY_UPGRADED_ERROR = `agent is already being upgraded.`;
export const INVALID_VERSION_ERROR = 'agent version is not valid.';
export const SELECTED_VERSION_ERROR = 'the selected version is not valid.';
export const RUNNING_SELECTED_VERSION_ERROR = `agent is already running on the selected version.`;
export const DOWNGRADE_NOT_ALLOWED_ERROR = `agent does not support downgrades.`;
export const LATEST_VERSION_NOT_VALID_ERROR = 'latest version is not valid.';
export const AGENT_ALREADY_ON_LATEST_ERROR = `agent is already running on the latest available version.`;
export const AGENT_ON_GREATER_VERSION_ERROR = `agent is running on a version greater than the latest available version.`;
export function isAgentUpgradeable(
agent: Agent,
latestAgentVersion: string,
@ -42,21 +58,76 @@ export function isAgentUpgradeable(
return isAgentVersionLessThanLatest(agentVersion, latestAgentVersion);
}
// Based on the previous, returns a detailed message explaining why the agent is not upgradeable
export const getNotUpgradeableMessage = (
agent: Agent,
latestAgentVersion?: string,
versionToUpgrade?: string
) => {
let agentVersion: string;
if (typeof agent?.local_metadata?.elastic?.agent?.version === 'string') {
agentVersion = agent.local_metadata.elastic.agent.version;
} else {
return VERSION_MISSING_ERROR;
}
if (agent.unenrolled_at) {
return UNENROLLED_ERROR;
}
if (agent.unenrollment_started_at) {
return ONGOING_UNEROLLMENT_ERROR;
}
if (!agent.local_metadata.elastic.agent.upgradeable) {
return NOT_UPGRADEABLE_ERROR;
}
if (isAgentUpgrading(agent)) {
return ALREADY_UPGRADED_ERROR;
}
if (getRecentUpgradeInfoForAgent(agent).hasBeenUpgradedRecently) {
const timeToWaitMins = getRecentUpgradeInfoForAgent(agent).timeToWaitMins;
const elapsedMinsSinceUpgrade = getRecentUpgradeInfoForAgent(agent).elapsedMinsSinceUpgrade;
return `agent was upgraded ${elapsedMinsSinceUpgrade} minutes ago, please wait ${timeToWaitMins} minutes before attempting the upgrade again.`;
}
const agentVersionNumber = semverCoerce(agentVersion);
if (!agentVersionNumber) return INVALID_VERSION_ERROR;
if (versionToUpgrade !== undefined) {
const versionToUpgradeNumber = semverCoerce(versionToUpgrade);
if (!versionToUpgradeNumber) return SELECTED_VERSION_ERROR;
if (semverEq(agentVersionNumber, versionToUpgradeNumber)) return RUNNING_SELECTED_VERSION_ERROR;
if (semverLt(versionToUpgradeNumber, agentVersionNumber)) return DOWNGRADE_NOT_ALLOWED_ERROR;
// explicitly allow this case - the agent is upgradeable
if (semverGt(versionToUpgradeNumber, agentVersionNumber)) return undefined;
}
const latestAgentVersionNumber = semverCoerce(latestAgentVersion);
if (!latestAgentVersionNumber) return LATEST_VERSION_NOT_VALID_ERROR;
if (semverEq(agentVersionNumber, latestAgentVersionNumber)) return AGENT_ALREADY_ON_LATEST_ERROR;
if (semverGt(agentVersionNumber, latestAgentVersionNumber)) return AGENT_ON_GREATER_VERSION_ERROR;
// in all the other cases, the agent is upgradeable; don't return any message.
return undefined;
};
const isAgentVersionLessThanLatest = (agentVersion: string, latestAgentVersion: string) => {
// make sure versions are only the number before comparison
const agentVersionNumber = semverCoerce(agentVersion);
if (!agentVersionNumber) throw new Error('agent version is not valid');
if (!agentVersionNumber) throw new Error(`${INVALID_VERSION_ERROR}`);
const latestAgentVersionNumber = semverCoerce(latestAgentVersion);
if (!latestAgentVersionNumber) throw new Error('latest version is not valid');
if (!latestAgentVersionNumber) throw new Error(`${LATEST_VERSION_NOT_VALID_ERROR}`);
return semverLt(agentVersionNumber, latestAgentVersionNumber);
};
const isNotDowngrade = (agentVersion: string, versionToUpgrade: string) => {
const agentVersionNumber = semverCoerce(agentVersion);
if (!agentVersionNumber) throw new Error('agent version is not valid');
if (!agentVersionNumber) throw new Error(`${INVALID_VERSION_ERROR}`);
const versionToUpgradeNumber = semverCoerce(versionToUpgrade);
if (!versionToUpgradeNumber) throw new Error('target version is not valid');
if (!versionToUpgradeNumber) throw new Error(`${SELECTED_VERSION_ERROR}`);
return semverGt(versionToUpgradeNumber, agentVersionNumber);
};
@ -64,19 +135,27 @@ const isNotDowngrade = (agentVersion: string, versionToUpgrade: string) => {
export function getRecentUpgradeInfoForAgent(agent: Agent): {
hasBeenUpgradedRecently: boolean;
timeToWaitMs: number;
elapsedMinsSinceUpgrade: number;
timeToWaitMins: number;
} {
if (!agent.upgraded_at) {
return {
hasBeenUpgradedRecently: false,
timeToWaitMs: 0,
timeToWaitMins: 0,
elapsedMinsSinceUpgrade: 0,
};
}
const elaspedSinceUpgradeInMillis = Date.now() - Date.parse(agent.upgraded_at);
const timeToWaitMs = AGENT_UPGRADE_COOLDOWN_IN_MIN * 6e4 - elaspedSinceUpgradeInMillis;
const hasBeenUpgradedRecently = elaspedSinceUpgradeInMillis / 6e4 < AGENT_UPGRADE_COOLDOWN_IN_MIN;
const elapsedSinceUpgradeInMillis = Date.now() - Date.parse(agent.upgraded_at);
const elapsedMins = moment.duration(elapsedSinceUpgradeInMillis, 'milliseconds').asMinutes();
const elapsedMinsSinceUpgrade = Math.ceil(elapsedMins);
return { hasBeenUpgradedRecently, timeToWaitMs };
const timeToWaitMs = AGENT_UPGRADE_COOLDOWN_IN_MIN * 6e4 - elapsedSinceUpgradeInMillis;
const hasBeenUpgradedRecently = elapsedSinceUpgradeInMillis / 6e4 < AGENT_UPGRADE_COOLDOWN_IN_MIN;
const timeToWait = moment.duration(timeToWaitMs, 'milliseconds').asMinutes();
const timeToWaitMins = Math.ceil(timeToWait);
return { hasBeenUpgradedRecently, timeToWaitMs, elapsedMinsSinceUpgrade, timeToWaitMins };
}
export function isAgentUpgrading(agent: Agent) {

View file

@ -31,6 +31,8 @@ import { Tags } from '../../components/tags';
import type { AgentMetrics } from '../../../../../../../common/types';
import { formatAgentCPU, formatAgentMemory } from '../../services/agent_metrics';
import { getNotUpgradeableMessage } from '../../../../../../../common/services/is_agent_upgradeable';
import { AgentUpgradeStatus } from './agent_upgrade_status';
import { EmptyPrompt } from './empty_prompt';
@ -303,6 +305,7 @@ export const AgentListTable: React.FC<Props> = (props: Props) => {
agentUpgradeStartedAt={agent.upgrade_started_at}
agentUpgradedAt={agent.upgraded_at}
agentUpgradeDetails={agent.upgrade_details}
notUpgradeableMessage={getNotUpgradeableMessage(agent, latestAgentVersion)}
/>
</EuiFlexItem>
</EuiFlexGroup>

View file

@ -219,7 +219,14 @@ export const AgentUpgradeStatus: React.FC<{
agentUpgradeStartedAt?: string | null;
agentUpgradedAt?: string | null;
agentUpgradeDetails?: AgentUpgradeDetails;
}> = ({ isAgentUpgradable, agentUpgradeStartedAt, agentUpgradedAt, agentUpgradeDetails }) => {
notUpgradeableMessage?: string | null;
}> = ({
isAgentUpgradable,
agentUpgradeStartedAt,
agentUpgradedAt,
agentUpgradeDetails,
notUpgradeableMessage,
}) => {
const isAgentUpgrading = useMemo(
() => agentUpgradeStartedAt && !agentUpgradedAt,
[agentUpgradeStartedAt, agentUpgradedAt]
@ -227,6 +234,24 @@ export const AgentUpgradeStatus: React.FC<{
const status = useMemo(() => getStatusComponents(agentUpgradeDetails), [agentUpgradeDetails]);
const minVersion = '8.12';
if (!isAgentUpgradable && notUpgradeableMessage) {
return (
<EuiIconTip
type="iInCircle"
content={
<FormattedMessage
id="xpack.fleet.agentUpgradeStatusBadge.notUpgradeable"
defaultMessage="Agent not upgradeable: {reason}"
values={{
reason: notUpgradeableMessage,
}}
/>
}
color="subdued"
/>
);
}
if (isAgentUpgradable) {
return (
<EuiBadge color="hollow" iconType="sortUp">

View file

@ -29,6 +29,7 @@ jest.mock('../../../../hooks', () => {
}),
sendPostBulkAgentUpgrade: jest.fn(),
useAgentVersion: jest.fn().mockReturnValue('8.10.2'),
useKibanaVersion: jest.fn().mockReturnValue('8.10.2'),
};
});
@ -203,4 +204,28 @@ describe('AgentUpgradeAgentModal', () => {
expect(el).toBeDisabled();
});
});
it('should disable submit button and display a warning for a single agent that is not upgradeable', async () => {
const { utils } = renderAgentUpgradeAgentModal({
agents: [
{
status: 'offline',
upgrade_started_at: '2022-11-21T12:27:24Z',
id: 'agent1',
local_metadata: { elastic: { agent: { version: '8.9.0' } } },
},
] as any,
agentCount: 2,
});
await waitFor(() => {
expect(utils.queryByText(/The selected agent is not upgradeable/)).toBeInTheDocument();
expect(
utils.queryByText(
/Reason: agent cannot be upgraded through Fleet. It may be running in a container or it is not installed as a service./
)
).toBeInTheDocument();
const el = utils.getByTestId('confirmModalConfirmButton');
expect(el).toBeDisabled();
});
});
});

View file

@ -48,6 +48,10 @@ import {
} from '../../../../hooks';
import { sendGetAgentsAvailableVersions } from '../../../../hooks';
import {
isAgentUpgradeable,
getNotUpgradeableMessage,
} from '../../../../../../../common/services/is_agent_upgradeable';
import {
FALLBACK_VERSIONS,
@ -127,7 +131,6 @@ export const AgentUpgradeAgentModal: React.FunctionComponent<AgentUpgradeAgentMo
return;
}
};
if (!isUpdating) return;
getStuckUpdatingAgentCount(agents);
@ -238,7 +241,9 @@ export const AgentUpgradeAgentModal: React.FunctionComponent<AgentUpgradeAgentMo
const getQuery = (agentsOrQuery: Agent[] | string) =>
Array.isArray(agentsOrQuery) ? agentsOrQuery.map((agent) => agent.id) : agentsOrQuery;
const { error } =
isSingleAgent && !isScheduled
isSingleAgent &&
!isScheduled &&
isAgentUpgradeable(agents[0], latestAgentVersion || '', selectedVersion[0].value)
? await sendPostAgentUpgrade((agents[0] as Agent).id, {
version,
force: isUpdating,
@ -332,7 +337,13 @@ export const AgentUpgradeAgentModal: React.FunctionComponent<AgentUpgradeAgentMo
defaultMessage="Cancel"
/>
}
confirmButtonDisabled={isSubmitting || noVersions || (isUpdating && updatingAgents === 0)}
confirmButtonDisabled={
isSubmitting ||
noVersions ||
(isUpdating && updatingAgents === 0) ||
(isSingleAgent &&
!isAgentUpgradeable(agents[0], latestAgentVersion || '', selectedVersion[0].value))
}
confirmButtonText={
isSingleAgent ? (
<FormattedMessage
@ -366,32 +377,58 @@ export const AgentUpgradeAgentModal: React.FunctionComponent<AgentUpgradeAgentMo
defaultMessage="No selected agents are eligible for an upgrade. Please select one or more eligible agents."
/>
) : isSingleAgent ? (
<>
<p>
!isAgentUpgradeable(agents[0], latestAgentVersion || '', selectedVersion[0].value) ? (
<EuiCallOut
data-test-subj="agentUpgradeModal.notUpgradeableCallout"
color="warning"
iconType="warning"
title={
<FormattedMessage
id="xpack.fleet.upgradeAgents.notUpgradeable"
defaultMessage="The selected agent is not upgradeable."
/>
}
>
<FormattedMessage
id="xpack.fleet.upgradeAgents.upgradeSingleDescription"
defaultMessage="This action will upgrade the agent running on '{hostName}' to version {version}. This action can not be undone. Are you sure you wish to continue?"
id="xpack.fleet.upgradeAgents.notUpgradeableMsg"
defaultMessage="Reason: {reason}"
values={{
hostName: ((agents[0] as Agent).local_metadata.host as any).hostname,
version: getVersion(selectedVersion),
reason: getNotUpgradeableMessage(
agents[0],
latestAgentVersion,
selectedVersion[0].value
),
}}
/>
</p>
{isUpdating && (
</EuiCallOut>
) : (
<>
<p>
<em>
<FormattedMessage
id="xpack.fleet.upgradeAgents.upgradeSingleTimeout"
// TODO: Add link to docs regarding agent upgrade cooldowns
defaultMessage="Note that you may only restart an upgrade every {minutes} minutes to ensure that the upgrade will not be rolled back."
values={{
minutes: AGENT_UPGRADE_COOLDOWN_IN_MIN,
}}
/>
</em>
<FormattedMessage
id="xpack.fleet.upgradeAgents.upgradeSingleDescription"
defaultMessage="This action will upgrade the agent running on '{hostName}' to version {version}. This action can not be undone. Are you sure you wish to continue?"
values={{
hostName: ((agents[0] as Agent).local_metadata.host as any).hostname,
version: getVersion(selectedVersion),
}}
/>
</p>
)}
</>
{isUpdating && (
<p>
<em>
<FormattedMessage
id="xpack.fleet.upgradeAgents.upgradeSingleTimeout"
// TODO: Add link to docs regarding agent upgrade cooldowns
defaultMessage="Note that you may only restart an upgrade every {minutes} minutes to ensure that the upgrade will not be rolled back."
values={{
minutes: AGENT_UPGRADE_COOLDOWN_IN_MIN,
}}
/>
</em>
</p>
)}
</>
)
) : (
<FormattedMessage
id="xpack.fleet.upgradeAgents.upgradeMultipleDescription"
@ -520,7 +557,15 @@ export const AgentUpgradeAgentModal: React.FunctionComponent<AgentUpgradeAgentMo
'Error upgrading the selected {count, plural, one {agent} other {{count} agents}}',
values: { count: isSingleAgent },
})}
/>
>
<FormattedMessage
id="xpack.fleet.upgradeAgents.warningCalloutErrorMessage"
defaultMessage="{originalMessage}"
values={{
originalMessage: errors,
}}
/>
</EuiCallOut>
</>
) : null}
</EuiConfirmModal>

View file

@ -25,6 +25,7 @@ import {
isAgentUpgradeable,
AGENT_UPGRADE_COOLDOWN_IN_MIN,
isAgentUpgrading,
getNotUpgradeableMessage,
} from '../../../common/services';
import { getMaxVersion } from '../../../common/services/get_min_max_version';
import { getAgentById } from '../../services/agents';
@ -114,7 +115,11 @@ export const postAgentUpgradeHandler: RequestHandler<
return response.customError({
statusCode: 400,
body: {
message: `agent ${request.params.agentId} is not upgradeable`,
message: `Agent ${request.params.agentId} is not upgradeable: ${getNotUpgradeableMessage(
agent,
latestAgentVersion,
version
)}`,
},
});
}

View file

@ -10,7 +10,11 @@ import type { SavedObjectsClientContract, ElasticsearchClient } from '@kbn/core/
import { v4 as uuidv4 } from 'uuid';
import moment from 'moment';
import { getRecentUpgradeInfoForAgent, isAgentUpgradeable } from '../../../common/services';
import {
getRecentUpgradeInfoForAgent,
isAgentUpgradeable,
getNotUpgradeableMessage,
} from '../../../common/services';
import type { Agent } from '../../types';
@ -86,7 +90,13 @@ export async function upgradeBatch(
getRecentUpgradeInfoForAgent(agent).hasBeenUpgradedRecently ||
(!options.force && !isAgentUpgradeable(agent, latestAgentVersion, options.version));
if (isNotAllowed) {
throw new FleetError(`Agent ${agent.id} is not upgradeable`);
throw new FleetError(
`Agent ${agent.id} is not upgradeable: ${getNotUpgradeableMessage(
agent,
latestAgentVersion,
options.version
)}`
);
}
if (!options.force && isHostedAgent(hostedPolicies, agent)) {

View file

@ -141,13 +141,16 @@ export default function (providerContext: FtrProviderContext) {
},
},
});
await supertest
const res = await supertest
.post(`/api/fleet/agents/agent1/upgrade`)
.set('kbn-xsrf', 'xxx')
.send({
version: fleetServerVersionSnapshot,
})
.expect(400);
expect(res.body.message).to.equal(
'Agent agent1 is not upgradeable: agent is already running on the selected version.'
);
});
it('should respond 200 if upgrading agent with version the same as snapshot version and force flag is passed', async () => {
@ -248,26 +251,30 @@ export default function (providerContext: FtrProviderContext) {
},
},
});
await supertest
const res = await supertest
.post(`/api/fleet/agents/agent1/upgrade`)
.set('kbn-xsrf', 'xxx')
.send({
version: '6.0.0',
})
.expect(400);
expect(res.body.message).to.equal(
'Agent agent1 is not upgradeable: agent does not support downgrades.'
);
});
it('should respond 400 if trying to upgrade an agent that is unenrolling', async () => {
await supertest.post(`/api/fleet/agents/agent1/unenroll`).set('kbn-xsrf', 'xxx').send({
revoke: true,
});
await supertest
const res = await supertest
.post(`/api/fleet/agents/agent1/upgrade`)
.set('kbn-xsrf', 'xxx')
.send({
version: fleetServerVersion,
})
.expect(400);
expect(res.body.message).to.equal('cannot upgrade an unenrolling or unenrolled agent');
});
it('should respond 400 if trying to upgrade an agent that is unenrolled', async () => {
@ -281,13 +288,14 @@ export default function (providerContext: FtrProviderContext) {
},
},
});
await supertest
const res = await supertest
.post(`/api/fleet/agents/agent1/upgrade`)
.set('kbn-xsrf', 'xxx')
.send({
version: fleetServerVersion,
})
.expect(400);
expect(res.body.message).to.equal('cannot upgrade an unenrolling or unenrolled agent');
});
it('should respond 400 if trying to upgrade an agent that is not upgradeable', async () => {
@ -298,7 +306,9 @@ export default function (providerContext: FtrProviderContext) {
version: fleetServerVersion,
})
.expect(400);
expect(res.body.message).to.equal('agent agent1 is not upgradeable');
expect(res.body.message).to.equal(
'Agent agent1 is not upgradeable: agent cannot be upgraded through Fleet. It may be running in a container or it is not installed as a service.'
);
});
it('enrolled in a hosted agent policy should respond 400 to upgrade and not update the agent SOs', async () => {