forked from opensearch-project/OpenSearch-Dashboards
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable Cypress tests to detect features of the OSD instance they are …
…running against Also: * Turn on test isolation when security is disabled Signed-off-by: Miki <[email protected]>
- Loading branch information
Showing
6 changed files
with
225 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/* eslint-disable no-console */ | ||
|
||
import { setTimeout } from 'timers/promises'; | ||
import fetch from 'node-fetch'; | ||
|
||
const CONNECTION_TIMEOUT = 15000; | ||
const CONNECTION_TIMEOUT_TOTAL = 60000; | ||
const CONNECTION_RETRY_INTERVAL = 15000; | ||
|
||
/** | ||
* Check if the security plugin is enabled on Dashboards and set env.SECURITY_ENABLED accordingly. | ||
* Turn on test isolation when security is disabled, and off when security is enabled so we don't | ||
* have to log in for each test. | ||
*/ | ||
const checkSecurity = async (config: Cypress.PluginConfigOptions) => { | ||
const startTime = Date.now(); | ||
do { | ||
// Not catching to allow Cypress to fail | ||
const resp = await fetch(config.baseUrl, { timeout: CONNECTION_TIMEOUT }); | ||
|
||
if (resp.status === 200) { | ||
console.log('OpenSearch Dashboards is configured without security.'); | ||
config.env.SECURITY_ENABLED = false; | ||
|
||
console.log('Test isolation is turned on.'); | ||
config.testIsolation = true; | ||
|
||
return; | ||
} | ||
|
||
if (resp.status === 401) { | ||
console.log('OpenSearch Dashboards is configured with security.'); | ||
config.env.SECURITY_ENABLED = true; | ||
|
||
console.log('Test isolation is turned off.'); | ||
config.testIsolation = false; | ||
|
||
return; | ||
} | ||
|
||
console.log('Waiting for OpenSearch Dashboards to be ready...'); | ||
await setTimeout(CONNECTION_RETRY_INTERVAL); | ||
} while (Date.now() - startTime < CONNECTION_TIMEOUT_TOTAL); | ||
|
||
throw new Error( | ||
'Security plugin status check failed: OpenSearch Dashboards unreachable or misconfigured.' | ||
); | ||
}; | ||
|
||
const checkPlugins = async (config: Cypress.PluginConfigOptions) => { | ||
const startTime = Date.now(); | ||
const apiStatusUrl = new URL('/api/status', config.baseUrl); | ||
const headers: fetch.HeadersInit = {}; | ||
|
||
if (config.env.SECURITY_ENABLED) { | ||
headers.Authorization = | ||
'Basic ' + Buffer.from(config.env.username + ':' + config.env.password).toString('base64'); | ||
} | ||
|
||
do { | ||
// Not catching to allow Cypress to fail | ||
const resp = await fetch(apiStatusUrl, { timeout: CONNECTION_TIMEOUT, headers }); | ||
if (resp.status === 200) { | ||
const json = await resp.json(); | ||
|
||
if (!Array.isArray(json?.status?.statuses)) | ||
throw new Error( | ||
'Invalid OpenSearch Dashboards status response: OpenSearch Dashboards unreachable or misconfigured.' | ||
); | ||
|
||
json.status.statuses.forEach?.(({ id }: { id: string }) => { | ||
if (!id.startsWith('plugin:')) return; | ||
const envName = id | ||
.replace(/^plugin:(.+?)(Dashboards)*@.*$/, '$1') | ||
.replace(/([A-Z])/g, '_$1') | ||
.toUpperCase(); | ||
config.env[`${envName}_ENABLED`] = true; | ||
}); | ||
|
||
return; | ||
} | ||
|
||
console.log('Waiting for OpenSearch Dashboards to be ready...'); | ||
await setTimeout(CONNECTION_RETRY_INTERVAL); | ||
} while (Date.now() - startTime < CONNECTION_TIMEOUT_TOTAL); | ||
|
||
throw new Error( | ||
'Plugins status check failed: OpenSearch Dashboards unreachable or misconfigured.' | ||
); | ||
}; | ||
|
||
export const setupDynamicConfig = async (config: Cypress.PluginConfigOptions) => { | ||
await checkSecurity(config); | ||
await checkPlugins(config); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/** | ||
* Helper function to describe conditional test suites, based on features enabled in OSD | ||
* | ||
* @param {string} featureName - The name of feature to be checked. | ||
* Based on the status of the feature, the suite will be described. | ||
* | ||
* @returns {Mocha.SuiteFunction & { describe: Mocha.SuiteFunction, not: Mocha.SuiteFunction & { describe: Mocha.SuiteFunction }}} | ||
*/ | ||
|
||
const ifEnabled = (featureName) => { | ||
/** | ||
* Describes a "suite" that should be executed if the feature is enabled. | ||
* @type {Mocha.SuiteFunction & { not: Mocha.SuiteFunction & {describe: Mocha.SuiteFunction}}} | ||
*/ | ||
const describer = (name, fn, options = {}) => { | ||
const { skip = false, only = false, condition = true, not = false } = options; | ||
|
||
if ( | ||
skip || | ||
!condition || | ||
(!not && !Cypress.env(`${featureName}_ENABLED`)) || | ||
(not && Cypress.env(`${featureName}_ENABLED`)) | ||
) { | ||
describe.skip(name, fn); | ||
} else if (only) { | ||
// eslint-disable-next-line mocha/no-exclusive-tests | ||
describe.only(name, fn); | ||
} else { | ||
describe(name, fn); | ||
} | ||
}; | ||
|
||
/** | ||
* Describes a "suite" that should be executed if the feature is disabled. | ||
* @type {Mocha.SuiteFunction & {describe: Mocha.SuiteFunction}} | ||
*/ | ||
describer.not = (name, fn, options = {}) => { | ||
describer(name, fn, { ...options, not: true }); | ||
}; | ||
|
||
/** | ||
* Describes a "suite" that should not be executed. | ||
* @type {Mocha.PendingSuiteFunction} | ||
*/ | ||
describer.skip = describer.not.skip = (name, fn) => { | ||
describer(name, fn, { skip: true }); | ||
}; | ||
|
||
/** | ||
* Describes a "suite" that should be executed exclusively and only if the feature is enabled. | ||
* @type {Mocha.ExclusiveSuiteFunction} | ||
*/ | ||
describer.only = (name, fn) => { | ||
describer(name, fn, { only: true }); | ||
}; | ||
|
||
/** | ||
* Describes a "suite" that should be executed exclusively and only if the feature is disabled. | ||
* @type {Mocha.ExclusiveSuiteFunction} | ||
*/ | ||
describer.not.only = (name, fn) => { | ||
describer(name, fn, { not: true, only: true }); | ||
}; | ||
|
||
// Ease-of-use aliases | ||
|
||
/** | ||
* Describes a "suite" that should be executed if the feature is enabled. | ||
* @type {Mocha.SuiteFunction} | ||
*/ | ||
describer.describe = describer; | ||
|
||
/** | ||
* Describes a "suite" that should be executed if the feature is disabled. | ||
* @type {Mocha.SuiteFunction} | ||
*/ | ||
describer.not.describe = describer.not; | ||
|
||
/** | ||
* Describes a "suite" that should not be executed. | ||
* @type {Mocha.PendingSuiteFunction} | ||
*/ | ||
describer.describe.skip = describer.not.describe.skip = describer.skip; | ||
|
||
/** | ||
* Describes a "suite" that should be executed exclusively and only if the feature is enabled. | ||
* @type {Mocha.ExclusiveSuiteFunction} | ||
*/ | ||
describer.only.describe = describer.only; | ||
|
||
/** | ||
* Describes a "suite" that should be executed exclusively and only if the feature is disabled. | ||
* @type {Mocha.ExclusiveSuiteFunction} | ||
*/ | ||
describer.not.describe.only = describer.not.only; | ||
|
||
return describer; | ||
}; | ||
|
||
global.ifEnabled = ifEnabled; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters