Skip to content

Commit

Permalink
[7.4] [ftr/savedObjects] add simple saved object api client to… (#45941)
Browse files Browse the repository at this point in the history
* [ftr/savedObjects] add simple saved object api client to ftr services

* fix typo

* use consistent spacing

* fix types and TS-ify the rest of kibanaServer service

* expose server urls with better API

* tweak status api response types

* fix http body param name

* second arg to axios post is the post data

* use standardized error handling behavior

* Revert "use standardized error handling behavior"

This reverts commit 7e9a7f8.

* revert unnecessary changes
  • Loading branch information
Spencer authored Sep 18, 2019
1 parent 3c92f98 commit d5af3d5
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 13 deletions.
11 changes: 8 additions & 3 deletions packages/kbn-test/types/ftr.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import { ToolingLog } from '@kbn/dev-utils';
import { Config, Lifecycle } from '../src/functional_test_runner/lib';

export { Lifecycle, Config };

interface AsyncInstance<T> {
/**
* Services that are initialized async are not ready before the tests execute, so you might need
Expand All @@ -36,14 +38,17 @@ interface AsyncInstance<T> {
*/
type MaybeAsyncInstance<T> = T extends Promise<infer X> ? AsyncInstance<X> & X : T;

/**
* Covert a Provider type to the instance type it provides
*/
export type ProvidedType<T extends (...args: any[]) => any> = MaybeAsyncInstance<ReturnType<T>>;

/**
* Convert a map of providers to a map of the instance types they provide, also converting
* promise types into the async instances that other providers will receive.
*/
type ProvidedTypeMap<T extends {}> = {
[K in keyof T]: T[K] extends (...args: any[]) => any
? MaybeAsyncInstance<ReturnType<T[K]>>
: unknown;
[K in keyof T]: T[K] extends (...args: any[]) => any ? ProvidedType<T[K]> : unknown;
};

export interface GenericFtrProviderContext<
Expand Down
1 change: 0 additions & 1 deletion test/common/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import { EsProvider } from './es';
import { EsArchiverProvider } from './es_archiver';
// @ts-ignore not TS yet
import { KibanaServerProvider } from './kibana_server';
import { RetryProvider } from './retry';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@
*/

export { KibanaServerProvider } from './kibana_server';
// @ts-ignore
export { extendEsArchiver } from './extend_es_archiver';
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,37 @@
* under the License.
*/

import { format as formatUrl } from 'url';
import Url from 'url';

import { FtrProviderContext } from '../../ftr_provider_context';
// @ts-ignore not ts yet
import { KibanaServerStatus } from './status';
// @ts-ignore not ts yet
import { KibanaServerUiSettings } from './ui_settings';
// @ts-ignore not ts yet
import { KibanaServerVersion } from './version';
import { KibanaServerSavedObjects } from './saved_objects';

export function KibanaServerProvider({ getService }) {
export function KibanaServerProvider({ getService }: FtrProviderContext) {
const log = getService('log');
const config = getService('config');
const lifecycle = getService('lifecycle');

return new class KibanaServer {
constructor() {
const url = formatUrl(config.get('servers.kibana'));
this.status = new KibanaServerStatus(url);
this.version = new KibanaServerVersion(this.status);
this.uiSettings = new KibanaServerUiSettings(url, log, config.get('uiSettings.defaults'), lifecycle);
const url = Url.format(config.get('servers.kibana'));

return new (class KibanaServer {
public readonly status = new KibanaServerStatus(url);
public readonly version = new KibanaServerVersion(this.status);
public readonly savedObjects = new KibanaServerSavedObjects(url, log);
public readonly uiSettings = new KibanaServerUiSettings(
url,
log,
config.get('uiSettings.defaults'),
lifecycle
);

public resolveUrl(path = '/') {
return Url.resolve(url, path);
}
};
})();
}
153 changes: 153 additions & 0 deletions test/common/services/kibana_server/saved_objects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* 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 Url from 'url';

import Axios, { AxiosRequestConfig } from 'axios';
import { ToolingLog } from '@kbn/dev-utils';

const joinPath = (...components: Array<string | undefined>) =>
`/${components
.filter((s): s is string => !!s)
.map(c => encodeURIComponent(c))
.join('/')}`;

type MigrationVersion = Record<string, string>;

interface Reference {
id: string;
name: string;
type: string;
}

interface SavedObjectResponse<Attributes extends Record<string, any>> {
attributes: Attributes;
id: string;
migrationVersion?: MigrationVersion;
references: Reference[];
type: string;
updated_at?: string;
version?: string;
}

interface GetOptions {
type: string;
id: string;
}

interface IndexOptions<Attributes> {
type: string;
attributes: Attributes;
id?: string;
overwrite?: boolean;
migrationVersion?: MigrationVersion;
references?: Reference[];
}

interface UpdateOptions<Attributes> extends IndexOptions<Attributes> {
id: string;
}

export class KibanaServerSavedObjects {
private readonly x = Axios.create({
baseURL: Url.resolve(this.url, '/api/saved_objects/'),
headers: {
'kbn-xsrf': 'KibanaServerSavedObjects',
},
});

constructor(private readonly url: string, private readonly log: ToolingLog) {}

/**
* Get an object
*/
public async get<Attributes extends Record<string, any>>(options: GetOptions) {
this.log.debug('Gettings saved object: %j', options);

return await this.request<SavedObjectResponse<Attributes>>('get saved object', {
url: joinPath(options.type, options.id),
method: 'GET',
});
}

/**
* Create a saved object
*/
public async create<Attributes extends Record<string, any>>(options: IndexOptions<Attributes>) {
this.log.debug('Creating saved object: %j', options);

return await this.request<SavedObjectResponse<Attributes>>('update saved object', {
url: joinPath(options.type, options.id),
params: {
overwrite: options.overwrite,
},
method: 'POST',
data: {
attributes: options.attributes,
migrationVersion: options.migrationVersion,
references: options.references,
},
});
}

/**
* Update a saved object
*/
public async update<Attributes extends Record<string, any>>(options: UpdateOptions<Attributes>) {
this.log.debug('Updating saved object: %j', options);

return await this.request<SavedObjectResponse<Attributes>>('update saved object', {
url: joinPath(options.type, options.id),
params: {
overwrite: options.overwrite,
},
method: 'PUT',
data: {
attributes: options.attributes,
migrationVersion: options.migrationVersion,
references: options.references,
},
});
}

/**
* Delete an object
*/
public async delete(options: GetOptions) {
this.log.debug('Deleting saved object %s/%s', options);

return await this.request('delete saved object', {
url: joinPath(options.type, options.id),
method: 'DELETE',
});
}

private async request<T>(desc: string, options: AxiosRequestConfig) {
try {
const resp = await this.x.request<T>(options);
return resp.data;
} catch (error) {
if (error.response) {
throw new Error(`Failed to ${desc}:\n${JSON.stringify(error.response.data, null, 2)}`);
}

throw error;
}
}
}

0 comments on commit d5af3d5

Please sign in to comment.