Skip to content

Commit

Permalink
Do not support bulk Operation through API
Browse files Browse the repository at this point in the history
  • Loading branch information
nchaulet committed Apr 20, 2020
1 parent 28bd4e5 commit 22817a7
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 221 deletions.
4 changes: 2 additions & 2 deletions x-pack/plugins/ingest_manager/common/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ export const AGENT_API_ROUTES = {
ACKS_PATTERN: `${FLEET_API_ROOT}/agents/{agentId}/acks`,
ACTIONS_PATTERN: `${FLEET_API_ROOT}/agents/{agentId}/actions`,
ENROLL_PATTERN: `${FLEET_API_ROOT}/agents/enroll`,
UNENROLL_PATTERN: `${FLEET_API_ROOT}/agents/unenroll`,
REASSIGN_PATTERN: `${FLEET_API_ROOT}/agents/reassign`,
UNENROLL_PATTERN: `${FLEET_API_ROOT}/agents/{agentId}/unenroll`,
REASSIGN_PATTERN: `${FLEET_API_ROOT}/agents/{agentId}/reassign`,
STATUS_PATTERN: `${FLEET_API_ROOT}/agent-status`,
};

Expand Down
6 changes: 4 additions & 2 deletions x-pack/plugins/ingest_manager/common/services/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@ export const agentRouteService = {
getInfoPath: (agentId: string) => AGENT_API_ROUTES.INFO_PATTERN.replace('{agentId}', agentId),
getUpdatePath: (agentId: string) => AGENT_API_ROUTES.UPDATE_PATTERN.replace('{agentId}', agentId),
getEventsPath: (agentId: string) => AGENT_API_ROUTES.EVENTS_PATTERN.replace('{agentId}', agentId),
getUnenrollPath: () => AGENT_API_ROUTES.UNENROLL_PATTERN,
getReassignPath: () => AGENT_API_ROUTES.REASSIGN_PATTERN,
getUnenrollPath: (agentId: string) =>
AGENT_API_ROUTES.UNENROLL_PATTERN.replace('{agentId}', agentId),
getReassignPath: (agentId: string) =>
AGENT_API_ROUTES.REASSIGN_PATTERN.replace('{agentId}', agentId),
getListPath: () => AGENT_API_ROUTES.LIST_PATTERN,
getStatusPath: () => AGENT_API_ROUTES.STATUS_PATTERN,
};
Expand Down
21 changes: 7 additions & 14 deletions x-pack/plugins/ingest_manager/common/types/rest_spec/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,30 +96,23 @@ export interface PostNewAgentActionResponse {
}

export interface PostAgentUnenrollRequest {
body: { kuery: string } | { ids: string[] };
params: {
agentId: string;
};
}

export interface PostAgentUnenrollResponse {
results: Array<{
success: boolean;
error?: any;
id: string;
action: string;
}>;
success: boolean;
}

export interface PutAgentReassignRequest {
body: { kuery: string; config_id: string } | { ids: string[]; config_id: string };
params: {
agentId: string;
};
body: { config_id: string };
}

