Import multiple envs when importing OpenAPI3 (#4254)

* feat(import): import multiple envs when importing OpenAPI3

When the OpenApi file to import contains multiple servers, import each one as an environment.

Closes #3627

* feat(import): import multiple envs when importing OpenAPI3

When the OpenApi file to import contains multiple servers, import each one as an environment.

Closes #3627

* fix lint and tests & rebase with latest develop

Co-authored-by: SIX Douglas <douglas.six@ext.adeo.com>
Co-authored-by: Filipe Freire <livrofubia@gmail.com>
This commit is contained in:
SIX Douglas 2022-12-05 12:31:43 +01:00 committed by GitHub
parent cfc1ac09aa
commit f39d47b5bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 102 additions and 57 deletions

1
.gitignore vendored
View File

@ -22,6 +22,7 @@ node_modules/
.yarn-integrity
.env
.idea
*.iml
.DS_Store
*test-plugins
graphql.config.json

View File

@ -21,7 +21,7 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__33ebaa67",
"_type": "environment",
"data": {
"apiKey": "apiKey",
@ -31,7 +31,7 @@
"oauth2RedirectUrl": "http://localhost/",
"scheme": "http"
},
"name": "OpenAPI env",
"name": "OpenAPI env petstore.swagger.io",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -21,7 +21,7 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__33ebaa67",
"_type": "environment",
"data": {
"apiKey": "apiKey",
@ -31,7 +31,7 @@
"oauth2RedirectUrl": "http://localhost/",
"scheme": "http"
},
"name": "OpenAPI env",
"name": "OpenAPI env petstore.swagger.io",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -21,7 +21,7 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__64c0ce7d",
"_type": "environment",
"data": {
"anotherCookieName": "anotherCookieName",
@ -42,7 +42,7 @@
"xApiKey": "xApiKey",
"xAppVersion": "xAppVersion"
},
"name": "OpenAPI env",
"name": "OpenAPI env api.server.test",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -21,14 +21,14 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__b0168b4d",
"_type": "environment",
"data": {
"base_path": "/filemanagement",
"host": "localhost:8080",
"scheme": "https"
},
"name": "OpenAPI env",
"name": "OpenAPI env localhost:8080",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -21,14 +21,14 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__9c17e047",
"_type": "environment",
"data": {
"base_path": "",
"host": "example.com",
"scheme": "http"
},
"name": "OpenAPI env",
"name": "OpenAPI env example.com",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -22,7 +22,7 @@
},
{
"parentId": "__BASE_ENVIRONMENT_ID__",
"name": "OpenAPI env",
"name": "OpenAPI env api.server.test",
"data": {
"scheme": "https",
"apiKeyHere": "apiKeyHere",
@ -35,7 +35,7 @@
"xApiKey": "xApiKey"
},
"_type": "environment",
"_id": "env___BASE_ENVIRONMENT_ID___sub"
"_id": "env___BASE_ENVIRONMENT_ID___sub__64c0ce7d"
},
{
"parentId": "__WORKSPACE_ID__",

View File

@ -21,7 +21,7 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__3d8ac28f",
"_type": "environment",
"data": {
"base_path": "/v2",
@ -31,7 +31,7 @@
"xAppId": "xAppId",
"xAppSecret": "xAppSecret"
},
"name": "OpenAPI env",
"name": "OpenAPI env petstore.swagger.io",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -21,7 +21,7 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__64c0ce7d",
"_type": "environment",
"data": {
"base_path": "/v1",
@ -31,7 +31,7 @@
"oauth2RedirectUrl": "http://localhost/",
"scheme": "https"
},
"name": "OpenAPI env",
"name": "OpenAPI env api.server.test",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -21,14 +21,14 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__64b4aec9",
"_type": "environment",
"data": {
"base_path": "",
"host": "api.insomnia.rest",
"scheme": "https"
},
"name": "OpenAPI env",
"name": "OpenAPI env api.insomnia.rest",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -20,6 +20,9 @@
"servers": [
{
"url": "http://petstore.swagger.io/v2/"
},
{
"url": "http://petstore-preprod.swagger.io/v2/"
}
],
"tags": [],

View File

@ -21,7 +21,7 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__c88af77d",
"_type": "environment",
"data": {
"apiKey": "apiKey",
@ -31,7 +31,21 @@
"oauth2RedirectUrl": "http://localhost/",
"scheme": "http"
},
"name": "OpenAPI env",
"name": "OpenAPI env petstore.swagger.io",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub__33d9f12e",
"_type": "environment",
"data": {
"apiKey": "apiKey",
"base_path": "/v2",
"host": "petstore-preprod.swagger.io",
"oauth2ClientId": "clientId",
"oauth2RedirectUrl": "http://localhost/",
"scheme": "http"
},
"name": "OpenAPI env petstore-preprod.swagger.io",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -21,14 +21,14 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__5be46d1c",
"_type": "environment",
"data": {
"base_path": "/v1",
"host": "petstore.swagger.io",
"scheme": "http"
},
"name": "OpenAPI env",
"name": "OpenAPI env petstore.swagger.io",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -21,7 +21,7 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__33ebaa67",
"_type": "environment",
"data": {
"apiKey": "apiKey",
@ -31,7 +31,7 @@
"oauth2RedirectUrl": "http://localhost/",
"scheme": "http"
},
"name": "OpenAPI env",
"name": "OpenAPI env petstore.swagger.io",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -21,14 +21,14 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__5be46d1c",
"_type": "environment",
"data": {
"base_path": "/v1",
"host": "petstore.swagger.io",
"scheme": "http"
},
"name": "OpenAPI env",
"name": "OpenAPI env petstore.swagger.io",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -21,14 +21,14 @@
"parentId": "__WORKSPACE_ID__"
},
{
"_id": "env___BASE_ENVIRONMENT_ID___sub",
"_id": "env___BASE_ENVIRONMENT_ID___sub__5be46d1c",
"_type": "environment",
"data": {
"base_path": "/v1",
"host": "petstore.swagger.io",
"scheme": "http"
},
"name": "OpenAPI env",
"name": "OpenAPI env petstore.swagger.io",
"parentId": "__BASE_ENVIRONMENT_ID__"
},
{

View File

@ -64,17 +64,14 @@ let requestCounts: Record<string, number> = {};
*
* @returns the resolved server URL
*/
const getDefaultServerUrl = (api: OpenAPIV3.Document) => {
const getServerUrl = (server: OpenAPIV3.ServerObject) => {
const exampleServer = 'http://example.com/';
const servers = api.servers || [];
const firstServer = servers[0];
const foundServer = firstServer && firstServer.url;
if (!foundServer) {
if (!(server && server.url)) {
return urlParse(exampleServer);
}
const url = resolveVariables(firstServer);
const url = resolveVariables(server);
return urlParse(url);
};
@ -128,6 +125,57 @@ const isSpecExtension = (property: string): property is SpecExtension => {
return property.indexOf('x-') === 0;
};
/**
* Create env definitions based on openapi document.
*/
const parseEnvs = (baseEnv: ImportRequest, document?: OpenAPIV3.Document | null) => {
if (!document) {
return [];
}
let servers: OpenAPIV3.ServerObject[] | undefined;
if (!document.servers) {
servers = [{ url: 'http://example.com/' }];
} else {
servers = document.servers;
}
const securityVariables = getSecurityEnvVariables(
document.components?.securitySchemes as unknown as OpenAPIV3.SecuritySchemeObject,
);
return servers
.map(server => {
const currentServerUrl = getServerUrl(server);
const protocol = currentServerUrl.protocol || '';
// Base path is pulled out of the URL, and the trailing slash is removed
const basePath = (currentServerUrl.pathname || '').replace(/\/$/, '');
const hash = crypto
.createHash('sha1')
.update(server.url)
.digest('hex')
.slice(0, 8);
const openapiEnv: ImportRequest = {
_type: 'environment',
_id: `env___BASE_ENVIRONMENT_ID___sub__${hash}`,
parentId: baseEnv._id,
name: `OpenAPI env ${currentServerUrl.host}`,
data: {
// note: `URL.protocol` returns with trailing `:` (i.e. "https:")
scheme: protocol.replace(/:$/, '') || ['http'],
base_path: basePath,
host: currentServerUrl.host || '',
...securityVariables,
},
};
return openapiEnv;
}) || [];
};
/**
* Create request definitions based on openapi document.
*/
@ -767,35 +815,14 @@ export const convert: Converter = async rawData => {
base_url: '{{ scheme }}://{{ host }}{{ base_path }}',
},
};
const defaultServerUrl = getDefaultServerUrl(apiDocument);
const securityVariables = getSecurityEnvVariables(
apiDocument.components?.securitySchemes as unknown as OpenAPIV3.SecuritySchemeObject,
);
const protocol = defaultServerUrl.protocol || '';
// Base path is pulled out of the URL, and the trailing slash is removed
const basePath = (defaultServerUrl.pathname || '').replace(/\/$/, '');
const openapiEnv: ImportRequest = {
_type: 'environment',
_id: 'env___BASE_ENVIRONMENT_ID___sub',
parentId: baseEnv._id,
name: 'OpenAPI env',
data: {
// note: `URL.protocol` returns with trailing `:` (i.e. "https:")
scheme: protocol.replace(/:$/, '') || ['http'],
base_path: basePath,
host: defaultServerUrl.host || '',
...securityVariables,
},
};
const openapiEnvs = parseEnvs(baseEnv, apiDocument);
const endpoints = parseEndpoints(apiDocument);
return [
workspace,
baseEnv,
openapiEnv,
...openapiEnvs,
...endpoints,
];
};