Skip to content

Commit

Permalink
Merge branch 'main' into fleet/173048-dot-notation-secret-var-names
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Dec 12, 2023
2 parents 17b8173 + 849e3d4 commit 2ed16ac
Show file tree
Hide file tree
Showing 29 changed files with 646 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .buildkite/pipelines/quality-gates/pipeline.kibana-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
#
# Docs: https://docs.elastic.dev/serverless/qualitygates

agents:
cpu: 2
ephemeralStorage: "20G"
memory: "8G"

env:
TEAM_CHANNEL: "#kibana-mission-control"
ENVIRONMENT: ${ENVIRONMENT?}
Expand Down
2 changes: 1 addition & 1 deletion examples/README.asciidoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[[example-plugins]]
== Example plugins

This folder contains example plugins. To run the plugins in this folder, use the `--run-examples` flag, via
This folder contains example plugins. To run the plugins in this folder, use the `--run-examples` flag (without a basepath), via

[source,bash]
----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
EuiTabbedContentTab,
EuiTitle,
EuiText,
EuiTextColor,
} from '@elastic/eui';

import { i18n } from '@kbn/i18n';
Expand Down Expand Up @@ -130,15 +131,27 @@ export const ConfigurePipeline: React.FC = () => {
<EuiSpacer />
</>
)}
<EuiFormRow
fullWidth
label={i18n.translate(
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.titleSelectTrainedModel',
{ defaultMessage: 'Select a trained ML Model' }
)}
>
<ModelSelect />
</EuiFormRow>
<EuiSpacer size="s" />
<EuiTitle size="xxxs">
<h6>
{i18n.translate(
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.titleSelectTrainedModel',
{ defaultMessage: 'Select a trained ML Model' }
)}
</h6>
</EuiTitle>
{formErrors.modelStatus !== undefined && (
<>
<EuiSpacer size="xs" />
<EuiText size="xs">
<p>
<EuiTextColor color="danger">{formErrors.modelStatus}</EuiTextColor>
</p>
</EuiText>
</>
)}
<EuiSpacer size="xs" />
<ModelSelect />
</EuiForm>
</>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,25 @@ describe('MlInferenceLogic', () => {
pipelineName: 'Name already used by another pipeline.',
});
});
it('has errors when non-deployed model is selected', () => {
MLInferenceLogic.actions.setInferencePipelineConfiguration({
...MLInferenceLogic.values.addInferencePipelineModal.configuration,
pipelineName: 'unit-test-pipeline',
modelID: 'unit-test-model',
existingPipeline: false,
fieldMappings: [
{
sourceField: 'body',
targetField: 'ml.inference.body',
},
],
isModelPlaceholderSelected: true,
});

expect(MLInferenceLogic.values.formErrors).toEqual({
modelStatus: 'Model must be deployed before use.',
});
});
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,23 @@ describe('ModelSelect', () => {
})
);
});
it('sets placeholder flag on selecting a placeholder item', () => {
setMockValues(DEFAULT_VALUES);

const wrapper = shallow(<ModelSelect />);
expect(wrapper.find(EuiSelectable)).toHaveLength(1);
const selectable = wrapper.find(EuiSelectable);
selectable.simulate('change', [
{ modelId: 'model_1' },
{ modelId: 'model_2', isPlaceholder: true, checked: 'on' },
]);
expect(MOCK_ACTIONS.setInferencePipelineConfiguration).toHaveBeenCalledWith(
expect.objectContaining({
modelID: 'model_2',
isModelPlaceholderSelected: true,
})
);
});
it('generates pipeline name on selecting an item', () => {
setMockValues(DEFAULT_VALUES);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const ModelSelect: React.FC = () => {
...configuration,
inferenceConfig: undefined,
modelID: selectedOption?.modelId ?? '',
isModelPlaceholderSelected: selectedOption?.isPlaceholder ?? false,
fieldMappings: undefined,
pipelineName: isPipelineNameUserSupplied
? pipelineName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface InferencePipelineConfiguration {
existingPipeline?: boolean;
inferenceConfig?: InferencePipelineInferenceConfig;
isPipelineNameUserSupplied?: boolean;
isModelPlaceholderSelected?: boolean;
modelID: string;
pipelineName: string;
fieldMappings?: FieldMapping[];
Expand All @@ -21,6 +22,7 @@ export interface InferencePipelineConfiguration {

export interface AddInferencePipelineFormErrors {
modelID?: string;
modelStatus?: string;
fieldMappings?: string;
pipelineName?: string;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ const PIPELINE_NAME_EXISTS_ERROR = i18n.translate(
defaultMessage: 'Name already used by another pipeline.',
}
);
const MODEL_NOT_DEPLOYED_ERROR = i18n.translate(
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.modelNotDeployedError',
{
defaultMessage: 'Model must be deployed before use.',
}
);

export const validateInferencePipelineConfiguration = (
config: InferencePipelineConfiguration
Expand All @@ -55,6 +61,8 @@ export const validateInferencePipelineConfiguration = (
}
if (config.modelID.trim().length === 0) {
errors.modelID = FIELD_REQUIRED_ERROR;
} else if (config.isModelPlaceholderSelected) {
errors.modelStatus = MODEL_NOT_DEPLOYED_ERROR;
}

return errors;
Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/fleet/server/services/epm/agent/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export function compileTemplate(variables: PackagePolicyConfigRecord, templateSt
const { vars, yamlValues } = buildTemplateVariables(logger, variables);
let compiledTemplate: string;
try {
logger.debug(`Compiling agent template: ${templateStr}`);
const template = handlebars.compile(templateStr, { noEscape: true });
compiledTemplate = template(vars);
} catch (err) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ export async function _installPackage({
await packagePolicyService.upgrade(savedObjectsClient, esClient, policyIdsToUpgrade.items);
});
}
logger.debug(`Package install - Installation complete}`);
logger.debug(`Package install - Installation complete`);
return [...installedKibanaAssetsRefs, ...esReferences];
} catch (err) {
if (SavedObjectsErrorHelpers.isConflictError(err)) {
Expand Down
4 changes: 1 addition & 3 deletions x-pack/plugins/fleet/server/services/epm/packages/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,9 +516,7 @@ async function installPackageCommon(options: {
} = options;
let { telemetryEvent } = options;
const logger = appContextService.getLogger();
logger.info(
`Install - Starting installation of ${pkgName}@${pkgVersion} from ${installSource}, paths: ${paths}`
);
logger.info(`Install - Starting installation of ${pkgName}@${pkgVersion} from ${installSource} `);

// Workaround apm issue with async spans: https://github.com/elastic/apm-agent-nodejs/issues/2611
await Promise.resolve();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import { formatHumanReadableDateTimeSeconds, timeFormatter } from '@kbn/ml-date-
import { SEARCH_QUERY_LANGUAGE } from '@kbn/ml-query-utils';
import type { DataView, DataViewField } from '@kbn/data-views-plugin/common';
import { CATEGORIZE_FIELD_TRIGGER } from '@kbn/ml-ui-actions';
import { isDefined } from '@kbn/ml-is-defined';
import { escapeQuotes } from '@kbn/es-query';
import { PLUGIN_ID } from '../../../../common/constants/app';
import { mlJobService } from '../../services/job_service';
import { findMessageField, getDataViewIdFromName } from '../../util/index_utils';
Expand Down Expand Up @@ -265,12 +267,19 @@ export const LinksMenuUI = (props: LinksMenuProps) => {

if (record.influencers) {
kqlQuery = record.influencers
.map(
(influencer) =>
`"${influencer.influencer_field_name}":"${
influencer.influencer_field_values[0] ?? ''
}"`
)
.filter((influencer) => isDefined(influencer))
.map((influencer) => {
const values = influencer.influencer_field_values;

if (values.length > 0) {
const fieldName = escapeQuotes(influencer.influencer_field_name);
const escapedVals = values
.filter((value) => isDefined(value))
.map((value) => `"${fieldName}":"${escapeQuotes(value)}"`);
// Ensure there's enclosing () if there are multiple field values,
return escapedVals.length > 1 ? `(${escapedVals.join(' OR ')})` : escapedVals[0];
}
})
.join(' AND ');
}

Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/observability/common/locators/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const SLOS_WELCOME_PATH = '/slos/welcome' as const;
export const SLO_DETAIL_PATH = '/slos/:sloId' as const;
export const SLO_CREATE_PATH = '/slos/create' as const;
export const SLO_EDIT_PATH = '/slos/edit/:sloId' as const;
export const SLOS_OUTDATED_DEFINITIONS_PATH = '/slos/outdated-definitions' as const;
export const CASES_PATH = '/cases' as const;

export const paths = {
Expand All @@ -31,6 +32,7 @@ export const paths = {
ruleDetails: (ruleId: string) => `${OBSERVABILITY_BASE_PATH}${RULES_PATH}/${encodeURI(ruleId)}`,
slos: `${OBSERVABILITY_BASE_PATH}${SLOS_PATH}`,
slosWelcome: `${OBSERVABILITY_BASE_PATH}${SLOS_WELCOME_PATH}`,
slosOutdatedDefinitions: `${OBSERVABILITY_BASE_PATH}${SLOS_OUTDATED_DEFINITIONS_PATH}`,
sloCreate: `${OBSERVABILITY_BASE_PATH}${SLO_CREATE_PATH}`,
sloCreateWithEncodedForm: (encodedParams: string) =>
`${OBSERVABILITY_BASE_PATH}${SLO_CREATE_PATH}?_a=${encodedParams}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

import { EuiConfirmModal } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { ALL_VALUE, SLOWithSummaryResponse } from '@kbn/slo-schema';
import { ALL_VALUE, SLOResponse, SLOWithSummaryResponse } from '@kbn/slo-schema';
import React from 'react';

export interface SloDeleteConfirmationModalProps {
slo: SLOWithSummaryResponse;
slo: SLOWithSummaryResponse | SLOResponse;
onCancel: () => void;
onConfirm: () => void;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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 { EuiConfirmModal } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { SLOResponse, SLOWithSummaryResponse } from '@kbn/slo-schema';
import React from 'react';

export interface SloResetConfirmationModalProps {
slo: SLOWithSummaryResponse | SLOResponse;
onCancel: () => void;
onConfirm: () => void;
}

export function SloResetConfirmationModal({
slo,
onCancel,
onConfirm,
}: SloResetConfirmationModalProps) {
const { name } = slo;
return (
<EuiConfirmModal
buttonColor="danger"
data-test-subj="sloResetConfirmationModal"
title={i18n.translate('xpack.observability.slo.resetConfirmationModal.title', {
defaultMessage: 'Reset {name}?',
values: { name },
})}
cancelButtonText={i18n.translate(
'xpack.observability.slo.resetConfirmationModal.cancelButtonLabel',
{ defaultMessage: 'Cancel' }
)}
confirmButtonText={i18n.translate(
'xpack.observability.slo.resetConfirmationModal.resetButtonLabel',
{ defaultMessage: 'Reset' }
)}
onCancel={onCancel}
onConfirm={onConfirm}
>
{i18n.translate('xpack.observability.slo.resetConfirmationModal.descriptionText', {
defaultMessage: 'Resetting this SLO will also regenerate the historical data.',
})}
</EuiConfirmModal>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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 { EuiButton, EuiCallOut } from '@elastic/eui';
import React from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { useFetchSloDefinitions } from '../../../hooks/slo/use_fetch_slo_definitions';
import { useKibana } from '../../../utils/kibana_react';
import { paths } from '../../../../common/locators/paths';

export function SloOutdatedCallout() {
const {
application: { navigateToUrl },
http: { basePath },
} = useKibana().services;

const handleClick = () => {
navigateToUrl(basePath.prepend(paths.observability.slosOutdatedDefinitions));
};

const { isLoading, data } = useFetchSloDefinitions({ includeOutdatedOnly: true });
if (!isLoading && data && data.total > 0) {
return (
<EuiCallOut
color="warning"
iconType="warning"
title={i18n.translate('xpack.observability.slo.outdatedSloCallout.title', {
defaultMessage: '{total} Outdated SLOs Detected',
values: {
total: data.total,
},
})}
>
<p>
<FormattedMessage
id="xpack.observability.slo.outdatedSloCallout.message"
defaultMessage="We've noticed that you have {total} outdated SLO definitions, these SLOs will not be running or alerting until you've reset them. Please click the button below to review the SLO definitions; you can choose to either reset the SLO definition or remove it."
values={{ total: data.total }}
/>
</p>
<p>
<EuiButton
color="warning"
data-test-subj="o11ySloOutdatedCalloutViewOutdatedSloDefinitionsButton"
fill
onClick={handleClick}
>
<FormattedMessage
id="xpack.observability.outdatedSloCallout.buttonLabel"
defaultMessage="Review Outdated SLO Definitions"
/>
</EuiButton>
</p>
</EuiCallOut>
);
}
return null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export const sloKeys = {
historicalSummaries: () => [...sloKeys.all, 'historicalSummary'] as const,
historicalSummary: (list: Array<{ sloId: string; instanceId: string }>) =>
[...sloKeys.historicalSummaries(), list] as const,
definitions: (search: string) => [...sloKeys.all, 'definitions', search] as const,
definitions: (search: string, page: number, perPage: number, includeOutdatedOnly: boolean) =>
[...sloKeys.all, 'definitions', search, page, perPage, includeOutdatedOnly] as const,
globalDiagnosis: () => [...sloKeys.all, 'globalDiagnosis'] as const,
burnRates: (sloId: string, instanceId: string | undefined) =>
[...sloKeys.all, 'burnRates', sloId, instanceId] as const,
Expand Down
Loading

0 comments on commit 2ed16ac

Please sign in to comment.