Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change saved object bulkUpdate to work across multiple namespaces #75478

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fa6ae1c
Add `namespaceStringToId` and `namespaceIdToString` methods to core
jportner Aug 19, 2020
341052a
Change `bulkUpdate` method to allow per-object namespaces
jportner Aug 20, 2020
6c78cd4
Merge branch 'master' into issue-75449-bulk-update-across-spaces
elasticmachine Aug 26, 2020
9d849b6
Merge branch 'master' into issue-75449-bulk-update-across-spaces
jportner Aug 31, 2020
2096fc3
Add comment per review feedback
jportner Aug 31, 2020
440d987
Tweak secure saved objects client wrapper authZ checks
jportner Aug 31, 2020
0b2f62c
Don't expose core namespace conversion methods in the public contract
jportner Aug 31, 2020
1228d61
Remove @public tag from jsdocs that are no longer exported from core
jportner Sep 1, 2020
46bc77d
Normalize namespace strings for saved object CRUD operations
jportner Sep 1, 2020
9dd4d5b
Merge branch 'master' into issue-75449-bulk-update-across-spaces
jportner Sep 2, 2020
ea2235f
Change `bulkUpdate` in ESO plugin to use object namespace
jportner Sep 2, 2020
17985c3
Updated non-dev usages of node-forge
jportner Sep 3, 2020
def73c7
Merge branch 'master' of github.com:elastic/kibana
jportner Sep 4, 2020
978ccf1
Merge branch 'master' into issue-75449-bulk-update-across-spaces
jportner Sep 4, 2020
ba8c72d
Revert "Don't expose core namespace conversion methods in the public …
jportner Sep 4, 2020
2c36a31
Wrap namespace utility methods in `SavedObjectsUtils` class
jportner Sep 4, 2020
714a14e
Change ESO plugin to use SavedObjectsUtils for namespaces
jportner Sep 4, 2020
c2a207a
Remove unnecessary comment
jportner Sep 4, 2020
0a36aa5
Merge branch 'master' into issue-75449-bulk-update-across-spaces
elasticmachine Sep 7, 2020
0c97bf3
Merge branch 'master' into issue-75449-bulk-update-across-spaces
elasticmachine Sep 9, 2020
65acf6d
Merge branch 'master' into issue-75449-bulk-update-across-spaces
jportner Sep 9, 2020
cf0a0a0
Address PR review feedback
jportner Sep 9, 2020
71bf105
Merge branch 'master' into issue-75449-bulk-update-across-spaces
jportner Sep 10, 2020
70793b0
Address more PR review feedback
jportner Sep 10, 2020
f345891
Update JSdocs
jportner Sep 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/development/core/server/kibana-plugin-core-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| Variable | Description |
| --- | --- |
| [kibanaResponseFactory](./kibana-plugin-core-server.kibanaresponsefactory.md) | Set of helpers used to create <code>KibanaResponse</code> to form HTTP response on an incoming request. Should be returned as a result of [RequestHandler](./kibana-plugin-core-server.requesthandler.md) execution. |
| [namespaceIdToString](./kibana-plugin-core-server.namespaceidtostring.md) | Converts a given saved object namespace ID to its string representation. All namespace IDs have an identical string representation, with the exception of the <code>undefined</code> namespace ID (which has a namespace string of <code>'default'</code>). |
| [namespaceStringToId](./kibana-plugin-core-server.namespacestringtoid.md) | Converts a given saved object namespace string to its ID representation. All namespace strings have an identical ID representation, with the exception of the <code>'default'</code> namespace string (which has a namespace ID of <code>undefined</code>). |
| [ServiceStatusLevels](./kibana-plugin-core-server.servicestatuslevels.md) | The current "level" of availability of a service. |
| [validBodyOutput](./kibana-plugin-core-server.validbodyoutput.md) | The set of valid body.output |

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [namespaceIdToString](./kibana-plugin-core-server.namespaceidtostring.md)

## namespaceIdToString variable

Converts a given saved object namespace ID to its string representation. All namespace IDs have an identical string representation, with the exception of the `undefined` namespace ID (which has a namespace string of `'default'`<!-- -->).

<b>Signature:</b>

