diff --git a/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts b/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts index 279018ef4212..b8af26588309 100644 --- a/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts +++ b/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts @@ -92,21 +92,14 @@ export const postBulkAgentsUpgradeHandler: RequestHandler< } try { - if (Array.isArray(agents)) { - await AgentService.sendUpgradeAgentsActions(soClient, esClient, { - agentIds: agents, - sourceUri, - version, - force, - }); - } else { - await AgentService.sendUpgradeAgentsActions(soClient, esClient, { - kuery: agents, - sourceUri, - version, - force, - }); - } + const agentOptions = Array.isArray(agents) ? { agentIds: agents } : { kuery: agents }; + const upgradeOptions = { + ...agentOptions, + sourceUri, + version, + force, + }; + await AgentService.sendUpgradeAgentsActions(soClient, esClient, upgradeOptions); const body: PostBulkAgentUpgradeResponse = {}; return response.ok({ body }); diff --git a/x-pack/plugins/fleet/server/services/agents/upgrade.ts b/x-pack/plugins/fleet/server/services/agents/upgrade.ts index 12623be0ed04..6c3b404a5b6f 100644 --- a/x-pack/plugins/fleet/server/services/agents/upgrade.ts +++ b/x-pack/plugins/fleet/server/services/agents/upgrade.ts @@ -83,32 +83,33 @@ export async function sendUpgradeAgentsActions( force?: boolean; } ) { - const kibanaVersion = appContextService.getKibanaVersion(); - // Filter out agents currently unenrolling, agents unenrolled, and agents not upgradeable - const agents = await getAgents(esClient, options); + // Full set of agents + const agentsGiven = await getAgents(esClient, options); - // upgradeable if they pass the version check + // Filter out agents currently unenrolling, unenrolled, or not upgradeable b/c of version check + const kibanaVersion = appContextService.getKibanaVersion(); const upgradeableAgents = options.force - ? agents - : agents.filter((agent) => isAgentUpgradeable(agent, kibanaVersion)); + ? agentsGiven + : agentsGiven.filter((agent) => isAgentUpgradeable(agent, kibanaVersion)); - // get any policy ids from upgradable agents - const policyIdsToGet = new Set( - upgradeableAgents.filter((agent) => agent.policy_id).map((agent) => agent.policy_id!) - ); + if (!options.force) { + // get any policy ids from upgradable agents + const policyIdsToGet = new Set( + upgradeableAgents.filter((agent) => agent.policy_id).map((agent) => agent.policy_id!) + ); - // get the agent policies for those ids - const agentPolicies = await agentPolicyService.getByIDs(soClient, Array.from(policyIdsToGet), { - fields: ['is_managed'], - }); + // get the agent policies for those ids + const agentPolicies = await agentPolicyService.getByIDs(soClient, Array.from(policyIdsToGet), { + fields: ['is_managed'], + }); - // throw if any of those agent policies are managed - for (const policy of agentPolicies) { - if (policy.is_managed) { - throw new IngestManagerError(`Cannot upgrade agent in managed policy ${policy.id}`); + // throw if any of those agent policies are managed + for (const policy of agentPolicies) { + if (policy.is_managed) { + throw new IngestManagerError(`Cannot upgrade agent in managed policy ${policy.id}`); + } } } - // Create upgrade action for each agent const now = new Date().toISOString(); const data = { diff --git a/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts b/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts index 9f2280ed9613..9a747fb11a6a 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts @@ -23,7 +23,7 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); - describe('fleet upgrade agent', () => { + describe('fleet upgrade', () => { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.loadIfNeeded('fleet/agents'); @@ -36,478 +36,511 @@ export default function (providerContext: FtrProviderContext) { await esArchiver.unload('fleet/agents'); }); - it('should respond 200 to upgrade agent and update the agent SO', async () => { - const kibanaVersion = await kibanaServer.version.get(); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + describe('one agent', () => { + it('should respond 200 to upgrade agent and update the agent SO', async () => { + const kibanaVersion = await kibanaServer.version.get(); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, }, - }, - }); - await supertest - .post(`/api/fleet/agents/agent1/upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - version: kibanaVersion, - source_uri: 'http://path/to/download', - }) - .expect(200); + }); + await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: kibanaVersion, + source_uri: 'http://path/to/download', + }) + .expect(200); - const res = await supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'); - expect(typeof res.body.item.upgrade_started_at).to.be('string'); - }); - it('should respond 400 if upgrading agent with version the same as snapshot version', async () => { - const kibanaVersion = await kibanaServer.version.get(); - const kibanaVersionSnapshot = makeSnapshotVersion(kibanaVersion); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: kibanaVersion } } }, + const res = await supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'); + expect(typeof res.body.item.upgrade_started_at).to.be('string'); + }); + it('should respond 400 if upgrading agent with version the same as snapshot version', async () => { + const kibanaVersion = await kibanaServer.version.get(); + const kibanaVersionSnapshot = makeSnapshotVersion(kibanaVersion); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: kibanaVersion } } }, + }, }, - }, + }); + await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: kibanaVersionSnapshot, + }) + .expect(400); }); - await supertest - .post(`/api/fleet/agents/agent1/upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - version: kibanaVersionSnapshot, - }) - .expect(400); - }); - it('should respond 200 if upgrading agent with version the same as snapshot version and force flag is passed', async () => { - const kibanaVersion = await kibanaServer.version.get(); - const kibanaVersionSnapshot = makeSnapshotVersion(kibanaVersion); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: kibanaVersion } } }, + it('should respond 200 if upgrading agent with version the same as snapshot version and force flag is passed', async () => { + const kibanaVersion = await kibanaServer.version.get(); + const kibanaVersionSnapshot = makeSnapshotVersion(kibanaVersion); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: kibanaVersion } } }, + }, }, - }, + }); + await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: kibanaVersionSnapshot, + force: true, + }) + .expect(200); }); - await supertest - .post(`/api/fleet/agents/agent1/upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - version: kibanaVersionSnapshot, - force: true, - }) - .expect(200); - }); - it('should respond 200 if upgrading agent with version less than kibana snapshot version', async () => { - const kibanaVersion = await kibanaServer.version.get(); - const kibanaVersionSnapshot = makeSnapshotVersion(kibanaVersion); + it('should respond 200 if upgrading agent with version less than kibana snapshot version', async () => { + const kibanaVersion = await kibanaServer.version.get(); + const kibanaVersionSnapshot = makeSnapshotVersion(kibanaVersion); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, }, - }, + }); + await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: kibanaVersionSnapshot, + }) + .expect(200); }); - await supertest - .post(`/api/fleet/agents/agent1/upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - version: kibanaVersionSnapshot, - }) - .expect(200); - }); - it('should respond 200 to upgrade agent and update the agent SO without source_uri', async () => { - const kibanaVersion = await kibanaServer.version.get(); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + it('should respond 200 to upgrade agent and update the agent SO without source_uri', async () => { + const kibanaVersion = await kibanaServer.version.get(); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, }, - }, + }); + await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: kibanaVersion, + }) + .expect(200); + const res = await supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'); + expect(typeof res.body.item.upgrade_started_at).to.be('string'); }); - await supertest - .post(`/api/fleet/agents/agent1/upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - version: kibanaVersion, - }) - .expect(200); - const res = await supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'); - expect(typeof res.body.item.upgrade_started_at).to.be('string'); - }); - it('should respond 400 if trying to upgrade to a version that does not match installed kibana version', async () => { - const kibanaVersion = await kibanaServer.version.get(); - const higherVersion = semver.inc(kibanaVersion, 'patch'); - await supertest - .post(`/api/fleet/agents/agent1/upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - version: higherVersion, - source_uri: 'http://path/to/download', - }) - .expect(400); - }); - it('should respond 400 if trying to upgrade an agent that is unenrolling', async () => { - const kibanaVersion = await kibanaServer.version.get(); - await supertest.post(`/api/fleet/agents/agent1/unenroll`).set('kbn-xsrf', 'xxx').send({ - force: true, + it('should respond 400 if trying to upgrade to a version that does not match installed kibana version', async () => { + const kibanaVersion = await kibanaServer.version.get(); + const higherVersion = semver.inc(kibanaVersion, 'patch'); + await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: higherVersion, + source_uri: 'http://path/to/download', + }) + .expect(400); }); - await supertest - .post(`/api/fleet/agents/agent1/upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - version: kibanaVersion, - }) - .expect(400); - }); - it('should respond 400 if trying to upgrade an agent that is unenrolled', async () => { - const kibanaVersion = await kibanaServer.version.get(); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - unenrolled_at: new Date().toISOString(), + it('should respond 400 if trying to upgrade an agent that is unenrolling', async () => { + const kibanaVersion = await kibanaServer.version.get(); + await supertest.post(`/api/fleet/agents/agent1/unenroll`).set('kbn-xsrf', 'xxx').send({ + force: true, + }); + await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: kibanaVersion, + }) + .expect(400); + }); + it('should respond 400 if trying to upgrade an agent that is unenrolled', async () => { + const kibanaVersion = await kibanaServer.version.get(); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + unenrolled_at: new Date().toISOString(), + }, }, - }, + }); + await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: kibanaVersion, + }) + .expect(400); }); - await supertest - .post(`/api/fleet/agents/agent1/upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - version: kibanaVersion, - }) - .expect(400); - }); - it('should respond 400 if trying to upgrade an agent that is not upgradeable', async () => { - const kibanaVersion = await kibanaServer.version.get(); - const res = await supertest - .post(`/api/fleet/agents/agent1/upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - version: kibanaVersion, - }) - .expect(400); - expect(res.body.message).to.equal('agent agent1 is not upgradeable'); - }); + it('should respond 400 if trying to upgrade an agent that is not upgradeable', async () => { + const kibanaVersion = await kibanaServer.version.get(); + const res = await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: kibanaVersion, + }) + .expect(400); + expect(res.body.message).to.equal('agent agent1 is not upgradeable'); + }); - it('should respond 200 to bulk upgrade upgradeable agents and update the agent SOs', async () => { - const kibanaVersion = await kibanaServer.version.get(); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + it('enrolled in a managed policy should respond 400 to upgrade and not update the agent SOs', async () => { + // update enrolled policy to managed + await supertest.put(`/api/fleet/agent_policies/policy1`).set('kbn-xsrf', 'xxxx').send({ + name: 'Test policy', + namespace: 'default', + is_managed: true, + }); + + const kibanaVersion = await kibanaServer.version.get(); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, }, - }, + }); + // attempt to upgrade agent in managed policy + const { body } = await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ version: kibanaVersion }) + .expect(400); + expect(body.message).to.contain('Cannot upgrade agent agent1 in managed policy policy1'); + + const agent1data = await supertest.get(`/api/fleet/agents/agent1`); + expect(typeof agent1data.body.item.upgrade_started_at).to.be('undefined'); }); - await es.update({ - id: 'agent2', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { - elastic: { - agent: { upgradeable: true, version: semver.inc(kibanaVersion, 'patch') }, + }); + + describe('multiple agents', () => { + it('should respond 200 to bulk upgrade upgradeable agents and update the agent SOs', async () => { + const kibanaVersion = await kibanaServer.version.get(); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, + }, + }); + await es.update({ + id: 'agent2', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { + elastic: { + agent: { upgradeable: true, version: semver.inc(kibanaVersion, 'patch') }, + }, }, }, }, - }, - }); - await supertest - .post(`/api/fleet/agents/bulk_upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - version: kibanaVersion, - agents: ['agent1', 'agent2'], - }) - .expect(200); + }); + await supertest + .post(`/api/fleet/agents/bulk_upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: kibanaVersion, + agents: ['agent1', 'agent2'], + }) + .expect(200); - const [agent1data, agent2data] = await Promise.all([ - supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), - supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), - ]); - expect(typeof agent1data.body.item.upgrade_started_at).to.be('string'); - expect(typeof agent2data.body.item.upgrade_started_at).to.be('undefined'); - }); + const [agent1data, agent2data] = await Promise.all([ + supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), + supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), + ]); + expect(typeof agent1data.body.item.upgrade_started_at).to.be('string'); + expect(typeof agent2data.body.item.upgrade_started_at).to.be('undefined'); + }); - it('should allow to upgrade multiple upgradeable agents by kuery', async () => { - const kibanaVersion = await kibanaServer.version.get(); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + it('should allow to upgrade multiple upgradeable agents by kuery', async () => { + const kibanaVersion = await kibanaServer.version.get(); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, }, - }, - }); - await es.update({ - id: 'agent2', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { - elastic: { - agent: { upgradeable: true, version: semver.inc(kibanaVersion, 'patch') }, + }); + await es.update({ + id: 'agent2', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { + elastic: { + agent: { upgradeable: true, version: semver.inc(kibanaVersion, 'patch') }, + }, }, }, }, - }, + }); + await supertest + .post(`/api/fleet/agents/bulk_upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + agents: 'active:true', + version: kibanaVersion, + }) + .expect(200); + const [agent1data, agent2data] = await Promise.all([ + supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), + supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), + ]); + expect(typeof agent1data.body.item.upgrade_started_at).to.be('string'); + expect(typeof agent2data.body.item.upgrade_started_at).to.be('undefined'); }); - await supertest - .post(`/api/fleet/agents/bulk_upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - agents: 'active:true', - version: kibanaVersion, - }) - .expect(200); - const [agent1data, agent2data] = await Promise.all([ - supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), - supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), - ]); - expect(typeof agent1data.body.item.upgrade_started_at).to.be('string'); - expect(typeof agent2data.body.item.upgrade_started_at).to.be('undefined'); - }); - it('should not upgrade an unenrolling agent during bulk_upgrade', async () => { - const kibanaVersion = await kibanaServer.version.get(); - await supertest.post(`/api/fleet/agents/agent1/unenroll`).set('kbn-xsrf', 'xxx').send({ - force: true, - }); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + it('should not upgrade an unenrolling agent during bulk_upgrade', async () => { + const kibanaVersion = await kibanaServer.version.get(); + await supertest.post(`/api/fleet/agents/agent1/unenroll`).set('kbn-xsrf', 'xxx').send({ + force: true, + }); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, }, - }, - }); - await es.update({ - id: 'agent2', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }); + await es.update({ + id: 'agent2', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, }, - }, + }); + await supertest + .post(`/api/fleet/agents/bulk_upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + agents: ['agent1', 'agent2'], + version: kibanaVersion, + }); + const [agent1data, agent2data] = await Promise.all([ + supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), + supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), + ]); + expect(typeof agent1data.body.item.upgrade_started_at).to.be('undefined'); + expect(typeof agent2data.body.item.upgrade_started_at).to.be('string'); }); - await supertest - .post(`/api/fleet/agents/bulk_upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - agents: ['agent1', 'agent2'], - version: kibanaVersion, - }); - const [agent1data, agent2data] = await Promise.all([ - supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), - supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), - ]); - expect(typeof agent1data.body.item.upgrade_started_at).to.be('undefined'); - expect(typeof agent2data.body.item.upgrade_started_at).to.be('string'); - }); - it('should not upgrade an unenrolled agent during bulk_upgrade', async () => { - const kibanaVersion = await kibanaServer.version.get(); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - unenrolled_at: new Date().toISOString(), - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + it('should not upgrade an unenrolled agent during bulk_upgrade', async () => { + const kibanaVersion = await kibanaServer.version.get(); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + unenrolled_at: new Date().toISOString(), + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, }, - }, - }); - await es.update({ - id: 'agent2', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { - elastic: { agent: { upgradeable: true, version: '0.0.0' } }, + }); + await es.update({ + id: 'agent2', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { + elastic: { agent: { upgradeable: true, version: '0.0.0' } }, + }, }, }, - }, + }); + await supertest + .post(`/api/fleet/agents/bulk_upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + agents: ['agent1', 'agent2'], + version: kibanaVersion, + }); + const [agent1data, agent2data] = await Promise.all([ + supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), + supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), + ]); + expect(typeof agent1data.body.item.upgrade_started_at).to.be('undefined'); + expect(typeof agent2data.body.item.upgrade_started_at).to.be('string'); }); - await supertest - .post(`/api/fleet/agents/bulk_upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - agents: ['agent1', 'agent2'], - version: kibanaVersion, - }); - const [agent1data, agent2data] = await Promise.all([ - supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), - supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), - ]); - expect(typeof agent1data.body.item.upgrade_started_at).to.be('undefined'); - expect(typeof agent2data.body.item.upgrade_started_at).to.be('string'); - }); - it('should not upgrade an non upgradeable agent during bulk_upgrade', async () => { - const kibanaVersion = await kibanaServer.version.get(); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + it('should not upgrade an non upgradeable agent during bulk_upgrade', async () => { + const kibanaVersion = await kibanaServer.version.get(); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, }, - }, - }); - await es.update({ - id: 'agent2', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { - elastic: { - agent: { upgradeable: true, version: semver.inc(kibanaVersion, 'patch') }, + }); + await es.update({ + id: 'agent2', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { + elastic: { + agent: { upgradeable: true, version: semver.inc(kibanaVersion, 'patch') }, + }, }, }, }, - }, - }); - await es.update({ - id: 'agent3', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: false, version: '0.0.0' } } }, + }); + await es.update({ + id: 'agent3', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: false, version: '0.0.0' } } }, + }, }, - }, + }); + await supertest + .post(`/api/fleet/agents/bulk_upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + agents: ['agent1', 'agent2', 'agent3'], + version: kibanaVersion, + }); + const [agent1data, agent2data, agent3data] = await Promise.all([ + supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), + supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), + supertest.get(`/api/fleet/agents/agent3`).set('kbn-xsrf', 'xxx'), + ]); + expect(typeof agent1data.body.item.upgrade_started_at).to.be('string'); + expect(typeof agent2data.body.item.upgrade_started_at).to.be('undefined'); + expect(typeof agent3data.body.item.upgrade_started_at).to.be('undefined'); }); - await supertest - .post(`/api/fleet/agents/bulk_upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - agents: ['agent1', 'agent2', 'agent3'], - version: kibanaVersion, - }); - const [agent1data, agent2data, agent3data] = await Promise.all([ - supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), - supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), - supertest.get(`/api/fleet/agents/agent3`).set('kbn-xsrf', 'xxx'), - ]); - expect(typeof agent1data.body.item.upgrade_started_at).to.be('string'); - expect(typeof agent2data.body.item.upgrade_started_at).to.be('undefined'); - expect(typeof agent3data.body.item.upgrade_started_at).to.be('undefined'); - }); - it('should upgrade a non upgradeable agent during bulk_upgrade with force flag', async () => { - const kibanaVersion = await kibanaServer.version.get(); - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + it('should upgrade a non upgradeable agent during bulk_upgrade with force flag', async () => { + const kibanaVersion = await kibanaServer.version.get(); + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, }, - }, - }); - await es.update({ - id: 'agent2', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { - elastic: { - agent: { upgradeable: true, version: semver.inc(kibanaVersion, 'patch') }, + }); + await es.update({ + id: 'agent2', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { + elastic: { + agent: { upgradeable: true, version: semver.inc(kibanaVersion, 'patch') }, + }, }, }, }, - }, - }); - await es.update({ - id: 'agent3', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: false, version: '0.0.0' } } }, - }, - }, - }); - await supertest - .post(`/api/fleet/agents/bulk_upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - agents: ['agent1', 'agent2', 'agent3'], - version: kibanaVersion, - force: true, }); - const [agent1data, agent2data, agent3data] = await Promise.all([ - supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), - supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), - supertest.get(`/api/fleet/agents/agent3`).set('kbn-xsrf', 'xxx'), - ]); - expect(typeof agent1data.body.item.upgrade_started_at).to.be('string'); - expect(typeof agent2data.body.item.upgrade_started_at).to.be('string'); - expect(typeof agent3data.body.item.upgrade_started_at).to.be('string'); - }); - it('should respond 400 if trying to bulk upgrade to a version that does not match installed kibana version', async () => { - await es.update({ - id: 'agent1', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + await es.update({ + id: 'agent3', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: false, version: '0.0.0' } } }, + }, }, - }, + }); + await supertest + .post(`/api/fleet/agents/bulk_upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + agents: ['agent1', 'agent2', 'agent3'], + version: kibanaVersion, + force: true, + }); + const [agent1data, agent2data, agent3data] = await Promise.all([ + supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), + supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), + supertest.get(`/api/fleet/agents/agent3`).set('kbn-xsrf', 'xxx'), + ]); + expect(typeof agent1data.body.item.upgrade_started_at).to.be('string'); + expect(typeof agent2data.body.item.upgrade_started_at).to.be('string'); + expect(typeof agent3data.body.item.upgrade_started_at).to.be('string'); }); - await es.update({ - id: 'agent2', - refresh: 'wait_for', - index: AGENTS_INDEX, - body: { - doc: { - local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + it('should respond 400 if trying to bulk upgrade to a version that does not match installed kibana version', async () => { + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, + }, + }); + await es.update({ + id: 'agent2', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, }, - }, + }); + await supertest + .post(`/api/fleet/agents/bulk_upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + agents: ['agent1', 'agent2'], + version: '1.0.0', + force: true, + }) + .expect(400); }); - await supertest - .post(`/api/fleet/agents/bulk_upgrade`) - .set('kbn-xsrf', 'xxx') - .send({ - agents: ['agent1', 'agent2'], - version: '1.0.0', - force: true, - }) - .expect(400); - }); - describe('fleet upgrade agent(s) in a managed policy', function () { - it('should respond 400 to bulk upgrade and not update the agent SOs', async () => { + it('enrolled in a managed policy bulk upgrade should respond with 400 and not update the agent SOs', async () => { // update enrolled policy to managed await supertest.put(`/api/fleet/agent_policies/policy1`).set('kbn-xsrf', 'xxxx').send({ name: 'Test policy', @@ -560,7 +593,7 @@ export default function (providerContext: FtrProviderContext) { expect(typeof agent2data.body.item.upgrade_started_at).to.be('undefined'); }); - it('should respond 400 to upgrade and not update the agent SOs', async () => { + it('enrolled in a managed policy bulk upgrade with force flag should respond with 200 and update the agent SOs', async () => { // update enrolled policy to managed await supertest.put(`/api/fleet/agent_policies/policy1`).set('kbn-xsrf', 'xxxx').send({ name: 'Test policy', @@ -579,16 +612,37 @@ export default function (providerContext: FtrProviderContext) { }, }, }); + await es.update({ + id: 'agent2', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { + elastic: { + agent: { upgradeable: true, version: semver.inc(kibanaVersion, 'patch') }, + }, + }, + }, + }, + }); // attempt to upgrade agent in managed policy const { body } = await supertest - .post(`/api/fleet/agents/agent1/upgrade`) + .post(`/api/fleet/agents/bulk_upgrade`) .set('kbn-xsrf', 'xxx') - .send({ version: kibanaVersion }) - .expect(400); - expect(body.message).to.contain('Cannot upgrade agent agent1 in managed policy policy1'); + .send({ + version: kibanaVersion, + agents: ['agent1', 'agent2'], + force: true, + }); + expect(body).to.eql({}); - const agent1data = await supertest.get(`/api/fleet/agents/agent1`); - expect(typeof agent1data.body.item.upgrade_started_at).to.be('undefined'); + const [agent1data, agent2data] = await Promise.all([ + supertest.get(`/api/fleet/agents/agent1`), + supertest.get(`/api/fleet/agents/agent2`), + ]); + expect(typeof agent1data.body.item.upgrade_started_at).to.be('string'); + expect(typeof agent2data.body.item.upgrade_started_at).to.be('string'); }); }); });