Skip to content

Commit

Permalink
[Ingest] Add revision to agent configs & data sources (#59848)
Browse files Browse the repository at this point in the history
* Add revision to agent config and datasource saved objects, add delete datasource service and datasource

* Add revision to full agent config output

* PR feedback
  • Loading branch information
jen-huang authored Mar 12, 2020
1 parent 4a9af8d commit 755ba3a
Show file tree
Hide file tree
Showing 13 changed files with 151 additions and 43 deletions.
1 change: 1 addition & 0 deletions x-pack/plugins/ingest_manager/common/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const DATASOURCE_API_ROUTES = {
INFO_PATTERN: `${DATASOURCE_API_ROOT}/{datasourceId}`,
CREATE_PATTERN: `${DATASOURCE_API_ROOT}`,
UPDATE_PATTERN: `${DATASOURCE_API_ROOT}/{datasourceId}`,
DELETE_PATTERN: `${DATASOURCE_API_ROOT}/delete`,
};

// Agent config API routes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export const storedDatasourceToAgentDatasource = (
namespace,
enabled,
use_output: DEFAULT_OUTPUT.name, // TODO: hardcoded to default output for now
package: undefined,
inputs: inputs
.filter(input => input.enabled)
.map(input => ({
Expand Down Expand Up @@ -46,8 +45,6 @@ export const storedDatasourceToAgentDatasource = (
name: pkg.name,
version: pkg.version,
};
} else {
delete fullDatasource.package;
}

return fullDatasource;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export enum AgentConfigStatus {

export interface NewAgentConfig {
name: string;
namespace: string;
namespace?: string;
description?: string;
is_default?: boolean;
}
Expand All @@ -31,6 +31,7 @@ export interface AgentConfig extends NewAgentConfig, SavedObjectAttributes {
datasources: string[] | Datasource[];
updated_on: string;
updated_by: string;
revision: number;
}

export type FullAgentConfigDatasource = Pick<Datasource, 'namespace' | 'enabled'> & {
Expand All @@ -56,4 +57,5 @@ export interface FullAgentConfig {
};
};
datasources: FullAgentConfigDatasource[];
revision?: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,7 @@ export interface NewDatasource {
inputs: DatasourceInput[];
}

export type Datasource = NewDatasource & { id: string };
export type Datasource = NewDatasource & {
id: string;
revision: number;
};
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
<FormattedMessage
id="xpack.ingestManager.agentConfigList.revisionNumber"
defaultMessage="rev. {revNumber}"
values={{ revNumber: '999' }}
values={{ revNumber: agentConfig.revision }}
/>
</EuiText>
</EuiFlexItem>
Expand Down
40 changes: 31 additions & 9 deletions x-pack/plugins/ingest_manager/server/routes/datasource/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
*/
import { TypeOf } from '@kbn/config-schema';
import { RequestHandler } from 'kibana/server';
import { appContextService, datasourceService, agentConfigService } from '../../services';
import { appContextService, datasourceService } from '../../services';
import { ensureInstalledPackage } from '../../services/epm/packages';
import {
GetDatasourcesRequestSchema,
GetOneDatasourceRequestSchema,
CreateDatasourceRequestSchema,
UpdateDatasourceRequestSchema,
DeleteDatasourcesRequestSchema,
} from '../../types';
import { CreateDatasourceResponse } from '../../../common';
import { CreateDatasourceResponse, DeleteDatasourcesResponse } from '../../../common';

export const getDatasourcesHandler: RequestHandler<
undefined,
Expand Down Expand Up @@ -85,12 +86,7 @@ export const createDatasourceHandler: RequestHandler<
}

// Create datasource
const datasource = await datasourceService.create(soClient, request.body);

// Assign it to the given agent config
await agentConfigService.assignDatasources(soClient, datasource.config_id, [datasource.id], {
user,
});
const datasource = await datasourceService.create(soClient, request.body, { user });
const body: CreateDatasourceResponse = { item: datasource, success: true };
return response.ok({
body,
Expand All @@ -109,11 +105,13 @@ export const updateDatasourceHandler: RequestHandler<
TypeOf<typeof UpdateDatasourceRequestSchema.body>
> = async (context, request, response) => {
const soClient = context.core.savedObjects.client;
const user = (await appContextService.getSecurity()?.authc.getCurrentUser(request)) || undefined;
try {
const datasource = await datasourceService.update(
soClient,
request.params.datasourceId,
request.body
request.body,
{ user }
);
return response.ok({
body: { item: datasource, success: true },
Expand All @@ -125,3 +123,27 @@ export const updateDatasourceHandler: RequestHandler<
});
}
};

export const deleteDatasourceHandler: RequestHandler<
unknown,
unknown,
TypeOf<typeof DeleteDatasourcesRequestSchema.body>
> = async (context, request, response) => {
const soClient = context.core.savedObjects.client;
const user = (await appContextService.getSecurity()?.authc.getCurrentUser(request)) || undefined;
try {
const body: DeleteDatasourcesResponse = await datasourceService.delete(
soClient,
request.body.datasourceIds,
{ user }
);
return response.ok({
body,
});
} catch (e) {
return response.customError({
statusCode: 500,
body: { message: e.message },
});
}
};
12 changes: 12 additions & 0 deletions x-pack/plugins/ingest_manager/server/routes/datasource/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import {
GetOneDatasourceRequestSchema,
CreateDatasourceRequestSchema,
UpdateDatasourceRequestSchema,
DeleteDatasourcesRequestSchema,
} from '../../types';
import {
getDatasourcesHandler,
getOneDatasourceHandler,
createDatasourceHandler,
updateDatasourceHandler,
deleteDatasourceHandler,
} from './handlers';

export const registerRoutes = (router: IRouter) => {
Expand Down Expand Up @@ -58,4 +60,14 @@ export const registerRoutes = (router: IRouter) => {
},
updateDatasourceHandler
);

// Delete
router.post(
{
path: DATASOURCE_API_ROUTES.DELETE_PATTERN,
validate: DeleteDatasourcesRequestSchema,
options: { tags: [`access:${PLUGIN_ID}`] },
},
deleteDatasourceHandler
);
};
2 changes: 2 additions & 0 deletions x-pack/plugins/ingest_manager/server/saved_objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export const savedObjectMappings = {
datasources: { type: 'keyword' },
updated_on: { type: 'keyword' },
updated_by: { type: 'keyword' },
revision: { type: 'integer' },
},
},
[ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE]: {
Expand Down Expand Up @@ -138,6 +139,7 @@ export const savedObjectMappings = {
},
},
},
revision: { type: 'integer' },
},
},
[PACKAGES_SAVED_OBJECT_TYPE]: {
Expand Down
41 changes: 26 additions & 15 deletions x-pack/plugins/ingest_manager/server/services/agent_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,24 @@ class AgentConfigService {
agentConfig: Partial<AgentConfig>,
user?: AuthenticatedUser
): Promise<AgentConfig> {
const oldAgentConfig = await this.get(soClient, id, false);

if (!oldAgentConfig) {
throw new Error('Agent config not found');
}

if (
oldAgentConfig.status === AgentConfigStatus.Inactive &&
agentConfig.status !== AgentConfigStatus.Active
) {
throw new Error(
`Agent config ${id} cannot be updated because it is ${oldAgentConfig.status}`
);
}

await soClient.update<AgentConfig>(SAVED_OBJECT_TYPE, id, {
...agentConfig,
revision: oldAgentConfig.revision + 1,
updated_on: new Date().toString(),
updated_by: user ? user.username : 'system',
});
Expand Down Expand Up @@ -76,6 +92,7 @@ class AgentConfigService {
SAVED_OBJECT_TYPE,
{
...agentConfig,
revision: 1,
updated_on: new Date().toISOString(),
updated_by: options?.user?.username || 'system',
} as AgentConfig,
Expand Down Expand Up @@ -160,24 +177,17 @@ class AgentConfigService {
agentConfig: Partial<AgentConfig>,
options?: { user?: AuthenticatedUser }
): Promise<AgentConfig> {
const oldAgentConfig = await this.get(soClient, id);

if (!oldAgentConfig) {
throw new Error('Agent config not found');
}

if (
oldAgentConfig.status === AgentConfigStatus.Inactive &&
agentConfig.status !== AgentConfigStatus.Active
) {
throw new Error(
`Agent config ${id} cannot be updated because it is ${oldAgentConfig.status}`
);
}

return this._update(soClient, id, agentConfig, options?.user);
}

public async bumpRevision(
soClient: SavedObjectsClientContract,
id: string,
options?: { user?: AuthenticatedUser }
): Promise<AgentConfig> {
return this._update(soClient, id, {}, options?.user);
}

public async assignDatasources(
soClient: SavedObjectsClientContract,
id: string,
Expand Down Expand Up @@ -307,6 +317,7 @@ class AgentConfigService {
datasources: (config.datasources as Datasource[]).map(ds =>
storedDatasourceToAgentDatasource(ds)
),
revision: config.revision,
};

return agentConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { SavedObjectsClientContract } from 'kibana/server';
import { generateEnrollmentAPIKey, deleteEnrollmentApiKeyForConfigId } from './api_keys';
import { updateAgentsForPolicyId, unenrollForPolicyId } from './agents';
import { updateAgentsForConfigId, unenrollForConfigId } from './agents';

export async function agentConfigUpdateEventHandler(
soClient: SavedObjectsClientContract,
Expand All @@ -20,11 +20,11 @@ export async function agentConfigUpdateEventHandler(
}

if (action === 'updated') {
await updateAgentsForPolicyId(soClient, configId);
await updateAgentsForConfigId(soClient, configId);
}

if (action === 'deleted') {
await unenrollForPolicyId(soClient, configId);
await unenrollForConfigId(soClient, configId);
await deleteEnrollmentApiKeyForConfigId(soClient, configId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { listAgents } from './crud';
import { AGENT_SAVED_OBJECT_TYPE } from '../../constants';
import { unenrollAgents } from './unenroll';

export async function updateAgentsForPolicyId(
export async function updateAgentsForConfigId(
soClient: SavedObjectsClientContract,
configId: string
) {
Expand Down Expand Up @@ -37,7 +37,7 @@ export async function updateAgentsForPolicyId(
}
}

export async function unenrollForPolicyId(soClient: SavedObjectsClientContract, configId: string) {
export async function unenrollForConfigId(soClient: SavedObjectsClientContract, configId: string) {
let hasMore = true;
let page = 1;
while (hasMore) {
Expand Down
Loading

0 comments on commit 755ba3a

Please sign in to comment.