Skip to content

Commit

Permalink
[Fleet] Use 'hosted agent policy' naming in UI & API messages (#97287) (
Browse files Browse the repository at this point in the history
#97346)

## Summary

### What this PR _does_ change
 - [x] Replace all UI & API instances of "managed policy" with "hosted agent policy" #93504
 - [x] Replace all UI & API instances of "unmanaged policy" with "regular agent policy" #93504
 - [x] Update most variable names containing `managed` to `hosted`

<details><summary>screenshots</summary>

<img width="489" alt="Screen Shot 2021-04-15 at 10 54 01 AM" src="https://user-images.githubusercontent.com/57655/114898051-cac35980-9ddf-11eb-9c55-3fb5c0211c63.png">
<img width="339" alt="Screen Shot 2021-04-15 at 11 40 47 AM" src="https://user-images.githubusercontent.com/57655/114898053-cac35980-9ddf-11eb-8c60-3459aed3db6c.png">
<img width="714" alt="Screen Shot 2021-04-15 at 11 40 59 AM" src="https://user-images.githubusercontent.com/57655/114898054-cac35980-9ddf-11eb-912a-623eba9c3860.png">
</details>

### What this PR _does not_ change
  - [ ] The `is_managed` property of the agent policy saved object*
  - [ ] The updated error messages in #92591

<details><summary>*why not change the <code>is_managed</code> property?</summary>

<p>Changing the property will require a migration from 7.12. That's not a problem, but we haven't decided on <a href="https://github.com/elastic/kibana/issues/93504#issuecomment-790060997">a new name/approach</a> yet. Rather than update to <code>is_hosted: boolean</code> now and potentially something like <code>managed_by: enum</code> later, we'll update it when we have a decision.

<p><strong>TL;DR:</strong> It's a trivial update to make later and a minuscule amount of debt to pay until then. Less than cost of doing it twice.
 
</details>

### Checklist

- [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/master/packages/kbn-i18n/README.md)
- [x] [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: John Schulz <[email protected]>
  • Loading branch information
kibanamachine and John Schulz authored Apr 16, 2021
1 parent 9970e49 commit 5ede358
Show file tree
Hide file tree
Showing 19 changed files with 191 additions and 203 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => {
{agentPolicy?.is_managed && (
<EuiFlexItem grow={false}>
<EuiIconTip
title="Managed agent policy"
title="Hosted agent policy"
content={i18n.translate(
'xpack.fleet.policyDetails.policyDetailsManagedPolicyTooltip',
'xpack.fleet.policyDetails.policyDetailsHostedPolicyTooltip',
{
defaultMessage:
'This policy is managed outside of Fleet. Most actions related to this policy are unavailable.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,8 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
if (!agent.policy_id) return true;

const agentPolicy = agentPoliciesIndexedById[agent.policy_id];
const isManaged = agentPolicy?.is_managed === true;
return !isManaged;
const isHosted = agentPolicy?.is_managed === true;
return !isHosted;
};

const columns = [
Expand Down
6 changes: 3 additions & 3 deletions x-pack/plugins/fleet/server/services/agent_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ class AgentPolicyService {
}

if (oldAgentPolicy.is_managed && !options?.force) {
throw new IngestManagerError(`Cannot update integrations of managed policy ${id}`);
throw new IngestManagerError(`Cannot update integrations of hosted agent policy ${id}`);
}

return await this._update(
Expand Down Expand Up @@ -507,7 +507,7 @@ class AgentPolicyService {
}

if (oldAgentPolicy.is_managed && !options?.force) {
throw new IngestManagerError(`Cannot remove integrations of managed policy ${id}`);
throw new IngestManagerError(`Cannot remove integrations of hosted agent policy ${id}`);
}

return await this._update(
Expand Down Expand Up @@ -550,7 +550,7 @@ class AgentPolicyService {
}

if (agentPolicy.is_managed) {
throw new AgentPolicyDeletionError(`Cannot delete managed policy ${id}`);
throw new AgentPolicyDeletionError(`Cannot delete hosted agent policy ${id}`);
}

const {
Expand Down
5 changes: 3 additions & 2 deletions x-pack/plugins/fleet/server/services/agents/crud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,10 @@ export async function getAgentByAccessAPIKeyId(
q: `access_api_key_id:${escapeSearchQueryPhrase(accessAPIKeyId)}`,
});

const agent = searchHitToAgent(res.body.hits.hits[0]);
const searchHit = res.body.hits.hits[0];
const agent = searchHit && searchHitToAgent(searchHit);

if (!agent) {
if (!searchHit || !agent) {
throw new AgentNotFoundError('Agent not found');
}
if (agent.access_api_key_id !== accessAPIKeyId) {
Expand Down
85 changes: 40 additions & 45 deletions x-pack/plugins/fleet/server/services/agents/reassign.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,86 +13,81 @@ import { AgentReassignmentError } from '../../errors';

import { reassignAgent, reassignAgents } from './reassign';

const agentInManagedDoc = {
_id: 'agent-in-managed-policy',
_source: { policy_id: 'managed-agent-policy' },
const agentInHostedDoc = {
_id: 'agent-in-hosted-policy',
_source: { policy_id: 'hosted-agent-policy' },
};
const agentInManagedDoc2 = {
_id: 'agent-in-managed-policy2',
_source: { policy_id: 'managed-agent-policy' },
const agentInHostedDoc2 = {
_id: 'agent-in-hosted-policy2',
_source: { policy_id: 'hosted-agent-policy' },
};
const agentInUnmanagedDoc = {
_id: 'agent-in-unmanaged-policy',
_source: { policy_id: 'unmanaged-agent-policy' },
const agentInRegularDoc = {
_id: 'agent-in-regular-policy',
_source: { policy_id: 'regular-agent-policy' },
};
const unmanagedAgentPolicySO = {
id: 'unmanaged-agent-policy',
const regularAgentPolicySO = {
id: 'regular-agent-policy',
attributes: { is_managed: false },
} as SavedObject<AgentPolicy>;
const unmanagedAgentPolicySO2 = {
id: 'unmanaged-agent-policy-2',
const regularAgentPolicySO2 = {
id: 'regular-agent-policy-2',
attributes: { is_managed: false },
} as SavedObject<AgentPolicy>;
const managedAgentPolicySO = {
id: 'managed-agent-policy',
const hostedAgentPolicySO = {
id: 'hosted-agent-policy',
attributes: { is_managed: true },
} as SavedObject<AgentPolicy>;

describe('reassignAgent (singular)', () => {
it('can reassign from unmanaged policy to unmanaged', async () => {
it('can reassign from regular agent policy to regular', async () => {
const { soClient, esClient } = createClientsMock();
await reassignAgent(soClient, esClient, agentInUnmanagedDoc._id, unmanagedAgentPolicySO.id);
await reassignAgent(soClient, esClient, agentInRegularDoc._id, regularAgentPolicySO.id);

// calls ES update with correct values
expect(esClient.update).toBeCalledTimes(1);
const calledWith = esClient.update.mock.calls[0];
expect(calledWith[0]?.id).toBe(agentInUnmanagedDoc._id);
expect(calledWith[0]?.body?.doc).toHaveProperty('policy_id', unmanagedAgentPolicySO.id);
expect(calledWith[0]?.id).toBe(agentInRegularDoc._id);
expect(calledWith[0]?.body?.doc).toHaveProperty('policy_id', regularAgentPolicySO.id);
});

it('cannot reassign from unmanaged policy to managed', async () => {
it('cannot reassign from regular agent policy to hosted', async () => {
const { soClient, esClient } = createClientsMock();
await expect(
reassignAgent(soClient, esClient, agentInUnmanagedDoc._id, managedAgentPolicySO.id)
reassignAgent(soClient, esClient, agentInRegularDoc._id, hostedAgentPolicySO.id)
).rejects.toThrowError(AgentReassignmentError);

// does not call ES update
expect(esClient.update).toBeCalledTimes(0);
});

it('cannot reassign from managed policy', async () => {
it('cannot reassign from hosted agent policy', async () => {
const { soClient, esClient } = createClientsMock();
await expect(
reassignAgent(soClient, esClient, agentInManagedDoc._id, unmanagedAgentPolicySO.id)
reassignAgent(soClient, esClient, agentInHostedDoc._id, regularAgentPolicySO.id)
).rejects.toThrowError(AgentReassignmentError);
// does not call ES update
expect(esClient.update).toBeCalledTimes(0);

await expect(
reassignAgent(soClient, esClient, agentInManagedDoc._id, managedAgentPolicySO.id)
reassignAgent(soClient, esClient, agentInHostedDoc._id, hostedAgentPolicySO.id)
).rejects.toThrowError(AgentReassignmentError);
// does not call ES update
expect(esClient.update).toBeCalledTimes(0);
});
});

describe('reassignAgents (plural)', () => {
it('agents in managed policies are not updated', async () => {
it('agents in hosted policies are not updated', async () => {
const { soClient, esClient } = createClientsMock();
const idsToReassign = [agentInUnmanagedDoc._id, agentInManagedDoc._id, agentInManagedDoc2._id];
await reassignAgents(
soClient,
esClient,
{ agentIds: idsToReassign },
unmanagedAgentPolicySO2.id
);
const idsToReassign = [agentInRegularDoc._id, agentInHostedDoc._id, agentInHostedDoc2._id];
await reassignAgents(soClient, esClient, { agentIds: idsToReassign }, regularAgentPolicySO2.id);

// calls ES update with correct values
const calledWith = esClient.bulk.mock.calls[0][0];
// only 1 are unmanaged and bulk write two line per update
// only 1 are regular and bulk write two line per update
expect(calledWith.body.length).toBe(2);
// @ts-expect-error
expect(calledWith.body[0].update._id).toEqual(agentInUnmanagedDoc._id);
expect(calledWith.body[0].update._id).toEqual(agentInRegularDoc._id);
});
});

Expand All @@ -112,12 +107,12 @@ function createClientsMock() {
});
soClientMock.get.mockImplementation(async (_, id) => {
switch (id) {
case unmanagedAgentPolicySO.id:
return unmanagedAgentPolicySO;
case managedAgentPolicySO.id:
return managedAgentPolicySO;
case unmanagedAgentPolicySO2.id:
return unmanagedAgentPolicySO2;
case regularAgentPolicySO.id:
return regularAgentPolicySO;
case hostedAgentPolicySO.id:
return hostedAgentPolicySO;
case regularAgentPolicySO2.id:
return regularAgentPolicySO2;
default:
throw new Error(`${id} not found`);
}
Expand All @@ -133,17 +128,17 @@ function createClientsMock() {
esClientMock.mget.mockImplementation(async () => {
return {
body: {
docs: [agentInManagedDoc, agentInUnmanagedDoc, agentInManagedDoc2],
docs: [agentInHostedDoc, agentInRegularDoc, agentInHostedDoc2],
},
};
});
// @ts-expect-error
esClientMock.get.mockImplementation(async ({ id }) => {
switch (id) {
case agentInManagedDoc._id:
return { body: agentInManagedDoc };
case agentInUnmanagedDoc._id:
return { body: agentInUnmanagedDoc };
case agentInHostedDoc._id:
return { body: agentInHostedDoc };
case agentInRegularDoc._id:
return { body: agentInRegularDoc };
default:
throw new Error(`${id} not found`);
}
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/fleet/server/services/agents/reassign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ export async function reassignAgentIsAllowed(
const agentPolicy = await getAgentPolicyForAgent(soClient, esClient, agentId);
if (agentPolicy?.is_managed) {
throw new AgentReassignmentError(
`Cannot reassign an agent from managed agent policy ${agentPolicy.id}`
`Cannot reassign an agent from hosted agent policy ${agentPolicy.id}`
);
}

const newAgentPolicy = await agentPolicyService.get(soClient, newAgentPolicyId);
if (newAgentPolicy?.is_managed) {
throw new AgentReassignmentError(
`Cannot reassign an agent to managed agent policy ${newAgentPolicy.id}`
`Cannot reassign an agent to hosted agent policy ${newAgentPolicy.id}`
);
}

Expand Down
Loading

0 comments on commit 5ede358

Please sign in to comment.