Skip to content

Commit

Permalink
Merge branch 'main' into fix/142123
Browse files Browse the repository at this point in the history
  • Loading branch information
dej611 authored Oct 4, 2022
2 parents ab56cd2 + 53bf927 commit 10a2cc9
Show file tree
Hide file tree
Showing 252 changed files with 4,852 additions and 2,678 deletions.
2 changes: 1 addition & 1 deletion .buildkite/scripts/steps/storybooks/build_and_upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const STORYBOOKS = [
'apm',
'canvas',
'ci_composite',
'cloud',
'cloud_chat',
'coloring',
'chart_icons',
'controls',
Expand Down
9 changes: 9 additions & 0 deletions docs/api/saved-objects/find.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ experimental[] Retrieve a paginated set of {kib} saved objects by various condit
`has_reference`::
(Optional, object) Filters to objects that have a relationship with the type and ID combination.

`has_reference_operator`::
(Optional, string) The operator to use for the `has_reference` parameter. Either `OR` or `AND`. Defaults to `OR`.

`has_no_reference`::
(Optional, object) Filters to objects that do not have a relationship with the type and ID combination.

`has_no_reference_operator`::
(Optional, string) The operator to use for the `has_no_reference` parameter. Either `OR` or `AND`. Defaults to `OR`.

`filter`::
(Optional, string) The filter is a KQL string with the caveat that if you filter with an attribute from your saved object type,
it should look like that: `savedObjectType.attributes.title: "myTitle"`. However, If you use a root attribute of a saved
Expand Down
12 changes: 12 additions & 0 deletions docs/developer/plugin-list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,22 @@ The plugin exposes the static DefaultEditorController class to consume.
|The cloud plugin adds Cloud-specific features to Kibana.
|{kib-repo}blob/{branch}/x-pack/plugins/cloud_integrations/cloud_chat/README.md[cloudChat]
|Integrates with DriftChat in order to provide live support to our Elastic Cloud users. This plugin should only run on Elastic Cloud.
|{kib-repo}blob/{branch}/x-pack/plugins/cloud_integrations/cloud_experiments/README.mdx[cloudExperiments]
|The Cloud Experiments Service provides the necessary APIs to implement A/B testing scenarios, fetching the variations in configuration and reporting back metrics to track conversion rates of the experiments.
|{kib-repo}blob/{branch}/x-pack/plugins/cloud_integrations/cloud_full_story/README.md[cloudFullStory]
|Integrates with FullStory in order to provide better product analytics, so we can understand how our users make use of Kibana. This plugin should only run on Elastic Cloud.
|{kib-repo}blob/{branch}/x-pack/plugins/cloud_integrations/cloud_links/README.md[cloudLinks]
|Adds all the links to the Elastic Cloud console.
|{kib-repo}blob/{branch}/x-pack/plugins/cloud_security_posture/README.md[cloudSecurityPosture]
|Cloud Posture automates the identification and remediation of risks across cloud infrastructures
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4182,6 +4182,10 @@ describe('SavedObjectsRepository', () => {
type: 'foo',
id: '1',
},
hasNoReference: {
type: 'bar',
id: '1',
},
};

it(`passes mappings, registry, and search options to getSearchDsl`, async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,8 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
rootSearchFields,
hasReference,
hasReferenceOperator,
hasNoReference,
hasNoReferenceOperator,
page = FIND_DEFAULT_PAGE,
perPage = FIND_DEFAULT_PER_PAGE,
pit,
Expand Down Expand Up @@ -1235,6 +1237,8 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
typeToNamespacesMap,
hasReference,
hasReferenceOperator,
hasNoReference,
hasNoReferenceOperator,
kueryNode,
}),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,17 +195,18 @@ describe('#getQueryParams', () => {
});
});

