From 512efe0809fd7ff8df511e2d976031f462a60cec Mon Sep 17 00:00:00 2001 From: Christopher Kolstad Date: Tue, 4 Apr 2023 15:45:34 +0200 Subject: [PATCH] docs: Flesh out openapi for tag: Environments (#3440) ### What This fleshes out the documentation for actions tagged with Environments. Co-authored-by: Thomas Heartman --- .../spec/environment-project-schema.ts | 33 ++++- src/lib/openapi/spec/environment-schema.ts | 21 ++-- .../spec/environments-project-schema.ts | 1 + src/lib/routes/admin-api/environments.ts | 45 ++++++- .../__snapshots__/openapi.e2e.test.ts.snap | 119 ++++++++++++++++-- 5 files changed, 189 insertions(+), 30 deletions(-) diff --git a/src/lib/openapi/spec/environment-project-schema.ts b/src/lib/openapi/spec/environment-project-schema.ts index 26b0303a74..1aefdb031d 100644 --- a/src/lib/openapi/spec/environment-project-schema.ts +++ b/src/lib/openapi/spec/environment-project-schema.ts @@ -4,30 +4,51 @@ export const environmentProjectSchema = { $id: '#/components/schemas/environmentProjectSchema', type: 'object', additionalProperties: false, - required: ['name', 'type', 'enabled'], + required: ['name', 'type', 'enabled', 'protected', 'sortOrder'], + description: "Describes a project's configuration in a given environment.", properties: { name: { type: 'string', + example: 'development', + description: 'The name of the environment', }, type: { type: 'string', + example: 'production', + description: + 'The [type of environment](https://docs.getunleash.io/reference/environments#environment-types).', }, enabled: { type: 'boolean', + example: true, + description: + '`true` if the environment is enabled for the project, otherwise `false`', }, protected: { type: 'boolean', + example: false, + description: + '`true` if the environment is protected, otherwise `false`. A *protected* environment can not be deleted.', }, sortOrder: { - type: 'number', + type: 'integer', + example: 1, + description: + 'Priority of the environment in a list of environments, the lower the value, the higher up in the list the environment will appear', }, projectApiTokenCount: { - type: 'number', - nullable: true, + type: 'integer', + minimum: 0, + example: 5, + description: + 'The number of client and front-end API tokens that have access to this project', }, projectEnabledToggleCount: { - type: 'number', - nullable: true, + type: 'integer', + minimum: 0, + example: 7, + description: + 'The number of features enabled in this environment for this project', }, }, components: {}, diff --git a/src/lib/openapi/spec/environment-schema.ts b/src/lib/openapi/spec/environment-schema.ts index 32a8750030..500c99dc7b 100644 --- a/src/lib/openapi/spec/environment-schema.ts +++ b/src/lib/openapi/spec/environment-schema.ts @@ -4,7 +4,7 @@ export const environmentSchema = { $id: '#/components/schemas/environmentSchema', type: 'object', additionalProperties: false, - required: ['name', 'type', 'enabled'], + required: ['name', 'type', 'enabled', 'protected', 'sortOrder'], description: 'A definition of the project environment', properties: { name: { @@ -15,7 +15,8 @@ export const environmentSchema = { type: { type: 'string', example: 'development', - description: 'The type of the environment', + description: + 'The [type of environment](https://docs.getunleash.io/reference/environments#environment-types).', }, enabled: { type: 'boolean', @@ -25,28 +26,34 @@ export const environmentSchema = { }, protected: { type: 'boolean', + example: true, + description: + '`true` if the environment is protected, otherwise `false`. A *protected* environment can not be deleted.', }, sortOrder: { - type: 'number', + type: 'integer', example: 3, description: - 'The sort order of the environment in the environments list', + 'Priority of the environment in a list of environments, the lower the value, the higher up in the list the environment will appear. Needs to be an integer', }, projectCount: { - type: 'number', + type: 'integer', nullable: true, + minimum: 0, example: 10, description: 'The number of projects with this environment', }, apiTokenCount: { - type: 'number', + type: 'integer', nullable: true, + minimum: 0, example: 6, description: 'The number of API tokens for the project environment', }, enabledToggleCount: { - type: 'number', + type: 'integer', nullable: true, + minimum: 0, example: 10, description: 'The number of enabled toggles for the project environment', diff --git a/src/lib/openapi/spec/environments-project-schema.ts b/src/lib/openapi/spec/environments-project-schema.ts index eac5c53bdc..66747f67de 100644 --- a/src/lib/openapi/spec/environments-project-schema.ts +++ b/src/lib/openapi/spec/environments-project-schema.ts @@ -6,6 +6,7 @@ export const environmentsProjectSchema = { type: 'object', additionalProperties: false, required: ['version', 'environments'], + description: 'Environments defined for a given project', properties: { version: { type: 'integer', diff --git a/src/lib/routes/admin-api/environments.ts b/src/lib/routes/admin-api/environments.ts index e58f10a361..c55384ad76 100644 --- a/src/lib/routes/admin-api/environments.ts +++ b/src/lib/routes/admin-api/environments.ts @@ -17,7 +17,10 @@ import { EnvironmentSchema, } from '../../openapi/spec/environment-schema'; import { SortOrderSchema } from '../../openapi/spec/sort-order-schema'; -import { emptyResponse } from '../../openapi/util/standard-responses'; +import { + emptyResponse, + getStandardResponses, +} from '../../openapi/util/standard-responses'; import { environmentsProjectSchema, EnvironmentsProjectSchema, @@ -58,8 +61,14 @@ export class EnvironmentsController extends Controller { middleware: [ openApiService.validPath({ tags: ['Environments'], + summary: 'Get all environments', + description: + 'Retrieves all environments that exist in this Unleash instance.', operationId: 'getAllEnvironments', - responses: { 200: emptyResponse }, + responses: { + 200: createResponseSchema('environmentsSchema'), + ...getStandardResponses(401, 403), + }, }), ], }); @@ -73,8 +82,12 @@ export class EnvironmentsController extends Controller { openApiService.validPath({ tags: ['Environments'], operationId: 'getEnvironment', + summary: 'Get the environment with `name`', + description: + 'Retrieves the environment with `name` if it exists in this Unleash instance', responses: { 200: createResponseSchema('environmentSchema'), + ...getStandardResponses(401, 403, 404), }, }), ], @@ -89,8 +102,12 @@ export class EnvironmentsController extends Controller { openApiService.validPath({ tags: ['Environments'], operationId: 'getProjectEnvironments', + summary: 'Get the environments available to a project', + description: + 'Gets the environments that are available for this project. An environment is available for a project if enabled in the [project configuration](https://docs.getunleash.io/reference/environments#step-1-enable-new-environments-for-your-project)', responses: { 200: createResponseSchema('environmentsProjectSchema'), + ...getStandardResponses(401, 403, 404), }, }), ], @@ -104,9 +121,15 @@ export class EnvironmentsController extends Controller { middleware: [ openApiService.validPath({ tags: ['Environments'], + summary: 'Update environment sort orders', + description: + 'Updates sort orders for the named environments. Environments not specified are unaffected.', operationId: 'updateSortOrder', requestBody: createRequestSchema('sortOrderSchema'), - responses: { 200: emptyResponse }, + responses: { + 200: emptyResponse, + ...getStandardResponses(401, 403, 404), + }, }), ], }); @@ -120,8 +143,14 @@ export class EnvironmentsController extends Controller { middleware: [ openApiService.validPath({ tags: ['Environments'], + summary: 'Toggle the environment with `name` on', + description: + 'Makes it possible to enable this environment for a project. An environment must first be globally enabled using this endpoint before it can be enabled for a project', operationId: 'toggleEnvironmentOn', - responses: { 204: emptyResponse }, + responses: { + 204: emptyResponse, + ...getStandardResponses(401, 403, 404), + }, }), ], }); @@ -135,8 +164,14 @@ export class EnvironmentsController extends Controller { middleware: [ openApiService.validPath({ tags: ['Environments'], + summary: 'Toggle the environment with `name` off', + description: + 'Removes this environment from the list of available environments for projects to use', operationId: 'toggleEnvironmentOff', - responses: { 204: emptyResponse }, + responses: { + 204: emptyResponse, + ...getStandardResponses(401, 403, 404), + }, }), ], }); diff --git a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap index 27fd662d47..9c5357a55f 100644 --- a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap +++ b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap @@ -1008,28 +1008,43 @@ exports[`should serve the OpenAPI spec 1`] = ` }, "environmentProjectSchema": { "additionalProperties": false, + "description": "Describes a project's configuration in a given environment.", "properties": { "enabled": { + "description": "\`true\` if the environment is enabled for the project, otherwise \`false\`", + "example": true, "type": "boolean", }, "name": { + "description": "The name of the environment", + "example": "development", "type": "string", }, "projectApiTokenCount": { - "nullable": true, - "type": "number", + "description": "The number of client and front-end API tokens that have access to this project", + "example": 5, + "minimum": 0, + "type": "integer", }, "projectEnabledToggleCount": { - "nullable": true, - "type": "number", + "description": "The number of features enabled in this environment for this project", + "example": 7, + "minimum": 0, + "type": "integer", }, "protected": { + "description": "\`true\` if the environment is protected, otherwise \`false\`. A *protected* environment can not be deleted.", + "example": false, "type": "boolean", }, "sortOrder": { - "type": "number", + "description": "Priority of the environment in a list of environments, the lower the value, the higher up in the list the environment will appear", + "example": 1, + "type": "integer", }, "type": { + "description": "The [type of environment](https://docs.getunleash.io/reference/environments#environment-types).", + "example": "production", "type": "string", }, }, @@ -1037,6 +1052,8 @@ exports[`should serve the OpenAPI spec 1`] = ` "name", "type", "enabled", + "protected", + "sortOrder", ], "type": "object", }, @@ -1047,8 +1064,9 @@ exports[`should serve the OpenAPI spec 1`] = ` "apiTokenCount": { "description": "The number of API tokens for the project environment", "example": 6, + "minimum": 0, "nullable": true, - "type": "number", + "type": "integer", }, "enabled": { "description": "\`true\` if the environment is enabled for the project, otherwise \`false\`.", @@ -1058,8 +1076,9 @@ exports[`should serve the OpenAPI spec 1`] = ` "enabledToggleCount": { "description": "The number of enabled toggles for the project environment", "example": 10, + "minimum": 0, "nullable": true, - "type": "number", + "type": "integer", }, "name": { "description": "The name of the environment", @@ -1069,19 +1088,22 @@ exports[`should serve the OpenAPI spec 1`] = ` "projectCount": { "description": "The number of projects with this environment", "example": 10, + "minimum": 0, "nullable": true, - "type": "number", + "type": "integer", }, "protected": { + "description": "\`true\` if the environment is protected, otherwise \`false\`. A *protected* environment can not be deleted.", + "example": true, "type": "boolean", }, "sortOrder": { - "description": "The sort order of the environment in the environments list", + "description": "Priority of the environment in a list of environments, the lower the value, the higher up in the list the environment will appear. Needs to be an integer", "example": 3, - "type": "number", + "type": "integer", }, "type": { - "description": "The type of the environment", + "description": "The [type of environment](https://docs.getunleash.io/reference/environments#environment-types).", "example": "development", "type": "string", }, @@ -1090,11 +1112,14 @@ exports[`should serve the OpenAPI spec 1`] = ` "name", "type", "enabled", + "protected", + "sortOrder", ], "type": "object", }, "environmentsProjectSchema": { "additionalProperties": false, + "description": "Environments defined for a given project", "properties": { "environments": { "items": { @@ -4944,12 +4969,27 @@ Stats are divided into current and previous **windows**. }, "/api/admin/environments": { "get": { + "description": "Retrieves all environments that exist in this Unleash instance.", "operationId": "getAllEnvironments", "responses": { "200": { - "description": "This response has no body.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/environmentsSchema", + }, + }, + }, + "description": "environmentsSchema", + }, + "401": { + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "description": "User credentials are valid but does not have enough privileges to execute this operation", }, }, + "summary": "Get all environments", "tags": [ "Environments", ], @@ -4957,6 +4997,7 @@ Stats are divided into current and previous **windows**. }, "/api/admin/environments/project/{projectId}": { "get": { + "description": "Gets the environments that are available for this project. An environment is available for a project if enabled in the [project configuration](https://docs.getunleash.io/reference/environments#step-1-enable-new-environments-for-your-project)", "operationId": "getProjectEnvironments", "parameters": [ { @@ -4979,7 +5020,17 @@ Stats are divided into current and previous **windows**. }, "description": "environmentsProjectSchema", }, + "401": { + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "description": "User credentials are valid but does not have enough privileges to execute this operation", + }, + "404": { + "description": "The requested resource was not found.", + }, }, + "summary": "Get the environments available to a project", "tags": [ "Environments", ], @@ -4987,6 +5038,7 @@ Stats are divided into current and previous **windows**. }, "/api/admin/environments/sort-order": { "put": { + "description": "Updates sort orders for the named environments. Environments not specified are unaffected.", "operationId": "updateSortOrder", "requestBody": { "content": { @@ -5003,7 +5055,17 @@ Stats are divided into current and previous **windows**. "200": { "description": "This response has no body.", }, + "401": { + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "description": "User credentials are valid but does not have enough privileges to execute this operation", + }, + "404": { + "description": "The requested resource was not found.", + }, }, + "summary": "Update environment sort orders", "tags": [ "Environments", ], @@ -5011,6 +5073,7 @@ Stats are divided into current and previous **windows**. }, "/api/admin/environments/{name}": { "get": { + "description": "Retrieves the environment with \`name\` if it exists in this Unleash instance", "operationId": "getEnvironment", "parameters": [ { @@ -5033,7 +5096,17 @@ Stats are divided into current and previous **windows**. }, "description": "environmentSchema", }, + "401": { + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "description": "User credentials are valid but does not have enough privileges to execute this operation", + }, + "404": { + "description": "The requested resource was not found.", + }, }, + "summary": "Get the environment with \`name\`", "tags": [ "Environments", ], @@ -5041,6 +5114,7 @@ Stats are divided into current and previous **windows**. }, "/api/admin/environments/{name}/off": { "post": { + "description": "Removes this environment from the list of available environments for projects to use", "operationId": "toggleEnvironmentOff", "parameters": [ { @@ -5056,7 +5130,17 @@ Stats are divided into current and previous **windows**. "204": { "description": "This response has no body.", }, + "401": { + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "description": "User credentials are valid but does not have enough privileges to execute this operation", + }, + "404": { + "description": "The requested resource was not found.", + }, }, + "summary": "Toggle the environment with \`name\` off", "tags": [ "Environments", ], @@ -5064,6 +5148,7 @@ Stats are divided into current and previous **windows**. }, "/api/admin/environments/{name}/on": { "post": { + "description": "Makes it possible to enable this environment for a project. An environment must first be globally enabled using this endpoint before it can be enabled for a project", "operationId": "toggleEnvironmentOn", "parameters": [ { @@ -5079,7 +5164,17 @@ Stats are divided into current and previous **windows**. "204": { "description": "This response has no body.", }, + "401": { + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "description": "User credentials are valid but does not have enough privileges to execute this operation", + }, + "404": { + "description": "The requested resource was not found.", + }, }, + "summary": "Toggle the environment with \`name\` on", "tags": [ "Environments", ],