[Fleet] Make API responses consistent (#119494)

* make apis consistent

* UI and test fixes

* test fixes

* fixed test

* fix tests

* fix test

* removed deprecated shared_id from openapi spec

* added back list prop as deprecated

* renamed apis with hyphens

* openapi update

* fix checks

* fix test

* renamed epm api path and response

* fix tests

* fix ml

* moved splitPkgKey

* fixed edit package policy page

* fixed storybook

* fix prettier after conflict

* fix tests

* fix tests

* fix tests

* fix test

* fix test

* added back semver validation

* fix test

* pkgVersion optional

* fix tests

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Julia Bardi 2021-12-08 13:04:04 +01:00 committed by GitHub
parent 2e57f00253
commit b1a038ddc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
98 changed files with 1596 additions and 465 deletions

View file

@ -18,8 +18,8 @@ export const LIMITED_CONCURRENCY_ROUTE_TAG = 'ingest:limited-concurrency';
// EPM API routes
const EPM_PACKAGES_MANY = `${EPM_API_ROOT}/packages`;
const EPM_PACKAGES_BULK = `${EPM_PACKAGES_MANY}/_bulk`;
const EPM_PACKAGES_ONE = `${EPM_PACKAGES_MANY}/{pkgkey}`;
const EPM_PACKAGES_FILE = `${EPM_PACKAGES_MANY}/{pkgName}/{pkgVersion}`;
const EPM_PACKAGES_ONE_DEPRECATED = `${EPM_PACKAGES_MANY}/{pkgkey}`;
const EPM_PACKAGES_ONE = `${EPM_PACKAGES_MANY}/{pkgName}/{pkgVersion}`;
export const EPM_API_ROUTES = {
BULK_INSTALL_PATTERN: EPM_PACKAGES_BULK,
LIST_PATTERN: EPM_PACKAGES_MANY,
@ -28,9 +28,13 @@ export const EPM_API_ROUTES = {
INSTALL_FROM_REGISTRY_PATTERN: EPM_PACKAGES_ONE,
INSTALL_BY_UPLOAD_PATTERN: EPM_PACKAGES_MANY,
DELETE_PATTERN: EPM_PACKAGES_ONE,
FILEPATH_PATTERN: `${EPM_PACKAGES_FILE}/{filePath*}`,
FILEPATH_PATTERN: `${EPM_PACKAGES_ONE}/{filePath*}`,
CATEGORIES_PATTERN: `${EPM_API_ROOT}/categories`,
STATS_PATTERN: `${EPM_PACKAGES_MANY}/{pkgName}/stats`,
INFO_PATTERN_DEPRECATED: EPM_PACKAGES_ONE_DEPRECATED,
INSTALL_FROM_REGISTRY_PATTERN_DEPRECATED: EPM_PACKAGES_ONE_DEPRECATED,
DELETE_PATTERN_DEPRECATED: EPM_PACKAGES_ONE_DEPRECATED,
};
// Data stream API routes
@ -79,7 +83,9 @@ export const SETTINGS_API_ROUTES = {
// App API routes
export const APP_API_ROUTES = {
CHECK_PERMISSIONS_PATTERN: `${API_ROOT}/check-permissions`,
GENERATE_SERVICE_TOKEN_PATTERN: `${API_ROOT}/service-tokens`,
GENERATE_SERVICE_TOKEN_PATTERN: `${API_ROOT}/service_tokens`,
// deprecated since 8.0
GENERATE_SERVICE_TOKEN_PATTERN_DEPRECATED: `${API_ROOT}/service-tokens`,
};
// Agent API routes
@ -95,16 +101,23 @@ export const AGENT_API_ROUTES = {
BULK_UNENROLL_PATTERN: `${API_ROOT}/agents/bulk_unenroll`,
REASSIGN_PATTERN: `${API_ROOT}/agents/{agentId}/reassign`,
BULK_REASSIGN_PATTERN: `${API_ROOT}/agents/bulk_reassign`,
STATUS_PATTERN: `${API_ROOT}/agent-status`,
STATUS_PATTERN: `${API_ROOT}/agent_status`,
// deprecated since 8.0
STATUS_PATTERN_DEPRECATED: `${API_ROOT}/agent-status`,
UPGRADE_PATTERN: `${API_ROOT}/agents/{agentId}/upgrade`,
BULK_UPGRADE_PATTERN: `${API_ROOT}/agents/bulk_upgrade`,
};
export const ENROLLMENT_API_KEY_ROUTES = {
CREATE_PATTERN: `${API_ROOT}/enrollment-api-keys`,
LIST_PATTERN: `${API_ROOT}/enrollment-api-keys`,
INFO_PATTERN: `${API_ROOT}/enrollment-api-keys/{keyId}`,
DELETE_PATTERN: `${API_ROOT}/enrollment-api-keys/{keyId}`,
CREATE_PATTERN: `${API_ROOT}/enrollment_api_keys`,
LIST_PATTERN: `${API_ROOT}/enrollment_api_keys`,
INFO_PATTERN: `${API_ROOT}/enrollment_api_keys/{keyId}`,
DELETE_PATTERN: `${API_ROOT}/enrollment_api_keys/{keyId}`,
// deprecated since 8.0
CREATE_PATTERN_DEPRECATED: `${API_ROOT}/enrollment-api-keys`,
LIST_PATTERN_DEPRECATED: `${API_ROOT}/enrollment-api-keys`,
INFO_PATTERN_DEPRECATED: `${API_ROOT}/enrollment-api-keys/{keyId}`,
DELETE_PATTERN_DEPRECATED: `${API_ROOT}/enrollment-api-keys/{keyId}`,
};
// Agents setup API routes

View file

@ -157,6 +157,7 @@
"parameters": []
},
"/epm/packages/{pkgkey}": {
"deprecated": true,
"get": {
"summary": "Packages - Info",
"tags": [],
@ -352,6 +353,210 @@
}
}
},
"/epm/packages/{pkgName}/{pkgVersion}": {
"get": {
"summary": "Packages - Info",
"tags": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"allOf": [
{
"properties": {
"item": {
"$ref": "#/components/schemas/package_info"
}
}
},
{
"properties": {
"status": {
"type": "string",
"enum": [
"installed",
"installing",
"install_failed",
"not_installed"
]
},
"savedObject": {
"type": "string"
}
},
"required": [
"status",
"savedObject"
]
}
]
}
}
}
}
},
"operationId": "get-package",
"security": [
{
"basicAuth": []
}
]
},
"parameters": [
{
"schema": {
"type": "string"
},
"name": "pkgName",
"in": "path",
"required": true
},
{
"schema": {
"type": "string"
},
"name": "pkgVersion",
"in": "path",
"required": true
}
],
"post": {
"summary": "Packages - Install",
"tags": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"oneOf": [
{
"$ref": "#/components/schemas/kibana_saved_object_type"
},
{
"$ref": "#/components/schemas/elasticsearch_asset_type"
}
]
}
},
"required": [
"id",
"type"
]
}
}
},
"required": [
"items"
]
}
}
}
}
},
"operationId": "install-package",
"description": "",
"parameters": [
{
"$ref": "#/components/parameters/kbn_xsrf"
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"force": {
"type": "boolean"
}
}
}
}
}
}
},
"delete": {
"summary": "Packages - Delete",
"tags": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"oneOf": [
{
"$ref": "#/components/schemas/kibana_saved_object_type"
},
{
"$ref": "#/components/schemas/elasticsearch_asset_type"
}
]
}
},
"required": [
"id",
"type"
]
}
}
},
"required": [
"items"
]
}
}
}
}
},
"operationId": "delete-package",
"parameters": [
{
"$ref": "#/components/parameters/kbn_xsrf"
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"force": {
"type": "boolean"
}
}
}
}
}
}
}
},
"/agents/setup": {
"get": {
"summary": "Agents setup - Info",
@ -419,6 +624,72 @@
}
},
"/agent-status": {
"deprecated": true,
"get": {
"summary": "Agents - Summary stats",
"tags": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "integer"
},
"events": {
"type": "integer"
},
"inactive": {
"type": "integer"
},
"offline": {
"type": "integer"
},
"online": {
"type": "integer"
},
"other": {
"type": "integer"
},
"total": {
"type": "integer"
},
"updating": {
"type": "integer"
}
},
"required": [
"error",
"events",
"inactive",
"offline",
"online",
"other",
"total",
"updating"
]
}
}
}
}
},
"operationId": "get-agent-status",
"parameters": [
{
"schema": {
"type": "string"
},
"name": "policyId",
"in": "query",
"required": false
}
]
}
},
"/agent_status": {
"get": {
"summary": "Agents - Summary stats",
"tags": [],
@ -496,6 +767,13 @@
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/components/schemas/agent"
},
"deprecated": true
},
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/agent"
@ -512,7 +790,7 @@
}
},
"required": [
"list",
"items",
"total",
"page",
"perPage"
@ -1294,6 +1572,7 @@
"parameters": []
},
"/enrollment-api-keys": {
"deprecated": true,
"get": {
"summary": "Enrollment API Keys - List",
"tags": [],
@ -1306,6 +1585,13 @@
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/components/schemas/enrollment_api_key"
},
"deprecated": true
},
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/enrollment_api_key"
@ -1322,7 +1608,7 @@
}
},
"required": [
"list",
"items",
"page",
"perPage",
"total"
@ -1370,6 +1656,160 @@
}
},
"/enrollment-api-keys/{keyId}": {
"deprecated": true,
"parameters": [
{
"schema": {
"type": "string"
},
"name": "keyId",
"in": "path",
"required": true
}
],
"get": {
"summary": "Enrollment API Key - Info",
"tags": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"item": {
"$ref": "#/components/schemas/enrollment_api_key"
}
},
"required": [
"item"
]
}
}
}
}
},
"operationId": "get-enrollment-api-key"
},
"delete": {
"summary": "Enrollment API Key - Delete",
"tags": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"deleted"
]
}
},
"required": [
"action"
]
}
}
}
}
},
"operationId": "delete-enrollment-api-key",
"parameters": [
{
"$ref": "#/components/parameters/kbn_xsrf"
}
]
}
},
"/enrollment_api_keys": {
"get": {
"summary": "Enrollment API Keys - List",
"tags": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/components/schemas/enrollment_api_key"
},
"deprecated": true
},
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/enrollment_api_key"
}
},
"page": {
"type": "number"
},
"perPage": {
"type": "number"
},
"total": {
"type": "number"
}
},
"required": [
"items",
"page",
"perPage",
"total"
]
}
}
}
}
},
"operationId": "get-enrollment-api-keys",
"parameters": []
},
"post": {
"summary": "Enrollment API Key - Create",
"tags": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"item": {
"$ref": "#/components/schemas/enrollment_api_key"
},
"action": {
"type": "string",
"enum": [
"created"
]
}
}
}
}
}
}
},
"operationId": "create-enrollment-api-keys",
"parameters": [
{
"$ref": "#/components/parameters/kbn_xsrf"
}
]
}
},
"/enrollment_api_keys/{keyId}": {
"parameters": [
{
"schema": {
@ -2520,10 +2960,6 @@
"unenrollment_started_at": {
"type": "string"
},
"shared_id": {
"type": "string",
"deprecated": true
},
"access_api_key_id": {
"type": "string"
},

View file

@ -100,6 +100,7 @@ paths:
operationId: list-all-packages
parameters: []
/epm/packages/{pkgkey}:
deprecated: true
get:
summary: Packages - Info
tags: []
@ -213,6 +214,125 @@ paths:
properties:
force:
type: boolean
/epm/packages/{pkgName}/{pkgVersion}:
get:
summary: Packages - Info
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
allOf:
- properties:
item:
$ref: '#/components/schemas/package_info'
- properties:
status:
type: string
enum:
- installed
- installing
- install_failed
- not_installed
savedObject:
type: string
required:
- status
- savedObject
operationId: get-package
security:
- basicAuth: []
parameters:
- schema:
type: string
name: pkgName
in: path
required: true
- schema:
type: string
name: pkgVersion
in: path
required: true
post:
summary: Packages - Install
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
type: object
properties:
id:
type: string
type:
oneOf:
- $ref: '#/components/schemas/kibana_saved_object_type'
- $ref: '#/components/schemas/elasticsearch_asset_type'
required:
- id
- type
required:
- items
operationId: install-package
description: ''
parameters:
- $ref: '#/components/parameters/kbn_xsrf'
requestBody:
content:
application/json:
schema:
type: object
properties:
force:
type: boolean
delete:
summary: Packages - Delete
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
type: object
properties:
id:
type: string
type:
oneOf:
- $ref: '#/components/schemas/kibana_saved_object_type'
- $ref: '#/components/schemas/elasticsearch_asset_type'
required:
- id
- type
required:
- items
operationId: delete-package
parameters:
- $ref: '#/components/parameters/kbn_xsrf'
requestBody:
content:
application/json:
schema:
type: object
properties:
force:
type: boolean
/agents/setup:
get:
summary: Agents setup - Info
@ -253,6 +373,51 @@ paths:
parameters:
- $ref: '#/components/parameters/kbn_xsrf'
/agent-status:
deprecated: true
get:
summary: Agents - Summary stats
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
error:
type: integer
events:
type: integer
inactive:
type: integer
offline:
type: integer
online:
type: integer
other:
type: integer
total:
type: integer
updating:
type: integer
required:
- error
- events
- inactive
- offline
- online
- other
- total
- updating
operationId: get-agent-status
parameters:
- schema:
type: string
name: policyId
in: query
required: false
/agent_status:
get:
summary: Agents - Summary stats
tags: []
@ -312,6 +477,11 @@ paths:
type: array
items:
$ref: '#/components/schemas/agent'
deprecated: true
items:
type: array
items:
$ref: '#/components/schemas/agent'
total:
type: number
page:
@ -319,7 +489,7 @@ paths:
perPage:
type: number
required:
- list
- items
- total
- page
- perPage
@ -784,6 +954,7 @@ paths:
- $ref: '#/components/parameters/kbn_xsrf'
parameters: []
/enrollment-api-keys:
deprecated: true
get:
summary: Enrollment API Keys - List
tags: []
@ -799,6 +970,11 @@ paths:
type: array
items:
$ref: '#/components/schemas/enrollment_api_key'
deprecated: true
items:
type: array
items:
$ref: '#/components/schemas/enrollment_api_key'
page:
type: number
perPage:
@ -806,7 +982,7 @@ paths:
total:
type: number
required:
- list
- items
- page
- perPage
- total
@ -833,6 +1009,104 @@ paths:
parameters:
- $ref: '#/components/parameters/kbn_xsrf'
/enrollment-api-keys/{keyId}:
deprecated: true
parameters:
- schema:
type: string
name: keyId
in: path
required: true
get:
summary: Enrollment API Key - Info
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
item:
$ref: '#/components/schemas/enrollment_api_key'
required:
- item
operationId: get-enrollment-api-key
delete:
summary: Enrollment API Key - Delete
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
action:
type: string
enum:
- deleted
required:
- action
operationId: delete-enrollment-api-key
parameters:
- $ref: '#/components/parameters/kbn_xsrf'
/enrollment_api_keys:
get:
summary: Enrollment API Keys - List
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
list:
type: array
items:
$ref: '#/components/schemas/enrollment_api_key'
deprecated: true
items:
type: array
items:
$ref: '#/components/schemas/enrollment_api_key'
page:
type: number
perPage:
type: number
total:
type: number
required:
- items
- page
- perPage
- total
operationId: get-enrollment-api-keys
parameters: []
post:
summary: Enrollment API Key - Create
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
item:
$ref: '#/components/schemas/enrollment_api_key'
action:
type: string
enum:
- created
operationId: create-enrollment-api-keys
parameters:
- $ref: '#/components/parameters/kbn_xsrf'
/enrollment_api_keys/{keyId}:
parameters:
- schema:
type: string
@ -1582,9 +1856,6 @@ components:
type: string
unenrollment_started_at:
type: string
shared_id:
type: string
deprecated: true
access_api_key_id:
type: string
default_api_key_id:

View file

@ -11,9 +11,6 @@ properties:
type: string
unenrollment_started_at:
type: string
shared_id:
type: string
deprecated: true
access_api_key_id:
type: string
default_api_key_id:

View file

@ -25,11 +25,17 @@ paths:
$ref: paths/epm@packages.yaml
'/epm/packages/{pkgkey}':
$ref: 'paths/epm@packages@{pkgkey}.yaml'
deprecated: true
'/epm/packages/{pkgName}/{pkgVersion}':
$ref: 'paths/epm@packages@{pkg_name}@{pkg_version}.yaml'
# Agent-related endpoints
/agents/setup:
$ref: paths/agents@setup.yaml
/agent-status:
$ref: paths/agent_status.yaml
deprecated: true
/agent_status:
$ref: paths/agent_status.yaml
/agents:
$ref: paths/agents.yaml
/agents/bulk_upgrade:
@ -56,7 +62,13 @@ paths:
$ref: paths/agent_policies@delete.yaml
/enrollment-api-keys:
$ref: paths/enrollment_api_keys.yaml
deprecated: true
'/enrollment-api-keys/{keyId}':
$ref: 'paths/enrollment_api_keys@{key_id}.yaml'
deprecated: true
/enrollment_api_keys:
$ref: paths/enrollment_api_keys.yaml
'/enrollment_api_keys/{keyId}':
$ref: 'paths/enrollment_api_keys@{key_id}.yaml'
/package_policies:
$ref: paths/package_policies.yaml

View file

@ -13,6 +13,11 @@ get:
type: array
items:
$ref: ../components/schemas/agent.yaml
deprecated: true
items:
type: array
items:
$ref: ../components/schemas/agent.yaml
total:
type: number
page:
@ -20,7 +25,7 @@ get:
perPage:
type: number
required:
- list
- items
- total
- page
- perPage

View file

@ -13,6 +13,11 @@ get:
type: array
items:
$ref: ../components/schemas/enrollment_api_key.yaml
deprecated: true
items:
type: array
items:
$ref: ../components/schemas/enrollment_api_key.yaml
page:
type: number
perPage:
@ -20,7 +25,7 @@ get:
total:
type: number
required:
- list
- items
- page
- perPage
- total

View file

@ -0,0 +1,118 @@
get:
summary: Packages - Info
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
allOf:
- properties:
item:
$ref: ../components/schemas/package_info.yaml
- properties:
status:
type: string
enum:
- installed
- installing
- install_failed
- not_installed
savedObject:
type: string
required:
- status
- savedObject
operationId: get-package
security:
- basicAuth: []
parameters:
- schema:
type: string
name: pkgName
in: path
required: true
- schema:
type: string
name: pkgVersion
in: path
required: true
post:
summary: Packages - Install
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
type: object
properties:
id:
type: string
type:
oneOf:
- $ref: ../components/schemas/kibana_saved_object_type.yaml
- $ref: ../components/schemas/elasticsearch_asset_type.yaml
required:
- id
- type
required:
- items
operationId: install-package
description: ''
parameters:
- $ref: ../components/headers/kbn_xsrf.yaml
requestBody:
content:
application/json:
schema:
type: object
properties:
force:
type: boolean
delete:
summary: Packages - Delete
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
type: object
properties:
id:
type: string
type:
oneOf:
- $ref: ../components/schemas/kibana_saved_object_type.yaml
- $ref: ../components/schemas/elasticsearch_asset_type.yaml
required:
- id
- type
required:
- items
operationId: delete-package
parameters:
- $ref: ../components/headers/kbn_xsrf.yaml
requestBody:
content:
application/json:
schema:
type: object
properties:
force:
type: boolean

View file

@ -34,3 +34,4 @@ export {
} from './validate_package_policy';
export { normalizeHostsForAgents } from './hosts_utils';
export { splitPkgKey } from './split_pkg_key';

View file

@ -33,8 +33,11 @@ export const epmRouteService = {
return EPM_API_ROUTES.LIMITED_LIST_PATTERN;
},
getInfoPath: (pkgkey: string) => {
return EPM_API_ROUTES.INFO_PATTERN.replace('{pkgkey}', pkgkey);
getInfoPath: (pkgName: string, pkgVersion: string) => {
return EPM_API_ROUTES.INFO_PATTERN.replace('{pkgName}', pkgName).replace(
'{pkgVersion}',
pkgVersion
);
},
getStatsPath: (pkgName: string) => {
@ -45,23 +48,27 @@ export const epmRouteService = {
return `${EPM_API_ROOT}${filePath.replace('/package', '/packages')}`;
},
getInstallPath: (pkgkey: string) => {
return EPM_API_ROUTES.INSTALL_FROM_REGISTRY_PATTERN.replace('{pkgkey}', pkgkey).replace(
/\/$/,
''
); // trim trailing slash
getInstallPath: (pkgName: string, pkgVersion: string) => {
return EPM_API_ROUTES.INSTALL_FROM_REGISTRY_PATTERN.replace('{pkgName}', pkgName)
.replace('{pkgVersion}', pkgVersion)
.replace(/\/$/, ''); // trim trailing slash
},
getBulkInstallPath: () => {
return EPM_API_ROUTES.BULK_INSTALL_PATTERN;
},
getRemovePath: (pkgkey: string) => {
return EPM_API_ROUTES.DELETE_PATTERN.replace('{pkgkey}', pkgkey).replace(/\/$/, ''); // trim trailing slash
getRemovePath: (pkgName: string, pkgVersion: string) => {
return EPM_API_ROUTES.DELETE_PATTERN.replace('{pkgName}', pkgName)
.replace('{pkgVersion}', pkgVersion)
.replace(/\/$/, ''); // trim trailing slash
},
getUpdatePath: (pkgkey: string) => {
return EPM_API_ROUTES.INFO_PATTERN.replace('{pkgkey}', pkgkey);
getUpdatePath: (pkgName: string, pkgVersion: string) => {
return EPM_API_ROUTES.INFO_PATTERN.replace('{pkgName}', pkgName).replace(
'{pkgVersion}',
pkgVersion
);
},
};

View file

@ -0,0 +1,34 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import semverValid from 'semver/functions/valid';
/**
* Extract the package name and package version from a string.
*
* @param pkgkey a string containing the package name delimited by the package version
*/
export function splitPkgKey(pkgkey: string): { pkgName: string; pkgVersion: string } {
// If no version is provided, use the provided package key as the
// package name and return an empty version value
if (!pkgkey.includes('-')) {
return { pkgName: pkgkey, pkgVersion: '' };
}
const pkgName = pkgkey.includes('-') ? pkgkey.substr(0, pkgkey.indexOf('-')) : pkgkey;
if (pkgName === '') {
throw new Error('Package key parsing failed: package name was empty');
}
// this will return the entire string if `indexOf` return -1
const pkgVersion = pkgkey.substr(pkgkey.indexOf('-') + 1);
if (!semverValid(pkgVersion)) {
throw new Error('Package key parsing failed: package version was not a valid semver');
}
return { pkgName, pkgVersion };
}

View file

@ -7,22 +7,19 @@
import type { Agent, AgentAction, NewAgentAction } from '../models';
import type { ListResult, ListWithKuery } from './common';
export interface GetAgentsRequest {
query: {
page: number;
perPage: number;
kuery?: string;
query: ListWithKuery & {
showInactive: boolean;
showUpgradeable?: boolean;
};
}
export interface GetAgentsResponse {
list: Agent[];
total: number;
export interface GetAgentsResponse extends ListResult<Agent> {
totalInactive: number;
page: number;
perPage: number;
// deprecated in 8.x
list?: Agent[];
}
export interface GetOneAgentRequest {

View file

@ -7,7 +7,7 @@
import type { AgentPolicy, NewAgentPolicy, FullAgentPolicy } from '../models';
import type { ListWithKuery } from './common';
import type { ListResult, ListWithKuery } from './common';
export interface GetAgentPoliciesRequest {
query: ListWithKuery & {
@ -17,12 +17,7 @@ export interface GetAgentPoliciesRequest {
export type GetAgentPoliciesResponseItem = AgentPolicy & { agents?: number };
export interface GetAgentPoliciesResponse {
items: GetAgentPoliciesResponseItem[];
total: number;
page: number;
perPage: number;
}
export type GetAgentPoliciesResponse = ListResult<GetAgentPoliciesResponseItem>;
export interface GetOneAgentPolicyRequest {
params: {

View file

@ -7,20 +7,16 @@
import type { EnrollmentAPIKey } from '../models';
import type { ListResult, ListWithKuery } from './common';
export interface GetEnrollmentAPIKeysRequest {
query: {
page: number;
perPage: number;
kuery?: string;
};
query: ListWithKuery;
}
export interface GetEnrollmentAPIKeysResponse {
list: EnrollmentAPIKey[];
total: number;
page: number;
perPage: number;
}
export type GetEnrollmentAPIKeysResponse = ListResult<EnrollmentAPIKey> & {
// deprecated in 8.x
list?: EnrollmentAPIKey[];
};
export interface GetOneEnrollmentAPIKeyRequest {
params: {

View file

@ -22,7 +22,9 @@ export interface GetCategoriesRequest {
}
export interface GetCategoriesResponse {
response: CategorySummaryList;
items: CategorySummaryList;
// deprecated in 8.0
response?: CategorySummaryList;
}
export interface GetPackagesRequest {
@ -33,33 +35,46 @@ export interface GetPackagesRequest {
}
export interface GetPackagesResponse {
response: PackageList;
items: PackageList;
// deprecated in 8.0
response?: PackageList;
}
export interface GetLimitedPackagesResponse {
response: string[];
items: string[];
// deprecated in 8.0
response?: string[];
}
export interface GetFileRequest {
params: {
pkgkey: string;
pkgName: string;
pkgVersion: string;
filePath: string;
};
}
export interface GetInfoRequest {
params: {
pkgkey: string;
// deprecated in 8.0
pkgkey?: string;
pkgName: string;
pkgVersion: string;
};
}
export interface GetInfoResponse {
response: PackageInfo;
item: PackageInfo;
// deprecated in 8.0
response?: PackageInfo;
}
export interface UpdatePackageRequest {
params: {
pkgkey: string;
// deprecated in 8.0
pkgkey?: string;
pkgName: string;
pkgVersion: string;
};
body: {
keepPoliciesUpToDate?: boolean;
@ -67,7 +82,9 @@ export interface UpdatePackageRequest {
}
export interface UpdatePackageResponse {
response: PackageInfo;
item: PackageInfo;
// deprecated in 8.0
response?: PackageInfo;
}
export interface GetStatsRequest {
@ -82,12 +99,17 @@ export interface GetStatsResponse {
export interface InstallPackageRequest {
params: {
pkgkey: string;
// deprecated in 8.0
pkgkey?: string;
pkgName: string;
pkgVersion: string;
};
}
export interface InstallPackageResponse {
response: AssetReference[];
items: AssetReference[];
// deprecated in 8.0
response?: AssetReference[];
}
export interface IBulkInstallPackageHTTPError {
@ -110,7 +132,9 @@ export interface BulkInstallPackageInfo {
}
export interface BulkInstallPackagesResponse {
response: Array<BulkInstallPackageInfo | IBulkInstallPackageHTTPError>;
items: Array<BulkInstallPackageInfo | IBulkInstallPackageHTTPError>;
// deprecated in 8.0
response?: Array<BulkInstallPackageInfo | IBulkInstallPackageHTTPError>;
}
export interface BulkInstallPackagesRequest {
@ -125,10 +149,15 @@ export interface MessageResponse {
export interface DeletePackageRequest {
params: {
pkgkey: string;
// deprecated in 8.0
pkgkey?: string;
pkgName: string;
pkgVersion: string;
};
}
export interface DeletePackageResponse {
response: AssetReference[];
// deprecated in 8.0
response?: AssetReference[];
items: AssetReference[];
}

View file

@ -7,6 +7,8 @@
import type { Output } from '../models';
import type { ListResult } from './common';
export interface GetOneOutputResponse {
item: Output;
}
@ -53,9 +55,4 @@ export interface PutOutputResponse {
item: Output;
}
export interface GetOutputsResponse {
items: Output[];
total: number;
page: number;
perPage: number;
}
export type GetOutputsResponse = ListResult<Output>;

View file

@ -13,20 +13,13 @@ import type {
PackagePolicyPackage,
} from '../models';
import type { ListResult, ListWithKuery } from './common';
export interface GetPackagePoliciesRequest {
query: {
page: number;
perPage: number;
kuery?: string;
};
query: ListWithKuery;
}
export interface GetPackagePoliciesResponse {
items: PackagePolicy[];
total: number;
page: number;
perPage: number;
}
export type GetPackagePoliciesResponse = ListResult<PackagePolicy>;
export interface GetOnePackagePolicyRequest {
params: {

View file

@ -1,5 +1,5 @@
{
"response": {
"item": {
"name": "apache",
"title": "Apache",
"version": "1.1.0",

View file

@ -88,7 +88,7 @@ describe('Add Integration', () => {
fixture: 'integrations/agent_policy.json',
});
// TODO fixture includes 1 package policy, should be empty initially
cy.intercept('GET', '/api/fleet/epm/packages/apache-1.1.0', {
cy.intercept('GET', '/api/fleet/epm/packages/apache/1.1.0', {
fixture: 'integrations/apache.json',
});
addAndVerifyIntegration();

View file

@ -50,7 +50,7 @@ export const deleteIntegrations = async (integration: string) => {
export const installPackageWithVersion = (integration: string, version: string) => {
cy.request({
url: `/api/fleet/epm/packages/${integration}-${version}`,
url: `/api/fleet/epm/packages/${integration}/${version}`,
headers: { 'kbn-xsrf': 'cypress' },
body: '{ "force": true }',
method: 'POST',

View file

@ -14,11 +14,11 @@ curl localhost:5601/api/fleet/epm/packages
Install a package:
```
curl -X POST localhost:5601/api/fleet/epm/packages/iptables-1.0.4
curl -X POST localhost:5601/api/fleet/epm/packages/iptables/1.0.4
```
Delete a package:
```
curl -X DELETE localhost:5601/api/fleet/epm/packages/iptables-1.0.4
curl -X DELETE localhost:5601/api/fleet/epm/packages/iptables/1.0.4
```

View file

@ -24,6 +24,7 @@ import {
import type { EuiStepProps } from '@elastic/eui/src/components/steps/step';
import { safeLoad } from 'js-yaml';
import { splitPkgKey } from '../../../../../../common';
import type {
AgentPolicy,
NewPackagePolicy,
@ -152,15 +153,16 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
// Form state
const [formState, setFormState] = useState<PackagePolicyFormState>('VALID');
const { pkgName, pkgVersion } = splitPkgKey(params.pkgkey);
// Fetch package info
const {
data: packageInfoData,
error: packageInfoError,
isLoading: isPackageInfoLoading,
} = useGetPackageInfoByKey(params.pkgkey);
} = useGetPackageInfoByKey(pkgName, pkgVersion);
const packageInfo = useMemo(() => {
if (packageInfoData && packageInfoData.response) {
return packageInfoData.response;
if (packageInfoData && packageInfoData.item) {
return packageInfoData.item;
}
}, [packageInfoData]);

View file

@ -213,15 +213,16 @@ export const EditPackagePolicyForm = memo<{
}
const { data: packageData } = await sendGetPackageInfoByKey(
pkgKeyFromPackageInfo(_packageInfo!)
_packageInfo!.name,
_packageInfo!.version
);
if (packageData?.response) {
setPackageInfo(packageData.response);
if (packageData?.item) {
setPackageInfo(packageData.item);
const newValidationResults = validatePackagePolicy(
newPackagePolicy,
packageData.response,
packageData.item,
safeLoad
);
setValidationResults(newValidationResults);

View file

@ -308,7 +308,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
inactive: agentsRequest.data.totalInactive,
});
setAgents(agentsRequest.data.list);
setAgents(agentsRequest.data.items);
setTotalAgents(agentsRequest.data.total);
setTotalInactiveAgents(agentsRequest.data.totalInactive);
} catch (error) {

View file

@ -63,7 +63,7 @@ export const FleetServerUpgradeModal: React.FunctionComponent<Props> = ({ onClos
throw res.error;
}
for (const agent of res.data?.list ?? []) {
for (const agent of res.data?.items ?? []) {
if (!agent.policy_id || agentPoliciesAlreadyChecked[agent.policy_id]) {
continue;
}

View file

@ -182,7 +182,7 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => {
const total = enrollmentAPIKeysRequest?.data?.total ?? 0;
const rowItems =
enrollmentAPIKeysRequest?.data?.list.filter((enrollmentKey) => {
enrollmentAPIKeysRequest?.data?.items.filter((enrollmentKey) => {
if (!agentPolicies.length || !enrollmentKey.policy_id) return false;
const agentPolicy = agentPoliciesById[enrollmentKey.policy_id];
return !agentPolicy?.is_managed;

View file

@ -37,7 +37,7 @@ const mockApiCallsWithHealthyFleetServer = (http: MockedFleetStartServices['http
};
}
if (path === '/api/fleet/agent-status') {
if (path === '/api/fleet/agent_status') {
return {
data: {
results: { online: 1, updating: 0, offline: 0 },
@ -65,7 +65,7 @@ const mockApiCallsWithoutHealthyFleetServer = (http: MockedFleetStartServices['h
};
}
if (path === '/api/fleet/agent-status') {
if (path === '/api/fleet/agent_status') {
return {
data: {
results: { online: 0, updating: 0, offline: 1 },

View file

@ -39,8 +39,7 @@ export function useLinks() {
version: string;
}) => {
const imagePath = removeRelativePath(path);
const pkgkey = `${packageName}-${version}`;
const filePath = `${epmRouteService.getInfoPath(pkgkey)}/${imagePath}`;
const filePath = `${epmRouteService.getInfoPath(packageName, version)}/${imagePath}`;
return http.basePath.prepend(filePath);
},
};

View file

@ -61,9 +61,8 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar
const currStatus = getPackageInstallStatus(name);
const newStatus = { ...currStatus, name, status: InstallStatus.installing };
setPackageInstallStatus(newStatus);
const pkgkey = `${name}-${version}`;
const res = await sendInstallPackage(pkgkey);
const res = await sendInstallPackage(name, version);
if (res.error) {
if (fromUpdate) {
// if there is an error during update, set it back to the previous version
@ -126,9 +125,8 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar
redirectToVersion,
}: Pick<PackageInfo, 'name' | 'version' | 'title'> & { redirectToVersion: string }) => {
setPackageInstallStatus({ name, status: InstallStatus.uninstalling, version });
const pkgkey = `${name}-${version}`;
const res = await sendRemovePackage(pkgkey);
const res = await sendRemovePackage(name, version);
if (res.error) {
setPackageInstallStatus({ name, status: InstallStatus.installed, version });
notifications.toasts.addWarning({

View file

@ -75,7 +75,7 @@ describe('when on integration detail', () => {
describe('and the package is not installed', () => {
beforeEach(() => {
const unInstalledPackage = mockedApi.responseProvider.epmGetInfo();
unInstalledPackage.response.status = 'not_installed';
unInstalledPackage.item.status = 'not_installed';
mockedApi.responseProvider.epmGetInfo.mockReturnValue(unInstalledPackage);
render();
});
@ -283,7 +283,7 @@ const mockApiCalls = (
// @ts-ignore
const epmPackageResponse: GetInfoResponse = {
response: {
item: {
name: 'nginx',
title: 'Nginx',
version: '0.3.7',
@ -770,7 +770,7 @@ On Windows, the module was tested with Nginx installed from the Chocolatey repos
http.get.mockImplementation(async (path: any) => {
if (typeof path === 'string') {
if (path === epmRouteService.getInfoPath(`nginx-0.3.7`)) {
if (path === epmRouteService.getInfoPath(`nginx`, `0.3.7`)) {
markApiCallAsHandled();
return mockedApiInterface.responseProvider.epmGetInfo();
}

View file

@ -27,6 +27,7 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import semverLt from 'semver/functions/lt';
import { splitPkgKey } from '../../../../../../../common';
import {
useGetPackageInstallStatus,
useSetPackageInstallStatus,
@ -132,26 +133,27 @@ export function Detail() {
packageInfo.savedObject &&
semverLt(packageInfo.savedObject.attributes.version, packageInfo.latestVersion);
const { pkgName, pkgVersion } = splitPkgKey(pkgkey);
// Fetch package info
const {
data: packageInfoData,
error: packageInfoError,
isLoading: packageInfoLoading,
} = useGetPackageInfoByKey(pkgkey);
} = useGetPackageInfoByKey(pkgName, pkgVersion);
const isLoading = packageInfoLoading || permissionCheck.isLoading;
const showCustomTab =
useUIExtension(packageInfoData?.response.name ?? '', 'package-detail-custom') !== undefined;
useUIExtension(packageInfoData?.item.name ?? '', 'package-detail-custom') !== undefined;
// Track install status state
useEffect(() => {
if (packageInfoData?.response) {
const packageInfoResponse = packageInfoData.response;
if (packageInfoData?.item) {
const packageInfoResponse = packageInfoData.item;
setPackageInfo(packageInfoResponse);
let installedVersion;
const { name } = packageInfoData.response;
const { name } = packageInfoData.item;
if ('savedObject' in packageInfoResponse) {
installedVersion = packageInfoResponse.savedObject.attributes.version;
}

View file

@ -122,7 +122,7 @@ export const SettingsPage: React.FC<Props> = memo(({ packageInfo }: Props) => {
try {
setKeepPoliciesUpToDateSwitchValue((prev) => !prev);
await sendUpdatePackage(`${packageInfo.name}-${packageInfo.version}`, {
await sendUpdatePackage(packageInfo.name, packageInfo.version, {
keepPoliciesUpToDate: !keepPoliciesUpToDateSwitchValue,
});

View file

@ -215,7 +215,7 @@ export const AvailablePackages: React.FC = memo(() => {
category: '',
});
const eprIntegrationList = useMemo(
() => packageListToIntegrationsList(eprPackages?.response || []),
() => packageListToIntegrationsList(eprPackages?.items || []),
[eprPackages]
);
@ -256,7 +256,7 @@ export const AvailablePackages: React.FC = memo(() => {
? []
: mergeCategoriesAndCount(
eprCategories
? (eprCategories.response as Array<{ id: string; title: string; count: number }>)
? (eprCategories.items as Array<{ id: string; title: string; count: number }>)
: [],
cards
);

View file

@ -103,7 +103,7 @@ export const AdvancedAgentAuthenticationSettings: FunctionComponent<Props> = ({
onKeyChange,
}) => {
const { notifications } = useStartServices();
const [enrollmentAPIKeys, setEnrollmentAPIKeys] = useState<GetEnrollmentAPIKeysResponse['list']>(
const [enrollmentAPIKeys, setEnrollmentAPIKeys] = useState<GetEnrollmentAPIKeysResponse['items']>(
[]
);
@ -143,7 +143,7 @@ export const AdvancedAgentAuthenticationSettings: FunctionComponent<Props> = ({
throw new Error('No data while fetching enrollment API keys');
}
const enrollmentAPIKeysResponse = res.data.list.filter(
const enrollmentAPIKeysResponse = res.data.items.filter(
(key) => key.policy_id === agentPolicyId && key.active === true
);

View file

@ -66,11 +66,11 @@ export const usePackageIconType = ({
}
if (tryApi && !paramIcons && !iconList) {
sendGetPackageInfoByKey(cacheKey)
sendGetPackageInfoByKey(packageName, version)
.catch((error) => undefined) // Ignore API errors
.then((res) => {
CACHED_ICONS.delete(cacheKey);
setIconList(res?.data?.response?.icons);
setIconList(res?.data?.item?.icons);
});
}

View file

@ -36,9 +36,8 @@ export const usePackageInstallations = () => {
});
const allInstalledPackages = useMemo(
() =>
(allPackages?.response || []).filter((pkg) => pkg.status === installationStatuses.Installed),
[allPackages?.response]
() => (allPackages?.items || []).filter((pkg) => pkg.status === installationStatuses.Installed),
[allPackages?.items]
);
const updatablePackages = useMemo(

View file

@ -67,9 +67,9 @@ export const useGetLimitedPackages = () => {
});
};
export const useGetPackageInfoByKey = (pkgkey: string) => {
export const useGetPackageInfoByKey = (pkgName: string, pkgVersion: string) => {
return useRequest<GetInfoResponse>({
path: epmRouteService.getInfoPath(pkgkey),
path: epmRouteService.getInfoPath(pkgName, pkgVersion),
method: 'get',
});
};
@ -81,9 +81,9 @@ export const useGetPackageStats = (pkgName: string) => {
});
};
export const sendGetPackageInfoByKey = (pkgkey: string) => {
export const sendGetPackageInfoByKey = (pkgName: string, pkgVersion: string) => {
return sendRequest<GetInfoResponse>({
path: epmRouteService.getInfoPath(pkgkey),
path: epmRouteService.getInfoPath(pkgName, pkgVersion),
method: 'get',
});
};
@ -102,23 +102,27 @@ export const sendGetFileByPath = (filePath: string) => {
});
};
export const sendInstallPackage = (pkgkey: string) => {
export const sendInstallPackage = (pkgName: string, pkgVersion: string) => {
return sendRequest<InstallPackageResponse>({
path: epmRouteService.getInstallPath(pkgkey),
path: epmRouteService.getInstallPath(pkgName, pkgVersion),
method: 'post',
});
};
export const sendRemovePackage = (pkgkey: string) => {
export const sendRemovePackage = (pkgName: string, pkgVersion: string) => {
return sendRequest<DeletePackageResponse>({
path: epmRouteService.getRemovePath(pkgkey),
path: epmRouteService.getRemovePath(pkgName, pkgVersion),
method: 'delete',
});
};
export const sendUpdatePackage = (pkgkey: string, body: UpdatePackageRequest['body']) => {
export const sendUpdatePackage = (
pkgName: string,
pkgVersion: string,
body: UpdatePackageRequest['body']
) => {
return sendRequest<UpdatePackageResponse>({
path: epmRouteService.getUpdatePath(pkgkey),
path: epmRouteService.getUpdatePath(pkgName, pkgVersion),
method: 'put',
body,
});

View file

@ -24,7 +24,7 @@ import { sendGetPackages } from './hooks';
const mockSendGetPackages = sendGetPackages as jest.Mock;
const testResponse: GetPackagesResponse['response'] = [
const testResponse: GetPackagesResponse['items'] = [
{
description: 'test',
download: 'test',

View file

@ -105,7 +105,7 @@ export const createPackageSearchProvider = (core: CoreSetup): GlobalSearchResult
const toSearchResults = (
coreStart: CoreStart,
packagesResponse: GetPackagesResponse['response']
packagesResponse: GetPackagesResponse['items']
): GlobalSearchProviderResult[] => {
return packagesResponse
.flatMap(

View file

@ -122,7 +122,8 @@ export const getAgentsHandler: RequestHandler<
: 0;
const body: GetAgentsResponse = {
list: agents,
list: agents, // deprecated
items: agents,
total,
totalInactive,
page,

View file

@ -116,6 +116,15 @@ export const registerAPIRoutes = (router: IRouter, config: FleetConfigType) => {
},
getAgentStatusForAgentPolicyHandler
);
router.get(
{
path: AGENT_API_ROUTES.STATUS_PATTERN_DEPRECATED,
validate: GetAgentStatusRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-read`] },
},
getAgentStatusForAgentPolicyHandler
);
// upgrade agent
router.post(
{

View file

@ -90,4 +90,13 @@ export const registerRoutes = (router: IRouter) => {
},
generateServiceTokenHandler
);
router.post(
{
path: APP_API_ROUTES.GENERATE_SERVICE_TOKEN_PATTERN_DEPRECATED,
validate: {},
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
generateServiceTokenHandler
);
};

View file

@ -36,7 +36,13 @@ export const getEnrollmentApiKeysHandler: RequestHandler<
perPage: request.query.perPage,
kuery: request.query.kuery,
});
const body: GetEnrollmentAPIKeysResponse = { list: items, total, page, perPage };
const body: GetEnrollmentAPIKeysResponse = {
list: items, // deprecated
items,
total,
page,
perPage,
};
return response.ok({ body });
} catch (error) {

View file

@ -61,4 +61,44 @@ export const registerRoutes = (routers: { superuser: FleetRouter; fleetSetup: Fl
},
postEnrollmentApiKeyHandler
);
routers.fleetSetup.get(
{
path: ENROLLMENT_API_KEY_ROUTES.INFO_PATTERN_DEPRECATED,
validate: GetOneEnrollmentAPIKeyRequestSchema,
// Disable this tag and the automatic RBAC support until elastic/fleet-server access is removed in 8.0
// Required to allow elastic/fleet-server to access this API.
// options: { tags: [`access:${PLUGIN_ID}-read`] },
},
getOneEnrollmentApiKeyHandler
);
routers.superuser.delete(
{
path: ENROLLMENT_API_KEY_ROUTES.DELETE_PATTERN_DEPRECATED,
validate: DeleteEnrollmentAPIKeyRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
deleteEnrollmentApiKeyHandler
);
routers.fleetSetup.get(
{
path: ENROLLMENT_API_KEY_ROUTES.LIST_PATTERN_DEPRECATED,
validate: GetEnrollmentAPIKeysRequestSchema,
// Disable this tag and the automatic RBAC support until elastic/fleet-server access is removed in 8.0
// Required to allow elastic/fleet-server to access this API.
// options: { tags: [`access:${PLUGIN_ID}-read`] },
},
getEnrollmentApiKeysHandler
);
routers.superuser.post(
{
path: ENROLLMENT_API_KEY_ROUTES.CREATE_PATTERN_DEPRECATED,
validate: PostEnrollmentAPIKeyRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
postEnrollmentApiKeyHandler
);
};

View file

@ -9,6 +9,7 @@ import path from 'path';
import type { TypeOf } from '@kbn/config-schema';
import mime from 'mime-types';
import semverValid from 'semver/functions/valid';
import type { ResponseHeaders, KnownHeaders } from 'src/core/server';
import type {
@ -50,8 +51,11 @@ import {
getInstallation,
} from '../../services/epm/packages';
import type { BulkInstallResponse } from '../../services/epm/packages';
import { defaultIngestErrorHandler, ingestErrorToResponseOptions } from '../../errors';
import { splitPkgKey } from '../../services/epm/registry';
import {
defaultIngestErrorHandler,
ingestErrorToResponseOptions,
IngestManagerError,
} from '../../errors';
import { licenseService } from '../../services';
import { getArchiveEntry } from '../../services/epm/archive/cache';
import { getAsset } from '../../services/epm/archive/storage';
@ -65,6 +69,7 @@ export const getCategoriesHandler: FleetRequestHandler<
try {
const res = await getCategories(request.query);
const body: GetCategoriesResponse = {
items: res,
response: res,
};
return response.ok({ body });
@ -84,6 +89,7 @@ export const getListHandler: FleetRequestHandler<
...request.query,
});
const body: GetPackagesResponse = {
items: res,
response: res,
};
return response.ok({
@ -99,6 +105,7 @@ export const getLimitedListHandler: FleetRequestHandler = async (context, reques
const savedObjectsClient = context.fleet.epm.internalSoClient;
const res = await getLimitedPackages({ savedObjectsClient });
const body: GetLimitedPackagesResponse = {
items: res,
response: res,
};
return response.ok({
@ -186,13 +193,18 @@ export const getFileHandler: FleetRequestHandler<TypeOf<typeof GetFileRequestSch
export const getInfoHandler: FleetRequestHandler<TypeOf<typeof GetInfoRequestSchema.params>> =
async (context, request, response) => {
try {
const { pkgkey } = request.params;
const savedObjectsClient = context.fleet.epm.internalSoClient;
// TODO: change epm API to /packageName/version so we don't need to do this
const { pkgName, pkgVersion } = splitPkgKey(pkgkey);
const res = await getPackageInfo({ savedObjectsClient, pkgName, pkgVersion });
const { pkgName, pkgVersion } = request.params;
if (pkgVersion && !semverValid(pkgVersion)) {
throw new IngestManagerError('Package version is not a valid semver');
}
const res = await getPackageInfo({
savedObjectsClient,
pkgName,
pkgVersion: pkgVersion || '',
});
const body: GetInfoResponse = {
response: res,
item: res,
};
return response.ok({ body });
} catch (error) {
@ -206,14 +218,12 @@ export const updatePackageHandler: FleetRequestHandler<
TypeOf<typeof UpdatePackageRequestSchema.body>
> = async (context, request, response) => {
try {
const { pkgkey } = request.params;
const savedObjectsClient = context.fleet.epm.internalSoClient;
const { pkgName } = splitPkgKey(pkgkey);
const { pkgName } = request.params;
const res = await updatePackage({ savedObjectsClient, pkgName, ...request.body });
const body: UpdatePackageResponse = {
response: res,
item: res,
};
return response.ok({ body });
@ -243,18 +253,18 @@ export const installPackageFromRegistryHandler: FleetRequestHandler<
> = async (context, request, response) => {
const savedObjectsClient = context.fleet.epm.internalSoClient;
const esClient = context.core.elasticsearch.client.asInternalUser;
const { pkgkey } = request.params;
const { pkgName, pkgVersion } = request.params;
const res = await installPackage({
installSource: 'registry',
savedObjectsClient,
pkgkey,
pkgkey: pkgVersion ? `${pkgName}-${pkgVersion}` : pkgName,
esClient,
force: request.body?.force,
});
if (!res.error) {
const body: InstallPackageResponse = {
response: res.assets || [],
items: res.assets || [],
};
return response.ok({ body });
} else {
@ -291,6 +301,7 @@ export const bulkInstallPackagesFromRegistryHandler: FleetRequestHandler<
});
const payload = bulkInstalledResponses.map(bulkInstallServiceResponseToHttpEntry);
const body: BulkInstallPackagesResponse = {
items: payload,
response: payload,
};
return response.ok({ body });
@ -321,6 +332,7 @@ export const installPackageByUploadHandler: FleetRequestHandler<
});
if (!res.error) {
const body: InstallPackageResponse = {
items: res.assets || [],
response: res.assets || [],
};
return response.ok({ body });
@ -335,17 +347,18 @@ export const deletePackageHandler: FleetRequestHandler<
TypeOf<typeof DeletePackageRequestSchema.body>
> = async (context, request, response) => {
try {
const { pkgkey } = request.params;
const { pkgName, pkgVersion } = request.params;
const savedObjectsClient = context.fleet.epm.internalSoClient;
const esClient = context.core.elasticsearch.client.asInternalUser;
const res = await removeInstallation({
savedObjectsClient,
pkgkey,
pkgName,
pkgVersion,
esClient,
force: request.body?.force,
});
const body: DeletePackageResponse = {
response: res,
items: res,
};
return response.ok({ body });
} catch (error) {

View file

@ -5,18 +5,32 @@
* 2.0.
*/
import type { IKibanaResponse } from 'src/core/server';
import type {
DeletePackageResponse,
GetInfoResponse,
InstallPackageResponse,
UpdatePackageResponse,
} from '../../../common';
import { PLUGIN_ID, EPM_API_ROUTES } from '../../constants';
import { splitPkgKey } from '../../services/epm/registry';
import {
GetCategoriesRequestSchema,
GetPackagesRequestSchema,
GetFileRequestSchema,
GetInfoRequestSchema,
GetInfoRequestSchemaDeprecated,
InstallPackageFromRegistryRequestSchema,
InstallPackageFromRegistryRequestSchemaDeprecated,
InstallPackageByUploadRequestSchema,
DeletePackageRequestSchema,
DeletePackageRequestSchemaDeprecated,
BulkUpgradePackagesFromRegistryRequestSchema,
GetStatsRequestSchema,
UpdatePackageRequestSchema,
UpdatePackageRequestSchemaDeprecated,
} from '../../types';
import type { FleetRouter } from '../../types/request_context';
@ -142,4 +156,85 @@ export const registerRoutes = (routers: { rbac: FleetRouter; superuser: FleetRou
},
deletePackageHandler
);
// deprecated since 8.0
routers.rbac.get(
{
path: EPM_API_ROUTES.INFO_PATTERN_DEPRECATED,
validate: GetInfoRequestSchemaDeprecated,
options: { tags: [`access:${PLUGIN_ID}-read`] },
},
async (context, request, response) => {
const newRequest = { ...request, params: splitPkgKey(request.params.pkgkey) } as any;
const resp: IKibanaResponse<GetInfoResponse> = await getInfoHandler(
context,
newRequest,
response
);
if (resp.payload?.item) {
return response.ok({ body: { response: resp.payload.item } });
}
return resp;
}
);
routers.superuser.put(
{
path: EPM_API_ROUTES.INFO_PATTERN_DEPRECATED,
validate: UpdatePackageRequestSchemaDeprecated,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
async (context, request, response) => {
const newRequest = { ...request, params: splitPkgKey(request.params.pkgkey) } as any;
const resp: IKibanaResponse<UpdatePackageResponse> = await updatePackageHandler(
context,
newRequest,
response
);
if (resp.payload?.item) {
return response.ok({ body: { response: resp.payload.item } });
}
return resp;
}
);
routers.superuser.post(
{
path: EPM_API_ROUTES.INSTALL_FROM_REGISTRY_PATTERN_DEPRECATED,
validate: InstallPackageFromRegistryRequestSchemaDeprecated,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
async (context, request, response) => {
const newRequest = { ...request, params: splitPkgKey(request.params.pkgkey) } as any;
const resp: IKibanaResponse<InstallPackageResponse> = await installPackageFromRegistryHandler(
context,
newRequest,
response
);
if (resp.payload?.items) {
return response.ok({ body: { response: resp.payload.items } });
}
return resp;
}
);
routers.superuser.delete(
{
path: EPM_API_ROUTES.DELETE_PATTERN_DEPRECATED,
validate: DeletePackageRequestSchemaDeprecated,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
async (context, request, response) => {
const newRequest = { ...request, params: splitPkgKey(request.params.pkgkey) } as any;
const resp: IKibanaResponse<DeletePackageResponse> = await deletePackageHandler(
context,
newRequest,
response
);
if (resp.payload?.items) {
return response.ok({ body: { response: resp.payload.items } });
}
return resp;
}
);
};

View file

@ -164,7 +164,7 @@ export async function handleInstallPackageFailure({
const installType = getInstallType({ pkgVersion, installedPkg });
if (installType === 'install' || installType === 'reinstall') {
logger.error(`uninstalling ${pkgkey} after error installing: [${error.toString()}]`);
await removeInstallation({ savedObjectsClient, pkgkey, esClient });
await removeInstallation({ savedObjectsClient, pkgName, pkgVersion, esClient });
}
await updateInstallStatus({ savedObjectsClient, pkgName, status: 'install_failed' });

View file

@ -22,7 +22,6 @@ import { removeUnusedIndexPatterns } from '../kibana/index_pattern/install';
import { deleteTransforms } from '../elasticsearch/transform/remove';
import { deleteMlModel } from '../elasticsearch/ml_model';
import { packagePolicyService, appContextService } from '../..';
import { splitPkgKey } from '../registry';
import { deletePackageCache } from '../archive';
import { deleteIlms } from '../elasticsearch/datastream_ilm/remove';
import { removeArchiveEntries } from '../archive/storage';
@ -31,13 +30,12 @@ import { getInstallation, kibanaSavedObjectTypes } from './index';
export async function removeInstallation(options: {
savedObjectsClient: SavedObjectsClientContract;
pkgkey: string;
pkgName: string;
pkgVersion: string;
esClient: ElasticsearchClient;
force?: boolean;
}): Promise<AssetReference[]> {
const { savedObjectsClient, pkgkey, esClient, force } = options;
// TODO: the epm api should change to /name/version so we don't need to do this
const { pkgName, pkgVersion } = splitPkgKey(pkgkey);
const { savedObjectsClient, pkgName, pkgVersion, esClient, force } = options;
const installation = await getInstallation({ savedObjectsClient, pkgName });
if (!installation) throw Boom.badRequest(`${pkgName} is not installed`);
if (installation.removable === false && !force)

View file

@ -8,9 +8,11 @@
import { URL } from 'url';
import mime from 'mime-types';
import semverValid from 'semver/functions/valid';
import type { Response } from 'node-fetch';
import { splitPkgKey as split } from '../../../../common';
import { KibanaAssetType } from '../../../types';
import type {
AssetsGroupedByServiceByType,
@ -31,12 +33,7 @@ import {
} from '../archive';
import { streamToBuffer } from '../streams';
import { appContextService } from '../..';
import {
PackageKeyInvalidError,
PackageNotFoundError,
PackageCacheError,
RegistryResponseError,
} from '../../../errors';
import { PackageNotFoundError, PackageCacheError, RegistryResponseError } from '../../../errors';
import { fetchUrl, getResponse, getResponseStream } from './requests';
import { getRegistryUrl } from './registry_url';
@ -46,33 +43,7 @@ export interface SearchParams {
experimental?: boolean;
}
/**
* Extract the package name and package version from a string.
*
* @param pkgkey a string containing the package name delimited by the package version
*/
export function splitPkgKey(pkgkey: string): { pkgName: string; pkgVersion: string } {
// If no version is provided, use the provided package key as the
// package name and return an empty version value
if (!pkgkey.includes('-')) {
return { pkgName: pkgkey, pkgVersion: '' };
}
const pkgName = pkgkey.includes('-') ? pkgkey.substr(0, pkgkey.indexOf('-')) : pkgkey;
if (pkgName === '') {
throw new PackageKeyInvalidError('Package key parsing failed: package name was empty');
}
// this will return the entire string if `indexOf` return -1
const pkgVersion = pkgkey.substr(pkgkey.indexOf('-') + 1);
if (!semverValid(pkgVersion)) {
throw new PackageKeyInvalidError(
'Package key parsing failed: package version was not a valid semver'
);
}
return { pkgName, pkgVersion };
}
export const splitPkgKey = split;
export const pkgToPkgKey = ({ name, version }: { name: string; version: string }) =>
`${name}-${version}`;

View file

@ -30,12 +30,29 @@ export const GetFileRequestSchema = {
};
export const GetInfoRequestSchema = {
params: schema.object({
pkgName: schema.string(),
pkgVersion: schema.maybe(schema.string()),
}),
};
export const GetInfoRequestSchemaDeprecated = {
params: schema.object({
pkgkey: schema.string(),
}),
};
export const UpdatePackageRequestSchema = {
params: schema.object({
pkgName: schema.string(),
pkgVersion: schema.maybe(schema.string()),
}),
body: schema.object({
keepPoliciesUpToDate: schema.boolean(),
}),
};
export const UpdatePackageRequestSchemaDeprecated = {
params: schema.object({
pkgkey: schema.string(),
}),
@ -51,6 +68,18 @@ export const GetStatsRequestSchema = {
};
export const InstallPackageFromRegistryRequestSchema = {
params: schema.object({
pkgName: schema.string(),
pkgVersion: schema.maybe(schema.string()),
}),
body: schema.nullable(
schema.object({
force: schema.boolean(),
})
),
};
export const InstallPackageFromRegistryRequestSchemaDeprecated = {
params: schema.object({
pkgkey: schema.string(),
}),
@ -72,6 +101,18 @@ export const InstallPackageByUploadRequestSchema = {
};
export const DeletePackageRequestSchema = {
params: schema.object({
pkgName: schema.string(),
pkgVersion: schema.string(),
}),
body: schema.nullable(
schema.object({
force: schema.boolean(),
})
),
};
export const DeletePackageRequestSchemaDeprecated = {
params: schema.object({
pkgkey: schema.string(),
}),

View file

@ -6,7 +6,7 @@
*/
import type { GetCategoriesResponse } from '../../../public/types';
export const response: GetCategoriesResponse['response'] = [
export const items: GetCategoriesResponse['items'] = [
{
id: 'aws',
title: 'AWS',

View file

@ -7,7 +7,7 @@
import type { GetInfoResponse } from '../../../public/types';
import { KibanaAssetType, ElasticsearchAssetType } from '../../../common/types';
export const response: GetInfoResponse['response'] = {
export const item: GetInfoResponse['item'] = {
name: 'nginx',
title: 'Nginx',
version: '0.7.0',

View file

@ -7,7 +7,7 @@
import type { GetInfoResponse } from '../../../public/types';
import { KibanaAssetType, ElasticsearchAssetType } from '../../../common/types';
export const response: GetInfoResponse['response'] = {
export const item: GetInfoResponse['item'] = {
name: 'okta',
title: 'Okta',
version: '1.2.0',

View file

@ -7,7 +7,7 @@
import type { GetPackagesResponse } from '../../../public/types';
export const response: GetPackagesResponse['response'] = [
export const items: GetPackagesResponse['items'] = [
{
name: 'ga_not_installed',
title: 'a. GA, Not Installed',

View file

@ -55,7 +55,7 @@ export const getHttp = (basepath = BASE_PATH) => {
// Ideally, this would be a markdown file instead of a ts file, but we don't have
// markdown-loader in our package.json, so we'll make do with what we have.
if (path.startsWith('/api/fleet/epm/packages/nginx/')) {
if (path.match('/api/fleet/epm/packages/nginx/.*/.*/')) {
const { readme } = await import('./fixtures/readme.nginx');
return readme;
}
@ -66,7 +66,7 @@ export const getHttp = (basepath = BASE_PATH) => {
// Ideally, this would be a markdown file instead of a ts file, but we don't have
// markdown-loader in our package.json, so we'll make do with what we have.
if (path.startsWith('/api/fleet/epm/packages/okta/')) {
if (path.match('/api/fleet/epm/packages/okta/.*/.*/')) {
const { readme } = await import('./fixtures/readme.okta');
return readme;
}

View file

@ -25,7 +25,7 @@ export const useAgentStatus = ({ policyId, skip }: UseAgentStatus) => {
['agentStatus', policyId],
() =>
http.get(
`/internal/osquery/fleet_wrapper/agent-status`,
`/internal/osquery/fleet_wrapper/agent_status`,
policyId
? {
query: {

View file

@ -17,7 +17,7 @@ export const getAgentStatusForAgentPolicyRoute = (
) => {
router.get(
{
path: '/internal/osquery/fleet_wrapper/agent-status',
path: '/internal/osquery/fleet_wrapper/agent_status',
validate: {
query: schema.object({
policyId: schema.string(),

View file

@ -97,7 +97,7 @@ export async function indexEndpointHostDocs({
client: Client;
kbnClient: KbnClient;
realPolicies: Record<string, CreatePackagePolicyResponse['item']>;
epmEndpointPackage: GetPackagesResponse['response'][0];
epmEndpointPackage: GetPackagesResponse['items'][0];
metadataIndex: string;
policyResponseIndex: string;
enrollFleet: boolean;

View file

@ -101,7 +101,7 @@ export const installOrUpgradeEndpointFleetPackage = async (
})
.catch(wrapErrorAndRejectPromise)) as AxiosResponse<BulkInstallPackagesResponse>;
const bulkResp = installEndpointPackageResp.data.response;
const bulkResp = installEndpointPackageResp.data.items;
if (bulkResp.length <= 0) {
throw new EndpointDataLoadingError(

View file

@ -1600,7 +1600,7 @@ export class EndpointDocGenerator extends BaseDataGenerator {
/**
* Generate an EPM Package for Endpoint
*/
public generateEpmPackage(): GetPackagesResponse['response'][0] {
public generateEpmPackage(): GetPackagesResponse['items'][0] {
return {
id: this.seededUUIDv4(),
name: 'endpoint',

View file

@ -124,13 +124,13 @@ export async function indexHostsAndAlerts(
const getEndpointPackageInfo = async (
kbnClient: KbnClient
): Promise<GetPackagesResponse['response'][0]> => {
): Promise<GetPackagesResponse['items'][0]> => {
const endpointPackage = (
(await kbnClient.request({
path: `${EPM_API_ROUTES.LIST_PATTERN}?category=security`,
method: 'GET',
})) as AxiosResponse<GetPackagesResponse>
).data.response.find((epmPackage) => epmPackage.name === 'endpoint');
).data.items.find((epmPackage) => epmPackage.name === 'endpoint');
if (!endpointPackage) {
throw new Error('EPM Endpoint package was not found!');

View file

@ -92,7 +92,7 @@ const endpointListApiPathHandlerMocks = ({
}: {
/** route handlers will be setup for each individual host in this array */
endpointsResults?: MetadataListResponse['data'];
epmPackages?: GetPackagesResponse['response'];
epmPackages?: GetPackagesResponse['items'];
endpointPackagePolicies?: GetPolicyListResponse['items'];
policyResponse?: HostPolicyResponse;
agentPolicy?: GetAgentPoliciesResponseItem;
@ -103,7 +103,7 @@ const endpointListApiPathHandlerMocks = ({
// endpoint package info
[INGEST_API_EPM_PACKAGES]: (): GetPackagesResponse => {
return {
response: epmPackages,
items: epmPackages,
};
},
@ -150,7 +150,7 @@ const endpointListApiPathHandlerMocks = ({
[INGEST_API_FLEET_AGENTS]: (): GetAgentsResponse => {
return {
total: totalAgentsUsingEndpoint,
list: [],
items: [],
totalInactive: 0,
page: 1,
perPage: 10,

View file

@ -78,7 +78,7 @@ export interface EndpointState {
/** the selected policy ID in the onboarding flow */
selectedPolicyId?: string;
/** Endpoint package info */
endpointPackageInfo: AsyncResourceState<GetPackagesResponse['response'][0]>;
endpointPackageInfo: AsyncResourceState<GetPackagesResponse['items'][0]>;
/** Tracks the list of policies IDs used in Host metadata that may no longer exist */
nonExistingPolicies: PolicyIds['packagePolicy'];
/** List of Package Policy Ids mapped to an associated Fleet Parent Agent Policy Id*/

View file

@ -129,7 +129,7 @@ export const fleetGetPackageListHttpMock =
const generator = new EndpointDocGenerator('seed');
return {
response: [generator.generateEpmPackage()],
items: [generator.generateEpmPackage()],
};
},
},

View file

@ -21,7 +21,7 @@ import { NewPolicyData } from '../../../../../../common/endpoint/types';
const INGEST_API_ROOT = `/api/fleet`;
export const INGEST_API_PACKAGE_POLICIES = `${INGEST_API_ROOT}/package_policies`;
export const INGEST_API_AGENT_POLICIES = `${INGEST_API_ROOT}/agent_policies`;
const INGEST_API_FLEET_AGENT_STATUS = `${INGEST_API_ROOT}/agent-status`;
const INGEST_API_FLEET_AGENT_STATUS = `${INGEST_API_ROOT}/agent_status`;
export const INGEST_API_FLEET_AGENTS = `${INGEST_API_ROOT}/agents`;
export const INGEST_API_EPM_PACKAGES = `${INGEST_API_ROOT}/epm/packages`;
const INGEST_API_DELETE_PACKAGE_POLICY = `${INGEST_API_PACKAGE_POLICIES}/delete`;
@ -135,10 +135,10 @@ export const sendGetFleetAgentsWithEndpoint = (
*/
export const sendGetEndpointSecurityPackage = async (
http: HttpStart
): Promise<GetPackagesResponse['response'][0]> => {
): Promise<GetPackagesResponse['items'][0]> => {
const options = { query: { category: 'security' } };
const securityPackages = await http.get<GetPackagesResponse>(INGEST_API_EPM_PACKAGES, options);
const endpointPackageInfo = securityPackages.response.find(
const endpointPackageInfo = securityPackages.items.find(
(epmPackage) => epmPackage.name === 'endpoint'
);
if (!endpointPackageInfo) {

View file

@ -57,7 +57,7 @@ export const policyListApiPathHandlers = (totalPolicies: number = 1) => {
},
[INGEST_API_EPM_PACKAGES]: (): GetPackagesResponse => {
return {
response: [generator.generateEpmPackage()],
items: [generator.generateEpmPackage()],
};
},
};

View file

@ -12,7 +12,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
const ml = getService('ml');
const fleetPackages = ['apache', 'nginx'];
const installedPackages: string[] = [];
const installedPackages: Array<{ pkgName: string; version: string }> = [];
describe('modules', function () {
before(async () => {
@ -23,14 +23,14 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
await ml.testResources.setupFleet();
for (const fleetPackage of fleetPackages) {
const packageWithVersion = await ml.testResources.installFleetPackage(fleetPackage);
installedPackages.push(packageWithVersion);
const version = await ml.testResources.installFleetPackage(fleetPackage);
installedPackages.push({ pkgName: fleetPackage, version });
}
});
after(async () => {
for (const fleetPackage of installedPackages) {
await ml.testResources.removeFleetPackage(fleetPackage);
await ml.testResources.removeFleetPackage(fleetPackage.pkgName, fleetPackage.version);
}
await esArchiver.unload('x-pack/test/functional/es_archives/empty_kibana');
});

View file

@ -21,15 +21,15 @@ export default function (providerContext: FtrProviderContext) {
const esClient = getService('es');
async function getEnrollmentKeyForPolicyId(policyId: string) {
const listRes = await supertest.get(`/api/fleet/enrollment-api-keys`).expect(200);
const listRes = await supertest.get(`/api/fleet/enrollment_api_keys`).expect(200);
const key = listRes.body.list.find(
const key = listRes.body.items.find(
(item: { policy_id: string; id: string }) => item.policy_id === policyId
);
expect(key).not.empty();
const res = await supertest.get(`/api/fleet/enrollment-api-keys/${key.id}`).expect(200);
const res = await supertest.get(`/api/fleet/enrollment_api_keys/${key.id}`).expect(200);
return res.body.item;
}

View file

@ -39,12 +39,12 @@ export default function ({ getService }: FtrProviderContext) {
it('should return the list of agents when requesting as a user with fleet write permissions', async () => {
const { body: apiResponse } = await supertest.get(`/api/fleet/agents`).expect(200);
expect(apiResponse).to.have.keys('page', 'total', 'list');
expect(apiResponse).to.have.keys('page', 'total', 'items', 'list');
expect(apiResponse.total).to.eql(4);
});
it('should return the list of agents when requesting as a user with fleet read permissions', async () => {
const { body: apiResponse } = await supertest.get(`/api/fleet/agents`).expect(200);
expect(apiResponse).to.have.keys('page', 'total', 'list');
expect(apiResponse).to.have.keys('page', 'total', 'items', 'list');
expect(apiResponse.total).to.eql(4);
});
@ -66,7 +66,7 @@ export default function ({ getService }: FtrProviderContext) {
.expect(200);
expect(apiResponse.total).to.eql(1);
const agent = apiResponse.list[0];
const agent = apiResponse.items[0];
expect(agent.access_api_key_id).to.eql('api-key-2');
});
});

View file

@ -190,7 +190,7 @@ export default function (providerContext: FtrProviderContext) {
.expect(200);
const { body } = await supertest.get(`/api/fleet/agents`).set('kbn-xsrf', 'xxx');
expect(body.total).to.eql(4);
body.list.forEach((agent: any) => {
body.items.forEach((agent: any) => {
expect(agent.policy_id).to.eql('policy2');
});
});

View file

@ -68,7 +68,7 @@ export default function ({ getService }: FtrProviderContext) {
});
it('should return the status of agents', async () => {
const { body: apiResponse } = await supertest.get(`/api/fleet/agent-status`).expect(200);
const { body: apiResponse } = await supertest.get(`/api/fleet/agent_status`).expect(200);
expect(apiResponse).to.eql({
results: {
@ -83,5 +83,9 @@ export default function ({ getService }: FtrProviderContext) {
},
});
});
it('should work with deprecated api', async () => {
await supertest.get(`/api/fleet/agent-status`).expect(200);
});
});
}

View file

@ -21,17 +21,16 @@ export default function (providerContext: FtrProviderContext) {
const retry = getService('retry');
const pkgName = 'datastreams';
const pkgVersion = '0.1.0';
const pkgKey = `${pkgName}-${pkgVersion}`;
const logsTemplateName = `logs-${pkgName}.test_logs`;
const metricsTemplateName = `metrics-${pkgName}.test_metrics`;
const uninstallPackage = async (pkg: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx');
const uninstallPackage = async (name: string, version: string) => {
await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx');
};
const installPackage = async (pkg: string) => {
const installPackage = async (name: string, version: string) => {
return await supertest
.post(`/api/fleet/epm/packages/${pkg}`)
.post(`/api/fleet/epm/packages/${name}/${version}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
@ -91,11 +90,11 @@ export default function (providerContext: FtrProviderContext) {
skipIfNoDockerRegistry(providerContext);
beforeEach(async () => {
await installPackage(pkgKey);
await installPackage(pkgName, pkgVersion);
});
afterEach(async () => {
await uninstallPackage(pkgKey);
await uninstallPackage(pkgName, pkgVersion);
try {
await es.transport.request({
method: 'DELETE',

View file

@ -31,33 +31,34 @@ export default function (providerContext: FtrProviderContext) {
skipIfNoDockerRegistry(providerContext);
setupFleetAndAgents(providerContext);
describe('GET /fleet/enrollment-api-keys', async () => {
describe('GET /fleet/enrollment_api_keys', async () => {
it('should list existing api keys', async () => {
const { body: apiResponse } = await supertest
.get(`/api/fleet/enrollment-api-keys`)
.get(`/api/fleet/enrollment_api_keys`)
.expect(200);
expect(apiResponse.total).to.be(3);
expect(apiResponse.list[0]).to.have.keys('id', 'api_key_id', 'name');
expect(apiResponse.items[0]).to.have.keys('id', 'api_key_id', 'name');
expect(apiResponse).to.have.keys('list');
});
});
describe('GET /fleet/enrollment-api-keys/{id}', async () => {
describe('GET /fleet/enrollment_api_keys/{id}', async () => {
it('should allow to retrieve existing api keys', async () => {
const { body: apiResponse } = await supertest
.get(`/api/fleet/enrollment-api-keys/${ENROLLMENT_KEY_ID}`)
.get(`/api/fleet/enrollment_api_keys/${ENROLLMENT_KEY_ID}`)
.expect(200);
expect(apiResponse.item).to.have.keys('id', 'api_key_id', 'name');
});
});
describe('DELETE /fleet/enrollment-api-keys/{id}', async () => {
describe('DELETE /fleet/enrollment_api_keys/{id}', async () => {
let keyId: string;
let esApiKeyId: string;
before(async () => {
const { body: apiResponse } = await supertest
.post(`/api/fleet/enrollment-api-keys`)
.post(`/api/fleet/enrollment_api_keys`)
.set('kbn-xsrf', 'xxx')
.send({
policy_id: 'policy1',
@ -69,7 +70,7 @@ export default function (providerContext: FtrProviderContext) {
it('should invalide an existing api keys', async () => {
await supertest
.delete(`/api/fleet/enrollment-api-keys/${keyId}`)
.delete(`/api/fleet/enrollment_api_keys/${keyId}`)
.set('kbn-xsrf', 'xxx')
.expect(200);
@ -80,10 +81,10 @@ export default function (providerContext: FtrProviderContext) {
});
});
describe('POST /fleet/enrollment-api-keys', () => {
describe('POST /fleet/enrollment_api_keys', () => {
it('should not accept bad parameters', async () => {
await supertest
.post(`/api/fleet/enrollment-api-keys`)
.post(`/api/fleet/enrollment_api_keys`)
.set('kbn-xsrf', 'xxx')
.send({
raoul: 'raoul',
@ -93,7 +94,7 @@ export default function (providerContext: FtrProviderContext) {
it('should return a 400 if the fleet admin user is modifed outside of Fleet', async () => {
await supertest
.post(`/api/fleet/enrollment-api-keys`)
.post(`/api/fleet/enrollment_api_keys`)
.set('kbn-xsrf', 'xxx')
.send({
raoul: 'raoul',
@ -103,7 +104,7 @@ export default function (providerContext: FtrProviderContext) {
it('should allow to create an enrollment api key with only an agent policy', async () => {
const { body: apiResponse } = await supertest
.post(`/api/fleet/enrollment-api-keys`)
.post(`/api/fleet/enrollment_api_keys`)
.set('kbn-xsrf', 'xxx')
.send({
policy_id: 'policy1',
@ -115,7 +116,7 @@ export default function (providerContext: FtrProviderContext) {
it('should allow to create an enrollment api key with agent policy and unique name', async () => {
const { body: noSpacesRes } = await supertest
.post(`/api/fleet/enrollment-api-keys`)
.post(`/api/fleet/enrollment_api_keys`)
.set('kbn-xsrf', 'xxx')
.send({
policy_id: 'policy1',
@ -124,7 +125,7 @@ export default function (providerContext: FtrProviderContext) {
expect(noSpacesRes.item).to.have.keys('id', 'api_key', 'api_key_id', 'name', 'policy_id');
const { body: hasSpacesRes } = await supertest
.post(`/api/fleet/enrollment-api-keys`)
.post(`/api/fleet/enrollment_api_keys`)
.set('kbn-xsrf', 'xxx')
.send({
policy_id: 'policy1',
@ -133,7 +134,7 @@ export default function (providerContext: FtrProviderContext) {
expect(hasSpacesRes.item).to.have.keys('id', 'api_key', 'api_key_id', 'name', 'policy_id');
const { body: noSpacesDupe } = await supertest
.post(`/api/fleet/enrollment-api-keys`)
.post(`/api/fleet/enrollment_api_keys`)
.set('kbn-xsrf', 'xxx')
.send({
policy_id: 'policy1',
@ -148,7 +149,7 @@ export default function (providerContext: FtrProviderContext) {
});
const { body: hasSpacesDupe } = await supertest
.post(`/api/fleet/enrollment-api-keys`)
.post(`/api/fleet/enrollment_api_keys`)
.set('kbn-xsrf', 'xxx')
.send({
policy_id: 'policy1',
@ -164,7 +165,7 @@ export default function (providerContext: FtrProviderContext) {
it('should create an ES ApiKey with metadata', async () => {
const { body: apiResponse } = await supertest
.post(`/api/fleet/enrollment-api-keys`)
.post(`/api/fleet/enrollment_api_keys`)
.set('kbn-xsrf', 'xxx')
.send({
policy_id: 'policy1',
@ -185,7 +186,7 @@ export default function (providerContext: FtrProviderContext) {
it('should create an ES ApiKey with limited privileges', async () => {
const { body: apiResponse } = await supertest
.post(`/api/fleet/enrollment-api-keys`)
.post(`/api/fleet/enrollment_api_keys`)
.set('kbn-xsrf', 'xxx')
.send({
policy_id: 'policy1',
@ -234,5 +235,29 @@ export default function (providerContext: FtrProviderContext) {
});
});
});
describe('deprecated API', () => {
let keyId: string;
before(async () => {
const { body: apiResponse } = await supertest
.post(`/api/fleet/enrollment-api-keys`)
.set('kbn-xsrf', 'xxx')
.send({
policy_id: 'policy1',
})
.expect(200);
keyId = apiResponse.item.id;
});
it('should get and delete with deprecated API', async () => {
await supertest.get(`/api/fleet/enrollment-api-keys`).expect(200);
await supertest.get(`/api/fleet/enrollment-api-keys/${ENROLLMENT_KEY_ID}`).expect(200);
await supertest
.delete(`/api/fleet/enrollment-api-keys/${keyId}`)
.set('kbn-xsrf', 'xxx')
.expect(200);
});
});
});
}

View file

@ -21,8 +21,8 @@ export default function (providerContext: FtrProviderContext) {
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const deletePackage = async (pkgkey: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkgkey}`).set('kbn-xsrf', 'xxxx');
const deletePackage = async (name: string, version: string) => {
await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx');
};
describe('bulk package upgrade api', async () => {
@ -32,15 +32,15 @@ export default function (providerContext: FtrProviderContext) {
describe('bulk package upgrade with a package already installed', async () => {
beforeEach(async () => {
await supertest
.post(`/api/fleet/epm/packages/multiple_versions-0.1.0`)
.post(`/api/fleet/epm/packages/multiple_versions/0.1.0`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
});
afterEach(async () => {
await deletePackage('multiple_versions-0.1.0');
await deletePackage('multiple_versions-0.3.0');
await deletePackage('overrides-0.1.0');
await deletePackage('multiple_versions', '0.1.0');
await deletePackage('multiple_versions', '0.3.0');
await deletePackage('overrides', '0.1.0');
});
it('should return 400 if no packages are requested for upgrade', async function () {
@ -59,9 +59,9 @@ export default function (providerContext: FtrProviderContext) {
.set('kbn-xsrf', 'xxxx')
.send({ packages: ['multiple_versions'] })
.expect(200);
expect(body.response.length).equal(1);
expect(body.response[0].name).equal('multiple_versions');
const entry = body.response[0] as BulkInstallPackageInfo;
expect(body.items.length).equal(1);
expect(body.items[0].name).equal('multiple_versions');
const entry = body.items[0] as BulkInstallPackageInfo;
expect(entry.version).equal('0.3.0');
});
it('should return an error for packages that do not exist', async function () {
@ -70,14 +70,14 @@ export default function (providerContext: FtrProviderContext) {
.set('kbn-xsrf', 'xxxx')
.send({ packages: ['multiple_versions', 'blahblah'] })
.expect(200);
expect(body.response.length).equal(2);
expect(body.response[0].name).equal('multiple_versions');
const entry = body.response[0] as BulkInstallPackageInfo;
expect(body.items.length).equal(2);
expect(body.items[0].name).equal('multiple_versions');
const entry = body.items[0] as BulkInstallPackageInfo;
expect(entry.version).equal('0.3.0');
const err = body.response[1] as IBulkInstallPackageHTTPError;
const err = body.items[1] as IBulkInstallPackageHTTPError;
expect(err.statusCode).equal(404);
expect(body.response[1].name).equal('blahblah');
expect(body.items[1].name).equal('blahblah');
});
it('should upgrade multiple packages', async function () {
const { body }: { body: BulkInstallPackagesResponse } = await supertest
@ -85,12 +85,12 @@ export default function (providerContext: FtrProviderContext) {
.set('kbn-xsrf', 'xxxx')
.send({ packages: ['multiple_versions', 'overrides'] })
.expect(200);
expect(body.response.length).equal(2);
expect(body.response[0].name).equal('multiple_versions');
let entry = body.response[0] as BulkInstallPackageInfo;
expect(body.items.length).equal(2);
expect(body.items[0].name).equal('multiple_versions');
let entry = body.items[0] as BulkInstallPackageInfo;
expect(entry.version).equal('0.3.0');
entry = body.response[1] as BulkInstallPackageInfo;
entry = body.items[1] as BulkInstallPackageInfo;
expect(entry.version).equal('0.1.0');
expect(entry.name).equal('overrides');
});
@ -98,7 +98,7 @@ export default function (providerContext: FtrProviderContext) {
describe('bulk upgrade without package already installed', async () => {
afterEach(async () => {
await deletePackage('multiple_versions-0.3.0');
await deletePackage('multiple_versions', '0.3.0');
});
it('should return 200 and an array for upgrading a package', async function () {
@ -107,9 +107,9 @@ export default function (providerContext: FtrProviderContext) {
.set('kbn-xsrf', 'xxxx')
.send({ packages: ['multiple_versions'] })
.expect(200);
expect(body.response.length).equal(1);
expect(body.response[0].name).equal('multiple_versions');
const entry = body.response[0] as BulkInstallPackageInfo;
expect(body.items.length).equal(1);
expect(body.items[0].name).equal('multiple_versions');
const entry = body.items[0] as BulkInstallPackageInfo;
expect(entry.version).equal('0.3.0');
});
});

View file

@ -18,18 +18,16 @@ export default function (providerContext: FtrProviderContext) {
const pkgName = 'datastreams';
const pkgVersion = '0.1.0';
const pkgUpdateVersion = '0.2.0';
const pkgKey = `${pkgName}-${pkgVersion}`;
const pkgUpdateKey = `${pkgName}-${pkgUpdateVersion}`;
const logsTemplateName = `logs-${pkgName}.test_logs`;
const metricsTemplateName = `metrics-${pkgName}.test_metrics`;
const namespaces = ['default', 'foo', 'bar'];
const uninstallPackage = async (pkg: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx');
const uninstallPackage = async (name: string, version: string) => {
await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx');
};
const installPackage = async (pkg: string) => {
const installPackage = async (name: string, version: string) => {
return await supertest
.post(`/api/fleet/epm/packages/${pkg}`)
.post(`/api/fleet/epm/packages/${name}/${version}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
@ -40,7 +38,7 @@ export default function (providerContext: FtrProviderContext) {
setupFleetAndAgents(providerContext);
beforeEach(async () => {
await installPackage(pkgKey);
await installPackage(pkgName, pkgVersion);
await Promise.all(
namespaces.map(async (namespace) => {
const createLogsRequest = es.transport.request(
@ -100,8 +98,8 @@ export default function (providerContext: FtrProviderContext) {
return Promise.all([deleteLogsRequest, deleteMetricsRequest]);
})
);
await uninstallPackage(pkgKey);
await uninstallPackage(pkgUpdateKey);
await uninstallPackage(pkgName, pkgVersion);
await uninstallPackage(pkgName, pkgUpdateVersion);
});
it('should list the logs and metrics datastream', async function () {
@ -128,7 +126,7 @@ export default function (providerContext: FtrProviderContext) {
});
it('after update, it should have rolled over logs datastream because mappings are not compatible and not metrics', async function () {
await installPackage(pkgUpdateKey);
await installPackage(pkgName, pkgUpdateVersion);
await asyncForEach(namespaces, async (namespace) => {
const resLogsDatastream = await es.transport.request<any>(
{
@ -167,7 +165,7 @@ export default function (providerContext: FtrProviderContext) {
);
expect(resLogsDatastream.body.data_streams[0].indices.length).equal(2);
});
await installPackage(pkgUpdateKey);
await installPackage(pkgName, pkgUpdateVersion);
});
});
}

View file

@ -14,18 +14,19 @@ export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const requiredPackage = 'elastic_agent-0.0.7';
const requiredPackage = 'elastic_agent';
const pkgVersion = '0.0.7';
const installPackage = async (pkgkey: string) => {
const installPackage = async (name: string, version: string) => {
await supertest
.post(`/api/fleet/epm/packages/${pkgkey}`)
.post(`/api/fleet/epm/packages/${name}/${version}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true });
};
const deletePackage = async (pkgkey: string) => {
const deletePackage = async (name: string, version: string) => {
await supertest
.delete(`/api/fleet/epm/packages/${pkgkey}`)
.delete(`/api/fleet/epm/packages/${name}/${version}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true });
};
@ -34,22 +35,22 @@ export default function (providerContext: FtrProviderContext) {
skipIfNoDockerRegistry(providerContext);
setupFleetAndAgents(providerContext);
before(async () => {
await installPackage(requiredPackage);
await installPackage(requiredPackage, pkgVersion);
});
after(async () => {
await deletePackage(requiredPackage);
await deletePackage(requiredPackage, pkgVersion);
});
it('should return 400 if trying to uninstall a required package', async function () {
await supertest
.delete(`/api/fleet/epm/packages/${requiredPackage}`)
.delete(`/api/fleet/epm/packages/${requiredPackage}/${pkgVersion}`)
.set('kbn-xsrf', 'xxxx')
.expect(400);
});
it('should return 200 if trying to force uninstall a required package', async function () {
await supertest
.delete(`/api/fleet/epm/packages/${requiredPackage}`)
.delete(`/api/fleet/epm/packages/${requiredPackage}/${pkgVersion}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
@ -57,7 +58,7 @@ export default function (providerContext: FtrProviderContext) {
it('should return 403 for read-only users', async () => {
await supertestWithoutAuth
.delete(`/api/fleet/epm/packages/${requiredPackage}`)
.delete(`/api/fleet/epm/packages/${requiredPackage}/${pkgVersion}`)
.auth(testUsers.fleet_read_only.username, testUsers.fleet_read_only.password)
.set('kbn-xsrf', 'xxxx')
.expect(403);

View file

@ -103,7 +103,7 @@ export default function ({ getService }: FtrProviderContext) {
});
after(async () => {
if (!server.enabled) return;
await supertest.delete(`/api/fleet/epm/packages/apache-0.1.4`).set('kbn-xsrf', 'xxxx');
await supertest.delete(`/api/fleet/epm/packages/apache/0.1.4`).set('kbn-xsrf', 'xxxx');
});
it('fetches a .png screenshot image', async function () {
if (server.enabled) {

View file

@ -16,7 +16,7 @@ const FINAL_PIPELINE_ID = '.fleet_final_pipeline-1';
const FINAL_PIPELINE_VERSION = 1;
let pkgKey: string;
let pkgVersion: string;
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
@ -45,22 +45,22 @@ export default function (providerContext: FtrProviderContext) {
const { body: getPackagesRes } = await supertest.get(
`/api/fleet/epm/packages?experimental=true`
);
const logPackage = getPackagesRes.response.find((p: any) => p.name === 'log');
const logPackage = getPackagesRes.items.find((p: any) => p.name === 'log');
if (!logPackage) {
throw new Error('No log package');
}
pkgKey = `log-${logPackage.version}`;
pkgVersion = logPackage.version;
await supertest
.post(`/api/fleet/epm/packages/${pkgKey}`)
.post(`/api/fleet/epm/packages/log/${pkgVersion}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
});
after(async () => {
await supertest
.delete(`/api/fleet/epm/packages/${pkgKey}`)
.delete(`/api/fleet/epm/packages/log/${pkgVersion}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);

View file

@ -19,14 +19,15 @@ export default function (providerContext: FtrProviderContext) {
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const testPkgKey = 'apache-0.1.4';
const testPkgName = 'apache';
const testPkgVersion = '0.1.4';
const uninstallPackage = async (pkg: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx');
const uninstallPackage = async (name: string, version: string) => {
await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx');
};
const installPackage = async (pkg: string) => {
const installPackage = async (name: string, version: string) => {
await supertest
.post(`/api/fleet/epm/packages/${pkg}`)
.post(`/api/fleet/epm/packages/${name}/${version}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true });
};
@ -41,14 +42,16 @@ export default function (providerContext: FtrProviderContext) {
setupFleetAndAgents(providerContext);
it('returns package info from the registry if it was installed from the registry', async function () {
// this will install through the registry by default
await installPackage(testPkgKey);
const res = await supertest.get(`/api/fleet/epm/packages/${testPkgKey}`).expect(200);
const packageInfo = res.body.response;
await installPackage(testPkgName, testPkgVersion);
const res = await supertest
.get(`/api/fleet/epm/packages/${testPkgName}/${testPkgVersion}`)
.expect(200);
const packageInfo = res.body.item;
// the uploaded version will have this description
expect(packageInfo.description).to.not.equal('Apache Uploaded Test Integration');
// download property should exist
expect(packageInfo.download).to.not.equal(undefined);
await uninstallPackage(testPkgKey);
await uninstallPackage(testPkgName, testPkgVersion);
});
it('returns correct package info if it was installed by upload', async function () {
const buf = fs.readFileSync(testPkgArchiveZip);
@ -59,13 +62,15 @@ export default function (providerContext: FtrProviderContext) {
.send(buf)
.expect(200);
const res = await supertest.get(`/api/fleet/epm/packages/${testPkgKey}`).expect(200);
const packageInfo = res.body.response;
const res = await supertest
.get(`/api/fleet/epm/packages/${testPkgName}/${testPkgVersion}`)
.expect(200);
const packageInfo = res.body.item;
// the uploaded version will have this description
expect(packageInfo.description).to.equal('Apache Uploaded Test Integration');
// download property should not exist on uploaded packages
expect(packageInfo.download).to.equal(undefined);
await uninstallPackage(testPkgKey);
await uninstallPackage(testPkgName, testPkgVersion);
});
it('returns correct package info from registry if a different version is installed by upload', async function () {
const buf = fs.readFileSync(testPkgArchiveZip);
@ -76,27 +81,24 @@ export default function (providerContext: FtrProviderContext) {
.send(buf)
.expect(200);
const res = await supertest.get(`/api/fleet/epm/packages/apache-0.1.3`).expect(200);
const packageInfo = res.body.response;
const res = await supertest.get(`/api/fleet/epm/packages/apache/0.1.3`).expect(200);
const packageInfo = res.body.item;
expect(packageInfo.description).to.equal('Apache Integration');
expect(packageInfo.download).to.not.equal(undefined);
await uninstallPackage(testPkgKey);
});
it('returns a 400 for a package key without a proper name', async function () {
await supertest.get('/api/fleet/epm/packages/-0.1.0').expect(400);
await uninstallPackage(testPkgName, testPkgVersion);
});
it('returns a 404 for a package that do not exists', async function () {
await supertest.get('/api/fleet/epm/packages/notexists-99.99.99').expect(404);
await supertest.get('/api/fleet/epm/packages/notexists/99.99.99').expect(404);
});
it('returns a 400 for a package key without a proper semver version', async function () {
await supertest.get('/api/fleet/epm/packages/endpoint-0.1.0.1.2.3').expect(400);
await supertest.get('/api/fleet/epm/packages/endpoint/0.1.0.1.2.3').expect(400);
});
it('allows user with only read permission to access', async () => {
await supertestWithoutAuth
.get(`/api/fleet/epm/packages/${testPkgKey}`)
.get(`/api/fleet/epm/packages/${testPkgName}/${testPkgVersion}`)
.auth(testUsers.fleet_read_only.username, testUsers.fleet_read_only.password)
.expect(200);
});

View file

@ -49,11 +49,12 @@ export default function (providerContext: FtrProviderContext) {
'../fixtures/direct_upload_packages/apache_invalid_toplevel_mismatch_0.1.4.zip'
);
const testPkgKey = 'apache-0.1.4';
const testPkgName = 'apache';
const testPkgVersion = '0.1.4';
const server = dockerServers.get('registry');
const deletePackage = async (pkgkey: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkgkey}`).set('kbn-xsrf', 'xxxx');
const deletePackage = async (name: string, version: string) => {
await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx');
};
describe('installs packages from direct upload', async () => {
@ -62,7 +63,7 @@ export default function (providerContext: FtrProviderContext) {
afterEach(async () => {
if (server) {
// remove the packages just in case it being installed will affect other tests
await deletePackage(testPkgKey);
await deletePackage(testPkgName, testPkgVersion);
}
});
@ -74,7 +75,7 @@ export default function (providerContext: FtrProviderContext) {
.type('application/gzip')
.send(buf)
.expect(200);
expect(res.body.response.length).to.be(27);
expect(res.body.items.length).to.be(27);
});
it('should install a zip archive correctly and package info should return correctly after validation', async function () {
@ -85,21 +86,21 @@ export default function (providerContext: FtrProviderContext) {
.type('application/zip')
.send(buf)
.expect(200);
expect(res.body.response.length).to.be(27);
expect(res.body.items.length).to.be(27);
const packageInfoRes = await supertest
.get(`/api/fleet/epm/packages/${testPkgKey}`)
.get(`/api/fleet/epm/packages/${testPkgName}/${testPkgVersion}`)
.set('kbn-xsrf', 'xxxx')
.expect(200);
delete packageInfoRes.body.response.latestVersion;
delete packageInfoRes.body.response.savedObject.attributes.install_started_at;
delete packageInfoRes.body.response.savedObject.version;
delete packageInfoRes.body.response.savedObject.updated_at;
delete packageInfoRes.body.response.savedObject.coreMigrationVersion;
delete packageInfoRes.body.response.savedObject.migrationVersion;
delete packageInfoRes.body.item.latestVersion;
delete packageInfoRes.body.item.savedObject.attributes.install_started_at;
delete packageInfoRes.body.item.savedObject.version;
delete packageInfoRes.body.item.savedObject.updated_at;
delete packageInfoRes.body.item.savedObject.coreMigrationVersion;
delete packageInfoRes.body.item.savedObject.migrationVersion;
expectSnapshot(packageInfoRes.body.response).toMatch();
expectSnapshot(packageInfoRes.body.item).toMatch();
});
it('should throw an error if the archive is zip but content type is gzip', async function () {

View file

@ -72,13 +72,13 @@ export default function (providerContext: FtrProviderContext) {
});
});
const uninstallPackage = async (pkg: string) =>
supertest.delete(`/api/fleet/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx');
const uninstallPackage = async (pkg: string, version: string) =>
supertest.delete(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx');
// Endpoint doesn't currently support uninstalls
describe.skip('uninstall', () => {
before(async () => {
await uninstallPackage(`${pkgName}-${pkgVersion}`);
await uninstallPackage(pkgName, pkgVersion);
});
transforms.forEach((transform) => {

View file

@ -14,18 +14,19 @@ export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const goodPackage = 'error_handling-0.1.0';
const badPackage = 'error_handling-0.2.0';
const pkgName = 'error_handling';
const goodPackageVersion = '0.1.0';
const badPackageVersion = '0.2.0';
const installPackage = async (pkgkey: string) => {
const installPackage = async (pkg: string, version: string) => {
await supertest
.post(`/api/fleet/epm/packages/${pkgkey}`)
.post(`/api/fleet/epm/packages/${pkg}/${version}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true });
};
const getPackageInfo = async (pkgkey: string) => {
return await supertest.get(`/api/fleet/epm/packages/${pkgkey}`).set('kbn-xsrf', 'xxxx');
const getPackageInfo = async (pkg: string, version: string) => {
return await supertest.get(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx');
};
describe('package installation error handling and rollback', async () => {
@ -40,24 +41,24 @@ export default function (providerContext: FtrProviderContext) {
it('on a fresh install, it should uninstall a broken package during rollback', async function () {
await supertest
.post(`/api/fleet/epm/packages/${badPackage}`)
.post(`/api/fleet/epm/packages/${pkgName}/${badPackageVersion}`)
.set('kbn-xsrf', 'xxxx')
.expect(422); // the broken package contains a broken visualization triggering a 422 from Kibana
const pkgInfoResponse = await getPackageInfo(badPackage);
expect(JSON.parse(pkgInfoResponse.text).response.status).to.be('not_installed');
const pkgInfoResponse = await getPackageInfo(pkgName, badPackageVersion);
expect(JSON.parse(pkgInfoResponse.text).item.status).to.be('not_installed');
});
it('on an upgrade, it should fall back to the previous good version during rollback', async function () {
await installPackage(goodPackage);
await installPackage(pkgName, goodPackageVersion);
await supertest
.post(`/api/fleet/epm/packages/${badPackage}`)
.post(`/api/fleet/epm/packages/${pkgName}/${badPackageVersion}`)
.set('kbn-xsrf', 'xxxx')
.expect(422); // the broken package contains a broken visualization triggering a 422 from Kibana
const goodPkgInfoResponse = await getPackageInfo(goodPackage);
expect(JSON.parse(goodPkgInfoResponse.text).response.status).to.be('installed');
expect(JSON.parse(goodPkgInfoResponse.text).response.version).to.be('0.1.0');
const goodPkgInfoResponse = await getPackageInfo(pkgName, goodPackageVersion);
expect(JSON.parse(goodPkgInfoResponse.text).item.status).to.be('installed');
expect(JSON.parse(goodPkgInfoResponse.text).item.version).to.be('0.1.0');
});
});
}

View file

@ -16,11 +16,12 @@ export default function (providerContext: FtrProviderContext) {
const es = getService('es');
const dockerServers = getService('dockerServers');
const mappingsPackage = 'overrides-0.1.0';
const mappingsPackage = 'overrides';
const mappingsPackageVersion = '0.1.0';
const server = dockerServers.get('registry');
const deletePackage = async (pkgkey: string) =>
supertest.delete(`/api/fleet/epm/packages/${pkgkey}`).set('kbn-xsrf', 'xxxx');
const deletePackage = async (pkg: string, version: string) =>
supertest.delete(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx');
describe('installs packages that include settings and mappings overrides', async () => {
skipIfNoDockerRegistry(providerContext);
@ -28,17 +29,17 @@ export default function (providerContext: FtrProviderContext) {
after(async () => {
if (server.enabled) {
// remove the package just in case it being installed will affect other tests
await deletePackage(mappingsPackage);
await deletePackage(mappingsPackage, mappingsPackageVersion);
}
});
it('should install the overrides package correctly', async function () {
let { body } = await supertest
.post(`/api/fleet/epm/packages/${mappingsPackage}`)
.post(`/api/fleet/epm/packages/${mappingsPackage}/${mappingsPackageVersion}`)
.set('kbn-xsrf', 'xxxx')
.expect(200);
const templateName = body.response[0].id;
const templateName = body.items[0].id;
const { body: indexTemplateResponse } = await es.transport.request<any>(
{

View file

@ -14,11 +14,12 @@ export default function (providerContext: FtrProviderContext) {
const supertest = getService('supertest');
const dockerServers = getService('dockerServers');
const testPackage = 'prerelease-0.1.0-dev.0+abc';
const testPackage = 'prerelease';
const testPackageVersion = '0.1.0-dev.0+abc';
const server = dockerServers.get('registry');
const deletePackage = async (pkgkey: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkgkey}`).set('kbn-xsrf', 'xxxx');
const deletePackage = async (pkg: string, version: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx');
};
describe('installs package that has a prerelease version', async () => {
@ -27,13 +28,13 @@ export default function (providerContext: FtrProviderContext) {
after(async () => {
if (server.enabled) {
// remove the package just in case it being installed will affect other tests
await deletePackage(testPackage);
await deletePackage(testPackage, testPackageVersion);
}
});
it('should install the package correctly', async function () {
await supertest
.post(`/api/fleet/epm/packages/${testPackage}`)
.post(`/api/fleet/epm/packages/${testPackage}/${testPackageVersion}`)
.set('kbn-xsrf', 'xxxx')
.expect(200);
});

View file

@ -21,16 +21,15 @@ export default function (providerContext: FtrProviderContext) {
const es: Client = getService('es');
const pkgName = 'all_assets';
const pkgVersion = '0.1.0';
const pkgKey = `${pkgName}-${pkgVersion}`;
const logsTemplateName = `logs-${pkgName}.test_logs`;
const metricsTemplateName = `metrics-${pkgName}.test_metrics`;
const uninstallPackage = async (pkg: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx');
const uninstallPackage = async (pkg: string, version: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx');
};
const installPackage = async (pkg: string) => {
const installPackage = async (pkg: string, version: string) => {
await supertest
.post(`/api/fleet/epm/packages/${pkg}`)
.post(`/api/fleet/epm/packages/${pkg}/${version}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true });
};
@ -42,11 +41,11 @@ export default function (providerContext: FtrProviderContext) {
describe('installs all assets when installing a package for the first time', async () => {
before(async () => {
if (!server.enabled) return;
await installPackage(pkgKey);
await installPackage(pkgName, pkgVersion);
});
after(async () => {
if (!server.enabled) return;
await uninstallPackage(pkgKey);
await uninstallPackage(pkgName, pkgVersion);
});
expectAssetsInstalled({
logsTemplateName,
@ -63,8 +62,8 @@ export default function (providerContext: FtrProviderContext) {
if (!server.enabled) return;
// these tests ensure that uninstall works properly so make sure that the package gets installed and uninstalled
// and then we'll test that not artifacts are left behind.
await installPackage(pkgKey);
await uninstallPackage(pkgKey);
await installPackage(pkgName, pkgVersion);
await uninstallPackage(pkgName, pkgVersion);
});
it('should have uninstalled the index templates', async function () {
const resLogsTemplate = await es.transport.request(
@ -272,13 +271,13 @@ export default function (providerContext: FtrProviderContext) {
describe('reinstalls all assets', async () => {
before(async () => {
if (!server.enabled) return;
await installPackage(pkgKey);
await installPackage(pkgName, pkgVersion);
// reinstall
await installPackage(pkgKey);
await installPackage(pkgName, pkgVersion);
});
after(async () => {
if (!server.enabled) return;
await uninstallPackage(pkgKey);
await uninstallPackage(pkgName, pkgVersion);
});
expectAssetsInstalled({
logsTemplateName,

View file

@ -20,13 +20,10 @@ export default function (providerContext: FtrProviderContext) {
const server = dockerServers.get('registry');
const pkgName = 'all_assets';
const pkgVersion = '0.1.0';
const pkgKey = `${pkgName}-${pkgVersion}`;
const experimentalPkgName = 'experimental';
const experimentalPkgKey = `${experimentalPkgName}-${pkgVersion}`;
const experimental2PkgName = 'experimental2';
const experimental2PkgKey = `${experimental2PkgName}-${pkgVersion}`;
const uploadPkgKey = 'apache-0.1.4';
const uploadPkgName = 'apache';
const installUploadPackage = async (pkg: string) => {
const buf = fs.readFileSync(testPkgArchiveZip);
@ -43,22 +40,22 @@ export default function (providerContext: FtrProviderContext) {
'../fixtures/direct_upload_packages/apache_0.1.4.zip'
);
const uninstallPackage = async (pkg: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx');
const uninstallPackage = async (pkg: string, version: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx');
};
const installPackage = async (pkg: string) => {
const installPackage = async (pkg: string, version: string) => {
await supertest
.post(`/api/fleet/epm/packages/${pkg}`)
.post(`/api/fleet/epm/packages/${pkg}/${version}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true });
};
const installPackages = async (pkgs: string[]) => {
const installingPackagesPromise = pkgs.map((pkg) => installPackage(pkg));
const installPackages = async (pkgs: Array<{ name: string; version: string }>) => {
const installingPackagesPromise = pkgs.map((pkg) => installPackage(pkg.name, pkg.version));
return Promise.all(installingPackagesPromise);
};
const uninstallPackages = async (pkgs: string[]) => {
const uninstallingPackagesPromise = pkgs.map((pkg) => uninstallPackage(pkg));
const uninstallPackages = async (pkgs: Array<{ name: string; version: string }>) => {
const uninstallingPackagesPromise = pkgs.map((pkg) => uninstallPackage(pkg.name, pkg.version));
return Promise.all(uninstallingPackagesPromise);
};
@ -67,12 +64,19 @@ export default function (providerContext: FtrProviderContext) {
setupFleetAndAgents(providerContext);
before(async () => {
if (!server.enabled) return;
await installPackages([pkgKey, experimentalPkgKey, experimental2PkgKey]);
await installUploadPackage(uploadPkgKey);
await installPackages([
{ name: pkgName, version: pkgVersion },
{ name: experimentalPkgName, version: pkgVersion },
{ name: experimental2PkgName, version: pkgVersion },
]);
await installUploadPackage(uploadPkgName);
});
after(async () => {
if (!server.enabled) return;
await uninstallPackages([pkgKey, experimentalPkgKey]);
await uninstallPackages([
{ name: pkgName, version: pkgVersion },
{ name: experimentalPkgName, version: pkgVersion },
]);
});
it('should create index patterns (without fields)', async () => {
const resIndexPatternLogs = await kibanaServer.savedObjects.get({

View file

@ -19,20 +19,20 @@ export default function (providerContext: FtrProviderContext) {
const kibanaServer = getService('kibanaServer');
const supertest = getService('supertest');
const deletePackage = async (pkgkey: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkgkey}`).set('kbn-xsrf', 'xxxx');
const deletePackage = async (name: string, version: string) => {
await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx');
};
describe('installing and updating scenarios', async () => {
skipIfNoDockerRegistry(providerContext);
setupFleetAndAgents(providerContext);
after(async () => {
await deletePackage('multiple_versions-0.3.0');
await deletePackage('multiple_versions', '0.3.0');
});
it('should return 404 if package does not exist', async function () {
await supertest
.post(`/api/fleet/epm/packages/nonexistent-0.1.0`)
.post(`/api/fleet/epm/packages/nonexistent/0.1.0`)
.set('kbn-xsrf', 'xxxx')
.expect(404);
let res;
@ -48,7 +48,7 @@ export default function (providerContext: FtrProviderContext) {
});
it('should return 400 if trying to install an out-of-date package', async function () {
await supertest
.post(`/api/fleet/epm/packages/multiple_versions-0.1.0`)
.post(`/api/fleet/epm/packages/multiple_versions/0.1.0`)
.set('kbn-xsrf', 'xxxx')
.expect(400);
let res;
@ -64,26 +64,26 @@ export default function (providerContext: FtrProviderContext) {
});
it('should return 200 if trying to force install an out-of-date package', async function () {
await supertest
.post(`/api/fleet/epm/packages/multiple_versions-0.1.0`)
.post(`/api/fleet/epm/packages/multiple_versions/0.1.0`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
});
it('should return 200 if trying to reinstall an out-of-date package', async function () {
await supertest
.post(`/api/fleet/epm/packages/multiple_versions-0.1.0`)
.post(`/api/fleet/epm/packages/multiple_versions/0.1.0`)
.set('kbn-xsrf', 'xxxx')
.expect(200);
});
it('should return 400 if trying to update to an out-of-date package', async function () {
await supertest
.post(`/api/fleet/epm/packages/multiple_versions-0.2.0`)
.post(`/api/fleet/epm/packages/multiple_versions/0.2.0`)
.set('kbn-xsrf', 'xxxx')
.expect(400);
});
it('should return 200 if trying to force update to an out-of-date package', async function () {
await supertest
.post(`/api/fleet/epm/packages/multiple_versions-0.2.0`)
.post(`/api/fleet/epm/packages/multiple_versions/0.2.0`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
@ -102,20 +102,20 @@ export default function (providerContext: FtrProviderContext) {
},
});
await supertest
.post(`/api/fleet/epm/packages/multiple_versions-0.2.0`)
.post(`/api/fleet/epm/packages/multiple_versions/0.2.0`)
.set('kbn-xsrf', 'xxxx')
.expect(200);
});
it('should return 200 if trying to update to the latest package', async function () {
await supertest
.post(`/api/fleet/epm/packages/multiple_versions-0.3.0`)
.post(`/api/fleet/epm/packages/multiple_versions/0.3.0`)
.set('kbn-xsrf', 'xxxx')
.expect(200);
await deletePackage('multiple_versions-0.3.0');
await deletePackage('multiple_versions', '0.3.0');
});
it('should return 200 if trying to install the latest package', async function () {
await supertest
.post(`/api/fleet/epm/packages/multiple_versions-0.3.0`)
.post(`/api/fleet/epm/packages/multiple_versions/0.3.0`)
.set('kbn-xsrf', 'xxxx')
.expect(200);
});

View file

@ -41,7 +41,7 @@ export default function (providerContext: FtrProviderContext) {
return response.body;
};
const listResponse = await fetchPackageList();
expect(listResponse.response.length).not.to.be(0);
expect(listResponse.items.length).not.to.be(0);
});
it('lists all limited packages from the registry', async function () {
@ -54,7 +54,7 @@ export default function (providerContext: FtrProviderContext) {
};
const listResponse = await fetchLimitedPackageList();
expect(listResponse.response).to.eql(['endpoint']);
expect(listResponse.items).to.eql(['endpoint']);
});
it('allows user with only read permission to access', async () => {

View file

@ -30,7 +30,7 @@ export default function (providerContext: FtrProviderContext) {
before(async () => {
if (!server.enabled) return;
await supertest
.post(`/api/fleet/epm/packages/${pkgName}-0.1.0`)
.post(`/api/fleet/epm/packages/${pkgName}/0.1.0`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
@ -92,7 +92,7 @@ export default function (providerContext: FtrProviderContext) {
after(async () => {
if (!server.enabled) return;
await supertest
.delete(`/api/fleet/epm/packages/multiple_versions-0.1.0`)
.delete(`/api/fleet/epm/packages/multiple_versions/0.1.0`)
.set('kbn-xsrf', 'xxxx')
.expect(200);
});
@ -101,12 +101,12 @@ export default function (providerContext: FtrProviderContext) {
before(async () => {
if (!server.enabled) return;
await supertest
.post(`/api/fleet/epm/packages/${pkgName}-0.1.0`)
.post(`/api/fleet/epm/packages/${pkgName}/0.1.0`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
await supertest
.post(`/api/fleet/epm/packages/${pkgName}-0.2.0`)
.post(`/api/fleet/epm/packages/${pkgName}/0.2.0`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
@ -174,7 +174,7 @@ export default function (providerContext: FtrProviderContext) {
after(async () => {
if (!server.enabled) return;
await supertest
.delete(`/api/fleet/epm/packages/multiple_versions-0.1.0`)
.delete(`/api/fleet/epm/packages/multiple_versions/0.1.0`)
.set('kbn-xsrf', 'xxxx')
.expect(200);
});

View file

@ -34,19 +34,19 @@ export default function (providerContext: FtrProviderContext) {
});
it('upgrades the endpoint package from 0.13.0 to the latest version available', async function () {
let { body }: { body: GetInfoResponse } = await supertest
.get(`/api/fleet/epm/packages/endpoint-${oldEndpointVersion}`)
.get(`/api/fleet/epm/packages/endpoint/${oldEndpointVersion}`)
.expect(200);
const latestEndpointVersion = body.response.latestVersion;
const latestEndpointVersion = body.item.latestVersion;
log.info(`Endpoint package latest version: ${latestEndpointVersion}`);
// make sure we're actually doing an upgrade
expect(latestEndpointVersion).not.eql(oldEndpointVersion);
await supertest.post(`/api/fleet/setup`).set('kbn-xsrf', 'xxxx').expect(200);
({ body } = await supertest
.get(`/api/fleet/epm/packages/endpoint-${latestEndpointVersion}`)
.get(`/api/fleet/epm/packages/endpoint/${latestEndpointVersion}`)
.expect(200));
expect(body.response).to.have.property('savedObject');
expect((body.response as Installed).savedObject.attributes.install_version).to.eql(
expect(body.item).to.have.property('savedObject');
expect((body.item as Installed).savedObject.attributes.install_version).to.eql(
latestEndpointVersion
);
});
@ -65,8 +65,8 @@ export default function (providerContext: FtrProviderContext) {
// POST /api/fleet/setup
// POST /api/fleet/agents/setup
// GET /api/fleet/agent_policies
// GET /api/fleet/enrollment-api-keys
// GET /api/fleet/enrollment-api-keys/<id>
// GET /api/fleet/enrollment_api_keys
// GET /api/fleet/enrollment_api_keys/<id>
await supertestWithoutAuth
.post('/api/fleet/setup')
.set('Authorization', `Bearer ${token.value}`)
@ -83,13 +83,13 @@ export default function (providerContext: FtrProviderContext) {
.set('kbn-xsrf', 'xxx')
.expect(200);
const response = await supertestWithoutAuth
.get('/api/fleet/enrollment-api-keys')
.get('/api/fleet/enrollment_api_keys')
.set('Authorization', `Bearer ${token.value}`)
.set('kbn-xsrf', 'xxx')
.expect(200);
const enrollmentApiKeyId = response.body.list[0].id;
const enrollmentApiKeyId = response.body.items[0].id;
await supertestWithoutAuth
.get(`/api/fleet/enrollment-api-keys/${enrollmentApiKeyId}`)
.get(`/api/fleet/enrollment_api_keys/${enrollmentApiKeyId}`)
.set('Authorization', `Bearer ${token.value}`)
.set('kbn-xsrf', 'xxx')
.expect(200);

View file

@ -18,18 +18,16 @@ export default function (providerContext: FtrProviderContext) {
const pkgName = 'all_assets';
const pkgVersion = '0.1.0';
const pkgUpdateVersion = '0.2.0';
const pkgKey = `${pkgName}-${pkgVersion}`;
const pkgUpdateKey = `${pkgName}-${pkgUpdateVersion}`;
const logsTemplateName = `logs-${pkgName}.test_logs`;
const logsTemplateName2 = `logs-${pkgName}.test_logs2`;
const metricsTemplateName = `metrics-${pkgName}.test_metrics`;
const uninstallPackage = async (pkg: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx');
const uninstallPackage = async (pkg: string, version: string) => {
await supertest.delete(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx');
};
const installPackage = async (pkg: string) => {
const installPackage = async (pkg: string, version: string) => {
await supertest
.post(`/api/fleet/epm/packages/${pkg}`)
.post(`/api/fleet/epm/packages/${pkg}/${version}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true });
};
@ -39,11 +37,11 @@ export default function (providerContext: FtrProviderContext) {
setupFleetAndAgents(providerContext);
before(async () => {
await installPackage(pkgKey);
await installPackage(pkgUpdateKey);
await installPackage(pkgName, pkgVersion);
await installPackage(pkgName, pkgUpdateVersion);
});
after(async () => {
await uninstallPackage(pkgUpdateKey);
await uninstallPackage(pkgName, pkgUpdateVersion);
});
it('should have updated the ILM policy', async function () {
const resPolicy = await es.ilm.getLifecycle(

View file

@ -22,7 +22,7 @@ export default function (providerContext: FtrProviderContext) {
function withTestPackageVersion(version: string) {
before(async function () {
await supertest
.post(`/api/fleet/epm/packages/package_policy_upgrade-${version}`)
.post(`/api/fleet/epm/packages/package_policy_upgrade/${version}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
@ -30,7 +30,7 @@ export default function (providerContext: FtrProviderContext) {
after(async function () {
await supertest
.delete(`/api/fleet/epm/packages/package_policy_upgrade-${version}`)
.delete(`/api/fleet/epm/packages/package_policy_upgrade/${version}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);

View file

@ -23,10 +23,10 @@ export default function (providerContext: FtrProviderContext) {
await esArchiver.unload('x-pack/test/functional/es_archives/empty_kibana');
});
describe('POST /api/fleet/service-tokens', () => {
describe('POST /api/fleet/service_tokens', () => {
it('should create a valid service account token', async () => {
const { body: apiResponse } = await supertest
.post(`/api/fleet/service-tokens`)
.post(`/api/fleet/service_tokens`)
.set('kbn-xsrf', 'xxxx')
.expect(200);
@ -44,5 +44,9 @@ export default function (providerContext: FtrProviderContext) {
expect(tokensResponse.tokens).have.property(apiResponse.name);
});
});
it('should work with deprecated api', async () => {
await supertest.post(`/api/fleet/service-tokens`).set('kbn-xsrf', 'xxxx').expect(200);
});
});
}

View file

@ -50,10 +50,10 @@ export class AgentManager extends Manager {
public async startAgent() {
this.log.info('Getting agent enrollment key');
const { data: apiKeys } = await axios.get(
this.params.kibanaUrl + '/api/fleet/enrollment-api-keys',
this.params.kibanaUrl + '/api/fleet/enrollment_api_keys',
this.requestOptions
);
const policy = apiKeys.list[1];
const policy = apiKeys.items[1];
this.log.info('Running the agent');
@ -87,7 +87,7 @@ export class AgentManager extends Manager {
`${this.params.kibanaUrl}/api/fleet/agents`,
this.requestOptions
);
done = agents.list[0]?.status === 'online';
done = agents.items[0]?.status === 'online';
if (++retries > 12) {
this.log.error('Giving up on enrolling the agent after a minute');
throw new Error('Agent timed out while coming online');

View file

@ -474,25 +474,24 @@ export function MachineLearningTestResourcesProvider({ getService }: FtrProvider
log.debug(`Installing Fleet package '${packageName}'`);
const version = await this.getFleetPackageVersion(packageName);
const packageWithVersion = `${packageName}-${version}`;
await retry.tryForTime(30 * 1000, async () => {
await supertest
.post(`/api/fleet/epm/packages/${packageWithVersion}`)
.post(`/api/fleet/epm/packages/${packageName}/${version}`)
.set(COMMON_REQUEST_HEADERS)
.expect(200);
});
log.debug(` > Installed`);
return packageWithVersion;
return version;
},
async removeFleetPackage(packageWithVersion: string) {
log.debug(`Removing Fleet package '${packageWithVersion}'`);
async removeFleetPackage(packageName: string, version: string) {
log.debug(`Removing Fleet package '${packageName}-${version}'`);
await retry.tryForTime(30 * 1000, async () => {
await supertest
.delete(`/api/fleet/epm/packages/${packageWithVersion}`)
.delete(`/api/fleet/epm/packages/${packageName}/${version}`)
.set(COMMON_REQUEST_HEADERS)
.expect(200);
});

View file

@ -38,7 +38,7 @@ export function SyntheticsPackageProvider({ getService }: FtrProviderContext) {
// Retrieve information about the Synthetics package
// EPM does not currently have an API to get the "lastest" information for a page given its name,
// so we'll retrieve a list of packages and then find the package info in the list.
let apiRequest: Promise<GetPackagesResponse['response'][0] | undefined>;
let apiRequest: Promise<GetPackagesResponse['items'][0] | undefined>;
return () => {
if (!apiRequest) {
@ -57,7 +57,7 @@ export function SyntheticsPackageProvider({ getService }: FtrProviderContext) {
})
.then((response: { body: GetPackagesResponse }) => {
const { body } = response;
const syntheticsPackageInfo = body.response.find(
const syntheticsPackageInfo = body.items.find(
(epmPackage) => epmPackage.name === 'synthetics'
);
if (!syntheticsPackageInfo) {

View file

@ -50,10 +50,10 @@ export class AgentManager extends Manager {
public async startAgent() {
this.log.info('Getting agent enrollment key');
const { data: apiKeys } = await axios.get(
this.params.kibanaUrl + '/api/fleet/enrollment-api-keys',
this.params.kibanaUrl + '/api/fleet/enrollment_api_keys',
this.requestOptions
);
const policy = apiKeys.list[1];
const policy = apiKeys.items[1];
this.log.info('Running the agent');
@ -87,7 +87,7 @@ export class AgentManager extends Manager {
`${this.params.kibanaUrl}/api/fleet/agents`,
this.requestOptions
);
done = agents.list[0]?.status === 'online';
done = agents.items[0]?.status === 'online';
if (++retries > 12) {
this.log.error('Giving up on enrolling the agent after a minute');
throw new Error('Agent timed out while coming online');

View file

@ -48,7 +48,7 @@ export interface PolicyTestResourceInfo {
/**
* Information about the endpoint package
*/
packageInfo: Immutable<GetPackagesResponse['response'][0]>;
packageInfo: Immutable<GetPackagesResponse['items'][0]>;
/** will clean up (delete) the objects created (Agent Policy + Package Policy) */
cleanup: () => Promise<void>;
}
@ -72,7 +72,7 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC
// so we'll retrieve a list of packages for a category of Security, and will then find the
// endpoint package info. in the list. The request is kicked off here, but handled below after
// Agent Policy creation so that they can be executed concurrently
let apiRequest: Promise<GetPackagesResponse['response'][0] | undefined>;
let apiRequest: Promise<GetPackagesResponse['items'][0] | undefined>;
return () => {
if (!apiRequest) {
@ -94,7 +94,7 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC
})
.then((response: { body: GetPackagesResponse }) => {
const { body: secPackages } = response;
const endpointPackageInfo = secPackages.response.find(
const endpointPackageInfo = secPackages.items.find(
(epmPackage) => epmPackage.name === 'endpoint'
);
if (!endpointPackageInfo) {
@ -124,11 +124,11 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC
/**
* Retrieves the currently installed endpoint package
*/
async getEndpointPackage(): Promise<Immutable<GetPackagesResponse['response'][0]>> {
async getEndpointPackage(): Promise<Immutable<GetPackagesResponse['items'][0]>> {
const endpointPackage = await retrieveEndpointPackageInfo();
if (!endpointPackage) {
throw new EndpointError(`endpoint package not instealled`);
throw new EndpointError(`endpoint package not installed`);
}
return endpointPackage;