```typescript
namespaceIdToString: (namespace?: string | undefined) => string
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [namespaceStringToId](./kibana-plugin-core-server.namespacestringtoid.md)

## namespaceStringToId variable

Converts a given saved object namespace string to its ID representation. All namespace strings have an identical ID representation, with the exception of the `'default'` namespace string (which has a namespace ID of `undefined`<!-- -->).

<b>Signature:</b>

```typescript
namespaceStringToId: (namespace: string) => string | undefined
```
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ export interface SavedObjectsBulkUpdateObject<T = unknown> extends Pick<SavedObj
| --- | --- | --- |
| [attributes](./kibana-plugin-core-server.savedobjectsbulkupdateobject.attributes.md) | <code>Partial&lt;T&gt;</code> | The data for a Saved Object is stored as an object in the <code>attributes</code> property. |
| [id](./kibana-plugin-core-server.savedobjectsbulkupdateobject.id.md) | <code>string</code> | The ID of this Saved Object, guaranteed to be unique for all objects of the same <code>type</code> |
| [namespace](./kibana-plugin-core-server.savedobjectsbulkupdateobject.namespace.md) | <code>string</code> | Optional namespace string to use for this document. If this is defined, it will supersede the namespace ID that is in [SavedObjectsUpdateOptions](./kibana-plugin-core-server.savedobjectsupdateoptions.md)<!-- -->.<!-- -->Note: the default namespace's string representation is <code>'default'</code>, and its ID representation is <code>undefined</code>. |
| [type](./kibana-plugin-core-server.savedobjectsbulkupdateobject.type.md) | <code>string</code> | The type of this Saved Object. Each plugin can define it's own custom Saved Object types. |

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [SavedObjectsBulkUpdateObject](./kibana-plugin-core-server.savedobjectsbulkupdateobject.md) &gt; [namespace](./kibana-plugin-core-server.savedobjectsbulkupdateobject.namespace.md)

## SavedObjectsBulkUpdateObject.namespace property

Optional namespace string to use for this document. If this is defined, it will supersede the namespace ID that is in [SavedObjectsUpdateOptions](./kibana-plugin-core-server.savedobjectsupdateoptions.md)<!-- -->.

Note: the default namespace's string representation is `'default'`<!-- -->, and its ID representation is `undefined`<!-- -->.

<b>Signature:</b>

```typescript
namespace?: string;
```
2 changes: 2 additions & 0 deletions src/core/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ export {
exportSavedObjectsToStream,
importSavedObjectsFromStream,
resolveSavedObjectsImportErrors,
namespaceIdToString,
namespaceStringToId,
} from './saved_objects';

export {
Expand Down
1 change: 1 addition & 0 deletions src/core/server/saved_objects/routes/bulk_update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const registerBulkUpdateRoute = (router: IRouter) => {
})
)
),
namespace: schema.maybe(schema.string({ minLength: 1 })),
})
),
},
Expand Down
2 changes: 2 additions & 0 deletions src/core/server/saved_objects/service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export {
SavedObjectsErrorHelpers,
SavedObjectsClientFactory,
SavedObjectsClientFactoryProvider,
namespaceIdToString,
namespaceStringToId,
} from './lib';

export * from './saved_objects_client';
2 changes: 2 additions & 0 deletions src/core/server/saved_objects/service/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@ export {
} from './scoped_client_provider';

export { SavedObjectsErrorHelpers } from './errors';

export { namespaceIdToString, namespaceStringToId } from './namespace';
53 changes: 53 additions & 0 deletions src/core/server/saved_objects/service/lib/namespace.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { namespaceIdToString, namespaceStringToId } from './namespace';

describe('#namespaceIdToString', () => {
it('converts `undefined` to default namespace string', () => {
expect(namespaceIdToString(undefined)).toEqual('default');
});

it('leaves other namespace IDs as-is', () => {
expect(namespaceIdToString('foo')).toEqual('foo');
});

it('throws an error when a namespace ID is an empty string', () => {
expect(() => namespaceIdToString('')).toThrowError('namespace cannot be an empty string');
});
});

describe('#namespaceStringToId', () => {
it('converts default namespace string to `undefined`', () => {
expect(namespaceStringToId('default')).toBeUndefined();
});

it('leaves other namespace strings as-is', () => {
expect(namespaceStringToId('foo')).toEqual('foo');
});

it('throws an error when a namespace string is falsy', () => {
const test = (arg: any) =>
expect(() => namespaceStringToId(arg)).toThrowError('namespace must be a non-empty string');

test(undefined);
test(null);
test('');
});
});
50 changes: 50 additions & 0 deletions src/core/server/saved_objects/service/lib/namespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
jportner marked this conversation as resolved.
Show resolved Hide resolved
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export const DEFAULT_NAMESPACE_STRING = 'default';

/**
* @public
* Converts a given saved object namespace ID to its string representation. All namespace IDs have an identical string representation, with
* the exception of the `undefined` namespace ID (which has a namespace string of `'default'`).
*
* @param namespace The namespace ID, which must be either a non-empty string or `undefined`.
*/
export const namespaceIdToString = (namespace?: string) => {
if (namespace === '') {
throw new TypeError('namespace cannot be an empty string');
}

return namespace ?? DEFAULT_NAMESPACE_STRING;
};

/**
* @public
* Converts a given saved object namespace string to its ID representation. All namespace strings have an identical ID representation, with
* the exception of the `'default'` namespace string (which has a namespace ID of `undefined`).
*
* @param namespace The namespace string, which must be non-empty.
*/
export const namespaceStringToId = (namespace: string) => {
if (!namespace) {
throw new TypeError('namespace must be a non-empty string');
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a new error case that may be encountered when using the saved objects client now. That said, it should never happen organically, so I'm not sure we need to be concerned about it. Thoughts?

If we remove the error check here:

  • Single-namespace object types would be treated as if they are in the default space
  • Multi-namespace object types would be treated as if they are in the '' space

I don't like the difference in behavior, so I'm in favor of leaving the error check in.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm +1 to keeping the error check here


return namespace !== DEFAULT_NAMESPACE_STRING ? namespace : undefined;
};
Loading