[Fleet] Add feature-flag gate for single agent migrations UI/API & bulk migration API (#224143)

## Summary

Closes https://github.com/elastic/ingest-dev/issues/5694

- Adds a feature flag gate for the `single` agent migration UI and API
- Also gates the bulk migrate `endpoint`, UI will be gated separately as
part of
https://github.com/elastic/kibana/pull/224334

### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [ ] 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/main/src/platform/packages/shared/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [ ] [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
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

### Identify risks

N/A

---------

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Mason Herron 2025-06-18 10:11:45 -06:00 committed by GitHub
parent 6c0d67ea88
commit d3f6fb9870
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 96 additions and 1093 deletions

View file

@ -17238,159 +17238,6 @@
]
}
},
"/api/fleet/agents/bulk_migrate": {
"post": {
"description": "Bulk migrate agents to another cluster.<br/><br/>[Required authorization] Route required privileges: fleet-agents-all.",
"operationId": "post-fleet-agents-bulk-migrate",
"parameters": [
{
"description": "A required header to protect against CSRF attacks",
"in": "header",
"name": "kbn-xsrf",
"required": true,
"schema": {
"example": "true",
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"agents": {
"items": {
"type": "string"
},
"type": "array"
},
"enrollment_token": {
"type": "string"
},
"settings": {
"additionalProperties": false,
"properties": {
"ca_sha256": {
"type": "string"
},
"certificate_authorities": {
"type": "string"
},
"elastic_agent_cert": {
"type": "string"
},
"elastic_agent_cert_key": {
"type": "string"
},
"elastic_agent_cert_key_passphrase": {
"type": "string"
},
"headers": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"insecure": {
"type": "boolean"
},
"proxy_disabled": {
"type": "boolean"
},
"proxy_headers": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"proxy_url": {
"type": "string"
},
"staging": {
"type": "boolean"
},
"tags": {
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object"
},
"uri": {
"format": "uri",
"type": "string"
}
},
"required": [
"agents",
"uri",
"enrollment_token"
],
"type": "object"
}
}
}
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"actionId": {
"type": "string"
}
},
"required": [
"actionId"
],
"type": "object"
}
}
}
},
"400": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"description": "Generic Error",
"properties": {
"attributes": {},
"error": {
"type": "string"
},
"errorType": {
"type": "string"
},
"message": {
"type": "string"
},
"statusCode": {
"type": "number"
}
},
"required": [
"message",
"attributes"
],
"type": "object"
}
}
}
}
},
"summary": "Migrate multiple agents",
"tags": [
"Elastic Agents"
]
}
},
"/api/fleet/agents/bulk_reassign": {
"post": {
"description": "[Required authorization] Route required privileges: fleet-agents-all.",
@ -19406,7 +19253,7 @@
}
}
},
"summary": "Update an agent",
"summary": "Update an agent by ID",
"tags": [
"Elastic Agents"
]
@ -19621,163 +19468,6 @@
]
}
},
"/api/fleet/agents/{agentId}/migrate": {
"post": {
"description": "Migrate a single agent to another cluster.<br/><br/>[Required authorization] Route required privileges: fleet-agents-all.",
"operationId": "post-fleet-agents-agentid-migrate",
"parameters": [
{
"description": "A required header to protect against CSRF attacks",
"in": "header",
"name": "kbn-xsrf",
"required": true,
"schema": {
"example": "true",
"type": "string"
}
},
{
"in": "path",
"name": "agentId",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"enrollment_token": {
"type": "string"
},
"settings": {
"additionalProperties": false,
"properties": {
"ca_sha256": {
"type": "string"
},
"certificate_authorities": {
"type": "string"
},
"elastic_agent_cert": {
"type": "string"
},
"elastic_agent_cert_key": {
"type": "string"
},
"elastic_agent_cert_key_passphrase": {
"type": "string"
},
"headers": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"insecure": {
"type": "boolean"
},
"proxy_disabled": {
"type": "boolean"
},
"proxy_headers": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"proxy_url": {
"type": "string"
},
"replace_token": {
"type": "boolean"
},
"staging": {
"type": "boolean"
},
"tags": {
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object"
},
"uri": {
"format": "uri",
"type": "string"
}
},
"required": [
"uri",
"enrollment_token"
],
"type": "object"
}
}
}
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"actionId": {
"type": "string"
}
},
"required": [
"actionId"
],
"type": "object"
}
}
}
},
"400": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"description": "Generic Error",
"properties": {
"attributes": {},
"error": {
"type": "string"
},
"errorType": {
"type": "string"
},
"message": {
"type": "string"
},
"statusCode": {
"type": "number"
}
},
"required": [
"message",
"attributes"
],
"type": "object"
}
}
}
}
},
"summary": "Migrate a single agent",
"tags": [
"Elastic Agents"
]
}
},
"/api/fleet/agents/{agentId}/reassign": {
"post": {
"description": "[Required authorization] Route required privileges: fleet-agents-all.",

View file

@ -17238,159 +17238,6 @@
]
}
},
"/api/fleet/agents/bulk_migrate": {
"post": {
"description": "Bulk migrate agents to another cluster.<br/><br/>[Required authorization] Route required privileges: fleet-agents-all.",
"operationId": "post-fleet-agents-bulk-migrate",
"parameters": [
{
"description": "A required header to protect against CSRF attacks",
"in": "header",
"name": "kbn-xsrf",
"required": true,
"schema": {
"example": "true",
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"agents": {
"items": {
"type": "string"
},
"type": "array"
},
"enrollment_token": {
"type": "string"
},
"settings": {
"additionalProperties": false,
"properties": {
"ca_sha256": {
"type": "string"
},
"certificate_authorities": {
"type": "string"
},
"elastic_agent_cert": {
"type": "string"
},
"elastic_agent_cert_key": {
"type": "string"
},
"elastic_agent_cert_key_passphrase": {
"type": "string"
},
"headers": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"insecure": {
"type": "boolean"
},
"proxy_disabled": {
"type": "boolean"
},
"proxy_headers": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"proxy_url": {
"type": "string"
},
"staging": {
"type": "boolean"
},
"tags": {
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object"
},
"uri": {
"format": "uri",
"type": "string"
}
},
"required": [
"agents",
"uri",
"enrollment_token"
],
"type": "object"
}
}
}
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"actionId": {
"type": "string"
}
},
"required": [
"actionId"
],
"type": "object"
}
}
}
},
"400": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"description": "Generic Error",
"properties": {
"attributes": {},
"error": {
"type": "string"
},
"errorType": {
"type": "string"
},
"message": {
"type": "string"
},
"statusCode": {
"type": "number"
}
},
"required": [
"message",
"attributes"
],
"type": "object"
}
}
}
}
},
"summary": "Migrate multiple agents",
"tags": [
"Elastic Agents"
]
}
},
"/api/fleet/agents/bulk_reassign": {
"post": {
"description": "[Required authorization] Route required privileges: fleet-agents-all.",
@ -19406,7 +19253,7 @@
}
}
},
"summary": "Update an agent",
"summary": "Update an agent by ID",
"tags": [
"Elastic Agents"
]
@ -19621,163 +19468,6 @@
]
}
},
"/api/fleet/agents/{agentId}/migrate": {
"post": {
"description": "Migrate a single agent to another cluster.<br/><br/>[Required authorization] Route required privileges: fleet-agents-all.",
"operationId": "post-fleet-agents-agentid-migrate",
"parameters": [
{
"description": "A required header to protect against CSRF attacks",
"in": "header",
"name": "kbn-xsrf",
"required": true,
"schema": {
"example": "true",
"type": "string"
}
},
{
"in": "path",
"name": "agentId",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"enrollment_token": {
"type": "string"
},
"settings": {
"additionalProperties": false,
"properties": {
"ca_sha256": {
"type": "string"
},
"certificate_authorities": {
"type": "string"
},
"elastic_agent_cert": {
"type": "string"
},
"elastic_agent_cert_key": {
"type": "string"
},
"elastic_agent_cert_key_passphrase": {
"type": "string"
},
"headers": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"insecure": {
"type": "boolean"
},
"proxy_disabled": {
"type": "boolean"
},
"proxy_headers": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"proxy_url": {
"type": "string"
},
"replace_token": {
"type": "boolean"
},
"staging": {
"type": "boolean"
},
"tags": {
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object"
},
"uri": {
"format": "uri",
"type": "string"
}
},
"required": [
"uri",
"enrollment_token"
],
"type": "object"
}
}
}
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"actionId": {
"type": "string"
}
},
"required": [
"actionId"
],
"type": "object"
}
}
}
},
"400": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"description": "Generic Error",
"properties": {
"attributes": {},
"error": {
"type": "string"
},
"errorType": {
"type": "string"
},
"message": {
"type": "string"
},
"statusCode": {
"type": "number"
}
},
"required": [
"message",
"attributes"
],
"type": "object"
}
}
}
}
},
"summary": "Migrate a single agent",
"tags": [
"Elastic Agents"
]
}
},
"/api/fleet/agents/{agentId}/reassign": {
"post": {
"description": "[Required authorization] Route required privileges: fleet-agents-all.",

View file

@ -21371,7 +21371,7 @@ paths:
required:
- message
- attributes
summary: Update an agent
summary: Update an agent by ID
tags:
- Elastic Agents
/api/fleet/agents/{agentId}/actions:
@ -21514,109 +21514,6 @@ paths:
summary: Create an agent action
tags:
- Elastic Agent actions
/api/fleet/agents/{agentId}/migrate:
post:
description: 'Migrate a single agent to another cluster.<br/><br/>[Required authorization] Route required privileges: fleet-agents-all.'
operationId: post-fleet-agents-agentid-migrate
parameters:
- description: A required header to protect against CSRF attacks
in: header
name: kbn-xsrf
required: true
schema:
example: 'true'
type: string
- in: path
name: agentId
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
additionalProperties: false
type: object
properties:
enrollment_token:
type: string
settings:
additionalProperties: false
type: object
properties:
ca_sha256:
type: string
certificate_authorities:
type: string
elastic_agent_cert:
type: string
elastic_agent_cert_key:
type: string
elastic_agent_cert_key_passphrase:
type: string
headers:
additionalProperties:
type: string
type: object
insecure:
type: boolean
proxy_disabled:
type: boolean
proxy_headers:
additionalProperties:
type: string
type: object
proxy_url:
type: string
replace_token:
type: boolean
staging:
type: boolean
tags:
items:
type: string
type: array
uri:
format: uri
type: string
required:
- uri
- enrollment_token
responses:
'200':
content:
application/json:
schema:
additionalProperties: false
type: object
properties:
actionId:
type: string
required:
- actionId
'400':
content:
application/json:
schema:
additionalProperties: false
description: Generic Error
type: object
properties:
attributes: {}
error:
type: string
errorType:
type: string
message:
type: string
statusCode:
type: number
required:
- message
- attributes
summary: Migrate a single agent
tags:
- Elastic Agents
/api/fleet/agents/{agentId}/reassign:
post:
description: '[Required authorization] Route required privileges: fleet-agents-all.'
@ -22214,107 +22111,6 @@ paths:
summary: Get available agent versions
tags:
- Elastic Agents
/api/fleet/agents/bulk_migrate:
post:
description: 'Bulk migrate agents to another cluster.<br/><br/>[Required authorization] Route required privileges: fleet-agents-all.'
operationId: post-fleet-agents-bulk-migrate
parameters:
- description: A required header to protect against CSRF attacks
in: header
name: kbn-xsrf
required: true
schema:
example: 'true'
type: string
requestBody:
content:
application/json:
schema:
additionalProperties: false
type: object
properties:
agents:
items:
type: string
type: array
enrollment_token:
type: string
settings:
additionalProperties: false
type: object
properties:
ca_sha256:
type: string
certificate_authorities:
type: string
elastic_agent_cert:
type: string
elastic_agent_cert_key:
type: string
elastic_agent_cert_key_passphrase:
type: string
headers:
additionalProperties:
type: string
type: object
insecure:
type: boolean
proxy_disabled:
type: boolean
proxy_headers:
additionalProperties:
type: string
type: object
proxy_url:
type: string
staging:
type: boolean
tags:
items:
type: string
type: array
uri:
format: uri
type: string
required:
- agents
- uri
- enrollment_token
responses:
'200':
content:
application/json:
schema:
additionalProperties: false
type: object
properties:
actionId:
type: string
required:
- actionId
'400':
content:
application/json:
schema:
additionalProperties: false
description: Generic Error
type: object
properties:
attributes: {}
error:
type: string
errorType:
type: string
message:
type: string
statusCode:
type: number
required:
- message
- attributes
summary: Migrate multiple agents
tags:
- Elastic Agents
/api/fleet/agents/bulk_reassign:
post:
description: '[Required authorization] Route required privileges: fleet-agents-all.'

View file

@ -23613,7 +23613,7 @@ paths:
required:
- message
- attributes
summary: Update an agent
summary: Update an agent by ID
tags:
- Elastic Agents
/api/fleet/agents/{agentId}/actions:
@ -23756,109 +23756,6 @@ paths:
summary: Create an agent action
tags:
- Elastic Agent actions
/api/fleet/agents/{agentId}/migrate:
post:
description: 'Migrate a single agent to another cluster.<br/><br/>[Required authorization] Route required privileges: fleet-agents-all.'
operationId: post-fleet-agents-agentid-migrate
parameters:
- description: A required header to protect against CSRF attacks
in: header
name: kbn-xsrf
required: true
schema:
example: 'true'
type: string
- in: path
name: agentId
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
additionalProperties: false
type: object
properties:
enrollment_token:
type: string
settings:
additionalProperties: false
type: object
properties:
ca_sha256:
type: string
certificate_authorities:
type: string
elastic_agent_cert:
type: string
elastic_agent_cert_key:
type: string
elastic_agent_cert_key_passphrase:
type: string
headers:
additionalProperties:
type: string
type: object
insecure:
type: boolean
proxy_disabled:
type: boolean
proxy_headers:
additionalProperties:
type: string
type: object
proxy_url:
type: string
replace_token:
type: boolean
staging:
type: boolean
tags:
items:
type: string
type: array
uri:
format: uri
type: string
required:
- uri
- enrollment_token
responses:
'200':
content:
application/json:
schema:
additionalProperties: false
type: object
properties:
actionId:
type: string
required:
- actionId
'400':
content:
application/json:
schema:
additionalProperties: false
description: Generic Error
type: object
properties:
attributes: {}
error:
type: string
errorType:
type: string
message:
type: string
statusCode:
type: number
required:
- message
- attributes
summary: Migrate a single agent
tags:
- Elastic Agents
/api/fleet/agents/{agentId}/reassign:
post:
description: '[Required authorization] Route required privileges: fleet-agents-all.'
@ -24456,107 +24353,6 @@ paths:
summary: Get available agent versions
tags:
- Elastic Agents
/api/fleet/agents/bulk_migrate:
post:
description: 'Bulk migrate agents to another cluster.<br/><br/>[Required authorization] Route required privileges: fleet-agents-all.'
operationId: post-fleet-agents-bulk-migrate
parameters:
- description: A required header to protect against CSRF attacks
in: header
name: kbn-xsrf
required: true
schema:
example: 'true'
type: string
requestBody:
content:
application/json:
schema:
additionalProperties: false
type: object
properties:
agents:
items:
type: string
type: array
enrollment_token:
type: string
settings:
additionalProperties: false
type: object
properties:
ca_sha256:
type: string
certificate_authorities:
type: string
elastic_agent_cert:
type: string
elastic_agent_cert_key:
type: string
elastic_agent_cert_key_passphrase:
type: string
headers:
additionalProperties:
type: string
type: object
insecure:
type: boolean
proxy_disabled:
type: boolean
proxy_headers:
additionalProperties:
type: string
type: object
proxy_url:
type: string
staging:
type: boolean
tags:
items:
type: string
type: array
uri:
format: uri
type: string
required:
- agents
- uri
- enrollment_token
responses:
'200':
content:
application/json:
schema:
additionalProperties: false
type: object
properties:
actionId:
type: string
required:
- actionId
'400':
content:
application/json:
schema:
additionalProperties: false
description: Generic Error
type: object
properties:
attributes: {}
error:
type: string
errorType:
type: string
message:
type: string
statusCode:
type: number
required:
- message
- attributes
summary: Migrate multiple agents
tags:
- Elastic Agents
/api/fleet/agents/bulk_reassign:
post:
description: '[Required authorization] Route required privileges: fleet-agents-all.'

View file

@ -15,6 +15,7 @@ const _allowedExperimentalValues = {
enableSSLSecrets: false,
installedIntegrationsTabularUI: true,
enabledUpgradeAgentlessDeploymentsTask: true,
enableAgentMigrations: false,
};
/**

View file

@ -53,7 +53,7 @@ function renderTableRowActions({
}
describe('TableRowActions', () => {
beforeEach(() => {
mockedExperimentalFeaturesService.get.mockReturnValue({} as any);
mockedExperimentalFeaturesService.get.mockReturnValue({ enableAgentMigrations: true } as any); // mock the flag as true so the test runs and the table action item renders
mockedUseAuthz.mockReturnValue({
fleet: {
all: true,
@ -128,6 +128,24 @@ describe('TableRowActions', () => {
} as AgentPolicy,
});
expect(res).toBe(null);
});
it('should not render an active action button when feature flag is disabled', async () => {
mockedExperimentalFeaturesService.get.mockReturnValue({
enableAgentMigrations: false,
} as any);
const res = renderAndGetMigrateButton({
agent: {
active: true,
status: 'online',
local_metadata: { elastic: { agent: { version: '8.8.0' } } },
} as any,
agentPolicy: {
is_managed: false,
is_protected: false,
} as AgentPolicy,
});
expect(res).toBe(null);
});
});

View file

@ -20,6 +20,7 @@ import { useLink } from '../../../../hooks';
import { useAuthz } from '../../../../../../hooks/use_authz';
import { ContextMenuActions } from '../../../../components';
import { isAgentUpgradeable } from '../../../../services';
import { ExperimentalFeaturesService } from '../../../../services';
export const TableRowActions: React.FunctionComponent<{
agent: Agent;
@ -46,6 +47,7 @@ export const TableRowActions: React.FunctionComponent<{
const authz = useAuthz();
const isFleetServerAgent =
agentPolicy?.package_policies?.some((p) => p.package?.name === FLEET_SERVER_PACKAGE) ?? false;
const agentMigrationsEnabled = ExperimentalFeaturesService.get().enableAgentMigrations;
const isUnenrolling = agent.status === 'unenrolling';
const [isMenuOpen, setIsMenuOpen] = useState(false);
const menuItems = [
@ -57,7 +59,7 @@ export const TableRowActions: React.FunctionComponent<{
<FormattedMessage id="xpack.fleet.agentList.viewActionText" defaultMessage="View agent" />
</EuiContextMenuItem>,
];
if (!agentPolicy?.is_protected && !isFleetServerAgent) {
if (!agentPolicy?.is_protected && !isFleetServerAgent && agentMigrationsEnabled) {
menuItems.push(
<EuiContextMenuItem
icon="cluster"

View file

@ -9,6 +9,7 @@ import { schema } from '@kbn/config-schema';
import type { FleetAuthz } from '../../../common';
import { API_VERSIONS } from '../../../common/constants';
import { getRouteRequiredAuthz, type FleetAuthzRouter } from '../../services/security';
import { parseExperimentalConfigValue } from '../../../common/experimental_features';
import { AGENT_API_ROUTES } from '../../constants';
import {
@ -128,70 +129,76 @@ export const registerAPIRoutes = (router: FleetAuthzRouter, config: FleetConfigT
getAgentHandler
);
// Migrate a single agent
router.versioned
.post({
path: AGENT_API_ROUTES.MIGRATE_PATTERN,
security: {
authz: {
requiredPrivileges: [FLEET_API_PRIVILEGES.AGENTS.ALL],
// Migrate
const experimentalFeatures = parseExperimentalConfigValue(config.enableExperimental);
if (experimentalFeatures.enableAgentMigrations) {
// Single agent migration
router.versioned
.post({
path: AGENT_API_ROUTES.MIGRATE_PATTERN,
security: {
authz: {
requiredPrivileges: [FLEET_API_PRIVILEGES.AGENTS.ALL],
},
},
},
summary: `Migrate a single agent`,
description: `Migrate a single agent to another cluster.`,
options: {
tags: ['oas-tag:Elastic Agents'],
},
})
.addVersion(
{
version: API_VERSIONS.public.v1,
validate: {
request: MigrateSingleAgentRequestSchema,
response: {
200: {
body: () => MigrateSingleAgentResponseSchema,
},
400: {
body: genericErrorResponse,
summary: `Migrate a single agent`,
description: `Migrate a single agent to another cluster.`,
options: {
tags: ['oas-tag:Elastic Agents'],
},
})
.addVersion(
{
version: API_VERSIONS.public.v1,
validate: {
request: MigrateSingleAgentRequestSchema,
response: {
200: {
body: () => MigrateSingleAgentResponseSchema,
},
400: {
body: genericErrorResponse,
},
},
},
},
},
migrateSingleAgentHandler
);
// Bulk migrate multiple agents
router.versioned
.post({
path: AGENT_API_ROUTES.BULK_MIGRATE_PATTERN,
security: {
authz: {
requiredPrivileges: [FLEET_API_PRIVILEGES.AGENTS.ALL],
migrateSingleAgentHandler
);
// Bulk migrate multiple agents
router.versioned
.post({
path: AGENT_API_ROUTES.BULK_MIGRATE_PATTERN,
security: {
authz: {
requiredPrivileges: [FLEET_API_PRIVILEGES.AGENTS.ALL],
},
},
},
summary: `Migrate multiple agents`,
description: `Bulk migrate agents to another cluster.`,
options: {
tags: ['oas-tag:Elastic Agents'],
},
})
.addVersion(
{
version: API_VERSIONS.public.v1,
validate: {
request: BulkMigrateAgentsRequestSchema,
response: {
200: {
body: () => BulkMigrateAgentsResponseSchema,
},
400: {
body: genericErrorResponse,
summary: `Migrate multiple agents`,
description: `Bulk migrate agents to another cluster.`,
options: {
tags: ['oas-tag:Elastic Agents'],
},
})
.addVersion(
{
version: API_VERSIONS.public.v1,
validate: {
request: BulkMigrateAgentsRequestSchema,
response: {
200: {
body: () => BulkMigrateAgentsResponseSchema,
},
400: {
body: genericErrorResponse,
},
},
},
},
},
bulkMigrateAgentsHandler
);
bulkMigrateAgentsHandler
);
}
// Update
router.versioned
.put({
@ -201,7 +208,7 @@ export const registerAPIRoutes = (router: FleetAuthzRouter, config: FleetConfigT
requiredPrivileges: [FLEET_API_PRIVILEGES.AGENTS.ALL],
},
},
summary: `Update an agent`,
summary: `Update an agent by ID`,
description: `Update an agent by ID.`,
options: {
tags: ['oas-tag:Elastic Agents'],

View file

@ -23,6 +23,7 @@ export const migrateSingleAgentHandler: FleetRequestHandler<
const esClient = coreContext.elasticsearch.client.asInternalUser;
const soClient = coreContext.savedObjects.client;
const options = request.body;
// First validate the agent exists
const agent = await AgentService.getAgentById(esClient, soClient, request.params.agentId);
// Using the agent id, get the agent policy

View file

@ -6,7 +6,6 @@
*/
import { AGENTS_INDEX } from '@kbn/fleet-plugin/common';
import { FtrProviderContext } from '../../../api_integration/ftr_provider_context';
export default function (providerContext: FtrProviderContext) {

View file

@ -86,7 +86,10 @@ export default async function ({ readConfigFile, log }: FtrConfigProviderContext
'./apis/fixtures/package_verification/signatures/fleet_test_key_public.asc'
)}`,
`--xpack.securitySolution.enableExperimental=${JSON.stringify(['endpointRbacEnabled'])}`,
`--xpack.fleet.enableExperimental=${JSON.stringify(['enableAutomaticAgentUpgrades'])}`,
`--xpack.fleet.enableExperimental=${JSON.stringify([
'enableAutomaticAgentUpgrades',
'enableAgentMigrations',
])}`,
`--xpack.cloud.id='123456789'`,
`--xpack.fleet.agentless.enabled=true`,
`--xpack.fleet.agentless.api.url=http://localhost:8089/agentless-api`,