Skip to content

Commit

Permalink
Bump policies when preconfigred output are updated
Browse files Browse the repository at this point in the history
  • Loading branch information
nchaulet committed Sep 21, 2021
1 parent aef2a44 commit 8548b80
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 7 deletions.
32 changes: 32 additions & 0 deletions x-pack/plugins/fleet/server/services/agent_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,38 @@ class AgentPolicyService {
return res;
}

public async bumpAllAgentPoliciesForOutput(
soClient: SavedObjectsClientContract,
esClient: ElasticsearchClient,
outputId: string,
options?: { user?: AuthenticatedUser }
): Promise<SavedObjectsBulkUpdateResponse<AgentPolicy>> {
const currentPolicies = await soClient.find<AgentPolicySOAttributes>({
type: SAVED_OBJECT_TYPE,
fields: ['revision', 'data_output_id', 'monitoring_output_id'],
searchFields: ['data_output_id', 'monitoring_output_id'],
search: escapeSearchQueryPhrase(outputId),
});
const bumpedPolicies = currentPolicies.saved_objects.map((policy) => {
policy.attributes = {
...policy.attributes,
revision: policy.attributes.revision + 1,
updated_at: new Date().toISOString(),
updated_by: options?.user ? options.user.username : 'system',
};
return policy;
});
const res = await soClient.bulkUpdate<AgentPolicySOAttributes>(bumpedPolicies);

await Promise.all(
currentPolicies.saved_objects.map((policy) =>
this.triggerAgentPolicyUpdatedEvent(soClient, esClient, 'updated', policy.id)
)
);

return res;
}

public async bumpAllAgentPolicies(
soClient: SavedObjectsClientContract,
esClient: ElasticsearchClient,
Expand Down
20 changes: 16 additions & 4 deletions x-pack/plugins/fleet/server/services/preconfiguration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,17 @@ jest.mock('./app_context', () => ({
}));

const spyAgentPolicyServiceUpdate = jest.spyOn(agentPolicy.agentPolicyService, 'update');
const spyAgentPolicyServicBumpAllAgentPoliciesForOutput = jest.spyOn(
agentPolicy.agentPolicyService,
'bumpAllAgentPoliciesForOutput'
);

describe('policy preconfiguration', () => {
beforeEach(() => {
mockInstalledPackages.clear();
mockConfiguredPolicies.clear();
spyAgentPolicyServiceUpdate.mockClear();
spyAgentPolicyServicBumpAllAgentPoliciesForOutput.mockClear();
});

it('should perform a no-op when passed no policies or packages', async () => {
Expand Down Expand Up @@ -509,7 +514,8 @@ describe('output preconfiguration', () => {

it('should create preconfigured output that does not exists', async () => {
const soClient = savedObjectsClientMock.create();
await ensurePreconfiguredOutputs(soClient, [
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
await ensurePreconfiguredOutputs(soClient, esClient, [
{
id: 'non-existing-output-1',
name: 'Output 1',
Expand All @@ -521,11 +527,13 @@ describe('output preconfiguration', () => {

expect(mockedOutputService.create).toBeCalled();
expect(mockedOutputService.update).not.toBeCalled();
expect(spyAgentPolicyServicBumpAllAgentPoliciesForOutput).not.toBeCalled();
});

it('should set default hosts if hosts is not set output that does not exists', async () => {
const soClient = savedObjectsClientMock.create();
await ensurePreconfiguredOutputs(soClient, [
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
await ensurePreconfiguredOutputs(soClient, esClient, [
{
id: 'non-existing-output-1',
name: 'Output 1',
Expand All @@ -540,7 +548,9 @@ describe('output preconfiguration', () => {

it('should update output if preconfigured output exists and changed', async () => {
const soClient = savedObjectsClientMock.create();
await ensurePreconfiguredOutputs(soClient, [
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
soClient.find.mockResolvedValue({ saved_objects: [], page: 0, per_page: 0, total: 0 });
await ensurePreconfiguredOutputs(soClient, esClient, [
{
id: 'existing-output-1',
is_default: false,
Expand All @@ -552,6 +562,7 @@ describe('output preconfiguration', () => {

expect(mockedOutputService.create).not.toBeCalled();
expect(mockedOutputService.update).toBeCalled();
expect(spyAgentPolicyServicBumpAllAgentPoliciesForOutput).toBeCalled();
});

const SCENARIOS: Array<{ name: string; data: PreconfiguredOutput }> = [
Expand Down Expand Up @@ -580,7 +591,8 @@ describe('output preconfiguration', () => {
const { data, name } = scenario;
it(`should do nothing if preconfigured output exists and did not changed (${name})`, async () => {
const soClient = savedObjectsClientMock.create();
await ensurePreconfiguredOutputs(soClient, [data]);
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
await ensurePreconfiguredOutputs(soClient, esClient, [data]);

expect(mockedOutputService.create).not.toBeCalled();
expect(mockedOutputService.update).not.toBeCalled();
Expand Down
11 changes: 9 additions & 2 deletions x-pack/plugins/fleet/server/services/preconfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ function isPreconfiguredOutputDifferentFromCurrent(

export async function ensurePreconfiguredOutputs(
soClient: SavedObjectsClientContract,
esClient: ElasticsearchClient,
outputs: PreconfiguredOutput[]
) {
if (outputs.length === 0) {
Expand Down Expand Up @@ -94,9 +95,15 @@ export async function ensurePreconfiguredOutputs(
}

if (!existingOutput) {
return outputService.create(soClient, data, { id, overwrite: true });
await outputService.create(soClient, data, { id, overwrite: true });
} else if (isPreconfiguredOutputDifferentFromCurrent(existingOutput, data)) {
return outputService.update(soClient, id, data);
await outputService.update(soClient, id, data);
// Bump revision of all policies using that output
if (outputData.is_default) {
await agentPolicyService.bumpAllAgentPolicies(soClient, esClient);
} else {
await agentPolicyService.bumpAllAgentPoliciesForOutput(soClient, esClient, id);
}
}
})
);
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/fleet/server/services/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ async function createSetupSideEffects(
let packages = packagesOrUndefined ?? [];

await Promise.all([
ensurePreconfiguredOutputs(soClient, outputsOrUndefined ?? []),
ensurePreconfiguredOutputs(soClient, esClient, outputsOrUndefined ?? []),
settingsService.settingsSetup(soClient),
]);

Expand Down

0 comments on commit 8548b80

Please sign in to comment.