export interface PutAgentReassignResponse {
results: Array<{
success: boolean;
error?: any;
id: string;
action: string;
}>;
success: boolean;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,13 @@ export function sendGetAgentStatus(
}

export function sendPutAgentReassign(
agentId: string,
body: PutAgentReassignRequest['body'],
options?: RequestOptions
) {
return sendRequest<PutAgentReassignResponse>({
method: 'put',
path: agentRouteService.getReassignPath(),
path: agentRouteService.getReassignPath(agentId),
body,
...options,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ export const AgentReassignConfigFlyout: React.FunctionComponent<Props> = ({
if (!selectedAgentConfigId) {
throw new Error('No selected config id');
}
const res = await sendPutAgentReassign({
ids: [agentId],
const res = await sendPutAgentReassign(agentId, {
config_id: selectedAgentConfigId,
});
if (res.error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ export const AgentUnenrollProvider: React.FunctionComponent<Props> = ({ children
) => {
if (
agentsToUnenroll === undefined ||
(Array.isArray(agentsToUnenroll) && agentsToUnenroll.length === 0)
// !Only supports unenrolling one agent
(Array.isArray(agentsToUnenroll) && agentsToUnenroll.length !== 1)
) {
throw new Error('No agents specified for unenrollment');
}
Expand All @@ -60,55 +61,27 @@ export const AgentUnenrollProvider: React.FunctionComponent<Props> = ({ children
setIsLoading(true);

try {
const unenrollByKuery = typeof agents === 'string';
const { data, error } = await sendRequest<PostAgentUnenrollResponse>({
path: agentRouteService.getUnenrollPath(),
const agentId = agents[0];
const { error } = await sendRequest<PostAgentUnenrollResponse>({
path: agentRouteService.getUnenrollPath(agentId),
method: 'post',
body: JSON.stringify({
kuery: unenrollByKuery ? agents : undefined,
ids: !unenrollByKuery ? agents : undefined,
}),
});

if (error) {
throw new Error(error.message);
}

const results = data ? data.results : [];

const successfulResults = results.filter(result => result.success);
const failedResults = results.filter(result => !result.success);

if (successfulResults.length) {
const hasMultipleSuccesses = successfulResults.length > 1;
const successMessage = hasMultipleSuccesses
? i18n.translate('xpack.ingestManager.unenrollAgents.successMultipleNotificationTitle', {
defaultMessage: 'Unenrolled {count} agents',
values: { count: successfulResults.length },
})
: i18n.translate('xpack.ingestManager.unenrollAgents.successSingleNotificationTitle', {
defaultMessage: "Unenrolled agent '{id}'",
values: { id: successfulResults[0].id },
});
core.notifications.toasts.addSuccess(successMessage);
}

if (failedResults.length) {
const hasMultipleFailures = failedResults.length > 1;
const failureMessage = hasMultipleFailures
? i18n.translate('xpack.ingestManager.unenrollAgents.failureMultipleNotificationTitle', {
defaultMessage: 'Error unenrolling {count} agents',
values: { count: failedResults.length },
})
: i18n.translate('xpack.ingestManager.unenrollAgents.failureSingleNotificationTitle', {
defaultMessage: "Error unenrolling agent '{id}'",
values: { id: failedResults[0].id },
});
core.notifications.toasts.addDanger(failureMessage);
}
const successMessage = i18n.translate(
'xpack.ingestManager.unenrollAgents.successSingleNotificationTitle',
{
defaultMessage: "Unenrolled agent '{id}'",
values: { id: agentId },
}
);
core.notifications.toasts.addSuccess(successMessage);

if (onSuccessCallback.current) {
onSuccessCallback.current(successfulResults.map(result => result.id));
onSuccessCallback.current([agentId]);
}
} catch (e) {
core.notifications.toasts.addDanger(
Expand Down
100 changes: 8 additions & 92 deletions x-pack/plugins/ingest_manager/server/routes/agent/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,60 +295,15 @@ export const getAgentsHandler: RequestHandler<
}
};

export const postAgentsUnenrollHandler: RequestHandler<
undefined,
undefined,
TypeOf<typeof PostAgentUnenrollRequestSchema.body>
> = async (context, request, response) => {
export const postAgentsUnenrollHandler: RequestHandler<TypeOf<
typeof PostAgentUnenrollRequestSchema.params
>> = async (context, request, response) => {
const soClient = context.core.savedObjects.client;
try {
const kuery = (request.body as { kuery: string }).kuery;
let toUnenrollIds: string[] = (request.body as { ids: string[] }).ids || [];

if (kuery) {
let hasMore = true;
let page = 1;
while (hasMore) {
const { agents } = await AgentService.listAgents(soClient, {
page: page++,
perPage: 100,
kuery,
showInactive: true,
});
if (agents.length === 0) {
hasMore = false;
}
const agentIds = agents.filter(a => a.active).map(a => a.id);
toUnenrollIds = toUnenrollIds.concat(agentIds);
}
}
const results = (await AgentService.unenrollAgents(soClient, toUnenrollIds)).map(
({
success,
id,
error,
}): {
success: boolean;
id: string;
action: 'unenrolled';
error?: {
message: string;
};
} => {
return {
success,
id,
action: 'unenrolled',
error: error && {
message: error.message,
},
};
}
);
await AgentService.unenrollAgent(soClient, request.params.agentId);

const body: PostAgentUnenrollResponse = {
results,
success: results.every(result => result.success),
success: true,
};
return response.ok({ body });
} catch (e) {
Expand All @@ -360,55 +315,16 @@ export const postAgentsUnenrollHandler: RequestHandler<
};

export const putAgentsReassignHandler: RequestHandler<
undefined,
TypeOf<typeof PutAgentReassignRequestSchema.params>,
undefined,
TypeOf<typeof PutAgentReassignRequestSchema.body>
> = async (context, request, response) => {
const soClient = context.core.savedObjects.client;
try {
const kuery = (request.body as { kuery: string }).kuery;
let toReassignIds: string[] = (request.body as { ids: string[] }).ids || [];

if (kuery) {
let hasMore = true;
let page = 1;
while (hasMore) {
const { agents } = await AgentService.listAgents(soClient, {
page: page++,
perPage: 100,
kuery,
showInactive: true,
});
if (agents.length === 0) {
hasMore = false;
}
const agentIds = agents.filter(a => a.active).map(a => a.id);
toReassignIds = toReassignIds.concat(agentIds);
}
}
const results = (
await AgentService.reassignAgents(soClient, toReassignIds, request.body.config_id)
).map(({ success, id, error }): {
success: boolean;
id: string;
action: 'reassigned';
error?: {
message: string;
};
} => {
return {
success,
id,
action: 'reassigned',
error: error && {
message: error.message,
},
};
});
await AgentService.reassignAgent(soClient, request.params.agentId, request.body.config_id);

const body: PutAgentReassignResponse = {
results,
success: results.every(result => result.success),
success: true,
};
return response.ok({ body });
} catch (e) {
Expand Down
26 changes: 7 additions & 19 deletions x-pack/plugins/ingest_manager/server/services/agents/reassign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,19 @@ import { AGENT_SAVED_OBJECT_TYPE } from '../../constants';
import { AgentSOAttributes } from '../../types';
import { agentConfigService } from '../agent_config';

export async function reassignAgents(
export async function reassignAgent(
soClient: SavedObjectsClientContract,
toUnenrollIds: string[],
agentId: string,
newConfigId: string
) {
const config = await agentConfigService.get(soClient, newConfigId);
if (!config) {
throw Boom.notFound(`Agent Configuration not found: ${newConfigId}`);
}

const results = await soClient.bulkUpdate<AgentSOAttributes>(
toUnenrollIds.map(id => ({
type: AGENT_SAVED_OBJECT_TYPE,
id,
attributes: {
config_id: newConfigId,
config_revision: null,
config_newest_revision: config.revision,
},
}))
);

return results.saved_objects.map(result => ({
id: result.id,
success: !result.error,
error: result.error,
}));
await soClient.update<AgentSOAttributes>(AGENT_SAVED_OBJECT_TYPE, agentId, {
config_id: newConfigId,
config_revision: null,
config_newest_revision: config.revision,
});
}
26 changes: 1 addition & 25 deletions x-pack/plugins/ingest_manager/server/services/agents/unenroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,7 @@ import { AGENT_SAVED_OBJECT_TYPE } from '../../constants';
import { getAgent } from './crud';
import * as APIKeyService from '../api_keys';

export async function unenrollAgents(
soClient: SavedObjectsClientContract,
toUnenrollIds: string[]
) {
const response = [];
for (const id of toUnenrollIds) {
try {
await unenrollAgent(soClient, id);
response.push({
id,
success: true,
});
} catch (error) {
response.push({
id,
error,
success: false,
});
}
}

return response;
}

async function unenrollAgent(soClient: SavedObjectsClientContract, agentId: string) {
export async function unenrollAgent(soClient: SavedObjectsClientContract, agentId: string) {
const agent = await getAgent(soClient, agentId);

await Promise.all([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { SavedObjectsClientContract } from 'src/core/server';
import { listAgents } from './crud';
import { AGENT_SAVED_OBJECT_TYPE } from '../../constants';
import { unenrollAgents } from './unenroll';
import { unenrollAgent } from './unenroll';
import { agentConfigService } from '../agent_config';

export async function updateAgentsForConfigId(
Expand Down Expand Up @@ -55,9 +55,8 @@ export async function unenrollForConfigId(soClient: SavedObjectsClientContract,
if (agents.length === 0) {
hasMore = false;
}
await unenrollAgents(
soClient,
agents.map(a => a.id)
);
for (const agent of agents) {
await unenrollAgent(soClient, agent.id);
}
}
}
Loading

0 comments on commit 22817a7

Please sign in to comment.