describe('reference filter clause', () => {
describe('`hasReference` parameter', () => {
it('does not call `getReferencesFilter` when `hasReference` is not specified', () => {
getQueryParams({
registry,
hasReference: undefined,
});

expect(getReferencesFilterMock).not.toHaveBeenCalled();
describe('reference/noreference filter clause', () => {
it('does not call `getReferencesFilter` when neither `hasReference` nor `hasNoReference` are specified', () => {
getQueryParams({
registry,
hasReference: undefined,
hasNoReference: undefined,
});

expect(getReferencesFilterMock).not.toHaveBeenCalled();
});

describe('`hasReference` parameter', () => {
it('calls `getReferencesFilter` with the correct parameters', () => {
const hasReference = { id: 'foo', type: 'bar' };
getQueryParams({
Expand Down Expand Up @@ -235,6 +236,38 @@ describe('#getQueryParams', () => {
expect(filters.some((filter) => filter.references_filter === true)).toBeDefined();
});
});

describe('`hasNoReference` parameter', () => {
it('calls `getReferencesFilter` with the correct parameters', () => {
const hasNoReference = { id: 'noFoo', type: 'bar' };
getQueryParams({
registry,
hasNoReference,
hasNoReferenceOperator: 'AND',
});

expect(getReferencesFilterMock).toHaveBeenCalledTimes(1);
expect(getReferencesFilterMock).toHaveBeenCalledWith({
must: false,
references: [hasNoReference],
operator: 'AND',
});
});

it('includes the return of `getReferencesFilter` in the `filter` clause', () => {
getReferencesFilterMock.mockReturnValue({ references_filter: true });

const hasNoReference = { id: 'noFoo', type: 'bar' };
const result = getQueryParams({
registry,
hasNoReference,
hasReferenceOperator: 'AND',
});

const filters: any[] = result.query.bool.filter;
expect(filters.some((filter) => filter.references_filter === true)).toBeDefined();
});
});
});

describe('type filter clauses', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import * as esKuery from '@kbn/es-query';
import type { SavedObjectTypeIdTuple } from '@kbn/core-saved-objects-common';

type KueryNode = any;

Expand Down Expand Up @@ -123,11 +124,6 @@ function getClauseForType(
};
}

export interface HasReferenceQueryParams {
type: string;
id: string;
}

export type SearchOperator = 'AND' | 'OR';

interface QueryParams {
Expand All @@ -139,15 +135,24 @@ interface QueryParams {
defaultSearchOperator?: SearchOperator;
searchFields?: string[];
rootSearchFields?: string[];
hasReference?: HasReferenceQueryParams | HasReferenceQueryParams[];
hasReference?: SavedObjectTypeIdTuple | SavedObjectTypeIdTuple[];
hasReferenceOperator?: SearchOperator;
hasNoReference?: SavedObjectTypeIdTuple | SavedObjectTypeIdTuple[];
hasNoReferenceOperator?: SearchOperator;
kueryNode?: KueryNode;
}

// A de-duplicated set of namespaces makes for a more efficient query.
const uniqNamespaces = (namespacesToNormalize?: string[]) =>
namespacesToNormalize ? Array.from(new Set(namespacesToNormalize)) : undefined;

const toArray = (val: unknown) => {
if (typeof val === 'undefined') {
return val;
}
return !Array.isArray(val) ? [val] : val;
};

/**
* Get the "query" related keys for the search body
*/
Expand All @@ -162,16 +167,17 @@ export function getQueryParams({
defaultSearchOperator,
hasReference,
hasReferenceOperator,
hasNoReference,
hasNoReferenceOperator,
kueryNode,
}: QueryParams) {
const types = getTypes(
registry,
typeToNamespacesMap ? Array.from(typeToNamespacesMap.keys()) : type
);

if (hasReference && !Array.isArray(hasReference)) {
hasReference = [hasReference];
}
hasReference = toArray(hasReference);
hasNoReference = toArray(hasNoReference);

const bool: any = {
filter: [
Expand All @@ -184,6 +190,15 @@ export function getQueryParams({
}),
]
: []),
...(hasNoReference?.length
? [
getReferencesFilter({
references: hasNoReference,
operator: hasNoReferenceOperator,
must: false,
}),
]
: []),
{
bool: {
should: types.map((shouldType) => {
Expand Down
Loading

0 comments on commit 10a2cc9

Please sign in to comment.