Skip to content

Commit

Permalink
[7.x] [ci] run server integration tests (#81698) (#82530)
Browse files Browse the repository at this point in the history
Co-authored-by: spalger <[email protected]>
Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
3 people authored Nov 4, 2020
1 parent d190eda commit 279fbe1
Show file tree
Hide file tree
Showing 19 changed files with 132 additions and 89 deletions.
2 changes: 1 addition & 1 deletion packages/kbn-dev-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export {
KBN_P12_PATH,
KBN_P12_PASSWORD,
} from './certs';
export { KbnClient } from './kbn_client';
export * from './kbn_client';
export * from './run';
export * from './axios';
export * from './stdio';
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-dev-utils/src/kbn_client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@
* under the License.
*/

export { KbnClient } from './kbn_client';
export * from './kbn_client';
export { uriencode } from './kbn_client_requester';
54 changes: 36 additions & 18 deletions packages/kbn-dev-utils/src/kbn_client/kbn_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,55 @@
*/

import { ToolingLog } from '../tooling_log';
import { KibanaConfig, KbnClientRequester, ReqOptions } from './kbn_client_requester';
import { KbnClientRequester, ReqOptions } from './kbn_client_requester';
import { KbnClientStatus } from './kbn_client_status';
import { KbnClientPlugins } from './kbn_client_plugins';
import { KbnClientVersion } from './kbn_client_version';
import { KbnClientSavedObjects } from './kbn_client_saved_objects';
import { KbnClientUiSettings, UiSettingValues } from './kbn_client_ui_settings';

export interface KbnClientOptions {
url: string;
certificateAuthorities?: Buffer[];
log: ToolingLog;
uiSettingDefaults?: UiSettingValues;
}

export class KbnClient {
private readonly requester = new KbnClientRequester(this.log, this.kibanaConfig);
readonly status = new KbnClientStatus(this.requester);
readonly plugins = new KbnClientPlugins(this.status);
readonly version = new KbnClientVersion(this.status);
readonly savedObjects = new KbnClientSavedObjects(this.log, this.requester);
readonly uiSettings = new KbnClientUiSettings(this.log, this.requester, this.uiSettingDefaults);
readonly status: KbnClientStatus;
readonly plugins: KbnClientPlugins;
readonly version: KbnClientVersion;
readonly savedObjects: KbnClientSavedObjects;
readonly uiSettings: KbnClientUiSettings;

private readonly requester: KbnClientRequester;
private readonly log: ToolingLog;
private readonly uiSettingDefaults?: UiSettingValues;

/**
* Basic Kibana server client that implements common behaviors for talking
* to the Kibana server from dev tooling.
*
* @param log ToolingLog
* @param kibanaUrls Array of kibana server urls to send requests to
* @param uiSettingDefaults Map of uiSetting values that will be merged with all uiSetting resets
*/
constructor(
private readonly log: ToolingLog,
private readonly kibanaConfig: KibanaConfig,
private readonly uiSettingDefaults?: UiSettingValues
) {
if (!kibanaConfig.url) {
throw new Error('missing Kibana urls');
constructor(options: KbnClientOptions) {
if (!options.url) {
throw new Error('missing Kibana url');
}
if (!options.log) {
throw new Error('missing ToolingLog');
}

this.log = options.log;
this.uiSettingDefaults = options.uiSettingDefaults;

this.requester = new KbnClientRequester(this.log, {
url: options.url,
certificateAuthorities: options.certificateAuthorities,
});
this.status = new KbnClientStatus(this.requester);
this.plugins = new KbnClientPlugins(this.status);
this.version = new KbnClientVersion(this.status);
this.savedObjects = new KbnClientSavedObjects(this.log, this.requester);
this.uiSettings = new KbnClientUiSettings(this.log, this.requester, this.uiSettingDefaults);
}

/**
Expand Down
24 changes: 10 additions & 14 deletions packages/kbn-dev-utils/src/kbn_client/kbn_client_requester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,31 +69,27 @@ const delay = (ms: number) =>
setTimeout(resolve, ms);
});

export interface KibanaConfig {
interface Options {
url: string;
ssl?: {
enabled: boolean;
key: string;
certificate: string;
certificateAuthorities: string;
};
certificateAuthorities?: Buffer[];
}

export class KbnClientRequester {
private readonly url: string;
private readonly httpsAgent: Https.Agent | null;
constructor(private readonly log: ToolingLog, private readonly kibanaConfig: KibanaConfig) {

constructor(private readonly log: ToolingLog, options: Options) {
this.url = options.url;
this.httpsAgent =
kibanaConfig.ssl && kibanaConfig.ssl.enabled
Url.parse(options.url).protocol === 'https:'
? new Https.Agent({
cert: kibanaConfig.ssl.certificate,
key: kibanaConfig.ssl.key,
ca: kibanaConfig.ssl.certificateAuthorities,
ca: options.certificateAuthorities,
})
: null;
}

private pickUrl() {
return this.kibanaConfig.url;
return this.url;
}

public resolveUrl(relativeUrl: string = '/') {
Expand Down Expand Up @@ -132,7 +128,7 @@ export class KbnClientRequester {
errorMessage = `Conflict on GET (path=${options.path}, attempt=${attempt}/${maxAttempts})`;
this.log.error(errorMessage);
} else if (requestedRetries || failedToGetResponse) {
errorMessage = `[${description}] request failed (attempt=${attempt}/${maxAttempts})`;
errorMessage = `[${description}] request failed (attempt=${attempt}/${maxAttempts}): ${error.message}`;
this.log.error(errorMessage);
} else {
throw error;
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-es-archiver/src/es_archiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class EsArchiver {
this.client = client;
this.dataDir = dataDir;
this.log = log;
this.kbnClient = new KbnClient(log, { url: kibanaUrl });
this.kbnClient = new KbnClient({ log, url: kibanaUrl });
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,7 @@ const urlPartsSchema = () =>
password: Joi.string(),
pathname: Joi.string().regex(/^\//, 'start with a /'),
hash: Joi.string().regex(/^\//, 'start with a /'),
ssl: Joi.object()
.keys({
enabled: Joi.boolean().default(false),
certificate: Joi.string().optional(),
certificateAuthorities: Joi.string().optional(),
key: Joi.string().optional(),
})
.default(),
certificateAuthorities: Joi.array().items(Joi.binary()).optional(),
})
.default();

Expand Down
8 changes: 6 additions & 2 deletions test/common/services/kibana_server/kibana_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@ export function KibanaServerProvider({ getService }: FtrProviderContext) {
const config = getService('config');
const lifecycle = getService('lifecycle');
const url = Url.format(config.get('servers.kibana'));
const ssl = config.get('servers.kibana').ssl;
const defaults = config.get('uiSettings.defaults');
const kbn = new KbnClient(log, { url, ssl }, defaults);
const kbn = new KbnClient({
log,
url,
certificateAuthorities: config.get('servers.kibana.certificateAuthorities'),
uiSettingDefaults: defaults,
});

if (defaults) {
lifecycle.beforeTests.add(async () => {
Expand Down
5 changes: 5 additions & 0 deletions test/scripts/server_integration.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash

source test/scripts/jenkins_test_setup_oss.sh

yarn run grunt run:serverIntegrationTests
4 changes: 3 additions & 1 deletion test/server_integration/http/ssl/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ import { createKibanaSupertestProvider } from '../../services';

export default async function ({ readConfigFile }) {
const httpConfig = await readConfigFile(require.resolve('../../config'));
const certificateAuthorities = [readFileSync(CA_CERT_PATH)];

return {
testFiles: [require.resolve('./')],
services: {
...httpConfig.get('services'),
supertest: createKibanaSupertestProvider({
certificateAuthorities: [readFileSync(CA_CERT_PATH)],
certificateAuthorities,
}),
},
servers: {
...httpConfig.get('servers'),
kibana: {
...httpConfig.get('servers.kibana'),
protocol: 'https',
certificateAuthorities,
},
},
junit: {
Expand Down
20 changes: 11 additions & 9 deletions test/server_integration/http/ssl_redirect/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,30 @@
* under the License.
*/

import Url from 'url';
import { readFileSync } from 'fs';
import { CA_CERT_PATH, KBN_CERT_PATH, KBN_KEY_PATH } from '@kbn/dev-utils';

import { createKibanaSupertestProvider } from '../../services';

export default async function ({ readConfigFile }) {
const httpConfig = await readConfigFile(require.resolve('../../config'));
const certificateAuthorities = [readFileSync(CA_CERT_PATH)];

const redirectPort = httpConfig.get('servers.kibana.port') + 1;
const supertestOptions = {
...httpConfig.get('servers.kibana'),
port: redirectPort,
// test with non ssl protocol
protocol: 'http',
};
const redirectPort = httpConfig.get('servers.kibana.port') + 1234;

return {
testFiles: [require.resolve('./')],
services: {
...httpConfig.get('services'),
supertest: createKibanaSupertestProvider({
certificateAuthorities: [readFileSync(CA_CERT_PATH)],
options: supertestOptions,
certificateAuthorities,
kibanaUrl: Url.format({
...httpConfig.get('servers.kibana'),
port: redirectPort,
// test with non ssl protocol
protocol: 'http',
}),
}),
},
servers: {
Expand All @@ -48,6 +49,7 @@ export default async function ({ readConfigFile }) {
...httpConfig.get('servers.kibana'),
// start the server with https
protocol: 'https',
certificateAuthorities,
},
},
junit: {
Expand Down
2 changes: 1 addition & 1 deletion test/server_integration/http/ssl_redirect/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function ({ getService }) {

await supertest.get('/').expect('location', url).expect(302);

await supertest.get('/').redirects(1).expect('location', '/app/kibana').expect(302);
await supertest.get('/').redirects(1).expect('location', '/app/home').expect(302);
});
});
}
4 changes: 3 additions & 1 deletion test/server_integration/http/ssl_with_p12/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ import { createKibanaSupertestProvider } from '../../services';

export default async function ({ readConfigFile }) {
const httpConfig = await readConfigFile(require.resolve('../../config'));
const certificateAuthorities = [readFileSync(CA_CERT_PATH)];

return {
testFiles: [require.resolve('./')],
services: {
...httpConfig.get('services'),
supertest: createKibanaSupertestProvider({
certificateAuthorities: [readFileSync(CA_CERT_PATH)],
certificateAuthorities,
}),
},
servers: {
...httpConfig.get('servers'),
kibana: {
...httpConfig.get('servers.kibana'),
protocol: 'https',
certificateAuthorities,
},
},
junit: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ import { createKibanaSupertestProvider } from '../../services';

export default async function ({ readConfigFile }) {
const httpConfig = await readConfigFile(require.resolve('../../config'));
const certificateAuthorities = [readFileSync(CA1_CERT_PATH), readFileSync(CA2_CERT_PATH)];

return {
testFiles: [require.resolve('./')],
services: {
...httpConfig.get('services'),
supertest: createKibanaSupertestProvider({
certificateAuthorities: [readFileSync(CA1_CERT_PATH), readFileSync(CA2_CERT_PATH)],
certificateAuthorities,
}),
},
servers: {
...httpConfig.get('servers'),
kibana: {
...httpConfig.get('servers.kibana'),
protocol: 'https',
certificateAuthorities,
},
},
junit: {
Expand Down
8 changes: 4 additions & 4 deletions test/server_integration/services/supertest.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ import { format as formatUrl } from 'url';

import supertestAsPromised from 'supertest-as-promised';

export function createKibanaSupertestProvider({ certificateAuthorities, options } = {}) {
export function createKibanaSupertestProvider({ certificateAuthorities, kibanaUrl } = {}) {
return function ({ getService }) {
const config = getService('config');
const kibanaServerUrl = options ? formatUrl(options) : formatUrl(config.get('servers.kibana'));
kibanaUrl = kibanaUrl ?? formatUrl(config.get('servers.kibana'));

return certificateAuthorities
? supertestAsPromised.agent(kibanaServerUrl, { ca: certificateAuthorities })
: supertestAsPromised(kibanaServerUrl);
? supertestAsPromised.agent(kibanaUrl, { ca: certificateAuthorities })
: supertestAsPromised(kibanaUrl);
};
}

Expand Down
13 changes: 12 additions & 1 deletion vars/tasks.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,14 @@ def test() {
}

def functionalOss(Map params = [:]) {
def config = params ?: [ciGroups: true, firefox: true, accessibility: true, pluginFunctional: true, visualRegression: false]
def config = params ?: [
serverIntegration: true,
ciGroups: true,
firefox: true,
accessibility: true,
pluginFunctional: true,
visualRegression: false,
]

task {
kibanaPipeline.buildOss(6)
Expand All @@ -65,6 +72,10 @@ def functionalOss(Map params = [:]) {
if (config.visualRegression) {
task(kibanaPipeline.functionalTestProcess('oss-visualRegression', './test/scripts/jenkins_visual_regression.sh'))
}

if (config.serverIntegration) {
task(kibanaPipeline.scriptTaskDocker('serverIntegration', './test/scripts/server_integration.sh'))
}
}
}

Expand Down
Loading

0 comments on commit 279fbe1

Please sign in to comment.