mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 11:05:39 -04:00
# Backport This will backport the following commits from `main` to `9.0`: - [[Fleet] Fix dataset validation to show errors on upgrade (#219741)](https://github.com/elastic/kibana/pull/219741) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Nicolas Chaulet","email":"nicolas.chaulet@elastic.co"},"sourceCommit":{"committedDate":"2025-05-01T11:36:24Z","message":"[Fleet] Fix dataset validation to show errors on upgrade (#219741)","sha":"8081bd35eb5e2d2d50e2291a1dbabd0e37307ab7","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Fleet","v9.0.0","backport:prev-minor","backport:version","v9.1.0","v8.19.0","backport:8.18","v8.18.1","v8.18.2"],"title":"[Fleet] Fix dataset validation to show errors on upgrade","number":219741,"url":"https://github.com/elastic/kibana/pull/219741","mergeCommit":{"message":"[Fleet] Fix dataset validation to show errors on upgrade (#219741)","sha":"8081bd35eb5e2d2d50e2291a1dbabd0e37307ab7"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.19","8.18"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/219741","number":219741,"mergeCommit":{"message":"[Fleet] Fix dataset validation to show errors on upgrade (#219741)","sha":"8081bd35eb5e2d2d50e2291a1dbabd0e37307ab7"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
5b14c15a56
commit
d06913c217
8 changed files with 24586 additions and 2022 deletions
|
@ -37295,12 +37295,36 @@
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"additionalProperties": false,
|
"additionalProperties": true,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"created_at": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"created_by": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"description": "Package policy description",
|
"description": "Package policy description",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"elasticsearch": {
|
||||||
|
"additionalProperties": true,
|
||||||
|
"properties": {
|
||||||
|
"privileges": {
|
||||||
|
"additionalProperties": true,
|
||||||
|
"properties": {
|
||||||
|
"cluster": {
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"enabled": {
|
"enabled": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
@ -37332,6 +37356,7 @@
|
||||||
"items": {
|
"items": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"compiled_input": {},
|
||||||
"config": {
|
"config": {
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
@ -37503,7 +37528,8 @@
|
||||||
"required": [
|
"required": [
|
||||||
"type",
|
"type",
|
||||||
"enabled",
|
"enabled",
|
||||||
"streams"
|
"streams",
|
||||||
|
"compiled_input"
|
||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
@ -37613,12 +37639,36 @@
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
|
"revision": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"secret_references": {
|
||||||
|
"items": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
"supports_agentless": {
|
"supports_agentless": {
|
||||||
"default": false,
|
"default": false,
|
||||||
"description": "Indicates whether the package policy belongs to an agentless agent policy.",
|
"description": "Indicates whether the package policy belongs to an agentless agent policy.",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"updated_by": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"vars": {
|
"vars": {
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
@ -37638,6 +37688,9 @@
|
||||||
},
|
},
|
||||||
"description": "Package variable (see integration documentation for more information)",
|
"description": "Package variable (see integration documentation for more information)",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -37660,12 +37660,28 @@ paths:
|
||||||
- updated_by
|
- updated_by
|
||||||
- created_at
|
- created_at
|
||||||
- created_by
|
- created_by
|
||||||
- additionalProperties: false
|
- additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
created_at:
|
||||||
|
type: string
|
||||||
|
created_by:
|
||||||
|
type: string
|
||||||
description:
|
description:
|
||||||
description: Package policy description
|
description: Package policy description
|
||||||
type: string
|
type: string
|
||||||
|
elasticsearch:
|
||||||
|
additionalProperties: true
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
privileges:
|
||||||
|
additionalProperties: true
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
cluster:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
enabled:
|
enabled:
|
||||||
type: boolean
|
type: boolean
|
||||||
errors:
|
errors:
|
||||||
|
@ -37689,6 +37705,7 @@ paths:
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
compiled_input: {}
|
||||||
config:
|
config:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
@ -37809,6 +37826,7 @@ paths:
|
||||||
- type
|
- type
|
||||||
- enabled
|
- enabled
|
||||||
- streams
|
- streams
|
||||||
|
- compiled_input
|
||||||
type: array
|
type: array
|
||||||
is_managed:
|
is_managed:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
@ -37884,11 +37902,27 @@ paths:
|
||||||
description: Agent policy IDs where that package policy will be added
|
description: Agent policy IDs where that package policy will be added
|
||||||
type: string
|
type: string
|
||||||
type: array
|
type: array
|
||||||
|
revision:
|
||||||
|
type: number
|
||||||
|
secret_references:
|
||||||
|
items:
|
||||||
|
additionalProperties: false
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
type: array
|
||||||
supports_agentless:
|
supports_agentless:
|
||||||
default: false
|
default: false
|
||||||
description: Indicates whether the package policy belongs to an agentless agent policy.
|
description: Indicates whether the package policy belongs to an agentless agent policy.
|
||||||
nullable: true
|
nullable: true
|
||||||
type: boolean
|
type: boolean
|
||||||
|
updated_at:
|
||||||
|
type: string
|
||||||
|
updated_by:
|
||||||
|
type: string
|
||||||
vars:
|
vars:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
@ -37903,6 +37937,8 @@ paths:
|
||||||
- value
|
- value
|
||||||
description: Package variable (see integration documentation for more information)
|
description: Package variable (see integration documentation for more information)
|
||||||
type: object
|
type: object
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
- enabled
|
- enabled
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { createFleetTestRendererMock } from '../../../../../../../../mock';
|
||||||
import { DatasetComponent } from './dataset_component';
|
import { DatasetComponent } from './dataset_component';
|
||||||
|
|
||||||
describe('DatasetComponent', () => {
|
describe('DatasetComponent', () => {
|
||||||
function render(value = 'generic', datastreams: any = []) {
|
function render(value = 'generic', datastreams: any = [], props?: any) {
|
||||||
const renderer = createFleetTestRendererMock();
|
const renderer = createFleetTestRendererMock();
|
||||||
const mockOnChange = jest.fn();
|
const mockOnChange = jest.fn();
|
||||||
const fieldLabel = 'Dataset name';
|
const fieldLabel = 'Dataset name';
|
||||||
|
@ -29,6 +29,7 @@ describe('DatasetComponent', () => {
|
||||||
onChange={mockOnChange}
|
onChange={mockOnChange}
|
||||||
isDisabled={false}
|
isDisabled={false}
|
||||||
fieldLabel={fieldLabel}
|
fieldLabel={fieldLabel}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -36,22 +37,23 @@ describe('DatasetComponent', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should show validation error if dataset is invalid', () => {
|
it('should show validation error if dataset is invalid', () => {
|
||||||
const { utils } = render();
|
const { utils } = render('generic', [], {
|
||||||
|
errors: ['Dataset contains invalid characters'],
|
||||||
const inputEl = utils.getByTestId('comboBoxSearchInput');
|
isInvalid: true,
|
||||||
fireEvent.change(inputEl, { target: { value: 'generic*' } });
|
});
|
||||||
fireEvent.keyDown(inputEl, { key: 'Enter', code: 'Enter' });
|
|
||||||
|
|
||||||
utils.getByText('Dataset contains invalid characters');
|
utils.getByText('Dataset contains invalid characters');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show validation error if dataset is valid', () => {
|
it('should not show validation error if dataset is valid', () => {
|
||||||
const { utils } = render();
|
const { utils, mockOnChange } = render();
|
||||||
|
|
||||||
const inputEl = utils.getByTestId('comboBoxSearchInput');
|
const inputEl = utils.getByTestId('comboBoxSearchInput');
|
||||||
fireEvent.change(inputEl, { target: { value: 'test' } });
|
fireEvent.change(inputEl, { target: { value: 'test' } });
|
||||||
fireEvent.keyDown(inputEl, { key: 'Enter', code: 'Enter' });
|
fireEvent.keyDown(inputEl, { key: 'Enter', code: 'Enter' });
|
||||||
|
|
||||||
|
expect(mockOnChange).toBeCalled();
|
||||||
|
|
||||||
expect(utils.queryByText('Dataset contains invalid characters')).toBeNull();
|
expect(utils.queryByText('Dataset contains invalid characters')).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
|
||||||
import type { DataStream } from '../../../../../../../../../common/types';
|
import type { DataStream } from '../../../../../../../../../common/types';
|
||||||
import { GENERIC_DATASET_NAME } from '../../../../../../../../../common/constants';
|
import { GENERIC_DATASET_NAME } from '../../../../../../../../../common/constants';
|
||||||
import { isValidDataset } from '../../../../../../../../../common';
|
|
||||||
|
|
||||||
const FormRow = styled(EuiFormRow)`
|
const FormRow = styled(EuiFormRow)`
|
||||||
.euiFormRow__label {
|
.euiFormRow__label {
|
||||||
|
@ -48,7 +47,19 @@ export const DatasetComponent: React.FC<{
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
fieldLabel: string;
|
fieldLabel: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
}> = ({ value, onChange, datastreams, isDisabled, pkgName = '', fieldLabel, description }) => {
|
errors?: string[] | null;
|
||||||
|
isInvalid?: boolean;
|
||||||
|
}> = ({
|
||||||
|
value,
|
||||||
|
errors,
|
||||||
|
onChange,
|
||||||
|
datastreams,
|
||||||
|
isDisabled,
|
||||||
|
isInvalid,
|
||||||
|
pkgName = '',
|
||||||
|
fieldLabel,
|
||||||
|
description,
|
||||||
|
}) => {
|
||||||
const datasetOptions =
|
const datasetOptions =
|
||||||
datastreams.map((datastream: DataStream) => ({
|
datastreams.map((datastream: DataStream) => ({
|
||||||
label: datastream.dataset,
|
label: datastream.dataset,
|
||||||
|
@ -67,8 +78,8 @@ export const DatasetComponent: React.FC<{
|
||||||
};
|
};
|
||||||
|
|
||||||
const [selectedOptions, setSelectedOptions] = useState<Array<{ label: string }>>([defaultOption]);
|
const [selectedOptions, setSelectedOptions] = useState<Array<{ label: string }>>([defaultOption]);
|
||||||
const [isInvalid, setIsInvalid] = useState<boolean>(false);
|
|
||||||
const [error, setError] = useState<string | undefined>(undefined);
|
const error = errors ? errors.join(', ') : undefined;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!value || typeof value === 'string') onChange(defaultOption.value as SelectedDataset);
|
if (!value || typeof value === 'string') onChange(defaultOption.value as SelectedDataset);
|
||||||
|
@ -77,9 +88,7 @@ export const DatasetComponent: React.FC<{
|
||||||
const onDatasetChange = (newSelectedOptions: Array<{ label: string; value?: DataStream }>) => {
|
const onDatasetChange = (newSelectedOptions: Array<{ label: string; value?: DataStream }>) => {
|
||||||
setSelectedOptions(newSelectedOptions);
|
setSelectedOptions(newSelectedOptions);
|
||||||
const dataStream = newSelectedOptions[0].value;
|
const dataStream = newSelectedOptions[0].value;
|
||||||
const { valid, error: dsError } = isValidDataset(newSelectedOptions[0].label, false);
|
|
||||||
setIsInvalid(!valid);
|
|
||||||
setError(dsError);
|
|
||||||
onChange({
|
onChange({
|
||||||
dataset: newSelectedOptions[0].label,
|
dataset: newSelectedOptions[0].label,
|
||||||
package: !dataStream || typeof dataStream === 'string' ? pkgName : dataStream.package,
|
package: !dataStream || typeof dataStream === 'string' ? pkgName : dataStream.package,
|
||||||
|
@ -96,9 +105,6 @@ export const DatasetComponent: React.FC<{
|
||||||
value: { dataset: searchValue, package: pkgName },
|
value: { dataset: searchValue, package: pkgName },
|
||||||
};
|
};
|
||||||
setSelectedOptions([newOption]);
|
setSelectedOptions([newOption]);
|
||||||
const { valid, error: dsError } = isValidDataset(searchValue, false);
|
|
||||||
setIsInvalid(!valid);
|
|
||||||
setError(dsError);
|
|
||||||
onChange({
|
onChange({
|
||||||
dataset: searchValue,
|
dataset: searchValue,
|
||||||
package: pkgName,
|
package: pkgName,
|
||||||
|
|
|
@ -107,6 +107,8 @@ export const PackagePolicyInputVarField: React.FunctionComponent<InputFieldProps
|
||||||
datastreams={datastreams}
|
datastreams={datastreams}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
errors={errors}
|
||||||
|
isInvalid={isInvalid}
|
||||||
isDisabled={isEditPage}
|
isDisabled={isEditPage}
|
||||||
fieldLabel={fieldLabel}
|
fieldLabel={fieldLabel}
|
||||||
description={description}
|
description={description}
|
||||||
|
|
|
@ -402,20 +402,29 @@ export const OrphanedPackagePoliciesResponseSchema = schema.object({
|
||||||
total: schema.number(),
|
total: schema.number(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const DryRunPackagePolicySchema = schema.object({
|
export const DryRunPackagePolicySchema = PackagePolicySchema.extends(
|
||||||
...PackagePolicyBaseSchema,
|
{
|
||||||
id: schema.maybe(schema.string()),
|
id: schema.maybe(schema.string()),
|
||||||
force: schema.maybe(schema.boolean()),
|
force: schema.maybe(schema.boolean()),
|
||||||
errors: schema.maybe(
|
revision: schema.maybe(schema.number()),
|
||||||
schema.arrayOf(
|
updated_at: schema.maybe(schema.string()),
|
||||||
schema.object({
|
updated_by: schema.maybe(schema.string()),
|
||||||
message: schema.string(),
|
created_at: schema.maybe(schema.string()),
|
||||||
key: schema.maybe(schema.string()),
|
created_by: schema.maybe(schema.string()),
|
||||||
})
|
errors: schema.maybe(
|
||||||
)
|
schema.arrayOf(
|
||||||
),
|
schema.object({
|
||||||
missingVars: schema.maybe(schema.arrayOf(schema.string())),
|
message: schema.string(),
|
||||||
});
|
key: schema.maybe(schema.string()),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
),
|
||||||
|
missingVars: schema.maybe(schema.arrayOf(schema.string())),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
unknowns: 'allow',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const PackagePolicyStatusResponseSchema = schema.object({
|
export const PackagePolicyStatusResponseSchema = schema.object({
|
||||||
id: schema.string(),
|
id: schema.string(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue