From 95dfbd01aaff821ac4c820fb8197d907132060b5 Mon Sep 17 00:00:00 2001 From: prakhar katiyar Date: Fri, 30 May 2025 18:46:53 +0530 Subject: [PATCH 1/9] corrected api specs --- specs/app-store.yaml | 412 +++++++-- specs/application.yaml | 397 --------- specs/application/core.yaml | 509 +++++++++++ .../creation.yaml} | 18 +- .../labels.yaml} | 116 ++- .../listing.yaml} | 65 +- .../api-changes.yaml} | 121 ++- specs/audit/definitions.yaml | 299 +++++++ specs/batch.yaml | 541 ------------ .../buildInfraConfig/build-infra-config.yaml | 352 ++++++-- specs/bulk_actions.yaml | 155 ---- specs/change-deployment-chart-type.yaml | 34 - specs/ci-pipeline/ci-pipeline-build-spec.yaml | 281 +++++- specs/cluster_access_policy.yaml | 171 ---- specs/cluster_add_api_specs.yaml | 167 ---- specs/{ => common}/api-spec.yaml | 10 +- specs/{ => common}/delete-options.yaml | 0 specs/{version.yml => common/version.yaml} | 0 specs/configDiffView.yaml | 73 -- specs/default-template-values.yaml | 40 - .../app-type-change.yaml} | 104 ++- .../core.yaml} | 68 +- specs/deployment/group.yaml | 301 +++++++ specs/deployment/pipeline.yaml | 366 ++++++++ specs/{ => deployment}/rollback.yaml | 62 +- specs/deployment/timeline.yaml | 154 ++++ .../bulk-delete.yaml} | 66 +- specs/environment/config-diff.yaml | 398 +++++++++ .../core.yaml} | 79 +- specs/environment/templates.yaml | 123 +++ specs/ephemeralContainers.yaml | 109 --- specs/gitops-validation.yaml | 172 ---- .../bitbucket.yaml} | 77 +- specs/gitops/core.yaml | 423 +++++++++ specs/{fluxcd_app.yaml => gitops/fluxcd.yaml} | 236 +++-- specs/gitops/manifest-generation.yaml | 216 +++++ .../submodules.yaml} | 220 ++--- specs/gitops/validation.yaml | 390 +++++++++ specs/global-plugin.yaml | 604 ------------- specs/global_cm_cs.yaml | 81 -- specs/{ => helm}/charts.yaml | 164 ++-- specs/helm/deployment-chart-type.yaml | 104 +++ .../dynamic-charts.yaml} | 68 +- specs/helm/provider.yaml | 792 +++++++++++++++++ specs/helm/repo-validation.yaml | 211 +++++ specs/helm_repo_validation.yaml | 152 ---- specs/historical-definitions.yaml | 596 ------------- .../docker-build.yaml} | 241 +++++- specs/{ => infrastructure}/image-tagging.yaml | 23 +- specs/jobs.yaml | 194 ----- specs/jobs/batch.yaml | 411 +++++++++ specs/jobs/bulk-actions.yaml | 268 ++++++ .../bulk-update.yaml} | 119 +-- specs/jobs/core.yaml | 266 ++++++ specs/k8s-resource-apis.yaml | 35 - specs/k8s_apis-spec.yaml | 673 --------------- specs/kubernetes/access-policy.yaml | 288 +++++++ specs/kubernetes/apis.yaml | 498 +++++++++++ .../capacity.yaml} | 499 ++++++----- specs/kubernetes/cluster-management.yaml | 479 +++++++++++ .../cluster.yaml} | 83 +- specs/kubernetes/ephemeral-containers.yaml | 193 +++++ specs/kubernetes/resources.yaml | 281 ++++++ specs/manifest_generation.yeaml.yaml | 117 --- .../core.yaml} | 14 +- specs/notifications/webhooks.yaml | 661 ++++++++++++++ specs/pipeline-status-timeline.yaml | 77 -- specs/plugins/config-maps.yaml | 565 ++++++++++++ .../{plugin-system.yaml => plugins/core.yaml} | 142 +-- specs/plugins/global.yaml | 572 ++++++++++++ .../api-tokens.yaml} | 161 +++- specs/security/core.yaml | 811 ++++++++++++++++++ .../group-policy.yaml} | 296 ++++--- .../policy.yaml} | 312 +++---- specs/security/roles.yaml | 1 + specs/security/user-management.yaml | 416 +++++++++ 76 files changed, 13058 insertions(+), 5735 deletions(-) delete mode 100644 specs/application.yaml create mode 100644 specs/application/core.yaml rename specs/{app_create_api.yaml => application/creation.yaml} (97%) rename specs/{app-labels.yaml => application/labels.yaml} (65%) rename specs/{applisting.yaml => application/listing.yaml} (57%) rename specs/{historical-get-api-change.yaml => audit/api-changes.yaml} (78%) create mode 100644 specs/audit/definitions.yaml delete mode 100644 specs/batch.yaml delete mode 100644 specs/bulk_actions.yaml delete mode 100644 specs/change-deployment-chart-type.yaml delete mode 100644 specs/cluster_access_policy.yaml delete mode 100644 specs/cluster_add_api_specs.yaml rename specs/{ => common}/api-spec.yaml (91%) rename specs/{ => common}/delete-options.yaml (100%) rename specs/{version.yml => common/version.yaml} (100%) delete mode 100644 specs/configDiffView.yaml delete mode 100644 specs/default-template-values.yaml rename specs/{deployment_app_type_change_api.yaml => deployment/app-type-change.yaml} (57%) rename specs/{deployments.yaml => deployment/core.yaml} (61%) create mode 100644 specs/deployment/group.yaml create mode 100644 specs/deployment/pipeline.yaml rename specs/{ => deployment}/rollback.yaml (74%) create mode 100644 specs/deployment/timeline.yaml rename specs/{bulk-env-delete.yaml => environment/bulk-delete.yaml} (67%) create mode 100644 specs/environment/config-diff.yaml rename specs/{environment.yaml => environment/core.yaml} (56%) create mode 100644 specs/environment/templates.yaml delete mode 100644 specs/ephemeralContainers.yaml delete mode 100644 specs/gitops-validation.yaml rename specs/{gitops_bitbucket.yaml => gitops/bitbucket.yaml} (70%) create mode 100644 specs/gitops/core.yaml rename specs/{fluxcd_app.yaml => gitops/fluxcd.yaml} (69%) create mode 100644 specs/gitops/manifest-generation.yaml rename specs/{git_submodules.yaml => gitops/submodules.yaml} (55%) create mode 100644 specs/gitops/validation.yaml delete mode 100644 specs/global-plugin.yaml delete mode 100644 specs/global_cm_cs.yaml rename specs/{ => helm}/charts.yaml (54%) create mode 100644 specs/helm/deployment-chart-type.yaml rename specs/{dynamic-handling-of-charts.yaml => helm/dynamic-charts.yaml} (51%) create mode 100644 specs/helm/provider.yaml create mode 100644 specs/helm/repo-validation.yaml delete mode 100644 specs/helm_repo_validation.yaml delete mode 100644 specs/historical-definitions.yaml rename specs/{docker-build-config-override.yaml => infrastructure/docker-build.yaml} (55%) rename specs/{ => infrastructure}/image-tagging.yaml (84%) delete mode 100644 specs/jobs.yaml create mode 100644 specs/jobs/batch.yaml create mode 100644 specs/jobs/bulk-actions.yaml rename specs/{bulk_update.yaml => jobs/bulk-update.yaml} (76%) create mode 100644 specs/jobs/core.yaml delete mode 100644 specs/k8s-resource-apis.yaml delete mode 100644 specs/k8s_apis-spec.yaml create mode 100644 specs/kubernetes/access-policy.yaml create mode 100644 specs/kubernetes/apis.yaml rename specs/{kube-capacity.yaml => kubernetes/capacity.yaml} (60%) create mode 100644 specs/kubernetes/cluster-management.yaml rename specs/{cluster_api_spec.yaml => kubernetes/cluster.yaml} (68%) create mode 100644 specs/kubernetes/ephemeral-containers.yaml create mode 100644 specs/kubernetes/resources.yaml delete mode 100644 specs/manifest_generation.yeaml.yaml rename specs/{notification.yaml => notifications/core.yaml} (96%) create mode 100644 specs/notifications/webhooks.yaml delete mode 100644 specs/pipeline-status-timeline.yaml create mode 100644 specs/plugins/config-maps.yaml rename specs/{plugin-system.yaml => plugins/core.yaml} (87%) create mode 100644 specs/plugins/global.yaml rename specs/{apiToken_api-spec.yaml => security/api-tokens.yaml} (52%) create mode 100644 specs/security/core.yaml rename specs/{group_policy.yaml => security/group-policy.yaml} (52%) rename specs/{user_policy.yaml => security/policy.yaml} (51%) create mode 100644 specs/security/roles.yaml create mode 100644 specs/security/user-management.yaml diff --git a/specs/app-store.yaml b/specs/app-store.yaml index c9e72bf01f..8cc1678dd2 100644 --- a/specs/app-store.yaml +++ b/specs/app-store.yaml @@ -2,94 +2,404 @@ openapi: "3.0.0" info: version: 1.0.0 title: Devtron Labs + description: Devtron API for app store management + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080 paths: - /orchestrator/app-store/discover/: + /app-store/discover: get: - description: this api will return all the charts from charts repos. - parameters: [ ] + description: Get all charts from chart repositories + parameters: + - name: includeDeprecated + in: query + description: Include deprecated charts + required: false + schema: + type: boolean + - name: chartRepoId + in: query + description: Chart repository IDs (comma separated) + required: false + schema: + type: string + - name: registryId + in: query + description: Registry IDs (comma separated) + required: false + schema: + type: string + - name: appStoreName + in: query + description: App store name filter + required: false + schema: + type: string + - name: offset + in: query + description: Offset for pagination + required: false + schema: + type: integer + - name: size + in: query + description: Size for pagination + required: false + schema: + type: integer + - name: chartCategoryId + in: query + description: Chart category IDs (comma separated) + required: false + schema: + type: string responses: '200': - description: list response + description: List of app store applications with versions content: application/json: schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - allOf: - - type: object - properties: - appId: - type: integer - description: unique application id - required: - - appId - - $ref: '#/components/schemas/AppStore' - default: - description: unexpected error + $ref: '#/components/schemas/AppStoreListingResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' + /app-store/discover/application/{id}: + get: + description: Get chart details for a specific version + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: App store application version ID + responses: + '200': + description: Chart details + content: + application/json: + schema: + $ref: '#/components/schemas/AppStoreApplicationVersion' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /app-store/discover/application/{appStoreId}/version/autocomplete: + get: + description: Get chart versions for an app store application + parameters: + - name: appStoreId + in: path + required: true + schema: + type: integer + description: App store application ID + responses: + '200': + description: List of chart versions + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AppStoreApplicationVersion' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /app-store/discover/application/chartInfo/{appStoreApplicationVersionId}: + get: + description: Get chart information for a specific version + parameters: + - name: appStoreApplicationVersionId + in: path + required: true + schema: + type: integer + description: App store application version ID + responses: + '200': + description: Chart information + content: + application/json: + schema: + $ref: '#/components/schemas/ChartInfo' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /app-store/discover/search: + get: + description: Search app store charts by name + parameters: + - name: chartName + in: query + required: true + schema: + type: string + description: Chart name to search for + responses: + '200': + description: List of matching charts + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AppStoreApplication' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' - -# components mentioned below components: schemas: - AppStore: + AppStoreApplication: type: object - required: - - id - - name properties: id: type: integer - description: app store id + description: App store application ID name: type: string - description: app store name - appStoreApplicationVersionId: + description: App store application name + chartRepoId: type: integer - description: app store version id - chart_git_location: + description: Chart repository ID + active: + type: boolean + description: Whether the application is active + chartGitLocation: + type: string + description: Chart Git repository location + createdOn: type: string - description: chart git repo location - chart_name: + format: date-time + description: Creation timestamp + updatedOn: type: string - description: chart name - chart_repo_id: + format: date-time + description: Last update timestamp + appStoreApplicationVersions: + type: array + items: + $ref: '#/components/schemas/AppStoreApplicationVersion' + description: List of application versions + + AppStoreApplicationVersion: + type: object + properties: + id: type: integer - description: app store and chart repo link id + description: Version ID + version: + type: string + description: Version number + appVersion: + type: string + description: Application version + created: + type: string + format: date-time + description: Creation timestamp deprecated: type: boolean - description: deprecated app store flag + description: Whether the version is deprecated description: type: string - description: app store description, short summary + description: Version description + digest: + type: string + description: Chart digest icon: type: string - description: app store icon link - created_on: + description: Icon URL + name: type: string - description: created on - updated_on: + description: Chart name + chartName: type: string - description: modification date - version: + description: Chart name + appStoreApplicationName: type: string - description: app store version - active: + description: App store application name + home: + type: string + description: Home URL + source: + type: string + description: Source URL + valuesYaml: + type: string + description: Values YAML + chartYaml: + type: string + description: Chart YAML + appStoreId: + type: integer + description: App store ID + latest: type: boolean - description: active app store + description: Whether this is the latest version + createdOn: + type: string + format: date-time + description: Creation timestamp + rawValues: + type: string + description: Raw values + readme: + type: string + description: README content + valuesSchemaJson: + type: string + description: Values schema in JSON format + notes: + type: string + description: Release notes + + ChartInfo: + type: object + properties: + chartName: + type: string + description: Chart name + chartVersion: + type: string + description: Chart version + valuesYaml: + type: string + description: Values YAML + chartYaml: + type: string + description: Chart YAML + readme: + type: string + description: README content + notes: + type: string + description: Release notes + + AppStoreListingResponse: + type: object + properties: + code: + type: integer + description: Status code + status: + type: string + description: Status message + result: + type: array + items: + $ref: '#/components/schemas/AppStoreApplication' + description: List of app store applications ErrorResponse: required: @@ -105,7 +415,7 @@ components: description: Error message errors: type: array - description: errors + description: List of errors items: $ref: '#/components/schemas/Error' diff --git a/specs/application.yaml b/specs/application.yaml deleted file mode 100644 index 5fc4434f7f..0000000000 --- a/specs/application.yaml +++ /dev/null @@ -1,397 +0,0 @@ -openapi: "3.0.0" -info: - version: 1.0.0 - title: Devtron Labs -paths: - /orchestrator/app: - post: - description: create new application - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/App' - responses: - '200': - description: App create response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: object - description: string - allOf: - - type: object - properties: - id: - type: integer - description: unique application id - required: - - id - - $ref: '#/components/schemas/App' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /orchestrator/app/edit: - post: - description: update application projects and labels - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/App' - responses: - '200': - description: App update response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: object - description: string - allOf: - - type: object - properties: - id: - type: integer - description: unique application id - required: - - id - - $ref: '#/components/schemas/App' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - - /orchestrator/app/list: - post: - description: app listing, collection of deployed applications or undeployed or incomplete configured apps. - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AppListingRequest' - responses: - '200': - description: App create response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: object - description: string - required: - - appCount - - appContainers - - deploymentGroup - properties: - appCount: - type: integer - description: app count, total number of apps available based on filter provided in request. - appContainers: - type: array - description: app containers - items: - $ref: '#/components/schemas/AppContainer' - deploymentGroup: - type: object - description: deployment group - $ref: '#/components/schemas/DeploymentGroup' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - - /orchestrator/app/edit/projects: - post: - description: update project for app - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AppProjectUpdateRequest' - responses: - '200': - description: App update response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: object - description: string - $ref: '#/components/schemas/AppProjectUpdateRequest' - - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' -# components mentioned below -components: - schemas: - AppLabel: - type: object - required: - - key - - value - properties: - key: - type: string - description: label key - value: - type: string - description: label value - propagate: - type: boolean - description: Whether to propagate to kubernetes resources - - App: - type: object - required: - - appName - - teamId - - templateId - properties: - appName: - type: string - description: app name - teamId: - type: integer - description: project id - templateId: - type: integer - description: reference app id, used for clone, set default value 0 for blank app. - labels: - type: array - description: each apps may have multiple labels. these are optional. - items: - $ref: '#/components/schemas/AppLabel' - AppProjectUpdateRequest: - type: object - required: - - teamId - - appId - properties: - teamId: - type: integer - description: project id - appId: - type: array - description: team id, teams ids are projects ids - items: - type: integer - - AppListingRequest: - type: object - required: - - offset - - size - properties: - appNameSearch: - type: string - description: app name search, wildcard match - offset: - type: integer - description: offset - size: - type: integer - description: result size - sortBy: - type: string - description: sort by - sortOrder: - type: string - description: sort order - environments: - type: array - description: environment id - items: - type: integer - teams: - type: array - description: team id, teams ids are projects ids - items: - type: integer - labels: - type: array - description: app labels - items: - type: string - statuses: - type: array - description: status - items: - type: string - - AppContainer: - type: object - required: - - appId - - appName - - environments - properties: - appId: - type: integer - description: app id - appName: - type: string - description: app name - environments: - type: array - items: - $ref: '#/components/schemas/EnvContainer' - - EnvContainer: - type: object - required: - - appId - - appName - - environmentId - - environmentName - properties: - appId: - type: integer - description: app id - appName: - type: string - description: app name - cdStageStatus: - type: string - description: app name - dataSource: - type: string - description: app name - ciArtifactId: - type: integer - description: app name - deleted: - type: boolean - description: app name - environmentId: - type: integer - description: app name - environmentName: - type: string - description: app name - status: - type: string - description: app name - appStatus: - type: string - description: app status for this environment - postStageStatus: - type: string - description: app name - preStageStatus: - type: string - description: app name - lastDeployedTime: - type: string - description: deployed time - materialInfo: - type: array - items: - type: object - - DeploymentGroup: - type: object - required: - - id - properties: - id: - type: integer - description: id - ciPipelineId: - type: integer - description: ciPipelineId - environmentId: - type: integer - description: environmentId - appCount: - type: integer - description: appCount - name: - type: string - description: name - noOfApps: - type: string - description: noOfApps - - - ErrorResponse: - required: - - code - - status - properties: - code: - type: integer - format: int32 - description: Error code - status: - type: string - description: Error message - errors: - type: array - description: errors - items: - $ref: '#/components/schemas/Error' - - Error: - required: - - code - - status - properties: - code: - type: integer - format: int32 - description: Error internal code - internalMessage: - type: string - description: Error internal message - userMessage: - type: string - description: Error user message \ No newline at end of file diff --git a/specs/application/core.yaml b/specs/application/core.yaml new file mode 100644 index 0000000000..ebd0bb14ab --- /dev/null +++ b/specs/application/core.yaml @@ -0,0 +1,509 @@ +openapi: 3.0.3 +info: + version: 1.0.0 + title: Devtron Application Management API + description: | + This API provides functionality for managing applications in Devtron, including + creating, updating, and listing applications, as well as managing application + configurations, environments, and deployments. + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Support + email: support@devtron.ai + url: https://devtron.ai/support + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +servers: + - url: /orchestrator + description: Devtron Orchestrator API Server + +tags: + - name: Applications + description: Operations related to application management + - name: Environments + description: Operations related to application environments + - name: Deployments + description: Operations related to application deployments + +paths: + /core/v1beta1/application: + post: + tags: + - Applications + summary: Create a new application + description: Creates a new application in the Devtron system with the provided configuration. + operationId: createApplication + requestBody: + description: Application creation request + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateAppRequest' + responses: + '200': + description: Application created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + '400': + description: Invalid request format or missing required fields + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '409': + description: Application with the same name already exists + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + security: + - bearerAuth: [] + + /app/edit: + post: + tags: + - Applications + summary: Update application + description: Updates an existing application's configuration including projects and labels. + operationId: updateApplication + requestBody: + description: Application update request + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/App' + responses: + '200': + description: Application updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + '400': + description: Invalid request format or missing required fields + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: Application not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + security: + - bearerAuth: [] + + /app/list: + post: + tags: + - Applications + summary: List applications + description: | + Retrieves a paginated list of applications based on the provided filters. + Can return deployed applications, undeployed applications, or applications with incomplete configurations. + operationId: listApplications + requestBody: + description: Application listing filters + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AppListingRequest' + responses: + '200': + description: List of applications retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/AppListResponse' + '400': + description: Invalid request parameters + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + security: + - bearerAuth: [] + + /app/details/{appId}: + get: + tags: + - Applications + summary: Get application details + description: Retrieves detailed information about a specific application including its configurations and status. + operationId: getApplicationDetails + parameters: + - name: appId + in: path + description: ID of the application to retrieve + required: true + schema: + type: integer + format: int64 + minimum: 1 + example: 12345 + responses: + '200': + description: Application details retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/AppDetails' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: Application not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + security: + - bearerAuth: [] + + /app/edit/projects: + post: + tags: + - Applications + summary: Update application projects + description: Updates the projects associated with an application + operationId: updateApplicationProjects + requestBody: + description: Application project update request + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AppProjectUpdateRequest' + responses: + '200': + description: Projects updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + '400': + description: Invalid request format or missing required fields + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: Application not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + security: + - bearerAuth: [] + +# components section +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + + schemas: + ApiResponse: + type: object + properties: + code: + type: integer + description: Status code + status: + type: string + description: Status message + result: + type: object + description: Response result data + + ErrorResponse: + type: object + properties: + code: + type: integer + description: Error code + status: + type: string + description: Error status + errors: + type: array + items: + type: string + description: List of error messages + + AppLabel: + type: object + required: + - key + - value + properties: + key: + type: string + description: Label key + value: + type: string + description: Label value + propagate: + type: boolean + description: Whether to propagate to kubernetes resources + + App: + type: object + required: + - appName + properties: + id: + type: integer + format: int64 + description: Application ID + appName: + type: string + description: Name of the application + teamId: + type: integer + format: int64 + description: Team ID + labels: + type: array + items: + $ref: '#/components/schemas/AppLabel' + description: Application labels + description: + type: string + description: Application description + projectIds: + type: array + items: + type: integer + format: int64 + description: IDs of projects this application belongs to + + CreateAppRequest: + type: object + required: + - metadata + properties: + metadata: + $ref: '#/components/schemas/App' + appWorkflows: + type: array + description: App workflows + items: + type: object + environmentOverrides: + type: array + description: Environment overrides + items: + type: object + + AppListingRequest: + type: object + properties: + teamIds: + type: array + items: + type: integer + format: int64 + description: Filter by team IDs + environmentIds: + type: array + items: + type: integer + format: int64 + description: Filter by environment IDs + statuses: + type: array + items: + type: string + enum: [Healthy, Degraded, Failed, Progressing] + description: Filter by application statuses + appNameSearch: + type: string + description: Search term for application name + offset: + type: integer + description: Pagination offset + size: + type: integer + description: Page size + projectIds: + type: array + items: + type: integer + format: int64 + description: Filter by project IDs + + AppListResponse: + type: object + properties: + code: + type: integer + description: Status code + status: + type: string + description: Status message + result: + type: object + properties: + appCount: + type: integer + description: Total number of applications matching the filters + appContainers: + type: array + items: + $ref: '#/components/schemas/AppContainer' + deploymentGroup: + $ref: '#/components/schemas/DeploymentGroup' + + AppContainer: + type: object + properties: + appId: + type: integer + format: int64 + description: Application ID + appName: + type: string + description: Application name + environments: + type: array + items: + $ref: '#/components/schemas/AppEnvironment' + description: Environments where the application is deployed + + AppEnvironment: + type: object + properties: + environmentId: + type: integer + format: int64 + description: Environment ID + environmentName: + type: string + description: Environment name + status: + type: string + enum: [Healthy, Degraded, Failed, Progressing] + description: Application status in this environment + lastDeployed: + type: string + format: date-time + description: Last deployment timestamp + + DeploymentGroup: + type: object + properties: + id: + type: integer + format: int64 + description: Deployment group ID + name: + type: string + description: Deployment group name + applications: + type: array + items: + type: integer + format: int64 + description: IDs of applications in this deployment group + + AppDetails: + type: object + properties: + app: + $ref: '#/components/schemas/App' + environments: + type: array + items: + $ref: '#/components/schemas/AppEnvironment' + description: Environments where the application is deployed + ciConfig: + type: object + description: CI configuration + cdConfig: + type: object + description: CD configuration + + AppProjectUpdateRequest: + type: object + required: + - appId + - projectIds + properties: + appId: + type: integer + format: int64 + description: Application ID + projectIds: + type: array + items: + type: integer + format: int64 + description: IDs of projects to associate with the application diff --git a/specs/app_create_api.yaml b/specs/application/creation.yaml similarity index 97% rename from specs/app_create_api.yaml rename to specs/application/creation.yaml index ca95476cc9..6be90f226d 100644 --- a/specs/app_create_api.yaml +++ b/specs/application/creation.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: Create App Api paths: - /orchestrator/core/v1beta1/application/{appId}: + /core/v1beta1/application/{appId}: get: description: Get all details of an app by appId. These details include - metadata(appName, projectNamr, labels), gitMaterials, docker config, templates, workflows, configMaps, secrets, environment override configurations. operationId: GetAppAllDetail @@ -108,7 +108,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/core/v1beta1/application: + /core/v1beta1/application: post: description: Creates a new app for the configurations provided. The input json object is the same we get in response of GET method for fetching all details of an app operationId: CreateApp @@ -121,11 +121,21 @@ paths: $ref: '#/components/schemas/AppDetail' responses: '200': - description: Successfully return a message stating the operation is successful. + description: Successfully created the application content: application/json: schema: - type: string + type: object + properties: + code: + type: integer + description: HTTP status code + status: + type: string + description: Status message + result: + type: string + description: Success message '400': description: Bad Request. Validation error/wrong request body. content: diff --git a/specs/app-labels.yaml b/specs/application/labels.yaml similarity index 65% rename from specs/app-labels.yaml rename to specs/application/labels.yaml index df657b401c..6881d08710 100644 --- a/specs/app-labels.yaml +++ b/specs/application/labels.yaml @@ -21,15 +21,9 @@ paths: type: string description: status result: - allOf: - - type: object - properties: - appId: - type: integer - description: unique application id - required: - - appId - - $ref: '#/components/schemas/AppLabel' + type: array + items: + $ref: '#/components/schemas/AppLabel' default: description: unexpected error content: @@ -62,8 +56,6 @@ paths: type: string description: status result: - type: object - description: meta info project name and labels $ref: '#/components/schemas/AppMetaInfo' default: description: unexpected error @@ -71,6 +63,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' + /orchestrator/helm/meta/info/{appId}: get: description: application info for all types of helm apps @@ -95,9 +88,22 @@ paths: type: string description: status result: - type: object - description: meta info project name and labels - $ref: '#/components/schemas/AppMetaInfo' + allOf: + - $ref: '#/components/schemas/AppMetaInfo' + - type: object + properties: + chartUsed: + $ref: '#/components/schemas/ChartUsed' + gitMaterials: + type: array + items: + $ref: '#/components/schemas/GitMaterialMeta' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' # components mentioned below components: @@ -107,6 +113,7 @@ components: required: - key - value + - propagate properties: key: type: string @@ -118,20 +125,6 @@ components: type: boolean description: Whether to propagate to kubernetes resources - AppLabels: - type: object - required: - - appId - - labels - properties: - appId: - type: integer - description: application id - labels: - type: array - items: - $ref: '#/components/schemas/AppLabel' - AppMetaInfo: type: object required: @@ -141,7 +134,7 @@ components: - projectName - createdOn - createdBy - - labels + - active properties: appId: type: integer @@ -155,16 +148,81 @@ components: projectName: type: string description: team/project name + description: + type: string + description: app description labels: type: array items: $ref: '#/components/schemas/AppLabel' createdOn: type: string + format: date-time description: app creation date createdBy: type: string description: app created by + active: + type: boolean + description: whether app is active + note: + $ref: '#/components/schemas/GenericNoteResponse' + + ChartUsed: + type: object + properties: + appStoreChartName: + type: string + description: Name of the chart from app store + appStoreChartId: + type: integer + description: ID of the chart from app store + appStoreAppName: + type: string + description: Name of the app in app store + appStoreAppVersion: + type: string + description: Version of the app in app store + chartAvatar: + type: string + description: Avatar/icon of the chart + + GitMaterialMeta: + type: object + properties: + displayName: + type: string + description: Display name of the git material + redirectionUrl: + type: string + description: HTTPS URL for redirection + originalUrl: + type: string + description: Original git URL + + GenericNoteResponse: + type: object + properties: + id: + type: integer + description: Note ID + note: + type: string + description: Note content + createdOn: + type: string + format: date-time + description: Creation timestamp + createdBy: + type: string + description: Creator's email + updatedOn: + type: string + format: date-time + description: Last update timestamp + updatedBy: + type: string + description: Last updater's email ErrorResponse: required: diff --git a/specs/applisting.yaml b/specs/application/listing.yaml similarity index 57% rename from specs/applisting.yaml rename to specs/application/listing.yaml index c888185926..f5215ee4af 100644 --- a/specs/applisting.yaml +++ b/specs/application/listing.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: Devtron Labs paths: - /orchestrator/app/autocomplete: + /app/autocomplete: get: description: list of namespaces group by clusters parameters: @@ -60,6 +60,69 @@ components: name: type: string description: app name + teamId: + type: integer + description: project id + teamName: + type: string + description: project name + active: + type: boolean + description: whether app is active + createdOn: + type: string + format: date-time + description: creation timestamp + createdBy: + type: string + description: creator's name + updatedOn: + type: string + format: date-time + description: last update timestamp + material: + type: array + description: git materials + items: + $ref: '#/components/schemas/GitMaterial' + labels: + type: array + description: app labels + items: + $ref: '#/components/schemas/AppLabel' + AppLabel: + type: object + properties: + key: + type: string + description: label key + value: + type: string + description: label value + propagate: + type: boolean + description: whether to propagate to kubernetes resources + GitMaterial: + type: object + properties: + id: + type: integer + description: material id + gitProviderId: + type: integer + description: git provider id + gitProviderUrl: + type: string + description: git provider url + gitRepoUrl: + type: string + description: git repository url + checkoutPath: + type: string + description: checkout path + fetchSubmodules: + type: boolean + description: whether to fetch submodules ErrorResponse: required: - code diff --git a/specs/historical-get-api-change.yaml b/specs/audit/api-changes.yaml similarity index 78% rename from specs/historical-get-api-change.yaml rename to specs/audit/api-changes.yaml index 7ad6d05e79..40d74533d0 100644 --- a/specs/historical-get-api-change.yaml +++ b/specs/audit/api-changes.yaml @@ -177,65 +177,116 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' + components: schemas: HistoryComponentDetailDto: type: object properties: - values: - type: array - items: - $ref: '#/components/schemas/HistoryComponentValuesDto' - codeEditorValue: - type: object - properties: - displayName: - type: string - value: - type: string - HistoryComponentValuesDto: - type: object - properties: - fieldName: - type: object - properties: - displayName: - type: string - value: - type: string + id: + type: integer + pipelineId: + type: integer + dataType: + type: string + configData: + $ref: '#/components/schemas/ConfigData' + deployed: + type: boolean + deployedOn: + type: string + format: timestamp + deployedBy: + type: integer + HistoryComponentListDto: type: object properties: id: type: integer + pipelineId: + type: integer + dataType: + type: string + configData: + $ref: '#/components/schemas/ConfigData' + deployed: + type: boolean deployedOn: type: string format: timestamp deployedBy: - type: string - deploymentStatus: - type: string + type: integer + HistoryConfigurationListDto: - type: array - items: - $ref: '#/components/schemas/HistoryConfiguration' - HistoryConfiguration: type: object properties: id: type: integer + pipelineId: + type: integer + dataType: + type: string + configData: + $ref: '#/components/schemas/ConfigData' + deployed: + type: boolean + deployedOn: + type: string + format: timestamp + deployedBy: + type: integer + + ConfigData: + type: object + properties: name: type: string - enum: - - "DEPLOYMENT_TEMPLATE" - - "CONFIGMAP" - - "SECRET" - - "PIPELINE_STRATEGY" - childList: + type: + type: string + external: + type: boolean + mountPath: + type: string + data: + type: string + defaultData: + type: string + defaultMountPath: + type: string + global: + type: boolean + externalType: + type: string + secretData: type: array items: - type: string + $ref: '#/components/schemas/ExternalSecret' + defaultSecretData: + type: array + items: + $ref: '#/components/schemas/ExternalSecret' + roleArn: + type: string + subPath: + type: boolean + filePermission: + type: string + + ExternalSecret: + type: object + properties: + key: + type: string + name: + type: string + property: + type: string + isBinary: + type: boolean + Error: + type: object required: - code - message diff --git a/specs/audit/definitions.yaml b/specs/audit/definitions.yaml new file mode 100644 index 0000000000..63c8ea4651 --- /dev/null +++ b/specs/audit/definitions.yaml @@ -0,0 +1,299 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Historical Task definitions +paths: + /orchestrator/app/history/deployed-component/detail/{appId}/{pipelineId}/{id}: + get: + description: fetch detail of a history on the basis of the history component and it's name + operationId: FetchDeployedHistoryComponentDetail + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + - name: id + in: path + required: true + schema: + type: integer + - name: historyComponent + in: query + required: true + schema: + type: string + enum: + - "DEPLOYMENT_TEMPLATE" + - "CONFIGMAP" + - "SECRET" + - "PIPELINE_STRATEGY" + - name: historyComponentName + in: query + required: false + description: name of config-map, secret + schema: + type: string + responses: + '200': + description: Successfully return history + content: + application/json: + schema: + $ref: '#/components/schemas/HistoryComponentDetailDto' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/app/history/deployed-component/list/{appId}/{pipelineId}: + get: + description: fetch deployed history details list + operationId: FetchDeployedHistoryComponentList + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + - name: historyComponent + in: query + required: true + schema: + type: string + enum: + - "DEPLOYMENT_TEMPLATE" + - "CONFIGMAP" + - "SECRET" + - "PIPELINE_STRATEGY" + - name: historyComponentName + in: query + required: false + description: name of config-map, secret + schema: + type: string + - name: baseConfigurationId + in: query + required: true + description: id of base configuration + schema: + type: integer + responses: + '200': + description: Successfully return history list + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/HistoryComponentListDto' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/app/history/deployed-configuration/{appId}/{pipelineId}/{wfrId}: + get: + description: fetch all deployed configurations history (deployment template, pipeline strategy, configmaps, secrets) + operationId: FetchDeployedConfigurationsForWorkflow + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + - name: wfrId + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully return history + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/HistoryConfigurationListDto' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + HistoryComponentDetailDto: + type: object + properties: + id: + type: integer + pipelineId: + type: integer + dataType: + type: string + configData: + $ref: '#/components/schemas/ConfigData' + deployed: + type: boolean + deployedOn: + type: string + format: timestamp + deployedBy: + type: integer + + HistoryComponentListDto: + type: object + properties: + id: + type: integer + pipelineId: + type: integer + dataType: + type: string + configData: + $ref: '#/components/schemas/ConfigData' + deployed: + type: boolean + deployedOn: + type: string + format: timestamp + deployedBy: + type: integer + + HistoryConfigurationListDto: + type: object + properties: + id: + type: integer + pipelineId: + type: integer + dataType: + type: string + configData: + $ref: '#/components/schemas/ConfigData' + deployed: + type: boolean + deployedOn: + type: string + format: timestamp + deployedBy: + type: integer + + ConfigData: + type: object + properties: + name: + type: string + type: + type: string + external: + type: boolean + mountPath: + type: string + data: + type: string + defaultData: + type: string + defaultMountPath: + type: string + global: + type: boolean + externalType: + type: string + secretData: + type: array + items: + $ref: '#/components/schemas/ExternalSecret' + defaultSecretData: + type: array + items: + $ref: '#/components/schemas/ExternalSecret' + roleArn: + type: string + subPath: + type: boolean + filePermission: + type: string + + ExternalSecret: + type: object + properties: + key: + type: string + name: + type: string + property: + type: string + isBinary: + type: boolean + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/batch.yaml b/specs/batch.yaml deleted file mode 100644 index a1ce08955c..0000000000 --- a/specs/batch.yaml +++ /dev/null @@ -1,541 +0,0 @@ -components: - schemas: - buildMaterial: - type: object - required: - - source - - gitMaterialUrl - properties: - source: - type: object - required: - - type - - value - properties: - type: - type: string - value: - type: string - enum: - - BranchFixed - - BranchRegex - - TagAny - - TagRegex - gitMaterialUrl: - type: string - dockerConfig: - type: object - required: - - dockerFilePath - - dockerFileRepository - - dockerFileRelativePath - - gitMaterial - - args - properties: - dockerFilePath: - type: string - dockerFileRepository: - type: string - dockerFileRelativePath: - type: string - gitMaterial: - type: string - args: - type: object - app: - description: Application configuration - type: object - required: - - apiVersion - - operation - - team - - repo - - dockerConfig - - dockerRegistry - - dockerRepo - - configMaps - - secrets - properties: - apiVersion: - description: API version of this configuration - type: string - source: - description: Optionally mention the source from where to clone, in case operation is clone and source is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - destination: - description: Optionally mention the destination, in case operation is clone/update/delete and destination is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - operation: - description: Action to be taken on this component. This is used along with source and destination of pipeline. - $ref: '#/components/schemas/operation' - workflow: - type: array - description: Workflow for app - items: - $ref: '#/components/schemas/workflow' - team: - type: string - repo: - type: array - items: - $ref: '#/components/schemas/repo' - dockerRegistry: - type: string - dockerRepo: - type: string - dockerConfig: - $ref: '#/components/schemas/dockerConfig' - configMaps: - type: array - items: - $ref: '#/components/schemas/dataHolder' - secrets: - type: array - items: - $ref: '#/components/schemas/dataHolder' - workflow: - description: Workflow of the application - type: object - required: - - apiVersion - - operation - properties: - apiVersion: - description: API version of this configuration - type: string - source: - description: Optionally mention the source from where to clone, in case operation is clone and source is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - destination: - description: Optionally mention the destination, in case operation is clone/update/delete and destination is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - operation: - description: Action to be taken on this component. This is used along with source and destination of pipeline. - $ref: '#/components/schemas/operation' - pipelines: - type: array - description: Entries can be of type build or deployment - items: - $ref: '#/components/schemas/pipeline' - deploymentStrategy: - description: Strategy as defined by devtron template, this overrides at environment level - type: object - required: - - default - properties: - blueGreen: - $ref: '#/components/schemas/blueGreenStrategy' - canary: - $ref: '#/components/schemas/canaryStrategy' - rolling: - $ref: '#/components/schemas/rollingStrategy' - recreate: - $ref: '#/components/schemas/recreateStrategy' - default: - type: string - enum: - - BLUE-GREEN - - ROLLING - - CANARY - - RECREATE - inheritedProps: - type: object - required: - - operation - properties: - source: - $ref: '#/components/schemas/resourcePath' - destination: - $ref: '#/components/schemas/resourcePath' - operation: - $ref: '#/components/schemas/operation' - blueGreenStrategy: - type: object - required: - - autoPromotionSeconds - - scaleDownDelaySeconds - - previewReplicaCount - - autoPromotionEnabled - properties: - autoPromotionSeconds: - type: integer - format: int32 - scaleDownDelaySeconds: - type: integer - format: int32 - previewReplicaCount: - type: integer - format: int32 - autoPromotionEnabled: - type: boolean - canaryStrategy: - type: object - required: - - maxSurge - - maxUnavailable - - steps - properties: - maxSurge: - type: string - maxUnavailable: - type: integer - format: int32 - steps: - type: array - items: - setWeight: - type: integer - format: int32 - pause: - type: object - properties: - duration: - type: integer - format: int32 - recreateStrategy: - type: object - rollingStrategy: - type: object - required: - - maxSurge - - maxUnavailable - properties: - maxSurge: - type: string - maxUnavailable: - type: integer - format: int32 - pipeline: - type: object - properties: - build: - $ref: '#/components/schemas/build' - deployment: - $ref: '#/components/schemas/deployment' - operation: - type: string - description: Action to be taken on the component - enum: - - create - - delete - - update - - append - - clone - trigger: - type: string - description: How will this action be initiated - enum: - - manual - - automatic - resourcePath: - description: Unique identification of resource - type: object - properties: - app: - type: string - workflow: - type: string - pipeline: - type: string - configMap: - type: string - secret: - type: string - environment: - type: string - uid: - type: string - repo: - description: git repo to use in this build - type: object - properties: - url: - description: git url - type: string - branch: - description: branch to build - type: string - path: - description: path to checkout - type: string - stage: - type: object - required: - - operation - - name - properties: - operation: - $ref: '#/components/schemas/operation' - name: - type: string - position: - type: integer - format: int32 - script: - type: string - outputLocation: - type: string - task: - type: object - required: - - apiVersion - - operation - - stages - - configMaps - - secrets - properties: - apiVersion: - description: API version of this configuration - type: string - source: - description: Optionally mention the source from where to clone, in case operation is clone and source is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - destination: - description: Optionally mention the destination, in case operation is clone/update/delete and destination is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - operation: - description: Action to be taken on this component. This is used along with source and destination of pipeline. - $ref: '#/components/schemas/operation' - stages: - description: Different stages in this step - type: array - items: - $ref: '#/components/schemas/stage' - trigger: - $ref: '#/components/schemas/trigger' - configMaps: - type: array - items: - type: string - secrets: - type: array - items: - type: string - dataHolder: - type: object - required: - - operation - - data - - apiVersion - - type - - global - - externalType - - mountPath - - external - properties: - apiVersion: - description: API version of this configuration - type: string - operation: - description: Action to be taken on this component. This is used along with source and destination of pipeline. In case operation is delete then only source or destination can be present. If source is present then its skipping in cloning, if destination is present then it is deleted from database. - $ref: '#/components/schemas/operation' - type: - type: string - external: - type: boolean - mountPath: - type: string - global: - type: boolean - externalType: - type: string - source: - description: Optionally mention the source from where to clone, in case operation is clone and source is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - destination: - description: Optionally mention the destination, in case operation is clone/update/delete and destination is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - data: - description: If operation is clone, leaving value empty results in deletion of key in destination. - type: object - preBuild: - $ref: '#/components/schemas/task' - postBuild: - $ref: '#/components/schemas/task' - build: - type: object - required: - - apiVersion - - operation - - dockerArguments - - repo - - trigger - - buildMaterials - properties: - apiVersion: - description: API version of this configuration - type: string - source: - description: Optionally mention the source from where to clone, in case operation is clone and source is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - destination: - description: Optionally mention the destination, in case operation is clone/update/delete and destination is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - repo: - type: array - items: - $ref: '#/components/schemas/repo' - operation: - description: Action to be taken on this component. This is used along with source and destination of pipeline. - $ref: '#/components/schemas/operation' - dockerArguments: - type: object - trigger: - $ref: '#/components/schemas/trigger' - preBuild: - $ref: '#/components/schemas/task' - postBuild: - $ref: '#/components/schemas/task' - nextPipeline: - description: This can be either of type build or deployment - $ref: '#/components/schemas/pipeline' - webHookUrl: - type: string - payload: - type: string - accessKey: - type: string - buildMaterials: - type: array - items: - $ref: '#/components/schemas/buildMaterial' - preDeployment: - $ref: '#/components/schemas/task' - postDeployment: - $ref: '#/components/schemas/task' - deployment: - type: object - required: - - apiVersion - - operation - - configMaps - - secrets - - strategy - - runPostStageInEnv - - runPreStageInEnv - properties: - apiVersion: - description: API version of this configuration - type: string - source: - description: Optionally mention the source from where to clone, in case operation is clone and source is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - destination: - description: Optionally mention the destination, in case operation is clone/update/delete and destination is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - operation: - description: Action to be taken on this component. This is used along with source and destination of pipeline. - $ref: '#/components/schemas/operation' - trigger: - $ref: '#/components/schemas/trigger' - template: - description: Deployment template as defined by devtron template, these are applied at environment level - $ref: '#/components/schemas/deploymentTemplate' - strategy: - $ref: '#/components/schemas/deploymentStrategy' - configMaps: - description: These are applied for environment - type: array - items: - $ref: '#/components/schemas/dataHolder' - secrets: - description: These are applied for environment - type: array - items: - $ref: '#/components/schemas/dataHolder' - postDeployment: - $ref: '#/components/schemas/task' - preDeployment: - $ref: '#/components/schemas/task' - previousPipeline: - description: This can be either of type build or deployment - $ref: '#/components/schemas/pipeline' - nextPipeline: - description: This can be either of type build or deployment - $ref: '#/components/schemas/pipeline' - runPostStageInEnv: - type: boolean - runPreStageInEnv: - type: boolean - pipelineRequest: - type: object - required: - - apiVersion - - pipelines - properties: - apiVersion: - description: API version of this configuration - type: string - pipelines: - type: array - description: Entries can be of type build or deployment - items: - $ref: '#/components/schemas/pipeline' - configMaps: - $ref: '#/components/schemas/dataHolder' - secrets: - $ref: '#/components/schemas/dataHolder' - deploymentTemplate: - type: object - required: - - apiVersion - - operation - - refChartTemplate - - refChartTemplateVersion - - chartRefId - - isAppMetricsEnabled - - valuesOverride - - defaultAppOverride - properties: - apiVersion: - description: API version of this configuration - type: string - source: - description: Optionally mention the source from where to clone, in case operation is clone and source is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - destination: - description: Optionally mention the destination, in case operation is clone/update/delete and destination is missing it is inherited from parent pipeline. - $ref: '#/components/schemas/resourcePath' - operation: - description: Action to be taken on this component. This is used along with source and destination of pipeline. - $ref: '#/components/schemas/operation' - refChartTemplate: - type: string - refChartTemplateVersion: - type: string - chartRefId: - type: integer - format: int32 - isAppMetricsEnabled: - type: boolean - defaultAppOverride: - type: object - valuesOverride: - type: object - - -paths: - /batch/pipeline: - post: - requestBody: - description: payload to generate temporary token for this user - content: - 'application/json': - schema: - pipelineRequest: - $ref: '#/components/schemas/pipelineRequest' - responses: - '200': - description: token generated successfully - result: - type: object - properties: - success: - type: string - /batch/workflow: - get: - - post: - - - diff --git a/specs/buildInfraConfig/build-infra-config.yaml b/specs/buildInfraConfig/build-infra-config.yaml index 4698196884..e9ecca898b 100644 --- a/specs/buildInfraConfig/build-infra-config.yaml +++ b/specs/buildInfraConfig/build-infra-config.yaml @@ -5,20 +5,45 @@ info: version: 1.0.0 servers: - url: 'https' + paths: -# send 404 responses if resource doesn't exist - /orchestrator/infra-config/profile/{name}: + /infra-config/profile: get: description: Get Infra Profile by name + parameters: + - name: name + in: query + required: true + schema: + type: string + pattern: '^[a-z]+$' responses: "200": - description: gets the infra config profile by its name. + description: Gets the infra config profile by its name content: application/json: schema: - $ref: "#/components/schemas/ProfileResponse" + $ref: "#/components/schemas/ProfileResponse" + "400": + description: Invalid profile name + "401": + description: Unauthorized + "403": + description: Forbidden + "404": + description: Profile not found + "500": + description: Internal Server Error + put: description: Update Infra Profile + parameters: + - name: name + in: query + required: true + schema: + type: string + pattern: '^[a-z]+$' requestBody: required: true content: @@ -27,17 +52,23 @@ paths: $ref: '#/components/schemas/Profile' responses: "200": - description: creates a infra config profile. - content: - application/json: - schema: - $ref: "#/components/schemas/Profile" - + description: Successfully updated infra config profile + "400": + description: Invalid request payload + "401": + description: Unauthorized + "403": + description: Forbidden + "500": + description: Internal Server Error components: schemas: Unit: type: object + required: + - name + - conversionFactor properties: name: type: string @@ -49,112 +80,269 @@ components: example: 1 ConfigurationUnits: - type: object - properties: - name: - type: string - description: Configuration Units - units: - type: array - description: Configuration Units - items: - $ref: '#/components/schemas/Unit' - ProfileResponse: type: object + required: + - name + - units properties: - configurationUnits: + name: + type: string + description: Configuration Units + units: type: array description: Configuration Units items: + $ref: '#/components/schemas/Unit' + + ProfileResponse: + type: object + required: + - profile + - configurationUnits + - defaultConfigurations + properties: + profile: + $ref: '#/components/schemas/Profile' + configurationUnits: + type: object + additionalProperties: $ref: '#/components/schemas/ConfigurationUnits' defaultConfigurations: type: array - description: Default Configurations items: $ref: '#/components/schemas/Configuration' - profile: - $ref: '#/components/schemas/Profile' + Profile: + type: object + required: + - configurations + - targetPlatforms + properties: + configurations: + type: array + items: + $ref: '#/components/schemas/Configuration' + targetPlatforms: + type: array + items: + type: string + + Configuration: + type: object + required: + - key + - value + properties: + key: + type: string + description: Property Name + example: "cpu_limits" + value: + type: string + description: Property Value + example: "0.5"openapi: 3.0.3 +info: + title: Infra Config + description: API SPEC for Infra Configurations + version: 1.0.0 +servers: + - url: 'https' + +paths: + /infra-config/profile: + get: + description: Get Infra Profile by name + parameters: + - name: name + in: query + required: true + schema: + type: string + pattern: '^[a-z]+$' + responses: + "200": + description: Gets the infra config profile by its name + content: + application/json: + schema: + $ref: "#/components/schemas/ProfileResponse" + "400": + description: Invalid profile name + "401": + description: Unauthorized + "403": + description: Forbidden + "404": + description: Profile not found + "500": + description: Internal Server Error + + put: + description: Update Infra Profile + parameters: + - name: name + in: query + required: true + schema: + type: string + pattern: '^[a-z]+$' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + responses: + "200": + description: Successfully updated infra config profile + "400": + description: Invalid request payload + "401": + description: Unauthorized + "403": + description: Forbidden + "500": + description: Internal Server Error +components: + schemas: + Unit: + type: object + required: + - name + - conversionFactor + properties: + name: + type: string + description: Unit Name + example: "mi" + conversionFactor: + type: number + description: Conversion Factor to convert to base unit + example: 1 + ConfigurationUnits: + type: object + required: + - name + - units + properties: + name: + type: string + description: Configuration Units + units: + type: array + description: Configuration Units + items: + $ref: '#/components/schemas/Unit' + ProfileResponse: + type: object + required: + - profile + - configurationUnits + - defaultConfigurations + properties: + profile: + $ref: '#/components/schemas/Profile' + configurationUnits: + type: object + additionalProperties: + $ref: '#/components/schemas/ConfigurationUnits' + defaultConfigurations: + type: array + items: + $ref: '#/components/schemas/Configuration' + Profile: + type: object + required: + - configurations + - targetPlatforms + properties: + id: + type: integer + description: Profile Id + example: 1 + name: + type: string + description: Profile Name + example: "java" + description: + type: string + description: Profile Description + example: "all java apps should have this infra profile" + type: + type: string + description: Type of profile (DEFAULT, NORMAL, CUSTOM) + enum: [DEFAULT, NORMAL, CUSTOM] + example: "CUSTOM" + configurations: + type: array + description: Profile Configurations + items: + $ref: '#/components/schemas/Configuration' + targetPlatforms: + type: array + description: List of target platforms for this profile + items: + type: string + example: "linux/amd64" + appCount: + readOnly: true + type: integer + description: Number of apps using this profile + example: 1 + createdAt: + type: string + format: date-time + description: Profile creation timestamp + example: "2021-06-01T06:30:00.000Z" + updatedAt: + type: string + format: date-time + description: Profile last update timestamp + example: "2021-06-01T06:30:00.000Z" + createdBy: + type: integer + description: User ID who created the profile + example: 1 + updatedBy: + type: integer + description: User ID who last updated the profile + example: 1 Configuration: type: object + required: + - key + - value properties: id: type: integer - description: Property Id + description: Configuration ID example: 1 key: type: string - description: Property Name - required: true, + description: Configuration key example: "cpu_limits" value: - required: true, type: string - description: Property Value + description: Configuration value example: "0.5" profileName: type: string - description: Profile Name + description: Name of the profile this configuration belongs to example: "java" unit: type: string - description: Property Unit + description: Unit of the configuration value example: "m" active: type: boolean - description: Property Active + description: Whether the configuration is active example: true - - Profile: - type: object - properties: - id: - type: integer - description: Profile Id - example: 1 - name: - type: string - description: Profile Name - example: "java" - description: - type: string - description: Profile Description - example: "all java apps should have this infra profile" - type: - type: string - description: type of profile "eg:0,1,2" - example: DEFAULT,NORMAL,CUSTOM - configurations: - type: array - description: Profile Configurations - items: - $ref: '#/components/schemas/Configuration' - appCount: - readOnly: true - type: integer - description: Number of apps using this profile - example: 1 - createdAt: - required: false - type: string - description: Profile Created At - example: "2021-06-01T06:30:00.000Z" - updatedAt: - type: string - description: Profile Updated At - example: "2021-06-01T06:30:00.000Z" - createdBy: - type: integer - description: Profile Created By - example: 1 - updatedBy: - type: integer - description: Profile Updated By - example: 1 - - + platform: + type: string + description: Target platform for this configuration + example: "linux/amd64" diff --git a/specs/bulk_actions.yaml b/specs/bulk_actions.yaml deleted file mode 100644 index 8c1c7f57b8..0000000000 --- a/specs/bulk_actions.yaml +++ /dev/null @@ -1,155 +0,0 @@ -openapi: "3.0.0" -info: - version: 1.0.0 - title: Bulk Actions - Hibernate, UnHibernate, Deploy Latest Builds -servers: - - url: http://localhost:3000/orchestrator/batch -paths: - /v1beta1/hibernate: - post: - description: Bulk Hibernate all apps for specific environment - operationId: BulkHibernate - requestBody: - description: bulk hibernate - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionPayload' - responses: - '200': - description: Successfully hibernated all impacted apps. - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionPayload' - '400': - description: Bad Request. Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /v1beta1/unhibernate: - post: - description: Bulk Unhibernate all apps for specific environment - operationId: BulkUnhibernate - requestBody: - description: bulk unhibernate - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionPayload' - responses: - '200': - description: Successfully unhibernated all impacted apps. - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionPayload' - '400': - description: Bad Request. Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /v1beta1/deploy: - post: - description: Bulk Deploy all apps to the latest build image for specific environment - operationId: BulkDeploy - requestBody: - description: bulk deploy - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionPayload' - responses: - '200': - description: Successfully deploy all impacted apps. - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionPayload' - '400': - description: Bad Request. Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - -components: - schemas: - BulkActionPayload: - type: object - required: envId - properties: - appIdIncludes: - type: array - items: - type: integer - appIdExcludes: - type: array - items: - type: integer - envId: - type: integer - description: environment id - - IdsIncludesExcludes: - type: object - properties: - ids: - type: array - items: - type: integer - description: app ids - - Error: - required: - - code - - message - properties: - code: - type: integer - description: Error code - message: - type: string - description: Error message \ No newline at end of file diff --git a/specs/change-deployment-chart-type.yaml b/specs/change-deployment-chart-type.yaml deleted file mode 100644 index 496352d04c..0000000000 --- a/specs/change-deployment-chart-type.yaml +++ /dev/null @@ -1,34 +0,0 @@ -openapi: "3.0.0" -info: - version: 1.0.0 - title: Devtron Labs -paths: - /orchestrator/app/env/patch: - patch: - description: change the deployment template for an app and environment - requestBody: - content: - application/json: - schema: - properties: - envId: - type: integer - appId: - type: integer - targetChartRefId: - type: integer - - responses: - '200': - description: patched data - content: - application/json: - schema: - properties: - '422': - description: bad request - content: - application/json: - schema: - userDetailedMessage: - type: string \ No newline at end of file diff --git a/specs/ci-pipeline/ci-pipeline-build-spec.yaml b/specs/ci-pipeline/ci-pipeline-build-spec.yaml index 288889ec01..3ed5387201 100644 --- a/specs/ci-pipeline/ci-pipeline-build-spec.yaml +++ b/specs/ci-pipeline/ci-pipeline-build-spec.yaml @@ -1,58 +1,301 @@ -openapi: "3.0.0" +openapi: 3.0.0 info: version: 1.0.0 - title: Modularisation v1 APIs + title: CI Pipeline Build API + description: API for managing CI pipeline builds and related operations + contact: + name: Devtron Support + url: https://devtron.ai + email: support@devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +servers: + - url: /orchestrator + description: Devtron Orchestrator API Server + paths: - /orchestrator/app/commit-info/{ciPipelineMaterialId}/{gitHash}: + /app/commit-info/{ciPipelineMaterialId}/{gitHash}: get: - description: Get commit info for a particular commit hash for a ci-pipeline-material + tags: + - Commit + summary: Get commit information + description: Retrieves commit information for a specific commit hash in a CI pipeline material + operationId: getCommitInfo parameters: - name: ciPipelineMaterialId - description: ci-pipeline-material id in: path + description: ID of the CI pipeline material required: true schema: type: integer + format: int32 + minimum: 1 + example: 123 - name: gitHash - description: git hash for that commit in: path + description: Git commit hash required: true schema: type: string + pattern: '^[a-f0-9]{7,40}$' + example: "a1b2c3d4e5" responses: - "200": - description: Successfully fetched commit info. if CommitInfo is null, then commit is not found. + '200': + description: Successfully retrieved commit information content: application/json: schema: type: array items: - $ref: "#/components/schemas/CommitInfo" + $ref: '#/components/schemas/CommitInfo' + '400': + description: Invalid input parameters + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '404': + description: Commit not found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + security: + - bearerAuth: [] + + /app/workflow/trigger/{pipelineId}: + post: + tags: + - Workflow + summary: Trigger CI workflow + description: Triggers a new CI workflow for the specified pipeline + operationId: triggerWorkflow + parameters: + - name: pipelineId + in: path + description: ID of the CI pipeline to trigger + required: true + schema: + type: integer + format: int32 + minimum: 1 + example: 456 + requestBody: + description: Workflow trigger payload + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/WorkflowTriggerRequest' + responses: + '200': + description: Workflow triggered successfully + content: + application/json: + schema: + $ref: '#/components/schemas/WorkflowResponse' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + security: + - bearerAuth: [] + + /app/workflow/{workflowId}: + get: + tags: + - Workflow + summary: Get workflow details + description: Retrieves details of a specific workflow + operationId: getWorkflow + parameters: + - name: workflowId + in: path + description: ID of the workflow + required: true + schema: + type: integer + format: int32 + minimum: 1 + example: 789 + responses: + '200': + description: Workflow details retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/WorkflowResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '404': + description: Workflow not found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + security: + - bearerAuth: [] -# Components components: schemas: CommitInfo: type: object + required: + - Commit + - Author + - Date properties: Commit: type: string - description: Commit hash - example: "somehash" + description: Full commit hash + example: "a1b2c3d4e5f6g7h8i9j0" + minLength: 7 + maxLength: 40 Author: type: string - description: Author of that commit - example: "manish" + description: Author of the commit + example: "John Doe " Date: type: string - description: Date that commit - example: "2021-08-10T16:28:26+05:30" + format: date-time + description: Timestamp of the commit + example: "2023-01-15T14:30:22Z" Message: type: string description: Commit message - example: "some message" + example: "Update README with new features" Changes: type: array - description: file names which were changed in this commit + description: List of files changed in this commit + items: + type: string + example: "src/main.go" + + WorkflowTriggerRequest: + type: object + required: + - commitHash + properties: + commitHash: + type: string + description: Specific commit hash to build (optional, defaults to latest) + example: "a1b2c3d4e5" + branchName: + type: string + description: Branch name (required if commitHash not provided) + example: "main" + ciBuildConfig: + $ref: '#/components/schemas/CIBuildConfig' + ciBuildType: + type: string + enum: [SELF_DOCKERFILE_BUILD_TYPE, MANIFEST_PUSH, SKIP_BUILD] + default: "SELF_DOCKERFILE_BUILD_TYPE" + + CIBuildConfig: + type: object + properties: + dockerBuildConfig: + $ref: '#/components/schemas/DockerBuildConfig' + ciBuildType: + type: string + enum: [SELF_DOCKERFILE_BUILD_TYPE, MANIFEST_PUSH, SKIP_BUILD] + + DockerBuildConfig: + type: object + properties: + dockerfilePath: + type: string + example: "./Dockerfile" + args: + type: object + additionalProperties: + type: string + + WorkflowResponse: + type: object + properties: + id: + type: integer + format: int64 + example: 12345 + name: + type: string + example: "workflow-12345" + status: + type: string + enum: [QUEUED, RUNNING, SUCCEEDED, FAILED, ABORTED] + example: "QUEUED" + startTime: + type: string + format: date-time + example: "2023-01-15T14:30:22Z" + endTime: + type: string + format: date-time + example: "2023-01-15T14:35:45Z" + triggeredBy: + type: string + example: "user@example.com" + + ApiError: + type: object + properties: + code: + type: integer + format: int32 + example: 404 + message: + type: string + example: "Resource not found" + details: + type: array items: - type: string \ No newline at end of file + type: string + example: ["Commit not found in the repository"] + + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: >- + JWT token for authentication. + Include the token in the Authorization header as: 'Bearer {token}' \ No newline at end of file diff --git a/specs/cluster_access_policy.yaml b/specs/cluster_access_policy.yaml deleted file mode 100644 index a8d71c2449..0000000000 --- a/specs/cluster_access_policy.yaml +++ /dev/null @@ -1,171 +0,0 @@ -openapi: "3.0.0" -info: - version: 1.0.0 - title: Cluster access policy -paths: - /orchestrator/user: - post: - summary: Creates a new User - operationId: addUser - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/User' - responses: - '200': - description: create user response - content: - application/json: - schema: - $ref: '#/components/schemas/User' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - put: - summary: update user - operationId: updateUser - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/User' - responses: - '200': - description: user response - content: - application/json: - schema: - $ref: '#/components/schemas/User' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/role/group: - post: - summary: Creates a new role group - operationId: addUser - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RoleGroup' - responses: - '200': - description: create user response - content: - application/json: - schema: - $ref: '#/components/schemas/RoleGroup' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - put: - summary: update user - operationId: updateUser - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RoleGroup' - responses: - '200': - description: user response - content: - application/json: - schema: - $ref: '#/components/schemas/RoleGroup' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - -components: - schemas: - User: - type: object - required: - - email_id - properties: - id: - type: integer - description: Unique id of user - email_id: - type: string - description: Unique valid email-id of user, comma separated emails ids for multiple users - groups: - type: array - items: - type: string - roleFilters: - type: array - items: - $ref: '#/components/schemas/roleFilter' - description: role filters objects - RoleGroup: - type: object - properties: - id: - type: integer - name: - type: string - roleFilters: - type: array - items: - $ref: '#/components/schemas/roleFilter' - description: role filters objects - roleFilter: - type: object - required: - - action - properties: - cluster: - type: string - description: cluster name - namespace: - type: string - description: namespace names. for multiple selection comma separated values, for all selection an empty string. - group: - type: string - description: group names. for multiple selection comma separated values, for all selection an empty string. - kind: - type: string - description: kind names. for multiple selection comma separated values, for all selection an empty string. - resource: - type: string - description: resource names. for multiple selection comma separated values, for all selection an empty string. - action: - type: string - description: action is type of role, i.e, admin, trigger, view, etc. - enum: ["view","edit","admin"] - Error: - required: - - code - - message - properties: - code: - type: integer - format: int32 - description: Error code - message: - type: string - description: Error message \ No newline at end of file diff --git a/specs/cluster_add_api_specs.yaml b/specs/cluster_add_api_specs.yaml deleted file mode 100644 index 4c1c019088..0000000000 --- a/specs/cluster_add_api_specs.yaml +++ /dev/null @@ -1,167 +0,0 @@ -openapi: 3.0.0 -info: - title: Cluster API - version: 1.0.0 - description: API for managing clusters - -paths: - /orchestrator/cluster/validate: - post: - description: Validate a cluster - requestBody: - content: - application/json: - schema: - type: object - properties: - kubeconfig: - $ref: '#/components/schemas/Kubeconfig' - required: - - kubeconfig - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ValidateClusterBean' - '400': - description: Bad request - '500': - description: Internal server error - /orchestrator/cluster/saveClusters: - post: - description: Save clusters - requestBody: - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ValidateClusterBean' - responses: - '200': - description: OK - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ValidateClusterBean' - '400': - description: Bad request - '500': - description: Internal server error -components: - schemas: - Kubeconfig: - type: object - properties: - config: - type: string - ValidateClusterBean: - type: object - properties: - userInfos: - type: object - additionalProperties: - $ref: '#/components/schemas/UserInfos' - id: - type: integer - cluster_name: - type: string - server_url: - type: string - prometheus_url: - type: string - active: - type: boolean - config: - type: object - properties: - bearer_token: - type: string - description: it will be empty while fetching, and if no change while updating - tls_key: - type: string - description: it will be empty while fetching, and if no change while updating - cert_data: - type: string - description: it will be empty while fetching, and if no change while updating - cert_auth_data: - type: string - description: it will be empty while fetching, and if no change while updating - prometheusAuth: - $ref: '#/components/schemas/PrometheusAuth' - defaultClusterComponent: - type: array - items: - $ref: '#/components/schemas/DefaultClusterComponent' - agentInstallationStage: - type: integer - k8sVersion: - type: string - userName: - type: string - insecure-skip-tls-verify: - type: boolean - required: - - cluster_name - - server_url - UserInfos: - type: object - properties: - userName: - type: string - config: - type: object - additionalProperties: - type: string - errorInConnecting: - type: string - PrometheusAuth: - type: object - properties: - type: - type: string - enum: - - basic - - bearer - basic: - type: object - properties: - username: - type: string - password: - type: string - bearer: - type: object - properties: - token: - type: string - DefaultClusterComponent: - type: object - properties: - id: - type: string - name: - type: string - version: - type: string - status: - type: string - configuration: - $ref: '#/components/schemas/Configuration' - Configuration: - type: object - properties: - type: - type: string - enum: - - yaml - - json - - - - - diff --git a/specs/api-spec.yaml b/specs/common/api-spec.yaml similarity index 91% rename from specs/api-spec.yaml rename to specs/common/api-spec.yaml index ef6e7c6fdf..229b4efe6f 100644 --- a/specs/api-spec.yaml +++ b/specs/common/api-spec.yaml @@ -90,10 +90,18 @@ components: type: string description: Values yaml example: "some values yaml" + chartData: + type: string + format: byte + description: Chart Data in case of base deployment template TemplateChartResponse: type: object properties: manifest: type: string description: helm generated manifest - example: "some manifest" \ No newline at end of file + example: "some manifest" + chartBytes: + type: string + format: byte + description: Chart bytes data \ No newline at end of file diff --git a/specs/delete-options.yaml b/specs/common/delete-options.yaml similarity index 100% rename from specs/delete-options.yaml rename to specs/common/delete-options.yaml diff --git a/specs/version.yml b/specs/common/version.yaml similarity index 100% rename from specs/version.yml rename to specs/common/version.yaml diff --git a/specs/configDiffView.yaml b/specs/configDiffView.yaml deleted file mode 100644 index 8a24d50989..0000000000 --- a/specs/configDiffView.yaml +++ /dev/null @@ -1,73 +0,0 @@ -openapi: 3.0.0 -info: - title: Orchestrator Config Autocomplete API - version: 1.0.0 -paths: - /orchestrator/config/autocomplete: - get: - summary: Retrieve autocomplete data for configuration based on the provided appId and envId. The response includes configuration definitions with names, draft states, and types. - parameters: - - name: appId - in: query - description: The application ID. - required: true - schema: - type: string - - name: envId - in: query - description: The environment ID. - required: true - schema: - type: string - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/ConfigProperty" - - '500': - description: will get this response if any failure occurs at server side. - '400': - description: will get this response if invalid payload is sent in the request. - '403': - description: will get this response if user doesn't view access permission for the app or env - '404': - description: will get this when BaseDeployment Template is not configured - -components: - schemas: - ConfigDataResponse: - type: object - properties: - resourceConfig: - type: array - items: - $ref: '#/components/schemas/ConfigProperty' - - ConfigProperty: - type: object - properties: - name: - type: string - description: Name of the config - example: cm-1 - nullable: true - configState: - $ref: '#/components/schemas/ConfigStateEnum' - type: - $ref: '#/components/schemas/ResourceTypeEnum' - - ConfigStateEnum: - type: integer - enum: [ 1, 2, 3 ] - description: State of config (1 represents draft state , 2 represents approval pending state,3 represents published state) - - ResourceTypeEnum: - type: string - enum: [ "ConfigMap", "Secret", "Deployment Template" ] - description: Describe the config type (possible values are ConfigMap, Secret, Deployment Template) - diff --git a/specs/default-template-values.yaml b/specs/default-template-values.yaml deleted file mode 100644 index d839039f9b..0000000000 --- a/specs/default-template-values.yaml +++ /dev/null @@ -1,40 +0,0 @@ -openapi: "3.0.3" -info: - version: 1.0.0 - title: Devtron Labs -paths: - /orchestrator/app/template/default: - get: - description: Get default values of template by chartRefId - parameters: - - name: appId - in: query - required: true - schema: - type: integer - - name: chartRefId - in: query - required: true - schema: - type: integer - responses: - "200": - description: value - content: - application/json: - schema: - $ref: "#/components/schemas/DefaultTemplateResponse" -components: - schemas: - DefaultTemplateResponse: - properties: - appOverride: - type: array - items: - type: object - properties: - Key: - type: string - Value: - type: string - description: template json in form of map diff --git a/specs/deployment_app_type_change_api.yaml b/specs/deployment/app-type-change.yaml similarity index 57% rename from specs/deployment_app_type_change_api.yaml rename to specs/deployment/app-type-change.yaml index 5f1e3372ab..c980a395ca 100644 --- a/specs/deployment_app_type_change_api.yaml +++ b/specs/deployment/app-type-change.yaml @@ -10,7 +10,7 @@ paths: description: A JSON object containing environment id and desired deployment app type required: true content: - text/plain: + application/json: schema: $ref: '#/components/schemas/DeploymentAppTypeChangeRequest' responses: @@ -23,9 +23,9 @@ paths: '401': description: unauthorized user content: - text/plain: + application/json: schema: - type: string + $ref: '#/components/schemas/Error' '400': description: Bad Request. Validation error/wrong request body. content: @@ -40,12 +40,19 @@ paths: $ref: '#/components/schemas/Error' '403': description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' # components mentioned below components: schemas: DeploymentAppTypeChangeRequest: type: object + required: + - envId + - desiredDeploymentType properties: envId: type: integer @@ -53,59 +60,86 @@ components: desiredDeploymentType: type: string description: Desired deployment type. For eg argo_cd / helm + enum: [argo_cd, helm] excludeApps: type: array + items: + type: integer description: List of app ids to be excluded includeApps: type: array + items: + type: integer description: List of app ids to be included (deployment will be changed only for these apps) + autoTriggerDeployment: + type: boolean + description: Whether to automatically trigger deployment after type change + userId: + type: integer + format: int32 + description: User ID who initiated the change DeploymentChangeStatus: type: object properties: - id: + pipelineId: + type: integer + description: CD pipeline id + installedAppId: type: integer - description: cd pipeline id + description: Installed app id (for chart store apps) + appId: + type: integer + description: App id appName: type: string - description: app name + description: App name + envId: + type: integer + description: Environment id envName: type: string - description: environment name + description: Environment name error: type: string description: Error message if failed to change deployment app type status: type: string - description: If deployment change was successful or failed for this pipeline + description: Status of deployment change + enum: [Success, Failed, INITIATED, NOT_YET_DELETED, permission denied] DeploymentAppTypeChangeResponse: type: object properties: envId: type: integer - description: environment id + description: Environment id desiredDeploymentType: type: string - description: Desired deployment type. For eg argo_cd / helm + description: Desired deployment type + enum: [argo_cd, helm] successfulPipelines: type: array - description: Pipelines which were successfully deleted from current deployment + description: Pipelines which were successfully changed items: - $ref: '#components/schemas/DeploymentChangeStatus' + $ref: '#/components/schemas/DeploymentChangeStatus' failedPipelines: type: array - description: Pipelines which failed to get deleted from current deployment + description: Pipelines which failed to change deployment app type items: - $ref: '#components/schemas/DeploymentChangeStatus' - TriggeredPipelineDetails: - type: object - properties: - ciArtifactId: - type: integer - description: Artifact id deployed - pipelineId: - type: integer - description: Pipeline id for which deployment was triggered + $ref: '#/components/schemas/DeploymentChangeStatus' + triggeredPipelines: + type: array + description: Pipelines for which deployment was triggered + items: + type: object + properties: + ciArtifactId: + type: integer + description: CI artifact id + pipelineId: + type: integer + description: Pipeline id OkResponse: + type: object required: - code - status @@ -114,26 +148,30 @@ components: code: type: integer format: int32 - description: Error code + description: HTTP status code status: type: string - description: Error message + description: Status message result: - type: object - description: DeploymentAppTypeChangeResponse object + $ref: '#/components/schemas/DeploymentAppTypeChangeResponse' Error: + type: object required: - code - - status + - message properties: code: - type: integer - format: int32 - description: Error internal code + type: string + description: Error code + example: E100 + message: + type: string + description: Error message + example: User is not authenticated internalMessage: type: string - description: Error internal message + description: Internal error message for debugging userMessage: type: string - description: Error user message + description: User-friendly error message diff --git a/specs/deployments.yaml b/specs/deployment/core.yaml similarity index 61% rename from specs/deployments.yaml rename to specs/deployment/core.yaml index 2a47ec1842..fbe3b8fccf 100644 --- a/specs/deployments.yaml +++ b/specs/deployment/core.yaml @@ -2,8 +2,19 @@ openapi: "3.0.0" info: version: 1.0.0 title: Devtron Labs + description: Devtron API for deployment template management + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080 paths: - /orchestrator/deployment/template/validate: + /deployment/template/validate: post: description: upload template file from this api to validate. requestBody: @@ -14,7 +25,8 @@ paths: schema: properties: binaryFile: - type: object + type: string + format: binary description: zipped chart template file responses: '200': @@ -26,7 +38,10 @@ paths: code: type: integer description: status code - schema: + status: + type: string + description: status + result: $ref: '#/components/schemas/UploadTemplateResponse' default: description: unexpected error @@ -35,17 +50,16 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /orchestrator/deployment/template/upload: + /deployment/template/upload: put: description: upload template file from this api. requestBody: - description: form-data as request body + description: json as request body required: true content: application/json: schema: $ref: '#/components/schemas/UploadTemplateRequest' - responses: '200': description: template file upload response @@ -69,7 +83,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /orchestrator/deployment/template/fetch: + /deployment/template/fetch: get: summary: Returns all charts description: all the chart template uploaded by user @@ -79,7 +93,18 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Chart' + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + type: array + description: list of charts + items: + $ref: '#/components/schemas/Chart' default: description: unexpected error content: @@ -94,30 +119,57 @@ components: properties: fileId: type: string + description: ID of the uploaded file action: type: string + description: Action to perform (e.g. "upload", "validate") UploadTemplateResponse: type: object properties: chartName: type: string + description: Name of the chart description: type: string + description: Chart description fileId: type: string + description: ID of the uploaded file action: type: string + description: Action performed message: type: string + description: Response message Chart: type: object properties: name: type: string + description: Chart name description: type: string + description: Chart description count: type: integer + description: Number of deployments using this chart + version: + type: string + description: Chart version + createdOn: + type: string + format: date-time + description: Creation timestamp + createdBy: + type: string + description: Creator's name + updatedOn: + type: string + format: date-time + description: Last update timestamp + updatedBy: + type: string + description: Last updater's name ErrorResponse: required: - code diff --git a/specs/deployment/group.yaml b/specs/deployment/group.yaml new file mode 100644 index 0000000000..8c7fdb05a8 --- /dev/null +++ b/specs/deployment/group.yaml @@ -0,0 +1,301 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Devtron Labs + description: Devtron API for deployment group management + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080 +paths: + /deployment-group/create: + post: + description: Create a new deployment group + requestBody: + description: Deployment group details + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/DeploymentGroupRequest' + responses: + '200': + description: Deployment group created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/DeploymentGroupResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /deployment-group/update: + put: + description: Update an existing deployment group + requestBody: + description: Updated deployment group details + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/DeploymentGroupRequest' + responses: + '200': + description: Deployment group updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/DeploymentGroupResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /deployment-group/delete: + delete: + description: Delete a deployment group + parameters: + - name: groupId + in: path + required: true + schema: + type: integer + description: Deployment group ID + responses: + '200': + description: Deployment group deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/DeploymentGroupResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /deployment-group/trigger: + post: + description: Trigger deployment for a group + requestBody: + description: Deployment trigger details + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/DeploymentGroupTrigger' + responses: + '200': + description: Deployment triggered successfully + content: + application/json: + schema: + $ref: '#/components/schemas/DeploymentGroupTriggerResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + DeploymentGroupRequest: + type: object + required: + - name + - appIds + properties: + name: + type: string + description: Name of the deployment group + description: + type: string + description: Description of the deployment group + appIds: + type: array + items: + type: integer + description: List of application IDs in the group + envId: + type: integer + description: Environment ID + userId: + type: integer + description: User ID who created/updated the group + + DeploymentGroupResponse: + type: object + properties: + code: + type: integer + description: Status code + status: + type: string + description: Status message + result: + type: object + properties: + groupId: + type: integer + description: ID of the deployment group + name: + type: string + description: Name of the deployment group + description: + type: string + description: Description of the deployment group + appIds: + type: array + items: + type: integer + description: List of application IDs in the group + envId: + type: integer + description: Environment ID + createdOn: + type: string + format: date-time + description: Creation timestamp + createdBy: + type: string + description: Creator's name + updatedOn: + type: string + format: date-time + description: Last update timestamp + updatedBy: + type: string + description: Last updater's name + + DeploymentGroupTrigger: + type: object + required: + - groupId + properties: + groupId: + type: integer + description: Deployment group ID + artifactId: + type: integer + description: Artifact ID to deploy + triggeredBy: + type: integer + description: User ID who triggered the deployment + + DeploymentGroupTriggerResponse: + type: object + properties: + code: + type: integer + description: Status code + status: + type: string + description: Status message + result: + type: object + properties: + groupId: + type: integer + description: Deployment group ID + workflowIds: + type: array + items: + type: integer + description: List of workflow IDs + + ErrorResponse: + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/deployment/pipeline.yaml b/specs/deployment/pipeline.yaml new file mode 100644 index 0000000000..ce959ba77d --- /dev/null +++ b/specs/deployment/pipeline.yaml @@ -0,0 +1,366 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Devtron Labs + description: Devtron API for deployment pipeline management + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080 +paths: + /deployment/pipeline/configure: + post: + description: Configure deployment pipeline for an application + requestBody: + description: Pipeline configuration details + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PipelineConfig' + responses: + '200': + description: Pipeline configured successfully + content: + application/json: + schema: + $ref: '#/components/schemas/PipelineConfigResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /deployment/pipeline/trigger: + post: + description: Trigger a deployment pipeline + requestBody: + description: Pipeline trigger details + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PipelineTrigger' + responses: + '200': + description: Pipeline triggered successfully + content: + application/json: + schema: + $ref: '#/components/schemas/PipelineTriggerResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /deployment/pipeline/rollback: + post: + description: Rollback a deployment pipeline + requestBody: + description: Pipeline rollback details + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PipelineRollback' + responses: + '200': + description: Pipeline rollback initiated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/PipelineRollbackResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /deployment/pipeline/history: + get: + description: Get deployment pipeline history + parameters: + - name: appId + in: query + required: true + schema: + type: integer + description: Application ID + - name: envId + in: query + required: true + schema: + type: integer + description: Environment ID + responses: + '200': + description: Pipeline history retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/PipelineHistory' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + PipelineConfig: + type: object + required: + - appId + - envId + properties: + appId: + type: integer + description: Application ID + envId: + type: integer + description: Environment ID + pipelineName: + type: string + description: Name of the pipeline + triggerType: + type: string + enum: [AUTOMATIC, MANUAL] + description: Type of pipeline trigger + deploymentType: + type: string + enum: [HELM, ARGOCD] + description: Type of deployment + deploymentStrategy: + type: string + enum: [ROLLING, BLUE_GREEN, RECREATE] + description: Deployment strategy + preDeploymentScript: + type: string + description: Pre-deployment script + postDeploymentScript: + type: string + description: Post-deployment script + + PipelineConfigResponse: + type: object + properties: + code: + type: integer + description: Status code + status: + type: string + description: Status message + result: + type: object + properties: + pipelineId: + type: integer + description: ID of the created pipeline + pipelineName: + type: string + description: Name of the pipeline + + PipelineTrigger: + type: object + required: + - pipelineId + properties: + pipelineId: + type: integer + description: Pipeline ID + artifactId: + type: integer + description: Artifact ID to deploy + triggeredBy: + type: integer + description: User ID who triggered the pipeline + + PipelineTriggerResponse: + type: object + properties: + code: + type: integer + description: Status code + status: + type: string + description: Status message + result: + type: object + properties: + pipelineId: + type: integer + description: Pipeline ID + workflowId: + type: integer + description: Workflow ID + + PipelineRollback: + type: object + required: + - pipelineId + - version + properties: + pipelineId: + type: integer + description: Pipeline ID + version: + type: string + description: Version to rollback to + triggeredBy: + type: integer + description: User ID who triggered the rollback + + PipelineRollbackResponse: + type: object + properties: + code: + type: integer + description: Status code + status: + type: string + description: Status message + result: + type: object + properties: + pipelineId: + type: integer + description: Pipeline ID + workflowId: + type: integer + description: Workflow ID + + PipelineHistory: + type: object + properties: + code: + type: integer + description: Status code + status: + type: string + description: Status message + result: + type: array + items: + type: object + properties: + pipelineId: + type: integer + description: Pipeline ID + workflowId: + type: integer + description: Workflow ID + status: + type: string + description: Pipeline status + startedOn: + type: string + format: date-time + description: Start time + finishedOn: + type: string + format: date-time + description: End time + triggeredBy: + type: string + description: User who triggered the pipeline + artifactId: + type: integer + description: Artifact ID + version: + type: string + description: Deployed version + + ErrorResponse: + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/rollback.yaml b/specs/deployment/rollback.yaml similarity index 74% rename from specs/rollback.yaml rename to specs/deployment/rollback.yaml index bc61fd188b..7b3eca288d 100644 --- a/specs/rollback.yaml +++ b/specs/deployment/rollback.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Historical Task definitions - get api changes + title: Rollback API paths: /orchestrator/app/history/deployed-configuration/all/{appId}/{pipelineId}/{wfrId}: get: @@ -13,16 +13,19 @@ paths: required: true schema: type: integer + description: ID of the application - name: pipelineId in: path required: true schema: type: integer + description: ID of the pipeline - name: wfrId in: path required: true schema: type: integer + description: ID of the workflow runner responses: '200': description: Successfully return history detail @@ -58,11 +61,13 @@ paths: required: true schema: type: integer + description: ID of the application - name: pipelineId in: path required: true schema: type: integer + description: ID of the pipeline responses: '200': description: Successfully return history detail @@ -98,11 +103,13 @@ paths: required: true schema: type: integer + description: ID of the application - name: pipelineId in: path required: true schema: type: integer + description: ID of the pipeline responses: '200': description: Successfully return configuration detail @@ -145,14 +152,19 @@ components: properties: value: type: string + description: Template value displayName: type: string + description: Display name of the template isAppMetrics: - type: string + type: boolean + description: Whether app metrics are enabled templateName: type: string + description: Name of the template templateVersion: type: string + description: Version of the template configMap: type: object properties: @@ -163,6 +175,7 @@ components: properties: componentName: type: string + description: Name of the component config: type: object properties: @@ -171,22 +184,31 @@ components: properties: value: type: string + description: Config value displayName: type: string + description: Display name of the config type: type: string + description: Type of the config external: - type: string + type: boolean + description: Whether the config is external mountPath: type: string + description: Mount path for the config externalType: type: string + description: Type of external config roleARN: type: string + description: ARN of the role subPath: type: string + description: Sub path for the config filePermission: type: string + description: File permissions secret: type: object properties: @@ -197,6 +219,7 @@ components: properties: componentName: type: string + description: Name of the component config: type: object properties: @@ -205,22 +228,37 @@ components: properties: value: type: string + description: Secret value displayName: type: string + description: Display name of the secret type: type: string + description: Type of the secret external: - type: string + type: boolean + description: Whether the secret is external mountPath: type: string + description: Mount path for the secret externalType: type: string + description: Type of external secret roleARN: type: string + description: ARN of the role subPath: type: string + description: Sub path for the secret filePermission: type: string + description: File permissions + externalSecretType: + type: string + description: Type of external secret + esoSubPath: + type: string + description: ESO sub path pipelineStrategy: type: object properties: @@ -232,20 +270,26 @@ components: properties: value: type: string + description: Strategy value displayName: type: string + description: Display name of the strategy pipelineTriggerType: type: string + description: Type of pipeline trigger strategy: type: string + description: Deployment strategy Error: - required: - - code - - message + type: object properties: code: type: integer + format: int32 description: Error code - message: + status: + type: string + description: Error message + userDetailedMessage: type: string - description: Error message \ No newline at end of file + description: Detailed error message for user \ No newline at end of file diff --git a/specs/deployment/timeline.yaml b/specs/deployment/timeline.yaml new file mode 100644 index 0000000000..528b43e245 --- /dev/null +++ b/specs/deployment/timeline.yaml @@ -0,0 +1,154 @@ +openapi: "3.0.0" +info: + title: Pipeline Status Timeline API + version: "1.0" +paths: + /orchestrator/app/deployment-status/timeline/{appId}/{envId}: + get: + description: Get all timelines of a deployment trigger + operationId: GetPipelineStatusTimelines + parameters: + - name: appId + in: path + required: true + schema: + type: integer + description: ID of the application + - name: envId + in: path + required: true + schema: + type: integer + description: ID of the environment + - name: wfrId + in: query + required: false + schema: + type: integer + description: ID of the workflow runner. If not provided, latest workflow runner will be used + - name: showTimeline + in: query + required: false + schema: + type: boolean + description: Whether to show detailed timeline information + responses: + '200': + description: Successfully returns deployment timeline status of a pipeline + content: + application/json: + schema: + $ref: '#/components/schemas/PipelineTimelineDetailDto' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' +components: + schemas: + PipelineTimelineDetailDto: + type: object + properties: + deploymentStartedOn: + type: string + format: date-time + description: Time when the deployment started + deploymentFinishedOn: + type: string + format: date-time + description: Time when the deployment finished + triggeredBy: + type: string + description: Email ID of the user who triggered the deployment + timelines: + type: array + items: + $ref: '#/components/schemas/PipelineStatusTimelineDto' + description: List of timeline events + statusLastFetchedAt: + type: string + format: date-time + description: Last time when the status was fetched + statusFetchCount: + type: integer + description: Number of times status has been fetched + wfrStatus: + type: string + description: Status of the workflow runner + deploymentAppDeleteRequest: + type: boolean + description: Whether the deployment app delete request is pending + PipelineStatusTimelineDto: + type: object + properties: + id: + type: integer + description: Unique identifier for the timeline event + installedAppVersionHistoryId: + type: integer + description: ID of the installed app version history (for Helm apps) + cdWorkflowRunnerId: + type: integer + description: ID of the CD workflow runner + status: + type: string + description: Status of the timeline event + statusDetail: + type: string + description: Detailed status message + statusTime: + type: string + format: date-time + description: Time when the status was recorded + resourceDetails: + type: array + items: + $ref: '#/components/schemas/SyncStageResourceDetailDto' + description: Details of resources being synced + SyncStageResourceDetailDto: + type: object + properties: + resourceName: + type: string + description: Name of the resource + resourceKind: + type: string + description: Kind of the resource + resourceGroup: + type: string + description: Group of the resource + resourceStatus: + type: string + description: Status of the resource + statusMessage: + type: string + description: Status message for the resource + resourcePhase: + type: string + description: Phase of the resource (e.g. Sync, PreSync, PostSync) + Error: + type: object + properties: + code: + type: integer + format: int32 + description: Error code + message: + type: string + description: Error message + userDetailedMessage: + type: string + description: Detailed error message for the user diff --git a/specs/bulk-env-delete.yaml b/specs/environment/bulk-delete.yaml similarity index 67% rename from specs/bulk-env-delete.yaml rename to specs/environment/bulk-delete.yaml index 60e1f673d9..c561c866b6 100644 --- a/specs/bulk-env-delete.yaml +++ b/specs/environment/bulk-delete.yaml @@ -30,7 +30,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/CdPipelineImpactedObjectDto' + $ref: '#/components/schemas/PipelineAndWfBulkActionResponseDto' '400': description: Bad Request. Validation error/wrong request body. content: @@ -73,7 +73,7 @@ components: envNames: type: array items: - type: integer + type: string description: names of all environments whose pipelines are to be included in action appIds: type: array @@ -83,7 +83,7 @@ components: appNames: type: array items: - type: integer + type: string description: names of all apps for which the environment is to be included projectIds: type: array @@ -93,19 +93,69 @@ components: projectNames: type: array items: - type: integer + type: string description: names of all projects for which the environment is to be included - CdPipelineImpactedObjectDto: + deleteWfAndCiPipeline: + type: boolean + description: whether to delete workflow and CI pipeline + forceDelete: + type: boolean + description: whether to force delete + nonCascadeDelete: + type: boolean + description: whether to delete without cascade + userId: + type: integer + format: int32 + description: user id who is performing the action + PipelineAndWfBulkActionResponseDto: + type: object + properties: + cdPipelinesRespDtos: + type: array + items: + $ref: '#/components/schemas/CdBulkActionResponseDto' + ciPipelineRespDtos: + type: array + items: + $ref: '#/components/schemas/CiBulkActionResponseDto' + appWfRespDtos: + type: array + items: + $ref: '#/components/schemas/WfBulkActionResponseDto' + CdBulkActionResponseDto: type: object properties: pipelineName: - type: integer - environmentName: type: string + description: name of the pipeline appName: type: string - projectName: + description: name of the application + environmentName: + type: string + description: name of the environment + deletionResult: + type: string + description: result of the deletion operation + CiBulkActionResponseDto: + type: object + properties: + pipelineName: + type: string + description: name of the CI pipeline + deletionResult: + type: string + description: result of the deletion operation + WfBulkActionResponseDto: + type: object + properties: + workflowId: + type: integer + description: id of the workflow + deletionResult: type: string + description: result of the deletion operation ErrorResponse: required: - code diff --git a/specs/environment/config-diff.yaml b/specs/environment/config-diff.yaml new file mode 100644 index 0000000000..41dbf5c11a --- /dev/null +++ b/specs/environment/config-diff.yaml @@ -0,0 +1,398 @@ +openapi: 3.0.0 +info: + title: Configuration Diff View API + version: 1.0.0 + description: API for managing configuration differences and comparisons + +paths: + /orchestrator/config/autocomplete: + get: + summary: Get configuration autocomplete data + operationId: ConfigAutoComplete + parameters: + - name: appId + in: query + required: true + schema: + type: integer + description: The application ID + - name: envId + in: query + required: true + schema: + type: integer + description: The environment ID + responses: + '200': + description: Successfully retrieved configuration autocomplete data + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ConfigProperty' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/config/data: + get: + summary: Get configuration data + operationId: GetConfigData + parameters: + - name: appName + in: query + required: true + schema: + type: string + description: The application name + - name: envName + in: query + required: false + schema: + type: string + description: The environment name + - name: configType + in: query + required: true + schema: + type: string + description: The configuration type + - name: identifierId + in: query + required: false + schema: + type: integer + description: The identifier ID + - name: pipelineId + in: query + required: false + schema: + type: integer + description: The pipeline ID + - name: resourceName + in: query + required: false + schema: + type: string + description: The resource name + - name: resourceType + in: query + required: false + schema: + type: string + description: The resource type + - name: resourceId + in: query + required: false + schema: + type: integer + description: The resource ID + - name: wfrId + in: query + required: false + schema: + type: integer + description: The workflow run ID + - name: configArea + in: query + required: false + schema: + type: string + description: The configuration area + responses: + '200': + description: Successfully retrieved configuration data + content: + application/json: + schema: + $ref: '#/components/schemas/ConfigDataResponse' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/config/compare/{resource}: + get: + summary: Compare configuration data + operationId: CompareCategoryWiseConfigData + parameters: + - name: resource + in: path + required: true + schema: + type: string + enum: [ConfigMap, Secret, Deployment Template, Pipeline Strategy] + description: The resource type to compare + - name: compareConfig + in: query + required: true + schema: + type: string + description: JSON string containing comparison configuration + responses: + '200': + description: Successfully compared configuration data + content: + application/json: + schema: + $ref: '#/components/schemas/ComparisonResponseDto' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/config/manifest: + post: + summary: Get manifest for configuration + operationId: GetManifest + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ManifestRequest' + responses: + '200': + description: Successfully retrieved manifest + content: + application/json: + schema: + $ref: '#/components/schemas/ManifestResponse' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + ConfigProperty: + type: object + properties: + name: + type: string + description: Name of the configuration + example: cm-1 + nullable: true + configState: + $ref: '#/components/schemas/ConfigStateEnum' + type: + $ref: '#/components/schemas/ResourceTypeEnum' + + ConfigStateEnum: + type: integer + enum: [1, 2, 3] + description: State of configuration (1 = draft, 2 = approval pending, 3 = published) + + ResourceTypeEnum: + type: string + enum: [ConfigMap, Secret, Deployment Template] + description: Type of resource + + ConfigDataResponse: + type: object + properties: + resourceConfig: + type: array + items: + $ref: '#/components/schemas/ConfigProperty' + isAppAdmin: + type: boolean + description: Whether the user has admin access to the application + + ComparisonRequestDto: + type: object + properties: + comparisonItems: + type: array + items: + $ref: '#/components/schemas/ComparisonItemRequestDto' + + ComparisonItemRequestDto: + type: object + properties: + index: + type: integer + description: Index of the comparison item + appName: + type: string + description: Name of the application + envName: + type: string + description: Name of the environment + configType: + type: string + description: Type of configuration + identifierId: + type: integer + description: Identifier ID + pipelineId: + type: integer + description: Pipeline ID + resourceName: + type: string + description: Resource name + resourceType: + type: string + description: Resource type + resourceId: + type: integer + description: Resource ID + wfrId: + type: integer + description: Workflow run ID + configArea: + type: string + description: Configuration area + + ComparisonResponseDto: + type: object + properties: + comparisonItemResponse: + type: array + items: + $ref: '#/components/schemas/DeploymentAndCmCsConfigDto' + + DeploymentAndCmCsConfigDto: + type: object + properties: + configData: + type: object + description: Configuration data + deploymentTemplate: + type: object + description: Deployment template data + pipelineStrategy: + type: object + description: Pipeline strategy data + + ManifestRequest: + type: object + required: + - values + - resourceType + - appId + properties: + values: + type: object + description: Configuration values + mergeStrategy: + type: string + description: Strategy for merging configurations + resourceType: + type: string + description: Type of resource + resourceId: + type: integer + description: Resource ID + resourceName: + type: string + description: Resource name + appId: + type: integer + description: Application ID + environmentId: + type: integer + description: Environment ID + + ManifestResponse: + type: object + properties: + manifest: + type: string + description: Generated manifest + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message + diff --git a/specs/environment.yaml b/specs/environment/core.yaml similarity index 56% rename from specs/environment.yaml rename to specs/environment/core.yaml index 68f5232401..fed6f9b6d2 100644 --- a/specs/environment.yaml +++ b/specs/environment/core.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: Devtron Labs paths: - /orchestrator/env/namespace/autocomplete: + /env/namespace/autocomplete: get: description: list of namespaces group by clusters parameters: @@ -11,10 +11,10 @@ paths: name: ids example: "1,2" description: cluster ids - required: true - allowEmptyValue: false + required: false + allowEmptyValue: true schema: - type: integer + type: string responses: '200': description: list response @@ -32,7 +32,7 @@ paths: type: array description: namespace list group by cluster items: - $ref: '#/components/schemas/Cluster' + $ref: '#/components/schemas/ClusterEnvDto' default: description: unexpected error content: @@ -43,11 +43,8 @@ paths: # components mentioned below components: schemas: - Cluster: + ClusterEnvDto: type: object - required: - - key - - value properties: clusterId: type: integer @@ -58,22 +55,74 @@ components: environments: type: array items: - $ref: '#/components/schemas/Environment' - Environment: + $ref: '#/components/schemas/EnvDto' + isVirtualCluster: + type: boolean + description: whether cluster is virtual or not + clusterServerUrl: + type: string + description: cluster server URL + clusterConfig: + type: object + description: cluster configuration + properties: + bearerToken: + type: string + description: bearer token for cluster access + tlsConfig: + type: object + description: TLS configuration + properties: + insecureSkipTLSVerify: + type: boolean + description: whether to skip TLS verification + EnvDto: type: object properties: environmentId: type: integer - description: cluster id + description: environment id environmentName: type: string - description: cluster name + description: environment name + namespace: + type: string + description: namespace environmentIdentifier: type: string description: environment identifier - namespace: + description: type: string - description: namespace + description: environment description + isVirtualEnvironment: + type: boolean + description: whether environment is virtual or not + default: + type: boolean + description: whether environment is default or not + clusterId: + type: integer + description: cluster id + clusterName: + type: string + description: cluster name + active: + type: boolean + description: whether environment is active + createdOn: + type: string + format: date-time + description: creation timestamp + updatedOn: + type: string + format: date-time + description: last update timestamp + createdBy: + type: string + description: creator's name + updatedBy: + type: string + description: last updater's name ErrorResponse: required: diff --git a/specs/environment/templates.yaml b/specs/environment/templates.yaml new file mode 100644 index 0000000000..ef3a2a1af0 --- /dev/null +++ b/specs/environment/templates.yaml @@ -0,0 +1,123 @@ +openapi: "3.0.3" +info: + version: 1.0.0 + title: Default Template Values API + description: API for managing default template values for applications + +paths: + /orchestrator/app/template/default/{appId}/{chartRefId}: + get: + summary: Get default template values + operationId: GetDefaultDeploymentTemplate + description: Get default values of template by appId and chartRefId + parameters: + - name: appId + in: path + required: true + schema: + type: integer + description: The application ID + - name: chartRefId + in: path + required: true + schema: + type: integer + description: The chart reference ID + - name: token + in: header + required: true + schema: + type: string + description: Authentication token + responses: + '200': + description: Successfully retrieved default template values + content: + application/json: + schema: + type: object + properties: + code: + type: integer + description: HTTP status code + status: + type: string + description: Status message + result: + type: object + properties: + appOverride: + type: array + items: + type: object + properties: + Key: + type: string + description: The configuration key + Value: + type: string + description: The configuration value + isAppMetricsEnabled: + type: boolean + description: Whether application metrics are enabled + errors: + type: array + items: + $ref: '#/components/schemas/ApiError' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + ApiError: + type: object + properties: + code: + type: string + description: Error code + message: + type: string + description: Error message + internalMessage: + type: string + description: Internal error message for debugging + userMessage: + type: string + description: User-friendly error message + + Error: + type: object + required: + - code + - message + properties: + code: + type: string + description: Error code + example: E100 + message: + type: string + description: Error message + example: User is not authenticated diff --git a/specs/ephemeralContainers.yaml b/specs/ephemeralContainers.yaml deleted file mode 100644 index 665c2d49e3..0000000000 --- a/specs/ephemeralContainers.yaml +++ /dev/null @@ -1,109 +0,0 @@ -openapi: 3.0.0 -info: - title: Orchestrator K8s API - version: 1.0.0 -paths: - /orchestrator/k8s/resources/ephemeralContainers: - post: - summary: Create Ephemeral Container - parameters: - - name: identifier - in: query - required: true - schema: - type: string - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/EphemeralContainerRequest" - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: "#/components/schemas/PodContainerList" - '400': - description: Bad Request - '401': - description: Unauthorized - delete: - summary: Delete Ephemeral Container - parameters: - - name: identifier - in: query - required: true - schema: - type: string - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/EphemeralContainerRequest" - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: "#/components/schemas/PodContainerList" - '400': - description: Bad Request - '401': - description: Unauthorized - -components: - schemas: - EphemeralContainerRequest: - type: object - properties: - basicData: - $ref: "#/components/schemas/EphemeralContainerBasicData" - advancedData: - $ref: "#/components/schemas/EphemeralContainerAdvancedData" - namespace: - type: string - clusterId: - type: integer - podName: - type: string - userId: - type: integer - required: - - namespace - - clusterId - - podName - EphemeralContainerBasicData: - type: object - properties: - containerName: - type: string - targetContainerName: - type: string - image: - type: string - required: - - containerName - - targetContainerName - - image - EphemeralContainerAdvancedData: - type: object - properties: - manifest: - type: string - PodContainerList: - type: object - properties: - containers: - type: array - items: - type: string - initContainers: - type: array - items: - type: string - ephemeralContainers: - type: array - items: - type: string diff --git a/specs/gitops-validation.yaml b/specs/gitops-validation.yaml deleted file mode 100644 index 0a3a5ad68c..0000000000 --- a/specs/gitops-validation.yaml +++ /dev/null @@ -1,172 +0,0 @@ -openapi: "3.0.0" -info: - version: 1.0.0 - title: GitOps Validation -servers: - - url: http://localhost:3000/orchestrator/gitops -paths: - /validate: - post: - description: Validate gitops configuration by dry run - operationId: GitOpsValidateDryRun - requestBody: - description: A JSON object containing the gitops configuration - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GitOpsConfigDto' - responses: - '200': - description: Successfully return all validation stages results - content: - application/json: - schema: - $ref: '#/components/schemas/DetailedError' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /config: - post: - description: create/save new configuration and validate them before saving - operationId: CreateGitOpsConfig - requestBody: - description: A JSON object containing the gitops configuration - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GitOpsConfigDto' - responses: - '200': - description: Successfully return all validation stages results and if validation is correct then saves the configuration in the backend - content: - application/json: - schema: - $ref: '#/components/schemas/DetailedError' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - put: - description: update configuration and validate them before saving(if last validation is within 30 seconds then do not validate) - operationId: UpdateGitOpsConfig - requestBody: - description: A JSON object containing the gitops configuration - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GitOpsConfigDto' - responses: - '200': - description: Successfully return all validation stages results and if validation is correct then updates the configuration in the backend - content: - application/json: - schema: - $ref: '#/components/schemas/DetailedError' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - -components: - schemas: - GitOpsConfigDto: - type: object - properties: - id: - type: integer - provider: - type: string - username: - type: string - token: - type: string - gitLabGroupId: - type: string - gitHubOrgId: - type: string - host: - type: string - active: - type: boolean - azureProjectName: - type: string - userId: - type: integer - DetailedError: - type: object - properties: - successfulStages: - type: array - items: - type: string - description: All successful stages - validatedOn: - type: string - description: Timestamp of validation - stageErrorMap: - type: array - items: - type: object - properties: - stage: - type: string - error: - type: string - description: map of stage and their respective errors - Error: - required: - - code - - message - properties: - code: - type: integer - description: Error code - message: - type: string - description: Error message \ No newline at end of file diff --git a/specs/gitops_bitbucket.yaml b/specs/gitops/bitbucket.yaml similarity index 70% rename from specs/gitops_bitbucket.yaml rename to specs/gitops/bitbucket.yaml index 73c9cdf6fb..57268e7748 100644 --- a/specs/gitops_bitbucket.yaml +++ b/specs/gitops/bitbucket.yaml @@ -118,57 +118,102 @@ components: properties: id: type: integer + description: GitOps configuration ID provider: type: string + description: Git provider + enum: [GITLAB, GITHUB, AZURE_DEVOPS, BITBUCKET_CLOUD] username: type: string + description: Git username token: type: string + description: Git access token gitLabGroupId: type: string + description: GitLab group ID gitHubOrgId: type: string + description: GitHub organization ID host: type: string + description: Git host URL active: type: boolean + description: Whether this configuration is active azureProjectName: type: string + description: Azure DevOps project name bitBucketWorkspaceId: type: string + description: Bitbucket workspace ID bitBucketProjectKey: type: string - userId: - type: integer - DetailedError: + description: Bitbucket project key + allowCustomRepository: + type: boolean + description: Whether custom repositories are allowed + enableTLSVerification: + type: boolean + description: Whether TLS verification is enabled + tlsConfig: + $ref: '#/components/schemas/TLSConfig' + isCADataPresent: + type: boolean + description: Whether CA data is present + isTLSCertDataPresent: + type: boolean + description: Whether TLS certificate data is present + isTLSKeyDataPresent: + type: boolean + description: Whether TLS key data is present + + TLSConfig: + type: object + properties: + caData: + type: string + description: CA certificate data + tlsCertData: + type: string + description: TLS certificate data + tlsKeyData: + type: string + description: TLS key data + + DetailedErrorGitOpsConfigResponse: type: object properties: successfulStages: type: array items: type: string - description: All successful stages + description: List of successfully completed validation stages + stageErrorMap: + type: object + additionalProperties: + type: string + description: Map of stage names to error messages validatedOn: type: string + format: date-time description: Timestamp of validation - stageErrorMap: - type: array - items: - type: object - properties: - stage: - type: string - error: - type: string - description: map of stage and their respective errors - Error: + deleteRepoFailed: + type: boolean + description: Whether repository deletion failed + validationSkipped: + type: boolean + description: Whether validation was skipped + + ErrorResponse: + type: object required: - code - message properties: code: type: integer - description: Error code + description: HTTP status code message: type: string description: Error message \ No newline at end of file diff --git a/specs/gitops/core.yaml b/specs/gitops/core.yaml new file mode 100644 index 0000000000..b25480cae1 --- /dev/null +++ b/specs/gitops/core.yaml @@ -0,0 +1,423 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Devtron Labs + description: Devtron API for GitOps management + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080 +paths: + /gitops/config: + post: + description: Create or save new GitOps configuration and validate before saving + operationId: CreateGitOpsConfig + requestBody: + description: GitOps configuration details + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GitOpsConfigDto' + responses: + '200': + description: Successfully created and validated GitOps configuration + content: + application/json: + schema: + $ref: '#/components/schemas/DetailedErrorGitOpsConfigResponse' + '400': + description: Bad Request - Invalid input + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + put: + description: Update GitOps configuration and validate before saving + operationId: UpdateGitOpsConfig + requestBody: + description: GitOps configuration details + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GitOpsConfigDto' + responses: + '200': + description: Successfully updated and validated GitOps configuration + content: + application/json: + schema: + $ref: '#/components/schemas/DetailedErrorGitOpsConfigResponse' + '400': + description: Bad Request - Invalid input + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + get: + description: Get all GitOps configurations + operationId: GetAllGitOpsConfig + responses: + '200': + description: List of GitOps configurations + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/GitOpsConfigDto' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /gitops/config/{id}: + get: + description: Get GitOps configuration by ID + operationId: GetGitOpsConfigById + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: GitOps configuration ID + responses: + '200': + description: GitOps configuration details + content: + application/json: + schema: + $ref: '#/components/schemas/GitOpsConfigDto' + '400': + description: Bad Request - Invalid ID + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /gitops/config-by-provider: + get: + description: Get GitOps configuration by provider + operationId: GetGitOpsConfigByProvider + parameters: + - name: provider + in: query + required: true + schema: + type: string + description: Git provider (GITLAB, GITHUB, AZURE_DEVOPS, BITBUCKET_CLOUD) + responses: + '200': + description: GitOps configuration details + content: + application/json: + schema: + $ref: '#/components/schemas/GitOpsConfigDto' + '400': + description: Bad Request - Invalid provider + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /gitops/configured: + get: + description: Check if GitOps is configured + operationId: GitOpsConfigured + responses: + '200': + description: GitOps configuration status + content: + application/json: + schema: + type: object + properties: + exists: + type: boolean + description: Whether GitOps is configured + allowCustomRepository: + type: boolean + description: Whether custom repositories are allowed + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /gitops/validate: + post: + description: Validate GitOps configuration + operationId: GitOpsValidator + requestBody: + description: GitOps configuration to validate + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GitOpsConfigDto' + responses: + '200': + description: Validation results + content: + application/json: + schema: + $ref: '#/components/schemas/DetailedErrorGitOpsConfigResponse' + '400': + description: Bad Request - Invalid input + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + GitOpsConfigDto: + type: object + properties: + id: + type: integer + description: GitOps configuration ID + provider: + type: string + description: Git provider (GITLAB, GITHUB, AZURE_DEVOPS, BITBUCKET_CLOUD) + enum: [GITLAB, GITHUB, AZURE_DEVOPS, BITBUCKET_CLOUD] + username: + type: string + description: Git username + token: + type: string + description: Git access token + gitLabGroupId: + type: string + description: GitLab group ID + gitHubOrgId: + type: string + description: GitHub organization ID + host: + type: string + description: Git host URL + active: + type: boolean + description: Whether this configuration is active + azureProjectName: + type: string + description: Azure DevOps project name + bitBucketWorkspaceId: + type: string + description: Bitbucket workspace ID + bitBucketProjectKey: + type: string + description: Bitbucket project key + allowCustomRepository: + type: boolean + description: Whether custom repositories are allowed + enableTLSVerification: + type: boolean + description: Whether TLS verification is enabled + tlsConfig: + $ref: '#/components/schemas/TLSConfig' + isCADataPresent: + type: boolean + description: Whether CA data is present + isTLSCertDataPresent: + type: boolean + description: Whether TLS certificate data is present + isTLSKeyDataPresent: + type: boolean + description: Whether TLS key data is present + + TLSConfig: + type: object + properties: + tlsKeyData: + type: string + description: TLS key data + tlsCertData: + type: string + description: TLS certificate data + caData: + type: string + description: CA certificate data + + DetailedErrorGitOpsConfigResponse: + type: object + properties: + successfulStages: + type: array + items: + type: string + description: List of successful validation stages + stageErrorMap: + type: object + additionalProperties: + type: string + description: Map of stage names to error messages + validatedOn: + type: string + format: date-time + description: Validation timestamp + deleteRepoFailed: + type: boolean + description: Whether repository deletion failed + validationSkipped: + type: boolean + description: Whether validation was skipped + + ErrorResponse: + required: + - code + - status + properties: + code: + type: integer + format: int32 + description: Error code + status: + type: string + description: Error message + errors: + type: array + description: List of errors + items: + $ref: '#/components/schemas/Error' + + Error: + required: + - code + - status + properties: + code: + type: integer + format: int32 + description: Error internal code + internalMessage: + type: string + description: Error internal message + userMessage: + type: string + description: Error user message \ No newline at end of file diff --git a/specs/fluxcd_app.yaml b/specs/gitops/fluxcd.yaml similarity index 69% rename from specs/fluxcd_app.yaml rename to specs/gitops/fluxcd.yaml index ff83979291..ad1294c883 100644 --- a/specs/fluxcd_app.yaml +++ b/specs/gitops/fluxcd.yaml @@ -33,7 +33,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - '403': description: Forbidden content: @@ -48,48 +47,47 @@ paths: $ref: '#/components/schemas/Error' /orchestrator/flux-application/app: - get: - summary: Get application details - description: Retrieve details of a specific Flux application. - parameters: - - name: appId - in: query - required: true - schema: - type: string - description: The application identifier in the format "1|default|myksApp|Kustomization as the first field having the cluster id, then second field having the namespace of the app , third field denoted the app name and last contains a boolean value of true and false". - - name: token - in: header - required: true - schema: - type: string - description: The authentication token. - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/FluxApplicationDetailDto' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - + get: + summary: Get application details + description: Retrieve details of a specific Flux application. + parameters: + - name: appId + in: query + required: true + schema: + type: string + description: The application identifier in the format "clusterId|namespace|appName|isKustomizeApp" where isKustomizeApp is a boolean value indicating if the app is a Kustomization type. + - name: token + in: header + required: true + schema: + type: string + description: The authentication token. + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/FluxApplicationDetailDto' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' components: schemas: @@ -107,6 +105,13 @@ components: description: List of Flux applications items: $ref: '#/components/schemas/FluxAppDto' + errored: + type: boolean + description: Whether there was an error fetching the applications + errorMsg: + type: string + description: Error message if any + FluxAppDto: type: object properties: @@ -116,9 +121,8 @@ components: example: flux-system appStatus: type: boolean - enum: [True, False] - description: - example: True + description: Health status of the application + example: true syncStatus: type: string description: Sync status of the application @@ -137,9 +141,21 @@ components: example: flux-system fluxAppDeploymentType: type: string - enum": ["Kustomization", "HelmRelease"] + enum: ["Kustomization", "HelmRelease"] description: Indicates if the application is a Kustomize type or standalone flux made HelmRelease app - example: true + example: "Kustomization" + + FluxApplicationDetailDto: + type: object + allOf: + - $ref: '#/components/schemas/FluxAppDto' + - type: object + properties: + fluxAppStatusDetail: + $ref: '#/components/schemas/FluxAppStatusDetail' + resourceTree: + $ref: '#/components/schemas/ResourceTreeResponse' + FluxAppStatusDetail: type: object properties: @@ -153,29 +169,46 @@ components: type: string description: Short key words like 'ReconciliationFailed', 'Reconciled', and so on for the user to understand the reason of the given of the status - InfoItem: + ResourceTreeResponse: type: object properties: - name: - type: string - value: + nodes: + type: array + items: + $ref: '#/components/schemas/ResourceNode' + pods: + type: array + items: + $ref: '#/components/schemas/PodMetadata' + status: type: string + description: Status of the resource tree - HealthStatus: + ResourceNode: type: object properties: - status: + group: type: string - message: + version: type: string - - ResourceNetworkingInfo: - type: object - properties: - labels: - type: object - additionalProperties: - type: string + kind: + type: string + namespace: + type: string + name: + type: string + uid: + type: string + parentRefs: + type: array + items: + $ref: '#/components/schemas/ResourceRef' + networkingInfo: + $ref: '#/components/schemas/ResourceNetworkingInfo' + resourceVersion: + type: string + health: + $ref: '#/components/schemas/HealthStatus' ResourceRef: type: object @@ -193,6 +226,14 @@ components: uid: type: string + ResourceNetworkingInfo: + type: object + properties: + labels: + type: object + additionalProperties: + type: string + PodMetadata: type: object properties: @@ -223,77 +264,18 @@ components: isExternal: type: boolean - ResourceNode: + HealthStatus: type: object properties: - group: - type: string - version: - type: string - kind: - type: string - namespace: - type: string - name: - type: string - uid: - type: string - parentRefs: - type: array - items: - $ref: '#/components/schemas/ResourceRef' - networkingInfo: - $ref: '#/components/schemas/ResourceNetworkingInfo' - resourceVersion: - type: string - health: - $ref: '#/components/schemas/HealthStatus' - isHibernated: - type: boolean - canBeHibernated: - type: boolean - info: - type: array - items: - $ref: '#/components/schemas/InfoItem' - createdAt: + status: type: string - format: date-time - port: - type: array - items: - type: integer - isHook: - type: boolean - hookType: + message: type: string - ResourceTreeResponse: - type: object - properties: - nodes: - type: array - items: - $ref: '#/components/schemas/ResourceNode' - podMetadata: - type: array - items: - $ref: '#/components/schemas/PodMetadata' - - FluxApplicationDetailDto: - type: object - properties: - FluxApplication: - $ref: '#/components/schemas/FluxAppDto' - FluxAppStatusDetail: - $ref: '#/components/schemas/FluxAppStatusDetail' - ResourceTreeResponse: - $ref: '#/components/schemas/ResourceTreeResponse' - Error: type: object properties: + code: + type: string message: type: string - description: Error message - example: unauthorized diff --git a/specs/gitops/manifest-generation.yaml b/specs/gitops/manifest-generation.yaml new file mode 100644 index 0000000000..fa7408a0e6 --- /dev/null +++ b/specs/gitops/manifest-generation.yaml @@ -0,0 +1,216 @@ +openapi: 3.0.3 +info: + title: App Deployment API + version: 1.0.0 +paths: + /orchestrator/app/deployments/{app-id}/{env-id}: + get: + summary: Fetch Deployment Template Comparison List + description: Returns a list of deployment templates that can be compared + operationId: FetchDeploymentsWithChartRefs + parameters: + - name: app-id + in: path + required: true + schema: + type: integer + format: int64 + description: The ID of the application + - name: env-id + in: path + required: true + schema: + type: integer + format: int64 + description: The ID of the environment + responses: + '200': + description: List of deployment templates + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DeploymentTemplateComparisonMetadata' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/app/deployment/template/data: + post: + summary: Get Values and Manifest for Deployment Template + description: Returns the values and manifest for a deployment template + operationId: GetDeploymentTemplate + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/DeploymentTemplateRequest' + responses: + '200': + description: Values and manifest data + content: + application/json: + schema: + $ref: '#/components/schemas/DeploymentTemplateResponse' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + DeploymentTemplateComparisonMetadata: + type: object + properties: + chartId: + type: integer + format: int64 + description: The ID of the chart reference + chartVersion: + type: string + description: The version of the chart + chartType: + type: string + description: The type of the chart + environmentId: + type: integer + format: int64 + description: The ID of the environment + environmentName: + type: string + description: The name of the environment + pipelineConfigOverrideId: + type: integer + format: int64 + description: The ID of the pipeline configuration override + startedOn: + type: string + format: date-time + description: The timestamp when the deployment started + finishedOn: + type: string + format: date-time + description: The timestamp when the deployment finished + status: + type: string + description: The status of the deployment + type: + type: integer + enum: [1, 2, 3, 4] + description: The type of deployment template (1=DefaultVersions, 2=PublishedOnEnvironments, 3=DeployedOnSelfEnvironment, 4=DeployedOnOtherEnvironment) + + DeploymentTemplateRequest: + type: object + required: + - appId + - chartRefId + - type + properties: + appId: + type: integer + format: int64 + description: The ID of the application + chartRefId: + type: integer + format: int64 + description: The ID of the chart reference + getValues: + type: boolean + description: Whether to include values in the response + type: + type: integer + enum: [1, 2, 3, 4] + description: The type of deployment template (1=DefaultVersions, 2=PublishedOnEnvironments, 3=DeployedOnSelfEnvironment, 4=DeployedOnOtherEnvironment) + values: + type: string + description: The values to use for the template + pipelineConfigOverrideId: + type: integer + format: int64 + description: The ID of the pipeline configuration override + environmentId: + type: integer + format: int64 + description: The ID of the environment + requestDataMode: + type: string + enum: [Values, Manifest] + description: The mode of data to return (Values or Manifest) + + DeploymentTemplateResponse: + type: object + properties: + data: + type: string + description: The raw template data + resolvedData: + type: string + description: The resolved template data with variables replaced + variableSnapshot: + type: object + additionalProperties: + type: string + description: Map of variable names to their resolved values + manifest: + type: string + description: The generated manifest + values: + type: string + description: The values used for the template + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + description: Error code + message: + type: string + description: Error message diff --git a/specs/git_submodules.yaml b/specs/gitops/submodules.yaml similarity index 55% rename from specs/git_submodules.yaml rename to specs/gitops/submodules.yaml index 65d4c237c2..838a2626eb 100644 --- a/specs/git_submodules.yaml +++ b/specs/gitops/submodules.yaml @@ -3,24 +3,19 @@ info: version: 1.0.0 title: Git Submodules support in CI paths: - /orchestrator/git/provider: - post: - description: save git repo(account) config - operationId: SaveGitRepoConfig - requestBody: - description: A JSON object containing the git repo configuration - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GitRegistry' + /orchestrator/git/host: + get: + description: get all git hosts + operationId: GetGitHosts responses: '200': - description: Successfully save the config + description: Successfully return details of all git hosts content: application/json: schema: - $ref: '#/components/schemas/GitRegistry' + type: array + items: + $ref: '#/components/schemas/GitHostRequest' '400': description: Bad Request. Input Validation(decode) error/wrong request body. content: @@ -39,23 +34,23 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - put: - description: update git repo(account) config - operationId: UpdateGitRepoConfig + post: + description: create git host + operationId: CreateGitHost requestBody: - description: A JSON object containing the git repo configuration + description: A JSON object containing the git host configuration required: true content: application/json: schema: - $ref: '#/components/schemas/GitRegistry' + $ref: '#/components/schemas/GitHostRequest' responses: '200': - description: Successfully update the config + description: Successfully created git host content: application/json: schema: - $ref: '#/components/schemas/GitRegistry' + $ref: '#/components/schemas/GitHostRequest' '400': description: Bad Request. Input Validation(decode) error/wrong request body. content: @@ -74,54 +69,23 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - get: - description: get all git account config - operationId: FetchAllGitProviders - responses: - '200': - description: Successfully return details of all git providers - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/GitRegistry' - '400': - description: Bad Request. Input Validation(decode) error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/git/material: - post: - description: save git material config - operationId: CreateMaterial - requestBody: - description: A JSON object containing the git material configuration + /orchestrator/git/host/{id}: + parameters: + - name: id + in: path required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateMaterialDTO' + schema: + type: integer + get: + description: get git host by id + operationId: GetGitHostById responses: '200': - description: Successfully save the config + description: Successfully return git host details content: application/json: schema: - $ref: '#/components/schemas/CreateMaterialDTO' + $ref: '#/components/schemas/GitHostRequest' '400': description: Bad Request. Input Validation(decode) error/wrong request body. content: @@ -140,23 +104,25 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - put: - description: update git material config - operationId: UpdateMaterial - requestBody: - description: A JSON object containing the git repo configuration + /orchestrator/git/host/{id}/event: + parameters: + - name: id + in: path required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateMaterialDTO' + schema: + type: integer + get: + description: get all webhook event config for git host + operationId: GetAllWebhookEventConfig responses: '200': - description: Successfully update the config + description: Successfully return webhook event config content: application/json: schema: - $ref: '#/components/schemas/UpdateMaterialDTO' + type: array + items: + $ref: '#/components/schemas/WebhookEventConfig' '400': description: Bad Request. Input Validation(decode) error/wrong request body. content: @@ -175,25 +141,23 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/app/get/{appId}: + /orchestrator/git/host/event/{eventId}: parameters: - - name: appId + - name: eventId in: path required: true schema: type: integer get: - description: get details of an app by its Id - operationId: GetApp + description: get webhook event config by id + operationId: GetWebhookEventConfig responses: '200': - description: Successfully return details of an app + description: Successfully return webhook event config content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/CreateAppDTO' + $ref: '#/components/schemas/WebhookEventConfig' '400': description: Bad Request. Input Validation(decode) error/wrong request body. content: @@ -212,25 +176,23 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/app/{appId}/autocomplete/git: + /orchestrator/git/host/webhook-meta-config/{gitProviderId}: parameters: - - name: appId + - name: gitProviderId in: path required: true schema: - type: integer + type: string get: - description: get all git providers - operationId: GitListAutocomplete + description: get webhook data meta config for git provider + operationId: GetWebhookDataMetaConfig responses: '200': - description: Successfully return details of all git providers + description: Successfully return webhook data meta config content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/GitRegistry' + $ref: '#/components/schemas/WebhookDataMetaConfigResponse' '400': description: Bad Request. Input Validation(decode) error/wrong request body. content: @@ -251,8 +213,11 @@ paths: $ref: '#/components/schemas/Error' components: schemas: - GitRegistry: + GitHostRequest: type: object + required: + - name + - url properties: id: type: integer @@ -260,83 +225,30 @@ components: type: string url: type: string - userName: - type: string - password: - type: string - sshPrivateKey: - type: string - accessToken: - type: string - authMode: - type: string active: type: boolean - gitHostId: - type: integer - CreateAppDTO: + WebhookEventConfig: type: object properties: id: type: integer - appname: - type: string - material: - type: array - items: - $ref: '#/components/schemas/GitMaterial' - teamId: - type: integer - templateId: - type: integer - appLabels: - type: array - items: - $ref: '#/components/schemas/labels' - labels: - type: object - properties: - key: + name: type: string - value: + eventType: type: string - CreateMaterialDTO: - type: object - properties: - id: - type: integer - appId: + gitHostId: type: integer - material: - type: array - items: - $ref: '#/components/schemas/GitMaterial' - UpdateMaterialDTO: + WebhookDataMetaConfigResponse: type: object properties: - appId: + gitHostId: type: integer - material: + gitHost: + $ref: '#/components/schemas/GitHostRequest' + webhookEvents: type: array items: - $ref: '#/components/schemas/GitMaterial' - GitMaterial: - type: object - properties: - id: - type: integer - name: - type: string - url: - type: string - gitProviderId: - type: integer - checkoutPath: - type: string - fetchSubmodules: - type: boolean - isUsedInCiConfig: - type: boolean + $ref: '#/components/schemas/WebhookEventConfig' Error: required: - code diff --git a/specs/gitops/validation.yaml b/specs/gitops/validation.yaml new file mode 100644 index 0000000000..6915d91a6c --- /dev/null +++ b/specs/gitops/validation.yaml @@ -0,0 +1,390 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: GitOps Validation +servers: + - url: http://localhost:3000/orchestrator/gitops +paths: + /validate: + post: + description: Validate GitOps configuration + operationId: GitOpsValidator + requestBody: + description: A JSON object containing the gitops configuration + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GitOpsConfigDto' + responses: + '200': + description: Successfully validated GitOps configuration + content: + application/json: + schema: + $ref: '#/components/schemas/DetailedErrorGitOpsConfigResponse' + '400': + description: Bad Request - Invalid input or validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized - User not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - User lacks required permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /config: + post: + description: Create a new GitOps configuration + operationId: CreateGitOpsConfig + requestBody: + description: A JSON object containing the gitops configuration + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GitOpsConfigDto' + responses: + '200': + description: Successfully created and validated GitOps configuration + content: + application/json: + schema: + $ref: '#/components/schemas/DetailedErrorGitOpsConfigResponse' + '400': + description: Bad Request - Invalid input or validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized - User not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - User lacks required permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + put: + description: Update an existing GitOps configuration + operationId: UpdateGitOpsConfig + requestBody: + description: A JSON object containing the gitops configuration + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GitOpsConfigDto' + responses: + '200': + description: Successfully updated and validated GitOps configuration + content: + application/json: + schema: + $ref: '#/components/schemas/DetailedErrorGitOpsConfigResponse' + '400': + description: Bad Request - Invalid input or validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized - User not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - User lacks required permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /gitops/config: + get: + description: Get all GitOps configurations + operationId: GetAllGitOpsConfig + responses: + '200': + description: Successfully retrieved all GitOps configurations + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/GitOpsConfigDto' + '401': + description: Unauthorized - User not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - User lacks required permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /gitops/config/{id}: + get: + description: Get GitOps configuration by ID + operationId: GetGitOpsConfigById + parameters: + - name: id + in: path + description: ID of the GitOps configuration + required: true + schema: + type: integer + responses: + '200': + description: Successfully retrieved GitOps configuration + content: + application/json: + schema: + $ref: '#/components/schemas/GitOpsConfigDto' + '401': + description: Unauthorized - User not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - User lacks required permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: GitOps configuration not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /gitops/config-by-provider: + get: + description: Get GitOps configuration by provider + operationId: GetGitOpsConfigByProvider + parameters: + - name: provider + in: query + description: Git provider (e.g., GITHUB, GITLAB, BITBUCKET) + required: true + schema: + type: string + responses: + '200': + description: Successfully retrieved GitOps configuration + content: + application/json: + schema: + $ref: '#/components/schemas/GitOpsConfigDto' + '401': + description: Unauthorized - User not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - User lacks required permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: GitOps configuration not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /gitops/configured: + get: + description: Check if GitOps is configured + operationId: GitOpsConfigured + responses: + '200': + description: Successfully checked GitOps configuration status + content: + application/json: + schema: + type: object + properties: + exists: + type: boolean + description: Whether GitOps is configured + allowCustomRepository: + type: boolean + description: Whether custom repositories are allowed + '401': + description: Unauthorized - User not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - User lacks required permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + GitOpsConfigDto: + type: object + properties: + id: + type: integer + description: GitOps configuration ID + provider: + type: string + description: Git provider + enum: [GITLAB, GITHUB, AZURE_DEVOPS, BITBUCKET_CLOUD] + username: + type: string + description: Git username + token: + type: string + description: Git access token + gitLabGroupId: + type: string + description: GitLab group ID + gitHubOrgId: + type: string + description: GitHub organization ID + host: + type: string + description: Git host URL + active: + type: boolean + description: Whether this configuration is active + azureProjectName: + type: string + description: Azure DevOps project name + bitBucketWorkspaceId: + type: string + description: Bitbucket workspace ID + bitBucketProjectKey: + type: string + description: Bitbucket project key + allowCustomRepository: + type: boolean + description: Whether custom repositories are allowed + enableTLSVerification: + type: boolean + description: Whether TLS verification is enabled + tlsConfig: + $ref: '#/components/schemas/TLSConfig' + isCADataPresent: + type: boolean + description: Whether CA data is present + isTLSCertDataPresent: + type: boolean + description: Whether TLS certificate data is present + isTLSKeyDataPresent: + type: boolean + description: Whether TLS key data is present + + TLSConfig: + type: object + properties: + caData: + type: string + description: CA certificate data + tlsCertData: + type: string + description: TLS certificate data + tlsKeyData: + type: string + description: TLS key data + + DetailedErrorGitOpsConfigResponse: + type: object + properties: + successfulStages: + type: array + items: + type: string + description: List of successfully completed validation stages + stageErrorMap: + type: object + additionalProperties: + type: string + description: Map of stage names to error messages + validatedOn: + type: string + format: date-time + description: Timestamp of validation + deleteRepoFailed: + type: boolean + description: Whether repository deletion failed + validationSkipped: + type: boolean + description: Whether validation was skipped + + ErrorResponse: + type: object + required: + - code + - message + properties: + code: + type: integer + description: HTTP status code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/global-plugin.yaml b/specs/global-plugin.yaml deleted file mode 100644 index 3b888c14fa..0000000000 --- a/specs/global-plugin.yaml +++ /dev/null @@ -1,604 +0,0 @@ -openapi: "3.0.3" -info: - title: "Plugin System Integration - CI Stages" - description: | - This API facilitates the management of plugins used in pre/post CI or CD steps, - enhancing the customization and automation capabilities of CI/CD pipelines. - version: "1.0.0" - -paths: - /orchestrator/plugin/global/detail/{pluginId}: - get: - description: > - Retrieve detailed information about a specific plugin by its ID. Before proceeding to Patch Plugin, ensure to retrieve the plugin details using this endpoint as the same object will be used in the patch action of the global plugin. - parameters: - - name: pluginId - in: path - required: true - schema: - type: integer - description: Unique identifier of the plugin - - responses: - '200': - description: successfully return the Detailed information about the plugin - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - $ref: '#/components/schemas/PluginMetaDataDto' - '400': - description: Bad request, Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized, not found or invalid API token provided - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - '403': - description: Forbidden, user is not allowed to access this plugin information - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Not Found, the plugin with the specified ID does not exist - - '500': - description: Internal server error, could not retrieve plugin details - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/plugin/global/detail/all: - get: - description: > - Get detailed information of available plugins. - operationId: GetAllDetailedPluginInfo - responses: - '200': - description: A list of plugins with detailed information - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: array - items: - $ref: '#/components/schemas/PluginMetaDataDto' - '401': - description: Unauthorized user, Invalid or missing API token - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden, user is not authorized to access this resource - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error, could not fetch the plugin details - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - - - /orchestrator/plugin/global/: - post: - summary: "Manipulating the Global Plugin" - description: | - Allows for the management (creation, update, or deletion) of global plugins through a single endpoint. This endpoint is versatile and supports various actions based on the provided `action` field in the request payload. Before performing any action, ensure to retrieve detailed information about the plugin by its ID using the endpoint `/orchestrator/plugin/global/detail/{pluginId}`. The same or modified object retrieved can be used in the request payload for this endpoint. - operationId: "PatchPlugin" - requestBody: - description: "A JSON Object containing the PluginMetaData fields, including the specific action to be performed." - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PluginMetaDataDto' - responses: - '200': - description: "Successfully processed the global plugin operation. The response includes the updated plugin data." - content: - application/json: - schema: - $ref: '#/components/schemas/PluginMetaDataDto' - '400': - description: "Bad Request due to input validation errors or incorrect request body format." - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: "Unauthorized access attempt. This may occur if the user does not have the necessary permissions for the operation." - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: "Internal Server Error indicating an unexpected condition that prevented the request from being fulfilled." - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/plugin/global/list/global-variable: - get: - description: Get list of all global variables. - operationId: GetAllGlobalVariables - parameters: - - name: appId - in: query - required: true - schema: - type: integer - description: The ID of the application for which global variables are retrieved. - - responses: - '200': - description: Successfully returns all global variables. - content: - application/json: - schema: - type: object - properties: - code: - type: integer - description: Status code. - status: - type: string - description: Status. - result: - type: array - items: - $ref: '#/components/schemas/GlobalVariable' - '400': - description: Bad Request. Input validation error or wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - - - - -components: - schemas: - GlobalVariable: - type: object - properties: - name: - type: string - description: The name of the global variable. - value: - type: string - description: Optional.The value of the global variable. - format: - type: string - description: The format of the value. - description: - type: string - description: A description of the global variable and its purpose. - stageType: - type: string - description: The type of stage this global variable is associated with. - required: - - name - - format - - description - - type - - - PluginMetaDataDto: - type: object - properties: - id: - type: integer - description: Unique identifier for the plugin. - name: - type: string - description: Name of the plugin. - description: - type: string - description: Detailed description of what the plugin does. - type: - type: string - enum: [SHARED, PRESET] - description: > - Type of the plugin indicating whether it's a SHARED plugin accessible by user or a PRESET plugin provided by the system. - icon: - type: string - description: URL or a base64 encoded string representing an icon for the plugin - example: https://raw.githubusercontent.com/devtron-labs/devtron/main/assets/k6-plugin-icon.png - tags: - type: array - items: - type: string - description: A list of tags associated with the plugin for categorization and search. - action: - type: integer - description: | - This field represents the action to be performed with this plugin metadata. - - Use `0` to create a new plugin. - - Use `1` to update an existing plugin. - - Use `2` to delete a plugin. - - If you're opting to update an existing plugin (action `1`), - please take note: - - Ensure that the request body parameters are accurate before updating. - - Your request body (payload) will discard all previous updates and be treated as final. - - pluginStage: - type: string - enum: [ CD, CI, CI_CD] - description: Optional. Specifies the stage of the CI/CD pipeline or both (CI/CD) where this plugin can be used. Default value is CI_CD - pluginSteps: - type: array - items: - $ref: '#/components/schemas/PluginStepsDto' - description: Optional, A list of steps defined for the plugin. Each step contains specific instructions or actions the plugin will perform. - required: - - name - - description - - type - - icon - - tags - - action - - PluginStepsDto: - type: object - properties: - id: - type: integer - description: Unique identifier of the plugin step. - name: - type: string - description: Name of the plugin step. - description: - type: string - description: Detailed description of what the plugin step does. - index: - type: integer - description: The order index of the plugin step within the plugin. - stepType: - type: string - enum: [INLINE, REF_PLUGIN] - description: Type of the plugin step, indicating whether it's an INLINE step defined within the plugin or a REF_PLUGIN step referencing another plugin. - refPluginId: - type: integer - description: Unique identifier of the plugin used as reference by this step. - outputDirectoryPath: - type: array - items: - type: string - description: Paths to directories where the output of the plugin step should be stored. - dependentOnStep: - type: string - description: Identifier of the step, this step depends on to run. It can be used to establish execution order. - pluginStepVariable: - type: array - items: - $ref: '#/components/schemas/PluginVariableDto' - description: Optional. A list of variables associated with this plugin step. - pluginPipelineScript: - allOf: - - $ref: '#/components/schemas/PluginPipelineScript' - - description: Script associated with this plugin step to be executed as part of the pipeline. Optional. - required: - - name - - description - - index - - stepType - - refPluginId - - outputDirectoryPath - - dependentOnStep - - PluginVariableDto: - type: object - properties: - id: - type: integer - description: The unique identifier of the plugin variable. - name: - type: string - description: The name of the plugin variable. - format: - type: string - description: The format of the variable value. - enum: - - STRING - - NUMBER - - BOOL - - DATE - example: - - STRING - description: - type: string - description: A description of the plugin variable. - isExposed: - type: boolean - description: Indicates whether the variable is exposed. - allowEmptyValue: - type: boolean - description: Indicates whether an empty value is allowed for the variable. - defaultValue: - type: string - description: The default value of the variable. - value: - type: string - description: The value of the variable. - variableType: - type: string - description: | - The type of the variable. This specifies whether the variable is required by the plugin (Marked as INPUT type) or whether that variable is produced by the plugin (Marked as OUTPUT type). - enum: - - OUTPUT - - INPUT - example: - - INPUT - valueType: - type: string - description: | - The value type of the variable. Specifies whether the plugin uses a new value provided by the user (marked as NEW), retrieves the value from the previous step (marked as FROM_PREVIOUS_STEP), or fetches a global value (marked as GLOBAL). - This indicates whether the plugin utilizes a new user-provided value, a value from a previous step, or a global value. - enum: - - NEW - - FROM_PREVIOUS_STEP - - GLOBAL - example: - - NEW - previousStepIndex: - type: integer - description: The index of the previous step. - variableStepIndex: - type: integer - description: The index of the step it is using variable from . - variableStepIndexInPlugin: - type: integer - description: The index of the variable step in the plugin. - referenceVariableName: - type: string - description: The name of the reference variable. - pluginStepCondition: - type: array - items: - allOf: - - $ref: '#/components/schemas/PluginStepCondition' - - description: The conditions associated with the plugin variable. - required: - - name - - format - - description - - isExposed - - allowEmptyValue - - defaultValue - - variableType - - variableStepIndex - - variableStepIndexInPlugin - - - PluginStepCondition: - type: object - properties: - id: - type: integer - description: The unique identifier of the plugin step condition. - pluginStepId: - type: integer - description: The identifier of the plugin step associated with this condition. - conditionVariableId: - type: integer - description: The identifier of the variable on which the condition is written. - conditionType: - type: string - description: > - The type of condition. - Possible values are: - - SKIP: Skips the plugin step. - - TRIGGER: Triggers the plugin step. - - SUCCESS: Executes the plugin step on success. - - FAIL: Executes the plugin step on failure. - enum: - - SKIP - - TRIGGER - - SUCCESS - - FAIL - example: SKIP - conditionalOperator: - type: string - description: The operator used in the condition. - conditionalValue: - type: string - description: The value associated with the condition. - deleted : - type: boolean - description: Specifies whether the condition is deleted. - required: - - pluginStepId - - conditionVariableId - - conditionType - - conditionalOperator - - conditionalValue - - deleted - - PluginPipelineScript: - type: object - properties: - id: - type: integer - description: The unique identifier of the plugin pipeline script. Even if it is skipped by the user it will automatically get created with the default value - script: - type: string - description: The script associated with the plugin pipeline. - storeScriptAt: - type: string - description: The location where the script is stored. - type: - type: string - description: > - Specifies the type of script. - Possible values are: - - SHELL: Shell script. - - CONTAINER_IMAGE: Container image script. - enum: - - SHELL - - CONTAINER_IMAGE - example: - - SHELL - mountPath: - type: string - description: The path where the script is mounted. - mountCodeToContainer: - type: boolean - description: Indicates whether code is mounted to the container. - mountCodeToContainerPath: - type: string - description: The path where code is mounted to the container. - mountDirectoryFromHost: - type: boolean - description: Indicates whether a directory is mounted from the host. - containerImagePath: - type: string - description: The path to the container image. - imagePullSecretType: - type: string - description: > - Specifies the type of image pull secret. - Possible values are: - - CONTAINER_REGISTRY: Container registry image pull secret. - - SECRET_PATH: Secret path image pull secret. - enum: - - CONTAINER_REGISTRY - - SECRET_PATH - example: - - CONTAINER_REGISTRY - imagePullSecret: - type: string - description: The image pull secret. - deleted: - type: boolean - description: Indicates whether the plugin pipeline script is deleted. - pathArgPortMapping: - type: array - items: - $ref: '#/components/schemas/ScriptPathArgPortMapping' - description: The path argument port mappings associated with the plugin pipeline script. - required: - - script - - storeScriptAt - - type - - mountPath - - mountCodeToContainer - - mountCodeToContainerPath - - mountDirectoryFromHost - - containerImagePath - - imagePullSecretType - - imagePullSecret - - deleted - - pathArgPortMapping - - ScriptPathArgPortMapping: - type: object - properties: - id: - type: integer - description: The unique identifier of the script path argument port mapping. Even if it is skipped by the user it will automatically get created with the default value - typeOfMapping: - type: string - description: > - Specifies the type of mapping. - Possible values are: - - FILE_PATH - - PORT - enum: - - FILE_PATH - - PORT - example: - - PORT - filePathOnDisk: - type: string - description: The file path on the local disk. - filePathOnContainer: - type: string - description: The file path on the container. - command: - type: string - description: The command associated with the mapping. - args: - type: array - items: - type: string - description: The arguments associated with the command. - portOnLocal: - type: integer - description: The port on the local machine. - portOnContainer: - type: integer - description: The port on the container. - scriptId: - type: integer - description: The identifier of the script associated with the mapping. - required: - - id - - typeOfMapping - - filePathOnDisk - - filePathOnContainer - - command - - args - - portOnLocal - - portOnContainer - - scriptId - - Error: - title: Error - type: object - description: "A general error schema returned when status is not 200 OK" - properties: - code: - type: string - description: "a code for this particular error" - internalMessage: - type: string - description: "Optional. a message with further detail" - userMessage: - type: string - description: "Optional. A message for the user" - userDetailsMessage: - type: string - description: "Optional. Detailed User message" diff --git a/specs/global_cm_cs.yaml b/specs/global_cm_cs.yaml deleted file mode 100644 index 16cb81306a..0000000000 --- a/specs/global_cm_cs.yaml +++ /dev/null @@ -1,81 +0,0 @@ -openapi: "3.0.0" -info: - title: Global CM/CS support - version: "1.0" -paths: - /orchestrator/global/cm-cs: - post: - description: save a configmap/secret - operationId: CreateGlobalCMCSConfig - responses: - '200': - description: Successfully create given config - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/GlobalCMCSDto' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' -components: - schemas: - GlobalCMCSDto: - type: object - properties: - id: - type: integer - description: not needed in payload - name: - type: string - mountPath: - type: string - configType: - type: string - example: - - "CONFIGMAP" - - "SECRET" - type: - type: string - example: - - "environment" - - "volume" - data: - type: object - additionalProperties: - type: string - secretIngestionFor: - type: string - description: field for defining at where this config is to be ingested. If not set, "CI/CD" will be used as default. - enum: - - "CI" - - "CD" - - "CI/CD" - Error: - required: - - code - - message - properties: - code: - type: integer - format: int32 - description: Error code - message: - type: string - description: Error message diff --git a/specs/charts.yaml b/specs/helm/charts.yaml similarity index 54% rename from specs/charts.yaml rename to specs/helm/charts.yaml index ac17859e7e..924c05b183 100644 --- a/specs/charts.yaml +++ b/specs/helm/charts.yaml @@ -7,22 +7,24 @@ paths: get: description: deployed chart listing, with search filters parameters: - - name: envs + - name: envIds in: query description: environment ids required: false schema: - type: array - items: - type: string + type: string + - name: clusterIds + in: query + description: cluster ids + required: false + schema: + type: string - name: chartRepoId in: query description: chart repo ids required: false schema: - type: array - items: - type: string + type: string - name: appStoreName in: query description: chart name @@ -53,6 +55,12 @@ paths: required: false schema: type: integer + - name: appStatuses + in: query + description: app statuses filter + required: false + schema: + type: string responses: '200': description: deployed chart listing, with search filters @@ -67,30 +75,29 @@ paths: type: string description: status result: - type: array - description: deployed chart listing, with search filters - items: - $ref: '#/components/schemas/ChartInfo' + $ref: '#/components/schemas/AppListDetail' default: description: unexpected error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /orchestrator/app-store/installed-app/notes: + /orchestrator/app-store/installed-app/notes/{installed-app-id}/{env-id}: get: description: Used to fetch notes.txt for helm charts deployed via gitOps parameters: - name: env-id - in: query + in: path description: it is an environment id of app required: true - type: integer + schema: + type: integer - name: installed-app-id - in: query + in: path description: it is a installed application id required: true - type: integer + schema: + type: integer responses: '200': description: if it is able to fetch the notes.txt then status will be ok @@ -98,9 +105,14 @@ paths: application/json: schema: properties: - notes: + code: + type: integer + description: status code + status: type: string - description: it will provide notes + description: status + result: + $ref: '#/components/schemas/Notes' '500': description: error while fetching notes.txt @@ -109,64 +121,88 @@ paths: # components mentioned below components: schemas: - ChartInfo: + AppListDetail: type: object - required: - - installedAppId - - environmentId - - installedAppVersionId - - appStoreApplicationVersionId - - appStoreApplicationName - - status - - appName - - environmentName - - deployedAt - - deployedBy - - readme - - deprecated properties: - installedAppId: - type: integer - description: installed chart id - environmentId: - type: integer - description: environment id - installedAppVersionId: - type: integer - description: installed chart version id - appStoreApplicationVersionId: - type: integer - description: team/project id - appStoreApplicationName: - type: string - description: chart name externally - chartName: + clusterIds: + type: array + description: clusters to which result corresponds + items: + type: integer + applicationType: type: string - description: chart repo name - icon: + description: application type inside the array + enum: [DEVTRON-CHART-STORE, DEVTRON-APP, HELM-APP] + errored: + type: boolean + description: if data fetch for that cluster produced error + errorMsg: type: string - description: image - status: + description: error msg if client failed to fetch + helmApps: + type: array + description: all helm app list + items: + $ref: '#/components/schemas/HelmAppDetails' + devtronApps: + type: array + description: all devtron app list + items: + type: object + + HelmAppDetails: + type: object + properties: + lastDeployedAt: type: string - description: status of deployed chart + format: date-time + description: time when this application was last deployed/updated appName: type: string - description: chart name is app name for devtron - environmentName: + description: name of the helm application/helm release name + appId: + type: string + description: unique identifier for app + chartName: type: string - description: env name - deployedAt: + description: name of the chart + chartAvatar: type: string - description: deployement time - deployedBy: + description: url/location of the chart icon + projectId: + type: integer + description: unique identifier for the project, APP with no project will have id 0 + chartVersion: + type: string + description: chart version + environmentDetail: + $ref: '#/components/schemas/EnvironmentDetails' + appStatus: + type: string + description: application status + + EnvironmentDetails: + type: object + properties: + clusterName: type: string - description: user - readme: + description: cluster corresponding to the environment where application is deployed + clusterId: + type: integer + description: clusterId corresponding to the environment where application is deployed + namespace: type: string - description: readme - deprecated: + description: namespace where application is deployed + isVirtualEnvironment: type: boolean - description: is deprecated or not + description: whether environment is virtual or not + + Notes: + type: object + properties: + gitOpsNotes: + type: string + description: notes content ErrorResponse: required: diff --git a/specs/helm/deployment-chart-type.yaml b/specs/helm/deployment-chart-type.yaml new file mode 100644 index 0000000000..3ae2aadb21 --- /dev/null +++ b/specs/helm/deployment-chart-type.yaml @@ -0,0 +1,104 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Devtron Labs +paths: + /orchestrator/app/env/patch: + patch: + description: change the deployment template for an app and environment + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - envId + - appId + - targetChartRefId + properties: + envId: + type: integer + description: ID of the environment + appId: + type: integer + description: ID of the application + targetChartRefId: + type: integer + description: ID of the target chart reference + isBasicViewLocked: + type: boolean + description: Whether the basic view is locked + currentViewEditor: + type: string + enum: [BASIC, ADVANCED, UNDEFINED] + description: Current view editor type + template: + type: object + description: Deployment template configuration + + responses: + '200': + description: Successfully updated deployment template + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Whether the operation was successful + message: + type: string + description: Success message + '400': + description: Bad Request + content: + application/json: + schema: + type: object + properties: + code: + type: integer + format: int32 + description: Error code + status: + type: string + description: Error message + userDetailedMessage: + type: string + description: Detailed error message for user + '403': + description: Unauthorized User + content: + application/json: + schema: + type: object + properties: + code: + type: integer + format: int32 + description: Error code + status: + type: string + description: Error message + userDetailedMessage: + type: string + description: Detailed error message for user + '500': + description: Internal Server Error + content: + application/json: + schema: + type: object + properties: + code: + type: integer + format: int32 + description: Error code + status: + type: string + description: Error message + userDetailedMessage: + type: string + description: Detailed error message for user \ No newline at end of file diff --git a/specs/dynamic-handling-of-charts.yaml b/specs/helm/dynamic-charts.yaml similarity index 51% rename from specs/dynamic-handling-of-charts.yaml rename to specs/helm/dynamic-charts.yaml index 5271104b14..84a128b087 100644 --- a/specs/dynamic-handling-of-charts.yaml +++ b/specs/helm/dynamic-charts.yaml @@ -12,27 +12,27 @@ paths: operationId: ChartRefAutocompleteForApp parameters: - name: appId - in: query + in: path required: true schema: - type: string + type: integer + description: Application ID responses: '200': description: Successfully return all charts content: application/json: schema: + type: object properties: code: type: integer - description: status code + description: HTTP status code status: type: string - description: status + description: Status message result: - type: array - items: - $ref: '#/components/schemas/ChartRefResponse' + $ref: '#/components/schemas/ChartRefAutocompleteResponse' '400': description: Bad Request. Input Validation error/wrong request body. content: @@ -54,35 +54,79 @@ paths: components: schemas: - ChartRefResponse: + ChartRefAutocompleteResponse: type: object properties: chartRefs: type: array items: - $ref: '#/components/schemas/ChartRef' + $ref: '#/components/schemas/ChartRefAutocompleteDto' latestChartRef: type: integer + description: ID of the latest chart reference latestAppChartRef: type: integer + description: ID of the latest chart reference for the application latestEnvChartRef: type: integer + description: ID of the latest chart reference for the environment chartMetadata: + type: object + additionalProperties: + $ref: '#/components/schemas/ChartRefMetaData' + description: Map of chart name to metadata + compatibleChartTypes: type: array items: - type: string - ChartRef: + type: string + description: List of compatible chart types + + ChartRefAutocompleteDto: type: object properties: id: type: integer + description: Chart reference ID version: type: string + description: Chart version name: type: string + description: Chart name description: type: string + description: Chart description userUploaded: type: boolean + description: Whether the chart was uploaded by a user isAppMetricsSupported: - type: boolean \ No newline at end of file + type: boolean + description: Whether the chart supports application metrics + + ChartRefMetaData: + type: object + properties: + chartDescription: + type: string + description: Description of the chart + + Error: + type: object + required: + - code + - message + properties: + code: + type: string + description: Error code + example: E100 + message: + type: string + description: Error message + example: User is not authenticated + internalMessage: + type: string + description: Internal error message for debugging + userMessage: + type: string + description: User-friendly error message \ No newline at end of file diff --git a/specs/helm/provider.yaml b/specs/helm/provider.yaml new file mode 100644 index 0000000000..feee685202 --- /dev/null +++ b/specs/helm/provider.yaml @@ -0,0 +1,792 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Devtron Labs + description: Devtron API for chart provider management including chart repositories, chart groups, and chart provider configuration + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080 + +paths: + # Chart Provider APIs + /chart-provider/list: + get: + description: Get list of all chart providers + operationId: GetChartProviderList + responses: + '200': + description: List of chart providers + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ChartProviderResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /chart-provider/update: + post: + description: Toggle chart provider status + operationId: ToggleChartProvider + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ChartProviderRequest' + responses: + '200': + description: Chart provider updated successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Success status + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /chart-provider/sync-chart: + post: + description: Sync chart provider + operationId: SyncChartProvider + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ChartProviderRequest' + responses: + '200': + description: Chart provider synced successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Success status + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + # Chart Repository APIs + /chart-repo/{id}: + get: + description: Get chart repository by ID + operationId: GetChartRepoById + parameters: + - name: id + in: path + description: Chart repository ID + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: Chart repository details + content: + application/json: + schema: + $ref: '#/components/schemas/ChartRepository' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /chart-repo/list: + get: + description: Get list of all chart repositories + operationId: GetChartRepoList + responses: + '200': + description: List of chart repositories + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ChartRepository' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /chart-repo: + post: + description: Create a new chart repository + operationId: CreateChartRepo + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ChartRepositoryRequest' + responses: + '200': + description: Chart repository created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ChartRepository' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + put: + description: Update an existing chart repository + operationId: UpdateChartRepo + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ChartRepositoryRequest' + responses: + '200': + description: Chart repository updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ChartRepository' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /chart-repo/validate: + post: + description: Validate chart repository configuration + operationId: ValidateChartRepo + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ChartRepositoryRequest' + responses: + '200': + description: Chart repository configuration is valid + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Success status + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /chart-repo/sync: + post: + description: Trigger manual chart repository sync + operationId: TriggerChartSyncManual + responses: + '200': + description: Chart repository sync triggered successfully + content: + application/json: + schema: + type: object + properties: + status: + type: string + description: Sync status + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + # Chart Group APIs + /chart-group: + post: + description: Create a new chart group + operationId: CreateChartGroup + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ChartGroup' + responses: + '200': + description: Chart group created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ChartGroup' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + put: + description: Update an existing chart group + operationId: UpdateChartGroup + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ChartGroup' + responses: + '200': + description: Chart group updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ChartGroup' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /chart-group/entries: + post: + description: Save chart group entries + operationId: SaveChartGroupEntries + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ChartGroupEntries' + responses: + '200': + description: Chart group entries saved successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Success status + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /chart-group/list: + get: + description: Get list of all chart groups + operationId: GetChartGroupList + responses: + '200': + description: List of chart groups + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ChartGroup' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /chart-group/{id}: + delete: + description: Delete a chart group + operationId: DeleteChartGroup + parameters: + - name: id + in: path + description: Chart group ID + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: Chart group deleted successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Success status + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + ChartProviderResponse: + type: object + required: + - id + - name + - active + properties: + id: + type: string + description: Unique identifier of the chart provider + name: + type: string + description: Name of the chart provider + active: + type: boolean + description: Whether the chart provider is active + isEditable: + type: boolean + description: Whether the chart provider is editable + isOCIRegistry: + type: boolean + description: Whether the chart provider is an OCI registry + registryProvider: + type: string + description: Type of registry provider + enum: [DOCKER_HUB, ECR, GCR, ACR, OTHER] + + ChartProviderRequest: + type: object + required: + - id + properties: + id: + type: string + description: Unique identifier of the chart provider + isOCIRegistry: + type: boolean + description: Whether the chart provider is an OCI registry + active: + type: boolean + description: Whether to activate the chart provider + + ChartRepository: + type: object + required: + - name + - url + properties: + id: + type: integer + description: Unique identifier of the chart repository + name: + type: string + description: Name of the chart repository + url: + type: string + description: URL of the chart repository + username: + type: string + description: Username for authentication + password: + type: string + description: Password for authentication + isOCIRegistry: + type: boolean + description: Whether the repository is an OCI registry + active: + type: boolean + description: Whether the repository is active + default: + type: boolean + description: Whether this is the default repository + authMode: + type: string + description: Authentication mode + enum: [ANONYMOUS, USERNAME_PASSWORD, ACCESS_TOKEN] + + ChartRepositoryRequest: + type: object + required: + - name + - url + properties: + name: + type: string + description: Name of the chart repository + url: + type: string + description: URL of the chart repository + username: + type: string + description: Username for authentication + password: + type: string + description: Password for authentication + isOCIRegistry: + type: boolean + description: Whether the repository is an OCI registry + active: + type: boolean + description: Whether to activate the repository + default: + type: boolean + description: Whether to set as default repository + authMode: + type: string + description: Authentication mode + enum: [ANONYMOUS, USERNAME_PASSWORD, ACCESS_TOKEN] + + ChartGroup: + type: object + required: + - name + properties: + id: + type: integer + description: Unique identifier of the chart group + name: + type: string + description: Name of the chart group + description: + type: string + description: Description of the chart group + userId: + type: integer + description: ID of the user who created the group + entries: + type: array + items: + $ref: '#/components/schemas/ChartGroupEntry' + description: List of chart entries in the group + + ChartGroupEntry: + type: object + required: + - chartId + properties: + chartId: + type: integer + description: ID of the chart + chartName: + type: string + description: Name of the chart + chartVersion: + type: string + description: Version of the chart + chartRepoId: + type: integer + description: ID of the chart repository + chartRepoName: + type: string + description: Name of the chart repository + + ChartGroupEntries: + type: object + required: + - groupId + - entries + properties: + groupId: + type: integer + description: ID of the chart group + entries: + type: array + items: + $ref: '#/components/schemas/ChartGroupEntry' + description: List of chart entries to save + + ErrorResponse: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + description: Error code + message: + type: string + description: Error message + errors: + type: array + items: + $ref: '#/components/schemas/Error' + description: List of errors + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + description: Error code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/helm/repo-validation.yaml b/specs/helm/repo-validation.yaml new file mode 100644 index 0000000000..1d67ac1fd3 --- /dev/null +++ b/specs/helm/repo-validation.yaml @@ -0,0 +1,211 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Helm Chart Repo Validation +servers: + - url: http://localhost:3000/orchestrator/app-store +paths: + /repo/validate: + post: + description: Validate helm repo by checking index file + operationId: ValidateChartRepo + requestBody: + description: A JSON object containing the chart repo configuration + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ChartRepoDto' + responses: + '200': + description: Successfully validated chart repo + content: + application/json: + schema: + $ref: '#/components/schemas/DetailedErrorHelmRepoValidation' + '400': + description: Bad Request - Invalid input or validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized - User not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - User lacks required permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /repo/create: + post: + description: Validate chart repo config and save if successfully validated + operationId: ValidateAndCreateChartRepo + requestBody: + description: A JSON object containing the chart repo configuration + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ChartRepoDto' + responses: + '200': + description: Successfully created and validated chart repo + content: + application/json: + schema: + $ref: '#/components/schemas/ChartRepoDto' + '400': + description: Bad Request - Invalid input or validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized - User not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - User lacks required permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /repo/update: + post: + description: Validate configuration and update them if validation is successful + operationId: ValidateAndUpdateChartRepo + requestBody: + description: A JSON object containing the chart repo configuration + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ChartRepoDto' + responses: + '200': + description: Successfully updated and validated chart repo + content: + application/json: + schema: + $ref: '#/components/schemas/ChartRepoDto' + '400': + description: Bad Request - Invalid input or validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized - User not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - User lacks required permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + ChartRepoDto: + type: object + required: + - name + - authMode + properties: + id: + type: integer + description: Chart repo ID + name: + type: string + description: Chart repo name + minLength: 3 + url: + type: string + description: Chart repo URL + userName: + type: string + description: Username for authentication + password: + type: string + description: Password for authentication + sshKey: + type: string + description: SSH key for authentication + accessToken: + type: string + description: Access token for authentication + authMode: + type: string + description: Authentication mode + enum: [USERNAME_PASSWORD, SSH, ACCESS_TOKEN, ANONYMOUS] + active: + type: boolean + description: Whether the repo is active + default: + type: boolean + description: Whether this is the default repo + allowInsecureConnection: + type: boolean + description: Whether to allow insecure connections + + DetailedErrorHelmRepoValidation: + type: object + properties: + customErrMsg: + type: string + description: User-friendly error message + actualErrMsg: + type: string + description: Technical error message + + ErrorResponse: + type: object + required: + - code + - message + properties: + code: + type: integer + description: HTTP status code + message: + type: string + description: Error message + Error: + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/helm_repo_validation.yaml b/specs/helm_repo_validation.yaml deleted file mode 100644 index 87f5fd05d6..0000000000 --- a/specs/helm_repo_validation.yaml +++ /dev/null @@ -1,152 +0,0 @@ -openapi: "3.0.0" -info: - version: 1.0.0 - title: Helm Chart Repo Validation -servers: - - url: http://localhost:3000/orchestrator/app-store -paths: - /repo/validate: - post: - description: Validate helm repo by checking index file - operationId: ChartRepoValidate - requestBody: - description: A JSON object containing the chart repo configuration - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ChartRepoDto' - responses: - '200': - description: Successfully return the validation results - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '400': - description: Bad Request. Input Validation(decode) error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /repo/create: - post: - description: Validate chart repo config and save if successfully validated - operationId: ValidateAndCreateChartRepo - requestBody: - description: A JSON object containing the chart repo configuration - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ChartRepoDto' - responses: - '200': - description: Successfully return validation results and if validation is correct then save the configuration - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '400': - description: Bad Request. Input Validation(decode) error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /repo/update: - post: - description: Validate configuration and update them if validation is successful - operationId: ValidateAndUpdateChartRepo - requestBody: - description: A JSON object containing the chart repo configuration - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ChartRepoDto' - responses: - '200': - description: Successfully return validation results and if validation is correct then update the configuration - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '400': - description: Bad Request. Input Validation(decode) error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - -components: - schemas: - ChartRepoDto: - type: object - properties: - id: - type: integer - name: - type: string - url: - type: string - userName: - type: string - password: - type: string - sshKey: - type: string - accessToken: - type: string - active: - type: boolean - default: - type: boolean - userId: - type: integer - Error: - required: - - code - - message - properties: - code: - type: integer - description: Error code - message: - type: string - description: Error message \ No newline at end of file diff --git a/specs/historical-definitions.yaml b/specs/historical-definitions.yaml deleted file mode 100644 index 495b07245d..0000000000 --- a/specs/historical-definitions.yaml +++ /dev/null @@ -1,596 +0,0 @@ -openapi: "3.0.0" -info: - version: 1.0.0 - title: Historical Task definitions -paths: - /orchestrator/app/history/cm/{appId}/{pipelineId}: - get: - description: fetch deployment details in history for deployed config maps - operationId: FetchDeploymentDetailsForDeployedCMHistory - parameters: - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - responses: - '200': - description: Successfully return history - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ConfigMapAndSecretHistoryDto' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/app/history/cs/{appId}/{pipelineId}: - get: - description: fetch deployment details in history for deployed secrets - operationId: FetchDeploymentDetailsForDeployedCSHistory - parameters: - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - responses: - '200': - description: Successfully return history - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ConfigMapAndSecretHistoryDto' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/app/history/template/{appId}/{pipelineId}: - get: - description: fetch deployment details in history for deployed deployment templates - operationId: FetchDeploymentDetailsForDeployedTemplatesHistory - parameters: - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - responses: - '200': - description: Successfully return history - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/DeploymentTemplateHistoryDto' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/app/history/strategy/{appId}/{pipelineId}: - get: - description: fetch deployment details in history for deployed pipeline strategy - operationId: FetchDeploymentDetailsForDeployedStrategyHistory - parameters: - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - responses: - '200': - description: Successfully return history - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/PipelineStrategyHistoryDto' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/app/history/cm/{appId}/{pipelineId}/{id}: - get: - description: fetch history for deployed config map by id - operationId: FetchDeployedCMHistoryById - parameters: - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Successfully return history - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/DeploymentDetailsDataType' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/app/history/cs/{appId}/{pipelineId}/{id}: - get: - description: fetch history for deployed secret by id - operationId: FetchDeployedCSHistoryById - parameters: - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Successfully return history - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/DeploymentDetailsDataType' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/app/history/template/{appId}/{pipelineId}/{id}: - get: - description: fetch history for deployed deployment template by id - operationId: FetchDeployedTemplatesHistoryById - parameters: - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Successfully return history - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/DeploymentDetailsDataType' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/app/history/strategy/{appId}/{pipelineId}/{id}: - get: - description: fetch history for deployed pipeline strategy by id - operationId: FetchDeployedStrategyHistoryById - parameters: - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Successfully return history - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/DeploymentDetailsDataType' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - - /orchestrator/app/history/cd-config/{appId}/{pipelineId}: - get: - description: fetch history for cd config (pre/post stage config) - operationId: FetchDeployedCdConfigHistory - parameters: - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - - name: stage - in: query - required: true - schema: - type: string - enum: - - "PRE_CD" - - "POST_CD" - responses: - '200': - description: Successfully return history - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/PrePostCdScriptHistoryDto' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - -components: - schemas: - DeploymentDetailsDataType: - type: object - properties: - id: - type: integer - deployedOn: - type: string - format: timestamp - deployedBy: - type: integer - ConfigMapAndSecretHistoryDto: - type: object - properties: - id: - type: integer - pipelineId: - type: integer - dataType: - type: string - configData: - $ref: '#/components/schemas/ConfigData' - deployed: - type: boolean - deployedOn: - type: string - format: timestamp - deployedBy: - type: integer - - DeploymentTemplateHistoryDto: - type: object - properties: - id: - type: integer - pipelineId: - type: integer - imageDescriptorTemplate: - type: string - template: - type: string - templateName: - type: string - templateVersion: - type: string - isAppMetricsEnabled: - type: boolean - targetEnvironment: - type: integer - deployed: - type: boolean - deployedOn: - type: string - format: timestamp - deployedBy: - type: integer - - PipelineStrategyHistoryDto: - type: object - properties: - id: - type: integer - pipelineId: - type: integer - strategy: - type: string - config: - type: string - default: - type: boolean - deployed: - type: boolean - deployedOn: - type: string - format: timestamp - deployedBy: - type: integer - - PrePostCdScriptHistoryDto: - type: object - properties: - id: - type: integer - pipelineId: - type: integer - script: - type: string - stage: - type: string - configmapSecretNames: - $ref: '#/components/schemas/PrePostStageConfigMapSecretNames' - configmapData: - $ref: '#/components/schemas/ConfigData' - secretData: - $ref: '#/components/schemas/ConfigData' - triggerType: - type: string - execInEnv: - type: boolean - deployed: - type: boolean - deployedOn: - type: string - format: timestamp - deployedBy: - type: integer - - PrePostStageConfigMapSecretNames: - properties: - configMaps: - type: array - items: - type: string - secrets: - type: array - items: - type: string - - ConfigData: - properties: - name: - type: string - type: - type: string - external: - type: boolean - mountPath: - type: string - data: - type: string - defaultData: - type: string - defaultMountPath: - type: string - global: - type: boolean - externalType: - type: string - secretData: - type: array - items: - $ref: '#/components/schemas/ExternalSecret' - defaultSecretData: - type: array - items: - $ref: '#/components/schemas/ExternalSecret' - roleArn: - type: string - subPath: - type: boolean - filePermission: - type: string - ExternalSecret: - properties: - key: - type: string - name: - type: string - property: - type: string - isBinary: - type: boolean - - Error: - required: - - code - - message - properties: - code: - type: integer - description: Error code - message: - type: string - description: Error message \ No newline at end of file diff --git a/specs/docker-build-config-override.yaml b/specs/infrastructure/docker-build.yaml similarity index 55% rename from specs/docker-build-config-override.yaml rename to specs/infrastructure/docker-build.yaml index 2dbe846134..9fa7edee3e 100644 --- a/specs/docker-build-config-override.yaml +++ b/specs/infrastructure/docker-build.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Create App Api + title: Docker Build Config Override API paths: /orchestrator/app/wf/all/component-names/{appId}: get: @@ -75,7 +75,7 @@ paths: $ref: "#/components/schemas/Error" /orchestrator/app/ci-pipeline/patch: post: - description: Create/Update ci pipeline. + description: Create/Update CI pipeline with docker build config override operationId: PatchCiPipeline requestBody: description: A JSON object containing the pipeline configuration @@ -86,11 +86,11 @@ paths: $ref: "#/components/schemas/CiPatchRequest" responses: "200": - description: Successfully return a message stating the operation is successful. + description: Successfully updated CI pipeline content: application/json: schema: - type: string + $ref: "#/components/schemas/CiConfigRequest" "400": description: Bad Request. Validation error/wrong request body. content: @@ -135,15 +135,204 @@ components: type: string CiPatchRequest: type: object + required: + - appId + - ciPipeline properties: action: type: integer + description: Action type for the patch operation appId: type: integer + description: ID of the application appWorkflowId: type: integer + description: ID of the application workflow ciPipeline: - $ref: "#/components/schemas/CiPipelineDetails" + $ref: "#/components/schemas/CiPipeline" + userId: + type: integer + description: ID of the user performing the operation + isJob: + type: boolean + description: Whether this is a CI job + isCloneJob: + type: boolean + description: Whether this is a cloned CI job + CiPipeline: + type: object + required: + - name + - isManual + - isExternal + - scanEnabled + properties: + id: + type: integer + description: ID of the CI pipeline + name: + type: string + description: Name of the CI pipeline + isManual: + type: boolean + description: Whether the pipeline is manual + isExternal: + type: boolean + description: Whether the pipeline is external + scanEnabled: + type: boolean + description: Whether security scanning is enabled + isDockerConfigOverridden: + type: boolean + description: Whether docker config is overridden + dockerConfigOverride: + $ref: "#/components/schemas/DockerConfigOverride" + ciMaterial: + type: array + items: + $ref: "#/components/schemas/CiPipelineMaterial" + beforeDockerBuildScripts: + type: array + items: + $ref: "#/components/schemas/BuildScript" + afterDockerBuildScripts: + type: array + items: + $ref: "#/components/schemas/BuildScript" + pipelineType: + type: string + enum: [CI, CI_JOB] + description: Type of the pipeline + DockerConfigOverride: + type: object + properties: + dockerRegistry: + type: string + description: ID of the docker registry + dockerRepository: + type: string + description: Name of the docker repository + ciBuildConfig: + $ref: "#/components/schemas/CiBuildConfigBean" + CiBuildConfigBean: + type: object + properties: + id: + type: integer + description: ID of the build config + gitMaterialId: + type: integer + description: ID of the git material + buildContextGitMaterialId: + type: integer + description: ID of the build context git material + useRootBuildContext: + type: boolean + description: Whether to use root build context + ciBuildType: + type: string + enum: [SELF_DOCKERFILE_BUILD_TYPE, MANAGED_DOCKERFILE_BUILD_TYPE, SKIP_BUILD_TYPE] + description: Type of CI build + dockerBuildConfig: + $ref: "#/components/schemas/DockerBuildConfig" + buildPackConfig: + $ref: "#/components/schemas/BuildPackConfig" + DockerBuildConfig: + type: object + properties: + dockerfilePath: + type: string + description: Path to the Dockerfile + dockerfileContent: + type: string + description: Content of the Dockerfile + args: + type: object + additionalProperties: + type: string + description: Docker build arguments + targetPlatform: + type: string + description: Target platform for the build + language: + type: string + description: Programming language + languageFramework: + type: string + description: Language framework + dockerBuildOptions: + type: object + additionalProperties: + type: string + description: Docker build options + buildContext: + type: string + description: Build context path + useBuildx: + type: boolean + description: Whether to use buildx + buildxProvenanceMode: + type: string + description: Buildx provenance mode + buildxK8sDriverOptions: + type: array + items: + type: object + additionalProperties: + type: string + description: Buildx k8s driver options + BuildPackConfig: + type: object + properties: + builderId: + type: string + description: ID of the builder + language: + type: string + description: Programming language + languageVersion: + type: string + description: Language version + buildPacks: + type: array + items: + type: string + description: List of buildpacks + args: + type: object + additionalProperties: + type: string + description: Buildpack arguments + projectPath: + type: string + description: Project path + BuildScript: + type: object + properties: + name: + type: string + description: Name of the script + script: + type: string + description: Script content + index: + type: integer + description: Index of the script + CiPipelineMaterial: + type: object + properties: + gitMaterialId: + type: integer + description: ID of the git material + type: + type: string + description: Type of the material + value: + type: string + description: Value of the material + active: + type: boolean + description: Whether the material is active CiConfigRequest: type: object properties: @@ -189,25 +378,6 @@ components: type: string dockerBuildConfig: $ref: "#/components/schemas/DockerBuildConfig" - DockerBuildConfig: - type: object - properties: - gitMaterialId: - type: integer - dockerfileRelativePath: - type: string - targetPlatform: - type: string - args: - type: array - items: - type: object - properties: - Key: - type: string - Value: - type: string - description: map of docker arguments, i.e. key-value pairs CiPipelineDetails: type: object properties: @@ -260,25 +430,16 @@ components: type: string checkoutPath: type: string - BuildScript: - type: object - properties: - index: - type: integer - name: - type: string - script: - type: string - reportDirectoryPath: - type: string Error: - required: - - code - - message + type: object properties: code: type: integer + format: int32 description: Error code - message: + status: + type: string + description: Error message + userDetailedMessage: type: string - description: Error message \ No newline at end of file + description: Detailed error message for user \ No newline at end of file diff --git a/specs/image-tagging.yaml b/specs/infrastructure/image-tagging.yaml similarity index 84% rename from specs/image-tagging.yaml rename to specs/infrastructure/image-tagging.yaml index 0999dfd53a..a53a834634 100644 --- a/specs/image-tagging.yaml +++ b/specs/infrastructure/image-tagging.yaml @@ -11,8 +11,7 @@ paths: content: application/json: schema: - items: - $ref: "#/components/schemas/ImageTaggingRequestDTO" + $ref: "#/components/schemas/ImageTaggingRequestDTO" responses: "200": description: success on tags and comment creation for the given artifact. @@ -34,7 +33,7 @@ paths: content: application/json: schema: - $ref: "#components/schemas/ImageTaggingResponseDTO" + $ref: "#/components/schemas/ImageTaggingResponseDTO" "500": description: will get this response if any failure occurs at server side. "403": @@ -61,7 +60,11 @@ components: appReleaseTags: type: array items: - $ref: '#/components/schemas/ReleaseTag' + type: string + description: List of unique tag names in the app + hideImageTaggingHardDelete: + type: boolean + description: Whether hard delete of tags is hidden @@ -109,15 +112,19 @@ components: items: $ref: '#/components/schemas/ReleaseTag' description: tag objects requested for creation - updateTags: + softDeleteTags: + type: array + items: + $ref: '#/components/schemas/ReleaseTag' + description: tag objects requested for soft deletion + hardDeleteTags: type: array items: $ref: '#/components/schemas/ReleaseTag' - description: tag objects requested for deletion + description: tag objects requested for hard deletion imageComment: type: object - items: - $ref: '#/components/schemas/ImageComment' + $ref: '#/components/schemas/ImageComment' description: image comment data diff --git a/specs/jobs.yaml b/specs/jobs.yaml deleted file mode 100644 index 635136ad5a..0000000000 --- a/specs/jobs.yaml +++ /dev/null @@ -1,194 +0,0 @@ -openapi: "3.0.0" -info: - title: Jobs - version: "1.0" -paths: - /orchestrator/job: - post: - description: Create and clones a job - requestBody: - required: true - content: - application/json: - schema: - items: - $ref: "#/components/schemas/CreateJob" - responses: - "200 OK": - description: Used to give response once a job is created - content: - application/json: - schema: - $ref: "#/components/schemas/ActionResponse" - /orchestrator/job/list: - post: - description: Get the list of all the jobs by applying filter - requestBody: - required: true - content: - application/json: - schema: - items: - $ref: "#/components/schemas/JobList" - response: - description: Used to give response of list of jobs - content: - application/json: - schema: - items: - $ref: "#/components/schemas/JobListResponse" - /orchestrator/job/ci-pipeline/list/{jobId}: - get: - description: fetch details of job ci-pipelines for the overview page - parameters: - - name: jobId - in: path - required: true - schema: - type: integer -#components -components: - schemas: - CreateJob: - type: object - properties: - appName: - type: string - description: Used to give the name of the job - example: "my-job-1" - isJob: - type: boolean - description: States whether its a job or an app - example: true - teamId: - type: integer - description: Used to give team id - example: 1 - templateId: - type: integer - description: Used to give the id of the job it wants to clone - example: 18 - labels: - type: []label - label: - key: - type: string - example: "hello" - value: - type: string - example: "world" - propogate: - type: bool - example: false - description: - type: string - description: Used to give the description of the job once it is made. - example: "This is my first Job" - ActionResponse: - name: result - type: object - properties: - id: - type: integer - description: Used to give the id of job once its created - example: 25 - appName: - type: string - description: Used to give the name of job once its created - example: "my-job-1" - material: - type: []gitMaterial - gitMaterial: - name: - type: string - url: - type: string - id: - type: integer - gitProviderId: - type: integer - checkoutPath: - type: string - fetchSubmodules: - type: bool - isUsedInCiConfig: - type: bool - teamId: - type: integer - description: Used to give the team id - example: 1 - templateId: - type: integer - description: Used to give the templateId - example: 0 - description: - type: string - description: Used to give the description of the job once it is made. - example: "This is my first Job" - isJob: - type: boolean - description: used to tell whether it is a job or an app - example: true - JobList: - type: object - properties: - teams: - type: [] integer - description: used to give the project id - example: [1,2] - appStatuses: - type: [] string - description: used to give the filter of app ci-build status - example: ["Succeeded", "Starting"] - sortBy: - type: string - description: used to give the sort by constraint - example: "appNameSort" - sortOrder: - type: string - description: used to give the sort order - example: "ASC" - offset: - type: integer - description: used to give the number from which we want our job (if the offset is 20 means we want list of jobs from 20) - example: 0 - size: - type: integer - description: used to give the number of jobs we want - example: 20 - - JobListResponse: - type: object - properties: - jobContainers: - type: [] jobContainer - jobContainer: - properties: - jobId: - type: integer - jobName: - type: string - description: - type: string - ciPipelines: - type: []jobCiPipeline - jobCiPipeline: - properties: - ciPipelineId: - type: integer - status: - type: string - lastRunAt: - type: time.Time - lastSuccessAt: - type: time.Time - jobCount: - type: integer - - - - - - - - diff --git a/specs/jobs/batch.yaml b/specs/jobs/batch.yaml new file mode 100644 index 0000000000..68e23fd8d6 --- /dev/null +++ b/specs/jobs/batch.yaml @@ -0,0 +1,411 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Devtron Labs + description: Devtron API for batch and bulk operations + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080/orchestrator +paths: + /operate: + post: + description: Execute batch operations on applications and workflows + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BatchOperationRequest' + responses: + '200': + description: Batch operation response + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + type: string + description: operation result + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /bulk/v1beta1/application/dryrun: + post: + description: Get impacted apps for bulk update (dry run) + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkUpdatePayload' + responses: + '200': + description: Impacted apps response + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: '#/components/schemas/ImpactedObjectsResponse' + + /bulk/v1beta1/application: + post: + description: Execute bulk update on applications + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkUpdateScript' + responses: + '200': + description: Bulk update response + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: '#/components/schemas/BulkUpdateResponse' + +components: + schemas: + BatchOperationRequest: + type: object + properties: + apiVersion: + type: string + description: API version + pipelines: + type: array + description: List of pipelines to operate on + items: + $ref: '#/components/schemas/Pipeline' + + BulkUpdateScript: + type: object + properties: + apiVersion: + type: string + description: API version + kind: + type: string + description: Resource kind + spec: + $ref: '#/components/schemas/BulkUpdatePayload' + + BulkUpdatePayload: + type: object + properties: + includes: + type: array + description: Apps to include + items: + type: string + excludes: + type: array + description: Apps to exclude + items: + type: string + envIds: + type: array + description: Environment IDs + items: + type: integer + global: + type: boolean + description: Apply globally + deploymentTemplate: + $ref: '#/components/schemas/DeploymentTemplateSpec' + configMap: + $ref: '#/components/schemas/ConfigMapSpec' + secret: + $ref: '#/components/schemas/SecretSpec' + + Pipeline: + type: object + properties: + build: + $ref: '#/components/schemas/Build' + deployment: + $ref: '#/components/schemas/Deployment' + + Build: + type: object + properties: + apiVersion: + type: string + operation: + $ref: '#/components/schemas/Operation' + dockerArguments: + type: object + trigger: + $ref: '#/components/schemas/Trigger' + buildMaterials: + type: array + items: + $ref: '#/components/schemas/BuildMaterial' + + BuildMaterial: + type: object + required: + - source + - gitMaterialUrl + properties: + source: + type: object + required: + - type + - value + properties: + type: + type: string + value: + type: string + enum: + - BranchFixed + - BranchRegex + - TagAny + - TagRegex + gitMaterialUrl: + type: string + + Deployment: + type: object + properties: + apiVersion: + type: string + operation: + $ref: '#/components/schemas/Operation' + trigger: + $ref: '#/components/schemas/Trigger' + strategy: + $ref: '#/components/schemas/DeploymentStrategy' + configMaps: + type: array + items: + $ref: '#/components/schemas/DataHolder' + secrets: + type: array + items: + $ref: '#/components/schemas/DataHolder' + + Operation: + type: string + description: Action to be taken on the component + enum: + - create + - delete + - update + - append + - clone + + Trigger: + type: string + description: How will this action be initiated + enum: + - manual + - automatic + + DeploymentStrategy: + type: object + properties: + blueGreen: + $ref: '#/components/schemas/BlueGreenStrategy' + canary: + $ref: '#/components/schemas/CanaryStrategy' + rolling: + $ref: '#/components/schemas/RollingStrategy' + recreate: + $ref: '#/components/schemas/RecreateStrategy' + default: + type: string + enum: + - BLUE-GREEN + - ROLLING + - CANARY + - RECREATE + + BlueGreenStrategy: + type: object + properties: + autoPromotionSeconds: + type: integer + format: int32 + scaleDownDelaySeconds: + type: integer + format: int32 + previewReplicaCount: + type: integer + format: int32 + autoPromotionEnabled: + type: boolean + + CanaryStrategy: + type: object + properties: + maxSurge: + type: string + maxUnavailable: + type: integer + format: int32 + steps: + type: array + items: + type: object + properties: + setWeight: + type: integer + format: int32 + pause: + type: object + properties: + duration: + type: integer + format: int32 + + RecreateStrategy: + type: object + + RollingStrategy: + type: object + properties: + maxSurge: + type: string + maxUnavailable: + type: integer + format: int32 + + DataHolder: + type: object + properties: + apiVersion: + type: string + operation: + $ref: '#/components/schemas/Operation' + type: + type: string + external: + type: boolean + mountPath: + type: string + global: + type: boolean + externalType: + type: string + data: + type: object + + DeploymentTemplateSpec: + type: object + properties: + patchJson: + type: string + description: JSON patch to apply + + ConfigMapSpec: + type: object + properties: + patchJson: + type: string + description: JSON patch to apply + + SecretSpec: + type: object + properties: + patchJson: + type: string + description: JSON patch to apply + + ImpactedObjectsResponse: + type: object + properties: + deploymentTemplate: + type: array + items: + type: string + configMap: + type: array + items: + type: string + secret: + type: array + items: + type: string + + BulkUpdateResponse: + type: object + properties: + deploymentTemplate: + $ref: '#/components/schemas/DeploymentTemplateBulkUpdateResponse' + configMap: + $ref: '#/components/schemas/CmAndSecretBulkUpdateResponse' + secret: + $ref: '#/components/schemas/CmAndSecretBulkUpdateResponse' + + DeploymentTemplateBulkUpdateResponse: + type: object + properties: + message: + type: array + items: + type: string + failure: + type: array + items: + type: string + + CmAndSecretBulkUpdateResponse: + type: object + properties: + message: + type: array + items: + type: string + failure: + type: array + items: + type: string + + ErrorResponse: + type: object + properties: + code: + type: integer + status: + type: string + errors: + type: array + items: + type: object + + + diff --git a/specs/jobs/bulk-actions.yaml b/specs/jobs/bulk-actions.yaml new file mode 100644 index 0000000000..896ef41724 --- /dev/null +++ b/specs/jobs/bulk-actions.yaml @@ -0,0 +1,268 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Devtron Labs + description: Devtron API for bulk actions - Hibernate, UnHibernate, Deploy Latest Builds + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080/orchestrator/batch +paths: + /v1beta1/hibernate: + post: + description: Bulk Hibernate all apps for specific environment + operationId: BulkHibernate + requestBody: + description: bulk hibernate + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkApplicationForEnvironmentPayload' + responses: + '200': + description: Successfully hibernated all impacted apps. + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: '#/components/schemas/BulkApplicationHibernateUnhibernateForEnvironmentResponse' + '400': + description: Bad Request. Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /v1beta1/unhibernate: + post: + description: Bulk Unhibernate all apps for specific environment + operationId: BulkUnhibernate + requestBody: + description: bulk unhibernate + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkApplicationForEnvironmentPayload' + responses: + '200': + description: Successfully unhibernated all impacted apps. + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: '#/components/schemas/BulkApplicationHibernateUnhibernateForEnvironmentResponse' + '400': + description: Bad Request. Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /v1beta1/deploy: + post: + description: Bulk Deploy all apps to the latest build image for specific environment + operationId: BulkDeploy + requestBody: + description: bulk deploy + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkApplicationForEnvironmentPayload' + responses: + '200': + description: Successfully deploy all impacted apps. + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: '#/components/schemas/BulkApplicationForEnvironmentResponse' + '400': + description: Bad Request. Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + +components: + schemas: + BulkApplicationForEnvironmentPayload: + type: object + properties: + appIdIncludes: + type: array + items: + type: integer + description: app ids to include + appIdExcludes: + type: array + items: + type: integer + description: app ids to exclude + envId: + type: integer + description: environment id + envName: + type: string + description: environment name + appNamesIncludes: + type: array + items: + type: string + description: app names to include + appNamesExcludes: + type: array + items: + type: string + description: app names to exclude + invalidateCache: + type: boolean + description: whether to invalidate cache + deployLatestEligibleArtifact: + type: boolean + description: whether to deploy latest eligible artifact + + BulkApplicationHibernateUnhibernateForEnvironmentResponse: + type: object + properties: + appIdIncludes: + type: array + items: + type: integer + appIdExcludes: + type: array + items: + type: integer + envId: + type: integer + envName: + type: string + appNamesIncludes: + type: array + items: + type: string + appNamesExcludes: + type: array + items: + type: string + invalidateCache: + type: boolean + deployLatestEligibleArtifact: + type: boolean + response: + type: array + description: response array with operation results + items: + type: object + additionalProperties: true + + BulkApplicationForEnvironmentResponse: + type: object + properties: + appIdIncludes: + type: array + items: + type: integer + appIdExcludes: + type: array + items: + type: integer + envId: + type: integer + envName: + type: string + appNamesIncludes: + type: array + items: + type: string + appNamesExcludes: + type: array + items: + type: string + invalidateCache: + type: boolean + deployLatestEligibleArtifact: + type: boolean + response: + type: object + description: response map with operation results + additionalProperties: + type: object + additionalProperties: + type: boolean + + Error: + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/bulk_update.yaml b/specs/jobs/bulk-update.yaml similarity index 76% rename from specs/bulk_update.yaml rename to specs/jobs/bulk-update.yaml index 78de81d0ce..0ab0e5ed2b 100644 --- a/specs/bulk_update.yaml +++ b/specs/jobs/bulk-update.yaml @@ -26,7 +26,9 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/BulkUpdateSeeExampleResponse' + type: array + items: + $ref: '#/components/schemas/BulkUpdateSeeExampleResponse' '500': description: Internal Server Error content: @@ -50,9 +52,7 @@ paths: content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/ImpactedObjectsResponse' + $ref: '#/components/schemas/ImpactedObjectsResponse' '400': description: Bad Request. Validation error/wrong request body. content: @@ -115,7 +115,7 @@ components: required: - Script properties: - resource: + operation: type: string description: Resource from url path, i.e. {apiVersion} & {kind} script: @@ -158,41 +158,43 @@ components: global: type: boolean description: Global flag for updating dependent apps - DeploymentTemplate: + deploymentTemplate: $ref: '#/components/schemas/Tasks' - ConfigMaps: - type: object - properties: - names: - type: array - items: - type: string - description : Name of All ConfigMaps to be updated - tasks: - $ref: '#/components/schemas/Spec' - Secrets: - type: object - properties: - names: - type: array - items: - type: string - description : Name of All Secrets to be updated - tasks: - $ref: '#/components/schemas/Spec' + configMap: + $ref: '#/components/schemas/CmAndSecret' + secret: + $ref: '#/components/schemas/CmAndSecret' Tasks: type: object properties: spec: $ref: '#/components/schemas/Spec' description: Spec of the Task + CmAndSecret: + type: object + properties: + spec: + $ref: '#/components/schemas/CmAndSecretSpec' + description: Spec of the ConfigMap/Secret + CmAndSecretSpec: + type: object + required: + - names + properties: + names: + type: array + items: + type: string + description: Names of all configmaps/secrets to be updated + patchData: + type: string + description: string with details of the patch to be used for updating Spec: type: object properties: patchData: type: string description: string with details of the patch to be used for updating - NameIncludesExcludes: type: object properties: @@ -249,91 +251,58 @@ components: type: object properties: deploymentTemplate: - $ref: '#/components/schemas/DeploymentTemplateBulkUpdateResponse' - configMap: - $ref: '#/components/schemas/CmAndSecretBulkUpdateResponse' - secret: - $ref: '#/components/schemas/CmAndSecretBulkUpdateResponse' - DeploymentTemplateBulkUpdateResponse: - type: object - properties: - message: - type: array - items: - type: string - description: All top-level messages in response of bulk update action - failure: type: array items: $ref: '#/components/schemas/DeploymentTemplateBulkUpdateResponseForOneApp' - description: Details of all apps on which bulk update failed - successful: - type: array - items: - $ref: '#/components/schemas/DeploymentTemplateBulkUpdateResponseForOneApp' - description: Details of all apps on which bulk update applied successfully - CmAndSecretBulkUpdateResponse: - type: object - properties: - message: - type: array - items: - type: string - description: All top-level messages in response of bulk update action - failure: + configMap: type: array items: $ref: '#/components/schemas/CmAndSecretBulkUpdateResponseForOneApp' - description: Details of all apps on which bulk update failed - successful: + secret: type: array items: $ref: '#/components/schemas/CmAndSecretBulkUpdateResponseForOneApp' - description: Details of all apps on which bulk update applied successfully DeploymentTemplateBulkUpdateResponseForOneApp: type: object properties: appId: type: integer - description: Id of the concerned app + description: Id of the impacted app appName: type: string - description: Name of the concerned app + description: Name of the impacted app envId: - type: integer - description: Env ID of the concerned app + type: string + description: Env Id of the impacted app message: type: string - description: App-level message for the concerned app + description: Message indicating success or failure of the update CmAndSecretBulkUpdateResponseForOneApp: type: object properties: appId: type: integer - description: Id of the concerned app + description: Id of the impacted app appName: type: string - description: Name of the concerned app + description: Name of the impacted app envId: - type: integer - description: Env ID of the concerned app + type: string + description: Env Id of the impacted app names: type: array items: type: string - description: Names of all configmaps/secrets + description: Names of all configmaps/secrets impacted message: type: string - description: App-level message for the concerned app - + description: Message indicating success or failure of the update Error: - required: - - code - - message + type: object properties: code: type: integer - description: Error code + description: HTTP status code message: type: string description: Error message \ No newline at end of file diff --git a/specs/jobs/core.yaml b/specs/jobs/core.yaml new file mode 100644 index 0000000000..eb9935e88f --- /dev/null +++ b/specs/jobs/core.yaml @@ -0,0 +1,266 @@ +openapi: "3.0.0" +info: + title: Devtron Labs + description: Devtron API for job management + version: "1.0" + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080/orchestrator +paths: + /job: + post: + description: Create and clones a job + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateJob" + responses: + '200': + description: Used to give response once a job is created + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: "#/components/schemas/ActionResponse" + /job/list: + post: + description: Get the list of all the jobs by applying filter + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/JobListRequest" + responses: + '200': + description: Used to give response of list of jobs + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: "#/components/schemas/JobListResponse" + /job/ci-pipeline/list/{jobId}: + get: + description: fetch details of job ci-pipelines for the overview page + parameters: + - name: jobId + in: path + required: true + schema: + type: integer + responses: + '200': + description: Job CI pipeline details + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + type: array + items: + $ref: "#/components/schemas/JobCiPipeline" +components: + schemas: + CreateJob: + type: object + required: + - appName + - teamId + - isJob + properties: + appName: + type: string + description: Used to give the name of the job + example: "my-job-1" + isJob: + type: boolean + description: States whether its a job or an app + example: true + teamId: + type: integer + description: Used to give team id + example: 1 + templateId: + type: integer + description: Used to give the id of the job it wants to clone + example: 18 + labels: + type: array + description: Job labels + items: + $ref: "#/components/schemas/JobLabel" + description: + type: string + description: Used to give the description of the job once it is made. + example: "This is my first Job" + + JobLabel: + type: object + properties: + key: + type: string + example: "hello" + value: + type: string + example: "world" + propagate: + type: boolean + example: false + ActionResponse: + type: object + properties: + id: + type: integer + description: Used to give the id of job once its created + example: 25 + appName: + type: string + description: Used to give the name of job once its created + example: "my-job-1" + material: + type: array + description: Git materials + items: + $ref: "#/components/schemas/GitMaterial" + teamId: + type: integer + description: Used to give the team id + example: 1 + templateId: + type: integer + description: Used to give the templateId + example: 0 + description: + type: string + description: Used to give the description of the job once it is made. + example: "This is my first Job" + isJob: + type: boolean + description: used to tell whether it is a job or an app + example: true + + GitMaterial: + type: object + properties: + name: + type: string + url: + type: string + id: + type: integer + gitProviderId: + type: integer + checkoutPath: + type: string + fetchSubmodules: + type: boolean + isUsedInCiConfig: + type: boolean + JobListRequest: + type: object + properties: + teams: + type: array + description: used to give the project id + items: + type: integer + example: [1,2] + appStatuses: + type: array + description: used to give the filter of app ci-build status + items: + type: string + example: ["Succeeded", "Starting"] + sortBy: + type: string + description: used to give the sort by constraint + example: "appNameSort" + sortOrder: + type: string + description: used to give the sort order + example: "ASC" + offset: + type: integer + description: used to give the number from which we want our job (if the offset is 20 means we want list of jobs from 20) + example: 0 + size: + type: integer + description: used to give the number of jobs we want + example: 20 + + JobListResponse: + type: object + properties: + jobContainers: + type: array + description: List of job containers + items: + $ref: "#/components/schemas/JobContainer" + jobCount: + type: integer + description: Total count of jobs + + JobContainer: + type: object + properties: + jobId: + type: integer + jobName: + type: string + description: + type: string + ciPipelines: + type: array + items: + $ref: "#/components/schemas/JobCiPipeline" + + JobCiPipeline: + type: object + properties: + ciPipelineId: + type: integer + status: + type: string + lastRunAt: + type: string + format: date-time + lastSuccessAt: + type: string + format: date-time + + + + + + + + diff --git a/specs/k8s-resource-apis.yaml b/specs/k8s-resource-apis.yaml deleted file mode 100644 index 403800bff5..0000000000 --- a/specs/k8s-resource-apis.yaml +++ /dev/null @@ -1,35 +0,0 @@ -openapi: "3.0.2" -info: - title: version api - version: "1.0" -paths: - /orchestrator/k8s/resource/inception/info: - get: - responses: - "200": - description: this api give you inception pod info, such as pod name - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: object - description: string - $ref: '#/components/schemas/ResourceInfo' - -components: - schemas: - ResourceInfo: - type: object - required: - - podName - properties: - podName: - type: string - description: pod name \ No newline at end of file diff --git a/specs/k8s_apis-spec.yaml b/specs/k8s_apis-spec.yaml deleted file mode 100644 index 23d2a356be..0000000000 --- a/specs/k8s_apis-spec.yaml +++ /dev/null @@ -1,673 +0,0 @@ -openapi: "3.0.3" -info: - version: 1.0.0 - title: Devtron Labs -paths: - /orchestrator/k8s/resource: - post: - description: this api will be used for fetching all kind of manifest. - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - "200": - description: manifest fetch responces - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - $ref: '#/components/schemas/ResourceGetResponse' - put: - description: this api will be used for edit requested manifest. - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - "200": - description: manifest edit responces - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - $ref: '#/components/schemas/ResourceGetResponse' - /orchestrator/k8s/resource/create: - post: - description: this api will be used for applying desired manifest - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - "200": - description: create resource response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - $ref: '#/components/schemas/ResourceGetResponse' - /orchestrator/k8s/resource/delete: - post: - description: this api will be used for delete any resource. - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - "200": - description: manifest fetch responces - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - $ref: '#/components/schemas/ResourceGetResponse' - /orchestrator/k8s/events: - post: - description: this api will be used for fetching events for resources. - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - "200": - description: events success - content: - text/event-stream: - schema: - $ref: "#/components/schemas/EventsResponseObject" - /orchestrator/k8s/pods/logs/{podName}: - get: - description: this api will be used for fetching logs for container. - parameters: - - name: podName - in: path - required: true - schema: - type: string - - name: containerName - in: query - required: true - schema: - type: string - - name: appId - in: query - required: false - schema: - type: string - - name: clusterId - in: query - required: false - schema: - type: integer - - name: namespace - in: query - description: it is required when clusterId is passed - required: false - schema: - type: string - - name: follow - in: query - schema: - type: boolean - - name: sinceSeconds - in: query - schema: - type: integer - - name: tailLines - in: query - schema: - type: integer - responses: - "200": - description: events success - content: - text/event-stream: - schema: - $ref: "#/components/schemas/LogsResponseObject" - /orchestrator/k8s/pod/exec/session/{identifier}/{namespace}/{pod}/{shell}/{container}: - get: - description: get session for the terminal - parameters: - - in: path - name: identifier - schema: - type: string - required: true - description: application id or cluster id - example: "2|devtroncd|devtron or 3" - - in: path - name: namespace - schema: - type: string - required: true - description: namespace name - example: "devtroncd" - - in: path - name: pod - schema: - type: string - required: true - description: pod name - example: inception-58d44d99fd-tfw4s - - in: path - name: shell - schema: - type: string - oneOf: - - "bash" - - "sh" - - "powershell" - - "cmd" - required: true - description: shell to invoke - example: "bash" - - in: path - name: container - schema: - type: string - required: true - description: name of the container - example: "devtron" - responses: - 200: - description: session id - content: - application/json: - schema: - $ref: "#/components/schemas/TerminalMessage" - /orchestrator/k8s/api-resources/{clusterId}: - get: - description: Get All api resources for given cluster Id - parameters: - - name: clusterId - in: path - description: cluster Id - required: true - schema: - type: integer - format: int64 - responses: - "200": - description: Successfully fetched All api resources for given cluster Id - content: - application/json: - schema: - $ref: "#/components/schemas/GetAllApiResourcesResponse" - /orchestrator/k8s/resource/list: - post: - description: this api will be used for fetching all kind of manifest. - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - '200': - description: list response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: array - description: app list - items: - $ref: '#/components/schemas/ClusterResourceListResponse' - /orchestrator/k8s/resources/rotate: - post: - description: this api will be used to rotate pods for provided resources - parameters: - - in: query - name: appId - description: app id - required: true - schema: - type: string - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RotatePodRequest' - responses: - '200': - description: response in array of each resource - content: - application/json: - schema: - $ref: "#/components/schemas/RotatePodResponse" - /orchestrator/k8s/resources/apply: - post: - description: this api will be used to apply the resources in cluster - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ApplyResourcesRequest' - responses: - '200': - description: response in array of each resource - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/ApplyResourcesResponse" -components: - schemas: - TerminalMessage: - type: object - properties: - Op: - type: string - Data: - type: string - SessionID: - type: string - ResourceRequestObject: - type: object - properties: - appId: - type: string - clusterId: - type: number - description: clusterId is used when request is for direct cluster (when appId is not supplied) - k8sRequest: - $ref: '#/components/schemas/K8sRequestObject' - K8sRequestObject: - type: object - properties: - resourceIdentifier: - type: object - properties: - groupVersionKind: - type: object - properties: - Group: - type: string - Version: - type: string - Kind: - type: string - namespace: - type: string - name: - type: string - required: - - name - podLogsRequest: - type: object - properties: - containerName: - type: string - patch: - type: string - ResourceGetResponse: - type: object - properties: - manifestResponse: - $ref: '#/components/schemas/ManifestResponse' - secretViewAccess: - type: boolean - description: > - Indicates whether a user can see obscured secret values or not. - required: - - manifestResponse - - secretViewAccess - ManifestResponse: - type: object - properties: - manifest: - type: object - properties: - apiVersion: - type: string - data: - type: object - properties: - envoy.yaml: - type: string - kind: - type: string - metadata: - type: object - properties: - annotations: - type: object - properties: - meta.helm.sh/release-name: - type: string - meta.helm.sh/release-namespace: - type: string - creationTimestamp: - type: string - format: date-time - labels: - type: object - properties: - app: - type: string - app.kubernetes.io/managed-by: - type: string - chart: - type: string - heritage: - type: string - release: - type: string - name: - type: string - namespace: - type: string - resourceVersion: - type: string - selfLink: - type: string - uid: - type: string - EventsResponseObject: - type: object - properties: - events: - type: object - properties: - metadata: - type: object - properties: - selfLink: - type: string - resourceVersion: - type: string - items: - type: array - items: - type: object - properties: - metadata: - type: object - properties: - name: - type: string - namespace: - type: string - selfLink: - type: string - uid: - type: string - resourceVersion: - type: string - creationTimestamp: - type: string - format: date-time - managedFields: - type: array - items: - type: object - properties: - manager: - type: string - operation: - type: string - apiVersion: - type: string - time: - type: string - format: date-time - involvedObject: - type: object - properties: - kind: - type: string - namespace: - type: string - name: - type: string - uid: - type: string - apiVersion: - type: string - resourceVersion: - type: string - reason: - type: string - message: - type: string - source: - type: object - properties: - component: - type: string - firstTimestamp: - type: string - format: date-time - lastTimestamp: - type: string - format: date-time - count: - type: integer - format: int32 - type: - type: string - eventTime: - type: string - format: nullable - reportingComponent: - type: string - reportingInstance: - type: string - LogsResponseObject: - type: object - properties: - logs: - type: array - items: - type: object - properties: - id: - type: string - type: - type: string - data: - type: string - time: - type: string - GetAllApiResourcesResponse: - type: object - properties: - apiResources: - type: array - items: - $ref: "#/components/schemas/K8sApiResource" - allowedAll: - type: boolean - description: whether all api-resources allowed for this user - example: true - nullable: false - K8sApiResource: - type: object - properties: - gvk: - $ref: '#/components/schemas/GroupVersionKind' - namespaced: - type: boolean - description: whether this api resource is in namespaces scope or global - example: true - nullable: false - GroupVersionKind: - type: object - properties: - group: - type: string - description: group of the api-resource - example: "apps" - nullable: false - version: - type: string - description: version of the api-resource - example: "v1" - nullable: false - kind: - type: string - description: kind of the api-resource - example: "pod" - nullable: false - ClusterResourceListResponse: - type: object - properties: - headers: - type: array - items: - type: string - data: - type: array - items: - type: object - properties: - header-name: - type: string - description: each object from data key contains the objects keys length is equal to headers length - RotatePodRequest: - type: object - properties: - clusterId: - type: number - description: cluster Id - example: 1 - nullable: false - resources: - type: array - items: - type: object - properties: - groupVersionKind: - type: object - properties: - Group: - type: string - Version: - type: string - Kind: - type: string - namespace: - type: string - name: - type: string - required: - - name - RotatePodResponse: - type: object - properties: - containsError: - type: boolean - description: contains error - example: true - responses: - type: array - items: - type: object - properties: - groupVersionKind: - type: object - properties: - Group: - type: string - Version: - type: string - Kind: - type: string - namespace: - type: string - name: - type: string - errorResponse: - type: string - ApplyResourcesRequest: - type: object - properties: - clusterId: - type: number - description: cluster Id - example: 1 - nullable: false - manifest: - type: string - description: manifest of the resources (yamls saparated by ---) - example: "" - nullable: false - ApplyResourcesResponse: - type: object - properties: - kind: - type: string - description: kind of the resource - example: "pod" - nullable: false - name: - type: string - description: name of the resource - example: "someName" - nullable: false - error: - type: string - description: error in the operation of this resource - example: "someError" - nullable: true - isUpdate: - type: boolean - description: whether this resource was updated - example: true - nullable: false \ No newline at end of file diff --git a/specs/kubernetes/access-policy.yaml b/specs/kubernetes/access-policy.yaml new file mode 100644 index 0000000000..ce0676acb7 --- /dev/null +++ b/specs/kubernetes/access-policy.yaml @@ -0,0 +1,288 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Cluster Access Policy Management + description: API for managing cluster access policies and roles + +paths: + /orchestrator/cluster/access: + post: + summary: Create a new cluster access policy + operationId: CreateClusterAccessPolicy + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterAccessPolicy' + responses: + '200': + description: Successfully created cluster access policy + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterAccessPolicy' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + put: + summary: Update an existing cluster access policy + operationId: UpdateClusterAccessPolicy + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterAccessPolicy' + responses: + '200': + description: Successfully updated cluster access policy + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterAccessPolicy' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/cluster/access/{id}: + get: + summary: Get a cluster access policy by ID + operationId: GetClusterAccessPolicy + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully retrieved cluster access policy + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterAccessPolicy' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Cluster access policy not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + delete: + summary: Delete a cluster access policy + operationId: DeleteClusterAccessPolicy + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully deleted cluster access policy + content: + application/json: + schema: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Cluster access policy not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/cluster/access/list: + get: + summary: List all cluster access policies + operationId: ListClusterAccessPolicies + parameters: + - name: clusterId + in: query + required: false + schema: + type: integer + - name: namespace + in: query + required: false + schema: + type: string + responses: + '200': + description: Successfully retrieved cluster access policies + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterAccessPolicy' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + ClusterAccessPolicy: + type: object + required: + - cluster + - action + properties: + id: + type: integer + description: Unique identifier for the policy + cluster: + type: string + description: Name of the cluster + namespace: + type: string + description: Namespace name. For multiple namespaces, use comma-separated values. Empty string for all namespaces. + group: + type: string + description: Group name. For multiple groups, use comma-separated values. Empty string for all groups. + kind: + type: string + description: Resource kind. For multiple kinds, use comma-separated values. Empty string for all kinds. + resource: + type: string + description: Resource name. For multiple resources, use comma-separated values. Empty string for all resources. + action: + type: string + description: Type of access role + enum: ["view", "edit", "admin"] + userId: + type: integer + description: ID of the user who created/updated the policy + createdOn: + type: string + format: date-time + description: Timestamp when the policy was created + updatedOn: + type: string + format: date-time + description: Timestamp when the policy was last updated + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/kubernetes/apis.yaml b/specs/kubernetes/apis.yaml new file mode 100644 index 0000000000..b7b703229c --- /dev/null +++ b/specs/kubernetes/apis.yaml @@ -0,0 +1,498 @@ +openapi: "3.0.3" +info: + version: 1.0.0 + title: Devtron Labs +paths: + /orchestrator/k8s/resource: + post: + summary: Get Kubernetes resource manifest + description: Fetches the manifest for a specified Kubernetes resource + operationId: GetResource + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceRequestObject' + responses: + "200": + description: Resource manifest + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceGetResponse' + "400": + description: Bad request + "401": + description: Unauthorized + "403": + description: Forbidden + "500": + description: Internal server error + put: + summary: Update Kubernetes resource + description: Updates an existing Kubernetes resource manifest + operationId: UpdateResource + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceRequestObject' + responses: + "200": + description: Updated resource manifest + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceGetResponse' + "400": + description: Bad request + "401": + description: Unauthorized + "403": + description: Forbidden + "500": + description: Internal server error + /orchestrator/k8s/resource/create: + post: + summary: Create Kubernetes resource + description: Creates a new Kubernetes resource + operationId: CreateResource + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceRequestObject' + responses: + "200": + description: Created resource manifest + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceGetResponse' + "400": + description: Bad request + "401": + description: Unauthorized + "403": + description: Forbidden + "500": + description: Internal server error + /orchestrator/k8s/resource/delete: + post: + summary: Delete Kubernetes resource + description: Deletes a Kubernetes resource + operationId: DeleteResource + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceRequestObject' + responses: + "200": + description: Deleted resource manifest + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceGetResponse' + "400": + description: Bad request + "401": + description: Unauthorized + "403": + description: Forbidden + "500": + description: Internal server error + /orchestrator/k8s/events: + post: + summary: Get Kubernetes events + description: Fetches events for Kubernetes resources + operationId: ListEvents + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceRequestObject' + responses: + "200": + description: Resource events + content: + text/event-stream: + schema: + $ref: "#/components/schemas/EventsResponseObject" + "400": + description: Bad request + "401": + description: Unauthorized + "403": + description: Forbidden + "500": + description: Internal server error + /orchestrator/k8s/pods/logs/{podName}: + get: + summary: Get pod logs + description: Fetches logs for a container in a pod + operationId: GetPodLogs + parameters: + - name: podName + in: path + required: true + schema: + type: string + - name: containerName + in: query + required: true + schema: + type: string + - name: appId + in: query + required: false + schema: + type: string + - name: clusterId + in: query + required: false + schema: + type: integer + - name: namespace + in: query + description: Required when clusterId is provided + required: false + schema: + type: string + - name: follow + in: query + schema: + type: boolean + - name: sinceSeconds + in: query + schema: + type: integer + - name: tailLines + in: query + schema: + type: integer + responses: + "200": + description: Pod logs + content: + text/event-stream: + schema: + $ref: "#/components/schemas/LogsResponseObject" + "400": + description: Bad request + "401": + description: Unauthorized + "403": + description: Forbidden + "500": + description: Internal server error + /orchestrator/k8s/pod/exec/session/{identifier}/{namespace}/{pod}/{shell}/{container}: + get: + summary: Get terminal session + description: Gets a terminal session for a pod + operationId: GetTerminalSession + parameters: + - in: path + name: identifier + schema: + type: string + required: true + description: Application ID or cluster ID + example: "2|devtroncd|devtron or 3" + - in: path + name: namespace + schema: + type: string + required: true + description: Namespace name + example: "devtroncd" + - in: path + name: pod + schema: + type: string + required: true + description: Pod name + example: "inception-58d44d99fd-tfw4s" + - in: path + name: shell + schema: + type: string + enum: ["bash", "sh", "powershell", "cmd"] + required: true + description: Shell to invoke + example: "bash" + - in: path + name: container + schema: + type: string + required: true + description: Container name + example: "devtron" + responses: + "200": + description: Terminal session + content: + application/json: + schema: + $ref: "#/components/schemas/TerminalMessage" + "400": + description: Bad request + "401": + description: Unauthorized + "403": + description: Forbidden + "500": + description: Internal server error + /orchestrator/k8s/api-resources/{clusterId}: + get: + summary: Get API resources + description: Gets all API resources for a given cluster + operationId: GetAllApiResources + parameters: + - name: clusterId + in: path + description: Cluster ID + required: true + schema: + type: integer + format: int64 + responses: + "200": + description: API resources + content: + application/json: + schema: + $ref: "#/components/schemas/GetAllApiResourcesResponse" + "400": + description: Bad request + "401": + description: Unauthorized + "403": + description: Forbidden + "500": + description: Internal server error + /orchestrator/k8s/resource/list: + post: + summary: List resources + description: Lists Kubernetes resources + operationId: GetResourceList + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceRequestObject' + responses: + "200": + description: List of resources + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceGetResponse' + "400": + description: Bad request + "401": + description: Unauthorized + "403": + description: Forbidden + "500": + description: Internal server error +components: + schemas: + ResourceRequestObject: + type: object + required: + - clusterId + - k8sRequest + properties: + clusterId: + type: integer + description: Cluster ID + appId: + type: string + description: Application ID + k8sRequest: + $ref: '#/components/schemas/K8sRequest' + appType: + type: string + description: Application type + appIdentifier: + $ref: '#/components/schemas/AppIdentifier' + devtronAppIdentifier: + $ref: '#/components/schemas/DevtronAppIdentifier' + K8sRequest: + type: object + required: + - resourceIdentifier + properties: + resourceIdentifier: + $ref: '#/components/schemas/ResourceIdentifier' + patch: + type: string + description: JSON patch for update operations + ResourceIdentifier: + type: object + required: + - name + - namespace + - groupVersionKind + properties: + name: + type: string + description: Resource name + namespace: + type: string + description: Resource namespace + groupVersionKind: + $ref: '#/components/schemas/GroupVersionKind' + GroupVersionKind: + type: object + required: + - group + - version + - kind + properties: + group: + type: string + description: API group + version: + type: string + description: API version + kind: + type: string + description: Resource kind + AppIdentifier: + type: object + required: + - clusterId + - namespace + - releaseName + properties: + clusterId: + type: integer + description: Cluster ID + namespace: + type: string + description: Namespace + releaseName: + type: string + description: Release name + DevtronAppIdentifier: + type: object + required: + - clusterId + - namespace + - appName + properties: + clusterId: + type: integer + description: Cluster ID + namespace: + type: string + description: Namespace + appName: + type: string + description: Application name + ResourceGetResponse: + type: object + properties: + manifestResponse: + $ref: '#/components/schemas/ManifestResponse' + secretViewAccess: + type: boolean + description: Whether user has access to view secrets + ManifestResponse: + type: object + properties: + manifest: + type: string + description: Resource manifest in YAML format + ephemeralContainers: + type: array + items: + $ref: '#/components/schemas/EphemeralContainer' + description: List of ephemeral containers + EphemeralContainer: + type: object + properties: + name: + type: string + description: Container name + image: + type: string + description: Container image + status: + type: string + description: Container status + EventsResponseObject: + type: object + properties: + events: + type: array + items: + $ref: '#/components/schemas/Event' + description: List of events + Event: + type: object + properties: + type: + type: string + description: Event type + reason: + type: string + description: Event reason + message: + type: string + description: Event message + lastTimestamp: + type: string + format: date-time + description: Last occurrence timestamp + LogsResponseObject: + type: object + properties: + logs: + type: string + description: Container logs + TerminalMessage: + type: object + properties: + sessionId: + type: string + description: Terminal session ID + status: + type: string + description: Session status + GetAllApiResourcesResponse: + type: object + properties: + apiResources: + type: array + items: + $ref: '#/components/schemas/ApiResource' + description: List of API resources + ApiResource: + type: object + properties: + name: + type: string + description: Resource name + singularName: + type: string + description: Singular resource name + namespaced: + type: boolean + description: Whether resource is namespaced + kind: + type: string + description: Resource kind + verbs: + type: array + items: + type: string + description: Available verbs \ No newline at end of file diff --git a/specs/kube-capacity.yaml b/specs/kubernetes/capacity.yaml similarity index 60% rename from specs/kube-capacity.yaml rename to specs/kubernetes/capacity.yaml index 21befdb5e5..5bbbbebbaa 100644 --- a/specs/kube-capacity.yaml +++ b/specs/kubernetes/capacity.yaml @@ -1,42 +1,90 @@ openapi: "3.0.0" info: - title: Kube capacity + title: Kubernetes Capacity version: "1.0" paths: - /orchestrator/k8s/capacity/cluster/list: + /orchestrator/k8s/capacity/cluster/list/raw: get: - description: get list of clusters - operationId: GetClusterList + summary: Get cluster list + description: Returns a list of clusters with basic information + operationId: GetClusterListRaw responses: '200': - description: Successfully return list of cluster + description: List of clusters content: application/json: schema: type: array items: - $ref: '#/components/schemas/ClusterCapacityDto' + $ref: '#/components/schemas/ClusterCapacityDetail' '400': - description: Bad Request. Input Validation error/wrong request body. + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error' '500': - description: Internal Server Error + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/k8s/capacity/cluster/list: + get: + summary: Get cluster list with details + description: Returns a list of clusters with detailed capacity information + operationId: GetClusterListWithDetail + responses: + '200': + description: List of clusters with details + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterCapacityDetail' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Unauthorized User + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' + /orchestrator/k8s/capacity/cluster/{clusterId}: get: - description: get cluster detail + summary: Get cluster details + description: Returns detailed capacity information for a specific cluster operationId: GetClusterDetail parameters: - name: clusterId @@ -44,34 +92,43 @@ paths: required: true schema: type: integer + format: int64 responses: '200': - description: Successfully return detail of cluster + description: Cluster details content: application/json: schema: - $ref: '#/components/schemas/ClusterCapacityDetailDto' + $ref: '#/components/schemas/ClusterCapacityDetail' '400': - description: Bad Request. Input Validation error/wrong request body. + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error + '401': + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Unauthorized User + description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /orchestrator/k8s/capacity/node/list: get: - description: get node list + summary: Get node list + description: Returns a list of nodes in a cluster operationId: GetNodeList parameters: - name: clusterId @@ -79,36 +136,45 @@ paths: required: true schema: type: integer + format: int64 responses: '200': - description: Successfully return list of node + description: List of nodes content: application/json: schema: type: array items: - $ref: '#/components/schemas/NodeCapacityDto' + $ref: '#/components/schemas/NodeCapacityDetail' '400': - description: Bad Request. Input Validation error/wrong request body. + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error + '401': + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Unauthorized User + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' + /orchestrator/k8s/capacity/node: get: - description: get node detail + summary: Get node details + description: Returns detailed information for a specific node operationId: GetNodeDetail parameters: - name: clusterId @@ -116,206 +182,253 @@ paths: required: true schema: type: integer + format: int64 - name: name in: query required: true schema: type: string - description: name of node + description: Name of the node responses: '200': - description: Successfully return node detail + description: Node details content: application/json: schema: - $ref: '#/components/schemas/NodeCapacityDetailDto' + $ref: '#/components/schemas/NodeCapacityDetail' '400': - description: Bad Request. Input Validation error/wrong request body. + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error + '401': + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Unauthorized User + description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + put: - description: update node manifest + summary: Update node manifest + description: Updates the manifest for a specific node operationId: UpdateNodeManifest requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/NodeManifestUpdateDto' + $ref: '#/components/schemas/NodeUpdateRequestDto' responses: '200': - description: Successfully return updated node manifest + description: Updated node manifest content: application/json: schema: $ref: '#/components/schemas/NodeManifestUpdateResponse' '400': - description: Bad Request. Input Validation error/wrong request body. + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error + '401': + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Unauthorized User + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' + delete: - description: delete node detail + summary: Delete node + description: Deletes a specific node operationId: DeleteNode requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/NodeDeleteDto' + $ref: '#/components/schemas/NodeUpdateRequestDto' responses: '200': - description: Successfully return node detail + description: Node deleted successfully content: application/json: schema: - $ref: '#/components/schemas/NodeCapacityDetailDto' + $ref: '#/components/schemas/NodeManifestUpdateResponse' '400': - description: Bad Request. Input Validation error/wrong request body. + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error + '401': + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Unauthorized User + description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /orchestrator/k8s/capacity/node/cordon: put: - description: cordon/unCordon node + summary: Cordon or uncordon node + description: Marks a node as unschedulable or schedulable operationId: CordonOrUnCordonNode requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/NodeCordonReqDto' + $ref: '#/components/schemas/NodeUpdateRequestDto' responses: '200': - description: Return successful operation string. + description: Node cordoned/uncordoned successfully content: application/json: schema: type: string '400': - description: Bad Request. Input Validation error/wrong request body. + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error + '401': + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Unauthorized User + description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /orchestrator/k8s/capacity/node/drain: put: - description: drain a node + summary: Drain node + description: Safely evicts all pods from a node operationId: DrainNode requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/NodeDrainReqDto' + $ref: '#/components/schemas/NodeUpdateRequestDto' responses: '200': - description: Return successful operation string. + description: Node drained successfully content: application/json: schema: type: string '400': - description: Bad Request. Input Validation error/wrong request body. + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error + '401': + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Unauthorized User + description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /orchestrator/k8s/capacity/node/taints/edit: put: - description: edit node taints + summary: Edit node taints + description: Updates the taints on a node operationId: EditNodeTaints requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/NodeTaintEditReqDto' + $ref: '#/components/schemas/NodeUpdateRequestDto' responses: '200': - description: Return successful operation string. + description: Node taints updated successfully content: application/json: schema: type: string '400': - description: Bad Request. Input Validation error/wrong request body. + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error + '401': + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Unauthorized User + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: @@ -323,141 +436,120 @@ paths: components: schemas: - ClusterCapacityDto: + ClusterCapacityDetail: type: object properties: id: type: integer + format: int64 name: type: string + errorInNodeListing: + type: string nodeCount: type: integer - nodeErrors: + nodeDetails: type: array items: - type: string + $ref: '#/components/schemas/NodeDetails' + nodeErrors: + type: object + additionalProperties: + type: array + items: + type: string nodeK8sVersions: type: array items: type: string - errorInNodeListing: - type: boolean - cpu: - $ref: '#/components/schemas/ResourceDetailObject' - memory: - $ref: '#/components/schemas/ResourceDetailObject' - ClusterCapacityDetailDto: - type: object - properties: + serverVersion: + type: string cpu: $ref: '#/components/schemas/ResourceDetailObject' memory: $ref: '#/components/schemas/ResourceDetailObject' - NodeCapacityDto: + isVirtualCluster: + type: boolean + isProd: + type: boolean + + NodeCapacityDetail: type: object properties: name: type: string - status: + version: + type: string + kind: type: string roles: type: array items: type: string - errors: - type: array - items: - $ref: '#/components/schemas/NodeError' k8sVersion: type: string - podCount: - type: integer - taintCount: - type: integer cpu: $ref: '#/components/schemas/ResourceDetailObject' memory: $ref: '#/components/schemas/ResourceDetailObject' age: type: string - labels: - type: array - items: - $ref: '#/components/schemas/LabelTaintObject' - NodeCapacityDetailObject: - type: object - properties: - name: + status: type: string - roles: - type: array - items: + podCount: + type: integer + errors: + type: object + additionalProperties: type: string - k8sVersion: + internalIp: + type: string + externalIp: type: string unschedulable: type: boolean createdAt: type: string - internalIp: - type: string - externalIp: - type: string - resources: - type: array - items: - $ref: '#/components/schemas/ResourceDetailObject' labels: type: array items: - $ref: '#/components/schemas/LabelTaintObject' + $ref: '#/components/schemas/LabelAnnotationTaintObject' annotations: type: array items: - $ref: '#/components/schemas/LabelTaintObject' + $ref: '#/components/schemas/LabelAnnotationTaintObject' taints: type: array items: - $ref: '#/components/schemas/LabelTaintObject' + $ref: '#/components/schemas/LabelAnnotationTaintObject' conditions: type: array items: $ref: '#/components/schemas/NodeConditionObject' - errors: + resources: type: array items: - $ref: '#/components/schemas/NodeError' + $ref: '#/components/schemas/ResourceDetailObject' pods: type: array items: - $ref: '#/components/schemas/PodCapacityDto' + $ref: '#/components/schemas/PodCapacityDetail' manifest: + type: object + clusterName: type: string - version: + nodeGroup: type: string - kind: - type: string - NodeError: - type: object - description: map of conditionType(key) and error(value) - PodCapacityDto: - type: object - properties: - name: - type: string - namespace: - type: string - cpu: - $ref: '#/components/schemas/ResourceDetailObject' - memory: - $ref: '#/components/schemas/ResourceDetailObject' - age: - type: string - NodeManifestUpdateDto: + + NodeUpdateRequestDto: type: object + required: + - clusterId + - name properties: clusterId: type: integer + format: int64 name: type: string manifestPatch: @@ -466,118 +558,106 @@ components: type: string kind: type: string - NodeDeleteDto: - type: object - properties: - clusterId: - type: integer - name: - type: string - version: - type: string - kind: - type: string - NodeCordonReqDto: - type: object - properties: - clusterId: - type: integer - name: - type: string - version: - type: string - kind: - type: string + taints: + type: array + items: + $ref: '#/components/schemas/Taint' nodeCordonOptions: $ref: '#/components/schemas/NodeCordonHelper' + nodeDrainOptions: + $ref: '#/components/schemas/NodeDrainHelper' + NodeCordonHelper: type: object properties: unschedulableDesired: type: boolean - description: set true if want to cordon, set false if want to uncordon - NodeDrainReqDto: - type: object - properties: - clusterId: - type: integer - name: - type: string - version: - type: string - kind: - type: string - nodeDrainOptions: - $ref: '#/components/schemas/NodeDrainHelper' + NodeDrainHelper: type: object + required: + - force + - deleteEmptyDirData + - gracePeriodSeconds + - ignoreAllDaemonSets + - disableEviction properties: - gracePeriodSeconds: - type: integer force: type: boolean deleteEmptyDirData: type: boolean + gracePeriodSeconds: + type: integer ignoreAllDaemonSets: type: boolean disableEviction: type: boolean - NodeTaintEditReqDto: + + NodeDetails: type: object properties: - clusterId: - type: integer - name: - type: string - version: + nodeName: type: string - kind: + nodeGroup: type: string taints: type: array items: - $ref: '#/components/schemas/Taint' - Taint: + $ref: '#/components/schemas/LabelAnnotationTaintObject' + + LabelAnnotationTaintObject: type: object properties: key: type: string - effect: - type: string - oneOf: - - "NoSchedule" - - "NoExecute" - - "PreferNoSchedule" value: type: string - required: false - NodeManifestUpdateResponse: + effect: + type: string + + NodeConditionObject: type: object properties: - manifest: + type: + type: string + status: + type: string + lastHeartbeatTime: type: string + lastTransitionTime: + type: string + reason: + type: string + message: + type: string + ResourceDetailObject: type: object properties: - name: - type: string capacity: type: string - allocatable: - type: string usage: type: string - request: - type: string - limit: - type: string usagePercentage: + type: number + requests: + type: string + limits: type: string - requestPercentage: + + PodCapacityDetail: + type: object + properties: + name: type: string - limitPercentage: + namespace: type: string - LabelTaintObject: + cpu: + $ref: '#/components/schemas/ResourceDetailObject' + memory: + $ref: '#/components/schemas/ResourceDetailObject' + + Taint: type: object properties: key: @@ -586,14 +666,17 @@ components: type: string effect: type: string - NodeConditionObject: + + NodeManifestUpdateResponse: type: object properties: - type: - type: string - haveIssue: - type: boolean - reason: + manifest: + type: object + + Error: + type: object + properties: + code: type: string message: type: string diff --git a/specs/kubernetes/cluster-management.yaml b/specs/kubernetes/cluster-management.yaml new file mode 100644 index 0000000000..d613fb7da4 --- /dev/null +++ b/specs/kubernetes/cluster-management.yaml @@ -0,0 +1,479 @@ +openapi: 3.0.0 +info: + title: Cluster Management API + version: 1.0.0 + description: API for managing Kubernetes clusters + +paths: + /orchestrator/cluster: + post: + summary: Create a new cluster + operationId: CreateCluster + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterBean' + responses: + '200': + description: Successfully created cluster + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterBean' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + get: + summary: List all clusters + operationId: ListClusters + responses: + '200': + description: Successfully retrieved clusters + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterBean' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + put: + summary: Update a cluster + operationId: UpdateCluster + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterBean' + responses: + '200': + description: Successfully updated cluster + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterBean' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + delete: + summary: Delete a cluster + operationId: DeleteCluster + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterBean' + responses: + '200': + description: Successfully deleted cluster + content: + application/json: + schema: + type: string + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/cluster/saveClusters: + post: + summary: Save multiple clusters + operationId: SaveClusters + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterBean' + responses: + '200': + description: Successfully saved clusters + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterBean' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/cluster/validate: + post: + summary: Validate cluster configuration + operationId: ValidateCluster + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - kubeconfig + properties: + kubeconfig: + type: string + responses: + '200': + description: Successfully validated cluster + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterBean' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/cluster/namespaces/{clusterId}: + get: + summary: Get namespaces for a cluster + operationId: GetClusterNamespaces + parameters: + - name: clusterId + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully retrieved cluster namespaces + content: + application/json: + schema: + type: array + items: + type: string + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/cluster/namespaces: + get: + summary: Get namespaces for all clusters + operationId: GetAllClusterNamespaces + responses: + '200': + description: Successfully retrieved all cluster namespaces + content: + application/json: + schema: + type: object + additionalProperties: + type: array + items: + type: string + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/cluster/auth-list: + get: + summary: Get clusters with authentication details + operationId: GetClustersWithAuth + responses: + '200': + description: Successfully retrieved clusters with auth details + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterBean' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + ClusterBean: + type: object + required: + - cluster_name + - server_url + properties: + id: + type: integer + description: Unique identifier for the cluster + cluster_name: + type: string + description: Name of the cluster + server_url: + type: string + description: URL of the Kubernetes API server + prometheus_url: + type: string + description: URL of the Prometheus server + active: + type: boolean + description: Whether the cluster is active + config: + type: object + properties: + bearer_token: + type: string + description: Bearer token for authentication + tls_key: + type: string + description: TLS key for secure communication + cert_data: + type: string + description: Certificate data + cert_auth_data: + type: string + description: Certificate authority data + prometheusAuth: + type: object + properties: + type: + type: string + enum: [basic, bearer] + basic: + type: object + properties: + username: + type: string + password: + type: string + bearer: + type: object + properties: + token: + type: string + defaultClusterComponent: + type: array + items: + $ref: '#/components/schemas/DefaultClusterComponent' + agentInstallationStage: + type: integer + description: Stage of agent installation + k8sVersion: + type: string + description: Kubernetes version + userName: + type: string + description: Name of the user who created/updated the cluster + insecure-skip-tls-verify: + type: boolean + description: Whether to skip TLS verification + errorInConnecting: + type: string + description: Error message if connection fails + clusterUpdated: + type: boolean + description: Whether the cluster was updated + + DefaultClusterComponent: + type: object + properties: + id: + type: string + name: + type: string + version: + type: string + status: + type: string + configuration: + type: object + properties: + type: + type: string + enum: [yaml, json] + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message + + + + + diff --git a/specs/cluster_api_spec.yaml b/specs/kubernetes/cluster.yaml similarity index 68% rename from specs/cluster_api_spec.yaml rename to specs/kubernetes/cluster.yaml index d1fa91e613..bc741a67bd 100644 --- a/specs/cluster_api_spec.yaml +++ b/specs/kubernetes/cluster.yaml @@ -2,8 +2,19 @@ openapi: "3.0.0" info: version: 1.0.0 title: Devtron Labs + description: Devtron API for cluster management + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080 paths: - /orchestrator/cluster: + /cluster: put: description: Update Cluster operationId: UpdateCluster @@ -74,7 +85,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/cluster/auth-list: + /cluster/auth-list: get: description: list of accessible cluster responses: @@ -109,22 +120,60 @@ components: properties: id: type: integer + description: cluster id cluster_name: type: string + description: cluster name + description: + type: string + description: cluster description server_url: type: string + description: server url prometheus_url: type: string + description: prometheus url active: type: boolean + description: whether cluster is active config: type: object - properties: - bearer_token: - type: string - description: it will be empty while fetching, and if no change while updating - k8sversion: + additionalProperties: + type: string + description: cluster config + prometheusAuth: + $ref: '#/components/schemas/PrometheusAuth' + k8sVersion: + type: string + description: kubernetes version + errorInConnecting: + type: string + description: error message if cluster failed to connect + isVirtualCluster: + type: boolean + description: whether cluster is virtual + agentInstallationStage: + type: integer + description: agent installation stage + createdOn: type: string + format: date-time + description: creation timestamp + updatedOn: + type: string + format: date-time + description: last update timestamp + createdBy: + type: string + description: creator's name + updatedBy: + type: string + description: last updater's name + defaultClusterComponent: + type: array + description: default cluster components + items: + $ref: '#/components/schemas/DefaultClusterComponent' PrometheusAuth: type: object properties: @@ -166,6 +215,26 @@ components: errorInConnecting: type: string description: error message if cluster failed to connect + isVirtualCluster: + type: boolean + description: whether cluster is virtual + serverUrl: + type: string + description: cluster server URL + config: + type: object + description: cluster configuration + properties: + bearerToken: + type: string + description: bearer token for cluster access + tlsConfig: + type: object + description: TLS configuration + properties: + insecureSkipTLSVerify: + type: boolean + description: whether to skip TLS verification ErrorResponse: required: diff --git a/specs/kubernetes/ephemeral-containers.yaml b/specs/kubernetes/ephemeral-containers.yaml new file mode 100644 index 0000000000..b38a62eb61 --- /dev/null +++ b/specs/kubernetes/ephemeral-containers.yaml @@ -0,0 +1,193 @@ +openapi: 3.0.0 +info: + title: Orchestrator K8s API + version: 1.0.0 +paths: + /orchestrator/k8s/resources/ephemeralContainers: + post: + summary: Create Ephemeral Container + parameters: + - name: identifier + in: query + required: true + schema: + type: string + description: Unique identifier for the request + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/EphemeralContainerRequest" + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + code: + type: integer + description: HTTP status code + status: + type: string + description: Status message + result: + $ref: "#/components/schemas/PodContainerList" + '400': + description: Bad Request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + delete: + summary: Delete Ephemeral Container + parameters: + - name: identifier + in: query + required: true + schema: + type: string + description: Unique identifier for the request + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/EphemeralContainerRequest" + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + code: + type: integer + description: HTTP status code + status: + type: string + description: Status message + result: + type: boolean + description: Whether the ephemeral container was successfully terminated + '400': + description: Bad Request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + +components: + schemas: + EphemeralContainerRequest: + type: object + properties: + basicData: + $ref: "#/components/schemas/EphemeralContainerBasicData" + advancedData: + $ref: "#/components/schemas/EphemeralContainerAdvancedData" + namespace: + type: string + description: Kubernetes namespace + clusterId: + type: integer + description: Cluster ID + minimum: 1 + podName: + type: string + description: Name of the pod + userId: + type: integer + description: User ID + externalArgoApplicationName: + type: string + description: Name of the external Argo application (if applicable) + required: + - namespace + - clusterId + - podName + EphemeralContainerBasicData: + type: object + properties: + containerName: + type: string + description: Name of the ephemeral container + targetContainerName: + type: string + description: Name of the target container to attach to + image: + type: string + description: Container image to use + required: + - containerName + - targetContainerName + - image + EphemeralContainerAdvancedData: + type: object + properties: + manifest: + type: string + description: Kubernetes manifest for the ephemeral container + PodContainerList: + type: object + properties: + containers: + type: array + items: + type: string + description: List of regular containers + initContainers: + type: array + items: + type: string + description: List of init containers + ephemeralContainers: + type: array + items: + type: string + description: List of running ephemeral containers + Error: + type: object + required: + - code + - message + properties: + code: + type: string + description: Error code + example: E100 + message: + type: string + description: Error message + example: User is not authenticated + internalMessage: + type: string + description: Internal error message for debugging + userMessage: + type: string + description: User-friendly error message diff --git a/specs/kubernetes/resources.yaml b/specs/kubernetes/resources.yaml new file mode 100644 index 0000000000..540f1f3668 --- /dev/null +++ b/specs/kubernetes/resources.yaml @@ -0,0 +1,281 @@ +openapi: "3.0.2" +info: + title: Devtron Labs + description: Devtron API for Kubernetes resource management + version: "1.0" + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080/orchestrator/k8s +paths: + /resource/inception/info: + get: + description: Get inception pod info, such as pod name + responses: + "200": + description: this api give you inception pod info, such as pod name + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: '#/components/schemas/ResourceInfo' + + /resource: + post: + description: Get Kubernetes resource details + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceRequestBean' + responses: + "200": + description: Resource details + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: '#/components/schemas/ManifestResponse' + + /resource/create: + post: + description: Create Kubernetes resource + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceRequestBean' + responses: + "200": + description: Resource created successfully + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: '#/components/schemas/ManifestResponse' + + /resource/update: + put: + description: Update Kubernetes resource + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceRequestBean' + responses: + "200": + description: Resource updated successfully + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: '#/components/schemas/ManifestResponse' + + /resource/delete: + delete: + description: Delete Kubernetes resource + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceRequestBean' + responses: + "200": + description: Resource deleted successfully + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + $ref: '#/components/schemas/ManifestResponse' + + /api-resources/{clusterId}: + get: + description: Get all API resources for a cluster + parameters: + - name: clusterId + in: path + required: true + schema: + type: integer + responses: + "200": + description: API resources list + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + type: array + items: + $ref: '#/components/schemas/K8sApiResource' + + /resource/urls: + get: + description: Get host URLs by batch + parameters: + - name: appId + in: query + required: true + schema: + type: integer + - name: appType + in: query + required: true + schema: + type: string + responses: + "200": + description: Host URLs + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + type: array + items: + type: string + +components: + schemas: + ResourceInfo: + type: object + required: + - podName + properties: + podName: + type: string + description: pod name + + ResourceRequestBean: + type: object + properties: + appId: + type: integer + description: application id + k8sRequest: + $ref: '#/components/schemas/K8sRequestDto' + + K8sRequestDto: + type: object + properties: + resourceIdentifier: + $ref: '#/components/schemas/ResourceIdentifier' + patch: + type: string + description: patch data for update operations + + ResourceIdentifier: + type: object + properties: + name: + type: string + description: resource name + namespace: + type: string + description: resource namespace + groupVersionKind: + $ref: '#/components/schemas/GroupVersionKind' + + GroupVersionKind: + type: object + properties: + group: + type: string + description: API group + version: + type: string + description: API version + kind: + type: string + description: resource kind + + ManifestResponse: + type: object + properties: + manifest: + type: object + description: Kubernetes manifest + success: + type: boolean + description: operation success status + + K8sApiResource: + type: object + properties: + gvk: + $ref: '#/components/schemas/GroupVersionKind' + gvr: + $ref: '#/components/schemas/GroupVersionResource' + namespaced: + type: boolean + description: whether resource is namespaced + + GroupVersionResource: + type: object + properties: + group: + type: string + description: API group + version: + type: string + description: API version + resource: + type: string + description: resource name \ No newline at end of file diff --git a/specs/manifest_generation.yeaml.yaml b/specs/manifest_generation.yeaml.yaml deleted file mode 100644 index 1d3b345e80..0000000000 --- a/specs/manifest_generation.yeaml.yaml +++ /dev/null @@ -1,117 +0,0 @@ -openapi: 3.0.3 -info: - title: App Deployment API - version: 1.0.0 -paths: - /orchestrator/app/deployments/{app-id}/{env-id}: - get: - summary: Fetch Deployment Template Comparison List - parameters: - - name: app-id - in: path - required: true - schema: - type: integer - description: The ID of the application. - - name: env-id - in: path - required: true - schema: - type: integer - description: The ID of the environment. - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/FetchTemplateComparisonList' - /orchestrator/app/deployment/template/data: - post: - summary: Get Values and Manifest for Deployment Template - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DeploymentTemplateRequest' - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/ValuesAndManifestResponse' -components: - schemas: - FetchTemplateComparisonList: - type: object - properties: - chartId: - type: integer - description: The ID of the chart reference. - chartVersion: - type: string - description: The version of the chart. - chartType: - type: string - description: The type of the chart. - environmentId: - type: integer - description: The ID of the environment. - environmentName: - type: string - description: The name of the environment. - pipelineConfigOverrideId: - type: integer - description: The ID of the pipeline configuration override. - startedOn: - type: string - format: date-time - description: The timestamp when the deployment started. - finishedOn: - type: string - format: date-time - description: The timestamp when the deployment finished. - status: - type: string - description: The status of the deployment. - type: - type: integer - enum: [1, 2, 3, 4] - description: The type of deployment template. - DeploymentTemplateRequest: - type: object - properties: - appId: - type: integer - description: The ID of the application. - chartRefId: - type: integer - description: The ID of the chart reference. - getValues: - type: boolean - description: Whether to include values in the response. - type: - type: integer - enum: [1, 2, 3, 4] - description: The type of deployment template. - values: - type: boolean - description: Whether to include values in the response. - pipelineConfigOverrideId: - type: integer - description: The ID of the pipeline configuration override. - required: - - appId - - chartRefId - - getValues - - type - ValuesAndManifestResponse: - type: object - properties: - data: - type: string - description: The values or manifest data for the deployment template. diff --git a/specs/notification.yaml b/specs/notifications/core.yaml similarity index 96% rename from specs/notification.yaml rename to specs/notifications/core.yaml index 3b99e4a469..9d9976f76d 100644 --- a/specs/notification.yaml +++ b/specs/notifications/core.yaml @@ -1,18 +1,18 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Swagger Petstore - description: A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification - termsOfService: http://swagger.io/terms/ + title: Devtron Labs + description: Devtron API for notification management + termsOfService: https://devtron.ai/terms/ contact: - name: Swagger API Team - email: apiteam@swagger.io - url: http://swagger.io + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html servers: - - url: http://petstore.swagger.io/api + - url: http://localhost:8080/orchestrator paths: /notification: get: diff --git a/specs/notifications/webhooks.yaml b/specs/notifications/webhooks.yaml new file mode 100644 index 0000000000..2b77a53724 --- /dev/null +++ b/specs/notifications/webhooks.yaml @@ -0,0 +1,661 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Devtron Labs + description: Devtron API for webhook management including Git webhooks, CI/CD webhooks, and notification webhooks + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080 + +paths: + # Git Webhook APIs + /webhook/git: + post: + description: Handle Git webhook events + operationId: HandleGitWebhook + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GitWebhookPayload' + responses: + '200': + description: Webhook processed successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Success status + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /webhook/git/{gitHostId}: + post: + description: Handle Git webhook events for a specific Git host + operationId: HandleGitWebhookForHost + parameters: + - name: gitHostId + in: path + description: Git host ID or name + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GitWebhookPayload' + responses: + '200': + description: Webhook processed successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Success status + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /webhook/git/{gitHostId}/{secret}: + post: + description: Handle Git webhook events with secret validation + operationId: HandleGitWebhookWithSecret + parameters: + - name: gitHostId + in: path + description: Git host ID or name + required: true + schema: + type: string + - name: secret + in: path + description: Webhook secret for validation + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GitWebhookPayload' + responses: + '200': + description: Webhook processed successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Success status + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + # CI/CD Webhook APIs + /webhook/ci/workflow: + post: + description: Handle CI/CD workflow webhook events + operationId: HandleWorkflowWebhook + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CiCdStatus' + responses: + '200': + description: Webhook processed successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Success status + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /webhook/ext-ci/{externalCiId}: + post: + description: Handle external CI webhook events + operationId: HandleExternalCiWebhook + parameters: + - name: externalCiId + in: path + description: External CI ID + required: true + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalCiWebhookDto' + responses: + '200': + description: Webhook processed successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Success status + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + # Notification Webhook APIs + /webhook/notification: + post: + description: Create or update notification webhook configuration + operationId: SaveNotificationWebhook + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/WebhookChannelConfig' + responses: + '200': + description: Webhook configuration saved successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Success status + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /webhook/notification/{id}: + get: + description: Get notification webhook configuration by ID + operationId: GetNotificationWebhook + parameters: + - name: id + in: path + description: Webhook configuration ID + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: Webhook configuration retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/WebhookConfigDto' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /webhook/notification/variables: + get: + description: Get available webhook variables + operationId: GetWebhookVariables + responses: + '200': + description: Webhook variables retrieved successfully + content: + application/json: + schema: + type: array + items: + type: string + description: Available webhook variable + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + GitWebhookPayload: + type: object + properties: + after: + type: string + description: Commit hash after the event + before: + type: string + description: Commit hash before the event + commits: + type: array + items: + $ref: '#/components/schemas/WebhookCommit' + description: List of commits in the event + compare: + type: string + description: URL to compare changes + created: + type: boolean + description: Whether the event created a new reference + deleted: + type: boolean + description: Whether the event deleted a reference + forced: + type: boolean + description: Whether the event was forced + head_commit: + $ref: '#/components/schemas/WebhookCommit' + description: The head commit of the event + pusher: + $ref: '#/components/schemas/User' + description: User who pushed the changes + ref: + type: string + description: Git reference (branch/tag) + repository: + $ref: '#/components/schemas/Repository' + description: Repository information + sender: + $ref: '#/components/schemas/User' + description: User who triggered the event + + WebhookCommit: + type: object + properties: + id: + type: string + description: Commit hash + message: + type: string + description: Commit message + timestamp: + type: string + format: date-time + description: Commit timestamp + author: + $ref: '#/components/schemas/User' + description: Commit author + committer: + $ref: '#/components/schemas/User' + description: Commit committer + added: + type: array + items: + type: string + description: List of added files + removed: + type: array + items: + type: string + description: List of removed files + modified: + type: array + items: + type: string + description: List of modified files + + User: + type: object + properties: + name: + type: string + description: User's name + email: + type: string + description: User's email + username: + type: string + description: User's username + + Repository: + type: object + properties: + id: + type: integer + description: Repository ID + name: + type: string + description: Repository name + full_name: + type: string + description: Full repository name (owner/repo) + private: + type: boolean + description: Whether the repository is private + html_url: + type: string + description: Repository URL + description: + type: string + description: Repository description + fork: + type: boolean + description: Whether the repository is a fork + url: + type: string + description: Repository API URL + default_branch: + type: string + description: Default branch name + + CiCdStatus: + type: object + required: + - pipelineId + - status + properties: + pipelineId: + type: integer + description: Pipeline ID + status: + type: string + description: Pipeline status + enum: [SUCCESS, FAILED, RUNNING, CANCELLED] + message: + type: string + description: Status message + startedOn: + type: string + format: date-time + description: Pipeline start time + finishedOn: + type: string + format: date-time + description: Pipeline end time + + ExternalCiWebhookDto: + type: object + required: + - pipelineId + - status + properties: + pipelineId: + type: integer + description: External CI pipeline ID + status: + type: string + description: Pipeline status + enum: [SUCCESS, FAILED, RUNNING, CANCELLED] + message: + type: string + description: Status message + startedOn: + type: string + format: date-time + description: Pipeline start time + finishedOn: + type: string + format: date-time + description: Pipeline end time + triggeredBy: + type: integer + description: User ID who triggered the pipeline + + WebhookChannelConfig: + type: object + required: + - webhookConfigDtos + properties: + webhookConfigDtos: + type: array + items: + $ref: '#/components/schemas/WebhookConfigDto' + description: List of webhook configurations + + WebhookConfigDto: + type: object + required: + - name + - url + properties: + id: + type: integer + description: Webhook configuration ID + name: + type: string + description: Webhook name + url: + type: string + description: Webhook URL + secret: + type: string + description: Webhook secret for validation + events: + type: array + items: + type: string + description: List of events to trigger the webhook + active: + type: boolean + description: Whether the webhook is active + createdBy: + type: integer + description: User ID who created the webhook + updatedBy: + type: integer + description: User ID who last updated the webhook + createdAt: + type: string + format: date-time + description: Creation timestamp + updatedAt: + type: string + format: date-time + description: Last update timestamp + + ErrorResponse: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + description: Error code + message: + type: string + description: Error message + errors: + type: array + items: + $ref: '#/components/schemas/Error' + description: List of errors + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + description: Error code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/pipeline-status-timeline.yaml b/specs/pipeline-status-timeline.yaml deleted file mode 100644 index 430b54b984..0000000000 --- a/specs/pipeline-status-timeline.yaml +++ /dev/null @@ -1,77 +0,0 @@ -openapi: "3.0.0" -info: - title: Pipeline deployment status timeline - version: "1.0" -paths: - /orchestrator/app/deployment-status/timeline/{appId}/{envId}: - get: - description: get all timelines of a delpoyment trigger - operationId: GetPipelineStatusTimelines - parameters: - - name: appId - in: path - required: true - schema: - type: integer - - name: envId - in: path - required: true - schema: - type: integer - - name: wfrId - in: path - required: false - schema: - type: integer - responses: - '200': - description: Successfully return deployment timeline status of a pipeline - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/PipelineStatusTimelineDto' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' -components: - schemas: - PipelineStatusTimelineDto: - type: object - properties: - id: - type: integer - status: - type: string - status_detail: - type: integer - status_time: - type: timestampz - Error: - required: - - code - - message - properties: - code: - type: integer - format: int32 - description: Error code - message: - type: string - description: Error message diff --git a/specs/plugins/config-maps.yaml b/specs/plugins/config-maps.yaml new file mode 100644 index 0000000000..93e2dc837b --- /dev/null +++ b/specs/plugins/config-maps.yaml @@ -0,0 +1,565 @@ +openapi: "3.0.0" +info: + title: Global ConfigMap and Secret Management + description: API for managing global ConfigMaps and Secrets + version: "1.0" + +paths: + /orchestrator/configmap/global: + post: + description: Create or update a global ConfigMap + operationId: CMGlobalAddUpdate + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ConfigDataRequest' + responses: + '200': + description: Successfully created/updated ConfigMap + content: + application/json: + schema: + $ref: '#/components/schemas/ConfigDataRequest' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/configmap/environment: + post: + description: Create or update an environment-specific ConfigMap + operationId: CMEnvironmentAddUpdate + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ConfigDataRequest' + responses: + '200': + description: Successfully created/updated ConfigMap + content: + application/json: + schema: + $ref: '#/components/schemas/ConfigDataRequest' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/configmap/global/{appId}: + get: + description: Get all global ConfigMaps for an application + operationId: CMGlobalFetch + parameters: + - name: appId + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully retrieved ConfigMaps + content: + application/json: + schema: + $ref: '#/components/schemas/ConfigDataRequest' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/configmap/environment/{appId}/{envId}: + get: + description: Get all environment-specific ConfigMaps for an application + operationId: CMEnvironmentFetch + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: envId + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully retrieved ConfigMaps + content: + application/json: + schema: + $ref: '#/components/schemas/ConfigDataRequest' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/configmap/global/edit/{appId}/{id}: + get: + description: Get a global ConfigMap for editing + operationId: CMGlobalFetchForEdit + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: id + in: path + required: true + schema: + type: integer + - name: name + in: query + required: true + schema: + type: string + responses: + '200': + description: Successfully retrieved ConfigMap + content: + application/json: + schema: + $ref: '#/components/schemas/ConfigDataRequest' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/configmap/environment/edit/{appId}/{envId}/{id}: + get: + description: Get an environment-specific ConfigMap for editing + operationId: CMEnvironmentFetchForEdit + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: envId + in: path + required: true + schema: + type: integer + - name: id + in: path + required: true + schema: + type: integer + - name: name + in: query + required: true + schema: + type: string + responses: + '200': + description: Successfully retrieved ConfigMap + content: + application/json: + schema: + $ref: '#/components/schemas/ConfigDataRequest' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/configmap/global/{appId}/{id}: + delete: + description: Delete a global ConfigMap + operationId: CMGlobalDelete + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: id + in: path + required: true + schema: + type: integer + - name: name + in: query + required: true + schema: + type: string + responses: + '200': + description: Successfully deleted ConfigMap + content: + application/json: + schema: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/configmap/environment/{appId}/{envId}/{id}: + delete: + description: Delete an environment-specific ConfigMap + operationId: CMEnvironmentDelete + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: envId + in: path + required: true + schema: + type: integer + - name: id + in: path + required: true + schema: + type: integer + - name: name + in: query + required: true + schema: + type: string + responses: + '200': + description: Successfully deleted ConfigMap + content: + application/json: + schema: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/configmap/bulk/patch: + post: + description: Bulk patch ConfigMaps and Secrets + operationId: ConfigSecretBulkPatch + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkPatchRequest' + responses: + '200': + description: Successfully patched ConfigMaps and Secrets + content: + application/json: + schema: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + ConfigDataRequest: + type: object + required: + - appId + - userId + - configData + properties: + id: + type: integer + description: ID of the ConfigMap/Secret + appId: + type: integer + description: ID of the application + userId: + type: integer + description: ID of the user making the request + environmentId: + type: integer + description: ID of the environment (for environment-specific ConfigMaps/Secrets) + configData: + type: array + items: + $ref: '#/components/schemas/ConfigData' + + ConfigData: + type: object + required: + - name + - type + properties: + id: + type: integer + description: ID of the ConfigMap/Secret + name: + type: string + description: Name of the ConfigMap/Secret + type: + type: string + enum: [CONFIGMAP, SECRET] + description: Type of the configuration (ConfigMap or Secret) + external: + type: boolean + description: Whether this is an external ConfigMap/Secret + data: + type: object + additionalProperties: + type: string + description: Key-value pairs for the ConfigMap/Secret + mountPath: + type: string + description: Path where the ConfigMap/Secret should be mounted + subPath: + type: string + description: Subpath within the mount path + filePermission: + type: string + description: File permissions for the mounted ConfigMap/Secret + externalSecretType: + type: string + description: Type of external secret (for Secrets only) + roleARN: + type: string + description: ARN of the role to use for external secrets (for Secrets only) + externalSecret: + type: array + items: + $ref: '#/components/schemas/ExternalSecret' + description: External secret configuration (for Secrets only) + + ExternalSecret: + type: object + required: + - name + - key + properties: + name: + type: string + description: Name of the external secret + key: + type: string + description: Key in the external secret store + property: + type: string + description: Property to extract from the external secret + isBinary: + type: boolean + description: Whether the secret value is binary + + BulkPatchRequest: + type: object + required: + - userId + - global + properties: + userId: + type: integer + description: ID of the user making the request + global: + type: boolean + description: Whether to patch global or environment-specific ConfigMaps/Secrets + appId: + type: integer + description: ID of the application + environmentId: + type: integer + description: ID of the environment (for environment-specific patches) + configData: + type: array + items: + $ref: '#/components/schemas/ConfigData' + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message diff --git a/specs/plugin-system.yaml b/specs/plugins/core.yaml similarity index 87% rename from specs/plugin-system.yaml rename to specs/plugins/core.yaml index dc902158cf..2c2aa237c9 100644 --- a/specs/plugin-system.yaml +++ b/specs/plugins/core.yaml @@ -32,7 +32,7 @@ paths: result: type: array items: - $ref: '#/components/schemas/PluginMetaDataDto' + $ref: '#/components/schemas/PluginListComponentDto' '400': description: Bad Request. Input Validation error/wrong request body. content: @@ -77,7 +77,7 @@ paths: result: type: array items: - $ref: '#/components/schemas/PluginMetaDataDto' + $ref: '#/components/schemas/PluginListComponentDto' '400': description: Bad Request. Input Validation error/wrong request body. content: @@ -195,7 +195,7 @@ paths: type: string responses: '200': - description: Successfully return all operators + description: Successfully return all global variables content: application/json: schema: @@ -326,92 +326,115 @@ paths: $ref: '#/components/schemas/Error' components: schemas: + PluginListComponentDto: + type: object + properties: + id: + type: integer + description: Plugin ID + name: + type: string + description: Plugin name + type: + type: string + description: Plugin type (SHARED/PRESET) + description: + type: string + description: Plugin description + icon: + type: string + description: Plugin icon + tags: + type: array + items: + type: string + description: Plugin tags + inputVariables: + type: array + items: + $ref: '#/components/schemas/PluginVariableDto' + description: Input variables for the plugin + outputVariables: + type: array + items: + $ref: '#/components/schemas/PluginVariableDto' + description: Output variables from the plugin PluginDetailDto: type: object properties: metadata: - $ref: '#/components/schemas/PluginMetaDataDto' + $ref: '#/components/schemas/PluginMetadataDto' inputVariables: type: array items: $ref: '#/components/schemas/PluginVariableDto' + description: Input variables for the plugin outputVariables: type: array items: $ref: '#/components/schemas/PluginVariableDto' - PluginMetaDataDto: + description: Output variables from the plugin + PluginMetadataDto: type: object properties: id: type: integer + description: Plugin ID name: type: string + description: Plugin name type: type: string - example: - - "PRESET" + description: Plugin type (SHARED/PRESET) description: type: string + description: Plugin description icon: type: string + description: Plugin icon tags: type: array items: type: string - example: - - "GIT" - - "DATABASE" + description: Plugin tags PluginVariableDto: type: object properties: - id: - type: integer name: type: string - value: - type: integer - format: - type: string - example: - - "STRING" - - "NUMBER" - - "BOOL" - - "DATE" + description: Variable name description: type: string - defaultValue: + description: Variable description + type: type: string - RefVariableUsed: - type: boolean - variableType: + description: Variable type + format: type: string - example: - - "GLOBAL" - - "FROM_PREVIOUS_STEP" - RefVariableStepIndex: - type: integer - RefVariableName: + description: Variable format + required: + type: boolean + description: Whether the variable is required + defaultValue: type: string + description: Default value for the variable PluginListFilters: type: object properties: - pluginNameContains: + searchKey: type: string + description: Search key to filter plugins tags: type: array items: type: string - example: - - "GIT" - sortBy: - type: string - sortOrder: - type: string - pluginType: - type: string - example: - - "PRESET" - - "SHARED" + description: Tags to filter plugins + limit: + type: integer + description: Number of results to return + offset: + type: integer + description: Offset for pagination PluginFilterOptions: type: object properties: @@ -419,23 +442,24 @@ components: type: array items: type: string + description: Available plugin tags types: type: array items: type: string + description: Available plugin types GlobalVariable: type: object properties: - id: - type: integer name: type: string + description: Variable name value: type: string - format: - type: string + description: Variable value description: type: string + description: Variable description CiPipelineDto: type: object properties: @@ -725,13 +749,25 @@ components: portOnContainer: type: integer Error: - title: Error type: object - description: "A general error schema returned when status is not 200 OK" properties: code: + type: integer + description: Error code + status: type: string - description: "a code for this particular error" - message: - type: string - description: "a message with further detail" \ No newline at end of file + description: Error status + errors: + type: array + items: + type: object + properties: + code: + type: integer + description: Error code + internalMessage: + type: string + description: Internal error message + userMessage: + type: string + description: User friendly error message \ No newline at end of file diff --git a/specs/plugins/global.yaml b/specs/plugins/global.yaml new file mode 100644 index 0000000000..35ef08659e --- /dev/null +++ b/specs/plugins/global.yaml @@ -0,0 +1,572 @@ +openapi: "3.0.3" +info: + title: "Plugin System Integration - CI Stages" + description: | + This API facilitates the management of plugins used in pre/post CI or CD steps, + enhancing the customization and automation capabilities of CI/CD pipelines. + version: "1.0.0" + +paths: + /orchestrator/plugin/global/migrate: + put: + description: Migrate plugin data to the latest schema + operationId: MigratePluginData + responses: + '200': + description: Successfully migrated plugin data + content: + application/json: + schema: + type: object + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/plugin/global/create: + post: + description: Create a new plugin or plugin version + operationId: CreatePlugin + parameters: + - name: appId + in: query + required: false + schema: + type: integer + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PluginParentMetadataDto' + responses: + '200': + description: Successfully created plugin + content: + application/json: + schema: + $ref: '#/components/schemas/PluginMinDto' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/plugin/global/detail/all: + get: + description: Get detailed information of all available plugins + operationId: GetAllDetailedPluginInfo + responses: + '200': + description: Successfully retrieved all plugin details + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PluginMetaDataDto' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/plugin/global/detail/{pluginId}: + get: + description: Get detailed information of a specific plugin by ID + operationId: GetDetailedPluginInfoByPluginId + parameters: + - name: pluginId + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully retrieved plugin details + content: + application/json: + schema: + $ref: '#/components/schemas/PluginMetaDataDto' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/plugin/global/list/global-variable: + get: + description: Get list of all global variables + operationId: GetAllGlobalVariables + parameters: + - name: appId + in: query + required: true + schema: + type: integer + responses: + '200': + description: Successfully retrieved global variables + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/GlobalVariable' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/plugin/global/list/v2: + get: + description: Get list of all plugins with filtering options + operationId: ListAllPluginsV2 + parameters: + - name: appId + in: query + required: true + schema: + type: integer + - name: offset + in: query + required: false + schema: + type: integer + default: 0 + - name: size + in: query + required: false + schema: + type: integer + default: 20 + - name: searchKey + in: query + required: false + schema: + type: string + - name: tag + in: query + required: false + schema: + type: array + items: + type: string + - name: fetchAllVersionDetails + in: query + required: false + schema: + type: boolean + responses: + '200': + description: Successfully retrieved filtered plugins + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PluginMetaDataDto' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/plugin/global/list/detail/v2: + post: + description: Get detailed information for multiple plugins + operationId: GetPluginDetailByIds + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GlobalPluginDetailsRequest' + responses: + '200': + description: Successfully retrieved plugin details + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PluginMetaDataDto' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/plugin/global/list/tags: + get: + description: Get all unique tags used in plugins + operationId: GetAllUniqueTags + parameters: + - name: appId + in: query + required: true + schema: + type: integer + responses: + '200': + description: Successfully retrieved unique tags + content: + application/json: + schema: + type: array + items: + type: string + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/plugin/global/list/v2/min: + get: + description: Get minimal data for all plugins + operationId: GetAllPluginMinData + parameters: + - name: appId + in: query + required: true + schema: + type: integer + - name: type + in: query + required: true + schema: + type: string + enum: [SHARED, PRESET] + responses: + '200': + description: Successfully retrieved minimal plugin data + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PluginMinDto' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden, user is not authorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + PluginMetaDataDto: + type: object + properties: + id: + type: integer + description: Unique identifier for the plugin + name: + type: string + description: Name of the plugin + description: + type: string + description: Detailed description of what the plugin does + type: + type: string + enum: [SHARED, PRESET] + description: Type of the plugin indicating whether it's a SHARED plugin accessible by user or a PRESET plugin provided by the system + icon: + type: string + description: URL or a base64 encoded string representing an icon for the plugin + tags: + type: array + items: + type: string + description: List of tags associated with the plugin + versions: + type: array + items: + $ref: '#/components/schemas/PluginVersionDto' + createdOn: + type: string + format: date-time + description: Timestamp when the plugin was created + updatedOn: + type: string + format: date-time + description: Timestamp when the plugin was last updated + createdBy: + type: integer + description: ID of the user who created the plugin + updatedBy: + type: integer + description: ID of the user who last updated the plugin + + PluginVersionDto: + type: object + properties: + id: + type: integer + description: Unique identifier for the plugin version + version: + type: string + description: Version number of the plugin + description: + type: string + description: Description of changes in this version + createdOn: + type: string + format: date-time + description: Timestamp when the version was created + updatedOn: + type: string + format: date-time + description: Timestamp when the version was last updated + createdBy: + type: integer + description: ID of the user who created this version + updatedBy: + type: integer + description: ID of the user who last updated this version + + PluginParentMetadataDto: + type: object + properties: + id: + type: integer + description: Unique identifier for the plugin + name: + type: string + description: Name of the plugin + description: + type: string + description: Detailed description of what the plugin does + type: + type: string + enum: [SHARED, PRESET] + description: Type of the plugin + icon: + type: string + description: URL or base64 encoded icon + tags: + type: array + items: + type: string + description: List of tags + versions: + type: array + items: + $ref: '#/components/schemas/PluginVersionDto' + + PluginMinDto: + type: object + properties: + pluginVersionId: + type: integer + description: ID of the plugin version + + GlobalPluginDetailsRequest: + type: object + properties: + appId: + type: integer + description: ID of the application + parentPluginIdentifiers: + type: array + items: + type: string + description: List of parent plugin identifiers + + GlobalVariable: + type: object + required: + - name + - format + - description + - stageType + properties: + name: + type: string + description: The name of the global variable + value: + type: string + description: The value of the global variable + format: + type: string + description: The format of the value + description: + type: string + description: A description of the global variable and its purpose + stageType: + type: string + description: The type of stage this global variable is associated with + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message diff --git a/specs/apiToken_api-spec.yaml b/specs/security/api-tokens.yaml similarity index 52% rename from specs/apiToken_api-spec.yaml rename to specs/security/api-tokens.yaml index 76c2bcf537..308cf2465c 100644 --- a/specs/apiToken_api-spec.yaml +++ b/specs/security/api-tokens.yaml @@ -3,18 +3,36 @@ info: version: 1.0.0 title: Devtron Labs paths: - /orchestrator/api-token: + /api-token: get: description: Get All active Api Tokens responses: "200": - description: Successfully fetched active API tokens links + description: Successfully fetched active API tokens content: application/json: schema: type: array items: $ref: "#/components/schemas/ApiToken" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" post: description: Create api-token requestBody: @@ -22,9 +40,7 @@ paths: content: application/json: schema: - type: array - items: - $ref: "#/components/schemas/CreateApiTokenRequest" + $ref: "#/components/schemas/CreateApiTokenRequest" responses: "200": description: Api-token creation response @@ -32,7 +48,31 @@ paths: application/json: schema: $ref: "#/components/schemas/CreateApiTokenResponse" - /orchestrator/api-token/{id}: + "400": + description: Bad Request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /api-token/{id}: put: description: Update api-token parameters: @@ -56,6 +96,30 @@ paths: application/json: schema: $ref: "#/components/schemas/UpdateApiTokenResponse" + "400": + description: Bad Request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" delete: description: Delete api-token parameters: @@ -73,6 +137,76 @@ paths: application/json: schema: $ref: "#/components/schemas/ActionResponse" + "400": + description: Bad Request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /api-token/webhook: + get: + description: Get all api tokens which have given permission + parameters: + - name: projectName + in: query + description: Project name + schema: + type: string + - name: environmentName + in: query + description: Environment name + schema: + type: string + - name: appName + in: query + description: Application name + schema: + type: string + responses: + "200": + description: Successfully fetched API tokens for webhook + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/ApiToken" + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" components: schemas: ApiToken: @@ -127,6 +261,8 @@ components: example: "some date" CreateApiTokenRequest: type: object + required: + - name properties: name: type: string @@ -192,4 +328,15 @@ components: token: type: string description: Token of that api-token - example: "some token" \ No newline at end of file + example: "some token" + ErrorResponse: + type: object + properties: + code: + type: integer + description: HTTP status code + example: 400 + message: + type: string + description: Error message + example: "Bad Request" \ No newline at end of file diff --git a/specs/security/core.yaml b/specs/security/core.yaml new file mode 100644 index 0000000000..235a463b9c --- /dev/null +++ b/specs/security/core.yaml @@ -0,0 +1,811 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Devtron Labs + description: Devtron API for security management including user management, role groups, cluster access policies, and API token management + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080 + +paths: + # User Management APIs + /user/v2: + get: + description: Get all users with optional filters + operationId: GetAllUsers + parameters: + - name: searchKey + in: query + description: Search key for user listing + required: false + schema: + type: string + - name: sortOrder + in: query + description: Sorting order (ASC or DESC) + required: false + schema: + type: string + enum: [ASC, DESC] + - name: sortBy + in: query + description: Sorting by email_id or last_login + required: false + schema: + type: string + enum: [email_id, last_login] + - name: offset + in: query + description: Offset for paginating the results + required: false + schema: + type: integer + - name: size + in: query + description: Size of the result set + required: false + schema: + type: integer + - name: showAll + in: query + description: Show all users + required: false + schema: + type: boolean + responses: + '200': + description: List of users + content: + application/json: + schema: + $ref: '#/components/schemas/UserListingResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /user: + post: + description: Create a new user + operationId: CreateUser + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/User' + responses: + '200': + description: User created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + put: + description: Update an existing user + operationId: UpdateUser + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/User' + responses: + '200': + description: User updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /user/bulk: + delete: + description: Delete multiple users in bulk + operationId: BulkDeleteUsers + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkDeleteRequest' + responses: + '200': + description: Users deleted successfully + content: + application/json: + schema: + type: boolean + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + # Role Group Management APIs + /user/role/group/v2: + get: + description: Get all role groups with optional filters + operationId: GetAllRoleGroups + parameters: + - name: searchKey + in: query + description: Search key for group listing + required: false + schema: + type: string + - name: sortOrder + in: query + description: Sorting order (ASC or DESC) + required: false + schema: + type: string + enum: [ASC, DESC] + - name: sortBy + in: query + description: Sorting by name + required: false + schema: + type: string + enum: [name] + - name: offset + in: query + description: Offset for paginating the results + required: false + schema: + type: integer + - name: size + in: query + description: Size of the result set + required: false + schema: + type: integer + - name: showAll + in: query + description: Show all role groups + required: false + schema: + type: boolean + responses: + '200': + description: List of role groups + content: + application/json: + schema: + $ref: '#/components/schemas/RoleGroupListingResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /user/role/group: + post: + description: Create a new role group + operationId: CreateRoleGroup + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RoleGroup' + responses: + '200': + description: Role group created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/RoleGroup' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + put: + description: Update an existing role group + operationId: UpdateRoleGroup + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RoleGroup' + responses: + '200': + description: Role group updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/RoleGroup' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /user/role/group/bulk: + delete: + description: Delete multiple role groups in bulk + operationId: BulkDeleteRoleGroups + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkDeleteRequest' + responses: + '200': + description: Role groups deleted successfully + content: + application/json: + schema: + type: boolean + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + # API Token Management APIs + /api-token: + get: + description: Get all active API tokens + operationId: GetAllApiTokens + responses: + '200': + description: List of active API tokens + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ApiToken' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + post: + description: Create a new API token + operationId: CreateApiToken + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateApiTokenRequest' + responses: + '200': + description: API token created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CreateApiTokenResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api-token/{id}: + put: + description: Update an existing API token + operationId: UpdateApiToken + parameters: + - name: id + in: path + description: API token ID + required: true + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateApiTokenRequest' + responses: + '200': + description: API token updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateApiTokenResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + delete: + description: Delete an API token + operationId: DeleteApiToken + parameters: + - name: id + in: path + description: API token ID + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: API token deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ActionResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + User: + type: object + required: + - email_id + properties: + id: + type: integer + description: Unique ID of user + email_id: + type: string + description: Unique valid email ID of user + userRoleGroups: + type: array + items: + $ref: '#/components/schemas/UserRoleGroup' + roleFilters: + type: array + items: + $ref: '#/components/schemas/RoleFilter' + description: Role filters objects + + UserRoleGroup: + type: object + properties: + id: + type: integer + description: Role group ID + name: + type: string + description: Role group name + description: + type: string + description: Role group description + + RoleGroup: + type: object + required: + - name + properties: + id: + type: integer + description: Unique ID of role group + name: + type: string + description: Unique name of group + description: + type: string + description: Group description + roleFilters: + type: array + items: + $ref: '#/components/schemas/RoleFilter' + description: Role filters objects + + RoleFilter: + type: object + required: + - action + properties: + cluster: + type: string + description: Cluster name + namespace: + type: string + description: Namespace names (comma-separated for multiple, empty for all) + group: + type: string + description: Group names (comma-separated for multiple, empty for all) + kind: + type: string + description: Kind names (comma-separated for multiple, empty for all) + resource: + type: string + description: Resource names (comma-separated for multiple, empty for all) + action: + type: string + description: Action type (view, edit, admin) + enum: [view, edit, admin] + + UserListingResponse: + type: object + properties: + users: + type: array + items: + $ref: '#/components/schemas/User' + description: List of users + totalCount: + type: integer + description: Total number of users + + RoleGroupListingResponse: + type: object + properties: + groups: + type: array + items: + $ref: '#/components/schemas/RoleGroup' + description: List of role groups + totalCount: + type: integer + description: Total number of role groups + + BulkDeleteRequest: + type: object + properties: + ids: + type: array + items: + type: integer + description: List of IDs to delete + + ApiToken: + type: object + properties: + id: + type: integer + description: API token ID + userId: + type: integer + description: User ID associated with the token + userIdentifier: + type: string + description: Email ID of the token user + name: + type: string + description: Token name + description: + type: string + description: Token description + expireAtInMs: + type: integer + format: int64 + description: Expiration time in milliseconds + token: + type: string + description: Token value + lastUsedAt: + type: string + description: Last used timestamp + lastUsedByIp: + type: string + description: Last used IP address + updatedAt: + type: string + description: Last update timestamp + + CreateApiTokenRequest: + type: object + required: + - name + properties: + name: + type: string + description: Token name + description: + type: string + description: Token description + expireAtInMs: + type: integer + format: int64 + description: Expiration time in milliseconds + + UpdateApiTokenRequest: + type: object + properties: + description: + type: string + description: Token description + expireAtInMs: + type: integer + format: int64 + description: Expiration time in milliseconds + + CreateApiTokenResponse: + type: object + properties: + success: + type: boolean + description: Success status + token: + type: string + description: Generated token + userId: + type: integer + description: User ID + userIdentifier: + type: string + description: User email ID + + UpdateApiTokenResponse: + type: object + properties: + success: + type: boolean + description: Success status + token: + type: string + description: Updated token + + ActionResponse: + type: object + properties: + success: + type: boolean + description: Success status + + ErrorResponse: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + description: Error code + message: + type: string + description: Error message + errors: + type: array + items: + $ref: '#/components/schemas/Error' + description: List of errors + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + description: Error code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/group_policy.yaml b/specs/security/group-policy.yaml similarity index 52% rename from specs/group_policy.yaml rename to specs/security/group-policy.yaml index a509a411da..2ebe632155 100644 --- a/specs/group_policy.yaml +++ b/specs/security/group-policy.yaml @@ -69,20 +69,77 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' + post: + summary: Creates a new Role Group + description: Creates a new role group with the provided configuration + operationId: createRoleGroupV2 + requestBody: + description: Role group configuration + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RoleGroup' + responses: + '200': + description: Role group created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/RoleGroup' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + put: + summary: Updates an existing Role Group + description: Updates an existing role group with the provided configuration + operationId: updateRoleGroupV2 + requestBody: + description: Role group configuration + required: true + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/RoleGroup' + - type: object + required: + - id + properties: + id: + type: integer + format: int64 + responses: + '200': + description: Role group updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/RoleGroup' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' /user/role/group: get: summary: Returns all role groups - description: all the template group policies - operationId: findGroupPolicy - deprecated: true # Marking the operation as deprecated + description: Returns all role groups in the system + operationId: fetchRoleGroups responses: '200': - description: list response + description: List of role groups content: application/json: schema: - $ref: '#/components/schemas/RoleGroup' + type: array + items: + $ref: '#/components/schemas/RoleGroup' default: description: unexpected error content: @@ -91,10 +148,10 @@ paths: $ref: '#/components/schemas/Error' post: summary: Creates a new Role Group - description: create chart group api, with multiple environment in one row of policy, plus chart group additional type of policy. - operationId: addGroupPolicy + description: Creates a new role group with the provided configuration + operationId: createRoleGroup requestBody: - description: json as request body + description: Role group configuration required: true content: application/json: @@ -102,7 +159,7 @@ paths: $ref: '#/components/schemas/RoleGroup' responses: '200': - description: create group policy response + description: Role group created successfully content: application/json: schema: @@ -114,11 +171,11 @@ paths: schema: $ref: '#/components/schemas/Error' put: - summary: update a role group - description: update a role group in the system. - operationId: updateGroupPolicy + summary: Updates an existing Role Group + description: Updates an existing role group with the provided configuration + operationId: updateRoleGroup requestBody: - description: json as request body + description: Role group configuration required: true content: application/json: @@ -134,18 +191,11 @@ paths: format: int64 responses: '200': - description: group response + description: Role group updated successfully content: application/json: schema: - allOf: - - $ref: '#/components/schemas/RoleGroup' - - type: object - properties: - id: - type: integer - format: int64 - + $ref: '#/components/schemas/RoleGroup' default: description: unexpected error content: @@ -155,23 +205,25 @@ paths: /user/role/group/search: get: - summary: search a role group by NAME - description: search role group by group name + summary: Search role groups by name + description: Search role groups by their name operationId: findRoleGroupByName parameters: - name: name in: query - description: json as request body + description: Name of the role group to search for required: true schema: type: string responses: '200': - description: list response + description: List of matching role groups content: application/json: schema: - $ref: '#/components/schemas/RoleGroup' + type: array + items: + $ref: '#/components/schemas/RoleGroup' default: description: unexpected error content: @@ -180,31 +232,62 @@ paths: $ref: '#/components/schemas/Error' /user/role/group/{id}: + get: + summary: Get a role group by ID + description: Get detailed information about a specific role group + operationId: getRoleGroupById + parameters: + - name: id + in: path + description: ID of the role group + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: Role group details + content: + application/json: + schema: + $ref: '#/components/schemas/RoleGroup' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' delete: - summary: Deletes a group policy by ID - description: deletes a single group policy based on the ID supplied - operationId: deleteGroupPolicy + summary: Delete a role group + description: Delete a role group by its ID + operationId: deleteRoleGroup parameters: - name: id in: path - description: ID of group policy + description: ID of the role group to delete required: true schema: type: integer format: int64 responses: - '204': - description: group deleted + '200': + description: Role group deleted successfully + content: + application/json: + schema: + type: boolean default: description: unexpected error content: application/json: schema: $ref: '#/components/schemas/Error' + /user/role/group/bulk: delete: - summary: Delete multiple permission groups in bulk - description: Deletes permission groups entities in bulk based on the provided criteria. + summary: Delete multiple role groups + description: Delete multiple role groups in bulk + operationId: bulkDeleteRoleGroups requestBody: required: true content: @@ -213,96 +296,87 @@ paths: $ref: '#/components/schemas/BulkDeleteRequest' responses: '200': - description: Successfully deleted groups + description: Role groups deleted successfully content: application/json: schema: type: boolean - '400': - description: Bad request, invalid input - '404': - description: groups not found - '500': - description: Internal server error + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /user/role/group/detailed/get: + get: + summary: Returns detailed information about all role groups + description: Returns detailed information about all role groups including their permissions + operationId: fetchDetailedRoleGroups + responses: + '200': + description: List of detailed role groups + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/RoleGroup' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' components: schemas: RoleGroup: type: object - required: - - name properties: id: type: integer - description: Unique id of role group + format: int64 name: type: string - description: Unique name of group description: type: string - description: description roleFilters: type: array items: - $ref: '#/components/schemas/roleFilter' - description: role filters objects - + $ref: '#/components/schemas/RoleFilter' + superAdmin: + type: boolean + required: + - name - roleFilter: + RoleFilter: type: object - required: - - action properties: entity: type: string - description: global entity name, i.e chart-group, git, docker, cluster etc. if this key is present than field team, application and environment are ignored. - enum: - - chart-group - - docker - - git - - cluster - - notification team: type: string - description: team name entityName: type: string - description: global entity name item name, i.e chart-group ("abc"), git("devtron-gt") etc. environment: type: string - description: comma saperated environments names. action: type: string - description: action is type of role, i.e manager, admin, trigger, view, etc. accessType: type: string - enum: ["", "helm-app"] - description: accessType difine permission type dawf=devtron app work flow, helm-app=helm app work flow. based on this flag data categoriesed into devtron and helm permission tabs in user auth role group section. - - - Error: - required: - - code - - message - properties: - code: - type: integer - format: int32 - description: Error code - message: + cluster: + type: string + namespace: + type: string + group: + type: string + kind: + type: string + resource: + type: string + workflow: type: string - description: Error message - - RoleGroupListingResponse: - type: object - properties: - roleGroups: - items: - $ref: '#/components/schemas/RoleGroup' - description: role groups listing - totalCount: - type: integer - description: total number of results satisfying the conditions BulkDeleteRequest: type: object @@ -311,35 +385,57 @@ components: type: array items: type: integer - format: int32 - description: Array of group IDs to be deleted + format: int64 listingRequest: $ref: '#/components/schemas/ListingRequest' + required: + - ids + ListingRequest: type: object properties: searchKey: type: string - description: Search key for filtering sortOrder: type: string enum: - ASC - DESC - description: Sorting order sortBy: type: string enum: - name - description: Attribute to sort by offset: type: integer - format: int32 - description: Starting index for fetching listings size: type: integer - format: int32 - description: Number of listings to fetch showAll: type: boolean - description: Show all listings \ No newline at end of file + + Error: + type: object + properties: + code: + type: integer + status: + type: string + errors: + type: array + items: + type: object + properties: + code: + type: string + message: + type: string + + RoleGroupListingResponse: + type: object + properties: + roleGroups: + items: + $ref: '#/components/schemas/RoleGroup' + description: role groups listing + totalCount: + type: integer + description: total number of results satisfying the conditions \ No newline at end of file diff --git a/specs/user_policy.yaml b/specs/security/policy.yaml similarity index 51% rename from specs/user_policy.yaml rename to specs/security/policy.yaml index 7c8691acb5..ce5690b89f 100644 --- a/specs/user_policy.yaml +++ b/specs/security/policy.yaml @@ -8,13 +8,12 @@ paths: /user/v2: get: summary: Returns all users - description: all the template users + description: Returns a paginated list of users with optional filtering and sorting operationId: GetAllV2 parameters: - - name: searchKey in: query - description: Search key for user listing + description: Search key for filtering users required: false schema: type: string @@ -31,7 +30,7 @@ paths: - name: sortBy in: query - description: Sorting by email_id or last_login + description: Field to sort by (email_id or last_login) required: false schema: type: string @@ -41,63 +40,62 @@ paths: - name: offset in: query - description: Offset for paginating the results + description: Offset for pagination required: false schema: type: integer - name: size in: query - description: Size of the result set + description: Number of records per page required: false schema: type: integer - name: showAll in: query - description: Show all users (boolean) + description: Whether to show all users or only active ones required: false schema: type: boolean responses: '200': - description: list response + description: List of users content: application/json: schema: $ref: '#/components/schemas/UserListingResponse' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + '403': + description: Forbidden + '500': + description: Internal server error + /user: get: - summary: Returns all users - description: all the template users + summary: Returns all users (deprecated) + description: Returns all users (deprecated, use /user/v2 instead) operationId: findAllUsers - deprecated: true # Marking the operation as deprecated + deprecated: true responses: '200': - description: list response + description: List of users content: application/json: schema: $ref: '#/components/schemas/AllUsers' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + '500': + description: Internal server error + post: - summary: Creates a new User - description: create user api, with multiple environment in one row of policy, plus chart group additional type of policy. + summary: Creates a new user + description: Creates a new user with specified roles and permissions operationId: addUser requestBody: - description: json as request body required: true content: application/json: @@ -105,23 +103,27 @@ paths: $ref: '#/components/schemas/User' responses: '200': - description: create user response + description: Created user content: application/json: schema: $ref: '#/components/schemas/User' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + '400': + description: Bad request + '401': + description: Unauthorized + '403': + description: Forbidden + '406': + description: Not acceptable - incompatible request format + '500': + description: Internal server error + put: - summary: update a user - description: Updates a new user in the system + summary: Updates a user + description: Updates an existing user's roles and permissions operationId: updateUser requestBody: - description: json as request body required: true content: application/json: @@ -129,74 +131,80 @@ paths: $ref: '#/components/schemas/User' responses: '200': - description: user response + description: Updated user content: application/json: schema: $ref: '#/components/schemas/User' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + '400': + description: Bad request + '401': + description: Unauthorized + '403': + description: Forbidden + '406': + description: Not acceptable - incompatible request format + '500': + description: Internal server error /user/email: get: - summary: search a user list by name - description: search user detail by name + summary: Search user by email + description: Search for a user by their email address operationId: findUserByEmail parameters: - name: email-id in: query - description: ID of pet to delete + description: Email ID of the user to search for required: true schema: type: string responses: '200': - description: list response + description: User details content: application/json: schema: $ref: '#/components/schemas/User' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + '400': + description: Bad request + '401': + description: Unauthorized + '500': + description: Internal server error /user/{id}: get: - summary: Returns user detail with role filter - description: all the template group policies + summary: Get user by ID + description: Returns user details with role filters operationId: findUserById parameters: - name: id in: path - description: ID of user id + description: ID of the user required: true schema: type: integer format: int64 responses: '200': - description: user detail response + description: User details content: application/json: schema: $ref: '#/components/schemas/User' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + '400': + description: Bad request + '401': + description: Unauthorized + '500': + description: Internal server error + /orchestrator/user/bulk: delete: - summary: Delete multiple users in bulk - description: Deletes user entities in bulk based on the provided criteria. + summary: Delete multiple users + description: Deletes multiple users in bulk + operationId: bulkDeleteUsers requestBody: required: true content: @@ -211,13 +219,14 @@ paths: schema: type: boolean '400': - description: Bad request, invalid input - '404': - description: Users not found + description: Bad request + '401': + description: Unauthorized + '403': + description: Forbidden '500': description: Internal server error - components: schemas: User: @@ -227,10 +236,10 @@ components: properties: id: type: integer - description: Unique id of user + description: Unique ID of the user email_id: type: string - description: Unique valid email-id of user, comma separated emails ids for multiple users + description: Email ID of the user userRoleGroups: type: array items: @@ -239,156 +248,111 @@ components: type: array items: $ref: '#/components/schemas/roleFilter' - description: role filters objects + description: Role filters for the user + superAdmin: + type: boolean + description: Whether the user is a super admin + userId: + type: integer + description: ID of the user making the request + UserListingResponse: type: object properties: users: + type: array items: $ref: '#/components/schemas/AllUsersV2' - description: role filters objects + description: List of users totalCount: type: integer - description: total number of results satisfying the conditions + description: Total number of users - AllUsers: + AllUsersV2: type: object - required: - - email_id properties: id: type: integer - description: Unique id of user + description: User ID email_id: type: string - description: Unique valid email-id of user, comma separated emails ids for multiple users - groups: - type: array - items: - type: string + description: Email ID + last_login: + type: string + format: date-time + description: Last login timestamp roleFilters: type: array items: - $ref: '#/components/schemas/emptyRoleFilter' - description: role filters objects - lastLogin: - type: string - format: date-time - description: user last login time - AllUsersV2: + $ref: '#/components/schemas/roleFilter' + description: Role filters + + UserRoleGroupItem: type: object - required: - - email_id properties: id: type: integer - description: Unique id of user - email_id: - type: string - description: Unique valid email-id of user, comma separated emails ids for multiple users - userRoleGroups: - type: array - items: - $ref: '#/components/schemas/UserRoleGroupItem' - lastLogin: + description: Role group ID + name: type: string - format: date-time - description: user last login time - - emptyRoleFilter: - type: object - required: - - action - + description: Role group name roleFilter: type: object - required: - - action properties: entity: type: string - description: global entity name, i.e chart-group, git, docker, cluster etc. if this key is present than field team, application and environment are ignored, here empty entity means Devtron apps permission. - enum: - - chart-group - - docker - - git - - cluster - - notification + description: Entity type team: type: string - description: team name - entityName: - type: string - description: global entity name item name, i.e chart-group ("abc"), git("devtron-gt") etc. + description: Team name environment: type: string - description: comma saperated environments names. + description: Environment name action: type: string - description: action is type of role, i.e manager, admin, trigger, view, etc. - accessType: - type: string - enum: ["", "helm-app"] - description: accessType difine permission type "devtron-app"=devtron app work flow, "helm-app"=helm app work flow. based on this flag data categoriesed into devtron and helm permission tabs in user auth section. + description: Action type + BulkDeleteRequest: type: object + required: + - ids properties: ids: type: array items: type: integer - format: int32 - description: Array of user IDs to be deleted - listingRequest: - $ref: '#/components/schemas/ListingRequest' - ListingRequest: - type: object - properties: - searchKey: - type: string - description: Search key for filtering - sortOrder: - type: string - enum: - - ASC - - DESC - description: Sorting order - sortBy: - type: string - enum: - - email_id - - last_login - description: Attribute to sort by - offset: - type: integer - format: int32 - description: Starting index for fetching listings - size: - type: integer - format: int32 - description: Number of listings to fetch - showAll: - type: boolean - description: Show all listings - UserRoleGroupItem: - type: object - properties: - roleGroup: - $ref: '#/components/schemas/RoleGroup' - RoleGroup: + description: List of user IDs to delete + + AllUsers: type: object + required: + - email_id properties: id: type: integer - format: int32 - description: The ID of the role group - name: + description: Unique id of user + email_id: type: string - description: The name of the role group - description: + description: Unique valid email-id of user, comma separated emails ids for multiple users + groups: + type: array + items: + type: string + roleFilters: + type: array + items: + $ref: '#/components/schemas/emptyRoleFilter' + description: role filters objects + lastLogin: type: string - description: The description of the role group + format: date-time + description: user last login time + + emptyRoleFilter: + type: object + required: + - action Error: required: diff --git a/specs/security/roles.yaml b/specs/security/roles.yaml new file mode 100644 index 0000000000..0519ecba6e --- /dev/null +++ b/specs/security/roles.yaml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/specs/security/user-management.yaml b/specs/security/user-management.yaml new file mode 100644 index 0000000000..2c44067cf2 --- /dev/null +++ b/specs/security/user-management.yaml @@ -0,0 +1,416 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Devtron Labs + description: Devtron API for user management + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Labs + email: support@devtron.ai + url: https://devtron.ai + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080 +paths: + /user/v2: + get: + description: Get all users with filters + parameters: + - name: searchKey + in: query + description: Search key for user listing + required: false + schema: + type: string + - name: sortOrder + in: query + description: Sorting order (ASC or DESC) + required: false + schema: + type: string + enum: [ASC, DESC] + - name: sortBy + in: query + description: Sorting by email_id or last_login + required: false + schema: + type: string + enum: [email_id, last_login] + - name: offset + in: query + description: Offset for paginating the results + required: false + schema: + type: integer + - name: size + in: query + description: Size of the result set + required: false + schema: + type: integer + - name: showAll + in: query + description: Show all users (boolean) + required: false + schema: + type: boolean + responses: + '200': + description: List of users + content: + application/json: + schema: + $ref: '#/components/schemas/UserListingResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /user: + post: + description: Create a new user + requestBody: + description: User details + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/User' + responses: + '200': + description: User created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + put: + description: Update an existing user + requestBody: + description: Updated user details + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/User' + responses: + '200': + description: User updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /user/{id}: + get: + description: Get user details by ID + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: User ID + responses: + '200': + description: User details + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + delete: + description: Delete a user + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: User ID + responses: + '200': + description: User deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /user/bulk: + delete: + description: Delete multiple users in bulk + requestBody: + description: List of user IDs to delete + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkDeleteRequest' + responses: + '200': + description: Users deleted successfully + content: + application/json: + schema: + type: boolean + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + User: + type: object + required: + - email_id + properties: + id: + type: integer + description: Unique ID of user + email_id: + type: string + description: Unique valid email ID of user + userRoleGroups: + type: array + items: + $ref: '#/components/schemas/UserRoleGroup' + roleFilters: + type: array + items: + $ref: '#/components/schemas/RoleFilter' + description: Role filters objects + createdOn: + type: string + format: date-time + description: Creation timestamp + createdBy: + type: string + description: Creator's name + updatedOn: + type: string + format: date-time + description: Last update timestamp + updatedBy: + type: string + description: Last updater's name + + UserRoleGroup: + type: object + properties: + id: + type: integer + description: Role group ID + name: + type: string + description: Role group name + description: + type: string + description: Role group description + createdOn: + type: string + format: date-time + description: Creation timestamp + createdBy: + type: string + description: Creator's name + updatedOn: + type: string + format: date-time + description: Last update timestamp + updatedBy: + type: string + description: Last updater's name + + RoleFilter: + type: object + properties: + entity: + type: string + description: Entity type (e.g. app, env, cluster) + entityName: + type: string + description: Entity name + action: + type: string + description: Action type (e.g. create, update, delete) + accessType: + type: string + description: Access type (e.g. admin, manager, viewer) + team: + type: string + description: Team name + environment: + type: string + description: Environment name + cluster: + type: string + description: Cluster name + + UserListingResponse: + type: object + properties: + users: + type: array + items: + $ref: '#/components/schemas/User' + description: List of users + totalCount: + type: integer + description: Total number of users + + BulkDeleteRequest: + type: object + required: + - ids + properties: + ids: + type: array + items: + type: integer + description: List of user IDs to delete + loggedInUserId: + type: integer + description: ID of the user performing the deletion + + ErrorResponse: + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message \ No newline at end of file From 02eacc9ccd04f347ba69937437cde1d7f35807e1 Mon Sep 17 00:00:00 2001 From: prakhar katiyar Date: Fri, 25 Jul 2025 17:12:34 +0530 Subject: [PATCH 2/9] specs enhance --- specs/application/labels.yaml | 30 +- .../ci-pipeline-change-source.yaml | 322 +++++++++++++++++- 2 files changed, 333 insertions(+), 19 deletions(-) diff --git a/specs/application/labels.yaml b/specs/application/labels.yaml index 6881d08710..393fbca68a 100644 --- a/specs/application/labels.yaml +++ b/specs/application/labels.yaml @@ -56,7 +56,16 @@ paths: type: string description: status result: - $ref: '#/components/schemas/AppMetaInfo' + allOf: + - $ref: '#/components/schemas/AppMetaInfo' + - type: object + properties: + gitMaterials: + type: array + items: + $ref: '#/components/schemas/GitMaterialMeta' + templateConfig: + $ref: '#/components/schemas/TemplateConfig' default: description: unexpected error content: @@ -64,7 +73,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /orchestrator/helm/meta/info/{appId}: + /orchestrator/app/helm/meta/info/{appId}: get: description: application info for all types of helm apps parameters: @@ -200,15 +209,28 @@ components: type: string description: Original git URL + TemplateConfig: + type: object + properties: + id: + type: integer + description: Template config ID + identifier: + type: string + description: Template identifier + name: + type: string + description: Template name + GenericNoteResponse: type: object properties: id: type: integer description: Note ID - note: + description: type: string - description: Note content + description: Note content/description createdOn: type: string format: date-time diff --git a/specs/ci-pipeline/ci-pipeline-change-source.yaml b/specs/ci-pipeline/ci-pipeline-change-source.yaml index b1a7c7d5b6..bedb0f1ede 100644 --- a/specs/ci-pipeline/ci-pipeline-change-source.yaml +++ b/specs/ci-pipeline/ci-pipeline-change-source.yaml @@ -5,40 +5,332 @@ info: paths: /orchestrator/app/ci-pipeline/patch-source: patch: - description: update source of a ci-matrial + summary: Update CI material source (branch/regex) for a specific app and environment + description: | + Updates the source configuration of a CI material for a specific application and environment. + This endpoint allows changing the branch name or regex pattern that triggers CI builds. + + **Supported Source Types:** + - `SOURCE_TYPE_BRANCH_FIXED`: Fixed branch name (e.g., "main", "develop") + - `SOURCE_TYPE_BRANCH_REGEX`: Regex pattern for branch matching (e.g., "feature-*") + + **Prerequisites:** + - User must have UPDATE permission on the application + - Application must be a custom app (not job or external app) + - Pipeline must exist for the given appId and environmentId + security: + - BearerAuth: [] requestBody: + required: true content: application/json: schema: $ref: "#/components/schemas/RequestBody" + examples: + branch_fixed: + summary: Change to fixed branch + description: Update CI material to use a fixed branch name + value: + appId: 16 + environmentId: 1 + source: + type: "SOURCE_TYPE_BRANCH_FIXED" + value: "main" + regex: "" + branch_regex: + summary: Change to regex pattern + description: Update CI material to use a regex pattern for branch matching + value: + appId: 16 + environmentId: 1 + source: + type: "SOURCE_TYPE_BRANCH_REGEX" + value: "feature-*" + regex: "feature-*" + develop_branch: + summary: Switch to develop branch + description: Update CI material to use develop branch + value: + appId: 25 + environmentId: 3 + source: + type: "SOURCE_TYPE_BRANCH_FIXED" + value: "develop" + regex: "" + hotfix_pattern: + summary: Use hotfix pattern + description: Update CI material to match hotfix branches + value: + appId: 30 + environmentId: 2 + source: + type: "SOURCE_TYPE_BRANCH_REGEX" + value: "hotfix/*" + regex: "hotfix/*" responses: "200": - description: Successfully fetched commit info. if CommitInfo is null, then commit is not found. + description: Successfully updated CI material source content: application/json: schema: - type: object + $ref: "#/components/schemas/SuccessResponse" + examples: + success_branch_fixed: + summary: Success - Branch Fixed + description: Successfully updated to fixed branch + value: + code: 200 + status: "OK" + result: + appId: 16 + environmentId: 1 + source: + type: "SOURCE_TYPE_BRANCH_FIXED" + value: "main" + regex: "" + success_branch_regex: + summary: Success - Branch Regex + description: Successfully updated to regex pattern + value: + code: 200 + status: "OK" + result: + appId: 16 + environmentId: 1 + source: + type: "SOURCE_TYPE_BRANCH_REGEX" + value: "feature-*" + regex: "feature-*" + "400": + description: Bad Request - Invalid request data or validation failed + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + invalid_source_type: + summary: Invalid Source Type + description: Unsupported source type provided + value: + code: 400 + status: "Bad Request" + errors: + - code: "400" + internalMessage: "source.type not supported" + userMessage: "source.type not supported" + missing_required_fields: + summary: Missing Required Fields + description: Required fields are missing from request + value: + code: 400 + status: "Bad Request" + errors: + - code: "400" + internalMessage: "Key: 'CiMaterialPatchRequest.AppId' Error:Field validation for 'AppId' failed on the 'required' tag" + userMessage: "AppId is required" + non_custom_app: + summary: Non-Custom App + description: Only custom applications are supported + value: + code: 400 + status: "Bad Request" + errors: + - code: "400" + internalMessage: "only custom apps supported" + userMessage: "only custom apps supported" + "401": + description: Unauthorized - Invalid or missing authentication token + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + missing_token: + summary: Missing Authentication Token + description: No authentication token provided + value: + code: 401 + status: "Unauthorized" + errors: + - code: "401" + internalMessage: "Unauthorized User" + userMessage: "Unauthorized User" + invalid_token: + summary: Invalid Token + description: Provided authentication token is invalid + value: + code: 401 + status: "Unauthorized" + errors: + - code: "401" + internalMessage: "Invalid token" + userMessage: "Invalid authentication token" + "403": + description: Forbidden - User doesn't have permission to update this app + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + insufficient_permissions: + summary: Insufficient Permissions + description: User lacks UPDATE permission on the application + value: + code: 403 + status: "Forbidden" + errors: + - code: "403" + internalMessage: "unauthorized user" + userMessage: "Unauthorized User" + "500": + description: Internal Server Error - Pipeline not found or other server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + pipeline_not_found: + summary: Pipeline Not Found + description: No pipeline exists for the given appId and environmentId + value: + code: 500 + status: "Internal Server Error" + errors: + - code: "000" + internalMessage: "[{unique pipeline was not found, for the given appId and environmentId}]" + userMessage: "unique pipeline was not found, for the given appId and environmentId" + multiple_pipelines: + summary: Multiple Pipelines Found + description: Multiple pipelines found for the given appId and environmentId + value: + code: 500 + status: "Internal Server Error" + errors: + - code: "000" + internalMessage: "[{multiple pipelines found for the given appId and environmentId}]" + userMessage: "multiple pipelines found for the given appId and environmentId" + database_error: + summary: Database Error + description: Database operation failed + value: + code: 500 + status: "Internal Server Error" + errors: + - code: "000" + internalMessage: "[{database connection error}]" + userMessage: "Database operation failed" -#{"appId": 16, "environmentId": 1, "source": {"type":"SOURCE_TYPE_BRANCH_FIXED", "value": "main1", "regex":""}} # Components components: + securitySchemes: + BearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token for authentication. Include in Authorization header as 'Bearer ' + schemas: RequestBody: type: object + required: + - appId + - environmentId + - source properties: appId: type: integer + description: Application ID - must be a custom application (not job or external app) + example: 16 + minimum: 1 environmentId: type: integer + description: Environment ID where the CI pipeline is configured + example: 1 + minimum: 1 source: - type: object - properties: - type: - type: string - description: "SOURCE_TYPE_BRANCH_FIXED / SOURCE_TYPE_BRANCH_REGEX" - value: - type: string - description: "name of the branch" - regex: - type: string - description: "regular expression when type is SOURCE_TYPE_BRANCH_REGEX" \ No newline at end of file + $ref: "#/components/schemas/SourceTypeConfig" + + SourceTypeConfig: + type: object + required: + - type + - value + properties: + type: + type: string + enum: + - SOURCE_TYPE_BRANCH_FIXED + - SOURCE_TYPE_BRANCH_REGEX + description: | + Source type for CI material. + - `SOURCE_TYPE_BRANCH_FIXED`: Use a specific branch name + - `SOURCE_TYPE_BRANCH_REGEX`: Use a regex pattern to match multiple branches + example: "SOURCE_TYPE_BRANCH_FIXED" + value: + type: string + description: | + Branch name or regex pattern. + - For `SOURCE_TYPE_BRANCH_FIXED`: The exact branch name (e.g., "main", "develop") + - For `SOURCE_TYPE_BRANCH_REGEX`: The regex pattern to match branches (e.g., "feature-*", "hotfix/*") + example: "main" + minLength: 1 + regex: + type: string + description: | + Regular expression pattern (only used when type is SOURCE_TYPE_BRANCH_REGEX). + Must match the value field for regex type. + example: "feature-*" + default: "" + + SuccessResponse: + type: object + properties: + code: + type: integer + description: HTTP status code + example: 200 + status: + type: string + description: Status message + example: "OK" + result: + $ref: "#/components/schemas/RequestBody" + + ErrorResponse: + type: object + required: + - code + - status + properties: + code: + type: integer + description: HTTP status code + example: 500 + status: + type: string + description: Error status message + example: "Internal Server Error" + errors: + type: array + items: + $ref: "#/components/schemas/Error" + + Error: + type: object + required: + - code + - internalMessage + - userMessage + properties: + code: + type: string + description: Error code for internal tracking + example: "000" + internalMessage: + type: string + description: Internal error message for debugging (not shown to end users) + example: "[{unique pipeline was not found, for the given appId and environmentId}]" + userMessage: + type: string + description: User-friendly error message that can be displayed to end users + example: "unique pipeline was not found, for the given appId and environmentId" \ No newline at end of file From cdd8421df6d83673699b047fa7e197bb5bf7b171 Mon Sep 17 00:00:00 2001 From: prakhar katiyar Date: Mon, 4 Aug 2025 12:59:53 +0530 Subject: [PATCH 3/9] corrected specs --- specs/deployment/core.yaml | 26 ++++++++++++-- .../external-links/external-links-specs.yaml | 4 +-- specs/gitops/core.yaml | 10 +++--- specs/helm/provider.yaml | 24 ++++++------- specs/helm/repo-validation.yaml | 8 ++--- specs/kubernetes/capacity.yaml | 28 +++++---------- specs/kubernetes/cluster.yaml | 4 +-- specs/kubernetes/resources.yaml | 14 ++++---- specs/modularisation/v1.yaml | 24 +++++++++++++ specs/notifications/core.yaml | 6 ++-- specs/notifications/webhooks.yaml | 16 ++++----- .../api/apiToken_api-openapi.yaml | 36 +++++++++++++++++-- specs/security/core.yaml | 16 ++++----- specs/security/group-policy.yaml | 12 +++---- specs/security/policy.yaml | 36 +++---------------- specs/security/user-management.yaml | 8 ++--- 16 files changed, 154 insertions(+), 118 deletions(-) diff --git a/specs/deployment/core.yaml b/specs/deployment/core.yaml index fbe3b8fccf..5f6f96c813 100644 --- a/specs/deployment/core.yaml +++ b/specs/deployment/core.yaml @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080 paths: - /deployment/template/validate: + /orchestrator/deployment/template/validate: post: description: upload template file from this api to validate. requestBody: @@ -43,6 +43,14 @@ paths: description: status result: $ref: '#/components/schemas/UploadTemplateResponse' + '400': + description: Bad request - validation error, unsupported format, or file parsing error + '401': + description: Unauthorized user + '403': + description: Forbidden - insufficient permissions + '500': + description: Internal server error default: description: unexpected error content: @@ -50,7 +58,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /deployment/template/upload: + /orchestrator/deployment/template/upload: put: description: upload template file from this api. requestBody: @@ -76,6 +84,14 @@ paths: result: type: string description: result + '400': + description: Bad request - validation error + '401': + description: Unauthorized user + '403': + description: Forbidden - insufficient permissions + '500': + description: Internal server error default: description: unexpected error content: @@ -83,7 +99,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /deployment/template/fetch: + /orchestrator/deployment/template/fetch: get: summary: Returns all charts description: all the chart template uploaded by user @@ -105,6 +121,10 @@ paths: description: list of charts items: $ref: '#/components/schemas/Chart' + '401': + description: Unauthorized user + '500': + description: Internal server error default: description: unexpected error content: diff --git a/specs/external-links/external-links-specs.yaml b/specs/external-links/external-links-specs.yaml index 0645fe3c99..0c94374a43 100644 --- a/specs/external-links/external-links-specs.yaml +++ b/specs/external-links/external-links-specs.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: External links APIs paths: - /orchestrator/external-link/tools: + /orchestrator/external-links/tools: get: description: Get all available monitoring tools for external links responses: @@ -15,7 +15,7 @@ paths: type: array items: $ref: "#/components/schemas/ExternalLinkMonitoringTool" - /orchestrator/external-link: + /orchestrator/external-links: get: description: Get All active External links (If query parameter is not supplied then it will give all external links otherwise it will give external links diff --git a/specs/gitops/core.yaml b/specs/gitops/core.yaml index b25480cae1..1b0178f009 100644 --- a/specs/gitops/core.yaml +++ b/specs/gitops/core.yaml @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080 paths: - /gitops/config: + /orchestrator/gitops/config: post: description: Create or save new GitOps configuration and validate before saving operationId: CreateGitOpsConfig @@ -128,7 +128,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /gitops/config/{id}: + /orchestrator/gitops/config/{id}: get: description: Get GitOps configuration by ID operationId: GetGitOpsConfigById @@ -171,7 +171,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /gitops/config-by-provider: + /orchestrator/gitops/config-by-provider: get: description: Get GitOps configuration by provider operationId: GetGitOpsConfigByProvider @@ -214,7 +214,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /gitops/configured: + /orchestrator/gitops/configured: get: description: Check if GitOps is configured operationId: GitOpsConfigured @@ -251,7 +251,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /gitops/validate: + /orchestrator/gitops/validate: post: description: Validate GitOps configuration operationId: GitOpsValidator diff --git a/specs/helm/provider.yaml b/specs/helm/provider.yaml index feee685202..c1cb646063 100644 --- a/specs/helm/provider.yaml +++ b/specs/helm/provider.yaml @@ -16,7 +16,7 @@ servers: paths: # Chart Provider APIs - /chart-provider/list: + /orchestrator/app-store/chart-provider/list: get: description: Get list of all chart providers operationId: GetChartProviderList @@ -48,7 +48,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /chart-provider/update: + /orchestrator/app-store/chart-provider/update: post: description: Toggle chart provider status operationId: ToggleChartProvider @@ -94,7 +94,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /chart-provider/sync-chart: + /orchestrator/app-store/chart-provider/sync-chart: post: description: Sync chart provider operationId: SyncChartProvider @@ -141,7 +141,7 @@ paths: $ref: '#/components/schemas/ErrorResponse' # Chart Repository APIs - /chart-repo/{id}: + /orchestrator/chart-repo/{id}: get: description: Get chart repository by ID operationId: GetChartRepoById @@ -185,7 +185,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /chart-repo/list: + /orchestrator/chart-repo/list: get: description: Get list of all chart repositories operationId: GetChartRepoList @@ -217,7 +217,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /chart-repo: + /orchestrator/chart-repo: post: description: Create a new chart repository operationId: CreateChartRepo @@ -299,7 +299,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /chart-repo/validate: + /orchestrator/chart-repo/validate: post: description: Validate chart repository configuration operationId: ValidateChartRepo @@ -345,7 +345,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /chart-repo/sync: + /orchestrator/chart-repo/sync: post: description: Trigger manual chart repository sync operationId: TriggerChartSyncManual @@ -380,7 +380,7 @@ paths: $ref: '#/components/schemas/ErrorResponse' # Chart Group APIs - /chart-group: + /orchestrator/chart-group: post: description: Create a new chart group operationId: CreateChartGroup @@ -462,7 +462,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /chart-group/entries: + /orchestrator/chart-group/entries: post: description: Save chart group entries operationId: SaveChartGroupEntries @@ -508,7 +508,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /chart-group/list: + /orchestrator/chart-group/list: get: description: Get list of all chart groups operationId: GetChartGroupList @@ -540,7 +540,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /chart-group/{id}: + /orchestrator/chart-group/{id}: delete: description: Delete a chart group operationId: DeleteChartGroup diff --git a/specs/helm/repo-validation.yaml b/specs/helm/repo-validation.yaml index 1d67ac1fd3..d13fbcb934 100644 --- a/specs/helm/repo-validation.yaml +++ b/specs/helm/repo-validation.yaml @@ -3,9 +3,9 @@ info: version: 1.0.0 title: Helm Chart Repo Validation servers: - - url: http://localhost:3000/orchestrator/app-store + - url: http://localhost:3000/orchestrator/chart-repo paths: - /repo/validate: + /validate: post: description: Validate helm repo by checking index file operationId: ValidateChartRepo @@ -47,7 +47,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /repo/create: + /create: post: description: Validate chart repo config and save if successfully validated operationId: ValidateAndCreateChartRepo @@ -89,7 +89,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /repo/update: + /update: post: description: Validate configuration and update them if validation is successful operationId: ValidateAndUpdateChartRepo diff --git a/specs/kubernetes/capacity.yaml b/specs/kubernetes/capacity.yaml index 5bbbbebbaa..631f495cb9 100644 --- a/specs/kubernetes/capacity.yaml +++ b/specs/kubernetes/capacity.yaml @@ -17,12 +17,6 @@ paths: type: array items: $ref: '#/components/schemas/ClusterCapacityDetail' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' '401': description: Unauthorized content: @@ -56,12 +50,6 @@ paths: type: array items: $ref: '#/components/schemas/ClusterCapacityDetail' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' '401': description: Unauthorized content: @@ -101,7 +89,7 @@ paths: schema: $ref: '#/components/schemas/ClusterCapacityDetail' '400': - description: Bad request + description: Bad request - invalid clusterId format content: application/json: schema: @@ -147,7 +135,7 @@ paths: items: $ref: '#/components/schemas/NodeCapacityDetail' '400': - description: Bad request + description: Bad request - invalid clusterId format content: application/json: schema: @@ -197,7 +185,7 @@ paths: schema: $ref: '#/components/schemas/NodeCapacityDetail' '400': - description: Bad request + description: Bad request - invalid clusterId format or missing name content: application/json: schema: @@ -239,7 +227,7 @@ paths: schema: $ref: '#/components/schemas/NodeManifestUpdateResponse' '400': - description: Bad request + description: Bad request - invalid request body content: application/json: schema: @@ -281,7 +269,7 @@ paths: schema: $ref: '#/components/schemas/NodeManifestUpdateResponse' '400': - description: Bad request + description: Bad request - invalid request body content: application/json: schema: @@ -324,7 +312,7 @@ paths: schema: type: string '400': - description: Bad request + description: Bad request - invalid request body content: application/json: schema: @@ -367,7 +355,7 @@ paths: schema: type: string '400': - description: Bad request + description: Bad request - invalid request body content: application/json: schema: @@ -410,7 +398,7 @@ paths: schema: type: string '400': - description: Bad request + description: Bad request - invalid request body content: application/json: schema: diff --git a/specs/kubernetes/cluster.yaml b/specs/kubernetes/cluster.yaml index 31684ea71c..63f0e2a45c 100644 --- a/specs/kubernetes/cluster.yaml +++ b/specs/kubernetes/cluster.yaml @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080 paths: - /cluster: + /orchestrator/cluster: put: description: Update Cluster operationId: UpdateCluster @@ -96,7 +96,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /cluster/auth-list: + /orchestrator/cluster/auth-list: get: description: list of accessible cluster responses: diff --git a/specs/kubernetes/resources.yaml b/specs/kubernetes/resources.yaml index 540f1f3668..a1c7a9ea12 100644 --- a/specs/kubernetes/resources.yaml +++ b/specs/kubernetes/resources.yaml @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080/orchestrator/k8s paths: - /resource/inception/info: + /orchestrator/resource/inception/info: get: description: Get inception pod info, such as pod name responses: @@ -33,7 +33,7 @@ paths: result: $ref: '#/components/schemas/ResourceInfo' - /resource: + /orchestrator/resource: post: description: Get Kubernetes resource details requestBody: @@ -58,7 +58,7 @@ paths: result: $ref: '#/components/schemas/ManifestResponse' - /resource/create: + /orchestrator/resource/create: post: description: Create Kubernetes resource requestBody: @@ -83,7 +83,7 @@ paths: result: $ref: '#/components/schemas/ManifestResponse' - /resource/update: + /orchestrator/resource/update: put: description: Update Kubernetes resource requestBody: @@ -108,7 +108,7 @@ paths: result: $ref: '#/components/schemas/ManifestResponse' - /resource/delete: + /orchestrator/resource/delete: delete: description: Delete Kubernetes resource requestBody: @@ -133,7 +133,7 @@ paths: result: $ref: '#/components/schemas/ManifestResponse' - /api-resources/{clusterId}: + /orchestrator/api-resources/{clusterId}: get: description: Get all API resources for a cluster parameters: @@ -160,7 +160,7 @@ paths: items: $ref: '#/components/schemas/K8sApiResource' - /resource/urls: + /orchestrator/resource/urls: get: description: Get host URLs by batch parameters: diff --git a/specs/modularisation/v1.yaml b/specs/modularisation/v1.yaml index 4b31b98df7..3341994338 100644 --- a/specs/modularisation/v1.yaml +++ b/specs/modularisation/v1.yaml @@ -22,6 +22,10 @@ paths: type: array items: $ref: "#/components/schemas/ModuleInfo" + "401": + description: Unauthorized user + "500": + description: Internal server error post: description: some action on module (for eg - install/upgrade/etc..) parameters: @@ -44,6 +48,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ActionResponse" + "400": + description: Bad request - validation error or missing module name + "401": + description: Unauthorized user + "403": + description: Forbidden - insufficient permissions + "500": + description: Internal server error /orchestrator/server: get: description: Get server info @@ -54,6 +66,10 @@ paths: application/json: schema: $ref: "#/components/schemas/ServerInfo" + "401": + description: Unauthorized user + "500": + description: Internal server error post: description: some action on server (for eg - install/upgrade/etc..) requestBody: @@ -69,6 +85,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ActionResponse" + "400": + description: Bad request - validation error + "401": + description: Unauthorized user + "403": + description: Forbidden - insufficient permissions + "500": + description: Internal server error # Components components: diff --git a/specs/notifications/core.yaml b/specs/notifications/core.yaml index 9d9976f76d..c58fc70530 100644 --- a/specs/notifications/core.yaml +++ b/specs/notifications/core.yaml @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080/orchestrator paths: - /notification: + /orchestrator/notification: get: summary: Returns all notification settings description: Returns all notification settings @@ -118,7 +118,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /notification/recipient: + /orchestrator/notification/recipient: get: summary: used to fetch providers(recipients) description: recipients fetch by string search, it will return slacks providers and email ids @@ -140,7 +140,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /notification/channel: + /orchestrator/notification/channel: get: summary: get all NotificationSettingConfig list description: get all NotificationSettingConfig list diff --git a/specs/notifications/webhooks.yaml b/specs/notifications/webhooks.yaml index 2b77a53724..f87dd816c9 100644 --- a/specs/notifications/webhooks.yaml +++ b/specs/notifications/webhooks.yaml @@ -16,7 +16,7 @@ servers: paths: # Git Webhook APIs - /webhook/git: + /orchestrator/webhook/git: post: description: Handle Git webhook events operationId: HandleGitWebhook @@ -62,7 +62,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /webhook/git/{gitHostId}: + /orchestrator/webhook/git/{gitHostId}: post: description: Handle Git webhook events for a specific Git host operationId: HandleGitWebhookForHost @@ -115,7 +115,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /webhook/git/{gitHostId}/{secret}: + /orchestrator/webhook/git/{gitHostId}/{secret}: post: description: Handle Git webhook events with secret validation operationId: HandleGitWebhookWithSecret @@ -175,7 +175,7 @@ paths: $ref: '#/components/schemas/ErrorResponse' # CI/CD Webhook APIs - /webhook/ci/workflow: + /orchestrator/webhook/ci/workflow: post: description: Handle CI/CD workflow webhook events operationId: HandleWorkflowWebhook @@ -221,7 +221,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /webhook/ext-ci/{externalCiId}: + /orchestrator/webhook/ext-ci/{externalCiId}: post: description: Handle external CI webhook events operationId: HandleExternalCiWebhook @@ -276,7 +276,7 @@ paths: $ref: '#/components/schemas/ErrorResponse' # Notification Webhook APIs - /webhook/notification: + /orchestrator/webhook/notification: post: description: Create or update notification webhook configuration operationId: SaveNotificationWebhook @@ -322,7 +322,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /webhook/notification/{id}: + /orchestrator/webhook/notification/{id}: get: description: Get notification webhook configuration by ID operationId: GetNotificationWebhook @@ -366,7 +366,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /webhook/notification/variables: + /orchestrator/webhook/notification/variables: get: description: Get available webhook variables operationId: GetWebhookVariables diff --git a/specs/openapiClient/api/apiToken_api-openapi.yaml b/specs/openapiClient/api/apiToken_api-openapi.yaml index 939a6f7dc5..a0e16d4f7b 100644 --- a/specs/openapiClient/api/apiToken_api-openapi.yaml +++ b/specs/openapiClient/api/apiToken_api-openapi.yaml @@ -17,15 +17,17 @@ paths: $ref: '#/components/schemas/ApiToken' type: array description: Successfully fetched active API tokens links + "401": + description: Unauthorized user + "500": + description: Internal server error post: description: Create api-token requestBody: content: application/json: schema: - items: - $ref: '#/components/schemas/CreateApiTokenRequest' - type: array + $ref: '#/components/schemas/CreateApiTokenRequest' required: true responses: "200": @@ -34,6 +36,14 @@ paths: schema: $ref: '#/components/schemas/CreateApiTokenResponse' description: Api-token creation response + "400": + description: Bad request - validation error or name cannot be blank + "401": + description: Unauthorized user + "403": + description: Forbidden - insufficient permissions + "500": + description: Internal server error /orchestrator/api-token/{id}: delete: description: Delete api-token @@ -54,6 +64,14 @@ paths: schema: $ref: '#/components/schemas/ActionResponse' description: Api-token delete response + "400": + description: Bad request - invalid ID format + "401": + description: Unauthorized user + "403": + description: Forbidden - insufficient permissions + "500": + description: Internal server error put: description: Update api-token parameters: @@ -79,6 +97,14 @@ paths: schema: $ref: '#/components/schemas/UpdateApiTokenResponse' description: Api-token update response + "400": + description: Bad request - validation error or invalid ID format + "401": + description: Unauthorized user + "403": + description: Forbidden - insufficient permissions + "500": + description: Internal server error /orchestrator/api-token/webhook: get: description: Get all api tokens which have given permission @@ -116,6 +142,10 @@ paths: $ref: '#/components/schemas/ApiToken' type: array description: Successfully fetched active API tokens links + "401": + description: Unauthorized user + "500": + description: Internal server error components: schemas: diff --git a/specs/security/core.yaml b/specs/security/core.yaml index 235a463b9c..8b604d7191 100644 --- a/specs/security/core.yaml +++ b/specs/security/core.yaml @@ -16,7 +16,7 @@ servers: paths: # User Management APIs - /user/v2: + /orchestrator/user/v2: get: description: Get all users with optional filters operationId: GetAllUsers @@ -85,7 +85,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /user: + /orchestrator/user: post: description: Create a new user operationId: CreateUser @@ -167,7 +167,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /user/bulk: + /orchestrator/user/bulk: delete: description: Delete multiple users in bulk operationId: BulkDeleteUsers @@ -210,7 +210,7 @@ paths: $ref: '#/components/schemas/ErrorResponse' # Role Group Management APIs - /user/role/group/v2: + /orchestrator/user/role/group/v2: get: description: Get all role groups with optional filters operationId: GetAllRoleGroups @@ -279,7 +279,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /user/role/group: + /orchestrator/user/role/group: post: description: Create a new role group operationId: CreateRoleGroup @@ -361,7 +361,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /user/role/group/bulk: + /orchestrator/user/role/group/bulk: delete: description: Delete multiple role groups in bulk operationId: BulkDeleteRoleGroups @@ -404,7 +404,7 @@ paths: $ref: '#/components/schemas/ErrorResponse' # API Token Management APIs - /api-token: + /orchestrator/api-token: get: description: Get all active API tokens operationId: GetAllApiTokens @@ -476,7 +476,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /api-token/{id}: + /orchestrator/api-token/{id}: put: description: Update an existing API token operationId: UpdateApiToken diff --git a/specs/security/group-policy.yaml b/specs/security/group-policy.yaml index 2ebe632155..9d64df518f 100644 --- a/specs/security/group-policy.yaml +++ b/specs/security/group-policy.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: Devtron paths: - /user/role/group/v2: + /orchestrator/user/role/group/v2: get: summary: Returns all role groups description: all the template group policies @@ -126,7 +126,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /user/role/group: + /orchestrator/user/role/group: get: summary: Returns all role groups description: Returns all role groups in the system @@ -203,7 +203,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /user/role/group/search: + /orchestrator/user/role/group/search: get: summary: Search role groups by name description: Search role groups by their name @@ -231,7 +231,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /user/role/group/{id}: + /orchestrator/user/role/group/{id}: get: summary: Get a role group by ID description: Get detailed information about a specific role group @@ -283,7 +283,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /user/role/group/bulk: + /orchestrator/user/role/group/bulk: delete: summary: Delete multiple role groups description: Delete multiple role groups in bulk @@ -308,7 +308,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /user/role/group/detailed/get: + /orchestrator/user/role/group/detailed/get: get: summary: Returns detailed information about all role groups description: Returns detailed information about all role groups including their permissions diff --git a/specs/security/policy.yaml b/specs/security/policy.yaml index ce5690b89f..fb325cb3d7 100644 --- a/specs/security/policy.yaml +++ b/specs/security/policy.yaml @@ -5,7 +5,7 @@ info: servers: - url: http://petstore.swagger.io/api paths: - /user/v2: + /orchestrator/user/v2: get: summary: Returns all users description: Returns a paginated list of users with optional filtering and sorting @@ -73,7 +73,7 @@ paths: '500': description: Internal server error - /user: + /orchestrator/user: get: summary: Returns all users (deprecated) description: Returns all users (deprecated, use /user/v2 instead) @@ -147,33 +147,7 @@ paths: '500': description: Internal server error - /user/email: - get: - summary: Search user by email - description: Search for a user by their email address - operationId: findUserByEmail - parameters: - - name: email-id - in: query - description: Email ID of the user to search for - required: true - schema: - type: string - responses: - '200': - description: User details - content: - application/json: - schema: - $ref: '#/components/schemas/User' - '400': - description: Bad request - '401': - description: Unauthorized - '500': - description: Internal server error - - /user/{id}: + /orchestrator/user/{id}: get: summary: Get user by ID description: Returns user details with role filters @@ -219,11 +193,11 @@ paths: schema: type: boolean '400': - description: Bad request + description: Bad request - validation error or invalid request format '401': description: Unauthorized '403': - description: Forbidden + description: Forbidden - insufficient permissions '500': description: Internal server error diff --git a/specs/security/user-management.yaml b/specs/security/user-management.yaml index 2c44067cf2..61d470b881 100644 --- a/specs/security/user-management.yaml +++ b/specs/security/user-management.yaml @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080 paths: - /user/v2: + /orchestrator/user/v2: get: description: Get all users with filters parameters: @@ -82,7 +82,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /user: + /orchestrator/user: post: description: Create a new user requestBody: @@ -164,7 +164,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /user/{id}: + /orchestrator/user/{id}: get: description: Get user details by ID parameters: @@ -246,7 +246,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /user/bulk: + /orchestrator/user/bulk: delete: description: Delete multiple users in bulk requestBody: From 8663138c85857d2a221cf65602a87f84460af0b7 Mon Sep 17 00:00:00 2001 From: prakhar katiyar Date: Tue, 5 Aug 2025 01:21:23 +0530 Subject: [PATCH 4/9] spec-fixes as per cursor when ran on results file --- api/restHandler/CoreAppRestHandler.go | 23 +- .../configure/BuildPipelineRestHandler.go | 38 ++- specs/application/core.yaml | 36 ++- specs/ci-pipeline/ci-pipeline-build-spec.yaml | 123 +++++++-- specs/common/delete-options.yaml | 234 ++++++++++++++++-- specs/deployment/core.yaml | 2 +- specs/deployment/pipeline.yaml | 8 +- specs/environment/config-diff.yaml | 46 +++- specs/gitops/manifest-generation.yaml | 59 ++++- specs/jobs/batch.yaml | 81 +++++- specs/kubernetes/apis.yaml | 55 +++- specs/kubernetes/capacity.yaml | 53 +++- specs/kubernetes/cluster-management.yaml | 48 +++- specs/plugins/global.yaml | 15 ++ specs/security/core.yaml | 43 +++- 15 files changed, 739 insertions(+), 125 deletions(-) diff --git a/api/restHandler/CoreAppRestHandler.go b/api/restHandler/CoreAppRestHandler.go index 277405a08b..d568b6961c 100644 --- a/api/restHandler/CoreAppRestHandler.go +++ b/api/restHandler/CoreAppRestHandler.go @@ -21,6 +21,11 @@ import ( "encoding/json" "errors" "fmt" + "net/http" + "strconv" + "strings" + "time" + app2 "github.com/devtron-labs/devtron/api/restHandler/app/pipeline/configure" "github.com/devtron-labs/devtron/internal/sql/constants" appWorkflowBean "github.com/devtron-labs/devtron/pkg/appWorkflow/bean" @@ -34,10 +39,6 @@ import ( read5 "github.com/devtron-labs/devtron/pkg/chart/read" "github.com/devtron-labs/devtron/pkg/cluster/environment/repository" read3 "github.com/devtron-labs/devtron/pkg/team/read" - "net/http" - "strconv" - "strings" - "time" appBean "github.com/devtron-labs/devtron/api/appbean" "github.com/devtron-labs/devtron/api/restHandler/common" @@ -150,15 +151,15 @@ func (handler CoreAppRestHandlerImpl) GetAppAllDetail(w http.ResponseWriter, r * userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.WriteUnauthorizedError(w) return } vars := mux.Vars(r) appId, err := strconv.Atoi(vars["appId"]) if err != nil { - handler.logger.Errorw("request err, GetAppAllDetail", "err", err, "appId", appId) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + handler.logger.Errorw("request err, GetAppAllDetail", "err", err, "appId", vars["appId"]) + common.WriteInvalidAppIdError(w, vars["appId"]) return } @@ -167,7 +168,7 @@ func (handler CoreAppRestHandlerImpl) GetAppAllDetail(w http.ResponseWriter, r * object := handler.enforcerUtil.GetAppRBACNameByAppId(appId) if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionUpdate, object); !ok { handler.logger.Errorw("Unauthorized User for app update action", "err", err, "appId", appId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden) + common.WriteForbiddenError(w, "update", "application") return } //rbac implementation ends here for app @@ -447,13 +448,17 @@ func (handler CoreAppRestHandlerImpl) buildAppMetadata(appId int) (*appBean.AppM appMetaInfo, err := handler.appCrudOperationService.GetAppMetaInfo(appId, app.ZERO_INSTALLED_APP_ID, app.ZERO_ENVIRONMENT_ID) if err != nil { handler.logger.Errorw("service err, GetAppMetaInfo in GetAppAllDetail", "err", err, "appId", appId) + // Check if it's a "not found" error + if util2.IsErrNoRows(err) { + return nil, err, http.StatusNotFound + } return nil, err, http.StatusInternalServerError } if appMetaInfo == nil { err = errors.New("invalid appId - appMetaInfo is null") handler.logger.Errorw("Validation error ", "err", err, "appId", appId) - return nil, err, http.StatusBadRequest + return nil, err, http.StatusNotFound } var appLabelsRes []*appBean.AppLabel diff --git a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go index d0172e714a..ae0162995a 100644 --- a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go +++ b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go @@ -21,6 +21,12 @@ import ( "encoding/json" "errors" "fmt" + "io" + "net/http" + "regexp" + "strconv" + "strings" + apiBean "github.com/devtron-labs/devtron/api/restHandler/app/pipeline/configure/bean" "github.com/devtron-labs/devtron/internal/sql/constants" "github.com/devtron-labs/devtron/pkg/build/artifacts/imageTagging" @@ -29,11 +35,6 @@ import ( constants2 "github.com/devtron-labs/devtron/pkg/pipeline/constants" "github.com/devtron-labs/devtron/util/stringsUtil" "golang.org/x/exp/maps" - "io" - "net/http" - "regexp" - "strconv" - "strings" "github.com/devtron-labs/devtron/util/response/pagination" "github.com/gorilla/schema" @@ -683,19 +684,25 @@ func (handler *PipelineConfigRestHandlerImpl) TriggerCiPipeline(w http.ResponseW return } + // Validate required fields + if ciTriggerRequest.PipelineId == 0 { + common.WriteMissingRequiredFieldError(w, "pipelineId") + return + } + token := r.Header.Get("token") // RBAC block starts err := handler.validateCiTriggerRBAC(token, ciTriggerRequest.PipelineId, ciTriggerRequest.EnvironmentId) if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + handler.Logger.Errorw("RBAC validation failed for CI trigger", "err", err, "pipelineId", ciTriggerRequest.PipelineId) + common.WriteForbiddenError(w, "trigger", "CI pipeline") return } // RBAC block ends if !handler.validForMultiMaterial(ciTriggerRequest) { handler.Logger.Errorw("invalid req, commit hash not present for multi-git", "payload", ciTriggerRequest) - common.WriteJsonResp(w, errors.New("invalid req, commit hash not present for multi-git"), - nil, http.StatusBadRequest) + common.WriteValidationError(w, "ciPipelineMaterials", "Commit hash is required for multi-git repositories") return } @@ -706,18 +713,18 @@ func (handler *PipelineConfigRestHandlerImpl) TriggerCiPipeline(w http.ResponseW resp, err := handler.ciHandlerService.HandleCIManual(ciTriggerRequest) if errors.Is(err, bean1.ErrImagePathInUse) { handler.Logger.Errorw("service err duplicate image tag, TriggerCiPipeline", "err", err, "payload", ciTriggerRequest) - common.WriteJsonResp(w, err, err, http.StatusConflict) + common.WriteSpecificErrorResponse(w, "IMAGE_TAG_IN_USE", "Image tag is already in use", []string{"The specified image tag is already being used by another pipeline"}, http.StatusConflict) return } if err != nil { handler.Logger.Errorw("service err, TriggerCiPipeline", "err", err, "payload", ciTriggerRequest) - common.WriteJsonResp(w, err, response, http.StatusInternalServerError) + common.WriteSpecificErrorResponse(w, "CI_TRIGGER_FAILED", "Failed to trigger CI pipeline", []string{err.Error()}, http.StatusInternalServerError) return } response["apiResponse"] = strconv.Itoa(resp) - common.WriteJsonResp(w, err, response, http.StatusOK) + common.WriteJsonResp(w, nil, response, http.StatusOK) } func (handler *PipelineConfigRestHandlerImpl) FetchMaterials(w http.ResponseWriter, r *http.Request) { @@ -740,7 +747,12 @@ func (handler *PipelineConfigRestHandlerImpl) FetchMaterials(w http.ResponseWrit ciPipeline, err := handler.ciPipelineRepository.FindById(pipelineId) if err != nil { handler.Logger.Errorw("service err, FindById", "err", err, "pipelineId", pipelineId) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + // Check if it's a "not found" error + if util.IsErrNoRows(err) { + common.WritePipelineNotFoundError(w, pipelineId) + } else { + common.WriteDatabaseError(w, "fetch CI pipeline", err) + } return } @@ -753,7 +765,7 @@ func (handler *PipelineConfigRestHandlerImpl) FetchMaterials(w http.ResponseWrit resp, err := handler.ciHandler.FetchMaterialsByPipelineId(pipelineId, showAll) if err != nil { handler.Logger.Errorw("service err", "err", err, "context", "FetchMaterials", "data", map[string]interface{}{"pipelineId": pipelineId}) - common.WriteJsonResp(w, err, resp, http.StatusInternalServerError) + common.WriteSpecificErrorResponse(w, "FETCH_MATERIALS_FAILED", "Failed to fetch materials for pipeline", []string{err.Error()}, http.StatusInternalServerError) return } common.WriteJsonResp(w, nil, resp, http.StatusOK) diff --git a/specs/application/core.yaml b/specs/application/core.yaml index ebd0bb14ab..310d1522f1 100644 --- a/specs/application/core.yaml +++ b/specs/application/core.yaml @@ -19,6 +19,14 @@ servers: - url: /orchestrator description: Devtron Orchestrator API Server +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token for authentication + tags: - name: Applications description: Operations related to application management @@ -35,6 +43,8 @@ paths: summary: Create a new application description: Creates a new application in the Devtron system with the provided configuration. operationId: createApplication + security: + - bearerAuth: [] requestBody: description: Application creation request required: true @@ -54,27 +64,25 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' + $ref: '#/components/schemas/ApiError' '401': description: Unauthorized content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' + $ref: '#/components/schemas/ApiError' '409': description: Application with the same name already exists content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' + $ref: '#/components/schemas/ApiError' '500': description: Internal server error content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' - security: - - bearerAuth: [] + $ref: '#/components/schemas/ApiError' /app/edit: post: @@ -507,3 +515,19 @@ components: type: integer format: int64 description: IDs of projects to associate with the application + + ApiError: + type: object + properties: + code: + type: integer + format: int32 + example: 404 + message: + type: string + example: "Resource not found" + details: + type: array + items: + type: string + example: ["Application not found in the system"] diff --git a/specs/ci-pipeline/ci-pipeline-build-spec.yaml b/specs/ci-pipeline/ci-pipeline-build-spec.yaml index 3ed5387201..20dad308d5 100644 --- a/specs/ci-pipeline/ci-pipeline-build-spec.yaml +++ b/specs/ci-pipeline/ci-pipeline-build-spec.yaml @@ -16,7 +16,7 @@ servers: description: Devtron Orchestrator API Server paths: - /app/commit-info/{ciPipelineMaterialId}/{gitHash}: + /commit-info/{ciPipelineMaterialId}/{gitHash}: get: tags: - Commit @@ -77,23 +77,13 @@ paths: security: - bearerAuth: [] - /app/workflow/trigger/{pipelineId}: + /ci-pipeline/trigger: post: tags: - Workflow summary: Trigger CI workflow description: Triggers a new CI workflow for the specified pipeline operationId: triggerWorkflow - parameters: - - name: pipelineId - in: path - description: ID of the CI pipeline to trigger - required: true - schema: - type: integer - format: int32 - minimum: 1 - example: 456 requestBody: description: Workflow trigger payload required: true @@ -129,7 +119,7 @@ paths: security: - bearerAuth: [] - /app/workflow/{workflowId}: + /{appId}/ci-pipeline/{pipelineId}/workflow/{workflowId}: get: tags: - Workflow @@ -137,6 +127,24 @@ paths: description: Retrieves details of a specific workflow operationId: getWorkflow parameters: + - name: appId + in: path + description: ID of the application + required: true + schema: + type: integer + format: int32 + minimum: 1 + example: 123 + - name: pipelineId + in: path + description: ID of the CI pipeline + required: true + schema: + type: integer + format: int32 + minimum: 1 + example: 456 - name: workflowId in: path description: ID of the workflow @@ -212,22 +220,89 @@ components: WorkflowTriggerRequest: type: object required: - - commitHash + - pipelineId + - ciPipelineMaterials + properties: + pipelineId: + type: integer + description: ID of the CI pipeline to trigger + example: 123 + ciPipelineMaterials: + type: array + description: CI pipeline materials configuration + items: + $ref: '#/components/schemas/CiPipelineMaterial' + triggeredBy: + type: integer + description: User ID who triggered the pipeline + example: 1 + invalidateCache: + type: boolean + description: Whether to invalidate cache + default: false + environmentId: + type: integer + description: Environment ID for the pipeline + example: 456 + pipelineType: + type: string + description: Type of pipeline + example: "CI" + ciArtifactLastFetch: + type: string + format: date-time + description: Last fetch time for CI artifacts + + CiPipelineMaterial: + type: object properties: - commitHash: + Id: + type: integer + description: Material ID + example: 1 + GitMaterialId: + type: integer + description: Git material ID + example: 2 + Type: type: string - description: Specific commit hash to build (optional, defaults to latest) - example: "a1b2c3d4e5" - branchName: + description: Type of material + example: "GIT" + Value: type: string - description: Branch name (required if commitHash not provided) + description: Material value example: "main" - ciBuildConfig: - $ref: '#/components/schemas/CIBuildConfig' - ciBuildType: + Active: + type: boolean + description: Whether material is active + default: true + GitCommit: + $ref: '#/components/schemas/GitCommit' + GitTag: type: string - enum: [SELF_DOCKERFILE_BUILD_TYPE, MANIFEST_PUSH, SKIP_BUILD] - default: "SELF_DOCKERFILE_BUILD_TYPE" + description: Git tag + example: "v1.0.0" + + GitCommit: + type: object + properties: + Commit: + type: string + description: Commit hash + example: "a1b2c3d4e5" + Author: + type: string + description: Author name + example: "John Doe" + Date: + type: string + format: date-time + description: Commit date + example: "2023-01-15T14:30:22Z" + Message: + type: string + description: Commit message + example: "Update README" CIBuildConfig: type: object diff --git a/specs/common/delete-options.yaml b/specs/common/delete-options.yaml index 9d853e9386..492cd8c5af 100644 --- a/specs/common/delete-options.yaml +++ b/specs/common/delete-options.yaml @@ -2,11 +2,34 @@ openapi: "3.0.0" info: version: 1.0.0 title: Delete Option support for various components + description: API for deleting various components in Devtron including clusters, environments, teams, and other resources + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Support + email: support@devtron.ai + url: https://devtron.ai/support + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +servers: + - url: /orchestrator + description: Devtron Orchestrator API Server + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token for authentication paths: - /orchestrator/cluster/delete: + /cluster/delete: post: description: Delete Cluster operationId: DeleteFromDb + security: + - bearerAuth: [] requestBody: description: A JSON object containing the cluster config required: true @@ -27,23 +50,25 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error + $ref: '#/components/schemas/ApiError' + '401': + description: Unauthorized User content: application/json: schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User + $ref: '#/components/schemas/ApiError' + '500': + description: Internal Server Error content: application/json: schema: - $ref: '#/components/schemas/Error' - /orchestrator/env/delete: + $ref: '#/components/schemas/ApiError' + /env/delete: post: description: Delete Environment operationId: Delete + security: + - bearerAuth: [] requestBody: description: A JSON object containing the env config required: true @@ -59,6 +84,103 @@ paths: schema: type: string example: "Environment deleted successfully." + '400': + description: Bad Request. Input Validation(decode) error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '401': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + /team: + post: + description: Create Project + operationId: SaveTeam + security: + - bearerAuth: [] + requestBody: + description: A JSON object containing the project config + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TeamRequest' + responses: + '200': + description: Successfully created the project + content: + application/json: + schema: + $ref: '#/components/schemas/TeamRequest' + '400': + description: Bad Request. Input Validation(decode) error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '401': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + get: + description: Get All Projects + operationId: FetchAll + responses: + '200': + description: Successfully retrieved all projects + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TeamRequest' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + put: + description: Update Project + operationId: UpdateTeam + requestBody: + description: A JSON object containing the project config + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TeamRequest' + responses: + '200': + description: Successfully updated the project + content: + application/json: + schema: + $ref: '#/components/schemas/TeamRequest' '400': description: Bad Request. Input Validation(decode) error/wrong request body. content: @@ -77,8 +199,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/team/delete: - post: + delete: description: Delete Project operationId: DeleteTeam requestBody: @@ -114,7 +235,68 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/git/provider/delete: + /team/autocomplete: + get: + description: Get Projects for Autocomplete + operationId: FetchForAutocomplete + responses: + '200': + description: Successfully retrieved projects for autocomplete + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TeamRequest' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /team/{id}: + get: + description: Get Project by ID + operationId: FetchOne + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: Project ID + responses: + '200': + description: Successfully retrieved the project + content: + application/json: + schema: + $ref: '#/components/schemas/TeamRequest' + '400': + description: Bad Request. Invalid ID format. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /git/provider/delete: post: description: Delete Git Provider operationId: DeleteGitRepoConfig @@ -151,7 +333,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/docker/registry/delete: + /docker/registry/delete: post: description: Delete Docker Registry operationId: DeleteDockerRegistryConfig @@ -188,7 +370,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/app-store/repo/delete: + /app-store/repo/delete: post: description: Delete Chart Repo operationId: DeleteChartRepo @@ -225,7 +407,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/app/material/delete: + /app/material/delete: post: description: Delete Git Material operationId: DeleteMaterial @@ -262,7 +444,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/chart-group/delete: + /chart-group/delete: post: description: Delete Chart Group operationId: DeleteChartgroup @@ -299,7 +481,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/notification/channel/delete: + /notification/channel/delete: post: description: Delete Notification Channel operationId: DeleteNotificationChannelConfig @@ -646,4 +828,20 @@ components: description: Error code message: type: string - description: Error message \ No newline at end of file + description: Error message + + ApiError: + type: object + properties: + code: + type: integer + format: int32 + example: 404 + message: + type: string + example: "Resource not found" + details: + type: array + items: + type: string + example: ["Resource not found in the system"] \ No newline at end of file diff --git a/specs/deployment/core.yaml b/specs/deployment/core.yaml index 5f6f96c813..1117ee1161 100644 --- a/specs/deployment/core.yaml +++ b/specs/deployment/core.yaml @@ -24,7 +24,7 @@ paths: multipart/form-data: schema: properties: - binaryFile: + BinaryFile: type: string format: binary description: zipped chart template file diff --git a/specs/deployment/pipeline.yaml b/specs/deployment/pipeline.yaml index ce959ba77d..5d851bf190 100644 --- a/specs/deployment/pipeline.yaml +++ b/specs/deployment/pipeline.yaml @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080 paths: - /deployment/pipeline/configure: + /orchestrator/deployment/pipeline/configure: post: description: Configure deployment pipeline for an application requestBody: @@ -56,7 +56,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /deployment/pipeline/trigger: + /orchestrator/deployment/pipeline/trigger: post: description: Trigger a deployment pipeline requestBody: @@ -98,7 +98,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /deployment/pipeline/rollback: + /orchestrator/deployment/pipeline/rollback: post: description: Rollback a deployment pipeline requestBody: @@ -140,7 +140,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /deployment/pipeline/history: + /orchestrator/deployment/pipeline/history: get: description: Get deployment pipeline history parameters: diff --git a/specs/environment/config-diff.yaml b/specs/environment/config-diff.yaml index 41dbf5c11a..52aab87b15 100644 --- a/specs/environment/config-diff.yaml +++ b/specs/environment/config-diff.yaml @@ -3,12 +3,34 @@ info: title: Configuration Diff View API version: 1.0.0 description: API for managing configuration differences and comparisons + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Support + email: support@devtron.ai + url: https://devtron.ai/support + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +servers: + - url: /orchestrator + description: Devtron Orchestrator API Server + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token for authentication paths: - /orchestrator/config/autocomplete: + /config/autocomplete: get: summary: Get configuration autocomplete data operationId: ConfigAutoComplete + security: + - bearerAuth: [] parameters: - name: appId in: query @@ -56,7 +78,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/config/data: + /config/data: get: summary: Get configuration data operationId: GetConfigData @@ -153,7 +175,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/config/compare/{resource}: + /config/compare/{resource}: get: summary: Compare configuration data operationId: CompareCategoryWiseConfigData @@ -203,7 +225,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/config/manifest: + /config/manifest: post: summary: Get manifest for configuration operationId: GetManifest @@ -396,3 +418,19 @@ components: type: string description: Error message + ApiError: + type: object + properties: + code: + type: integer + format: int32 + example: 404 + message: + type: string + example: "Resource not found" + details: + type: array + items: + type: string + example: ["Configuration not found in the system"] + diff --git a/specs/gitops/manifest-generation.yaml b/specs/gitops/manifest-generation.yaml index fa7408a0e6..3f0309b1f8 100644 --- a/specs/gitops/manifest-generation.yaml +++ b/specs/gitops/manifest-generation.yaml @@ -2,12 +2,35 @@ openapi: 3.0.3 info: title: App Deployment API version: 1.0.0 + description: API for GitOps manifest generation and deployment template management + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Support + email: support@devtron.ai + url: https://devtron.ai/support + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +servers: + - url: /orchestrator + description: Devtron Orchestrator API Server + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token for authentication paths: - /orchestrator/app/deployments/{app-id}/{env-id}: + /app/deployments/{app-id}/{env-id}: get: summary: Fetch Deployment Template Comparison List description: Returns a list of deployment templates that can be compared operationId: FetchDeploymentsWithChartRefs + security: + - bearerAuth: [] parameters: - name: app-id in: path @@ -37,31 +60,33 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ApiError' '401': description: Unauthorized content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ApiError' '403': description: Forbidden content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ApiError' '500': description: Internal server error content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ApiError' - /orchestrator/app/deployment/template/data: + /app/deployment/template/data: post: summary: Get Values and Manifest for Deployment Template description: Returns the values and manifest for a deployment template operationId: GetDeploymentTemplate + security: + - bearerAuth: [] requestBody: required: true content: @@ -80,19 +105,19 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ApiError' '401': description: Unauthorized content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ApiError' '403': description: Forbidden content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ApiError' '500': description: Internal server error content: @@ -214,3 +239,19 @@ components: message: type: string description: Error message + + ApiError: + type: object + properties: + code: + type: integer + format: int32 + example: 404 + message: + type: string + example: "Resource not found" + details: + type: array + items: + type: string + example: ["Deployment template not found"] diff --git a/specs/jobs/batch.yaml b/specs/jobs/batch.yaml index 68e23fd8d6..5210ee3a7a 100644 --- a/specs/jobs/batch.yaml +++ b/specs/jobs/batch.yaml @@ -12,11 +12,22 @@ info: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html servers: - - url: http://localhost:8080/orchestrator + - url: /orchestrator + description: Devtron Orchestrator API Server + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token for authentication paths: - /operate: + /batch/operate: post: description: Execute batch operations on applications and workflows + security: + - bearerAuth: [] requestBody: required: true content: @@ -39,16 +50,30 @@ paths: result: type: string description: operation result - default: - description: unexpected error + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + description: Internal server error content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' + $ref: '#/components/schemas/ApiError' - /bulk/v1beta1/application/dryrun: + /batch/bulk/v1beta1/application/dryrun: post: description: Get impacted apps for bulk update (dry run) + security: + - bearerAuth: [] requestBody: required: true content: @@ -70,10 +95,24 @@ paths: description: status result: $ref: '#/components/schemas/ImpactedObjectsResponse' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' - /bulk/v1beta1/application: + /batch/bulk/v1beta1/application: post: description: Execute bulk update on applications + security: + - bearerAuth: [] requestBody: required: true content: @@ -95,6 +134,18 @@ paths: description: status result: $ref: '#/components/schemas/BulkUpdateResponse' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' components: schemas: @@ -407,5 +458,21 @@ components: items: type: object + ApiError: + type: object + properties: + code: + type: integer + format: int32 + example: 404 + message: + type: string + example: "Resource not found" + details: + type: array + items: + type: string + example: ["Batch operation failed"] + diff --git a/specs/kubernetes/apis.yaml b/specs/kubernetes/apis.yaml index b7b703229c..95f2c4a0a1 100644 --- a/specs/kubernetes/apis.yaml +++ b/specs/kubernetes/apis.yaml @@ -2,8 +2,29 @@ openapi: "3.0.3" info: version: 1.0.0 title: Devtron Labs + description: API for managing Kubernetes resources and operations + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Support + email: support@devtron.ai + url: https://devtron.ai/support + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +servers: + - url: /orchestrator + description: Devtron Orchestrator API Server + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token for authentication paths: - /orchestrator/k8s/resource: + /k8s/resource: post: summary: Get Kubernetes resource manifest description: Fetches the manifest for a specified Kubernetes resource @@ -54,7 +75,7 @@ paths: description: Forbidden "500": description: Internal server error - /orchestrator/k8s/resource/create: + /k8s/resource/create: post: summary: Create Kubernetes resource description: Creates a new Kubernetes resource @@ -80,7 +101,7 @@ paths: description: Forbidden "500": description: Internal server error - /orchestrator/k8s/resource/delete: + /k8s/resource/delete: post: summary: Delete Kubernetes resource description: Deletes a Kubernetes resource @@ -106,7 +127,7 @@ paths: description: Forbidden "500": description: Internal server error - /orchestrator/k8s/events: + /k8s/events: post: summary: Get Kubernetes events description: Fetches events for Kubernetes resources @@ -132,7 +153,7 @@ paths: description: Forbidden "500": description: Internal server error - /orchestrator/k8s/pods/logs/{podName}: + /k8s/pods/logs/{podName}: get: summary: Get pod logs description: Fetches logs for a container in a pod @@ -191,7 +212,7 @@ paths: description: Forbidden "500": description: Internal server error - /orchestrator/k8s/pod/exec/session/{identifier}/{namespace}/{pod}/{shell}/{container}: + /k8s/pod/exec/session/{identifier}/{namespace}/{pod}/{shell}/{container}: get: summary: Get terminal session description: Gets a terminal session for a pod @@ -248,7 +269,7 @@ paths: description: Forbidden "500": description: Internal server error - /orchestrator/k8s/api-resources/{clusterId}: + /k8s/api-resources/{clusterId}: get: summary: Get API resources description: Gets all API resources for a given cluster @@ -276,7 +297,7 @@ paths: description: Forbidden "500": description: Internal server error - /orchestrator/k8s/resource/list: + /k8s/resource/list: post: summary: List resources description: Lists Kubernetes resources @@ -495,4 +516,20 @@ components: type: array items: type: string - description: Available verbs \ No newline at end of file + description: Available verbs + + ApiError: + type: object + properties: + code: + type: integer + format: int32 + example: 404 + message: + type: string + example: "Resource not found" + details: + type: array + items: + type: string + example: ["Kubernetes resource not found"] \ No newline at end of file diff --git a/specs/kubernetes/capacity.yaml b/specs/kubernetes/capacity.yaml index 631f495cb9..1d74069dde 100644 --- a/specs/kubernetes/capacity.yaml +++ b/specs/kubernetes/capacity.yaml @@ -2,8 +2,29 @@ openapi: "3.0.0" info: title: Kubernetes Capacity version: "1.0" + description: API for managing Kubernetes cluster capacity and node operations + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Support + email: support@devtron.ai + url: https://devtron.ai/support + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +servers: + - url: /orchestrator + description: Devtron Orchestrator API Server + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token for authentication paths: - /orchestrator/k8s/capacity/cluster/list/raw: + /k8s/capacity/cluster/list/raw: get: summary: Get cluster list description: Returns a list of clusters with basic information @@ -36,7 +57,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/k8s/capacity/cluster/list: + /k8s/capacity/cluster/list: get: summary: Get cluster list with details description: Returns a list of clusters with detailed capacity information @@ -69,7 +90,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/k8s/capacity/cluster/{clusterId}: + /k8s/capacity/cluster/{clusterId}: get: summary: Get cluster details description: Returns detailed capacity information for a specific cluster @@ -113,7 +134,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/k8s/capacity/node/list: + /k8s/capacity/node/list: get: summary: Get node list description: Returns a list of nodes in a cluster @@ -159,7 +180,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/k8s/capacity/node: + /k8s/capacity/node: get: summary: Get node details description: Returns detailed information for a specific node @@ -293,7 +314,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/k8s/capacity/node/cordon: + /k8s/capacity/node/cordon: put: summary: Cordon or uncordon node description: Marks a node as unschedulable or schedulable @@ -336,7 +357,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/k8s/capacity/node/drain: + /k8s/capacity/node/drain: put: summary: Drain node description: Safely evicts all pods from a node @@ -379,7 +400,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/k8s/capacity/node/taints/edit: + /k8s/capacity/node/taints/edit: put: summary: Edit node taints description: Updates the taints on a node @@ -668,3 +689,19 @@ components: type: string message: type: string + + ApiError: + type: object + properties: + code: + type: integer + format: int32 + example: 404 + message: + type: string + example: "Resource not found" + details: + type: array + items: + type: string + example: ["Kubernetes resource not found"] diff --git a/specs/kubernetes/cluster-management.yaml b/specs/kubernetes/cluster-management.yaml index d613fb7da4..2509b25bcf 100644 --- a/specs/kubernetes/cluster-management.yaml +++ b/specs/kubernetes/cluster-management.yaml @@ -3,9 +3,29 @@ info: title: Cluster Management API version: 1.0.0 description: API for managing Kubernetes clusters + termsOfService: https://devtron.ai/terms/ + contact: + name: Devtron Support + email: support@devtron.ai + url: https://devtron.ai/support + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +servers: + - url: /orchestrator + description: Devtron Orchestrator API Server + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token for authentication paths: - /orchestrator/cluster: + /cluster: post: summary: Create a new cluster operationId: CreateCluster @@ -160,7 +180,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/cluster/saveClusters: + /cluster/saveClusters: post: summary: Save multiple clusters operationId: SaveClusters @@ -206,7 +226,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/cluster/validate: + /cluster/validate: post: summary: Validate cluster configuration operationId: ValidateCluster @@ -253,7 +273,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/cluster/namespaces/{clusterId}: + /cluster/namespaces/{clusterId}: get: summary: Get namespaces for a cluster operationId: GetClusterNamespaces @@ -297,7 +317,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/cluster/namespaces: + /cluster/namespaces: get: summary: Get namespaces for all clusters operationId: GetAllClusterNamespaces @@ -331,7 +351,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/cluster/auth-list: + /cluster/auth-list: get: summary: Get clusters with authentication details operationId: GetClustersWithAuth @@ -473,6 +493,22 @@ components: type: string description: Error message + ApiError: + type: object + properties: + code: + type: integer + format: int32 + example: 404 + message: + type: string + example: "Resource not found" + details: + type: array + items: + type: string + example: ["Cluster not found in the system"] + diff --git a/specs/plugins/global.yaml b/specs/plugins/global.yaml index 35ef08659e..c0d658104a 100644 --- a/specs/plugins/global.yaml +++ b/specs/plugins/global.yaml @@ -11,6 +11,8 @@ paths: put: description: Migrate plugin data to the latest schema operationId: MigratePluginData + security: + - bearerAuth: [] responses: '200': description: Successfully migrated plugin data @@ -41,6 +43,8 @@ paths: post: description: Create a new plugin or plugin version operationId: CreatePlugin + security: + - bearerAuth: [] parameters: - name: appId in: query @@ -89,6 +93,8 @@ paths: get: description: Get detailed information of all available plugins operationId: GetAllDetailedPluginInfo + security: + - bearerAuth: [] responses: '200': description: Successfully retrieved all plugin details @@ -570,3 +576,12 @@ components: message: type: string description: Error message + + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: >- + JWT token for authentication. + Include the token in the Authorization header as: 'Bearer {token}' diff --git a/specs/security/core.yaml b/specs/security/core.yaml index 8b604d7191..0c12150aae 100644 --- a/specs/security/core.yaml +++ b/specs/security/core.yaml @@ -12,14 +12,25 @@ info: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html servers: - - url: http://localhost:8080 + - url: /orchestrator + description: Devtron Orchestrator API Server + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token for authentication paths: # User Management APIs - /orchestrator/user/v2: + /user/v2: get: description: Get all users with optional filters operationId: GetAllUsers + security: + - bearerAuth: [] parameters: - name: searchKey in: query @@ -71,24 +82,26 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' + $ref: '#/components/schemas/ApiError' '403': description: Forbidden content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' + $ref: '#/components/schemas/ApiError' '500': description: Internal Server Error content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' + $ref: '#/components/schemas/ApiError' - /orchestrator/user: + /user: post: description: Create a new user operationId: CreateUser + security: + - bearerAuth: [] requestBody: required: true content: @@ -808,4 +821,20 @@ components: description: Error code message: type: string - description: Error message \ No newline at end of file + description: Error message + + ApiError: + type: object + properties: + code: + type: integer + format: int32 + example: 404 + message: + type: string + example: "Resource not found" + details: + type: array + items: + type: string + example: ["User not found in the system"] \ No newline at end of file From f91993f00fc5ba6fc64e6094856255f604e785fb Mon Sep 17 00:00:00 2001 From: prakhar katiyar Date: Tue, 5 Aug 2025 03:25:10 +0530 Subject: [PATCH 5/9] spec-fixes manually for /orchestrator path --- specs/app-store.yaml | 2 +- specs/application/core.yaml | 517 +++++++++--------- specs/application/creation.yaml | 2 +- specs/application/listing.yaml | 2 +- .../buildInfraConfig/build-infra-config.yaml | 4 +- specs/ci-pipeline/ci-pipeline-build-spec.yaml | 2 +- specs/common/delete-options.yaml | 2 +- specs/deployment/group.yaml | 2 +- specs/environment/config-diff.yaml | 2 +- specs/environment/core.yaml | 2 +- specs/gitops/manifest-generation.yaml | 2 +- specs/gitops/validation.yaml | 2 +- specs/helm/repo-validation.yaml | 2 +- specs/jobs/batch.yaml | 2 +- specs/jobs/bulk-actions.yaml | 2 +- specs/jobs/bulk-update.yaml | 2 +- specs/jobs/core.yaml | 2 +- specs/kubernetes/apis.yaml | 2 +- specs/kubernetes/capacity.yaml | 2 +- specs/kubernetes/cluster-management.yaml | 2 +- specs/security/api-tokens.yaml | 2 +- specs/security/core.yaml | 4 +- specs/security/security-dashboard-apis.yml | 2 +- specs/swagger/openapi.yaml | 100 ++-- .../workflow-stage-status.internal.yaml | 2 +- wire_gen.go | 2 +- 26 files changed, 331 insertions(+), 338 deletions(-) diff --git a/specs/app-store.yaml b/specs/app-store.yaml index 8cc1678dd2..b330245a7b 100644 --- a/specs/app-store.yaml +++ b/specs/app-store.yaml @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080 paths: - /app-store/discover: + /orchestrator/app-store/discover: get: description: Get all charts from chart repositories parameters: diff --git a/specs/application/core.yaml b/specs/application/core.yaml index 310d1522f1..4d13c2315e 100644 --- a/specs/application/core.yaml +++ b/specs/application/core.yaml @@ -26,6 +26,260 @@ components: scheme: bearer bearerFormat: JWT description: JWT token for authentication + schemas: + ApiResponse: + type: object + properties: + code: + type: integer + description: Status code + status: + type: string + description: Status message + result: + type: object + description: Response result data + + ErrorResponse: + type: object + properties: + code: + type: integer + description: Error code + status: + type: string + description: Error status + errors: + type: array + items: + type: string + description: List of error messages + + AppLabel: + type: object + required: + - key + - value + properties: + key: + type: string + description: Label key + value: + type: string + description: Label value + propagate: + type: boolean + description: Whether to propagate to kubernetes resources + + App: + type: object + required: + - appName + properties: + id: + type: integer + format: int64 + description: Application ID + appName: + type: string + description: Name of the application + teamId: + type: integer + format: int64 + description: Team ID + labels: + type: array + items: + $ref: '#/components/schemas/AppLabel' + description: Application labels + description: + type: string + description: Application description + projectIds: + type: array + items: + type: integer + format: int64 + description: IDs of projects this application belongs to + + CreateAppRequest: + type: object + required: + - metadata + properties: + metadata: + $ref: '#/components/schemas/App' + appWorkflows: + type: array + description: App workflows + items: + type: object + environmentOverrides: + type: array + description: Environment overrides + items: + type: object + + AppListingRequest: + type: object + properties: + teamIds: + type: array + items: + type: integer + format: int64 + description: Filter by team IDs + environmentIds: + type: array + items: + type: integer + format: int64 + description: Filter by environment IDs + statuses: + type: array + items: + type: string + enum: [Healthy, Degraded, Failed, Progressing] + description: Filter by application statuses + appNameSearch: + type: string + description: Search term for application name + offset: + type: integer + description: Pagination offset + size: + type: integer + description: Page size + projectIds: + type: array + items: + type: integer + format: int64 + description: Filter by project IDs + + AppListResponse: + type: object + properties: + code: + type: integer + description: Status code + status: + type: string + description: Status message + result: + type: object + properties: + appCount: + type: integer + description: Total number of applications matching the filters + appContainers: + type: array + items: + $ref: '#/components/schemas/AppContainer' + deploymentGroup: + $ref: '#/components/schemas/DeploymentGroup' + + AppContainer: + type: object + properties: + appId: + type: integer + format: int64 + description: Application ID + appName: + type: string + description: Application name + environments: + type: array + items: + $ref: '#/components/schemas/AppEnvironment' + description: Environments where the application is deployed + + AppEnvironment: + type: object + properties: + environmentId: + type: integer + format: int64 + description: Environment ID + environmentName: + type: string + description: Environment name + status: + type: string + enum: [Healthy, Degraded, Failed, Progressing] + description: Application status in this environment + lastDeployed: + type: string + format: date-time + description: Last deployment timestamp + + DeploymentGroup: + type: object + properties: + id: + type: integer + format: int64 + description: Deployment group ID + name: + type: string + description: Deployment group name + applications: + type: array + items: + type: integer + format: int64 + description: IDs of applications in this deployment group + + AppDetails: + type: object + properties: + app: + $ref: '#/components/schemas/App' + environments: + type: array + items: + $ref: '#/components/schemas/AppEnvironment' + description: Environments where the application is deployed + ciConfig: + type: object + description: CI configuration + cdConfig: + type: object + description: CD configuration + + AppProjectUpdateRequest: + type: object + required: + - appId + - projectIds + properties: + appId: + type: integer + format: int64 + description: Application ID + projectIds: + type: array + items: + type: integer + format: int64 + description: IDs of projects to associate with the application + + ApiError: + type: object + properties: + code: + type: integer + format: int32 + example: 404 + message: + type: string + example: "Resource not found" + details: + type: array + items: + type: string + example: ["Application not found in the system"] tags: - name: Applications @@ -36,7 +290,7 @@ tags: description: Operations related to application deployments paths: - /core/v1beta1/application: + /orchestrator/core/v1beta1/application: post: tags: - Applications @@ -270,264 +524,3 @@ paths: - bearerAuth: [] # components section -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - - schemas: - ApiResponse: - type: object - properties: - code: - type: integer - description: Status code - status: - type: string - description: Status message - result: - type: object - description: Response result data - - ErrorResponse: - type: object - properties: - code: - type: integer - description: Error code - status: - type: string - description: Error status - errors: - type: array - items: - type: string - description: List of error messages - - AppLabel: - type: object - required: - - key - - value - properties: - key: - type: string - description: Label key - value: - type: string - description: Label value - propagate: - type: boolean - description: Whether to propagate to kubernetes resources - - App: - type: object - required: - - appName - properties: - id: - type: integer - format: int64 - description: Application ID - appName: - type: string - description: Name of the application - teamId: - type: integer - format: int64 - description: Team ID - labels: - type: array - items: - $ref: '#/components/schemas/AppLabel' - description: Application labels - description: - type: string - description: Application description - projectIds: - type: array - items: - type: integer - format: int64 - description: IDs of projects this application belongs to - - CreateAppRequest: - type: object - required: - - metadata - properties: - metadata: - $ref: '#/components/schemas/App' - appWorkflows: - type: array - description: App workflows - items: - type: object - environmentOverrides: - type: array - description: Environment overrides - items: - type: object - - AppListingRequest: - type: object - properties: - teamIds: - type: array - items: - type: integer - format: int64 - description: Filter by team IDs - environmentIds: - type: array - items: - type: integer - format: int64 - description: Filter by environment IDs - statuses: - type: array - items: - type: string - enum: [Healthy, Degraded, Failed, Progressing] - description: Filter by application statuses - appNameSearch: - type: string - description: Search term for application name - offset: - type: integer - description: Pagination offset - size: - type: integer - description: Page size - projectIds: - type: array - items: - type: integer - format: int64 - description: Filter by project IDs - - AppListResponse: - type: object - properties: - code: - type: integer - description: Status code - status: - type: string - description: Status message - result: - type: object - properties: - appCount: - type: integer - description: Total number of applications matching the filters - appContainers: - type: array - items: - $ref: '#/components/schemas/AppContainer' - deploymentGroup: - $ref: '#/components/schemas/DeploymentGroup' - - AppContainer: - type: object - properties: - appId: - type: integer - format: int64 - description: Application ID - appName: - type: string - description: Application name - environments: - type: array - items: - $ref: '#/components/schemas/AppEnvironment' - description: Environments where the application is deployed - - AppEnvironment: - type: object - properties: - environmentId: - type: integer - format: int64 - description: Environment ID - environmentName: - type: string - description: Environment name - status: - type: string - enum: [Healthy, Degraded, Failed, Progressing] - description: Application status in this environment - lastDeployed: - type: string - format: date-time - description: Last deployment timestamp - - DeploymentGroup: - type: object - properties: - id: - type: integer - format: int64 - description: Deployment group ID - name: - type: string - description: Deployment group name - applications: - type: array - items: - type: integer - format: int64 - description: IDs of applications in this deployment group - - AppDetails: - type: object - properties: - app: - $ref: '#/components/schemas/App' - environments: - type: array - items: - $ref: '#/components/schemas/AppEnvironment' - description: Environments where the application is deployed - ciConfig: - type: object - description: CI configuration - cdConfig: - type: object - description: CD configuration - - AppProjectUpdateRequest: - type: object - required: - - appId - - projectIds - properties: - appId: - type: integer - format: int64 - description: Application ID - projectIds: - type: array - items: - type: integer - format: int64 - description: IDs of projects to associate with the application - - ApiError: - type: object - properties: - code: - type: integer - format: int32 - example: 404 - message: - type: string - example: "Resource not found" - details: - type: array - items: - type: string - example: ["Application not found in the system"] diff --git a/specs/application/creation.yaml b/specs/application/creation.yaml index 6be90f226d..3d1239eba2 100644 --- a/specs/application/creation.yaml +++ b/specs/application/creation.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: Create App Api paths: - /core/v1beta1/application/{appId}: + /orchestrator/core/v1beta1/application/{appId}: get: description: Get all details of an app by appId. These details include - metadata(appName, projectNamr, labels), gitMaterials, docker config, templates, workflows, configMaps, secrets, environment override configurations. operationId: GetAppAllDetail diff --git a/specs/application/listing.yaml b/specs/application/listing.yaml index f5215ee4af..07f4b38249 100644 --- a/specs/application/listing.yaml +++ b/specs/application/listing.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: Devtron Labs paths: - /app/autocomplete: + /orchestrator/app/autocomplete: get: description: list of namespaces group by clusters parameters: diff --git a/specs/buildInfraConfig/build-infra-config.yaml b/specs/buildInfraConfig/build-infra-config.yaml index e9ecca898b..a03b401ca7 100644 --- a/specs/buildInfraConfig/build-infra-config.yaml +++ b/specs/buildInfraConfig/build-infra-config.yaml @@ -7,7 +7,7 @@ servers: - url: 'https' paths: - /infra-config/profile: + /orchestrator/infra-config/profile: get: description: Get Infra Profile by name parameters: @@ -149,7 +149,7 @@ servers: - url: 'https' paths: - /infra-config/profile: + /orchestrator/infra-config/profile: get: description: Get Infra Profile by name parameters: diff --git a/specs/ci-pipeline/ci-pipeline-build-spec.yaml b/specs/ci-pipeline/ci-pipeline-build-spec.yaml index 20dad308d5..d88ede2f46 100644 --- a/specs/ci-pipeline/ci-pipeline-build-spec.yaml +++ b/specs/ci-pipeline/ci-pipeline-build-spec.yaml @@ -16,7 +16,7 @@ servers: description: Devtron Orchestrator API Server paths: - /commit-info/{ciPipelineMaterialId}/{gitHash}: + /orchestrator/commit-info/{ciPipelineMaterialId}/{gitHash}: get: tags: - Commit diff --git a/specs/common/delete-options.yaml b/specs/common/delete-options.yaml index 492cd8c5af..3720f9be78 100644 --- a/specs/common/delete-options.yaml +++ b/specs/common/delete-options.yaml @@ -24,7 +24,7 @@ components: bearerFormat: JWT description: JWT token for authentication paths: - /cluster/delete: + /orchestrator/cluster/delete: post: description: Delete Cluster operationId: DeleteFromDb diff --git a/specs/deployment/group.yaml b/specs/deployment/group.yaml index 8c7fdb05a8..7e0767364a 100644 --- a/specs/deployment/group.yaml +++ b/specs/deployment/group.yaml @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080 paths: - /deployment-group/create: + /orchestrator/deployment-group/create: post: description: Create a new deployment group requestBody: diff --git a/specs/environment/config-diff.yaml b/specs/environment/config-diff.yaml index 52aab87b15..4d0086d6c1 100644 --- a/specs/environment/config-diff.yaml +++ b/specs/environment/config-diff.yaml @@ -25,7 +25,7 @@ components: description: JWT token for authentication paths: - /config/autocomplete: + /orchestrator/config/autocomplete: get: summary: Get configuration autocomplete data operationId: ConfigAutoComplete diff --git a/specs/environment/core.yaml b/specs/environment/core.yaml index fed6f9b6d2..dce28062e0 100644 --- a/specs/environment/core.yaml +++ b/specs/environment/core.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: Devtron Labs paths: - /env/namespace/autocomplete: + /orchestrator/env/namespace/autocomplete: get: description: list of namespaces group by clusters parameters: diff --git a/specs/gitops/manifest-generation.yaml b/specs/gitops/manifest-generation.yaml index 3f0309b1f8..d72fffc380 100644 --- a/specs/gitops/manifest-generation.yaml +++ b/specs/gitops/manifest-generation.yaml @@ -24,7 +24,7 @@ components: bearerFormat: JWT description: JWT token for authentication paths: - /app/deployments/{app-id}/{env-id}: + /orchestrator/app/deployments/{app-id}/{env-id}: get: summary: Fetch Deployment Template Comparison List description: Returns a list of deployment templates that can be compared diff --git a/specs/gitops/validation.yaml b/specs/gitops/validation.yaml index 6915d91a6c..6c9bf6d2b9 100644 --- a/specs/gitops/validation.yaml +++ b/specs/gitops/validation.yaml @@ -5,7 +5,7 @@ info: servers: - url: http://localhost:3000/orchestrator/gitops paths: - /validate: + /orchestrator/validate: post: description: Validate GitOps configuration operationId: GitOpsValidator diff --git a/specs/helm/repo-validation.yaml b/specs/helm/repo-validation.yaml index d13fbcb934..c58703f2b8 100644 --- a/specs/helm/repo-validation.yaml +++ b/specs/helm/repo-validation.yaml @@ -5,7 +5,7 @@ info: servers: - url: http://localhost:3000/orchestrator/chart-repo paths: - /validate: + /orchestrator/validate: post: description: Validate helm repo by checking index file operationId: ValidateChartRepo diff --git a/specs/jobs/batch.yaml b/specs/jobs/batch.yaml index 5210ee3a7a..bb544d9964 100644 --- a/specs/jobs/batch.yaml +++ b/specs/jobs/batch.yaml @@ -23,7 +23,7 @@ components: bearerFormat: JWT description: JWT token for authentication paths: - /batch/operate: + /orchestrator/batch/operate: post: description: Execute batch operations on applications and workflows security: diff --git a/specs/jobs/bulk-actions.yaml b/specs/jobs/bulk-actions.yaml index 896ef41724..d317757bba 100644 --- a/specs/jobs/bulk-actions.yaml +++ b/specs/jobs/bulk-actions.yaml @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080/orchestrator/batch paths: - /v1beta1/hibernate: + /orchestrator/v1beta1/hibernate: post: description: Bulk Hibernate all apps for specific environment operationId: BulkHibernate diff --git a/specs/jobs/bulk-update.yaml b/specs/jobs/bulk-update.yaml index 0a480e13a4..e6040d011a 100644 --- a/specs/jobs/bulk-update.yaml +++ b/specs/jobs/bulk-update.yaml @@ -5,7 +5,7 @@ info: servers: - url: http://localhost:3000/orchestrator/batch paths: - /{apiVersion}/{kind}/readme: + /orchestrator/{apiVersion}/{kind}/readme: get: description: Returns Readme for bulk update for different resource in the url operationId: FindBulkUpdateReadme diff --git a/specs/jobs/core.yaml b/specs/jobs/core.yaml index eb9935e88f..68ff161ace 100644 --- a/specs/jobs/core.yaml +++ b/specs/jobs/core.yaml @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080/orchestrator paths: - /job: + /orchestrator/job: post: description: Create and clones a job requestBody: diff --git a/specs/kubernetes/apis.yaml b/specs/kubernetes/apis.yaml index 95f2c4a0a1..671aa8d9c2 100644 --- a/specs/kubernetes/apis.yaml +++ b/specs/kubernetes/apis.yaml @@ -24,7 +24,7 @@ components: bearerFormat: JWT description: JWT token for authentication paths: - /k8s/resource: + /orchestrator/k8s/resource: post: summary: Get Kubernetes resource manifest description: Fetches the manifest for a specified Kubernetes resource diff --git a/specs/kubernetes/capacity.yaml b/specs/kubernetes/capacity.yaml index 1d74069dde..35655a0109 100644 --- a/specs/kubernetes/capacity.yaml +++ b/specs/kubernetes/capacity.yaml @@ -24,7 +24,7 @@ components: bearerFormat: JWT description: JWT token for authentication paths: - /k8s/capacity/cluster/list/raw: + /orchestrator/k8s/capacity/cluster/list/raw: get: summary: Get cluster list description: Returns a list of clusters with basic information diff --git a/specs/kubernetes/cluster-management.yaml b/specs/kubernetes/cluster-management.yaml index 2509b25bcf..8fe247aacf 100644 --- a/specs/kubernetes/cluster-management.yaml +++ b/specs/kubernetes/cluster-management.yaml @@ -25,7 +25,7 @@ components: description: JWT token for authentication paths: - /cluster: + /orchestrator/cluster: post: summary: Create a new cluster operationId: CreateCluster diff --git a/specs/security/api-tokens.yaml b/specs/security/api-tokens.yaml index 308cf2465c..c739ce64bd 100644 --- a/specs/security/api-tokens.yaml +++ b/specs/security/api-tokens.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: Devtron Labs paths: - /api-token: + /orchestrator/api-token: get: description: Get All active Api Tokens responses: diff --git a/specs/security/core.yaml b/specs/security/core.yaml index 0c12150aae..d60cc1f633 100644 --- a/specs/security/core.yaml +++ b/specs/security/core.yaml @@ -25,7 +25,7 @@ components: paths: # User Management APIs - /user/v2: + /orchestrator/user/v2: get: description: Get all users with optional filters operationId: GetAllUsers @@ -96,7 +96,7 @@ paths: schema: $ref: '#/components/schemas/ApiError' - /user: + /orchestrator/user: post: description: Create a new user operationId: CreateUser diff --git a/specs/security/security-dashboard-apis.yml b/specs/security/security-dashboard-apis.yml index acfd97db77..c83b3234d7 100644 --- a/specs/security/security-dashboard-apis.yml +++ b/specs/security/security-dashboard-apis.yml @@ -5,7 +5,7 @@ info: servers: - url: https://api.server.test/v1 paths: - /security/scan/executionDetail: + /orchestrator/security/scan/executionDetail: get: summary: fetch image scan execution result, by multiple ways for different use case description: params are option but at least one is required diff --git a/specs/swagger/openapi.yaml b/specs/swagger/openapi.yaml index 9928580eff..b611f714c1 100644 --- a/specs/swagger/openapi.yaml +++ b/specs/swagger/openapi.yaml @@ -84,7 +84,7 @@ tags: - name: GitOps Validation x-displayName: GitOps Validation paths: - /resource/history/deployment/cd-pipeline/v1: + /orchestrator/resource/history/deployment/cd-pipeline/v1: get: summary: Get Deployment History description: Retrieves the deployment history for a specific CD pipeline based @@ -1075,7 +1075,7 @@ paths: $ref: '#/components/schemas/ErrorResponse' tags: - Applications - /app/labels/list: + /orchestrator/app/labels/list: get: summary: List Application Labels description: "Retrieves a list of application labels. By default, returns all\ @@ -1231,7 +1231,7 @@ paths: message: type: string example: An unexpected error occurred - /batch/{apiVersion}/{kind}/readme: + /orchestrator/batch/{apiVersion}/{kind}/readme: get: summary: Get Readme for Bulk Update description: Returns Readme for bulk update for different resource in the url @@ -1271,7 +1271,7 @@ paths: $ref: '#/components/schemas/Error' tags: - bulk_other - /batch/v1beta1/application/dryrun: + /orchestrator/batch/v1beta1/application/dryrun: post: summary: Dry Run for Bulk Application Update description: Returns details(id, name, envId) of all apps to be impacted with @@ -1315,7 +1315,7 @@ paths: $ref: '#/components/schemas/Error' tags: - bulk_other - /batch/v1beta1/hibernate: + /orchestrator/batch/v1beta1/hibernate: post: summary: Bulk Hibernate Applications description: Bulk Hibernates applications @@ -1357,7 +1357,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /batch/v1beta1/unhibernate: + /orchestrator/batch/v1beta1/unhibernate: post: summary: Bulk Un-Hibernate Applications description: Bulk Un-Hibernates applications @@ -1399,7 +1399,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /batch/v1beta1/deploy: + /orchestrator/batch/v1beta1/deploy: post: summary: Bulk Deploy Applications description: Bulk Triggers deployment of applications @@ -1440,7 +1440,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /batch/v1beta1/build: + /orchestrator/batch/v1beta1/build: post: summary: Bulk Trigger Application Builds description: Bulk Triggers build of applications @@ -1481,7 +1481,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /batch/v1beta1/application: + /orchestrator/batch/v1beta1/application: post: summary: Bulk Edit Applications description: Bulk Updates (Edit) all impacted apps. This endpoint can be used @@ -1525,7 +1525,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /sso/create: + /orchestrator/sso/create: post: tags: - SSO Configuration @@ -1546,7 +1546,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /sso/update: + /orchestrator/sso/update: put: tags: - SSO Configuration @@ -1567,7 +1567,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /sso/list: + /orchestrator/sso/list: get: tags: - SSO Configuration @@ -1586,7 +1586,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /sso/{id}: + /orchestrator/sso/{id}: get: tags: - SSO Configuration @@ -1613,7 +1613,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /sso: + /orchestrator/sso: get: tags: - SSO Configuration @@ -1643,7 +1643,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /rbac/roles/default: + /orchestrator/rbac/roles/default: get: tags: - RBAC @@ -1666,7 +1666,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /api/v1/session: + /orchestrator/api/v1/session: post: tags: - Authentication @@ -1719,7 +1719,7 @@ paths: $ref: '#/components/schemas/ErrorResponse' security: [] - /refresh: + /orchestrator/refresh: get: tags: - Authentication @@ -1733,7 +1733,7 @@ paths: $ref: '#/components/responses/Unauthorized' security: [] - /admin/policy/default: + /orchestrator/admin/policy/default: post: tags: - Policy Management @@ -1775,7 +1775,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /devtron/auth/verify: + /orchestrator/devtron/auth/verify: get: tags: - Authentication @@ -1792,7 +1792,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /devtron/auth/verify/v2: + /orchestrator/devtron/auth/verify/v2: get: tags: - Authentication @@ -1816,7 +1816,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/v2: + /orchestrator/user/v2: get: tags: - User Management @@ -1889,7 +1889,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user: + /orchestrator/user: get: tags: - User Management @@ -1954,7 +1954,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/{id}: + /orchestrator/user/{id}: get: tags: - User Management @@ -2005,7 +2005,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/v2/{id}: + /orchestrator/user/v2/{id}: get: tags: - User Management @@ -2030,7 +2030,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/bulk: + /orchestrator/user/bulk: delete: tags: - User Management @@ -2049,7 +2049,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/detail/get: + /orchestrator/user/detail/get: get: tags: - User Management @@ -2072,7 +2072,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/role/group/v2: + /orchestrator/user/role/group/v2: get: tags: - Role Group Management @@ -2141,7 +2141,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/role/group: + /orchestrator/user/role/group: get: tags: - Role Group Management @@ -2202,7 +2202,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/role/group/{id}: + /orchestrator/user/role/group/{id}: get: tags: - Role Group Management @@ -2249,7 +2249,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/role/group/v2/{id}: + /orchestrator/user/role/group/v2/{id}: get: tags: - Role Group Management @@ -2272,7 +2272,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/role/group/detailed/get: + /orchestrator/user/role/group/detailed/get: get: tags: - Role Group Management @@ -2289,7 +2289,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/role/group/search: + /orchestrator/user/role/group/search: get: tags: - Role Group Management @@ -2317,7 +2317,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/role/group/bulk: + /orchestrator/user/role/group/bulk: delete: tags: - Role Group Management @@ -2336,7 +2336,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/check/roles: + /orchestrator/user/check/roles: get: tags: - Authentication @@ -2379,7 +2379,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/sync/orchestratortocasbin: + /orchestrator/user/sync/orchestratortocasbin: get: tags: - Policy Management @@ -2400,7 +2400,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/update/trigger/terminal: + /orchestrator/user/update/trigger/terminal: put: tags: - Policy Management @@ -2423,7 +2423,7 @@ paths: $ref: '#/components/responses/InternalServerError' security: [] - /user/role/cache: + /orchestrator/user/role/cache: get: tags: - Cache Management @@ -2441,7 +2441,7 @@ paths: $ref: '#/components/responses/Forbidden' security: [] - /user/role/cache/invalidate: + /orchestrator/user/role/cache/invalidate: get: tags: - Cache Management @@ -2459,7 +2459,7 @@ paths: $ref: '#/components/responses/Forbidden' security: [] - /login: + /orchestrator/login: get: tags: - Authentication @@ -2471,7 +2471,7 @@ paths: description: Redirect to OIDC provider. security: [] - /auth/login: + /orchestrator/auth/login: get: tags: - Authentication @@ -2483,7 +2483,7 @@ paths: description: Redirect to OIDC provider. security: [] - /auth/callback: + /orchestrator/auth/callback: get: tags: - Authentication @@ -2500,7 +2500,7 @@ paths: description: Server error during OIDC callback. security: [] - /api/dex/{path}: + /orchestrator/api/dex/{path}: get: tags: - Authentication @@ -2525,7 +2525,7 @@ paths: description: Response from Dex. security: [] - /env: + /orchestrator/env: post: summary: Create Environment description: Create a new environment within a cluster. @@ -2658,7 +2658,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /cluster/delete: + /orchestrator/cluster/delete: post: summary: Delete Cluster description: Delete an existing cluster. @@ -2703,7 +2703,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /env/delete: + /orchestrator/env/delete: post: summary: Delete Environment (via POST) description: Delete an existing environment using POST method. @@ -2748,7 +2748,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /env/clusters: + /orchestrator/env/clusters: get: summary: List clusters with their environments description: Provides a list of all clusters and the environments within each. @@ -2778,7 +2778,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /cluster/{cluster_id}/env: + /orchestrator/cluster/{cluster_id}/env: get: summary: List environments for a specific cluster description: Provides a list of all environments for a given cluster ID. @@ -2833,7 +2833,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /cluster: + /orchestrator/cluster: put: summary: Update Cluster description: Update an existing cluster's configuration. @@ -2920,7 +2920,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /cluster/auth-list: + /orchestrator/cluster/auth-list: get: summary: List Accessible Clusters description: list of clusters accessible to the authenticated user. @@ -2954,7 +2954,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /cluster/validate: + /orchestrator/cluster/validate: post: summary: Validate Cluster Configuration description: Validate a cluster configuration using kubeconfig. diff --git a/specs/workflow/workflow-stage-status.internal.yaml b/specs/workflow/workflow-stage-status.internal.yaml index 999e0af05a..f44dccedfb 100644 --- a/specs/workflow/workflow-stage-status.internal.yaml +++ b/specs/workflow/workflow-stage-status.internal.yaml @@ -3,7 +3,7 @@ info: title: Workflow Status API for showing execution stage version: 1.0.0 paths: - /workflow/status: #this is not real API, only for sharing purpose + /orchestrator/workflow/status: #this is not real API, only for sharing purpose get: summary: Get Workflow Status responses: diff --git a/wire_gen.go b/wire_gen.go index 1661261a59..08a1f2420e 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -471,7 +471,7 @@ func InitializeApp() (*App, error) { transactionUtilImpl := sql.NewTransactionUtilImpl(db) chartRepositoryImpl := chartRepoRepository.NewChartRepository(db, transactionUtilImpl) envConfigOverrideRepositoryImpl := chartConfig.NewEnvConfigOverrideRepository(db) - envConfigOverrideReadServiceImpl := read7.NewEnvConfigOverrideReadServiceImpl(envConfigOverrideRepositoryImpl, sugaredLogger) + envConfigOverrideReadServiceImpl := read7.NewEnvConfigOverrideReadServiceImpl(sugaredLogger, environmentRepositoryImpl, envConfigOverrideRepositoryImpl) chartRefRepositoryImpl := chartRepoRepository.NewChartRefRepositoryImpl(db) deploymentConfigReadServiceImpl := read8.NewDeploymentConfigReadServiceImpl(sugaredLogger, repositoryImpl, environmentVariables, chartRepositoryImpl, pipelineRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, envConfigOverrideReadServiceImpl) deploymentConfigServiceImpl := common.NewDeploymentConfigServiceImpl(repositoryImpl, sugaredLogger, chartRepositoryImpl, pipelineRepositoryImpl, appRepositoryImpl, installedAppReadServiceEAImpl, environmentVariables, envConfigOverrideReadServiceImpl, environmentRepositoryImpl, chartRefRepositoryImpl, deploymentConfigReadServiceImpl, acdAuthConfig) From 9c024fae6929ee59c0e25f4de092b63fca2d0f09 Mon Sep 17 00:00:00 2001 From: prakhar katiyar Date: Tue, 5 Aug 2025 04:17:39 +0530 Subject: [PATCH 6/9] naming changed from devtron-lab duplicated removed ap spec correction --- specs/app-store.yaml | 10 +- specs/application/labels.yaml | 2 +- specs/application/listing.yaml | 2 +- specs/common/api-spec.yaml | 2 +- specs/deployment/app-type-change.yaml | 2 +- specs/deployment/core.yaml | 2 +- specs/deployment/group.yaml | 2 +- specs/deployment/pipeline.yaml | 2 +- specs/environment/bulk-delete.yaml | 2 +- specs/environment/core.yaml | 2 +- specs/external-app/applist.yaml | 2 +- .../external-links/external-links-specs.yaml | 147 ++++++++ specs/gitops/core.yaml | 2 +- specs/helm/charts.yaml | 2 +- specs/helm/deployment-chart-type.yaml | 2 +- specs/helm/provider.yaml | 2 +- .../helmApp/deployment-history-api-spec.yaml | 2 +- specs/infrastructure/image-tagging.yaml | 130 ------- specs/jobs/batch.yaml | 2 +- specs/jobs/bulk-actions.yaml | 4 +- specs/jobs/core.yaml | 6 +- specs/kubernetes/apis.yaml | 2 +- specs/kubernetes/cluster.yaml | 2 +- specs/kubernetes/resources.yaml | 2 +- specs/notifications/core.yaml | 182 +++++++++- specs/notifications/webhooks.yaml | 2 +- .../api/apiToken_api-openapi.yaml | 2 +- specs/openapiClient/api/openapi.yaml | 2 +- specs/security/api-tokens.yaml | 2 +- specs/security/core.yaml | 2 +- specs/security/group-policy.yaml | 2 +- specs/security/policy.yaml | 342 ------------------ specs/security/security-dashboard-apis.yml | 2 +- specs/security/security-policy.yml | 4 +- specs/security/user-management.yaml | 2 +- specs/webhook/webhook_helm-api-spec.yaml | 2 +- 36 files changed, 353 insertions(+), 528 deletions(-) delete mode 100644 specs/infrastructure/image-tagging.yaml delete mode 100644 specs/security/policy.yaml diff --git a/specs/app-store.yaml b/specs/app-store.yaml index b330245a7b..a89f54f546 100644 --- a/specs/app-store.yaml +++ b/specs/app-store.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: App Store Management description: Devtron API for app store management termsOfService: https://devtron.ai/terms/ contact: @@ -86,7 +86,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /app-store/discover/application/{id}: + /orchestrator/app-store/discover/application/{id}: get: description: Get chart details for a specific version parameters: @@ -128,7 +128,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /app-store/discover/application/{appStoreId}/version/autocomplete: + /orchestrator/app-store/discover/application/{appStoreId}/version/autocomplete: get: description: Get chart versions for an app store application parameters: @@ -172,7 +172,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /app-store/discover/application/chartInfo/{appStoreApplicationVersionId}: + /orchestrator/app-store/discover/application/chartInfo/{appStoreApplicationVersionId}: get: description: Get chart information for a specific version parameters: @@ -214,7 +214,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /app-store/discover/search: + /orchestrator/app-store/discover/search: get: description: Search app store charts by name parameters: diff --git a/specs/application/labels.yaml b/specs/application/labels.yaml index 393fbca68a..55bf0a391f 100644 --- a/specs/application/labels.yaml +++ b/specs/application/labels.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Application Labels Management paths: /orchestrator/app/labels/list: get: diff --git a/specs/application/listing.yaml b/specs/application/listing.yaml index 07f4b38249..0c6ca1061f 100644 --- a/specs/application/listing.yaml +++ b/specs/application/listing.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Application Listing & Discovery paths: /orchestrator/app/autocomplete: get: diff --git a/specs/common/api-spec.yaml b/specs/common/api-spec.yaml index 229b4efe6f..6b5b1c8e83 100644 --- a/specs/common/api-spec.yaml +++ b/specs/common/api-spec.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: version: 1.0.0 - title: Devtron Labs + title: Common API Utilities paths: /orchestrator/application/rollback: put: diff --git a/specs/deployment/app-type-change.yaml b/specs/deployment/app-type-change.yaml index c980a395ca..a482e3c1e1 100644 --- a/specs/deployment/app-type-change.yaml +++ b/specs/deployment/app-type-change.yaml @@ -1,7 +1,7 @@ openapi: 3.0.3 info: version: 1.0.0 - title: Devtron Labs + title: Application Type Change API paths: /orchestrator/app/cd-pipeline/patch/deployment: post: diff --git a/specs/deployment/core.yaml b/specs/deployment/core.yaml index 1117ee1161..b0cac22c5f 100644 --- a/specs/deployment/core.yaml +++ b/specs/deployment/core.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Deployment Template Management description: Devtron API for deployment template management termsOfService: https://devtron.ai/terms/ contact: diff --git a/specs/deployment/group.yaml b/specs/deployment/group.yaml index 7e0767364a..250e370f10 100644 --- a/specs/deployment/group.yaml +++ b/specs/deployment/group.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Deployment Group Management description: Devtron API for deployment group management termsOfService: https://devtron.ai/terms/ contact: diff --git a/specs/deployment/pipeline.yaml b/specs/deployment/pipeline.yaml index 5d851bf190..7b6a8940bf 100644 --- a/specs/deployment/pipeline.yaml +++ b/specs/deployment/pipeline.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Deployment Pipeline Management description: Devtron API for deployment pipeline management termsOfService: https://devtron.ai/terms/ contact: diff --git a/specs/environment/bulk-delete.yaml b/specs/environment/bulk-delete.yaml index c561c866b6..22cfedd7d3 100644 --- a/specs/environment/bulk-delete.yaml +++ b/specs/environment/bulk-delete.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Environment Bulk Operations paths: /orchestrtor/batch/v1beta1/cd-pipeline: post: diff --git a/specs/environment/core.yaml b/specs/environment/core.yaml index dce28062e0..fb8808b691 100644 --- a/specs/environment/core.yaml +++ b/specs/environment/core.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Environment & Namespace Management paths: /orchestrator/env/namespace/autocomplete: get: diff --git a/specs/external-app/applist.yaml b/specs/external-app/applist.yaml index 628b19914b..72a169d40d 100644 --- a/specs/external-app/applist.yaml +++ b/specs/external-app/applist.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: version: 1.0.0 - title: Devtron Labs + title: External Application Management paths: /orchestrator/application: post: diff --git a/specs/external-links/external-links-specs.yaml b/specs/external-links/external-links-specs.yaml index 0c94374a43..d66d106a38 100644 --- a/specs/external-links/external-links-specs.yaml +++ b/specs/external-links/external-links-specs.yaml @@ -15,6 +15,18 @@ paths: type: array items: $ref: "#/components/schemas/ExternalLinkMonitoringTool" + "401": + description: Unauthorized user + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" /orchestrator/external-links: get: description: Get All active External links (If query parameter is not supplied @@ -54,6 +66,30 @@ paths: type: array items: $ref: "#/components/schemas/ExternalLink" + "400": + description: Bad request - invalid parameters + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "401": + description: Unauthorized user + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "403": + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" post: description: Create external links (id should be zero in externalLink object) requestBody: @@ -71,6 +107,30 @@ paths: application/json: schema: $ref: "#/components/schemas/ActionResponse" + "400": + description: Bad request - invalid input data + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "401": + description: Unauthorized user + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "403": + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" put: description: update external link requestBody: @@ -86,6 +146,36 @@ paths: application/json: schema: $ref: "#/components/schemas/ActionResponse" + "400": + description: Bad request - invalid input data + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "401": + description: Unauthorized user + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "403": + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "404": + description: External link not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" delete: description: delete external link parameters: @@ -104,6 +194,36 @@ paths: application/json: schema: $ref: "#/components/schemas/ActionResponse" + "400": + description: Bad request - invalid ID parameter + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "401": + description: Unauthorized user + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "403": + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "404": + description: External link not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" # Components @@ -184,3 +304,30 @@ components: clusterId: type: integer description: cluster-id for which you want to configure the app level external-link + ErrorResponse: + type: object + properties: + code: + type: integer + description: Error code + example: 400 + status: + type: string + description: Error status + example: "Bad Request" + message: + type: string + description: Error message + example: "Invalid request parameters" + errors: + type: array + description: Detailed error information + items: + type: object + properties: + field: + type: string + description: Field name that caused the error + message: + type: string + description: Specific error message for the field diff --git a/specs/gitops/core.yaml b/specs/gitops/core.yaml index 1b0178f009..d4dfd942f0 100644 --- a/specs/gitops/core.yaml +++ b/specs/gitops/core.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: GitOps Configuration Management description: Devtron API for GitOps management termsOfService: https://devtron.ai/terms/ contact: diff --git a/specs/helm/charts.yaml b/specs/helm/charts.yaml index 924c05b183..e05cacf410 100644 --- a/specs/helm/charts.yaml +++ b/specs/helm/charts.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Helm Chart Store Management paths: /orchestrator/app-store/installed-app: get: diff --git a/specs/helm/deployment-chart-type.yaml b/specs/helm/deployment-chart-type.yaml index 3ae2aadb21..1872692ade 100644 --- a/specs/helm/deployment-chart-type.yaml +++ b/specs/helm/deployment-chart-type.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Helm Deployment Chart Types paths: /orchestrator/app/env/patch: patch: diff --git a/specs/helm/provider.yaml b/specs/helm/provider.yaml index c1cb646063..738b980585 100644 --- a/specs/helm/provider.yaml +++ b/specs/helm/provider.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Helm Chart Provider Management description: Devtron API for chart provider management including chart repositories, chart groups, and chart provider configuration termsOfService: https://devtron.ai/terms/ contact: diff --git a/specs/helmApp/deployment-history-api-spec.yaml b/specs/helmApp/deployment-history-api-spec.yaml index 2686dd7ea4..2160b67951 100644 --- a/specs/helmApp/deployment-history-api-spec.yaml +++ b/specs/helmApp/deployment-history-api-spec.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: version: 1.0.0 - title: Devtron Labs + title: Helm App Deployment History paths: /orchestrator/application/deployment-history: get: diff --git a/specs/infrastructure/image-tagging.yaml b/specs/infrastructure/image-tagging.yaml deleted file mode 100644 index a53a834634..0000000000 --- a/specs/infrastructure/image-tagging.yaml +++ /dev/null @@ -1,130 +0,0 @@ -openapi: "3.0.0" -info: - title: image-tags - version: "1.0" -paths: - /orchestrator/apps/image-tags/{artifact-id}: - post: - description: Create tags and comment for a particular image in a app - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/ImageTaggingRequestDTO" - responses: - "200": - description: success on tags and comment creation for the given artifact. - content: - application/json: - schema: - $ref: "#/components/schemas/ImageTaggingResponseDTO" - "500": - description: will get this response if any failure occurs at server side. - "400": - description: will get this response if invalid payload is sent in the request. - "403": - description: will get this response if user doesn't have build and deploy permission for the app - get: - description: will get all the tags and comment added for the provided artifact-id - responses: - "200": - description: on succesfull fetching of all the tags and comment for the requested artifact. - content: - application/json: - schema: - $ref: "#/components/schemas/ImageTaggingResponseDTO" - "500": - description: will get this response if any failure occurs at server side. - "403": - description: will get this if user doesn't have access to the app that the requested artifact belongs. - - -#components -components: - schemas: - ImageTaggingResponseDTO: - type: object - properties: - prodEnvExists: - type: boolean - description: true/false - imageReleaseTags: - type: array - items: - $ref: '#/components/schemas/ReleaseTag' - imageComments: - type: array - items: - $ref: '#/components/schemas/ImageComment' - appReleaseTags: - type: array - items: - type: string - description: List of unique tag names in the app - hideImageTaggingHardDelete: - type: boolean - description: Whether hard delete of tags is hidden - - - - ImageComment: - type: object - properties: - id: - type: integer - description: id of the image comment - comment: - type: string - description: image comments - example: 'this image is build for arm64 platform only' - artifactId: - type: integer - description: id of the artifact to which this comment is added - - - ReleaseTag: - type: object - properties: - id: - type: integer - description: id of the tag - tagName: - type: string - description: tag name - example: "v1.1" - appId: - type: integer - description: id of the app in which this tag is created - artifactId: - type: integer - description: id of the artifact to which this tag is tagged - softDeleted: - type: boolean - description: tag is deleted or not - - - ImageTaggingRequestDTO: - type: object - properties: - createTags: - type: array - items: - $ref: '#/components/schemas/ReleaseTag' - description: tag objects requested for creation - softDeleteTags: - type: array - items: - $ref: '#/components/schemas/ReleaseTag' - description: tag objects requested for soft deletion - hardDeleteTags: - type: array - items: - $ref: '#/components/schemas/ReleaseTag' - description: tag objects requested for hard deletion - imageComment: - type: object - $ref: '#/components/schemas/ImageComment' - description: image comment data - - diff --git a/specs/jobs/batch.yaml b/specs/jobs/batch.yaml index bb544d9964..c7ca496826 100644 --- a/specs/jobs/batch.yaml +++ b/specs/jobs/batch.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Batch Job Operations description: Devtron API for batch and bulk operations termsOfService: https://devtron.ai/terms/ contact: diff --git a/specs/jobs/bulk-actions.yaml b/specs/jobs/bulk-actions.yaml index d317757bba..2f158864bc 100644 --- a/specs/jobs/bulk-actions.yaml +++ b/specs/jobs/bulk-actions.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Job Bulk Actions description: Devtron API for bulk actions - Hibernate, UnHibernate, Deploy Latest Builds termsOfService: https://devtron.ai/terms/ contact: @@ -14,7 +14,7 @@ info: servers: - url: http://localhost:8080/orchestrator/batch paths: - /orchestrator/v1beta1/hibernate: + /orchestrator/batch/v1beta1/hibernate: post: description: Bulk Hibernate all apps for specific environment operationId: BulkHibernate diff --git a/specs/jobs/core.yaml b/specs/jobs/core.yaml index 68ff161ace..16d6beea8a 100644 --- a/specs/jobs/core.yaml +++ b/specs/jobs/core.yaml @@ -1,6 +1,6 @@ openapi: "3.0.0" info: - title: Devtron Labs + title: Job Pipeline Management description: Devtron API for job management version: "1.0" termsOfService: https://devtron.ai/terms/ @@ -38,7 +38,7 @@ paths: description: status result: $ref: "#/components/schemas/ActionResponse" - /job/list: + /orchestrator/job/list: post: description: Get the list of all the jobs by applying filter requestBody: @@ -62,7 +62,7 @@ paths: description: status result: $ref: "#/components/schemas/JobListResponse" - /job/ci-pipeline/list/{jobId}: + /orchestrator/job/ci-pipeline/list/{jobId}: get: description: fetch details of job ci-pipelines for the overview page parameters: diff --git a/specs/kubernetes/apis.yaml b/specs/kubernetes/apis.yaml index 671aa8d9c2..de09a13baa 100644 --- a/specs/kubernetes/apis.yaml +++ b/specs/kubernetes/apis.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: version: 1.0.0 - title: Devtron Labs + title: Kubernetes Resource Management description: API for managing Kubernetes resources and operations termsOfService: https://devtron.ai/terms/ contact: diff --git a/specs/kubernetes/cluster.yaml b/specs/kubernetes/cluster.yaml index 63f0e2a45c..3cec785fd8 100644 --- a/specs/kubernetes/cluster.yaml +++ b/specs/kubernetes/cluster.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Kubernetes Cluster Management description: Devtron API for cluster management termsOfService: https://devtron.ai/terms/ contact: diff --git a/specs/kubernetes/resources.yaml b/specs/kubernetes/resources.yaml index a1c7a9ea12..2548834079 100644 --- a/specs/kubernetes/resources.yaml +++ b/specs/kubernetes/resources.yaml @@ -1,6 +1,6 @@ openapi: "3.0.2" info: - title: Devtron Labs + title: Kubernetes Resource Operations description: Devtron API for Kubernetes resource management version: "1.0" termsOfService: https://devtron.ai/terms/ diff --git a/specs/notifications/core.yaml b/specs/notifications/core.yaml index c58fc70530..dd456d4b54 100644 --- a/specs/notifications/core.yaml +++ b/specs/notifications/core.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Notification Management description: Devtron API for notification management termsOfService: https://devtron.ai/terms/ contact: @@ -39,8 +39,32 @@ paths: application/json: schema: $ref: '#/components/schemas/NotificationSetting' - default: - description: unexpected error + '400': + description: Bad request - invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Notification settings not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: @@ -63,8 +87,26 @@ paths: application/json: schema: $ref: '#/components/schemas/NotificationSetting' - default: - description: unexpected error + '400': + description: Bad request - invalid input data + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: @@ -87,8 +129,32 @@ paths: application/json: schema: $ref: '#/components/schemas/NotificationSetting' - default: - description: unexpected error + '400': + description: Bad request - invalid input data + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Notification setting not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: @@ -111,8 +177,32 @@ paths: application/json: schema: $ref: '#/components/schemas/NotificationSetting' - default: - description: unexpected error + '400': + description: Bad request - invalid input data + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Notification setting not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: @@ -131,10 +221,40 @@ paths: schema: type: string responses: - '204': + '200': description: list of recipients - default: - description: unexpected error + content: + application/json: + schema: + type: array + items: + type: string + '400': + description: Bad request - invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Recipients not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: @@ -152,8 +272,20 @@ paths: application/json: schema: $ref: '#/components/schemas/NotificationConfigResponse' - default: - description: unexpected error + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: @@ -176,8 +308,26 @@ paths: application/json: schema: $ref: '#/components/schemas/NotificationConfigResponse' - default: - description: unexpected error + '400': + description: Bad request - invalid input data + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: diff --git a/specs/notifications/webhooks.yaml b/specs/notifications/webhooks.yaml index f87dd816c9..3746ad58ed 100644 --- a/specs/notifications/webhooks.yaml +++ b/specs/notifications/webhooks.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Webhook Notification Management description: Devtron API for webhook management including Git webhooks, CI/CD webhooks, and notification webhooks termsOfService: https://devtron.ai/terms/ contact: diff --git a/specs/openapiClient/api/apiToken_api-openapi.yaml b/specs/openapiClient/api/apiToken_api-openapi.yaml index a0e16d4f7b..4a3e8f3973 100644 --- a/specs/openapiClient/api/apiToken_api-openapi.yaml +++ b/specs/openapiClient/api/apiToken_api-openapi.yaml @@ -1,6 +1,6 @@ openapi: 3.0.3 info: - title: Devtron Labs + title: API Token Client Management version: 1.0.0 servers: - url: / diff --git a/specs/openapiClient/api/openapi.yaml b/specs/openapiClient/api/openapi.yaml index 5b9aba4704..78ad8d984b 100644 --- a/specs/openapiClient/api/openapi.yaml +++ b/specs/openapiClient/api/openapi.yaml @@ -1,6 +1,6 @@ openapi: 3.0.3 info: - title: Devtron Labs + title: OpenAPI Client Management version: 1.0.0 servers: - url: / diff --git a/specs/security/api-tokens.yaml b/specs/security/api-tokens.yaml index c739ce64bd..a52a18c865 100644 --- a/specs/security/api-tokens.yaml +++ b/specs/security/api-tokens.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: version: 1.0.0 - title: Devtron Labs + title: API Token Management paths: /orchestrator/api-token: get: diff --git a/specs/security/core.yaml b/specs/security/core.yaml index d60cc1f633..523c869640 100644 --- a/specs/security/core.yaml +++ b/specs/security/core.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: Security & Access Management API description: Devtron API for security management including user management, role groups, cluster access policies, and API token management termsOfService: https://devtron.ai/terms/ contact: diff --git a/specs/security/group-policy.yaml b/specs/security/group-policy.yaml index 9d64df518f..d745006cb1 100644 --- a/specs/security/group-policy.yaml +++ b/specs/security/group-policy.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron + title: User Role Group Management API paths: /orchestrator/user/role/group/v2: get: diff --git a/specs/security/policy.yaml b/specs/security/policy.yaml deleted file mode 100644 index fb325cb3d7..0000000000 --- a/specs/security/policy.yaml +++ /dev/null @@ -1,342 +0,0 @@ -openapi: "3.0.0" -info: - version: 1.0.0 - title: Devtron -servers: - - url: http://petstore.swagger.io/api -paths: - /orchestrator/user/v2: - get: - summary: Returns all users - description: Returns a paginated list of users with optional filtering and sorting - operationId: GetAllV2 - parameters: - - name: searchKey - in: query - description: Search key for filtering users - required: false - schema: - type: string - - - name: sortOrder - in: query - description: Sorting order (ASC or DESC) - required: false - schema: - type: string - enum: - - ASC - - DESC - - - name: sortBy - in: query - description: Field to sort by (email_id or last_login) - required: false - schema: - type: string - enum: - - email_id - - last_login - - - name: offset - in: query - description: Offset for pagination - required: false - schema: - type: integer - - - name: size - in: query - description: Number of records per page - required: false - schema: - type: integer - - - name: showAll - in: query - description: Whether to show all users or only active ones - required: false - schema: - type: boolean - - responses: - '200': - description: List of users - content: - application/json: - schema: - $ref: '#/components/schemas/UserListingResponse' - '401': - description: Unauthorized - '403': - description: Forbidden - '500': - description: Internal server error - - /orchestrator/user: - get: - summary: Returns all users (deprecated) - description: Returns all users (deprecated, use /user/v2 instead) - operationId: findAllUsers - deprecated: true - responses: - '200': - description: List of users - content: - application/json: - schema: - $ref: '#/components/schemas/AllUsers' - '401': - description: Unauthorized - '500': - description: Internal server error - - post: - summary: Creates a new user - description: Creates a new user with specified roles and permissions - operationId: addUser - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/User' - responses: - '200': - description: Created user - content: - application/json: - schema: - $ref: '#/components/schemas/User' - '400': - description: Bad request - '401': - description: Unauthorized - '403': - description: Forbidden - '406': - description: Not acceptable - incompatible request format - '500': - description: Internal server error - - put: - summary: Updates a user - description: Updates an existing user's roles and permissions - operationId: updateUser - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/User' - responses: - '200': - description: Updated user - content: - application/json: - schema: - $ref: '#/components/schemas/User' - '400': - description: Bad request - '401': - description: Unauthorized - '403': - description: Forbidden - '406': - description: Not acceptable - incompatible request format - '500': - description: Internal server error - - /orchestrator/user/{id}: - get: - summary: Get user by ID - description: Returns user details with role filters - operationId: findUserById - parameters: - - name: id - in: path - description: ID of the user - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: User details - content: - application/json: - schema: - $ref: '#/components/schemas/User' - '400': - description: Bad request - '401': - description: Unauthorized - '500': - description: Internal server error - - /orchestrator/user/bulk: - delete: - summary: Delete multiple users - description: Deletes multiple users in bulk - operationId: bulkDeleteUsers - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkDeleteRequest' - responses: - '200': - description: Successfully deleted users - content: - application/json: - schema: - type: boolean - '400': - description: Bad request - validation error or invalid request format - '401': - description: Unauthorized - '403': - description: Forbidden - insufficient permissions - '500': - description: Internal server error - -components: - schemas: - User: - type: object - required: - - email_id - properties: - id: - type: integer - description: Unique ID of the user - email_id: - type: string - description: Email ID of the user - userRoleGroups: - type: array - items: - $ref: '#/components/schemas/UserRoleGroupItem' - roleFilters: - type: array - items: - $ref: '#/components/schemas/roleFilter' - description: Role filters for the user - superAdmin: - type: boolean - description: Whether the user is a super admin - userId: - type: integer - description: ID of the user making the request - - UserListingResponse: - type: object - properties: - users: - type: array - items: - $ref: '#/components/schemas/AllUsersV2' - description: List of users - totalCount: - type: integer - description: Total number of users - - AllUsersV2: - type: object - properties: - id: - type: integer - description: User ID - email_id: - type: string - description: Email ID - last_login: - type: string - format: date-time - description: Last login timestamp - roleFilters: - type: array - items: - $ref: '#/components/schemas/roleFilter' - description: Role filters - - UserRoleGroupItem: - type: object - properties: - id: - type: integer - description: Role group ID - name: - type: string - description: Role group name - - roleFilter: - type: object - properties: - entity: - type: string - description: Entity type - team: - type: string - description: Team name - environment: - type: string - description: Environment name - action: - type: string - description: Action type - - BulkDeleteRequest: - type: object - required: - - ids - properties: - ids: - type: array - items: - type: integer - description: List of user IDs to delete - - AllUsers: - type: object - required: - - email_id - properties: - id: - type: integer - description: Unique id of user - email_id: - type: string - description: Unique valid email-id of user, comma separated emails ids for multiple users - groups: - type: array - items: - type: string - roleFilters: - type: array - items: - $ref: '#/components/schemas/emptyRoleFilter' - description: role filters objects - lastLogin: - type: string - format: date-time - description: user last login time - - emptyRoleFilter: - type: object - required: - - action - - Error: - required: - - code - - message - properties: - code: - type: integer - format: int32 - description: Error code - message: - type: string - description: Error message \ No newline at end of file diff --git a/specs/security/security-dashboard-apis.yml b/specs/security/security-dashboard-apis.yml index c83b3234d7..e7bfa7ba88 100644 --- a/specs/security/security-dashboard-apis.yml +++ b/specs/security/security-dashboard-apis.yml @@ -1,6 +1,6 @@ openapi: '3.0.2' info: - title: API Title + title: Security Scan API version: '1.0' servers: - url: https://api.server.test/v1 diff --git a/specs/security/security-policy.yml b/specs/security/security-policy.yml index 18c3b716ec..30606e0b6e 100644 --- a/specs/security/security-policy.yml +++ b/specs/security/security-policy.yml @@ -1,11 +1,11 @@ openapi: '3.0.2' info: - title: API Title + title: Security Policy Management version: '1.0' servers: - url: http://localhost:3000/orchestrator paths: - /security/cve/control/list: + /orchestrator/security/cve/control/list: get: description: Fetch current security policy for global, cluster, environment and application level. operationId: FetchPolicy diff --git a/specs/security/user-management.yaml b/specs/security/user-management.yaml index 61d470b881..1a41245fd4 100644 --- a/specs/security/user-management.yaml +++ b/specs/security/user-management.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: version: 1.0.0 - title: Devtron Labs + title: User Management API description: Devtron API for user management termsOfService: https://devtron.ai/terms/ contact: diff --git a/specs/webhook/webhook_helm-api-spec.yaml b/specs/webhook/webhook_helm-api-spec.yaml index 1a6194c169..5fd514823b 100644 --- a/specs/webhook/webhook_helm-api-spec.yaml +++ b/specs/webhook/webhook_helm-api-spec.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: version: 1.0.0 - title: Devtron Labs + title: Helm Webhook Management paths: /orchestrator/webhook/helm/app: post: From f79c59d1fdf6092bb83fe6715b3e6c16da64db35 Mon Sep 17 00:00:00 2001 From: prakhar katiyar Date: Tue, 5 Aug 2025 16:52:44 +0530 Subject: [PATCH 7/9] specs fixes --- specs/gitops/validation.yaml | 9 ++++----- specs/helm/provider.yaml | 11 ++++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/specs/gitops/validation.yaml b/specs/gitops/validation.yaml index 6c9bf6d2b9..b9f50b6f0b 100644 --- a/specs/gitops/validation.yaml +++ b/specs/gitops/validation.yaml @@ -47,7 +47,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /config: + /orchestrator/gitops/config: post: description: Create a new GitOps configuration operationId: CreateGitOpsConfig @@ -130,7 +130,6 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /gitops/config: get: description: Get all GitOps configurations operationId: GetAllGitOpsConfig @@ -161,7 +160,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /gitops/config/{id}: + /orchestrator/gitops/config/{id}: get: description: Get GitOps configuration by ID operationId: GetGitOpsConfigById @@ -203,7 +202,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /gitops/config-by-provider: + /orchestrator/gitops/config-by-provider: get: description: Get GitOps configuration by provider operationId: GetGitOpsConfigByProvider @@ -245,7 +244,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /gitops/configured: + /orchestrator/gitops/configured: get: description: Check if GitOps is configured operationId: GitOpsConfigured diff --git a/specs/helm/provider.yaml b/specs/helm/provider.yaml index 738b980585..3e1f24e736 100644 --- a/specs/helm/provider.yaml +++ b/specs/helm/provider.yaml @@ -217,7 +217,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /orchestrator/chart-repo: + /orchestrator/chart-repo/create: post: description: Create a new chart repository operationId: CreateChartRepo @@ -258,7 +258,8 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - put: + /orchestrator/chart-repo/update: + post: description: Update an existing chart repository operationId: UpdateChartRepo requestBody: @@ -345,7 +346,7 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - /orchestrator/chart-repo/sync: + /orchestrator/chart-repo/sync-charts: post: description: Trigger manual chart repository sync operationId: TriggerChartSyncManual @@ -380,7 +381,7 @@ paths: $ref: '#/components/schemas/ErrorResponse' # Chart Group APIs - /orchestrator/chart-group: + /orchestrator/chart-group/: post: description: Create a new chart group operationId: CreateChartGroup @@ -463,7 +464,7 @@ paths: $ref: '#/components/schemas/ErrorResponse' /orchestrator/chart-group/entries: - post: + put: description: Save chart group entries operationId: SaveChartGroupEntries requestBody: From f936d8e75c0d29ef7883f6c626fce7a28838ce0b Mon Sep 17 00:00:00 2001 From: prakhar katiyar Date: Tue, 5 Aug 2025 16:52:44 +0530 Subject: [PATCH 8/9] api-spec fix api-spec fix api-spec fix api-spec fix API Error wrapper API Error wrapper specs fixes --- api/apiToken/ApiTokenRestHandler.go | 10 +- api/appStore/InstalledAppRestHandler.go | 12 +- .../chartGroup/ChartGroupRestHandler.go | 33 +- .../AppStoreDeploymentRestHandler.go | 14 +- .../deployment/CommonDeploymentRestHandler.go | 6 +- .../values/AppStoreValuesRestHandler.go | 12 +- api/auth/sso/SsoLoginHandler.go | 8 +- api/auth/user/RbacRoleRestHandler.go | 2 +- api/auth/user/UserRestHandler.go | 81 +- api/chartRepo/ChartRepositoryRestHandler.go | 27 +- api/cluster/ClusterRestHandler.go | 38 +- api/cluster/EnvironmentRestHandler.go | 28 +- api/externalLink/ExternalLinkRestHandler.go | 13 +- api/helm-app/HelmAppRestHandler.go | 12 +- api/infraConfig/restHandler.go | 8 +- .../application/k8sApplicationRestHandler.go | 14 +- api/k8s/capacity/k8sCapacityRestHandler.go | 20 +- api/middleware/ErrorHandlingMiddleware.go | 202 + api/module/ModuleRestHandler.go | 8 +- api/resourceScan/resourceScanRestHandler.go | 2 +- api/restHandler/AttributesRestHandlder.go | 12 +- api/restHandler/BatchOperationRestHandler.go | 2 +- api/restHandler/BulkUpdateRestHandler.go | 10 +- api/restHandler/CommonRestHanlder.go | 4 +- api/restHandler/ConfigMapRestHandler.go | 40 +- api/restHandler/CoreAppRestHandler.go | 8 +- api/restHandler/DeploymentGroupRestHandler.go | 14 +- api/restHandler/DockerRegRestHandler.go | 28 +- api/restHandler/GitHostRestHandler.go | 12 +- api/restHandler/GitOpsConfigRestHandler.go | 14 +- api/restHandler/GitProviderRestHandler.go | 16 +- api/restHandler/GlobalCMCSRestHandler.go | 10 +- api/restHandler/GlobalPluginRestHandler.go | 8 +- api/restHandler/ImageScanRestHandler.go | 6 +- api/restHandler/NotificationRestHandler.go | 55 +- api/restHandler/PProfRestHandler.go | 22 +- api/restHandler/PolicyRestHandler.go | 6 +- api/restHandler/ReleaseMetricsRestHandler.go | 2 +- api/restHandler/ResourceGroupRestHandler.go | 8 +- api/restHandler/TelemetryRestHandler.go | 2 +- api/restHandler/UserAttributesRestHandler.go | 4 +- api/restHandler/WebhookEventHandler.go | 16 +- .../app/appInfo/AppInfoRestHandler.go | 21 +- .../app/appList/AppFilteringRestHandler.go | 2 +- .../app/appList/AppListingRestHandler.go | 12 +- .../DeploymentConfigurationRestHandler.go | 8 +- .../app/pipeline/AutoCompleteRestHandler.go | 8 +- .../configure/BuildPipelineRestHandler.go | 44 +- .../BuildPipelineRestHandlerHelper.go | 16 +- .../DeploymentPipelineRestHandler.go | 60 +- .../configure/PipelineConfigRestHandler.go | 14 +- .../history/PipelineHistoryRestHandler.go | 10 +- .../PipelineStatusTimelineRestHandler.go | 2 +- .../trigger/PipelineTriggerRestHandler.go | 12 +- .../webhook/WebhookDataRestHandler.go | 4 +- .../app/workflow/AppWorkflowRestHandler.go | 4 +- .../common/EnhancedErrorResponse.go | 228 + api/restHandler/common/ParamParserUtils.go | 36 + .../common/ResourceContextExtractor.go | 114 + api/restHandler/common/apiError.go | 16 +- .../ScopedVariableRestHandler.go | 4 +- api/server/ServerRestHandler.go | 4 +- api/team/TeamRestHandler.go | 25 +- api/terminal/UserTerminalAccessRestHandler.go | 22 +- api/userResource/UserResourceRestHandler.go | 2 +- internal/constants/InternalErrorCode.go | 15 + internal/util/ResourceErrorFactory.go | 91 + specs/application/labels.yaml | 437 +- specs/ci-pipeline/ci-pipeline-build-spec.yaml | 2 +- specs/common/schemas.yaml | 572 ++ specs/deployment/rollback.yaml | 42 - specs/environment/bulk-delete.yaml | 2 +- specs/helm/charts.yaml | 214 +- specs/jobs/core.yaml | 228 +- specs/kubernetes/access-policy.yaml | 288 - specs/kubernetes/resources.yaml | 18 +- specs/notifications/core.yaml | 1252 +++- specs/notifications/webhooks.yaml | 122 +- specs/plugins/config-maps.yaml | 18 +- specs/swagger/openapi.html | 1547 ---- specs/swagger/openapi.yaml | 6524 ----------------- .../reports/live-server-validation-report.md | 2057 ++++++ 82 files changed, 5420 insertions(+), 9526 deletions(-) create mode 100644 api/middleware/ErrorHandlingMiddleware.go create mode 100644 api/restHandler/common/EnhancedErrorResponse.go create mode 100644 api/restHandler/common/ResourceContextExtractor.go create mode 100644 internal/util/ResourceErrorFactory.go create mode 100644 specs/common/schemas.yaml delete mode 100644 specs/kubernetes/access-policy.yaml delete mode 100644 specs/swagger/openapi.html delete mode 100644 specs/swagger/openapi.yaml create mode 100644 tests/api-spec-validation/reports/live-server-validation-report.md diff --git a/api/apiToken/ApiTokenRestHandler.go b/api/apiToken/ApiTokenRestHandler.go index 0ff8901f1a..1663493b6c 100644 --- a/api/apiToken/ApiTokenRestHandler.go +++ b/api/apiToken/ApiTokenRestHandler.go @@ -62,7 +62,7 @@ func NewApiTokenRestHandlerImpl(logger *zap.SugaredLogger, apiTokenService apiTo func (impl ApiTokenRestHandlerImpl) GetAllApiTokens(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -86,7 +86,7 @@ func (impl ApiTokenRestHandlerImpl) GetAllApiTokens(w http.ResponseWriter, r *ht func (impl ApiTokenRestHandlerImpl) CreateApiToken(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -132,7 +132,7 @@ func (impl ApiTokenRestHandlerImpl) CreateApiToken(w http.ResponseWriter, r *htt func (impl ApiTokenRestHandlerImpl) UpdateApiToken(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -182,7 +182,7 @@ func (impl ApiTokenRestHandlerImpl) UpdateApiToken(w http.ResponseWriter, r *htt func (impl ApiTokenRestHandlerImpl) DeleteApiToken(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -221,7 +221,7 @@ func (handler ApiTokenRestHandlerImpl) checkManagerAuth(resource, token, object func (impl ApiTokenRestHandlerImpl) GetAllApiTokensForWebhook(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/appStore/InstalledAppRestHandler.go b/api/appStore/InstalledAppRestHandler.go index 3c39da689e..73a8620117 100644 --- a/api/appStore/InstalledAppRestHandler.go +++ b/api/appStore/InstalledAppRestHandler.go @@ -177,7 +177,7 @@ func (handler *InstalledAppRestHandlerImpl) FetchAppOverview(w http.ResponseWrit func (handler InstalledAppRestHandlerImpl) GetAllInstalledApp(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } v := r.URL.Query() @@ -343,7 +343,7 @@ func (handler InstalledAppRestHandlerImpl) GetAllInstalledApp(w http.ResponseWri func (handler *InstalledAppRestHandlerImpl) DeployBulk(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -512,7 +512,7 @@ func (handler *InstalledAppRestHandlerImpl) getChartGroupInstallMetadata(req *ch func (handler *InstalledAppRestHandlerImpl) CheckAppExists(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -538,7 +538,7 @@ func (impl *InstalledAppRestHandlerImpl) DefaultComponentInstallation(w http.Res userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { impl.Logger.Errorw("service err, DefaultComponentInstallation", "error", err, "userId", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -885,7 +885,7 @@ func (handler *InstalledAppRestHandlerImpl) fetchResourceTreeWithHibernateForACD func (handler *InstalledAppRestHandlerImpl) MigrateDeploymentTypeForChartStore(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -929,7 +929,7 @@ func (handler *InstalledAppRestHandlerImpl) MigrateDeploymentTypeForChartStore(w func (handler *InstalledAppRestHandlerImpl) TriggerChartStoreAppAfterMigration(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/appStore/chartGroup/ChartGroupRestHandler.go b/api/appStore/chartGroup/ChartGroupRestHandler.go index 199ce00bec..d8c35a16e6 100644 --- a/api/appStore/chartGroup/ChartGroupRestHandler.go +++ b/api/appStore/chartGroup/ChartGroupRestHandler.go @@ -26,7 +26,6 @@ import ( "github.com/devtron-labs/devtron/pkg/appStore/chartGroup" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/auth/user" - "github.com/gorilla/mux" "go.uber.org/zap" "gopkg.in/go-playground/validator.v9" ) @@ -67,7 +66,7 @@ type ChartGroupRestHandler interface { func (impl *ChartGroupRestHandlerImpl) CreateChartGroup(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -112,7 +111,7 @@ func (impl *ChartGroupRestHandlerImpl) CreateChartGroup(w http.ResponseWriter, r func (impl *ChartGroupRestHandlerImpl) UpdateChartGroup(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -153,7 +152,7 @@ func (impl *ChartGroupRestHandlerImpl) UpdateChartGroup(w http.ResponseWriter, r func (impl *ChartGroupRestHandlerImpl) SaveChartGroupEntries(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -187,14 +186,14 @@ func (impl *ChartGroupRestHandlerImpl) SaveChartGroupEntries(w http.ResponseWrit func (impl *ChartGroupRestHandlerImpl) GetChartGroupWithChartMetaData(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } - vars := mux.Vars(r) - chartGroupId, err := strconv.Atoi(vars["chartGroupId"]) + + // Use enhanced parameter parsing with context + chartGroupId, err := common.ExtractIntPathParamWithContext(w, r, "chartGroupId", "chart group") if err != nil { - impl.Logger.Errorw("request err, GetChartGroupWithChartMetaData", "err", err, "chartGroupId", chartGroupId) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } @@ -219,14 +218,14 @@ func (impl *ChartGroupRestHandlerImpl) GetChartGroupWithChartMetaData(w http.Res func (impl *ChartGroupRestHandlerImpl) GetChartGroupInstallationDetail(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } - vars := mux.Vars(r) - chartGroupId, err := strconv.Atoi(vars["chartGroupId"]) + + // Use enhanced parameter parsing with context + chartGroupId, err := common.ExtractIntPathParamWithContext(w, r, "chartGroupId", "chart group") if err != nil { - impl.Logger.Errorw("request err, GetChartGroupInstallationDetail", "err", err, "chartGroupId", chartGroupId) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } @@ -251,7 +250,7 @@ func (impl *ChartGroupRestHandlerImpl) GetChartGroupInstallationDetail(w http.Re func (impl *ChartGroupRestHandlerImpl) GetChartGroupList(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -286,7 +285,7 @@ func (impl *ChartGroupRestHandlerImpl) GetChartGroupList(w http.ResponseWriter, func (impl *ChartGroupRestHandlerImpl) GetChartGroupListMin(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -321,7 +320,7 @@ func (impl *ChartGroupRestHandlerImpl) GetChartGroupListMin(w http.ResponseWrite func (impl *ChartGroupRestHandlerImpl) DeleteChartGroup(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) diff --git a/api/appStore/deployment/AppStoreDeploymentRestHandler.go b/api/appStore/deployment/AppStoreDeploymentRestHandler.go index 9aa316460c..119c74e157 100644 --- a/api/appStore/deployment/AppStoreDeploymentRestHandler.go +++ b/api/appStore/deployment/AppStoreDeploymentRestHandler.go @@ -93,7 +93,7 @@ func (handler AppStoreDeploymentRestHandlerImpl) InstallApp(w http.ResponseWrite decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request appStoreBean.InstallAppVersionDTO @@ -179,7 +179,7 @@ func (handler AppStoreDeploymentRestHandlerImpl) InstallApp(w http.ResponseWrite func (handler AppStoreDeploymentRestHandlerImpl) GetInstalledAppsByAppStoreId(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -232,7 +232,7 @@ func (handler AppStoreDeploymentRestHandlerImpl) DeleteInstalledApp(w http.Respo userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -364,7 +364,7 @@ func (handler *AppStoreDeploymentRestHandlerImpl) LinkHelmApplicationToChartStor userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -395,7 +395,7 @@ func (handler AppStoreDeploymentRestHandlerImpl) UpdateInstalledApp(w http.Respo decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request appStoreBean.InstallAppVersionDTO @@ -474,7 +474,7 @@ func (handler AppStoreDeploymentRestHandlerImpl) UpdateInstalledApp(w http.Respo func (handler AppStoreDeploymentRestHandlerImpl) GetInstalledAppVersion(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -520,7 +520,7 @@ func (handler AppStoreDeploymentRestHandlerImpl) GetInstalledAppVersion(w http.R func (handler AppStoreDeploymentRestHandlerImpl) UpdateProjectHelmApp(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") diff --git a/api/appStore/deployment/CommonDeploymentRestHandler.go b/api/appStore/deployment/CommonDeploymentRestHandler.go index e3ee4fba45..019fcaa51d 100644 --- a/api/appStore/deployment/CommonDeploymentRestHandler.go +++ b/api/appStore/deployment/CommonDeploymentRestHandler.go @@ -134,7 +134,7 @@ func (handler *CommonDeploymentRestHandlerImpl) getAppOfferingMode(installedAppI func (handler *CommonDeploymentRestHandlerImpl) GetDeploymentHistory(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } v := r.URL.Query() @@ -181,7 +181,7 @@ func (handler *CommonDeploymentRestHandlerImpl) GetDeploymentHistory(w http.Resp func (handler *CommonDeploymentRestHandlerImpl) GetDeploymentHistoryValues(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -251,7 +251,7 @@ func (handler *CommonDeploymentRestHandlerImpl) GetDeploymentHistoryValues(w htt func (handler *CommonDeploymentRestHandlerImpl) RollbackApplication(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } request := &openapi2.RollbackReleaseRequest{} diff --git a/api/appStore/values/AppStoreValuesRestHandler.go b/api/appStore/values/AppStoreValuesRestHandler.go index f5894612a0..0c86ce7263 100644 --- a/api/appStore/values/AppStoreValuesRestHandler.go +++ b/api/appStore/values/AppStoreValuesRestHandler.go @@ -59,7 +59,7 @@ func (handler AppStoreValuesRestHandlerImpl) CreateAppStoreVersionValues(w http. decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request appStoreBean.AppStoreVersionValuesDTO @@ -84,7 +84,7 @@ func (handler AppStoreValuesRestHandlerImpl) UpdateAppStoreVersionValues(w http. decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request appStoreBean.AppStoreVersionValuesDTO @@ -108,7 +108,7 @@ func (handler AppStoreValuesRestHandlerImpl) UpdateAppStoreVersionValues(w http. func (handler AppStoreValuesRestHandlerImpl) FindValuesById(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -161,7 +161,7 @@ func (handler AppStoreValuesRestHandlerImpl) DeleteAppStoreVersionValues(w http. func (handler AppStoreValuesRestHandlerImpl) FindValuesByAppStoreIdAndReferenceType(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -185,7 +185,7 @@ func (handler AppStoreValuesRestHandlerImpl) FindValuesByAppStoreIdAndReferenceT func (handler AppStoreValuesRestHandlerImpl) FetchTemplateValuesByAppStoreId(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -221,7 +221,7 @@ func (handler AppStoreValuesRestHandlerImpl) FetchTemplateValuesByAppStoreId(w h func (handler AppStoreValuesRestHandlerImpl) GetSelectedChartMetadata(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) diff --git a/api/auth/sso/SsoLoginHandler.go b/api/auth/sso/SsoLoginHandler.go index 6044df9995..9b6e14d574 100644 --- a/api/auth/sso/SsoLoginHandler.go +++ b/api/auth/sso/SsoLoginHandler.go @@ -59,7 +59,7 @@ func NewSsoLoginRestHandlerImpl(validator *validator.Validate, func (handler SsoLoginRestHandlerImpl) CreateSSOLoginConfig(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -91,7 +91,7 @@ func (handler SsoLoginRestHandlerImpl) CreateSSOLoginConfig(w http.ResponseWrite func (handler SsoLoginRestHandlerImpl) UpdateSSOLoginConfig(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -134,7 +134,7 @@ func (handler SsoLoginRestHandlerImpl) GetAllSSOLoginConfig(w http.ResponseWrite func (handler SsoLoginRestHandlerImpl) GetSSOLoginConfig(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -164,7 +164,7 @@ func (handler SsoLoginRestHandlerImpl) GetSSOLoginConfig(w http.ResponseWriter, func (handler SsoLoginRestHandlerImpl) GetSSOLoginConfigByName(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/auth/user/RbacRoleRestHandler.go b/api/auth/user/RbacRoleRestHandler.go index e509095861..d604fbaf60 100644 --- a/api/auth/user/RbacRoleRestHandler.go +++ b/api/auth/user/RbacRoleRestHandler.go @@ -59,7 +59,7 @@ func NewRbacRoleHandlerImpl(logger *zap.SugaredLogger, func (handler *RbacRoleRestHandlerImpl) GetAllDefaultRoles(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } handler.logger.Debugw("request payload, GetAllDefaultRoles") diff --git a/api/auth/user/UserRestHandler.go b/api/auth/user/UserRestHandler.go index 9c7610f310..9fac7e4c98 100644 --- a/api/auth/user/UserRestHandler.go +++ b/api/auth/user/UserRestHandler.go @@ -98,7 +98,7 @@ func (handler UserRestHandlerImpl) CreateUser(w http.ResponseWriter, r *http.Req decoder := json.NewDecoder(r.Body) userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var userInfo bean2.UserInfo @@ -162,7 +162,7 @@ func (handler UserRestHandlerImpl) UpdateUser(w http.ResponseWriter, r *http.Req decoder := json.NewDecoder(r.Body) userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var userInfo bean2.UserInfo @@ -205,21 +205,22 @@ func (handler UserRestHandlerImpl) UpdateUser(w http.ResponseWriter, r *http.Req func (handler UserRestHandlerImpl) GetById(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } - vars := mux.Vars(r) - /* #nosec */ - id, err := strconv.Atoi(vars["id"]) + + // Use enhanced parameter parsing with context + id, err := common.ExtractIntPathParamWithContext(w, r, "id", "user") if err != nil { - handler.logger.Errorw("request err, GetById", "err", err, "id", id) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } + res, err := handler.userService.GetByIdWithoutGroupClaims(int32(id)) if err != nil { - handler.logger.Errorw("service err, GetById", "err", err, "id", id) - common.WriteJsonResp(w, err, "Failed to get by id", http.StatusInternalServerError) + handler.logger.Errorw("Failed to get user by ID", "userId", id, "err", err) + // Use enhanced error response with resource context + common.WriteJsonRespWithResourceContextFromId(w, err, nil, 0, "user", id) return } @@ -237,7 +238,7 @@ func (handler UserRestHandlerImpl) GetAllV2(w http.ResponseWriter, r *http.Reque var decoder = schema.NewDecoder() userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -274,7 +275,7 @@ func (handler UserRestHandlerImpl) GetAllV2(w http.ResponseWriter, r *http.Reque func (handler UserRestHandlerImpl) GetAll(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -303,7 +304,7 @@ func (handler UserRestHandlerImpl) GetAll(w http.ResponseWriter, r *http.Request func (handler UserRestHandlerImpl) GetAllDetailedUsers(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -328,21 +329,22 @@ func (handler UserRestHandlerImpl) GetAllDetailedUsers(w http.ResponseWriter, r func (handler UserRestHandlerImpl) DeleteUser(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } - vars := mux.Vars(r) - /* #nosec */ - id, err := strconv.Atoi(vars["id"]) + + // Use enhanced parameter parsing with context + id, err := common.ExtractIntPathParamWithContext(w, r, "id", "user") if err != nil { - handler.logger.Errorw("request err, DeleteUser", "err", err, "id", id) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } - handler.logger.Infow("request payload, DeleteUser", "err", err, "id", id) + + handler.logger.Infow("Delete user request", "userId", id, "requestedBy", userId) user, err := handler.userService.GetByIdWithoutGroupClaims(int32(id)) if err != nil { - common.WriteJsonResp(w, err, "", http.StatusInternalServerError) + handler.logger.Errorw("Failed to get user for deletion", "userId", id, "err", err) + common.WriteJsonRespWithResourceContextFromId(w, err, nil, 0, "user", id) return } @@ -376,7 +378,7 @@ func (handler UserRestHandlerImpl) DeleteUser(w http.ResponseWriter, r *http.Req func (handler UserRestHandlerImpl) BulkDeleteUsers(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -424,18 +426,17 @@ func (handler UserRestHandlerImpl) BulkDeleteUsers(w http.ResponseWriter, r *htt } func (handler UserRestHandlerImpl) FetchRoleGroupById(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - /* #nosec */ - id, err := strconv.Atoi(vars["id"]) + // Use enhanced parameter parsing with context + id, err := common.ExtractIntPathParamWithContext(w, r, "id", "role group") if err != nil { - handler.logger.Errorw("request err, FetchRoleGroupById", "err", err, "id", id) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } + res, err := handler.roleGroupService.FetchRoleGroupsById(int32(id)) if err != nil { - handler.logger.Errorw("service err, FetchRoleGroupById", "err", err, "id", id) - common.WriteJsonResp(w, err, "Failed to get by id", http.StatusInternalServerError) + handler.logger.Errorw("Failed to fetch role group by ID", "roleGroupId", id, "err", err) + common.WriteJsonRespWithResourceContextFromId(w, err, nil, 0, "role group", id) return } @@ -454,7 +455,7 @@ func (handler UserRestHandlerImpl) CreateRoleGroup(w http.ResponseWriter, r *htt decoder := json.NewDecoder(r.Body) userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request bean2.RoleGroup @@ -507,7 +508,7 @@ func (handler UserRestHandlerImpl) UpdateRoleGroup(w http.ResponseWriter, r *htt decoder := json.NewDecoder(r.Body) userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request bean2.RoleGroup @@ -552,7 +553,7 @@ func (handler UserRestHandlerImpl) FetchRoleGroupsV2(w http.ResponseWriter, r *h var decoder = schema.NewDecoder() userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // RBAC enforcer applying @@ -588,7 +589,7 @@ func (handler UserRestHandlerImpl) FetchRoleGroupsV2(w http.ResponseWriter, r *h func (handler UserRestHandlerImpl) FetchRoleGroups(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // RBAC enforcer applying @@ -615,7 +616,7 @@ func (handler UserRestHandlerImpl) FetchRoleGroups(w http.ResponseWriter, r *htt func (handler UserRestHandlerImpl) FetchDetailedRoleGroups(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -640,7 +641,7 @@ func (handler UserRestHandlerImpl) FetchDetailedRoleGroups(w http.ResponseWriter func (handler UserRestHandlerImpl) FetchRoleGroupsByName(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -658,7 +659,7 @@ func (handler UserRestHandlerImpl) FetchRoleGroupsByName(w http.ResponseWriter, func (handler UserRestHandlerImpl) DeleteRoleGroup(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -701,7 +702,7 @@ func (handler UserRestHandlerImpl) DeleteRoleGroup(w http.ResponseWriter, r *htt func (handler UserRestHandlerImpl) BulkDeleteRoleGroups(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -745,7 +746,7 @@ func (handler UserRestHandlerImpl) BulkDeleteRoleGroups(w http.ResponseWriter, r func (handler UserRestHandlerImpl) CheckUserRoles(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } roles, err := handler.userService.CheckUserRoles(userId, "") @@ -804,7 +805,7 @@ func (handler UserRestHandlerImpl) CheckUserRoles(w http.ResponseWriter, r *http func (handler UserRestHandlerImpl) SyncOrchestratorToCasbin(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } userEmailId, err := handler.userService.GetActiveEmailById(userId) @@ -830,7 +831,7 @@ func (handler UserRestHandlerImpl) UpdateTriggerPolicyForTerminalAccess(w http.R userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { handler.logger.Errorw("unauthorized user, UpdateTriggerPolicyForTerminalAccess", "userId", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/chartRepo/ChartRepositoryRestHandler.go b/api/chartRepo/ChartRepositoryRestHandler.go index 11a48a296d..ccd417827d 100644 --- a/api/chartRepo/ChartRepositoryRestHandler.go +++ b/api/chartRepo/ChartRepositoryRestHandler.go @@ -21,7 +21,6 @@ import ( "errors" "mime/multipart" "net/http" - "strconv" "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/internal/util" @@ -30,7 +29,6 @@ import ( "github.com/devtron-labs/devtron/pkg/auth/user" "github.com/devtron-labs/devtron/pkg/chartRepo" delete2 "github.com/devtron-labs/devtron/pkg/delete" - "github.com/gorilla/mux" "go.uber.org/zap" "gopkg.in/go-playground/validator.v9" ) @@ -82,21 +80,22 @@ func NewChartRepositoryRestHandlerImpl(Logger *zap.SugaredLogger, userAuthServic func (handler *ChartRepositoryRestHandlerImpl) GetChartRepoById(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, nil, http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } - vars := mux.Vars(r) - id, err := strconv.Atoi(vars["id"]) + + // Use enhanced parameter parsing with context + id, err := common.ExtractIntPathParamWithContext(w, r, "id", "chart repository") if err != nil { - handler.Logger.Errorw("request err, GetChartRepoById", "err", err, "chart repo id", id) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } - handler.Logger.Infow("request payload, GetChartRepoById, app store", "chart repo id", id) + + handler.Logger.Infow("Get chart repository request", "chartRepoId", id, "userId", userId) res, err := handler.chartRepositoryService.GetChartRepoById(id) if err != nil { - handler.Logger.Errorw("service err, GetChartRepoById, app store", "err", err, "userId", userId) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + handler.Logger.Errorw("Failed to get chart repository", "chartRepoId", id, "userId", userId, "err", err) + common.WriteJsonRespWithResourceContextFromId(w, err, nil, 0, "chart repository", id) return } common.WriteJsonResp(w, err, res, http.StatusOK) @@ -147,7 +146,7 @@ func (handler *ChartRepositoryRestHandlerImpl) CreateChartRepo(w http.ResponseWr decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request *chartRepo.ChartRepoDto @@ -191,7 +190,7 @@ func (handler *ChartRepositoryRestHandlerImpl) UpdateChartRepo(w http.ResponseWr decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request *chartRepo.ChartRepoDto @@ -235,7 +234,7 @@ func (handler *ChartRepositoryRestHandlerImpl) ValidateChartRepo(w http.Response decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request *chartRepo.ChartRepoDto @@ -292,7 +291,7 @@ func (handler *ChartRepositoryRestHandlerImpl) DeleteChartRepo(w http.ResponseWr decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request *chartRepo.ChartRepoDto diff --git a/api/cluster/ClusterRestHandler.go b/api/cluster/ClusterRestHandler.go index 2d2f946cb9..c400a34f7a 100644 --- a/api/cluster/ClusterRestHandler.go +++ b/api/cluster/ClusterRestHandler.go @@ -106,7 +106,7 @@ func (impl ClusterRestHandlerImpl) SaveClusters(w http.ResponseWriter, r *http.R decoder := json.NewDecoder(r.Body) userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } beans := []*bean2.ClusterBean{} @@ -169,7 +169,7 @@ func (impl ClusterRestHandlerImpl) Save(w http.ResponseWriter, r *http.Request) decoder := json.NewDecoder(r.Body) userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } bean := new(bean2.ClusterBean) @@ -230,7 +230,7 @@ func (impl ClusterRestHandlerImpl) ValidateKubeconfig(w http.ResponseWriter, r * decoder := json.NewDecoder(r.Body) userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } bean := &bean2.Kubeconfig{} @@ -352,18 +352,18 @@ func (impl ClusterRestHandlerImpl) FindByIds(w http.ResponseWriter, r *http.Requ } func (impl ClusterRestHandlerImpl) FindById(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - id := vars["id"] - i, err := strconv.Atoi(id) + // Use enhanced parameter parsing with context + clusterId, err := common.ExtractIntPathParamWithContext(w, r, "id", "cluster") if err != nil { - impl.logger.Errorw("request err, FindById", "error", err, "clusterId", id) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } - bean, err := impl.clusterService.FindByIdWithoutConfig(i) + + bean, err := impl.clusterService.FindByIdWithoutConfig(clusterId) if err != nil { - impl.logger.Errorw("service err, FindById", "err", err, "clusterId", id) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + impl.logger.Errorw("Failed to find cluster", "clusterId", clusterId, "err", err) + // Use enhanced error response with resource context + common.WriteJsonRespWithResourceContextFromId(w, err, nil, 0, "cluster", clusterId) return } @@ -381,7 +381,7 @@ func (impl ClusterRestHandlerImpl) FindById(w http.ResponseWriter, r *http.Reque func (impl ClusterRestHandlerImpl) FindNoteByClusterId(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -425,7 +425,7 @@ func (impl ClusterRestHandlerImpl) Update(w http.ResponseWriter, r *http.Request userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { impl.logger.Errorw("service err, Update", "error", err, "userId", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean bean2.ClusterBean @@ -478,7 +478,7 @@ func (impl ClusterRestHandlerImpl) UpdateClusterDescription(w http.ResponseWrite userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { impl.logger.Errorw("service err, Update", "error", err, "userId", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean bean2.ClusterBean @@ -518,7 +518,7 @@ func (impl ClusterRestHandlerImpl) UpdateClusterNote(w http.ResponseWriter, r *h userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { impl.logger.Errorw("service err, Update", "error", err, "userId", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean repository.GenericNote @@ -608,7 +608,7 @@ func (impl ClusterRestHandlerImpl) DeleteCluster(w http.ResponseWriter, r *http. userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { impl.logger.Errorw("service err, Delete", "error", err, "userId", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean bean2.DeleteClusterBean @@ -647,7 +647,7 @@ func (impl ClusterRestHandlerImpl) GetAllClusterNamespaces(w http.ResponseWriter userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { impl.logger.Errorw("err, GetAllClusterNamespaces", "error", err, "userId", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } clusterNamespaces := impl.clusterService.GetAllClusterNamespaces() @@ -709,7 +709,7 @@ func (impl ClusterRestHandlerImpl) GetClusterNamespaces(w http.ResponseWriter, r userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { impl.logger.Errorw("user not authorized", "error", err, "userId", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -743,7 +743,7 @@ func (impl ClusterRestHandlerImpl) FindAllForClusterPermission(w http.ResponseWr userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { impl.logger.Errorw("user not authorized", "error", err, "userId", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") diff --git a/api/cluster/EnvironmentRestHandler.go b/api/cluster/EnvironmentRestHandler.go index 9189ba28ea..1ce898bd5d 100644 --- a/api/cluster/EnvironmentRestHandler.go +++ b/api/cluster/EnvironmentRestHandler.go @@ -110,7 +110,7 @@ func (impl EnvironmentRestHandlerImpl) Create(w http.ResponseWriter, r *http.Req decoder := json.NewDecoder(r.Body) userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean bean2.EnvironmentBean @@ -206,7 +206,7 @@ func (impl EnvironmentRestHandlerImpl) GetAll(w http.ResponseWriter, r *http.Req userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -261,7 +261,7 @@ func (impl EnvironmentRestHandlerImpl) Update(w http.ResponseWriter, r *http.Req decoder := json.NewDecoder(r.Body) userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -303,16 +303,18 @@ func (impl EnvironmentRestHandlerImpl) Update(w http.ResponseWriter, r *http.Req } func (impl EnvironmentRestHandlerImpl) FindById(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - envId, err := strconv.Atoi(vars["id"]) + // Use enhanced parameter parsing with context + envId, err := common.ExtractIntPathParamWithContext(w, r, "id", "environment") if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } + bean, err := impl.environmentClusterMappingsService.FindById(envId) if err != nil { - impl.logger.Errorw("service err, FindById", "err", err, "envId", envId) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + impl.logger.Errorw("Failed to find environment", "envId", envId, "err", err) + // Use enhanced error response with resource context + common.WriteJsonRespWithResourceContextFromId(w, err, nil, 0, "environment", envId) return } @@ -330,7 +332,7 @@ func (impl EnvironmentRestHandlerImpl) FindById(w http.ResponseWriter, r *http.R func (impl EnvironmentRestHandlerImpl) GetEnvironmentListForAutocomplete(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } start := time.Now() @@ -363,7 +365,7 @@ func (impl EnvironmentRestHandlerImpl) GetEnvironmentListForAutocomplete(w http. func (impl EnvironmentRestHandlerImpl) GetCombinedEnvironmentListForDropDown(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -385,7 +387,7 @@ func (impl EnvironmentRestHandlerImpl) DeleteEnvironment(w http.ResponseWriter, decoder := json.NewDecoder(r.Body) userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean bean2.EnvironmentBean @@ -423,7 +425,7 @@ func (impl EnvironmentRestHandlerImpl) DeleteEnvironment(w http.ResponseWriter, func (impl EnvironmentRestHandlerImpl) GetCombinedEnvironmentListForDropDownByClusterIds(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } v := r.URL.Query() @@ -468,7 +470,7 @@ func (impl EnvironmentRestHandlerImpl) GetEnvironmentConnection(w http.ResponseW userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { impl.logger.Errorw("user not authorized", "error", err, "userId", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } bean, err := impl.environmentClusterMappingsService.FindById(envId) diff --git a/api/externalLink/ExternalLinkRestHandler.go b/api/externalLink/ExternalLinkRestHandler.go index cbf6783371..2c24ef6ebd 100644 --- a/api/externalLink/ExternalLinkRestHandler.go +++ b/api/externalLink/ExternalLinkRestHandler.go @@ -67,7 +67,7 @@ func NewExternalLinkRestHandlerImpl(logger *zap.SugaredLogger, func (impl ExternalLinkRestHandlerImpl) roleCheckHelper(w http.ResponseWriter, r *http.Request, action string) (int32, string, error) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return userId, "", fmt.Errorf("unauthorized error") } userRole := "" @@ -78,8 +78,9 @@ func (impl ExternalLinkRestHandlerImpl) roleCheckHelper(w http.ResponseWriter, r if v.Has("appId") { id, err := strconv.Atoi(appId) if err != nil { - impl.logger.Errorw("error occurred while converting appId to integer", "err", err, "appId", appId) - common.WriteJsonResp(w, errors.New("Invalid request"), nil, http.StatusBadRequest) + impl.logger.Errorw("Invalid appId query parameter", "err", err, "appId", appId) + // Use enhanced error handling for query parameter validation + common.HandleParameterError(w, r, "appId", appId) return userId, "", fmt.Errorf("invalid request query param appId = %s", appId) } object := impl.enforcerUtil.GetAppRBACNameByAppId(id) @@ -122,7 +123,7 @@ func (impl ExternalLinkRestHandlerImpl) CreateExternalLinks(w http.ResponseWrite func (impl ExternalLinkRestHandlerImpl) GetExternalLinkMonitoringTools(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -139,7 +140,7 @@ func (impl ExternalLinkRestHandlerImpl) GetExternalLinkMonitoringTools(w http.Re func (impl ExternalLinkRestHandlerImpl) GetExternalLinks(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -198,7 +199,7 @@ func (impl ExternalLinkRestHandlerImpl) GetExternalLinks(w http.ResponseWriter, func (impl ExternalLinkRestHandlerImpl) GetExternalLinksV2(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/helm-app/HelmAppRestHandler.go b/api/helm-app/HelmAppRestHandler.go index bb4343a530..49c2da7c14 100644 --- a/api/helm-app/HelmAppRestHandler.go +++ b/api/helm-app/HelmAppRestHandler.go @@ -116,8 +116,9 @@ func (handler *HelmAppRestHandlerImpl) ListApplications(w http.ResponseWriter, r } j, err := strconv.Atoi(is) if err != nil { - handler.logger.Errorw("request err, CreateUser", "err", err, "payload", clusterIds) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + handler.logger.Errorw("Invalid cluster ID in list", "err", err, "clusterId", is, "clusterIdString", clusterIdString) + // Use enhanced error handling for parameter validation + common.HandleParameterError(w, r, "clusterIds", clusterIdString) return } clusterIds = append(clusterIds, j) @@ -190,7 +191,8 @@ func (handler *HelmAppRestHandlerImpl) Hibernate(w http.ResponseWriter, r *http. } else { appType, err = strconv.Atoi(appTypeString) if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + handler.logger.Errorw("Invalid app type parameter", "err", err, "appType", appTypeString) + common.HandleParameterError(w, r, "appType", appTypeString) return } } @@ -446,7 +448,7 @@ func (handler *HelmAppRestHandlerImpl) GetDesiredManifest(w http.ResponseWriter, func (handler *HelmAppRestHandlerImpl) DeleteApplication(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -529,7 +531,7 @@ func (handler *HelmAppRestHandlerImpl) UpdateApplication(w http.ResponseWriter, func (handler *HelmAppRestHandlerImpl) TemplateChart(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } request := &openapi2.TemplateChartRequest{} diff --git a/api/infraConfig/restHandler.go b/api/infraConfig/restHandler.go index 6d7b550fc2..a98f0cb234 100644 --- a/api/infraConfig/restHandler.go +++ b/api/infraConfig/restHandler.go @@ -71,7 +71,7 @@ func NewInfraConfigRestHandlerImpl(logger *zap.SugaredLogger, infraProfileServic func (handler *InfraConfigRestHandlerImpl) GetProfile(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -129,7 +129,7 @@ func (handler *InfraConfigRestHandlerImpl) GetProfile(w http.ResponseWriter, r * func (handler *InfraConfigRestHandlerImpl) UpdateInfraProfile(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -176,7 +176,7 @@ func (handler *InfraConfigRestHandlerImpl) UpdateInfraProfile(w http.ResponseWri func (handler *InfraConfigRestHandlerImpl) GetProfileV0(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -238,7 +238,7 @@ func (handler *InfraConfigRestHandlerImpl) GetProfileV0(w http.ResponseWriter, r func (handler *InfraConfigRestHandlerImpl) UpdateInfraProfileV0(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") diff --git a/api/k8s/application/k8sApplicationRestHandler.go b/api/k8s/application/k8sApplicationRestHandler.go index 7c92322f60..830895dd38 100644 --- a/api/k8s/application/k8sApplicationRestHandler.go +++ b/api/k8s/application/k8sApplicationRestHandler.go @@ -466,7 +466,7 @@ func (handler *K8sApplicationRestHandlerImpl) handleRbac(r *http.Request, w http func (handler *K8sApplicationRestHandlerImpl) DeleteResource(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request bean3.ResourceRequestBean @@ -771,7 +771,7 @@ func (handler *K8sApplicationRestHandlerImpl) GetTerminalSession(w http.Response token := r.Header.Get("token") userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } request, resourceRequestBean, err := handler.k8sApplicationService.ValidateTerminalRequestQuery(r) @@ -837,7 +837,7 @@ func (handler *K8sApplicationRestHandlerImpl) GetTerminalSession(w http.Response func (handler *K8sApplicationRestHandlerImpl) GetResourceInfo(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -856,7 +856,7 @@ func (handler *K8sApplicationRestHandlerImpl) GetResourceInfo(w http.ResponseWri func (handler *K8sApplicationRestHandlerImpl) GetAllApiResourceGVKWithoutAuthorization(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -883,7 +883,7 @@ func (handler *K8sApplicationRestHandlerImpl) GetAllApiResourceGVKWithoutAuthori func (handler *K8sApplicationRestHandlerImpl) GetAllApiResources(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -991,7 +991,7 @@ func (handler *K8sApplicationRestHandlerImpl) CreateEphemeralContainer(w http.Re token := r.Header.Get("token") userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -1041,7 +1041,7 @@ func (handler *K8sApplicationRestHandlerImpl) DeleteEphemeralContainer(w http.Re token := r.Header.Get("token") userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) diff --git a/api/k8s/capacity/k8sCapacityRestHandler.go b/api/k8s/capacity/k8sCapacityRestHandler.go index 2dee3457f9..75f9254392 100644 --- a/api/k8s/capacity/k8sCapacityRestHandler.go +++ b/api/k8s/capacity/k8sCapacityRestHandler.go @@ -87,7 +87,7 @@ func NewK8sCapacityRestHandlerImpl(logger *zap.SugaredLogger, func (handler *K8sCapacityRestHandlerImpl) GetClusterListRaw(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -129,7 +129,7 @@ func (handler *K8sCapacityRestHandlerImpl) GetClusterListRaw(w http.ResponseWrit func (handler *K8sCapacityRestHandlerImpl) GetClusterListWithDetail(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -169,7 +169,7 @@ func (handler *K8sCapacityRestHandlerImpl) GetClusterDetail(w http.ResponseWrite vars := mux.Vars(r) userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } clusterId, err := strconv.Atoi(vars["clusterId"]) @@ -209,7 +209,7 @@ func (handler *K8sCapacityRestHandlerImpl) GetNodeList(w http.ResponseWriter, r vars := r.URL.Query() userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } clusterId, err := strconv.Atoi(vars.Get("clusterId")) @@ -244,7 +244,7 @@ func (handler *K8sCapacityRestHandlerImpl) GetNodeDetail(w http.ResponseWriter, vars := r.URL.Query() userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } clusterId, err := strconv.Atoi(vars.Get("clusterId")) @@ -292,7 +292,7 @@ func (handler *K8sCapacityRestHandlerImpl) UpdateNodeManifest(w http.ResponseWri } userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // RBAC enforcer applying @@ -327,7 +327,7 @@ func (handler *K8sCapacityRestHandlerImpl) DeleteNode(w http.ResponseWriter, r * } userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // RBAC enforcer applying @@ -371,7 +371,7 @@ func (handler *K8sCapacityRestHandlerImpl) CordonOrUnCordonNode(w http.ResponseW } userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // RBAC enforcer applying @@ -415,7 +415,7 @@ func (handler *K8sCapacityRestHandlerImpl) DrainNode(w http.ResponseWriter, r *h userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // RBAC enforcer applying @@ -450,7 +450,7 @@ func (handler *K8sCapacityRestHandlerImpl) EditNodeTaints(w http.ResponseWriter, } userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // RBAC enforcer applying diff --git a/api/middleware/ErrorHandlingMiddleware.go b/api/middleware/ErrorHandlingMiddleware.go new file mode 100644 index 0000000000..a1309c5fb6 --- /dev/null +++ b/api/middleware/ErrorHandlingMiddleware.go @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2024. Devtron Inc. + * + * Licensed 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. + */ + +package middleware + +import ( + "context" + "fmt" + "github.com/devtron-labs/devtron/internal/util" + "github.com/gorilla/mux" + "go.uber.org/zap" + "net/http" + "strconv" + "time" +) + +// ErrorHandlingMiddleware provides enhanced error handling and logging for REST handlers +type ErrorHandlingMiddleware struct { + logger *zap.SugaredLogger +} + +// NewErrorHandlingMiddleware creates a new error handling middleware +func NewErrorHandlingMiddleware(logger *zap.SugaredLogger) *ErrorHandlingMiddleware { + return &ErrorHandlingMiddleware{ + logger: logger, + } +} + +// RequestContext holds information about the current request for better error handling +type RequestContext struct { + RequestID string + StartTime time.Time + Method string + Path string + ResourceType string + ResourceID string + UserID int +} + +// ContextKey is used for storing request context in the request context +type ContextKey string + +const RequestContextKey ContextKey = "request_context" + +// WithRequestContext middleware adds request context for better error handling +func (m *ErrorHandlingMiddleware) WithRequestContext(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Generate request ID for correlation + requestID := fmt.Sprintf("%d", time.Now().UnixNano()) + + // Extract resource information from path + vars := mux.Vars(r) + resourceType, resourceID := extractResourceFromPath(r.URL.Path, vars) + + // Create request context + reqCtx := &RequestContext{ + RequestID: requestID, + StartTime: time.Now(), + Method: r.Method, + Path: r.URL.Path, + ResourceType: resourceType, + ResourceID: resourceID, + } + + // Add to request context + ctx := context.WithValue(r.Context(), RequestContextKey, reqCtx) + r = r.WithContext(ctx) + + // Add request ID to response headers for debugging + w.Header().Set("X-Request-ID", requestID) + + // Log request start + m.logger.Infow("Request started", + "requestId", requestID, + "method", r.Method, + "path", r.URL.Path, + "resourceType", resourceType, + "resourceId", resourceID, + ) + + next.ServeHTTP(w, r) + + // Log request completion + duration := time.Since(reqCtx.StartTime) + m.logger.Infow("Request completed", + "requestId", requestID, + "duration", duration, + "method", r.Method, + "path", r.URL.Path, + ) + }) +} + +// extractResourceFromPath attempts to extract resource type and ID from the request path +func extractResourceFromPath(path string, vars map[string]string) (resourceType, resourceID string) { + // Common resource type mappings based on path patterns + resourceMappings := map[string]string{ + "/api/v1/team/": "team", + "/api/v1/cluster/": "cluster", + "/api/v1/env/": "environment", + "/api/v1/app/": "application", + "/api/v1/docker/": "docker registry", + "/api/v1/git/": "git provider", + "/api/v1/pipeline/": "pipeline", + "/api/v1/webhook/": "webhook", + "/orchestrator/team/": "team", + "/orchestrator/app/": "application", + "/orchestrator/env/": "environment", + } + + // Try to match path patterns + for pathPrefix, resType := range resourceMappings { + if len(path) > len(pathPrefix) && path[:len(pathPrefix)] == pathPrefix { + resourceType = resType + break + } + } + + // Try to extract ID from common parameter names + if id, exists := vars["id"]; exists { + resourceID = id + } else if id, exists := vars["teamId"]; exists { + resourceID = id + } else if id, exists := vars["appId"]; exists { + resourceID = id + } else if id, exists := vars["clusterId"]; exists { + resourceID = id + } else if id, exists := vars["envId"]; exists { + resourceID = id + } else if id, exists := vars["gitHostId"]; exists { + resourceID = id + } + + return resourceType, resourceID +} + +// GetRequestContext retrieves the request context from the HTTP request +func GetRequestContext(r *http.Request) *RequestContext { + if ctx := r.Context().Value(RequestContextKey); ctx != nil { + if reqCtx, ok := ctx.(*RequestContext); ok { + return reqCtx + } + } + return nil +} + +// LogError logs an error with request context for better debugging +func (m *ErrorHandlingMiddleware) LogError(r *http.Request, err error, operation string) { + reqCtx := GetRequestContext(r) + if reqCtx != nil { + m.logger.Errorw("Request error", + "requestId", reqCtx.RequestID, + "operation", operation, + "error", err, + "method", reqCtx.Method, + "path", reqCtx.Path, + "resourceType", reqCtx.ResourceType, + "resourceId", reqCtx.ResourceID, + ) + } else { + m.logger.Errorw("Request error", + "operation", operation, + "error", err, + "method", r.Method, + "path", r.URL.Path, + ) + } +} + +// ValidateIntPathParam validates and extracts an integer path parameter with enhanced error handling +func ValidateIntPathParam(r *http.Request, paramName string) (int, *util.ApiError) { + vars := mux.Vars(r) + paramValue := vars[paramName] + + if paramValue == "" { + return 0, util.NewMissingRequiredFieldError(paramName) + } + + id, err := strconv.Atoi(paramValue) + if err != nil { + return 0, util.NewInvalidPathParameterError(paramName, paramValue) + } + + if id <= 0 { + return 0, util.NewValidationErrorForField(paramName, "must be a positive integer") + } + + return id, nil +} diff --git a/api/module/ModuleRestHandler.go b/api/module/ModuleRestHandler.go index 664cae0322..58649ae68a 100644 --- a/api/module/ModuleRestHandler.go +++ b/api/module/ModuleRestHandler.go @@ -64,7 +64,7 @@ func NewModuleRestHandlerImpl(logger *zap.SugaredLogger, func (impl ModuleRestHandlerImpl) GetModuleConfig(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -90,7 +90,7 @@ func (impl ModuleRestHandlerImpl) GetModuleInfo(w http.ResponseWriter, r *http.R // check if user is logged in or not userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -121,7 +121,7 @@ func (impl ModuleRestHandlerImpl) HandleModuleAction(w http.ResponseWriter, r *h // check if user is logged in or not userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -171,7 +171,7 @@ func (impl ModuleRestHandlerImpl) EnableModule(w http.ResponseWriter, r *http.Re // check if user is logged in or not userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/resourceScan/resourceScanRestHandler.go b/api/resourceScan/resourceScanRestHandler.go index f15747e4ec..e3c1bc746a 100644 --- a/api/resourceScan/resourceScanRestHandler.go +++ b/api/resourceScan/resourceScanRestHandler.go @@ -99,7 +99,7 @@ func getResourceScanQueryParams(w http.ResponseWriter, r *http.Request) (*bean.R func (impl ScanningResultRestHandlerImpl) ScanResults(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } resourceScanQueryParams, err := getResourceScanQueryParams(w, r) diff --git a/api/restHandler/AttributesRestHandlder.go b/api/restHandler/AttributesRestHandlder.go index 0eed5eef87..767bc2d1ff 100644 --- a/api/restHandler/AttributesRestHandlder.go +++ b/api/restHandler/AttributesRestHandlder.go @@ -60,7 +60,7 @@ func NewAttributesRestHandlerImpl(logger *zap.SugaredLogger, enforcer casbin.Enf func (handler AttributesRestHandlerImpl) AddAttributes(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -91,7 +91,7 @@ func (handler AttributesRestHandlerImpl) AddAttributes(w http.ResponseWriter, r func (handler AttributesRestHandlerImpl) UpdateAttributes(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -123,7 +123,7 @@ func (handler AttributesRestHandlerImpl) UpdateAttributes(w http.ResponseWriter, func (handler AttributesRestHandlerImpl) GetAttributesById(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -151,7 +151,7 @@ func (handler AttributesRestHandlerImpl) GetAttributesById(w http.ResponseWriter func (handler AttributesRestHandlerImpl) GetAttributesActiveList(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -173,7 +173,7 @@ func (handler AttributesRestHandlerImpl) GetAttributesActiveList(w http.Response func (handler AttributesRestHandlerImpl) GetAttributesByKey(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -197,7 +197,7 @@ func (handler AttributesRestHandlerImpl) GetAttributesByKey(w http.ResponseWrite func (handler AttributesRestHandlerImpl) AddDeploymentEnforcementConfig(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) diff --git a/api/restHandler/BatchOperationRestHandler.go b/api/restHandler/BatchOperationRestHandler.go index f9df83eeed..c1f3adb535 100644 --- a/api/restHandler/BatchOperationRestHandler.go +++ b/api/restHandler/BatchOperationRestHandler.go @@ -66,7 +66,7 @@ func (handler BatchOperationRestHandlerImpl) Operate(w http.ResponseWriter, r *h decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var data map[string]interface{} diff --git a/api/restHandler/BulkUpdateRestHandler.go b/api/restHandler/BulkUpdateRestHandler.go index d02a8be6b8..782bddd7bb 100644 --- a/api/restHandler/BulkUpdateRestHandler.go +++ b/api/restHandler/BulkUpdateRestHandler.go @@ -229,7 +229,7 @@ func (handler BulkUpdateRestHandlerImpl) CheckAuthForBulkUpdate(AppId int, EnvId func (handler BulkUpdateRestHandlerImpl) BulkEdit(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -300,7 +300,7 @@ func (handler BulkUpdateRestHandlerImpl) BulkHibernate(w http.ResponseWriter, r func (handler BulkUpdateRestHandlerImpl) decodeAndValidateBulkRequest(w http.ResponseWriter, r *http.Request) (*bean.BulkApplicationForEnvironmentPayload, error) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return nil, err } @@ -339,7 +339,7 @@ func (handler BulkUpdateRestHandlerImpl) BulkDeploy(w http.ResponseWriter, r *ht token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -370,7 +370,7 @@ func (handler BulkUpdateRestHandlerImpl) BulkDeploy(w http.ResponseWriter, r *ht func (handler BulkUpdateRestHandlerImpl) BulkBuildTrigger(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -420,7 +420,7 @@ func (handler BulkUpdateRestHandlerImpl) HandleCdPipelineBulkAction(w http.Respo decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var cdPipelineBulkActionReq bean.CdBulkActionRequestDto diff --git a/api/restHandler/CommonRestHanlder.go b/api/restHandler/CommonRestHanlder.go index 5527aa2f4a..6ffb772695 100644 --- a/api/restHandler/CommonRestHanlder.go +++ b/api/restHandler/CommonRestHanlder.go @@ -50,7 +50,7 @@ func NewCommonRestHandlerImpl( func (impl CommonRestHandlerImpl) GlobalChecklist(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } res, err := impl.commonService.GlobalChecklist() @@ -66,7 +66,7 @@ func (impl CommonRestHandlerImpl) GlobalChecklist(w http.ResponseWriter, r *http func (impl CommonRestHandlerImpl) EnvironmentVariableList(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // TODO: ADD RBAC (if required) diff --git a/api/restHandler/ConfigMapRestHandler.go b/api/restHandler/ConfigMapRestHandler.go index 85d57e2784..bd4278662b 100644 --- a/api/restHandler/ConfigMapRestHandler.go +++ b/api/restHandler/ConfigMapRestHandler.go @@ -101,7 +101,7 @@ func (handler ConfigMapRestHandlerImpl) CMGlobalAddUpdate(w http.ResponseWriter, decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var configMapRequest bean.ConfigDataRequest @@ -140,7 +140,7 @@ func (handler ConfigMapRestHandlerImpl) CMEnvironmentAddUpdate(w http.ResponseWr decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var configMapRequest bean.ConfigDataRequest @@ -185,7 +185,7 @@ func (handler ConfigMapRestHandlerImpl) CMEnvironmentAddUpdate(w http.ResponseWr func (handler ConfigMapRestHandlerImpl) CMGlobalFetch(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -218,7 +218,7 @@ func (handler ConfigMapRestHandlerImpl) CMGlobalFetch(w http.ResponseWriter, r * func (handler ConfigMapRestHandlerImpl) CMGlobalFetchForEdit(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -255,7 +255,7 @@ func (handler ConfigMapRestHandlerImpl) CMGlobalFetchForEdit(w http.ResponseWrit func (handler ConfigMapRestHandlerImpl) CMEnvironmentFetchForEdit(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -306,7 +306,7 @@ func (handler ConfigMapRestHandlerImpl) CMEnvironmentFetchForEdit(w http.Respons func (handler ConfigMapRestHandlerImpl) CMEnvironmentFetch(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -346,7 +346,7 @@ func (handler ConfigMapRestHandlerImpl) CSGlobalAddUpdate(w http.ResponseWriter, decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var configMapRequest bean.ConfigDataRequest @@ -385,7 +385,7 @@ func (handler ConfigMapRestHandlerImpl) CSEnvironmentAddUpdate(w http.ResponseWr decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var configMapRequest bean.ConfigDataRequest @@ -431,7 +431,7 @@ func (handler ConfigMapRestHandlerImpl) CSEnvironmentAddUpdate(w http.ResponseWr func (handler ConfigMapRestHandlerImpl) CSGlobalFetch(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -464,7 +464,7 @@ func (handler ConfigMapRestHandlerImpl) CSGlobalFetch(w http.ResponseWriter, r * func (handler ConfigMapRestHandlerImpl) CSEnvironmentFetch(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -503,7 +503,7 @@ func (handler ConfigMapRestHandlerImpl) CSEnvironmentFetch(w http.ResponseWriter func (handler ConfigMapRestHandlerImpl) CMGlobalDelete(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -551,7 +551,7 @@ func (handler ConfigMapRestHandlerImpl) CMGlobalDelete(w http.ResponseWriter, r func (handler ConfigMapRestHandlerImpl) CMEnvironmentDelete(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -613,7 +613,7 @@ func (handler ConfigMapRestHandlerImpl) CMEnvironmentDelete(w http.ResponseWrite func (handler ConfigMapRestHandlerImpl) CSGlobalDelete(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -661,7 +661,7 @@ func (handler ConfigMapRestHandlerImpl) CSGlobalDelete(w http.ResponseWriter, r func (handler ConfigMapRestHandlerImpl) CSEnvironmentDelete(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -723,7 +723,7 @@ func (handler ConfigMapRestHandlerImpl) CSEnvironmentDelete(w http.ResponseWrite func (handler ConfigMapRestHandlerImpl) CSGlobalFetchForEdit(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -764,7 +764,7 @@ func (handler ConfigMapRestHandlerImpl) CSGlobalFetchForEdit(w http.ResponseWrit func (handler ConfigMapRestHandlerImpl) CSEnvironmentFetchForEdit(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -820,7 +820,7 @@ func (handler ConfigMapRestHandlerImpl) ConfigSecretBulkPatch(w http.ResponseWri decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -863,7 +863,7 @@ func (handler ConfigMapRestHandlerImpl) AddEnvironmentToJob(w http.ResponseWrite decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -899,7 +899,7 @@ func (handler ConfigMapRestHandlerImpl) RemoveEnvironmentFromJob(w http.Response decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -934,7 +934,7 @@ func (handler ConfigMapRestHandlerImpl) RemoveEnvironmentFromJob(w http.Response func (handler ConfigMapRestHandlerImpl) GetEnvironmentsForJob(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) diff --git a/api/restHandler/CoreAppRestHandler.go b/api/restHandler/CoreAppRestHandler.go index d568b6961c..39e1934f00 100644 --- a/api/restHandler/CoreAppRestHandler.go +++ b/api/restHandler/CoreAppRestHandler.go @@ -261,7 +261,7 @@ func (handler CoreAppRestHandlerImpl) CreateApp(w http.ResponseWriter, r *http.R decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -2248,7 +2248,7 @@ func (handler CoreAppRestHandlerImpl) CreateAppWorkflow(w http.ResponseWriter, r decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -2326,7 +2326,7 @@ func (handler CoreAppRestHandlerImpl) GetAppWorkflow(w http.ResponseWriter, r *h userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -2382,7 +2382,7 @@ func (handler CoreAppRestHandlerImpl) GetAppWorkflowAndOverridesSample(w http.Re userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) diff --git a/api/restHandler/DeploymentGroupRestHandler.go b/api/restHandler/DeploymentGroupRestHandler.go index a9e6aa2dc9..77d592fc9b 100644 --- a/api/restHandler/DeploymentGroupRestHandler.go +++ b/api/restHandler/DeploymentGroupRestHandler.go @@ -65,7 +65,7 @@ func (impl *DeploymentGroupRestHandlerImpl) CreateDeploymentGroup(w http.Respons decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean deploymentGroup.DeploymentGroupRequest @@ -109,7 +109,7 @@ func (impl *DeploymentGroupRestHandlerImpl) CreateDeploymentGroup(w http.Respons func (impl *DeploymentGroupRestHandlerImpl) FetchParentCiForDG(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -145,7 +145,7 @@ func (impl *DeploymentGroupRestHandlerImpl) FetchParentCiForDG(w http.ResponseWr func (impl *DeploymentGroupRestHandlerImpl) FetchEnvApplicationsForDG(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -196,7 +196,7 @@ func (impl *DeploymentGroupRestHandlerImpl) FetchEnvApplicationsForDG(w http.Res func (impl *DeploymentGroupRestHandlerImpl) FetchAllDeploymentGroups(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -230,7 +230,7 @@ func (impl *DeploymentGroupRestHandlerImpl) FetchAllDeploymentGroups(w http.Resp func (impl *DeploymentGroupRestHandlerImpl) DeleteDeploymentGroup(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -270,7 +270,7 @@ func (impl *DeploymentGroupRestHandlerImpl) DeleteDeploymentGroup(w http.Respons func (impl *DeploymentGroupRestHandlerImpl) TriggerReleaseForDeploymentGroup(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean *deploymentGroup.DeploymentGroupTriggerRequest @@ -318,7 +318,7 @@ func (impl *DeploymentGroupRestHandlerImpl) UpdateDeploymentGroup(w http.Respons decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean deploymentGroup.DeploymentGroupRequest diff --git a/api/restHandler/DockerRegRestHandler.go b/api/restHandler/DockerRegRestHandler.go index f76705ba72..96e696cdeb 100644 --- a/api/restHandler/DockerRegRestHandler.go +++ b/api/restHandler/DockerRegRestHandler.go @@ -196,7 +196,7 @@ func (impl DockerRegRestHandlerImpl) SaveDockerRegistryConfig(w http.ResponseWri decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean types.DockerArtifactStoreBean @@ -295,7 +295,7 @@ func (impl DockerRegRestHandlerImpl) ValidateDockerRegistryConfig(w http.Respons decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean types.DockerArtifactStoreBean @@ -428,12 +428,21 @@ func (impl DockerRegRestHandlerExtendedImpl) FetchAllDockerAccounts(w http.Respo } func (impl DockerRegRestHandlerImpl) FetchOneDockerAccounts(w http.ResponseWriter, r *http.Request) { + // Use enhanced error response builder + errorBuilder := common.NewErrorResponseBuilder(w, r). + WithOperation("fetch docker registry"). + WithResource("docker registry", "") + params := mux.Vars(r) id := params["id"] + + // Update resource context with actual ID + errorBuilder = errorBuilder.WithResource("docker registry", id) + res, err := impl.dockerRegistryConfig.FetchOneDockerAccount(id) if err != nil { - impl.logger.Errorw("service err, FetchOneDockerAccounts", "err", err, "id", id) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + impl.logger.Errorw("Failed to fetch docker registry", "registryId", id, "err", err) + errorBuilder.HandleError(err) return } res.DisabledFields = make([]types.DisabledFields, 0) @@ -446,12 +455,13 @@ func (impl DockerRegRestHandlerImpl) FetchOneDockerAccounts(w http.ResponseWrite // RBAC enforcer applying token := r.Header.Get("token") if ok := impl.enforcer.Enforce(token, casbin.ResourceDocker, casbin.ActionGet, res.Id); !ok { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden) + impl.logger.Warnw("Unauthorized access to docker registry", "registryId", id, "userId", token) + common.HandleForbidden(w, r, "docker registry") return } //RBAC enforcer Ends - common.WriteJsonResp(w, err, res, http.StatusOK) + errorBuilder.HandleSuccess(res) } func (impl DockerRegRestHandlerExtendedImpl) FetchOneDockerAccounts(w http.ResponseWriter, r *http.Request) { @@ -488,7 +498,7 @@ func (impl DockerRegRestHandlerImpl) UpdateDockerRegistryConfig(w http.ResponseW decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean types.DockerArtifactStoreBean @@ -597,7 +607,7 @@ func (impl DockerRegRestHandlerImpl) DeleteDockerRegistryConfig(w http.ResponseW decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean types.DockerArtifactStoreBean @@ -636,7 +646,7 @@ func (impl DockerRegRestHandlerExtendedImpl) DeleteDockerRegistryConfig(w http.R decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean types.DockerArtifactStoreBean diff --git a/api/restHandler/GitHostRestHandler.go b/api/restHandler/GitHostRestHandler.go index 1aae1e6141..833f84fd1c 100644 --- a/api/restHandler/GitHostRestHandler.go +++ b/api/restHandler/GitHostRestHandler.go @@ -77,7 +77,7 @@ func (impl GitHostRestHandlerImpl) GetGitHosts(w http.ResponseWriter, r *http.Re // check if user is logged in or not userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -107,7 +107,7 @@ func (impl GitHostRestHandlerImpl) GetGitHostById(w http.ResponseWriter, r *http // check if user is logged in or not userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -136,7 +136,7 @@ func (impl GitHostRestHandlerImpl) CreateGitHost(w http.ResponseWriter, r *http. // check if user is logged in or not userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -182,7 +182,7 @@ func (impl GitHostRestHandlerImpl) GetAllWebhookEventConfig(w http.ResponseWrite // check if user is logged in or not userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -224,7 +224,7 @@ func (impl GitHostRestHandlerImpl) GetWebhookEventConfig(w http.ResponseWriter, // check if user is logged in or not userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -258,7 +258,7 @@ func (impl GitHostRestHandlerImpl) GetWebhookDataMetaConfig(w http.ResponseWrite // check if user is logged in or not userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/restHandler/GitOpsConfigRestHandler.go b/api/restHandler/GitOpsConfigRestHandler.go index 1f70424635..740e0eca1b 100644 --- a/api/restHandler/GitOpsConfigRestHandler.go +++ b/api/restHandler/GitOpsConfigRestHandler.go @@ -77,7 +77,7 @@ func (impl GitOpsConfigRestHandlerImpl) CreateGitOpsConfig(w http.ResponseWriter decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // RBAC enforcer applying @@ -116,7 +116,7 @@ func (impl GitOpsConfigRestHandlerImpl) UpdateGitOpsConfig(w http.ResponseWriter decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // RBAC enforcer applying @@ -164,7 +164,7 @@ func (impl GitOpsConfigRestHandlerImpl) GetGitOpsConfigById(w http.ResponseWrite vars := mux.Vars(r) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } id, err := strconv.Atoi(vars["id"]) @@ -194,7 +194,7 @@ func (impl GitOpsConfigRestHandlerImpl) GetGitOpsConfigById(w http.ResponseWrite func (impl GitOpsConfigRestHandlerImpl) GitOpsConfigured(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } result, err := impl.gitOpsConfigService.GetAllGitOpsConfig() @@ -223,7 +223,7 @@ func (impl GitOpsConfigRestHandlerImpl) GitOpsConfigured(w http.ResponseWriter, func (impl GitOpsConfigRestHandlerImpl) GetAllGitOpsConfig(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } result, err := impl.gitOpsConfigService.GetAllGitOpsConfig() @@ -247,7 +247,7 @@ func (impl GitOpsConfigRestHandlerImpl) GetAllGitOpsConfig(w http.ResponseWriter func (impl GitOpsConfigRestHandlerImpl) GetGitOpsConfigByProvider(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -274,7 +274,7 @@ func (impl GitOpsConfigRestHandlerImpl) GitOpsValidator(w http.ResponseWriter, r decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // RBAC enforcer applying diff --git a/api/restHandler/GitProviderRestHandler.go b/api/restHandler/GitProviderRestHandler.go index 55b7ea1bae..84c92eddf7 100644 --- a/api/restHandler/GitProviderRestHandler.go +++ b/api/restHandler/GitProviderRestHandler.go @@ -81,7 +81,7 @@ func (impl GitProviderRestHandlerImpl) SaveGitRepoConfig(w http.ResponseWriter, decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean bean.GitRegistry @@ -110,8 +110,9 @@ func (impl GitProviderRestHandlerImpl) SaveGitRepoConfig(w http.ResponseWriter, res, err := impl.gitRegistryConfig.Create(&bean) if err != nil { - impl.logger.Errorw("service err, SaveGitRepoConfig", "err", err, "payload", bean) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + impl.logger.Errorw("Failed to create git provider", "gitProviderName", bean.Name, "err", err) + // Use enhanced error response with resource context + common.WriteJsonRespWithResourceContext(w, err, nil, 0, "git provider", bean.Name) return } common.WriteJsonResp(w, err, res, http.StatusOK) @@ -120,8 +121,9 @@ func (impl GitProviderRestHandlerImpl) SaveGitRepoConfig(w http.ResponseWriter, func (impl GitProviderRestHandlerImpl) GetGitProviders(w http.ResponseWriter, r *http.Request) { res, err := impl.gitProviderReadService.GetAll() if err != nil { - impl.logger.Errorw("service err, GetGitProviders", "err", err) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + impl.logger.Errorw("Failed to get git providers", "err", err) + // Use enhanced error response for service errors + common.WriteJsonRespWithResourceContext(w, err, nil, 0, "git providers", "all") return } @@ -174,7 +176,7 @@ func (impl GitProviderRestHandlerImpl) UpdateGitRepoConfig(w http.ResponseWriter decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean bean.GitRegistry @@ -213,7 +215,7 @@ func (impl GitProviderRestHandlerImpl) DeleteGitRepoConfig(w http.ResponseWriter decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean bean.GitRegistry diff --git a/api/restHandler/GlobalCMCSRestHandler.go b/api/restHandler/GlobalCMCSRestHandler.go index 6936bafa7b..f15f7a95a6 100644 --- a/api/restHandler/GlobalCMCSRestHandler.go +++ b/api/restHandler/GlobalCMCSRestHandler.go @@ -66,7 +66,7 @@ func (handler *GlobalCMCSRestHandlerImpl) CreateGlobalCMCSConfig(w http.Response decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean pipelineBean.GlobalCMCSDto @@ -106,7 +106,7 @@ func (handler *GlobalCMCSRestHandlerImpl) UpdateGlobalCMCSDataById(w http.Respon decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean pipeline.GlobalCMCSDataUpdateDto @@ -146,7 +146,7 @@ func (handler *GlobalCMCSRestHandlerImpl) GetGlobalCMCSDataByConfigTypeAndName(w userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -174,7 +174,7 @@ func (handler *GlobalCMCSRestHandlerImpl) GetGlobalCMCSDataByConfigTypeAndName(w func (handler *GlobalCMCSRestHandlerImpl) GetAllGlobalCMCSData(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -205,7 +205,7 @@ func (handler *GlobalCMCSRestHandlerImpl) DeleteByID(w http.ResponseWriter, r *h userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") diff --git a/api/restHandler/GlobalPluginRestHandler.go b/api/restHandler/GlobalPluginRestHandler.go index 2b5ee0d9fb..36a19a9fbc 100644 --- a/api/restHandler/GlobalPluginRestHandler.go +++ b/api/restHandler/GlobalPluginRestHandler.go @@ -84,7 +84,7 @@ func (handler *GlobalPluginRestHandlerImpl) patchPlugin(w http.ResponseWriter, r decoder := json.NewDecoder(r.Body) userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var pluginDataDto bean.PluginMetadataDto @@ -115,7 +115,7 @@ func (handler *GlobalPluginRestHandlerImpl) patchPlugin(w http.ResponseWriter, r func (handler *GlobalPluginRestHandlerImpl) GetDetailedPluginInfoByPluginId(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -144,7 +144,7 @@ func (handler *GlobalPluginRestHandlerImpl) GetDetailedPluginInfoByPluginId(w ht func (handler *GlobalPluginRestHandlerImpl) GetAllDetailedPluginInfo(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // RBAC enforcer applying @@ -442,7 +442,7 @@ func (handler *GlobalPluginRestHandlerImpl) MigratePluginData(w http.ResponseWri func (handler *GlobalPluginRestHandlerImpl) CreatePlugin(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") diff --git a/api/restHandler/ImageScanRestHandler.go b/api/restHandler/ImageScanRestHandler.go index 087d53d3a4..e28c286cee 100644 --- a/api/restHandler/ImageScanRestHandler.go +++ b/api/restHandler/ImageScanRestHandler.go @@ -73,7 +73,7 @@ func NewImageScanRestHandlerImpl(logger *zap.SugaredLogger, func (impl ImageScanRestHandlerImpl) ScanExecutionList(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -209,7 +209,7 @@ func (impl ImageScanRestHandlerImpl) getAuthorisedImageScanDeployInfoIds(token s func (impl ImageScanRestHandlerImpl) FetchExecutionDetail(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } v := r.URL.Query() @@ -360,7 +360,7 @@ func (impl ImageScanRestHandlerImpl) FetchMinScanResultByAppIdAndEnvId(w http.Re func (impl ImageScanRestHandlerImpl) VulnerabilityExposure(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/restHandler/NotificationRestHandler.go b/api/restHandler/NotificationRestHandler.go index d7ddbd76ff..621d615d15 100644 --- a/api/restHandler/NotificationRestHandler.go +++ b/api/restHandler/NotificationRestHandler.go @@ -120,7 +120,7 @@ func NewNotificationRestHandlerImpl(dockerRegistryConfig pipeline.DockerRegistry func (impl NotificationRestHandlerImpl) SaveNotificationSettingsV2(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var notificationSetting beans.NotificationRequest @@ -159,7 +159,7 @@ func (impl NotificationRestHandlerImpl) SaveNotificationSettingsV2(w http.Respon func (impl NotificationRestHandlerImpl) UpdateNotificationSettings(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var notificationSetting beans.NotificationUpdateRequest @@ -219,17 +219,16 @@ func (impl NotificationRestHandlerImpl) DeleteNotificationSettings(w http.Respon } func (impl NotificationRestHandlerImpl) GetAllNotificationSettings(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - size, err := strconv.Atoi(vars["size"]) + // Use enhanced parameter parsing with context + size, err := common.ExtractIntPathParamWithContext(w, r, "size", "pagination") if err != nil { - impl.logger.Errorw("request err, GetAllNotificationSettings", "err", err, "payload", size) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } - offset, err := strconv.Atoi(vars["offset"]) + + offset, err := common.ExtractIntPathParamWithContext(w, r, "offset", "pagination") if err != nil { - impl.logger.Errorw("request err, GetAllNotificationSettings", "err", err, "payload", offset) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } @@ -265,7 +264,7 @@ func (impl NotificationRestHandlerImpl) GetAllNotificationSettings(w http.Respon func (impl NotificationRestHandlerImpl) SaveNotificationChannelConfig(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -430,7 +429,7 @@ type ChannelResponseDTO struct { func (impl NotificationRestHandlerImpl) FindAllNotificationConfig(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -518,14 +517,14 @@ func (impl NotificationRestHandlerImpl) FindAllNotificationConfig(w http.Respons func (impl NotificationRestHandlerImpl) FindSESConfig(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } - vars := mux.Vars(r) - id, err := strconv.Atoi(vars["id"]) + + // Use enhanced parameter parsing with context + id, err := common.ExtractIntPathParamWithContext(w, r, "id", "SES config") if err != nil { - impl.logger.Errorw("request err, FindSESConfig", "err", err) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } token := r.Header.Get("token") @@ -547,14 +546,14 @@ func (impl NotificationRestHandlerImpl) FindSESConfig(w http.ResponseWriter, r * func (impl NotificationRestHandlerImpl) FindSlackConfig(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } - vars := mux.Vars(r) - id, err := strconv.Atoi(vars["id"]) + + // Use enhanced parameter parsing with context + id, err := common.ExtractIntPathParamWithContext(w, r, "id", "Slack config") if err != nil { - impl.logger.Errorw("request err, FindSlackConfig", "err", err, "id", id) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } @@ -572,7 +571,7 @@ func (impl NotificationRestHandlerImpl) FindSlackConfig(w http.ResponseWriter, r func (impl NotificationRestHandlerImpl) FindSMTPConfig(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -599,7 +598,7 @@ func (impl NotificationRestHandlerImpl) FindSMTPConfig(w http.ResponseWriter, r func (impl NotificationRestHandlerImpl) FindWebhookConfig(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -623,7 +622,7 @@ func (impl NotificationRestHandlerImpl) FindWebhookConfig(w http.ResponseWriter, func (impl NotificationRestHandlerImpl) GetWebhookVariables(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -641,7 +640,7 @@ func (impl NotificationRestHandlerImpl) GetWebhookVariables(w http.ResponseWrite func (impl NotificationRestHandlerImpl) RecipientListingSuggestion(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -671,7 +670,7 @@ func (impl NotificationRestHandlerImpl) RecipientListingSuggestion(w http.Respon func (impl NotificationRestHandlerImpl) FindAllNotificationConfigAutocomplete(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -749,7 +748,7 @@ func (impl NotificationRestHandlerImpl) GetOptionsForNotificationSettings(w http decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request repository.SearchRequest @@ -783,7 +782,7 @@ func (impl NotificationRestHandlerImpl) GetOptionsForNotificationSettings(w http func (impl NotificationRestHandlerImpl) DeleteNotificationChannelConfig(w http.ResponseWriter, r *http.Request) { userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/restHandler/PProfRestHandler.go b/api/restHandler/PProfRestHandler.go index 5728602cf2..6231d8a5a0 100644 --- a/api/restHandler/PProfRestHandler.go +++ b/api/restHandler/PProfRestHandler.go @@ -55,7 +55,7 @@ func NewPProfRestHandler(userService user.UserService, func (p PProfRestHandlerImpl) Index(w http.ResponseWriter, r *http.Request) { userId, err := p.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -70,7 +70,7 @@ func (p PProfRestHandlerImpl) Index(w http.ResponseWriter, r *http.Request) { func (p PProfRestHandlerImpl) Cmdline(w http.ResponseWriter, r *http.Request) { userId, err := p.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -85,7 +85,7 @@ func (p PProfRestHandlerImpl) Cmdline(w http.ResponseWriter, r *http.Request) { func (p PProfRestHandlerImpl) Profile(w http.ResponseWriter, r *http.Request) { userId, err := p.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -100,7 +100,7 @@ func (p PProfRestHandlerImpl) Profile(w http.ResponseWriter, r *http.Request) { func (p PProfRestHandlerImpl) Symbol(w http.ResponseWriter, r *http.Request) { userId, err := p.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -115,7 +115,7 @@ func (p PProfRestHandlerImpl) Symbol(w http.ResponseWriter, r *http.Request) { func (p PProfRestHandlerImpl) Trace(w http.ResponseWriter, r *http.Request) { userId, err := p.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -130,7 +130,7 @@ func (p PProfRestHandlerImpl) Trace(w http.ResponseWriter, r *http.Request) { func (p PProfRestHandlerImpl) Goroutine(w http.ResponseWriter, r *http.Request) { userId, err := p.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -145,7 +145,7 @@ func (p PProfRestHandlerImpl) Goroutine(w http.ResponseWriter, r *http.Request) func (p PProfRestHandlerImpl) Threadcreate(w http.ResponseWriter, r *http.Request) { userId, err := p.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -160,7 +160,7 @@ func (p PProfRestHandlerImpl) Threadcreate(w http.ResponseWriter, r *http.Reques func (p PProfRestHandlerImpl) Heap(w http.ResponseWriter, r *http.Request) { userId, err := p.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -175,7 +175,7 @@ func (p PProfRestHandlerImpl) Heap(w http.ResponseWriter, r *http.Request) { func (p PProfRestHandlerImpl) Block(w http.ResponseWriter, r *http.Request) { userId, err := p.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -190,7 +190,7 @@ func (p PProfRestHandlerImpl) Block(w http.ResponseWriter, r *http.Request) { func (p PProfRestHandlerImpl) Mutex(w http.ResponseWriter, r *http.Request) { userId, err := p.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -205,7 +205,7 @@ func (p PProfRestHandlerImpl) Mutex(w http.ResponseWriter, r *http.Request) { func (p PProfRestHandlerImpl) Allocs(w http.ResponseWriter, r *http.Request) { userId, err := p.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") diff --git a/api/restHandler/PolicyRestHandler.go b/api/restHandler/PolicyRestHandler.go index 2678207843..c10ca49e68 100644 --- a/api/restHandler/PolicyRestHandler.go +++ b/api/restHandler/PolicyRestHandler.go @@ -71,7 +71,7 @@ func (impl PolicyRestHandlerImpl) SavePolicy(w http.ResponseWriter, r *http.Requ decoder := json.NewDecoder(r.Body) userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var req bean.CreateVulnerabilityPolicyRequest @@ -135,7 +135,7 @@ func (impl PolicyRestHandlerImpl) UpdatePolicy(w http.ResponseWriter, r *http.Re decoder := json.NewDecoder(r.Body) userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var req bean.UpdatePolicyParams @@ -204,7 +204,7 @@ func (impl PolicyRestHandlerImpl) UpdatePolicy(w http.ResponseWriter, r *http.Re func (impl PolicyRestHandlerImpl) GetPolicy(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } req := bean.FetchPolicyParams{} diff --git a/api/restHandler/ReleaseMetricsRestHandler.go b/api/restHandler/ReleaseMetricsRestHandler.go index f9de1c48c2..a69d4ab652 100644 --- a/api/restHandler/ReleaseMetricsRestHandler.go +++ b/api/restHandler/ReleaseMetricsRestHandler.go @@ -76,7 +76,7 @@ func (impl *ReleaseMetricsRestHandlerImpl) ResetDataForAppEnvironment(w http.Res decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var req MetricsRequest diff --git a/api/restHandler/ResourceGroupRestHandler.go b/api/restHandler/ResourceGroupRestHandler.go index 735f05d563..6a8fa991c0 100644 --- a/api/restHandler/ResourceGroupRestHandler.go +++ b/api/restHandler/ResourceGroupRestHandler.go @@ -103,7 +103,7 @@ func (handler ResourceGroupRestHandlerImpl) GetActiveResourceGroupList(w http.Re // func (handler ResourceGroupRestHandlerImpl) GetApplicationsForResourceGroup(w http.ResponseWriter, r *http.Request) { // userId, err := handler.userService.GetLoggedInUser(r) // if userId == 0 || err != nil { -// common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) +// common.HandleUnauthorized(w, r) // return // } // token := r.Header.Get("token") @@ -129,7 +129,7 @@ func (handler ResourceGroupRestHandlerImpl) CreateResourceGroup(w http.ResponseW token := r.Header.Get("token") userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -193,7 +193,7 @@ func (handler ResourceGroupRestHandlerImpl) UpdateResourceGroup(w http.ResponseW token := r.Header.Get("token") userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -266,7 +266,7 @@ func (handler ResourceGroupRestHandlerImpl) CheckResourceGroupPermissions(w http userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) diff --git a/api/restHandler/TelemetryRestHandler.go b/api/restHandler/TelemetryRestHandler.go index 4894132a87..2a16472e2a 100644 --- a/api/restHandler/TelemetryRestHandler.go +++ b/api/restHandler/TelemetryRestHandler.go @@ -65,7 +65,7 @@ func (handler TelemetryRestHandlerImpl) GetTelemetryMetaInfo(w http.ResponseWrit func (handler TelemetryRestHandlerImpl) SendTelemetryData(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) diff --git a/api/restHandler/UserAttributesRestHandler.go b/api/restHandler/UserAttributesRestHandler.go index 3a2187677b..e88dee6e5a 100644 --- a/api/restHandler/UserAttributesRestHandler.go +++ b/api/restHandler/UserAttributesRestHandler.go @@ -112,7 +112,7 @@ func (handler *UserAttributesRestHandlerImpl) PatchUserAttributes(w http.Respons func (handler *UserAttributesRestHandlerImpl) validateUserAttributesRequest(w http.ResponseWriter, r *http.Request, operation string) (*bean.UserAttributesDto, bool) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return nil, false } @@ -147,7 +147,7 @@ func (handler *UserAttributesRestHandlerImpl) validateUserAttributesRequest(w ht func (handler *UserAttributesRestHandlerImpl) GetUserAttribute(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/restHandler/WebhookEventHandler.go b/api/restHandler/WebhookEventHandler.go index 922a53ad8f..d8ca3bd844 100644 --- a/api/restHandler/WebhookEventHandler.go +++ b/api/restHandler/WebhookEventHandler.go @@ -69,23 +69,27 @@ func (impl WebhookEventHandlerImpl) OnWebhookEvent(w http.ResponseWriter, r *htt var err error var gitHostName string var gitHost *bean3.GitHostRequest + + // Try to parse gitHostId as integer first, fallback to name-based lookup if gitHostId, err = strconv.Atoi(vars["gitHostId"]); err != nil { gitHostName = vars["gitHostId"] - // get git host from DB + // get git host from DB by name gitHost, err = impl.gitHostReadService.GetByName(gitHostName) if err != nil { - impl.logger.Errorw("Error in getting git host from DB by Name", "err", err, "gitHostName", gitHostName) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + impl.logger.Errorw("Git host not found by name", "err", err, "gitHostName", gitHostName) + // Use enhanced error handling with resource context + common.WriteJsonRespWithResourceContext(w, err, nil, 0, "git host", gitHostName) return } gitHostId = gitHost.Id } else { - // get git host from DB + // get git host from DB by ID gitHost, err = impl.gitHostReadService.GetById(gitHostId) if err != nil { - impl.logger.Errorw("Error in getting git host from DB by Id", "err", err, "gitHostId", gitHostId) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + impl.logger.Errorw("Git host not found by ID", "err", err, "gitHostId", gitHostId) + // Use enhanced error handling with resource context + common.WriteJsonRespWithResourceContextFromId(w, err, nil, 0, "git host", gitHostId) return } } diff --git a/api/restHandler/app/appInfo/AppInfoRestHandler.go b/api/restHandler/app/appInfo/AppInfoRestHandler.go index e6ba47a5a8..b389ae364a 100644 --- a/api/restHandler/app/appInfo/AppInfoRestHandler.go +++ b/api/restHandler/app/appInfo/AppInfoRestHandler.go @@ -84,7 +84,7 @@ func NewAppInfoRestHandlerImpl(logger *zap.SugaredLogger, appService app.AppCrud func (handler AppInfoRestHandlerImpl) GetAllLabels(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } propagatedLabelsOnlyStr := r.URL.Query().Get("showPropagatedOnly") @@ -122,14 +122,13 @@ func (handler AppInfoRestHandlerImpl) GetAllLabels(w http.ResponseWriter, r *htt func (handler AppInfoRestHandlerImpl) GetAppMetaInfo(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } - vars := mux.Vars(r) - appId, err := strconv.Atoi(vars["appId"]) + // Use enhanced parameter parsing with context + appId, err := common.ExtractIntPathParamWithContext(w, r, "appId", "application") if err != nil { - handler.logger.Errorw("request err, GetAppMetaInfo", "err", err, "appId", appId) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } @@ -155,7 +154,7 @@ func (handler AppInfoRestHandlerImpl) GetAppMetaInfo(w http.ResponseWriter, r *h func (handler AppInfoRestHandlerImpl) GetHelmAppMetaInfo(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -208,7 +207,7 @@ func (handler AppInfoRestHandlerImpl) GetHelmAppMetaInfo(w http.ResponseWriter, func (handler AppInfoRestHandlerImpl) UpdateApp(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -262,7 +261,7 @@ func (handler AppInfoRestHandlerImpl) UpdateApp(w http.ResponseWriter, r *http.R func (handler AppInfoRestHandlerImpl) UpdateProjectForApps(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -306,7 +305,7 @@ func (handler AppInfoRestHandlerImpl) UpdateProjectForApps(w http.ResponseWriter func (handler AppInfoRestHandlerImpl) GetAppListByTeamIds(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } //vars := mux.Vars(r) @@ -349,7 +348,7 @@ func (handler AppInfoRestHandlerImpl) UpdateAppNote(w http.ResponseWriter, r *ht userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { handler.logger.Errorw("service err, Update", "error", err, "userId", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean repository.GenericNote diff --git a/api/restHandler/app/appList/AppFilteringRestHandler.go b/api/restHandler/app/appList/AppFilteringRestHandler.go index bff8f84a06..ba28ef4d92 100644 --- a/api/restHandler/app/appList/AppFilteringRestHandler.go +++ b/api/restHandler/app/appList/AppFilteringRestHandler.go @@ -82,7 +82,7 @@ func NewAppFilteringRestHandlerImpl(logger *zap.SugaredLogger, func (handler AppFilteringRestHandlerImpl) GetClusterTeamAndEnvListForAutocomplete(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } clusterMapping := make(map[string]bean3.ClusterBean) diff --git a/api/restHandler/app/appList/AppListingRestHandler.go b/api/restHandler/app/appList/AppListingRestHandler.go index 8f52a64b9c..8c15bee342 100644 --- a/api/restHandler/app/appList/AppListingRestHandler.go +++ b/api/restHandler/app/appList/AppListingRestHandler.go @@ -149,7 +149,7 @@ func (handler AppListingRestHandlerImpl) FetchAllDevtronManagedApps(w http.Respo token := r.Header.Get("token") userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } handler.logger.Infow("got request to fetch all devtron managed apps ", "userId", userId) @@ -168,7 +168,7 @@ func (handler AppListingRestHandlerImpl) FetchJobs(w http.ResponseWriter, r *htt userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { handler.logger.Errorw("request err, userId", "err", err, "payload", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -241,7 +241,7 @@ func (handler AppListingRestHandlerImpl) FetchJobOverviewCiPipelines(w http.Resp userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { handler.logger.Errorw("request err, userId", "err", err, "payload", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -287,7 +287,7 @@ func (handler AppListingRestHandlerImpl) FetchAppsByEnvironmentV2(w http.Respons userId, err := handler.userService.GetLoggedInUser(r) span.End() if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } newCtx, span = otel.Tracer("userService").Start(newCtx, "GetById") @@ -411,7 +411,7 @@ func (handler AppListingRestHandlerImpl) FetchOverviewAppsByEnvironment(w http.R vars := mux.Vars(r) userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -475,7 +475,7 @@ func (handler AppListingRestHandlerImpl) FetchOverviewAppsByEnvironment(w http.R func (handler AppListingRestHandlerImpl) FetchAppDetailsV2(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) diff --git a/api/restHandler/app/configDiff/DeploymentConfigurationRestHandler.go b/api/restHandler/app/configDiff/DeploymentConfigurationRestHandler.go index b7030aa496..bf6b099ef2 100644 --- a/api/restHandler/app/configDiff/DeploymentConfigurationRestHandler.go +++ b/api/restHandler/app/configDiff/DeploymentConfigurationRestHandler.go @@ -50,7 +50,7 @@ func NewDeploymentConfigurationRestHandlerImpl(logger *zap.SugaredLogger, func (handler *DeploymentConfigurationRestHandlerImpl) ConfigAutoComplete(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } appId, err := common.ExtractIntQueryParam(w, r, "appId", 0) @@ -84,7 +84,7 @@ func (handler *DeploymentConfigurationRestHandlerImpl) ConfigAutoComplete(w http func (handler *DeploymentConfigurationRestHandlerImpl) GetConfigData(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } configDataQueryParams, err := getConfigDataQueryParams(r) @@ -122,7 +122,7 @@ func (handler *DeploymentConfigurationRestHandlerImpl) GetConfigData(w http.Resp func (handler *DeploymentConfigurationRestHandlerImpl) GetManifest(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -191,7 +191,7 @@ func getConfigDataQueryParams(r *http.Request) (*bean.ConfigDataQueryParams, err func (handler *DeploymentConfigurationRestHandlerImpl) CompareCategoryWiseConfigData(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) diff --git a/api/restHandler/app/pipeline/AutoCompleteRestHandler.go b/api/restHandler/app/pipeline/AutoCompleteRestHandler.go index 8bae0d4b8e..ee4895af9a 100644 --- a/api/restHandler/app/pipeline/AutoCompleteRestHandler.go +++ b/api/restHandler/app/pipeline/AutoCompleteRestHandler.go @@ -85,7 +85,7 @@ func NewDevtronAppAutoCompleteRestHandlerImpl( func (handler DevtronAppAutoCompleteRestHandlerImpl) GetAppListForAutocomplete(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -244,10 +244,10 @@ func (handler DevtronAppAutoCompleteRestHandlerImpl) GitListAutocomplete(w http. func (handler DevtronAppAutoCompleteRestHandlerImpl) RegistriesListAutocomplete(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("token") - vars := mux.Vars(r) - appId, err := strconv.Atoi(vars["appId"]) + // Use enhanced parameter parsing with context + appId, err := common.ExtractIntPathParamWithContext(w, r, "appId", "application") if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } v := r.URL.Query() diff --git a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go index ae0162995a..dded6fd4a2 100644 --- a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go +++ b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go @@ -241,7 +241,7 @@ func (handler *PipelineConfigRestHandlerImpl) UpdateBranchCiPipelinesWithRegex(w func (handler *PipelineConfigRestHandlerImpl) parseSourceChangeRequest(w http.ResponseWriter, r *http.Request) (*bean.CiMaterialPatchRequest, int32, error) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return nil, 0, err } @@ -260,7 +260,7 @@ func (handler *PipelineConfigRestHandlerImpl) parseSourceChangeRequest(w http.Re func (handler *PipelineConfigRestHandlerImpl) parseBulkSourceChangeRequest(w http.ResponseWriter, r *http.Request) (*bean.CiMaterialBulkPatchRequest, int32, error) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return nil, 0, err } @@ -359,7 +359,7 @@ func (handler *PipelineConfigRestHandlerImpl) PatchCiPipelines(w http.ResponseWr decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var patchRequest bean.CiPatchRequest @@ -1003,7 +1003,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetHistoricBuildLogs(w http.Respon func (handler *PipelineConfigRestHandlerImpl) GetBuildHistory(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -1090,7 +1090,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetBuildHistory(w http.ResponseWri func (handler *PipelineConfigRestHandlerImpl) GetBuildLogs(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -1169,7 +1169,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetBuildLogs(w http.ResponseWriter func (handler *PipelineConfigRestHandlerImpl) FetchMaterialInfo(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -1332,7 +1332,7 @@ func (handler *PipelineConfigRestHandlerImpl) CreateMaterial(w http.ResponseWrit decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var createMaterialDto bean.CreateMaterialDTO @@ -1385,7 +1385,7 @@ func (handler *PipelineConfigRestHandlerImpl) UpdateMaterial(w http.ResponseWrit decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var updateMaterialDto bean.UpdateMaterialDTO @@ -1435,7 +1435,7 @@ func (handler *PipelineConfigRestHandlerImpl) DeleteMaterial(w http.ResponseWrit decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var deleteMaterial bean.UpdateMaterialDTO @@ -1518,7 +1518,7 @@ func (handler *PipelineConfigRestHandlerImpl) ValidateGitMaterialUrl(gitProvider func (handler *PipelineConfigRestHandlerImpl) CancelWorkflow(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } queryVars := r.URL.Query() @@ -1602,7 +1602,7 @@ func (handler *PipelineConfigRestHandlerImpl) CancelWorkflow(w http.ResponseWrit func (handler *PipelineConfigRestHandlerImpl) FetchChanges(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -1660,7 +1660,7 @@ func (handler *PipelineConfigRestHandlerImpl) FetchChanges(w http.ResponseWriter func (handler *PipelineConfigRestHandlerImpl) GetCommitMetadataForPipelineMaterial(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -1706,7 +1706,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetCommitMetadataForPipelineMateri func (handler *PipelineConfigRestHandlerImpl) FetchWorkflowDetails(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -1757,7 +1757,7 @@ func (handler *PipelineConfigRestHandlerImpl) FetchWorkflowDetails(w http.Respon func (handler *PipelineConfigRestHandlerImpl) GetArtifactsForCiJob(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -1804,7 +1804,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetCiPipelineByEnvironment(w http. token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } envId, err := strconv.Atoi(vars["envId"]) @@ -1862,7 +1862,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetCiPipelineByEnvironmentMin(w ht token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } envId, err := strconv.Atoi(vars["envId"]) @@ -1919,7 +1919,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetExternalCiByEnvironment(w http. token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } envId, err := strconv.Atoi(vars["envId"]) @@ -1976,7 +1976,7 @@ func (handler *PipelineConfigRestHandlerImpl) CreateUpdateImageTagging(w http.Re token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } isSuperAdmin := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionCreate, "*") @@ -2069,7 +2069,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetImageTaggingData(w http.Respons token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } artifactId, err := strconv.Atoi(vars["artifactId"]) @@ -2181,7 +2181,7 @@ func (handler *PipelineConfigRestHandlerImpl) checkAppSpecificAccess(token, acti func (handler *PipelineConfigRestHandlerImpl) GetSourceCiDownStreamFilters(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -2218,7 +2218,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetSourceCiDownStreamInfo(w http.R decoder := schema.NewDecoder() userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -2274,7 +2274,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetAppMetadataListByEnvironment(w token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } envId, err := strconv.Atoi(vars["envId"]) diff --git a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandlerHelper.go b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandlerHelper.go index d3bbd75d0f..cd06626581 100644 --- a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandlerHelper.go +++ b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandlerHelper.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" + "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/bean" "net/http" @@ -33,18 +34,27 @@ import ( func (handler *PipelineConfigRestHandlerImpl) getUserIdOrUnauthorized(w http.ResponseWriter, r *http.Request) (int32, bool) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return 0, false } return userId, true } // getIntPathParam gets an integer path parameter from the request +// DEPRECATED: Use common.ExtractIntPathParamWithContext() for new code func (handler *PipelineConfigRestHandlerImpl) getIntPathParam(w http.ResponseWriter, vars map[string]string, paramName string) (int, bool) { paramValue, err := strconv.Atoi(vars[paramName]) if err != nil { - handler.Logger.Errorw("request err, invalid path param", "err", err, "paramName", paramName) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Use enhanced error handling + apiErr := util.NewInvalidPathParameterError(paramName, vars[paramName]) + handler.Logger.Errorw("Invalid path parameter", "paramName", paramName, "paramValue", vars[paramName], "err", err) + common.WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) + return 0, false + } + if paramValue <= 0 { + apiErr := util.NewValidationErrorForField(paramName, "must be a positive integer") + handler.Logger.Errorw("Invalid path parameter value", "paramName", paramName, "paramValue", paramValue) + common.WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) return 0, false } return paramValue, true diff --git a/api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go b/api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go index 04124d8221..552027152b 100644 --- a/api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go +++ b/api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go @@ -127,7 +127,7 @@ func (handler *PipelineConfigRestHandlerImpl) ConfigureDeploymentTemplateForApp( decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var templateRequest bean3.TemplateRequest @@ -194,7 +194,7 @@ func (handler *PipelineConfigRestHandlerImpl) CreateCdPipeline(w http.ResponseWr decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var cdPipeline bean.CdPipelines @@ -280,7 +280,7 @@ func (handler *PipelineConfigRestHandlerImpl) PatchCdPipeline(w http.ResponseWri decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var cdPipeline bean.CDPatchRequest @@ -373,7 +373,7 @@ func (handler *PipelineConfigRestHandlerImpl) HandleChangeDeploymentRequest(w ht // Auth check userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -436,7 +436,7 @@ func (handler *PipelineConfigRestHandlerImpl) HandleChangeDeploymentTypeRequest( userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -491,7 +491,7 @@ func (handler *PipelineConfigRestHandlerImpl) HandleTriggerDeploymentAfterTypeCh userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -548,7 +548,7 @@ func (handler *PipelineConfigRestHandlerImpl) HandleTriggerDeploymentAfterTypeCh func (handler *PipelineConfigRestHandlerImpl) ChangeChartRef(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -618,7 +618,7 @@ func (handler *PipelineConfigRestHandlerImpl) ChangeChartRef(w http.ResponseWrit func (handler *PipelineConfigRestHandlerImpl) EnvConfigOverrideCreate(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -696,7 +696,7 @@ func (handler *PipelineConfigRestHandlerImpl) EnvConfigOverrideUpdate(w http.Res // userId := getLoggedInUser(r) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var envConfigProperties pipelineBean.EnvironmentProperties @@ -810,7 +810,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetTemplateComparisonMetadata(w ht vars := mux.Vars(r) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -865,7 +865,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetDeploymentTemplateData(w http.R userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { handler.Logger.Errorw("request err, userId", "err", err, "payload", userId) - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } isSuperAdmin := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*") @@ -887,7 +887,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetDeploymentTemplateData(w http.R func (handler *PipelineConfigRestHandlerImpl) GetRestartWorkloadData(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } envId, err := common.ExtractIntQueryParam(w, r, "envId", 0) @@ -1097,7 +1097,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetArtifactsByCDPipeline(w http.Re token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -1297,7 +1297,7 @@ func (handler *PipelineConfigRestHandlerImpl) UpdateAppOverride(w http.ResponseW decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -1363,7 +1363,7 @@ func (handler *PipelineConfigRestHandlerImpl) UpdateAppOverride(w http.ResponseW func (handler *PipelineConfigRestHandlerImpl) GetArtifactsForRollback(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -1449,7 +1449,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetArtifactsForRollback(w http.Res func (handler *PipelineConfigRestHandlerImpl) EnvConfigOverrideReset(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -1508,7 +1508,7 @@ func (handler *PipelineConfigRestHandlerImpl) EnvConfigOverrideReset(w http.Resp func (handler *PipelineConfigRestHandlerImpl) ListDeploymentHistory(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -1583,7 +1583,7 @@ func (handler *PipelineConfigRestHandlerImpl) ListDeploymentHistory(w http.Respo func (handler *PipelineConfigRestHandlerImpl) GetPrePostDeploymentLogs(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -1667,7 +1667,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetPrePostDeploymentLogs(w http.Re func (handler *PipelineConfigRestHandlerImpl) FetchCdWorkflowDetails(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -1719,7 +1719,7 @@ func (handler *PipelineConfigRestHandlerImpl) FetchCdWorkflowDetails(w http.Resp func (handler *PipelineConfigRestHandlerImpl) DownloadArtifacts(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -1779,7 +1779,7 @@ func (handler *PipelineConfigRestHandlerImpl) DownloadArtifacts(w http.ResponseW func (handler *PipelineConfigRestHandlerImpl) GetStageStatus(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -1826,7 +1826,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetStageStatus(w http.ResponseWrit func (handler *PipelineConfigRestHandlerImpl) GetConfigmapSecretsForDeploymentStages(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -1898,7 +1898,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetCdPipelineById(w http.ResponseW func (handler *PipelineConfigRestHandlerImpl) CancelStage(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -2013,7 +2013,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetDefaultDeploymentPipelineStrate func (handler *PipelineConfigRestHandlerImpl) EnvConfigOverrideCreateNamespace(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -2106,7 +2106,7 @@ func (handler *PipelineConfigRestHandlerImpl) IsReadyToTrigger(w http.ResponseWr func (handler *PipelineConfigRestHandlerImpl) UpgradeForAllApps(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -2211,7 +2211,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetCdPipelinesByEnvironment(w http token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } envId, err := strconv.Atoi(vars["envId"]) @@ -2268,7 +2268,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetCdPipelinesByEnvironmentMin(w h vars := mux.Vars(r) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -2339,7 +2339,7 @@ func (handler *PipelineConfigRestHandlerImpl) SaveGitOpsConfiguration(w http.Res decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var appGitOpsConfigRequest devtronAppGitOpConfigBean.AppGitOpsConfigRequest @@ -2387,7 +2387,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetGitOpsConfiguration(w http.Resp userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -2446,7 +2446,7 @@ func (handler *PipelineConfigRestHandlerImpl) ValidateExternalAppLinkRequest(w h decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var request pipelineBean.MigrateReleaseValidationRequest diff --git a/api/restHandler/app/pipeline/configure/PipelineConfigRestHandler.go b/api/restHandler/app/pipeline/configure/PipelineConfigRestHandler.go index 74ecde9387..ab8a097f6f 100644 --- a/api/restHandler/app/pipeline/configure/PipelineConfigRestHandler.go +++ b/api/restHandler/app/pipeline/configure/PipelineConfigRestHandler.go @@ -241,7 +241,7 @@ func (handler *PipelineConfigRestHandlerImpl) DeleteApp(w http.ResponseWriter, r token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -283,7 +283,7 @@ func (handler *PipelineConfigRestHandlerImpl) DeleteACDAppWithNonCascade(w http. token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -358,7 +358,7 @@ func (handler *PipelineConfigRestHandlerImpl) CreateApp(w http.ResponseWriter, r decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var createRequest bean.CreateAppDTO @@ -591,7 +591,7 @@ func (handler *PipelineConfigRestHandlerImpl) sendData(event []byte, w http.Resp func (handler *PipelineConfigRestHandlerImpl) FetchAppWorkflowStatusForTriggerView(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -691,7 +691,7 @@ func (handler *PipelineConfigRestHandlerImpl) FetchAppWorkflowStatusForTriggerVi token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -808,7 +808,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetApplicationsByEnvironment(w htt token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } envId, err := strconv.Atoi(vars["envId"]) @@ -862,7 +862,7 @@ func (handler *PipelineConfigRestHandlerImpl) FetchAppDeploymentStatusForEnviron token := r.Header.Get("token") userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) diff --git a/api/restHandler/app/pipeline/history/PipelineHistoryRestHandler.go b/api/restHandler/app/pipeline/history/PipelineHistoryRestHandler.go index 7a759af09c..d454cb4452 100644 --- a/api/restHandler/app/pipeline/history/PipelineHistoryRestHandler.go +++ b/api/restHandler/app/pipeline/history/PipelineHistoryRestHandler.go @@ -79,7 +79,7 @@ func NewPipelineHistoryRestHandlerImpl(logger *zap.SugaredLogger, userAuthServic func (handler *PipelineHistoryRestHandlerImpl) FetchDeployedConfigurationsForWorkflow(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -124,7 +124,7 @@ func (handler *PipelineHistoryRestHandlerImpl) FetchDeployedConfigurationsForWor func (handler *PipelineHistoryRestHandlerImpl) FetchDeployedHistoryComponentList(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -183,7 +183,7 @@ func (handler *PipelineHistoryRestHandlerImpl) FetchDeployedHistoryComponentList func (handler *PipelineHistoryRestHandlerImpl) FetchDeployedHistoryComponentDetail(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -246,7 +246,7 @@ func (handler *PipelineHistoryRestHandlerImpl) FetchDeployedHistoryComponentDeta func (handler *PipelineHistoryRestHandlerImpl) GetAllDeployedConfigurationHistoryForLatestWfrIdForPipeline(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -290,7 +290,7 @@ func (handler *PipelineHistoryRestHandlerImpl) GetAllDeployedConfigurationHistor // trigger is mapped by wfr (help for method name) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) diff --git a/api/restHandler/app/pipeline/status/PipelineStatusTimelineRestHandler.go b/api/restHandler/app/pipeline/status/PipelineStatusTimelineRestHandler.go index 0d1f5cc6a0..1ab1865af1 100644 --- a/api/restHandler/app/pipeline/status/PipelineStatusTimelineRestHandler.go +++ b/api/restHandler/app/pipeline/status/PipelineStatusTimelineRestHandler.go @@ -117,7 +117,7 @@ func (handler *PipelineStatusTimelineRestHandlerImpl) ManualSyncAcdPipelineDeplo vars := mux.Vars(r) userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } appId, err := strconv.Atoi(vars["appId"]) diff --git a/api/restHandler/app/pipeline/trigger/PipelineTriggerRestHandler.go b/api/restHandler/app/pipeline/trigger/PipelineTriggerRestHandler.go index d7a7e1015f..6adbe072ec 100644 --- a/api/restHandler/app/pipeline/trigger/PipelineTriggerRestHandler.go +++ b/api/restHandler/app/pipeline/trigger/PipelineTriggerRestHandler.go @@ -113,7 +113,7 @@ func (handler PipelineTriggerRestHandlerImpl) OverrideConfig(w http.ResponseWrit decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var overrideRequest bean.ValuesOverrideRequest @@ -163,7 +163,7 @@ func (handler PipelineTriggerRestHandlerImpl) RotatePods(w http.ResponseWriter, decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var podRotateRequest bean2.PodRotateRequest @@ -212,7 +212,7 @@ func (handler PipelineTriggerRestHandlerImpl) StartStopApp(w http.ResponseWriter decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var overrideRequest bean2.StopAppRequest @@ -266,7 +266,7 @@ func (handler PipelineTriggerRestHandlerImpl) StartStopDeploymentGroup(w http.Re userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var stopDeploymentGroupRequest bean4.StopDeploymentGroupRequest @@ -325,7 +325,7 @@ func (handler PipelineTriggerRestHandlerImpl) ReleaseStatusUpdate(w http.Respons decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var releaseStatusUpdateRequest bean.ReleaseStatusUpdateRequest @@ -354,7 +354,7 @@ func (handler PipelineTriggerRestHandlerImpl) ReleaseStatusUpdate(w http.Respons func (handler PipelineTriggerRestHandlerImpl) GetAllLatestDeploymentConfiguration(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } handler.logger.Infow("request payload, GetAllLatestDeploymentConfiguration") diff --git a/api/restHandler/app/pipeline/webhook/WebhookDataRestHandler.go b/api/restHandler/app/pipeline/webhook/WebhookDataRestHandler.go index b0cf40a3a2..bd05afb624 100644 --- a/api/restHandler/app/pipeline/webhook/WebhookDataRestHandler.go +++ b/api/restHandler/app/pipeline/webhook/WebhookDataRestHandler.go @@ -65,7 +65,7 @@ func (impl WebhookDataRestHandlerImpl) GetWebhookPayloadDataForPipelineMaterialI userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } @@ -134,7 +134,7 @@ func (impl WebhookDataRestHandlerImpl) GetWebhookPayloadFilterDataForPipelineMat userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/restHandler/app/workflow/AppWorkflowRestHandler.go b/api/restHandler/app/workflow/AppWorkflowRestHandler.go index b4251d2630..bcad863c97 100644 --- a/api/restHandler/app/workflow/AppWorkflowRestHandler.go +++ b/api/restHandler/app/workflow/AppWorkflowRestHandler.go @@ -306,7 +306,7 @@ func (impl AppWorkflowRestHandlerImpl) FindAllWorkflowsForApps(w http.ResponseWr decoder := json.NewDecoder(r.Body) userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } token := r.Header.Get("token") @@ -337,7 +337,7 @@ func (impl AppWorkflowRestHandlerImpl) FindAppWorkflowByEnvironment(w http.Respo token := r.Header.Get("token") userId, err := impl.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/restHandler/common/EnhancedErrorResponse.go b/api/restHandler/common/EnhancedErrorResponse.go new file mode 100644 index 0000000000..d70109adc0 --- /dev/null +++ b/api/restHandler/common/EnhancedErrorResponse.go @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2024. Devtron Inc. + * + * Licensed 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. + */ + +package common + +import ( + "fmt" + "github.com/devtron-labs/devtron/api/middleware" + "github.com/devtron-labs/devtron/internal/util" + "net/http" + "strconv" +) + +// ErrorResponseBuilder provides a fluent interface for building error responses +type ErrorResponseBuilder struct { + request *http.Request + writer http.ResponseWriter + operation string + resourceType string + resourceID string +} + +// NewErrorResponseBuilder creates a new error response builder +func NewErrorResponseBuilder(w http.ResponseWriter, r *http.Request) *ErrorResponseBuilder { + // Try to extract resource context from request + reqCtx := middleware.GetRequestContext(r) + resourceType := "" + resourceID := "" + + if reqCtx != nil { + resourceType = reqCtx.ResourceType + resourceID = reqCtx.ResourceID + } + + return &ErrorResponseBuilder{ + request: r, + writer: w, + resourceType: resourceType, + resourceID: resourceID, + } +} + +// WithOperation sets the operation context for better error messages +func (erb *ErrorResponseBuilder) WithOperation(operation string) *ErrorResponseBuilder { + erb.operation = operation + return erb +} + +// WithResource sets the resource context for better error messages +func (erb *ErrorResponseBuilder) WithResource(resourceType, resourceID string) *ErrorResponseBuilder { + erb.resourceType = resourceType + erb.resourceID = resourceID + return erb +} + +// WithResourceFromId sets the resource context with an integer ID +func (erb *ErrorResponseBuilder) WithResourceFromId(resourceType string, resourceID int) *ErrorResponseBuilder { + erb.resourceType = resourceType + erb.resourceID = strconv.Itoa(resourceID) + return erb +} + +// HandleError processes an error and writes an appropriate response +func (erb *ErrorResponseBuilder) HandleError(err error) { + if err == nil { + return + } + + // If it's already an ApiError, use it directly + if apiErr, ok := err.(*util.ApiError); ok { + WriteJsonResp(erb.writer, apiErr, nil, apiErr.HttpStatusCode) + return + } + + // Handle database errors + if util.IsErrNoRows(err) { + if erb.resourceType != "" && erb.resourceID != "" { + apiErr := util.NewResourceNotFoundError(erb.resourceType, erb.resourceID) + WriteJsonResp(erb.writer, apiErr, nil, apiErr.HttpStatusCode) + } else { + apiErr := util.NewGenericResourceNotFoundError() + WriteJsonResp(erb.writer, apiErr, nil, apiErr.HttpStatusCode) + } + return + } + + // Handle validation errors + if isValidationError(err) { + apiErr := util.NewApiError(http.StatusBadRequest, "Validation failed", err.Error()). + WithCode("11004") + WriteJsonResp(erb.writer, apiErr, nil, apiErr.HttpStatusCode) + return + } + + // Handle business logic errors (check for common patterns) + if isBusinessLogicError(err) { + apiErr := util.NewApiError(http.StatusConflict, "Operation failed", err.Error()). + WithCode("11008") + WriteJsonResp(erb.writer, apiErr, nil, apiErr.HttpStatusCode) + return + } + + // Default to internal server error + operation := erb.operation + if operation == "" { + operation = "operation" + } + + apiErr := util.NewApiError(http.StatusInternalServerError, + fmt.Sprintf("Internal server error during %s", operation), + err.Error()).WithCode("11009") + WriteJsonResp(erb.writer, apiErr, nil, apiErr.HttpStatusCode) +} + +// HandleSuccess writes a successful response +func (erb *ErrorResponseBuilder) HandleSuccess(data interface{}) { + WriteJsonResp(erb.writer, nil, data, http.StatusOK) +} + +// isValidationError checks if the error is a validation error +func isValidationError(err error) bool { + errMsg := err.Error() + // Common validation error patterns + validationPatterns := []string{ + "validation failed", + "invalid input", + "required field", + "invalid format", + "constraint violation", + } + + for _, pattern := range validationPatterns { + if contains(errMsg, pattern) { + return true + } + } + return false +} + +// isBusinessLogicError checks if the error is a business logic error +func isBusinessLogicError(err error) bool { + errMsg := err.Error() + // Common business logic error patterns + businessPatterns := []string{ + "already exists", + "duplicate", + "conflict", + "not allowed", + "permission denied", + "unauthorized", + "forbidden", + } + + for _, pattern := range businessPatterns { + if contains(errMsg, pattern) { + return true + } + } + return false +} + +// contains checks if a string contains a substring (case-insensitive) +func contains(s, substr string) bool { + return len(s) >= len(substr) && + (s == substr || + (len(s) > len(substr) && + (s[:len(substr)] == substr || + s[len(s)-len(substr):] == substr || + containsSubstring(s, substr)))) +} + +// containsSubstring checks if a string contains a substring anywhere +func containsSubstring(s, substr string) bool { + for i := 0; i <= len(s)-len(substr); i++ { + if s[i:i+len(substr)] == substr { + return true + } + } + return false +} + +// Convenience functions for common error scenarios + +// HandleParameterError handles path parameter validation errors +func HandleParameterError(w http.ResponseWriter, r *http.Request, paramName, paramValue string) { + apiErr := util.NewInvalidPathParameterError(paramName, paramValue) + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} + +// HandleResourceNotFound handles resource not found errors +func HandleResourceNotFound(w http.ResponseWriter, r *http.Request, resourceType, resourceID string) { + apiErr := util.NewResourceNotFoundError(resourceType, resourceID) + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} + +// HandleUnauthorized handles unauthorized access errors +func HandleUnauthorized(w http.ResponseWriter, r *http.Request) { + apiErr := util.NewApiError(http.StatusUnauthorized, "Unauthorized access", "unauthorized"). + WithCode("11010") + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} + +// HandleForbidden handles forbidden access errors +func HandleForbidden(w http.ResponseWriter, r *http.Request, resource string) { + apiErr := util.NewApiError(http.StatusForbidden, + fmt.Sprintf("Access denied for %s", resource), + "forbidden").WithCode("11011") + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} + +// HandleValidationError handles validation errors +func HandleValidationError(w http.ResponseWriter, r *http.Request, fieldName, message string) { + apiErr := util.NewValidationErrorForField(fieldName, message) + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} diff --git a/api/restHandler/common/ParamParserUtils.go b/api/restHandler/common/ParamParserUtils.go index e4e60328e2..0d7b93c8ff 100644 --- a/api/restHandler/common/ParamParserUtils.go +++ b/api/restHandler/common/ParamParserUtils.go @@ -17,6 +17,7 @@ package common import ( + "github.com/devtron-labs/devtron/internal/util" "github.com/gorilla/mux" "net/http" "strconv" @@ -35,6 +36,17 @@ func ExtractIntPathParam(w http.ResponseWriter, r *http.Request, paramName strin return paramIntValue, nil } +// ExtractIntPathParamWithContext provides enhanced error messages with resource context +func ExtractIntPathParamWithContext(w http.ResponseWriter, r *http.Request, paramName string, resourceType string) (int, error) { + vars := mux.Vars(r) + paramValue := vars[paramName] + paramIntValue, err := convertToIntWithContext(w, paramValue, paramName, resourceType) + if err != nil { + return 0, err + } + return paramIntValue, nil +} + func convertToInt(w http.ResponseWriter, paramValue string) (int, error) { paramIntValue, err := strconv.Atoi(paramValue) if err != nil { @@ -44,6 +56,30 @@ func convertToInt(w http.ResponseWriter, paramValue string) (int, error) { return paramIntValue, nil } +// convertToIntWithContext provides better error messages for parameter conversion +func convertToIntWithContext(w http.ResponseWriter, paramValue, paramName, resourceType string) (int, error) { + if paramValue == "" { + apiErr := util.NewMissingRequiredFieldError(paramName) + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) + return 0, apiErr + } + + paramIntValue, err := strconv.Atoi(paramValue) + if err != nil { + apiErr := util.NewInvalidPathParameterError(paramName, paramValue) + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) + return 0, apiErr + } + + if paramIntValue <= 0 { + apiErr := util.NewValidationErrorForField(paramName, "must be a positive integer") + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) + return 0, apiErr + } + + return paramIntValue, nil +} + func convertToIntArray(paramValue string) ([]int, error) { var paramValues []int splittedParamValues := strings.Split(paramValue, ",") diff --git a/api/restHandler/common/ResourceContextExtractor.go b/api/restHandler/common/ResourceContextExtractor.go new file mode 100644 index 0000000000..623e8bc02a --- /dev/null +++ b/api/restHandler/common/ResourceContextExtractor.go @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024. Devtron Inc. + * + * Licensed 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. + */ + +package common + +import ( + "fmt" + "github.com/devtron-labs/devtron/internal/util" + "net/http" + "strconv" + "strings" +) + +// extractResourceContext tries to extract resource type and ID from response body +func extractResourceContext(respBody interface{}) (resourceType, resourceId string) { + // Try to extract from response body if it contains context + if respBody == nil { + return "", "" + } + + // Check if respBody is a map with resource context + if contextMap, ok := respBody.(map[string]interface{}); ok { + if rt, exists := contextMap["resourceType"]; exists { + resourceType = fmt.Sprintf("%v", rt) + } + if ri, exists := contextMap["resourceId"]; exists { + resourceId = fmt.Sprintf("%v", ri) + } + } + + return resourceType, resourceId +} + +// WriteJsonRespWithResourceContext enhances error response with resource context +// This function provides better error messages for database errors by including resource context +func WriteJsonRespWithResourceContext(w http.ResponseWriter, err error, respBody interface{}, + status int, resourceType, resourceId string) { + + if err != nil && util.IsErrNoRows(err) { + // Override respBody with resource context for better error handling + respBody = map[string]interface{}{ + "resourceType": resourceType, + "resourceId": resourceId, + } + } + WriteJsonResp(w, err, respBody, status) +} + +// WriteJsonRespWithResourceContextFromId is a convenience function for integer IDs +func WriteJsonRespWithResourceContextFromId(w http.ResponseWriter, err error, respBody interface{}, + status int, resourceType string, resourceId int) { + WriteJsonRespWithResourceContext(w, err, respBody, status, resourceType, strconv.Itoa(resourceId)) +} + +// Convenience functions for common error scenarios (to fix build errors) +func WriteMissingRequiredFieldError(w http.ResponseWriter, fieldName string) { + apiErr := util.NewMissingRequiredFieldError(fieldName) + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} + +func WriteForbiddenError(w http.ResponseWriter, operation string, resource string) { + apiErr := util.NewApiError(http.StatusForbidden, + fmt.Sprintf("Access denied for %s operation on %s", operation, resource), + "forbidden").WithCode("11008") + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} + +func WriteValidationError(w http.ResponseWriter, fieldName string, message string) { + apiErr := util.NewValidationErrorForField(fieldName, message) + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} + +func WriteSpecificErrorResponse(w http.ResponseWriter, errorCode string, message string, details []string, statusCode int) { + apiErr := util.NewApiError(statusCode, message, fmt.Sprintf("Error: %s", errorCode)). + WithCode(errorCode). + WithUserDetailMessage(fmt.Sprintf("Details: %s", strings.Join(details, "; "))) + WriteJsonResp(w, apiErr, nil, statusCode) +} + +func WritePipelineNotFoundError(w http.ResponseWriter, pipelineId int) { + apiErr := util.NewResourceNotFoundError("pipeline", strconv.Itoa(pipelineId)) + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} + +func WriteDatabaseError(w http.ResponseWriter, operation string, err error) { + apiErr := util.NewApiError(http.StatusInternalServerError, + fmt.Sprintf("Database operation failed: %s", operation), + err.Error()).WithCode("11009") + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} + +func WriteUnauthorizedError(w http.ResponseWriter) { + apiErr := util.NewApiError(http.StatusUnauthorized, "Unauthorized access", "unauthorized"). + WithCode("11010") + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} + +func WriteInvalidAppIdError(w http.ResponseWriter, appId string) { + apiErr := util.NewInvalidPathParameterError("appId", appId) + WriteJsonResp(w, apiErr, nil, apiErr.HttpStatusCode) +} diff --git a/api/restHandler/common/apiError.go b/api/restHandler/common/apiError.go index 7c1d4755c8..1ba6693827 100644 --- a/api/restHandler/common/apiError.go +++ b/api/restHandler/common/apiError.go @@ -52,15 +52,17 @@ func WriteJsonResp(w http.ResponseWriter, err error, respBody interface{}, statu response.Errors = valErrors } else if util.IsErrNoRows(err) { status = http.StatusNotFound - apiErr := &util.ApiError{} - apiErr.Code = "000" // 000=unknown - apiErr.InternalMessage = errors.Details(err) - if respBody != nil { - apiErr.UserMessage = respBody + // Try to extract resource context from respBody for better error messages + resourceType, resourceId := extractResourceContext(respBody) + if resourceType != "" && resourceId != "" { + // Create context-aware resource not found error + apiErr := util.NewResourceNotFoundError(resourceType, resourceId) + response.Errors = []*util.ApiError{apiErr} } else { - apiErr.UserMessage = err.Error() + // Fallback to generic not found error (no more "pg: no rows in result set") + apiErr := util.NewGenericResourceNotFoundError() + response.Errors = []*util.ApiError{apiErr} } - response.Errors = []*util.ApiError{apiErr} } else if multiErr, ok := err.(*multierror.Error); ok { var errorsResp []*util.ApiError for _, e := range multiErr.Errors { diff --git a/api/restHandler/scopedVariable/ScopedVariableRestHandler.go b/api/restHandler/scopedVariable/ScopedVariableRestHandler.go index fdd1d60fc7..5a8ed20c4d 100644 --- a/api/restHandler/scopedVariable/ScopedVariableRestHandler.go +++ b/api/restHandler/scopedVariable/ScopedVariableRestHandler.go @@ -73,7 +73,7 @@ func (handler *ScopedVariableRestHandlerImpl) CreateVariables(w http.ResponseWri decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } request := models.VariableRequest{} @@ -168,7 +168,7 @@ func (handler *ScopedVariableRestHandlerImpl) GetScopedVariables(w http.Response func (handler *ScopedVariableRestHandlerImpl) GetJsonForVariables(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } // not logging bean object as it contains sensitive data diff --git a/api/server/ServerRestHandler.go b/api/server/ServerRestHandler.go index 2927d6448d..20bd951a65 100644 --- a/api/server/ServerRestHandler.go +++ b/api/server/ServerRestHandler.go @@ -62,7 +62,7 @@ func (impl ServerRestHandlerImpl) GetServerInfo(w http.ResponseWriter, r *http.R // check if user is logged in or not userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } showServerStatus := true @@ -89,7 +89,7 @@ func (impl ServerRestHandlerImpl) HandleServerAction(w http.ResponseWriter, r *h // check if user is logged in or not userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/team/TeamRestHandler.go b/api/team/TeamRestHandler.go index 136b8d7825..c99e967392 100644 --- a/api/team/TeamRestHandler.go +++ b/api/team/TeamRestHandler.go @@ -21,7 +21,6 @@ import ( "fmt" bean2 "github.com/devtron-labs/devtron/pkg/team/bean" "net/http" - "strconv" "strings" "time" @@ -32,7 +31,6 @@ import ( user2 "github.com/devtron-labs/devtron/pkg/auth/user" delete2 "github.com/devtron-labs/devtron/pkg/delete" "github.com/devtron-labs/devtron/pkg/team" - "github.com/gorilla/mux" "go.uber.org/zap" "gopkg.in/go-playground/validator.v9" ) @@ -91,7 +89,7 @@ func (impl TeamRestHandlerImpl) SaveTeam(w http.ResponseWriter, r *http.Request) decoder := json.NewDecoder(r.Body) userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean bean2.TeamRequest @@ -145,19 +143,18 @@ func (impl TeamRestHandlerImpl) FetchAll(w http.ResponseWriter, r *http.Request) } func (impl TeamRestHandlerImpl) FetchOne(w http.ResponseWriter, r *http.Request) { - params := mux.Vars(r) - id := params["id"] - idi, err := strconv.Atoi(id) + // Use enhanced parameter parsing with context + teamId, err := common.ExtractIntPathParamWithContext(w, r, "id", "team") if err != nil { - impl.logger.Errorw("request err, FetchOne", "err", err, "id", id) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + // Error already written by ExtractIntPathParamWithContext return } - res, err := impl.teamService.FetchOne(idi) + res, err := impl.teamService.FetchOne(teamId) if err != nil { - impl.logger.Errorw("service err, FetchOne", "err", err, "id", idi) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + impl.logger.Errorw("Failed to fetch team", "teamId", teamId, "err", err) + // Use enhanced error response with resource context + common.WriteJsonRespWithResourceContextFromId(w, err, nil, 0, "team", teamId) return } @@ -174,7 +171,7 @@ func (impl TeamRestHandlerImpl) UpdateTeam(w http.ResponseWriter, r *http.Reques decoder := json.NewDecoder(r.Body) userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var bean bean2.TeamRequest @@ -210,7 +207,7 @@ func (impl TeamRestHandlerImpl) DeleteTeam(w http.ResponseWriter, r *http.Reques decoder := json.NewDecoder(r.Body) userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } var deleteRequest bean2.TeamRequest @@ -247,7 +244,7 @@ func (impl TeamRestHandlerImpl) DeleteTeam(w http.ResponseWriter, r *http.Reques func (impl TeamRestHandlerImpl) FetchForAutocomplete(w http.ResponseWriter, r *http.Request) { userId, err := impl.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } start := time.Now() diff --git a/api/terminal/UserTerminalAccessRestHandler.go b/api/terminal/UserTerminalAccessRestHandler.go index befa62e123..0d4f9ac570 100644 --- a/api/terminal/UserTerminalAccessRestHandler.go +++ b/api/terminal/UserTerminalAccessRestHandler.go @@ -77,7 +77,7 @@ func NewUserTerminalAccessRestHandlerImpl(logger *zap.SugaredLogger, userTermina func (handler UserTerminalAccessRestHandlerImpl) ValidateShell(w http.ResponseWriter, r *http.Request) { userId, err := handler.UserService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -113,7 +113,7 @@ func (handler UserTerminalAccessRestHandlerImpl) ValidateShell(w http.ResponseWr func (handler UserTerminalAccessRestHandlerImpl) StartTerminalSession(w http.ResponseWriter, r *http.Request) { userId, err := handler.UserService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -155,7 +155,7 @@ func (handler UserTerminalAccessRestHandlerImpl) StartTerminalSession(w http.Res func (handler UserTerminalAccessRestHandlerImpl) UpdateTerminalSession(w http.ResponseWriter, r *http.Request) { userId, err := handler.UserService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -197,7 +197,7 @@ func (handler UserTerminalAccessRestHandlerImpl) UpdateTerminalSession(w http.Re func (handler UserTerminalAccessRestHandlerImpl) UpdateTerminalShellSession(w http.ResponseWriter, r *http.Request) { userId, err := handler.UserService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -238,7 +238,7 @@ func (handler UserTerminalAccessRestHandlerImpl) UpdateTerminalShellSession(w ht func (handler UserTerminalAccessRestHandlerImpl) FetchTerminalStatus(w http.ResponseWriter, r *http.Request) { userId, err := handler.UserService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -275,7 +275,7 @@ func (handler UserTerminalAccessRestHandlerImpl) FetchTerminalStatus(w http.Resp func (handler UserTerminalAccessRestHandlerImpl) FetchTerminalPodEvents(w http.ResponseWriter, r *http.Request) { userId, err := handler.UserService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -310,7 +310,7 @@ func (handler UserTerminalAccessRestHandlerImpl) FetchTerminalPodEvents(w http.R func (handler UserTerminalAccessRestHandlerImpl) FetchTerminalPodManifest(w http.ResponseWriter, r *http.Request) { userId, err := handler.UserService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -345,7 +345,7 @@ func (handler UserTerminalAccessRestHandlerImpl) FetchTerminalPodManifest(w http func (handler UserTerminalAccessRestHandlerImpl) DisconnectTerminalSession(w http.ResponseWriter, r *http.Request) { userId, err := handler.UserService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -379,7 +379,7 @@ func (handler UserTerminalAccessRestHandlerImpl) DisconnectTerminalSession(w htt func (handler UserTerminalAccessRestHandlerImpl) StopTerminalSession(w http.ResponseWriter, r *http.Request) { userId, err := handler.UserService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } vars := mux.Vars(r) @@ -408,7 +408,7 @@ func (handler UserTerminalAccessRestHandlerImpl) StopTerminalSession(w http.Resp func (handler UserTerminalAccessRestHandlerImpl) DisconnectAllTerminalSessionAndRetry(w http.ResponseWriter, r *http.Request) { userId, err := handler.UserService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } decoder := json.NewDecoder(r.Body) @@ -451,7 +451,7 @@ func (handler UserTerminalAccessRestHandlerImpl) DisconnectAllTerminalSessionAnd func (handler UserTerminalAccessRestHandlerImpl) EditPodManifest(w http.ResponseWriter, r *http.Request) { userId, err := handler.UserService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/api/userResource/UserResourceRestHandler.go b/api/userResource/UserResourceRestHandler.go index b410373ad5..84e3492793 100644 --- a/api/userResource/UserResourceRestHandler.go +++ b/api/userResource/UserResourceRestHandler.go @@ -34,7 +34,7 @@ func NewUserResourceRestHandler(logger *zap.SugaredLogger, func (handler *RestHandlerImpl) GetResourceOptions(w http.ResponseWriter, r *http.Request) { userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + common.HandleUnauthorized(w, r) return } diff --git a/internal/constants/InternalErrorCode.go b/internal/constants/InternalErrorCode.go index 70710974a5..48579d5eb0 100644 --- a/internal/constants/InternalErrorCode.go +++ b/internal/constants/InternalErrorCode.go @@ -169,6 +169,21 @@ const ( // Feasibility Errors End ---------------- ) +const ( + // Generic API Errors Start -------------- + // Sequence 11000-11999 + + InvalidPathParameter string = "11001" + InvalidRequestBody string = "11002" + InvalidQueryParameter string = "11003" + ValidationFailed string = "11004" + MissingRequiredField string = "11005" + ResourceNotFound string = "11006" + DuplicateResource string = "11007" + + // Generic API Errors End ---------------- +) + const ( // Not Processed Internal Errors Start --- // Sequence 11000-11999 diff --git a/internal/util/ResourceErrorFactory.go b/internal/util/ResourceErrorFactory.go new file mode 100644 index 0000000000..91042fef01 --- /dev/null +++ b/internal/util/ResourceErrorFactory.go @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024. Devtron Inc. + * + * Licensed 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. + */ + +package util + +import ( + "fmt" + "github.com/devtron-labs/devtron/internal/constants" + "net/http" +) + +// ResourceContext holds information about the resource for better error messages +type ResourceContext struct { + ResourceType string + ResourceId string + Operation string +} + +// NewResourceNotFoundError creates a user-friendly error for resource not found scenarios +// Leverages existing util.NewApiError() function +func NewResourceNotFoundError(resourceType, resourceId string) *ApiError { + return NewApiError( + http.StatusNotFound, + fmt.Sprintf("%s with ID '%s' not found", resourceType, resourceId), + fmt.Sprintf("%s not found: %s", resourceType, resourceId), + ).WithCode(constants.ResourceNotFound). + WithUserDetailMessage(fmt.Sprintf("The requested %s does not exist or has been deleted.", resourceType)) +} + +// NewDuplicateResourceError creates a user-friendly error for duplicate resource scenarios +func NewDuplicateResourceError(resourceType, resourceName string) *ApiError { + return NewApiError( + http.StatusConflict, + fmt.Sprintf("%s with name '%s' already exists", resourceType, resourceName), + fmt.Sprintf("duplicate %s: %s", resourceType, resourceName), + ).WithCode(constants.DuplicateResource). + WithUserDetailMessage(fmt.Sprintf("A %s with this name already exists. Please choose a different name.", resourceType)) +} + +// NewValidationErrorForField creates a user-friendly error for field validation failures +func NewValidationErrorForField(fieldName, reason string) *ApiError { + return NewApiError( + http.StatusBadRequest, + fmt.Sprintf("Validation failed for field '%s': %s", fieldName, reason), + fmt.Sprintf("validation failed for %s: %s", fieldName, reason), + ).WithCode(constants.ValidationFailed). + WithUserDetailMessage("Please check the field value and try again.") +} + +// NewInvalidPathParameterError creates a user-friendly error for invalid path parameters +func NewInvalidPathParameterError(paramName, paramValue string) *ApiError { + return NewApiError( + http.StatusBadRequest, + fmt.Sprintf("Invalid path parameter '%s'", paramName), + fmt.Sprintf("invalid path parameter %s: %s", paramName, paramValue), + ).WithCode(constants.InvalidPathParameter). + WithUserDetailMessage("Please check the parameter format and try again.") +} + +// NewMissingRequiredFieldError creates a user-friendly error for missing required fields +func NewMissingRequiredFieldError(fieldName string) *ApiError { + return NewApiError( + http.StatusBadRequest, + fmt.Sprintf("Required field '%s' is missing", fieldName), + fmt.Sprintf("missing required field: %s", fieldName), + ).WithCode(constants.MissingRequiredField). + WithUserDetailMessage("Please provide all required fields and try again.") +} + +// NewGenericResourceNotFoundError creates a generic not found error when resource context is unknown +func NewGenericResourceNotFoundError() *ApiError { + return NewApiError( + http.StatusNotFound, + "Requested resource not found", + "resource not found", + ).WithCode(constants.ResourceNotFound). + WithUserDetailMessage("The requested resource does not exist or has been deleted.") +} diff --git a/specs/application/labels.yaml b/specs/application/labels.yaml index 55bf0a391f..f8696a7a7a 100644 --- a/specs/application/labels.yaml +++ b/specs/application/labels.yaml @@ -2,84 +2,262 @@ openapi: "3.0.0" info: version: 1.0.0 title: Application Labels Management + description: API for managing application labels and metadata + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +servers: + - url: /orchestrator + description: Devtron Orchestrator API Server + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + paths: - /orchestrator/app/labels/list: + /app/labels/list: get: - description: this api will return all the labels available in database. - parameters: [ ] + summary: List Application Labels + description: | + Retrieves a list of application labels. By default, returns all labels. + Use the `showPropagatedOnly` parameter to filter for labels where propagate = true. + + **Required Token Permission:** + - Must have **View** access to the applications in scope. + operationId: getAppLabels + security: + - bearerAuth: [] + parameters: + - name: showPropagatedOnly + in: query + description: | + If true, only returns labels where propagate = true. + If false or not provided, all labels are returned. + required: false + schema: + type: boolean + default: false + example: false responses: '200': - description: list response + description: Successfully retrieved labels list content: application/json: schema: + type: object properties: code: type: integer - description: status code + description: HTTP status code + example: 200 status: type: string - description: status + description: Response status message + example: OK result: type: array + description: Array of label objects items: - $ref: '#/components/schemas/AppLabel' + allOf: + - type: object + properties: + appId: + type: integer + description: unique application id + appName: + type: string + description: The name of the application + required: + - appId + - appName + - $ref: '../common/schemas.yaml#/components/schemas/AppLabel' + examples: + all_labels: + summary: All labels response + description: Example response when showPropagatedOnly is false or not provided + value: + code: 200 + status: OK + result: + - key: environment + value: production + propagate: true + appId: 1234 + appName: web-service + - key: team + value: backend + propagate: false + appId: 1234 + appName: web-service + propagated_only: + summary: Propagated labels only + description: Example response when showPropagatedOnly is true + value: + code: 200 + status: OK + result: + - key: environment + value: production + propagate: true + appId: 1234 + appName: web-service + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '401': + description: Authentication required or token invalid + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 401 + status: + type: string + example: Unauthorized + message: + type: string + example: Authentication token is required + '403': + description: Insufficient permissions to access the resource + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 403 + status: + type: string + example: Forbidden + message: + type: string + example: Token does not have View access to the applications in scope + '404': + description: Not found + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 500 + status: + type: string + example: Internal Server Error + message: + type: string + example: An unexpected error occurred default: - description: unexpected error + description: Unexpected error content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + tags: + - Application Labels - /orchestrator/app/meta/info/{appId}: + /app/meta/info/{appId}: get: - description: application basic info, projects and labels + summary: Get Application Meta Info + description: Retrieves application basic info, projects and labels + operationId: getAppMetaInfo + security: + - bearerAuth: [] parameters: - name: appId in: path - description: application id + description: Application ID required: true schema: type: integer format: int64 responses: '200': - description: application basic info, projects and labels + description: Application basic info, projects and labels content: application/json: schema: + type: object properties: code: type: integer - description: status code + description: Status code status: type: string - description: status + description: Status result: allOf: - - $ref: '#/components/schemas/AppMetaInfo' + - $ref: '../common/schemas.yaml#/components/schemas/AppMetaInfo' - type: object properties: gitMaterials: type: array items: - $ref: '#/components/schemas/GitMaterialMeta' + $ref: '../common/schemas.yaml#/components/schemas/GitMaterialMeta' templateConfig: - $ref: '#/components/schemas/TemplateConfig' + $ref: '../common/schemas.yaml#/components/schemas/TemplateConfig' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '404': + description: Application not found + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' default: - description: unexpected error + description: Unexpected error content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + tags: + - Application Metadata - /orchestrator/app/helm/meta/info/{appId}: + /helm/meta/info/{appId}: get: - description: application info for all types of helm apps + summary: Get Helm Application Meta Info + description: Retrieves application info for all types of Helm apps + operationId: getHelmAppMetaInfo + security: + - bearerAuth: [] parameters: - name: appId in: path - description: application id + description: Application ID required: true schema: type: string @@ -89,193 +267,62 @@ paths: content: application/json: schema: + type: object properties: code: type: integer - description: status code + description: Status code status: type: string - description: status + description: Status result: allOf: - - $ref: '#/components/schemas/AppMetaInfo' + - $ref: '../common/schemas.yaml#/components/schemas/AppMetaInfo' - type: object properties: chartUsed: - $ref: '#/components/schemas/ChartUsed' + $ref: '../common/schemas.yaml#/components/schemas/ChartUsed' gitMaterials: type: array items: - $ref: '#/components/schemas/GitMaterialMeta' + $ref: '../common/schemas.yaml#/components/schemas/GitMaterialMeta' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '404': + description: Application not found + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' default: - description: unexpected error + description: Unexpected error content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' - -# components mentioned below -components: - schemas: - AppLabel: - type: object - required: - - key - - value - - propagate - properties: - key: - type: string - description: label key - value: - type: string - description: label value - propagate: - type: boolean - description: Whether to propagate to kubernetes resources - - AppMetaInfo: - type: object - required: - - appId - - projectId - - appName - - projectName - - createdOn - - createdBy - - active - properties: - appId: - type: integer - description: app id - projectId: - type: integer - description: team/project id - appName: - type: string - description: app name - projectName: - type: string - description: team/project name - description: - type: string - description: app description - labels: - type: array - items: - $ref: '#/components/schemas/AppLabel' - createdOn: - type: string - format: date-time - description: app creation date - createdBy: - type: string - description: app created by - active: - type: boolean - description: whether app is active - note: - $ref: '#/components/schemas/GenericNoteResponse' - - ChartUsed: - type: object - properties: - appStoreChartName: - type: string - description: Name of the chart from app store - appStoreChartId: - type: integer - description: ID of the chart from app store - appStoreAppName: - type: string - description: Name of the app in app store - appStoreAppVersion: - type: string - description: Version of the app in app store - chartAvatar: - type: string - description: Avatar/icon of the chart - - GitMaterialMeta: - type: object - properties: - displayName: - type: string - description: Display name of the git material - redirectionUrl: - type: string - description: HTTPS URL for redirection - originalUrl: - type: string - description: Original git URL - - TemplateConfig: - type: object - properties: - id: - type: integer - description: Template config ID - identifier: - type: string - description: Template identifier - name: - type: string - description: Template name - - GenericNoteResponse: - type: object - properties: - id: - type: integer - description: Note ID - description: - type: string - description: Note content/description - createdOn: - type: string - format: date-time - description: Creation timestamp - createdBy: - type: string - description: Creator's email - updatedOn: - type: string - format: date-time - description: Last update timestamp - updatedBy: - type: string - description: Last updater's email - - ErrorResponse: - required: - - code - - status - properties: - code: - type: integer - format: int32 - description: Error code - status: - type: string - description: Error message - errors: - type: array - description: errors - items: - $ref: '#/components/schemas/Error' + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + tags: + - Helm Application Metadata - Error: - required: - - code - - status - properties: - code: - type: integer - format: int32 - description: Error internal code - internalMessage: - type: string - description: Error internal message - userMessage: - type: string - description: Error user message \ No newline at end of file +tags: + - name: Application Labels + description: Operations related to application labels + - name: Application Metadata + description: Operations related to application metadata + - name: Helm Application Metadata + description: Operations related to Helm application metadata \ No newline at end of file diff --git a/specs/ci-pipeline/ci-pipeline-build-spec.yaml b/specs/ci-pipeline/ci-pipeline-build-spec.yaml index d88ede2f46..32526ebea0 100644 --- a/specs/ci-pipeline/ci-pipeline-build-spec.yaml +++ b/specs/ci-pipeline/ci-pipeline-build-spec.yaml @@ -16,7 +16,7 @@ servers: description: Devtron Orchestrator API Server paths: - /orchestrator/commit-info/{ciPipelineMaterialId}/{gitHash}: + /orchestrator/app/commit-info/{ciPipelineMaterialId}/{gitHash}: get: tags: - Commit diff --git a/specs/common/schemas.yaml b/specs/common/schemas.yaml new file mode 100644 index 0000000000..3a6bd9a8ec --- /dev/null +++ b/specs/common/schemas.yaml @@ -0,0 +1,572 @@ +openapi: 3.0.0 +info: + version: 1.0.0 + title: Devtron Common Schemas + description: Shared schemas and components used across all Devtron API specifications + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token for authentication + + schemas: + # Common Response Schemas + ApiResponse: + type: object + properties: + code: + type: integer + description: HTTP status code + example: 200 + status: + type: string + description: HTTP status message + example: OK + result: + type: object + description: Response result data + + ErrorResponse: + type: object + required: + - code + - status + properties: + code: + type: integer + format: int32 + description: Error code + status: + type: string + description: Error message + result: + type: object + nullable: true + errors: + type: array + items: + $ref: '#/components/schemas/Error' + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + description: Error internal code + message: + type: string + description: Error message + internalMessage: + type: string + description: Error internal message + userMessage: + type: string + description: Error user message + + # Application Related Schemas + AppLabel: + type: object + required: + - key + - value + properties: + key: + type: string + description: Label key + value: + type: string + description: Label value + propagate: + type: boolean + description: Whether to propagate to kubernetes resources + + AppMetaInfo: + type: object + required: + - appId + - projectId + - appName + - projectName + - createdOn + - createdBy + properties: + appId: + type: integer + description: Application ID + projectId: + type: integer + description: Team/project ID + appName: + type: string + description: Application name + projectName: + type: string + description: Team/project name + description: + type: string + description: Application description + labels: + type: array + items: + $ref: '#/components/schemas/AppLabel' + createdOn: + type: string + format: date-time + description: Application creation date + createdBy: + type: string + description: Application created by + active: + type: boolean + description: Whether application is active + note: + $ref: '#/components/schemas/GenericNoteResponse' + + App: + type: object + required: + - appName + properties: + id: + type: integer + format: int64 + description: Application ID + appName: + type: string + description: Name of the application + teamId: + type: integer + format: int64 + description: Team ID + templateId: + type: integer + description: Reference app id, used for clone, set default value 0 for blank app + labels: + type: array + description: Application labels (optional) + items: + $ref: '#/components/schemas/AppLabel' + description: + type: string + description: Application description + projectIds: + type: array + items: + type: integer + format: int64 + description: IDs of projects this application belongs to + + AppContainer: + type: object + required: + - appId + - appName + - environments + properties: + appId: + type: integer + description: Application ID + appName: + type: string + description: Application name + environments: + type: array + items: + $ref: '#/components/schemas/EnvContainer' + + EnvContainer: + type: object + required: + - appId + - appName + - environmentId + - environmentName + properties: + appId: + type: integer + description: Application ID + appName: + type: string + description: Application name + cdStageStatus: + type: string + description: CD stage status + dataSource: + type: string + description: Data source + ciArtifactId: + type: integer + description: CI artifact ID + deleted: + type: boolean + description: Whether deleted + environmentId: + type: integer + description: Environment ID + environmentName: + type: string + description: Environment name + status: + type: string + description: Status + appStatus: + type: string + description: Application status for this environment + postStageStatus: + type: string + description: Post stage status + preStageStatus: + type: string + description: Pre stage status + lastDeployedTime: + type: string + description: Last deployment time + materialInfo: + type: array + items: + type: object + + AppProjectUpdateRequest: + type: object + required: + - appId + - projectIds + properties: + appId: + type: integer + format: int64 + description: Application ID + projectIds: + type: array + items: + type: integer + format: int64 + description: IDs of projects to associate with the application + + AppListingRequest: + type: object + properties: + appNameSearch: + type: string + description: Application name search, wildcard match + offset: + type: integer + description: Pagination offset + size: + type: integer + description: Page size + sortBy: + type: string + description: Sort by field + sortOrder: + type: string + description: Sort order + environments: + type: array + description: Environment IDs + items: + type: integer + teams: + type: array + description: Team IDs (project IDs) + items: + type: integer + labels: + type: array + description: Application labels + items: + type: string + statuses: + type: array + description: Application statuses + items: + type: string + + DeploymentGroup: + type: object + required: + - id + properties: + id: + type: integer + description: Deployment group ID + ciPipelineId: + type: integer + description: CI pipeline ID + environmentId: + type: integer + description: Environment ID + appCount: + type: integer + description: Application count + name: + type: string + description: Deployment group name + noOfApps: + type: string + description: Number of applications + + # Common Utility Schemas + GenericNoteResponse: + type: object + properties: + id: + type: integer + description: Note ID + description: + type: string + description: Note content/description + createdOn: + type: string + format: date-time + description: Creation timestamp + createdBy: + type: string + description: Creator's email + updatedOn: + type: string + format: date-time + description: Last update timestamp + updatedBy: + type: string + description: Last updater's email + + ListingRequest: + type: object + properties: + searchKey: + type: string + nullable: true + sortOrder: + type: string + enum: [ASC, DESC] + nullable: true + sortBy: + type: string + nullable: true + offset: + type: integer + format: int32 + minimum: 0 + nullable: true + size: + type: integer + format: int32 + minimum: 1 + default: 20 + nullable: true + showAll: + type: boolean + nullable: true + readOnly: true + + # Git Material Schemas + GitMaterial: + type: object + properties: + name: + type: string + url: + type: string + id: + type: integer + gitProviderId: + type: integer + checkoutPath: + type: string + fetchSubmodules: + type: boolean + isUsedInCiConfig: + type: boolean + + GitMaterialMeta: + type: object + properties: + displayName: + type: string + description: Display name of the git material + redirectionUrl: + type: string + description: HTTPS URL for redirection + originalUrl: + type: string + description: Original git URL + + # Template Schemas + TemplateConfig: + type: object + properties: + id: + type: integer + description: Template config ID + identifier: + type: string + description: Template identifier + name: + type: string + description: Template name + + # Chart Related Schemas + ChartUsed: + type: object + properties: + appStoreChartName: + type: string + description: Name of the chart from app store + appStoreChartId: + type: integer + description: ID of the chart from app store + appStoreAppName: + type: string + description: Name of the app in app store + appStoreAppVersion: + type: string + description: Version of the app in app store + chartAvatar: + type: string + description: Avatar/icon of the chart + + ChartInfo: + type: object + required: + - installedAppId + - environmentId + - installedAppVersionId + - appStoreApplicationVersionId + - appStoreApplicationName + - status + - appName + - environmentName + - deployedAt + - deployedBy + - readme + - deprecated + properties: + installedAppId: + type: integer + description: Installed chart ID + environmentId: + type: integer + description: Environment ID + installedAppVersionId: + type: integer + description: Installed chart version ID + appStoreApplicationVersionId: + type: integer + description: App store application version ID + appStoreApplicationName: + type: string + description: Chart name externally + chartName: + type: string + description: Chart repo name + icon: + type: string + description: Chart icon + status: + type: string + description: Status of deployed chart + appName: + type: string + description: Chart name as app name for devtron + environmentName: + type: string + description: Environment name + deployedAt: + type: string + description: Deployment time + deployedBy: + type: string + description: User who deployed + readme: + type: string + description: Chart readme + deprecated: + type: boolean + description: Whether chart is deprecated + + # Bulk Operation Schemas + NameIncludesExcludes: + type: object + properties: + names: + type: array + items: + type: string + description: All strings of app names to be included/excluded + + BulkActionRequest: + type: object + properties: + includes: + $ref: '#/components/schemas/NameIncludesExcludes' + excludes: + $ref: '#/components/schemas/NameIncludesExcludes' + envIds: + type: array + items: + type: integer + description: All Environment IDs for the bulk action + appIds: + type: array + items: + type: integer + description: All Application IDs for the bulk action + projectIds: + type: array + items: + type: integer + description: All Project IDs for the bulk action + + BulkActionResponse: + type: object + properties: + message: + type: array + items: + type: string + description: Top-level messages in response of the bulk action + failure: + type: array + items: + $ref: '#/components/schemas/BulkActionFailureDetail' + description: Details of all items on which the bulk action failed + successful: + type: array + items: + $ref: '#/components/schemas/BulkActionSuccessDetail' + description: Details of all items on which the bulk action applied successfully + + BulkActionFailureDetail: + type: object + properties: + appId: + type: integer + appName: + type: string + envId: + type: integer + message: + type: string + + BulkActionSuccessDetail: + type: object + properties: + appId: + type: integer + appName: + type: string + envId: + type: integer + message: + type: string diff --git a/specs/deployment/rollback.yaml b/specs/deployment/rollback.yaml index 7b3eca288d..af68e9752f 100644 --- a/specs/deployment/rollback.yaml +++ b/specs/deployment/rollback.yaml @@ -93,48 +93,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orchestrator/app/deployment-configuration/all/latest/{appId}/{pipelineId}: - get: - operationId: FetchDeploymentConfiguration - description: Fetch latest deployment configuration i.e. currently saved in the system and marked as active - parameters: - - name: appId - in: path - required: true - schema: - type: integer - description: ID of the application - - name: pipelineId - in: path - required: true - schema: - type: integer - description: ID of the pipeline - responses: - '200': - description: Successfully return configuration detail - content: - application/json: - schema: - $ref: '#/components/schemas/HistoryConfigurationDetailDto' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' components: schemas: diff --git a/specs/environment/bulk-delete.yaml b/specs/environment/bulk-delete.yaml index 22cfedd7d3..73f77f17eb 100644 --- a/specs/environment/bulk-delete.yaml +++ b/specs/environment/bulk-delete.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: Environment Bulk Operations paths: - /orchestrtor/batch/v1beta1/cd-pipeline: + /orchestrator/batch/v1beta1/cd-pipeline: post: description: perform bulk actions on cd pipelines parameters: diff --git a/specs/helm/charts.yaml b/specs/helm/charts.yaml index e05cacf410..2e5982f60f 100644 --- a/specs/helm/charts.yaml +++ b/specs/helm/charts.yaml @@ -2,151 +2,227 @@ openapi: "3.0.0" info: version: 1.0.0 title: Helm Chart Store Management + description: API for managing Helm chart deployments and operations + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +servers: + - url: /orchestrator + description: Devtron Orchestrator API Server + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + paths: - /orchestrator/app-store/installed-app: + /app-store/installed-app: get: - description: deployed chart listing, with search filters + summary: List deployed charts + operationId: listDeployedCharts + description: Deployed chart listing with search filters + security: + - bearerAuth: [] parameters: - name: envIds in: query - description: environment ids + description: Environment IDs required: false schema: - type: string + type: array + items: + type: string - name: clusterIds in: query - description: cluster ids + description: Cluster IDs required: false schema: - type: string + type: array + items: + type: string - name: chartRepoId in: query - description: chart repo ids + description: Chart repository IDs required: false schema: - type: string + type: array + items: + type: string - name: appStoreName in: query - description: chart name + description: Chart name required: false schema: type: string - name: appName in: query - description: chart name as app name for devtron + description: Chart name as app name for devtron required: false schema: type: string - name: onlyDeprecated in: query - description: show only deprecated or all + description: Show only deprecated charts or all required: false schema: type: boolean - name: offset in: query - description: offset for result set + description: Offset for result set (pagination) required: false schema: type: integer - name: size in: query - description: total request size. + description: Total request size (pagination) required: false schema: type: integer - name: appStatuses in: query - description: app statuses filter + description: Application statuses filter required: false schema: - type: string + type: array + items: + type: string responses: '200': - description: deployed chart listing, with search filters + description: Deployed chart listing with search filters content: application/json: schema: + type: object properties: code: type: integer - description: status code + description: Status code status: type: string - description: status + description: Status result: $ref: '#/components/schemas/AppListDetail' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' default: - description: unexpected error + description: Unexpected error content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' - /orchestrator/app-store/installed-app/notes/{installed-app-id}/{env-id}: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + tags: + - Helm Charts + /app-store/installed-app/notes: get: - description: Used to fetch notes.txt for helm charts deployed via gitOps + summary: Fetch notes.txt for deployed helm charts + operationId: fetchNotesTxt + description: Used to fetch notes.txt for helm charts deployed via GitOps + security: + - bearerAuth: [] parameters: - name: env-id - in: path - description: it is an environment id of app + in: query + description: Environment ID of app required: true schema: type: integer - name: installed-app-id - in: path - description: it is a installed application id + in: query + description: Installed application ID required: true schema: type: integer responses: '200': - description: if it is able to fetch the notes.txt then status will be ok + description: Successfully fetched notes.txt content: application/json: schema: + type: object properties: code: type: integer - description: status code + description: Status code status: type: string - description: status + description: Status result: $ref: '#/components/schemas/Notes' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '404': + description: Chart or notes not found + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' '500': - description: error while fetching notes.txt + description: Error while fetching notes.txt + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + tags: + - Helm Charts -# components mentioned below -components: schemas: AppListDetail: type: object properties: clusterIds: type: array - description: clusters to which result corresponds + description: Clusters to which result corresponds items: type: integer applicationType: type: string - description: application type inside the array + description: Application type inside the array enum: [DEVTRON-CHART-STORE, DEVTRON-APP, HELM-APP] errored: type: boolean - description: if data fetch for that cluster produced error + description: If data fetch for that cluster produced error errorMsg: type: string - description: error msg if client failed to fetch + description: Error message if client failed to fetch helmApps: type: array - description: all helm app list + description: All helm app list items: $ref: '#/components/schemas/HelmAppDetails' devtronApps: type: array - description: all devtron app list + description: All devtron app list items: type: object @@ -156,84 +232,54 @@ components: lastDeployedAt: type: string format: date-time - description: time when this application was last deployed/updated + description: Time when this application was last deployed/updated appName: type: string - description: name of the helm application/helm release name + description: Name of the helm application/helm release name appId: type: string - description: unique identifier for app + description: Unique identifier for app chartName: type: string - description: name of the chart + description: Name of the chart chartAvatar: type: string - description: url/location of the chart icon + description: URL/location of the chart icon projectId: type: integer - description: unique identifier for the project, APP with no project will have id 0 + description: Unique identifier for the project, APP with no project will have id 0 chartVersion: type: string - description: chart version + description: Chart version environmentDetail: $ref: '#/components/schemas/EnvironmentDetails' appStatus: type: string - description: application status + description: Application status EnvironmentDetails: type: object properties: clusterName: type: string - description: cluster corresponding to the environment where application is deployed + description: Cluster corresponding to the environment where application is deployed clusterId: type: integer - description: clusterId corresponding to the environment where application is deployed + description: Cluster ID corresponding to the environment where application is deployed namespace: type: string - description: namespace where application is deployed + description: Namespace where application is deployed isVirtualEnvironment: type: boolean - description: whether environment is virtual or not + description: Whether environment is virtual or not Notes: type: object properties: gitOpsNotes: type: string - description: notes content + description: Notes content - ErrorResponse: - required: - - code - - status - properties: - code: - type: integer - format: int32 - description: Error code - status: - type: string - description: Error message - errors: - type: array - description: errors - items: - $ref: '#/components/schemas/Error' - - Error: - required: - - code - - status - properties: - code: - type: integer - format: int32 - description: Error internal code - internalMessage: - type: string - description: Error internal message - userMessage: - type: string - description: Error user message \ No newline at end of file +tags: + - name: Helm Charts + description: Helm chart deployment management and operations \ No newline at end of file diff --git a/specs/jobs/core.yaml b/specs/jobs/core.yaml index 16d6beea8a..5a18f05128 100644 --- a/specs/jobs/core.yaml +++ b/specs/jobs/core.yaml @@ -1,7 +1,7 @@ openapi: "3.0.0" info: title: Job Pipeline Management - description: Devtron API for job management + description: Devtron API for job management operations including creation, cloning, and listing version: "1.0" termsOfService: https://devtron.ai/terms/ contact: @@ -11,12 +11,26 @@ info: license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html + servers: - - url: http://localhost:8080/orchestrator + - url: /orchestrator + description: Devtron Orchestrator API Server + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + paths: - /orchestrator/job: + /job: post: - description: Create and clones a job + summary: Create or clone a job + description: Create and clone a job + operationId: createOrCloneJob + security: + - bearerAuth: [] requestBody: required: true content: @@ -25,22 +39,47 @@ paths: $ref: "#/components/schemas/CreateJob" responses: '200': - description: Used to give response once a job is created + description: Job created successfully content: application/json: schema: + type: object properties: code: type: integer - description: status code + description: Status code status: type: string - description: status + description: Status result: $ref: "#/components/schemas/ActionResponse" - /orchestrator/job/list: + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + tags: + - Jobs + /job/list: post: + summary: List jobs description: Get the list of all the jobs by applying filter + operationId: listJobs + security: + - bearerAuth: [] requestBody: required: true content: @@ -49,46 +88,99 @@ paths: $ref: "#/components/schemas/JobListRequest" responses: '200': - description: Used to give response of list of jobs + description: List of jobs retrieved successfully content: application/json: schema: + type: object properties: code: type: integer - description: status code + description: Status code status: type: string - description: status + description: Status result: $ref: "#/components/schemas/JobListResponse" - /orchestrator/job/ci-pipeline/list/{jobId}: + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + tags: + - Jobs + + /job/ci-pipeline/list/{jobId}: get: - description: fetch details of job ci-pipelines for the overview page + summary: Get job CI pipeline list + description: Fetch details of job CI-pipelines for the overview page + operationId: getJobCiPipelineList + security: + - bearerAuth: [] parameters: - name: jobId in: path required: true + description: Job ID schema: type: integer responses: '200': - description: Job CI pipeline details + description: Job CI pipeline list retrieved successfully content: application/json: schema: + type: object properties: code: type: integer - description: status code + description: Status code status: type: string - description: status + description: Status result: type: array items: $ref: "#/components/schemas/JobCiPipeline" -components: + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '404': + description: Job not found + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '../common/schemas.yaml#/components/schemas/ErrorResponse' + tags: + - Jobs schemas: CreateJob: type: object @@ -99,122 +191,91 @@ components: properties: appName: type: string - description: Used to give the name of the job - example: "my-job-1" + description: Name of the job + example: my-job-1 isJob: type: boolean - description: States whether its a job or an app + description: States whether it's a job or an app example: true teamId: type: integer - description: Used to give team id + description: Project ID example: 1 templateId: type: integer - description: Used to give the id of the job it wants to clone + description: ID of the job to clone from example: 18 labels: type: array - description: Job labels items: - $ref: "#/components/schemas/JobLabel" + $ref: '../common/schemas.yaml#/components/schemas/AppLabel' description: type: string - description: Used to give the description of the job once it is made. - example: "This is my first Job" + description: Description of the job + example: This is my first Job - JobLabel: - type: object - properties: - key: - type: string - example: "hello" - value: - type: string - example: "world" - propagate: - type: boolean - example: false ActionResponse: type: object properties: id: type: integer - description: Used to give the id of job once its created + description: ID of job once created example: 25 appName: type: string - description: Used to give the name of job once its created - example: "my-job-1" + description: Name of job once created + example: my-job-1 material: type: array - description: Git materials items: - $ref: "#/components/schemas/GitMaterial" + $ref: '../common/schemas.yaml#/components/schemas/GitMaterial' teamId: type: integer - description: Used to give the team id + description: Team ID example: 1 templateId: type: integer - description: Used to give the templateId + description: Template ID example: 0 description: type: string - description: Used to give the description of the job once it is made. - example: "This is my first Job" + description: Description of the job + example: This is my first Job isJob: type: boolean - description: used to tell whether it is a job or an app + description: Whether it is a job or an app example: true - GitMaterial: - type: object - properties: - name: - type: string - url: - type: string - id: - type: integer - gitProviderId: - type: integer - checkoutPath: - type: string - fetchSubmodules: - type: boolean - isUsedInCiConfig: - type: boolean JobListRequest: type: object properties: teams: type: array - description: used to give the project id items: type: integer - example: [1,2] + description: Project IDs to filter by + example: [1, 2] appStatuses: type: array - description: used to give the filter of app ci-build status items: type: string - example: ["Succeeded", "Starting"] + description: CI build status filter + example: [Succeeded, Starting] sortBy: type: string - description: used to give the sort by constraint - example: "appNameSort" + description: Sort by constraint + example: appNameSort sortOrder: type: string - description: used to give the sort order - example: "ASC" + description: Sort order + example: ASC offset: type: integer - description: used to give the number from which we want our job (if the offset is 20 means we want list of jobs from 20) + description: Number from which to start the job list (pagination) example: 0 size: type: integer - description: used to give the number of jobs we want + description: Number of jobs to return example: 20 JobListResponse: @@ -222,12 +283,11 @@ components: properties: jobContainers: type: array - description: List of job containers items: - $ref: "#/components/schemas/JobContainer" + $ref: '#/components/schemas/JobContainer' jobCount: type: integer - description: Total count of jobs + description: Total number of jobs JobContainer: type: object @@ -241,7 +301,7 @@ components: ciPipelines: type: array items: - $ref: "#/components/schemas/JobCiPipeline" + $ref: '#/components/schemas/JobCiPipeline' JobCiPipeline: type: object @@ -257,10 +317,6 @@ components: type: string format: date-time - - - - - - - +tags: + - name: Jobs + description: Job management operations for creating, cloning, and retrieving jobs \ No newline at end of file diff --git a/specs/kubernetes/access-policy.yaml b/specs/kubernetes/access-policy.yaml deleted file mode 100644 index ce0676acb7..0000000000 --- a/specs/kubernetes/access-policy.yaml +++ /dev/null @@ -1,288 +0,0 @@ -openapi: "3.0.0" -info: - version: 1.0.0 - title: Cluster Access Policy Management - description: API for managing cluster access policies and roles - -paths: - /orchestrator/cluster/access: - post: - summary: Create a new cluster access policy - operationId: CreateClusterAccessPolicy - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ClusterAccessPolicy' - responses: - '200': - description: Successfully created cluster access policy - content: - application/json: - schema: - $ref: '#/components/schemas/ClusterAccessPolicy' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized user - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden, user is not authorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - put: - summary: Update an existing cluster access policy - operationId: UpdateClusterAccessPolicy - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ClusterAccessPolicy' - responses: - '200': - description: Successfully updated cluster access policy - content: - application/json: - schema: - $ref: '#/components/schemas/ClusterAccessPolicy' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized user - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden, user is not authorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/cluster/access/{id}: - get: - summary: Get a cluster access policy by ID - operationId: GetClusterAccessPolicy - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Successfully retrieved cluster access policy - content: - application/json: - schema: - $ref: '#/components/schemas/ClusterAccessPolicy' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized user - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden, user is not authorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Cluster access policy not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - delete: - summary: Delete a cluster access policy - operationId: DeleteClusterAccessPolicy - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Successfully deleted cluster access policy - content: - application/json: - schema: - type: boolean - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized user - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden, user is not authorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Cluster access policy not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - - /orchestrator/cluster/access/list: - get: - summary: List all cluster access policies - operationId: ListClusterAccessPolicies - parameters: - - name: clusterId - in: query - required: false - schema: - type: integer - - name: namespace - in: query - required: false - schema: - type: string - responses: - '200': - description: Successfully retrieved cluster access policies - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ClusterAccessPolicy' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized user - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden, user is not authorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - -components: - schemas: - ClusterAccessPolicy: - type: object - required: - - cluster - - action - properties: - id: - type: integer - description: Unique identifier for the policy - cluster: - type: string - description: Name of the cluster - namespace: - type: string - description: Namespace name. For multiple namespaces, use comma-separated values. Empty string for all namespaces. - group: - type: string - description: Group name. For multiple groups, use comma-separated values. Empty string for all groups. - kind: - type: string - description: Resource kind. For multiple kinds, use comma-separated values. Empty string for all kinds. - resource: - type: string - description: Resource name. For multiple resources, use comma-separated values. Empty string for all resources. - action: - type: string - description: Type of access role - enum: ["view", "edit", "admin"] - userId: - type: integer - description: ID of the user who created/updated the policy - createdOn: - type: string - format: date-time - description: Timestamp when the policy was created - updatedOn: - type: string - format: date-time - description: Timestamp when the policy was last updated - - Error: - type: object - required: - - code - - message - properties: - code: - type: integer - description: Error code - message: - type: string - description: Error message \ No newline at end of file diff --git a/specs/kubernetes/resources.yaml b/specs/kubernetes/resources.yaml index 2548834079..4f55608bf1 100644 --- a/specs/kubernetes/resources.yaml +++ b/specs/kubernetes/resources.yaml @@ -12,9 +12,9 @@ info: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html servers: - - url: http://localhost:8080/orchestrator/k8s + - url: http://localhost:8080 paths: - /orchestrator/resource/inception/info: + /orchestrator/k8s/resource/inception/info: get: description: Get inception pod info, such as pod name responses: @@ -33,7 +33,7 @@ paths: result: $ref: '#/components/schemas/ResourceInfo' - /orchestrator/resource: + /orchestrator/k8s/resource: post: description: Get Kubernetes resource details requestBody: @@ -58,7 +58,7 @@ paths: result: $ref: '#/components/schemas/ManifestResponse' - /orchestrator/resource/create: + /orchestrator/k8s/resource/create: post: description: Create Kubernetes resource requestBody: @@ -83,7 +83,7 @@ paths: result: $ref: '#/components/schemas/ManifestResponse' - /orchestrator/resource/update: + /orchestrator/k8s/resource: put: description: Update Kubernetes resource requestBody: @@ -108,8 +108,8 @@ paths: result: $ref: '#/components/schemas/ManifestResponse' - /orchestrator/resource/delete: - delete: + /orchestrator/k8s/resource/delete: + post: description: Delete Kubernetes resource requestBody: required: true @@ -133,7 +133,7 @@ paths: result: $ref: '#/components/schemas/ManifestResponse' - /orchestrator/api-resources/{clusterId}: + /orchestrator/k8s/api-resources/{clusterId}: get: description: Get all API resources for a cluster parameters: @@ -160,7 +160,7 @@ paths: items: $ref: '#/components/schemas/K8sApiResource' - /orchestrator/resource/urls: + /orchestrator/k8s/resource/urls: get: description: Get host URLs by batch parameters: diff --git a/specs/notifications/core.yaml b/specs/notifications/core.yaml index dd456d4b54..a3bb55da76 100644 --- a/specs/notifications/core.yaml +++ b/specs/notifications/core.yaml @@ -2,7 +2,7 @@ openapi: "3.0.0" info: version: 1.0.0 title: Notification Management - description: Devtron API for notification management + description: Devtron API for notification management including settings, channels, and configurations termsOfService: https://devtron.ai/terms/ contact: name: Devtron Labs @@ -16,29 +16,36 @@ servers: paths: /orchestrator/notification: get: - summary: Returns all notification settings - description: Returns all notification settings - operationId: findNotificationSetting + summary: Get all notification settings + description: Returns paginated list of all notification settings + operationId: getAllNotificationSettings parameters: - name: offset in: query - description: value can be regex search string. + description: Number of records to skip for pagination required: true schema: type: integer + minimum: 0 + default: 0 + example: 0 - name: size in: query - description: value can be regex search string. + description: Number of records to return per page required: true schema: type: integer + minimum: 1 + maximum: 100 + default: 20 + example: 20 responses: '200': - description: list response + description: Notification settings retrieved successfully content: application/json: schema: - $ref: '#/components/schemas/NotificationSetting' + $ref: '#/components/schemas/NotificationSettingsViewResponse' '400': description: Bad request - invalid parameters content: @@ -57,12 +64,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Notification settings not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' '500': description: Internal server error content: @@ -70,23 +71,32 @@ paths: schema: $ref: '#/components/schemas/Error' post: - summary: Creates a new NotificationSetting - description: create NotificationSetting api. - operationId: addNotificationSetting + summary: Create notification settings + description: Create new notification settings configuration + operationId: saveNotificationSettingsV2 requestBody: - description: json as request body + description: Notification settings request required: true content: application/json: schema: - $ref: '#/components/schemas/NotificationSetting' + $ref: '#/components/schemas/NotificationRequest' + example: + notificationConfigRequest: + - pipelineType: "CI" + eventTypeIds: [1, 2, 3] + teamId: [1] + providers: + - dest: "slack" + configId: 1 + recipient: "#general" responses: '200': - description: create NotificationSetting response + description: Notification settings created successfully content: application/json: schema: - $ref: '#/components/schemas/NotificationSetting' + $ref: '#/components/schemas/NotificationSettingsResponse' '400': description: Bad request - invalid input data content: @@ -112,23 +122,30 @@ paths: schema: $ref: '#/components/schemas/Error' put: - summary: Update NotificationSetting - description: Update NotificationSetting api either recipients or events(trigger/success/failed). - operationId: updateNotificationSetting + summary: Update notification settings + description: Update existing notification settings configuration + operationId: updateNotificationSettings requestBody: - description: json as request body + description: Notification update request required: true content: application/json: schema: - $ref: '#/components/schemas/NotificationSetting' + $ref: '#/components/schemas/NotificationUpdateRequest' + example: + updateType: "events" + notificationConfigRequest: + - id: 1 + pipelineType: "CI" + eventTypeIds: [1, 2] + teamId: [1] responses: '200': - description: create NotificationSetting response + description: Notification settings updated successfully content: application/json: schema: - $ref: '#/components/schemas/NotificationSetting' + $ref: '#/components/schemas/NotificationSettingsResponse' '400': description: Bad request - invalid input data content: @@ -160,23 +177,29 @@ paths: schema: $ref: '#/components/schemas/Error' delete: - summary: delete NotificationSetting - description: delete NotificationSetting. - operationId: deleteNotificationSetting + summary: Delete notification settings + description: Delete notification settings by IDs + operationId: deleteNotificationSettings requestBody: - description: json as request body + description: Delete request with notification setting IDs required: true content: application/json: schema: - $ref: '#/components/schemas/NotificationSetting' + $ref: '#/components/schemas/NSDeleteRequest' + example: + id: [1, 2, 3] responses: '200': - description: create NotificationSetting response + description: Notification settings deleted successfully content: application/json: schema: - $ref: '#/components/schemas/NotificationSetting' + type: object + properties: + success: + type: boolean + description: Deletion success status '400': description: Bad request - invalid input data content: @@ -208,27 +231,73 @@ paths: schema: $ref: '#/components/schemas/Error' + /orchestrator/notification/v2: + post: + summary: Create notification settings (v2) + description: Create new notification settings configuration (v2 endpoint) + operationId: saveNotificationSettingsV2Alt + requestBody: + description: Notification settings request + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotificationRequest' + responses: + '200': + description: Notification settings created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/NotificationSettingsResponse' + '400': + description: Bad request - invalid input data + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /orchestrator/notification/recipient: get: - summary: used to fetch providers(recipients) - description: recipients fetch by string search, it will return slacks providers and email ids - operationId: deleteGroupPolicy + summary: Get recipient suggestions + description: Get recipient suggestions by search value, returns slack channels and email addresses + operationId: getRecipientListingSuggestion parameters: - name: value in: query - description: value can be regex search string. + description: Search value for recipient suggestions required: true schema: type: string + minLength: 1 + example: "test" responses: '200': - description: list of recipients + description: List of recipient suggestions content: application/json: schema: type: array items: - type: string + $ref: '#/components/schemas/NotificationRecipientListingResponse' '400': description: Bad request - invalid parameters content: @@ -247,12 +316,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Recipients not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' '500': description: Internal server error content: @@ -262,16 +325,16 @@ paths: /orchestrator/notification/channel: get: - summary: get all NotificationSettingConfig list - description: get all NotificationSettingConfig list - operationId: findNotificationSettingConfig + summary: Get all notification channel configurations + description: Get all notification channel configurations (Slack, SES, SMTP, Webhook) + operationId: findAllNotificationConfig responses: '200': - description: list response + description: Notification channel configurations retrieved successfully content: application/json: schema: - $ref: '#/components/schemas/NotificationConfigResponse' + $ref: '#/components/schemas/ChannelResponseDTO' '401': description: Unauthorized user content: @@ -291,23 +354,111 @@ paths: schema: $ref: '#/components/schemas/Error' post: - summary: Creates a new NotificationSettingConfig - description: create NotificationSettingConfig, Slack or SES - operationId: addNotificationSettingConfig + summary: Create notification channel configuration + description: Create notification channel configuration (Slack, SES, SMTP, or Webhook) + operationId: saveNotificationChannelConfig + requestBody: + description: Channel configuration request + required: true + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SlackChannelConfig' + - $ref: '#/components/schemas/SESChannelConfig' + - $ref: '#/components/schemas/SMTPChannelConfig' + - $ref: '#/components/schemas/WebhookChannelConfig' + discriminator: + propertyName: channel + mapping: + slack: '#/components/schemas/SlackChannelConfig' + ses: '#/components/schemas/SESChannelConfig' + smtp: '#/components/schemas/SMTPChannelConfig' + webhook: '#/components/schemas/WebhookChannelConfig' + examples: + slack: + summary: Slack channel configuration + value: + channel: "slack" + configs: + - teamId: 1 + webhookUrl: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX" + configName: "slack-config-1" + description: "Slack notifications for team 1" + ses: + summary: SES channel configuration + value: + channel: "ses" + configs: + - region: "us-east-1" + accessKey: "AKIAIOSFODNN7EXAMPLE" + secretKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" + fromEmail: "noreply@example.com" + configName: "ses-config-1" + description: "SES notifications" + responses: + '200': + description: Channel configuration created successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Creation success status + '400': + description: Bad request - invalid input data + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + summary: Delete notification channel configuration + description: Delete notification channel configuration (Slack, SES, SMTP, or Webhook) + operationId: deleteNotificationChannelConfig requestBody: - description: json as request body + description: Channel configuration delete request required: true content: application/json: schema: - $ref: '#/components/schemas/NotificationConfig' + oneOf: + - $ref: '#/components/schemas/SlackConfigDto' + - $ref: '#/components/schemas/SESConfigDto' + - $ref: '#/components/schemas/SMTPConfigDto' + - $ref: '#/components/schemas/WebhookConfigDto' + discriminator: + propertyName: channel responses: '200': - description: create NotificationSettingConfig response + description: Channel configuration deleted successfully content: application/json: schema: - $ref: '#/components/schemas/NotificationConfigResponse' + type: object + properties: + message: + type: string + description: Success message '400': description: Bad request - invalid input data content: @@ -333,134 +484,907 @@ paths: schema: $ref: '#/components/schemas/Error' -components: - schemas: - NotificationSetting: - type: object - required: - - configName - properties: - id: - type: integer - description: Unique id - configName: - type: string - description: Unique name of group - appId: - type: integer - description: app id - envId: - type: integer - description: env id - pipelineIds: - type: array - items: + /orchestrator/notification/channel/ses/{id}: + get: + summary: Get SES configuration by ID + description: Get SES notification configuration by ID + operationId: findSESConfig + parameters: + - name: id + in: path + description: SES configuration ID + required: true + schema: type: integer - eventTypeIds: - type: array - items: + responses: + '200': + description: SES configuration retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SESConfigDto' + '400': + description: Bad request - invalid ID + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: SES configuration not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/notification/channel/slack/{id}: + get: + summary: Get Slack configuration by ID + description: Get Slack notification configuration by ID + operationId: findSlackConfig + parameters: + - name: id + in: path + description: Slack configuration ID + required: true + schema: type: integer - pipelineType: - type: string - description: pipeline type CI or CD - providers: - type: array - items: - $ref: '#/components/schemas/providers' - description: role filters objects - providers: - type: object - required: - - dest - properties: - dest: - type: string - description: channel destination name - rule: - type: string - description: rule - configId: - type: integer - description: config id + responses: + '200': + description: Slack configuration retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SlackConfigDto' + '400': + description: Bad request - invalid ID + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Slack configuration not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /orchestrator/notification/channel/smtp/{id}: + get: + summary: Get SMTP configuration by ID + description: Get SMTP notification configuration by ID + operationId: findSMTPConfig + parameters: + - name: id + in: path + description: SMTP configuration ID + required: true + schema: + type: integer + responses: + '200': + description: SMTP configuration retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SMTPConfigDto' + '400': + description: Bad request - invalid ID + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: SMTP configuration not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' - NotificationConfig: - type: object - required: - - channel - properties: - channel: - type: string - description: channel type - enum: - - slack - - ses - configs: - type: array - items: - $ref: '#/components/schemas/configs' - description: config holds for either slack or ses - NotificationConfigResponse: - type: object - properties: - slackConfigs: - type: array - items: - $ref: '#/components/schemas/configs' - description: config holds for either slack or ses - sesConfigs: - type: array - items: - $ref: '#/components/schemas/configs' - description: config holds for either slack or ses - configs: - type: object - required: - - type - - configName - properties: - id: - type: integer - description: unique id for config either slack or ses on response or update only - type: - type: string - description: channel destination type, slack or ses - configName: - type: string - description: configName - secretKey: + /orchestrator/notification/channel/webhook/{id}: + get: + summary: Get Webhook configuration by ID + description: Get Webhook notification configuration by ID + operationId: findWebhookConfig + parameters: + - name: id + in: path + description: Webhook configuration ID + required: true + schema: + type: integer + responses: + '200': + description: Webhook configuration retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/WebhookConfigDto' + '400': + description: Bad request - invalid ID + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Webhook configuration not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/notification/variables: + get: + summary: Get webhook variables + description: Get available webhook variables for notification templates + operationId: getWebhookVariables + responses: + '200': + description: Webhook variables retrieved successfully + content: + application/json: + schema: + type: array + items: + type: string + description: Available webhook variable + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/notification/channel/autocomplete/{type}: + get: + summary: Get notification channel autocomplete suggestions + description: Get autocomplete suggestions for notification channels by type + operationId: findAllNotificationConfigAutocomplete + parameters: + - name: type + in: path + description: Channel type (slack, ses, smtp, webhook) + required: true + schema: + type: string + enum: [slack, ses, smtp, webhook] + responses: + '200': + description: Autocomplete suggestions retrieved successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/NotificationChannelAutoResponse' + '400': + description: Bad request - invalid type + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/notification/search: + post: + summary: Get notification settings options + description: Get options for notification settings based on search criteria + operationId: getOptionsForNotificationSettings + requestBody: + description: Search request for notification settings options + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SearchRequest' + example: + teamId: [1, 2] + appId: [1] + pipelineName: "test-pipeline" + responses: + '200': + description: Notification settings options retrieved successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SearchFilterResponse' + '400': + description: Bad request - invalid search criteria + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + # Main notification request/response schemas + NotificationRequest: + type: object + required: + - notificationConfigRequest + properties: + updateType: type: string - description: secretKey, only in case of ses - accessKey: + enum: [events, recipients] + description: Type of update operation + providers: + type: array + items: + $ref: '#/components/schemas/Provider' + description: List of notification providers + notificationConfigRequest: + type: array + items: + $ref: '#/components/schemas/NotificationConfigRequest' + description: List of notification configuration requests + sesConfigId: + type: integer + description: SES configuration ID (deprecated) + + NotificationUpdateRequest: + type: object + required: + - notificationConfigRequest + properties: + updateType: type: string - description: accessKey, only in case of ses - fromEmail: + enum: [events, recipients] + description: Type of update operation + notificationConfigRequest: + type: array + items: + $ref: '#/components/schemas/NotificationConfigRequest' + description: List of notification configuration requests + + NotificationConfigRequest: + type: object + required: + - pipelineType + - eventTypeIds + properties: + id: + type: integer + description: Configuration ID + teamId: + type: array + items: + type: integer + description: List of team IDs + appId: + type: array + items: + type: integer + description: List of application IDs + envId: + type: array + items: + type: integer + description: List of environment IDs + clusterId: + type: array + items: + type: integer + description: List of cluster IDs + pipelineId: + type: integer + description: Pipeline ID + pipelineType: type: string - description: fromEmail, only in case of ses - region: + enum: [CI, CD] + description: Pipeline type + eventTypeIds: + type: array + items: + type: integer + description: List of event type IDs + providers: + type: array + items: + $ref: '#/components/schemas/Provider' + description: List of notification providers + + Provider: + type: object + required: + - dest + - configId + properties: + dest: + type: string + enum: [slack, ses, smtp, webhook] + description: Destination channel type + rule: + type: string + description: Notification rule + configId: + type: integer + description: Configuration ID + recipient: + type: string + description: Recipient information + + NSDeleteRequest: + type: object + properties: + id: + type: array + items: + type: integer + description: List of notification setting IDs to delete + + NotificationSettingsViewResponse: + type: object + properties: + total: + type: integer + description: Total number of notification settings + settings: + type: array + items: + $ref: '#/components/schemas/NotificationSettingsResponse' + description: List of notification settings + + NotificationSettingsResponse: + type: object + properties: + id: + type: integer + description: Notification setting ID + configName: type: string - description: region, only in case of ses + description: Configuration name + team: + type: array + items: + $ref: '#/components/schemas/TeamResponse' + description: Associated teams + app: + type: array + items: + $ref: '#/components/schemas/AppResponse' + description: Associated applications + environment: + type: array + items: + $ref: '#/components/schemas/EnvResponse' + description: Associated environments + cluster: + type: array + items: + $ref: '#/components/schemas/ClusterResponse' + description: Associated clusters + pipeline: + $ref: '#/components/schemas/PipelineResponse' + description: Associated pipeline + pipelineType: + type: string + description: Pipeline type + providerConfigs: + type: array + items: + $ref: '#/components/schemas/ProvidersConfig' + description: Provider configurations + eventTypes: + type: array + items: + type: integer + description: Event type IDs + + # Channel configuration schemas + ChannelResponseDTO: + type: object + properties: + slackConfigs: + type: array + items: + $ref: '#/components/schemas/SlackConfigDto' + description: Slack configurations + webhookConfigs: + type: array + items: + $ref: '#/components/schemas/WebhookConfigDto' + description: Webhook configurations + sesConfigs: + type: array + items: + $ref: '#/components/schemas/SESConfigDto' + description: SES configurations + smtpConfigs: + type: array + items: + $ref: '#/components/schemas/SMTPConfigDto' + description: SMTP configurations + + SlackChannelConfig: + type: object + required: + - channel + - configs + properties: + channel: + type: string + enum: [slack] + description: Channel type + configs: + type: array + items: + $ref: '#/components/schemas/SlackConfigDto' + description: Slack configurations + + SlackConfigDto: + type: object + required: + - teamId + - webhookUrl + - configName + properties: + id: + type: integer + description: Configuration ID + userId: + type: integer + description: User ID + teamId: + type: integer + description: Team ID webhookUrl: type: string - description: webhook url, only fill in case of type is slack + description: Slack webhook URL + configName: + type: string + description: Configuration name + description: + type: string + description: Configuration description + + SESChannelConfig: + type: object + required: + - channel + - configs + properties: + channel: + type: string + enum: [ses] + description: Channel type + configs: + type: array + items: + $ref: '#/components/schemas/SESConfigDto' + description: SES configurations + + SESConfigDto: + type: object + required: + - region + - accessKey + - secretKey + - fromEmail + - configName + properties: + id: + type: integer + description: Configuration ID + ownerId: + type: integer + description: Owner user ID teamId: type: integer - description: project id, only fill in case of type is slack + description: Team ID + region: + type: string + description: AWS region + accessKey: + type: string + description: AWS access key + secretKey: + type: string + description: AWS secret key + fromEmail: + type: string + format: email + description: From email address + toEmail: + type: string + description: To email address + sessionToken: + type: string + description: AWS session token + configName: + type: string + description: Configuration name + description: + type: string + description: Configuration description + default: + type: boolean + description: Whether this is the default configuration + + SMTPChannelConfig: + type: object + required: + - channel + - configs + properties: + channel: + type: string + enum: [smtp] + description: Channel type + configs: + type: array + items: + $ref: '#/components/schemas/SMTPConfigDto' + description: SMTP configurations + + SMTPConfigDto: + type: object + properties: + id: + type: integer + description: Configuration ID + port: + type: string + description: SMTP port + host: + type: string + description: SMTP host + authType: + type: string + description: Authentication type + authUser: + type: string + description: Authentication username + authPassword: + type: string + description: Authentication password + fromEmail: + type: string + format: email + description: From email address + configName: + type: string + description: Configuration name + description: + type: string + description: Configuration description + ownerId: + type: integer + description: Owner user ID + default: + type: boolean + description: Whether this is the default configuration + deleted: + type: boolean + description: Whether this configuration is deleted + + WebhookChannelConfig: + type: object + required: + - channel + - configs + properties: + channel: + type: string + enum: [webhook] + description: Channel type + configs: + type: array + items: + $ref: '#/components/schemas/WebhookConfigDto' + description: Webhook configurations + + WebhookConfigDto: + type: object + required: + - webhookUrl + - configName + properties: + id: + type: integer + description: Configuration ID userId: type: integer - description: project id, only fill in case of type is slack + description: User ID + webhookUrl: + type: string + format: uri + description: Webhook URL + configName: + type: string + description: Configuration name + header: + type: object + additionalProperties: true + description: HTTP headers for webhook + payload: + type: string + description: Webhook payload template + description: + type: string + description: Configuration description + + # Response schemas for entities + TeamResponse: + type: object + properties: + id: + type: integer + description: Team ID + name: + type: string + description: Team name + + AppResponse: + type: object + properties: + id: + type: integer + description: Application ID + name: + type: string + description: Application name + + EnvResponse: + type: object + properties: + id: + type: integer + description: Environment ID + name: + type: string + description: Environment name + + ClusterResponse: + type: object + properties: + id: + type: integer + description: Cluster ID + name: + type: string + description: Cluster name + + PipelineResponse: + type: object + properties: + id: + type: integer + description: Pipeline ID + name: + type: string + description: Pipeline name + environmentName: + type: string + description: Environment name + appName: + type: string + description: Application name + branches: + type: array + items: + type: string + description: Git branches + clusterName: + type: string + description: Cluster name - entity: + ProvidersConfig: type: object properties: id: type: integer - description: it contains entity id + description: Provider configuration ID + dest: + type: string + description: Destination channel name: type: string - description: it contains entity name + description: Configuration name + recipient: + type: string + description: Recipient information + + # Utility schemas + NotificationRecipientListingResponse: + type: object + properties: + dest: + type: string + enum: [slack, ses, smtp, webhook] + description: Destination channel type + configId: + type: integer + description: Configuration ID + recipient: + type: string + description: Recipient information + NotificationChannelAutoResponse: + type: object + properties: + configName: + type: string + description: Configuration name + id: + type: integer + description: Configuration ID + SearchRequest: + type: object + properties: + teamId: + type: array + items: + type: integer + description: List of team IDs + envId: + type: array + items: + type: integer + description: List of environment IDs + appId: + type: array + items: + type: integer + description: List of application IDs + clusterId: + type: array + items: + type: integer + description: List of cluster IDs + pipelineName: + type: string + description: Pipeline name filter + + SearchFilterResponse: + type: object + properties: + team: + type: array + items: + $ref: '#/components/schemas/TeamResponse' + description: Team options + app: + type: array + items: + $ref: '#/components/schemas/AppResponse' + description: Application options + environment: + type: array + items: + $ref: '#/components/schemas/EnvResponse' + description: Environment options + cluster: + type: array + items: + $ref: '#/components/schemas/ClusterResponse' + description: Cluster options + pipeline: + $ref: '#/components/schemas/PipelineResponse' + description: Pipeline options + pipelineType: + type: string + description: Pipeline type Error: required: diff --git a/specs/notifications/webhooks.yaml b/specs/notifications/webhooks.yaml index 3746ad58ed..47cb526c37 100644 --- a/specs/notifications/webhooks.yaml +++ b/specs/notifications/webhooks.yaml @@ -275,129 +275,9 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' - # Notification Webhook APIs - /orchestrator/webhook/notification: - post: - description: Create or update notification webhook configuration - operationId: SaveNotificationWebhook - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/WebhookChannelConfig' - responses: - '200': - description: Webhook configuration saved successfully - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - description: Success status - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - '403': - description: Forbidden - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /orchestrator/webhook/notification/{id}: - get: - description: Get notification webhook configuration by ID - operationId: GetNotificationWebhook - parameters: - - name: id - in: path - description: Webhook configuration ID - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: Webhook configuration retrieved successfully - content: - application/json: - schema: - $ref: '#/components/schemas/WebhookConfigDto' - '400': - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - '403': - description: Forbidden - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /orchestrator/webhook/notification/variables: - get: - description: Get available webhook variables - operationId: GetWebhookVariables - responses: - '200': - description: Webhook variables retrieved successfully - content: - application/json: - schema: - type: array - items: - type: string - description: Available webhook variable - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - '403': - description: Forbidden - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' + components: schemas: diff --git a/specs/plugins/config-maps.yaml b/specs/plugins/config-maps.yaml index 93e2dc837b..f4e98f2e51 100644 --- a/specs/plugins/config-maps.yaml +++ b/specs/plugins/config-maps.yaml @@ -5,7 +5,7 @@ info: version: "1.0" paths: - /orchestrator/configmap/global: + /orchestrator/config/global/cm: post: description: Create or update a global ConfigMap operationId: CMGlobalAddUpdate @@ -47,7 +47,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/configmap/environment: + /orchestrator/config/environment/cm: post: description: Create or update an environment-specific ConfigMap operationId: CMEnvironmentAddUpdate @@ -89,7 +89,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/configmap/global/{appId}: + /orchestrator/config/global/cm/{appId}: get: description: Get all global ConfigMaps for an application operationId: CMGlobalFetch @@ -131,7 +131,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/configmap/environment/{appId}/{envId}: + /orchestrator/config/environment/cm/{appId}/{envId}: get: description: Get all environment-specific ConfigMaps for an application operationId: CMEnvironmentFetch @@ -178,7 +178,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/configmap/global/edit/{appId}/{id}: + /orchestrator/config/global/cm/edit/{appId}/{id}: get: description: Get a global ConfigMap for editing operationId: CMGlobalFetchForEdit @@ -230,7 +230,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/configmap/environment/edit/{appId}/{envId}/{id}: + /orchestrator/config/environment/cm/edit/{appId}/{envId}/{id}: get: description: Get an environment-specific ConfigMap for editing operationId: CMEnvironmentFetchForEdit @@ -287,7 +287,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/configmap/global/{appId}/{id}: + /orchestrator/config/global/cm/{appId}/{id}: delete: description: Delete a global ConfigMap operationId: CMGlobalDelete @@ -339,7 +339,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/configmap/environment/{appId}/{envId}/{id}: + /orchestrator/config/environment/cm/{appId}/{envId}/{id}: delete: description: Delete an environment-specific ConfigMap operationId: CMEnvironmentDelete @@ -396,7 +396,7 @@ paths: schema: $ref: '#/components/schemas/Error' - /orchestrator/configmap/bulk/patch: + /orchestrator/config/bulk/patch: post: description: Bulk patch ConfigMaps and Secrets operationId: ConfigSecretBulkPatch diff --git a/specs/swagger/openapi.html b/specs/swagger/openapi.html deleted file mode 100644 index c1512dd32b..0000000000 --- a/specs/swagger/openapi.html +++ /dev/null @@ -1,1547 +0,0 @@ - - - - - - Common Devtron automation APIs - - - - - - - - - -

Common Devtron automation APIs (1.0.0)

Download OpenAPI specification:

Labels

List Application Labels

Retrieves a list of application labels. By default, returns all labels. -Use the showPropagatedOnly parameter to filter for labels where propagate = true.

-

Required Token Permission:

-
    -
  • Must have View access to the applications in scope.
  • -
-
Authorizations:
bearerAuthapiKeyAuth
query Parameters
showPropagatedOnly
boolean
Default: false

If true, only returns labels where propagate = true. -If false or not provided, all labels are returned.

-

Responses

Response samples

Content type
application/json
Example

Example response when showPropagatedOnly is false or not provided

-
{
  • "code": 200,
  • "status": "OK",
  • "result": [
    ]
}

BulkGetData

Get Readme for Bulk Update

Returns Readme for bulk update for different resource in the url

-
Authorizations:
bearerAuthapiKeyAuth
path Parameters
apiVersion
required
string
kind
required
string

Responses

Response samples

Content type
application/json
{
  • "resource": "string",
  • "script": {
    },
  • "readMe": "string"
}

Dry Run for Bulk Application Update

Returns details(id, name, envId) of all apps to be impacted with bulk update

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

A JSON object containing information by which apps will be filtered

-
apiVersion
string

Api version from url

-
kind
string

Kind

-
object (BulkUpdatePayload)

Responses

Request samples

Content type
application/json
{
  • "apiVersion": [
    ],
  • "kind": [
    ],
  • "spec": {
    }
}

Response samples

Content type
application/json
[
  • {
    }
]

BulkUpdate

Bulk Hibernate Applications

Bulk Hibernates applications

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

A JSON object containing information about applications and environments to hibernate.

-
object (NameIncludesExcludes)
object (NameIncludesExcludes)
envIds
Array of integers

All Env Id's for the bulk action

-
appIds
Array of integers

All App Id's for the bulk action (alternative to includes/excludes by name)

-
projectIds
Array of integers

All Project Id's for the bulk action

-

Responses

Request samples

Content type
application/json
{
  • "includes": {
    },
  • "excludes": {
    },
  • "envIds": [
    ],
  • "appIds": [
    ],
  • "projectIds": [
    ]
}

Response samples

Content type
application/json
{
  • "message": [
    ],
  • "failure": [
    ],
  • "successful": [
    ]
}

Bulk Un-Hibernate Applications

Bulk Un-Hibernates applications

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

A JSON object containing information about applications and environments to un-hibernate.

-
object (NameIncludesExcludes)
object (NameIncludesExcludes)
envIds
Array of integers

All Env Id's for the bulk action

-
appIds
Array of integers

All App Id's for the bulk action (alternative to includes/excludes by name)

-
projectIds
Array of integers

All Project Id's for the bulk action

-

Responses

Request samples

Content type
application/json
{
  • "includes": {
    },
  • "excludes": {
    },
  • "envIds": [
    ],
  • "appIds": [
    ],
  • "projectIds": [
    ]
}

Response samples

Content type
application/json
{
  • "message": [
    ],
  • "failure": [
    ],
  • "successful": [
    ]
}

Bulk Deploy Applications

Bulk Triggers deployment of applications

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

A JSON object containing information for bulk deployment.

-
object (NameIncludesExcludes)
object (NameIncludesExcludes)
envIds
required
Array of integers

All Env Id's for the bulk deployment

-
appIds
Array of integers

All App Id's for the bulk deployment (alternative to includes/excludes by name)

-
projectIds
Array of integers

All Project Id's for the bulk deployment

-
artifactId
integer

ID of the CI artifact to be deployed

-
releaseId
integer

ID of the release to be deployed

-
deploymentStrategy
string

Deployment strategy to use (e.g., blue-green, canary, recreate)

-

Responses

Request samples

Content type
application/json
{
  • "includes": {
    },
  • "excludes": {
    },
  • "envIds": [
    ],
  • "appIds": [
    ],
  • "projectIds": [
    ],
  • "artifactId": 0,
  • "releaseId": 0,
  • "deploymentStrategy": "string"
}

Response samples

Content type
application/json
{
  • "message": [
    ],
  • "failure": [
    ],
  • "successful": [
    ]
}

Bulk Trigger Application Builds

Bulk Triggers build of applications

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

A JSON object containing information for bulk build trigger.

-
object (NameIncludesExcludes)
object (NameIncludesExcludes)
appIds
Array of integers

All App Id's for the bulk build trigger (alternative to includes/excludes by name)

-
projectIds
Array of integers

All Project Id's for the bulk build trigger

-
ciPipelineId
required
integer

ID of the CI pipeline to trigger builds for

-

Responses

Request samples

Content type
application/json
{
  • "includes": {
    },
  • "excludes": {
    },
  • "appIds": [
    ],
  • "projectIds": [
    ],
  • "ciPipelineId": 0
}

Response samples

Content type
application/json
{
  • "message": [
    ],
  • "failure": [
    ],
  • "successful": [
    ]
}

Bulk Edit Applications

Bulk Updates (Edit) all impacted apps. This endpoint can be used for bulk editing application configurations like deployment templates, configmaps, and secrets.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

A JSON object containing information about update changes and by which apps will be filtered for bulk editing.

-
apiVersion
string

Api version from url

-
kind
string

Kind

-
object (BulkUpdatePayload)

Responses

Request samples

Content type
application/json
{
  • "apiVersion": [
    ],
  • "kind": [
    ],
  • "spec": {
    }
}

Response samples

Content type
application/json
{
  • "deploymentTemplate": {
    },
  • "configMap": {
    },
  • "secret": {
    }
}

SSO Configuration

Manage Single Sign-On (SSO) provider configurations.

-

Create SSO Login Configuration

Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

SSO Login Configuration object

-
name
required
string
label
string or null
url
required
string or null <url>
config
required
object

Configuration for the SSO provider (Dex connector config). Structure varies.

-
active
required
boolean

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "label": "string",
  • "url": "string",
  • "config": { },
  • "active": true
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "label": "string",
  • "url": "string",
  • "config": { },
  • "active": true
}

Update SSO Login Configuration

Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

SSO Login Configuration object

-
name
required
string
label
string or null
url
required
string or null <url>
config
required
object

Configuration for the SSO provider (Dex connector config). Structure varies.

-
active
required
boolean

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "label": "string",
  • "url": "string",
  • "config": { },
  • "active": true
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "label": "string",
  • "url": "string",
  • "config": { },
  • "active": true
}

Get All SSO Login Configurations

Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get SSO Login Configuration by ID

Authorizations:
bearerAuthapiKeyAuth
path Parameters
id
required
integer <int32>

Identifier (typically integer ID).

-

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "label": "string",
  • "url": "string",
  • "config": { },
  • "active": true
}

Get SSO Login Configuration by Name

Authorizations:
bearerAuthapiKeyAuth
query Parameters
name
required
string

Name of the SSO configuration.

-

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "label": "string",
  • "url": "string",
  • "config": { },
  • "active": true
}

User Management

Operations related to user accounts (CRUD, listing, bulk actions).

-

List Users (V2 - Paginated, Filtered)

Authorizations:
bearerAuthapiKeyAuth
query Parameters
searchKey
string

Search term.

-
sortOrder
string
Enum: "ASC" "DESC"

Sort order (ASC or DESC).

-
sortBy
string
Enum: "email_id" "last_login"

Field to sort users by (e.g., email_id, last_login).

-
offset
integer <int32> >= 0

Offset for pagination.

-
size
integer <int32> >= 1
Default: 20

Number of items per page.

-

Responses

Response samples

Content type
application/json
{
  • "users": [
    ],
  • "totalCount": 0
}

Create User (V2)

Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

User Information object

-
id
integer <int32>

User ID. Should not be set for new user creation if auto-generated. Not allowed to be system-admin-userid (1 or 2) by validation.

-
email_id
required
string <email>

User's email address. Cannot be system admin user email by validation.

-
roles
Array of strings or null

List of direct roles assigned to the user (deprecated in favor of roleFilters and userRoleGroups).

-
Array of objects (RoleFilter)
groups
Array of strings or null

Deprecated field for user groups. Use userRoleGroups instead.

-
Array of objects or null (UserRoleGroup)
superAdmin
boolean

Indicates if the user has super admin privileges.

-

Responses

Request samples

Content type
application/json
{
  • "id": 0,
  • "email_id": "user@example.com",
  • "roles": [
    ],
  • "roleFilters": [
    ],
  • "groups": [
    ],
  • "userRoleGroups": [
    ],
  • "superAdmin": true
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "email_id": "user@example.com",
  • "roles": [
    ],
  • "accessToken": "string",
  • "roleFilters": [
    ],
  • "groups": [
    ],
  • "userRoleGroups": [
    ],
  • "superAdmin": true,
  • "lastLoginTime": "2019-08-24T14:15:22Z"
}

Update User (V2)

Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

User Information object

-
id
integer <int32>

User ID. Should not be set for new user creation if auto-generated. Not allowed to be system-admin-userid (1 or 2) by validation.

-
email_id
required
string <email>

User's email address. Cannot be system admin user email by validation.

-
roles
Array of strings or null

List of direct roles assigned to the user (deprecated in favor of roleFilters and userRoleGroups).

-
Array of objects (RoleFilter)
groups
Array of strings or null

Deprecated field for user groups. Use userRoleGroups instead.

-
Array of objects or null (UserRoleGroup)
superAdmin
boolean

Indicates if the user has super admin privileges.

-

Responses

Request samples

Content type
application/json
{
  • "id": 0,
  • "email_id": "user@example.com",
  • "roles": [
    ],
  • "roleFilters": [
    ],
  • "groups": [
    ],
  • "userRoleGroups": [
    ],
  • "superAdmin": true
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "email_id": "user@example.com",
  • "roles": [
    ],
  • "accessToken": "string",
  • "roleFilters": [
    ],
  • "groups": [
    ],
  • "userRoleGroups": [
    ],
  • "superAdmin": true,
  • "lastLoginTime": "2019-08-24T14:15:22Z"
}

List All Users (V1)

Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create User

Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

User Information object

-
id
integer <int32>

User ID. Should not be set for new user creation if auto-generated. Not allowed to be system-admin-userid (1 or 2) by validation.

-
email_id
required
string <email>

User's email address. Cannot be system admin user email by validation.

-
roles
Array of strings or null

List of direct roles assigned to the user (deprecated in favor of roleFilters and userRoleGroups).

-
Array of objects (RoleFilter)
groups
Array of strings or null

Deprecated field for user groups. Use userRoleGroups instead.

-
Array of objects or null (UserRoleGroup)
superAdmin
boolean

Indicates if the user has super admin privileges.

-

Responses

Request samples

Content type
application/json
{
  • "id": 0,
  • "email_id": "user@example.com",
  • "roles": [
    ],
  • "roleFilters": [
    ],
  • "groups": [
    ],
  • "userRoleGroups": [
    ],
  • "superAdmin": true
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "email_id": "user@example.com",
  • "roles": [
    ],
  • "accessToken": "string",
  • "roleFilters": [
    ],
  • "groups": [
    ],
  • "userRoleGroups": [
    ],
  • "superAdmin": true,
  • "lastLoginTime": "2019-08-24T14:15:22Z"
}

Update User

Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

User Information object

-
id
integer <int32>

User ID. Should not be set for new user creation if auto-generated. Not allowed to be system-admin-userid (1 or 2) by validation.

-
email_id
required
string <email>

User's email address. Cannot be system admin user email by validation.

-
roles
Array of strings or null

List of direct roles assigned to the user (deprecated in favor of roleFilters and userRoleGroups).

-
Array of objects (RoleFilter)
groups
Array of strings or null

Deprecated field for user groups. Use userRoleGroups instead.

-
Array of objects or null (UserRoleGroup)
superAdmin
boolean

Indicates if the user has super admin privileges.

-

Responses

Request samples

Content type
application/json
{
  • "id": 0,
  • "email_id": "user@example.com",
  • "roles": [
    ],
  • "roleFilters": [
    ],
  • "groups": [
    ],
  • "userRoleGroups": [
    ],
  • "superAdmin": true
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "email_id": "user@example.com",
  • "roles": [
    ],
  • "accessToken": "string",
  • "roleFilters": [
    ],
  • "groups": [
    ],
  • "userRoleGroups": [
    ],
  • "superAdmin": true,
  • "lastLoginTime": "2019-08-24T14:15:22Z"
}

Get User by ID

Authorizations:
bearerAuthapiKeyAuth
path Parameters
id
required
integer <int32>

Identifier (typically integer ID).

-

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "email_id": "user@example.com",
  • "roles": [
    ],
  • "accessToken": "string",
  • "roleFilters": [
    ],
  • "groups": [
    ],
  • "userRoleGroups": [
    ],
  • "superAdmin": true,
  • "lastLoginTime": "2019-08-24T14:15:22Z"
}

Delete User by ID

Authorizations:
bearerAuthapiKeyAuth
path Parameters
id
required
integer <int32>

Identifier (typically integer ID).

-

Responses

Response samples

Content type
application/json
{
  • "success": true
}

Get User by ID (V2)

Authorizations:
bearerAuthapiKeyAuth
path Parameters
id
required
integer <int32>

Identifier (typically integer ID).

-

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "email_id": "user@example.com",
  • "roles": [
    ],
  • "accessToken": "string",
  • "roleFilters": [
    ],
  • "groups": [
    ],
  • "userRoleGroups": [
    ],
  • "superAdmin": true,
  • "lastLoginTime": "2019-08-24T14:15:22Z"
}

Bulk Delete Users

Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
{
  • "success": true
}

List All Detailed Users

Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Role Group Management

Operations related to user role groups (CRUD, listing, bulk actions).

-

List Role Groups (V2 - Paginated, Filtered)

Authorizations:
bearerAuthapiKeyAuth
query Parameters
searchKey
string

Search term.

-
sortOrder
string
Enum: "ASC" "DESC"

Sort order (ASC or DESC).

-
sortBy
string
Value: "name"

Field to sort role groups by (e.g., name).

-
offset
integer <int32> >= 0

Offset for pagination.

-
size
integer <int32> >= 1
Default: 20

Number of items per page.

-

Responses

Response samples

Content type
application/json
{
  • "roleGroups": [
    ],
  • "totalCount": 0
}

Create Role Group (V2)

Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

Role Group object

-
name
required
string
description
string or null
required
Array of objects (RoleFilter)
superAdmin
boolean

Indicates if this role group grants super admin privileges.

-

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "description": "string",
  • "roleFilters": [
    ],
  • "superAdmin": true
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "description": "string",
  • "roleFilters": [
    ],
  • "superAdmin": true
}

Update Role Group (V2)

Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

Role Group object

-
name
required
string
description
string or null
required
Array of objects (RoleFilter)
superAdmin
boolean

Indicates if this role group grants super admin privileges.

-

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "description": "string",
  • "roleFilters": [
    ],
  • "superAdmin": true
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "description": "string",
  • "roleFilters": [
    ],
  • "superAdmin": true
}

List All Role Groups (V1)

Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create Role Group

Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

Role Group object

-
name
required
string
description
string or null
required
Array of objects (RoleFilter)
superAdmin
boolean

Indicates if this role group grants super admin privileges.

-

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "description": "string",
  • "roleFilters": [
    ],
  • "superAdmin": true
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "description": "string",
  • "roleFilters": [
    ],
  • "superAdmin": true
}

Update Role Group

Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

Role Group object

-
name
required
string
description
string or null
required
Array of objects (RoleFilter)
superAdmin
boolean

Indicates if this role group grants super admin privileges.

-

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "description": "string",
  • "roleFilters": [
    ],
  • "superAdmin": true
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "description": "string",
  • "roleFilters": [
    ],
  • "superAdmin": true
}

Get Role Group by ID

Authorizations:
bearerAuthapiKeyAuth
path Parameters
id
required
integer <int32>

Identifier (typically integer ID).

-

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "description": "string",
  • "roleFilters": [
    ],
  • "superAdmin": true
}

Delete Role Group by ID

Authorizations:
bearerAuthapiKeyAuth
path Parameters
id
required
integer <int32>

Identifier (typically integer ID).

-

Responses

Response samples

Content type
application/json
{
  • "success": true
}

Get Role Group by ID (V2)

Authorizations:
bearerAuthapiKeyAuth
path Parameters
id
required
integer <int32>

Identifier (typically integer ID).

-

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "description": "string",
  • "roleFilters": [
    ],
  • "superAdmin": true
}

List All Detailed Role Groups

Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
{
  • "roleGroups": [
    ],
  • "totalCount": 0
}

Search Role Groups by Name

Authorizations:
bearerAuthapiKeyAuth
query Parameters
name
required
string

Name of the role group to search for.

-

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "description": "string",
  • "roleFilters": [
    ],
  • "superAdmin": true
}

Bulk Delete Role Groups

Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
{
  • "success": true
}

RBAC

Operations related to Role-Based Access Control, like fetching default roles.

-

Get All Default Roles

Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Authentication

Core authentication endpoints including login, token refresh, and auth verification.

-

User Login

Authenticates a user and returns a session token.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

Username and password for login.

-
username
required
string
password
required
string <password>

Responses

Request samples

Content type
application/json
{
  • "username": "admin",
  • "password": "password123"
}

Response samples

Content type
application/json
{
  • "token": "string"
}

Refresh Session Token

Handles token refresh (details depend on OIDC/OAuth flow).

-
Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "status": "string",
  • "result": { },
  • "errors": [
    ]
}

Verify Authentication Status

Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
true

Verify Authentication Status (V2)

Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
{
  • "isSuperAdmin": true,
  • "isVerified": true,
  • "emailId": "string"
}

Check Logged-in User's Roles

Authorizations:
bearerAuthapiKeyAuth
query Parameters
appName
string

Optional application name to filter roles for.

-

Responses

Response samples

Content type
application/json
{
  • "role": "string",
  • "roles": [
    ],
  • "superAdmin": true
}

OIDC Login Redirect (Informational)

Initiates OIDC login flow. Handled by the OIDC client library.

-
Authorizations:
bearerAuthapiKeyAuth

Responses

OIDC Login Redirect (Informational - Alternate Path)

Initiates OIDC login flow. Handled by the OIDC client library.

-
Authorizations:
bearerAuthapiKeyAuth

Responses

OIDC Callback (Informational)

Handles the callback from the OIDC provider. Handled by the OIDC client library.

-
Authorizations:
bearerAuthapiKeyAuth

Responses

Dex Proxy (Informational)

Proxies requests to the Dex IdP. Handled by the Dex proxy mechanism.

-
Authorizations:
bearerAuthapiKeyAuth
path Parameters
path
required
string

Path to be proxied to Dex.

-

Responses

Policy Management

Endpoints for managing policies.

-

Add Default Policy and Roles

Creates default policies and roles based on team, app, and environment. This is a specialized endpoint.

-
Authorizations:
bearerAuthapiKeyAuth
query Parameters
team
required
string
app
required
string
env
required
string

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "status": "string",
  • "result": { },
  • "errors": [
    ]
}

Sync Orchestrator to Casbin

Synchronizes policies from orchestrator to Casbin. Requires admin privileges.

-
Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
true

Update Trigger Policy for Terminal Access

Updates trigger policies related to terminal access. Requires global update privileges.

-
Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
"string"

Cache Management

Endpoints for managing authentication and authorization caches.

-

Get Role Cache Dump

Retrieves a dump of the role cache. Requires super admin privileges.

-
Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
{ }

Invalidate Role Cache

Clears the role cache. Requires super admin privileges.

-
Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
"string"

Cluster Environment

Operations related to clusters and environments

-

List clusters with their environments

Provides a list of all clusters and the environments within each.

-
Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
[
  • {
    }
]

List environments for a specific cluster

Provides a list of all environments for a given cluster ID.

-
Authorizations:
bearerAuthapiKeyAuth
path Parameters
cluster_id
required
integer

ID of the cluster

-

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Cluster Management

Operations related to cluster creation, update, and validation

-

Delete Cluster

Delete an existing cluster.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

A JSON object containing the cluster config (primarily ID is used for deletion)

-
id
integer
cluster_name
string
server_url
string
prometheus_url
string
active
boolean
object
object (PrometheusAuthGet)
Array of objects (DefaultClusterComponentGet)
k8sversion
string

Responses

Request samples

Content type
application/json
{
  • "id": 0,
  • "cluster_name": "string",
  • "server_url": "string",
  • "prometheus_url": "string",
  • "active": true,
  • "config": {
    },
  • "prometheusAuth": {
    },
  • "defaultClusterComponents": [
    ],
  • "k8sversion": "string"
}

Response samples

Content type
application/json
{
  • "message": "Cluster deleted successfully."
}

Update Cluster

Update an existing cluster's configuration.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

A JSON object containing the cluster config

-
id
integer
cluster_name
string
server_url
string
prometheus_url
string
active
boolean
object
object (PrometheusAuthGet)
Array of objects (DefaultClusterComponentGet)
k8sversion
string

Responses

Request samples

Content type
application/json
{
  • "id": 0,
  • "cluster_name": "string",
  • "server_url": "string",
  • "prometheus_url": "string",
  • "active": true,
  • "config": {
    },
  • "prometheusAuth": {
    },
  • "defaultClusterComponents": [
    ],
  • "k8sversion": "string"
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "cluster_name": "string",
  • "server_url": "string",
  • "prometheus_url": "string",
  • "active": true,
  • "config": {
    },
  • "prometheusAuth": {
    },
  • "defaultClusterComponents": [
    ],
  • "k8sversion": "string"
}

Get Cluster

Get details of a specific cluster by ID.

-
Authorizations:
bearerAuthapiKeyAuth
query Parameters
id
required
integer

cluster id.

-

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "cluster_name": "string",
  • "server_url": "string",
  • "prometheus_url": "string",
  • "active": true,
  • "config": {
    },
  • "prometheusAuth": {
    },
  • "defaultClusterComponents": [
    ],
  • "k8sversion": "string"
}

List Accessible Clusters

list of clusters accessible to the authenticated user.

-
Authorizations:
bearerAuthapiKeyAuth

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "status": "string",
  • "result": [
    ]
}

Validate Cluster Configuration

Validate a cluster configuration using kubeconfig.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required
object (Kubeconfig)

Responses

Request samples

Content type
application/json
{
  • "kubeconfig": {
    }
}

Response samples

Content type
application/json
{
  • "userInfos": {
    },
  • "id": 0,
  • "cluster_name": "string",
  • "server_url": "string",
  • "prometheus_url": "string",
  • "active": true,
  • "config": {
    },
  • "prometheusAuth": {
    },
  • "defaultClusterComponent": [
    ],
  • "agentInstallationStage": 0,
  • "k8sVersion": "string",
  • "userName": "string",
  • "insecure-skip-tls-verify": true
}

Save Multiple Clusters

Save configurations for multiple clusters.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
Array
object
id
integer
cluster_name
required
string
server_url
required
string
prometheus_url
string
active
boolean
object
object (PrometheusAuthAdd)
Array of objects (DefaultClusterComponentAdd)
agentInstallationStage
integer
k8sVersion
string
userName
string
insecure-skip-tls-verify
boolean

Responses

Request samples

Content type
application/json
[
  • {
    }
]

Response samples

Content type
application/json
[
  • {
    }
]

Environment Management

Operations for creating, updating, and deleting environments

-

Create Environment

Create a new environment within a cluster.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

Environment details

-
environment_name
required
string <= 50 characters
cluster_id
required
integer
active
boolean
Default: true
default
boolean
Default: false
prometheus_endpoint
string
namespace
string <= 50 characters
isClusterCdActive
boolean
description
string <= 40 characters
isVirtualEnvironment
boolean
Default: false
allowedDeploymentTypes
Array of strings
Items Enum: "helm" "argo_cd"

Responses

Request samples

Content type
application/json
{
  • "environment_name": "string",
  • "cluster_id": 0,
  • "active": true,
  • "default": false,
  • "prometheus_endpoint": "string",
  • "namespace": "string",
  • "isClusterCdActive": true,
  • "description": "string",
  • "isVirtualEnvironment": false,
  • "allowedDeploymentTypes": [
    ]
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "environment_name": "string",
  • "cluster_id": 0,
  • "cluster_name": "string",
  • "active": true,
  • "default": true,
  • "prometheus_endpoint": "string",
  • "namespace": "string",
  • "isClusterCdActive": true,
  • "environmentIdentifier": "string",
  • "description": "string",
  • "appCount": 0,
  • "isVirtualEnvironment": true,
  • "allowedDeploymentTypes": [
    ]
}

Update Environment

Update an existing environment.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

Environment details to update

-
id
required
integer
environment_name
required
string <= 50 characters
cluster_id
required
integer
active
boolean
default
boolean
prometheus_endpoint
string
namespace
string <= 50 characters
isClusterCdActive
boolean
description
string <= 40 characters
isVirtualEnvironment
boolean
allowedDeploymentTypes
Array of strings
Items Enum: "helm" "argo_cd"

Responses

Request samples

Content type
application/json
{
  • "id": 0,
  • "environment_name": "string",
  • "cluster_id": 0,
  • "active": true,
  • "default": true,
  • "prometheus_endpoint": "string",
  • "namespace": "string",
  • "isClusterCdActive": true,
  • "description": "string",
  • "isVirtualEnvironment": true,
  • "allowedDeploymentTypes": [
    ]
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "environment_name": "string",
  • "cluster_id": 0,
  • "cluster_name": "string",
  • "active": true,
  • "default": true,
  • "prometheus_endpoint": "string",
  • "namespace": "string",
  • "isClusterCdActive": true,
  • "environmentIdentifier": "string",
  • "description": "string",
  • "appCount": 0,
  • "isVirtualEnvironment": true,
  • "allowedDeploymentTypes": [
    ]
}

Get Environment by ID

Get detailed information for a specific environment by its ID.

-
Authorizations:
bearerAuthapiKeyAuth
query Parameters
id
required
integer

ID of the environment

-

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "environment_name": "string",
  • "cluster_id": 0,
  • "cluster_name": "string",
  • "active": true,
  • "default": true,
  • "prometheus_endpoint": "string",
  • "namespace": "string",
  • "isClusterCdActive": true,
  • "environmentIdentifier": "string",
  • "description": "string",
  • "appCount": 0,
  • "isVirtualEnvironment": true,
  • "allowedDeploymentTypes": [
    ]
}

Delete Environment (via POST)

Delete an existing environment using POST method.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

A JSON object containing the env config (primarily ID is used for deletion)

-
id
integer
environment_name
string
cluster_id
integer
cluster_name
string
active
boolean
default
boolean
prometheus_endpoint
string
namespace
string
isClusterCdActive
boolean
environmentIdentifier
string
description
string
appCount
integer
isVirtualEnvironment
boolean
allowedDeploymentTypes
Array of strings
Items Enum: "helm" "argo_cd"

Responses

Request samples

Content type
application/json
{
  • "id": 0,
  • "environment_name": "string",
  • "cluster_id": 0,
  • "cluster_name": "string",
  • "active": true,
  • "default": true,
  • "prometheus_endpoint": "string",
  • "namespace": "string",
  • "isClusterCdActive": true,
  • "environmentIdentifier": "string",
  • "description": "string",
  • "appCount": 0,
  • "isVirtualEnvironment": true,
  • "allowedDeploymentTypes": [
    ]
}

Response samples

Content type
application/json
{
  • "message": "Environment deleted successfully."
}

ChangeChartType

Patch Application Environment

change the deployment template for an app and environment

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
envId
integer
appId
integer
targetChartRefId
integer

Responses

Request samples

Content type
application/json
{
  • "envId": 0,
  • "appId": 0,
  • "targetChartRefId": 0
}

CloneWorkflow (ENT)

Clone Application Workflow

Clones an application workflow from a source environment to a target environment

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

A JSON object containing the details required to clone the workflow

-
appId
integer

ID of the application

-
appName
string

Name of the application

-
sourceEnvironmentId
integer

ID of the source environment

-
sourceEnvironmentName
string

Name of the source environment

-
targetEnvironmentId
integer

ID of the target environment

-
targetEnvironmentName
string

Name of the target environment

-
cloneEnvInSameWorkflow
boolean

Flag indicating if the environment should be cloned in the same workflow

-

Responses

Request samples

Content type
application/json
{
  • "appId": 0,
  • "appName": "string",
  • "sourceEnvironmentId": 0,
  • "sourceEnvironmentName": "string",
  • "targetEnvironmentId": 0,
  • "targetEnvironmentName": "string",
  • "cloneEnvInSameWorkflow": true
}

Response samples

Content type
application/json
{
  • "code": 200,
  • "status": "OK",
  • "result": {
    }
}

K8s Resource

APIs for managing Kubernetes resources (get, create, update, delete, list).

-

Get Resource Manifest

This API is used for fetching the manifest of a specified Kubernetes resource.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

JSON payload specifying the resource to fetch.

-
appId
string

Application ID. Used when the request is context-specific to an application.

-
clusterId
number

Cluster ID. Used when the request is for a direct cluster resource (appId is not supplied).

-
object (K8sRequestObject)

Responses

Request samples

Content type
application/json
{
  • "appId": "my-app/env-1",
  • "clusterId": 1,
  • "k8sRequest": {
    }
}

Response samples

Content type
application/json
{
  • "code": 0,
  • "status": "string",
  • "result": {
    }
}

Update Resource Manifest

This API is used for editing the manifest of a specified Kubernetes resource.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

JSON payload containing the resource identifier and the patch.

-
appId
string

Application ID. Used when the request is context-specific to an application.

-
clusterId
number

Cluster ID. Used when the request is for a direct cluster resource (appId is not supplied).

-
object (K8sRequestObject)

Responses

Request samples

Content type
application/json
{
  • "appId": "my-app/env-1",
  • "clusterId": 1,
  • "k8sRequest": {
    }
}

Response samples

Content type
application/json
{
  • "code": 0,
  • "status": "string",
  • "result": {
    }
}

Create Resource

This API is used for applying a desired manifest to create a Kubernetes resource.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

JSON payload containing the resource manifest to apply.

-
appId
string

Application ID. Used when the request is context-specific to an application.

-
clusterId
number

Cluster ID. Used when the request is for a direct cluster resource (appId is not supplied).

-
object (K8sRequestObject)

Responses

Request samples

Content type
application/json
{
  • "appId": "my-app/env-1",
  • "clusterId": 1,
  • "k8sRequest": {
    }
}

Response samples

Content type
application/json
{
  • "code": 0,
  • "status": "string",
  • "result": {
    }
}

Delete Resource

This API is used for deleting a specified Kubernetes resource.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

JSON payload specifying the resource to delete.

-
appId
string

Application ID. Used when the request is context-specific to an application.

-
clusterId
number

Cluster ID. Used when the request is for a direct cluster resource (appId is not supplied).

-
object (K8sRequestObject)

Responses

Request samples

Content type
application/json
{
  • "appId": "my-app/env-1",
  • "clusterId": 1,
  • "k8sRequest": {
    }
}

Response samples

Content type
application/json
{
  • "code": 0,
  • "status": "string",
  • "result": {
    }
}

Get Resource Events

This API is used for fetching events for Kubernetes resources.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
optional
appId
string

Application ID. Used when the request is context-specific to an application.

-
clusterId
number

Cluster ID. Used when the request is for a direct cluster resource (appId is not supplied).

-
object (K8sRequestObject)

Responses

Request samples

Content type
application/json
{
  • "appId": "my-app/env-1",
  • "clusterId": 1,
  • "k8sRequest": {
    }
}

Get Pod Logs

This API is used for fetching logs for a specified container within a pod.

-
Authorizations:
bearerAuthapiKeyAuth
path Parameters
podName
required
string

Name of the pod.

-
query Parameters
containerName
required
string

Name of the container within the pod.

-
appId
string

Application ID.

-
clusterId
integer

Cluster ID.

-
namespace
string

Namespace of the pod. Required if clusterId is passed.

-
follow
boolean
Default: false

Whether to follow the log stream.

-
sinceSeconds
integer

Return logs newer than a relative duration like 5s, 2m, or 3h. Defaults to all logs.

-
tailLines
integer

If set, the number of lines from the end of the logs to show.

-

Responses

Get Pod Exec Session

This API establishes a session for executing commands in a pod's container (terminal access).

-
Authorizations:
bearerAuthapiKeyAuth
path Parameters
identifier
required
string

Application ID or Cluster ID. Example '2|devtroncd|devtron' or '3'.

-
namespace
required
string
Example: devtroncd

Namespace of the pod.

-
pod
required
string
Example: inception-58d44d99fd-tfw4s

Name of the pod.

-
shell
required
string
Enum: "bash" "sh" "powershell" "cmd"
Example: bash

Shell to invoke.

-
container
required
string
Example: devtron

Name of the container.

-

Responses

Response samples

Content type
application/json
{
  • "Op": "stdin",
  • "Data": "ls -l",
  • "SessionID": "unique-session-id-123"
}

Get API Resources

Get all available API resources for a given cluster ID.

-
Authorizations:
bearerAuthapiKeyAuth
path Parameters
clusterId
required
integer <int64>

ID of the cluster.

-

Responses

Response samples

Content type
application/json
{
  • "apiResources": [
    ],
  • "allowedAll": true
}

List Resources

This API is used for fetching a list of Kubernetes resources based on the request criteria.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

JSON payload specifying the criteria for listing resources.

-
appId
string

Application ID. Used when the request is context-specific to an application.

-
clusterId
number

Cluster ID. Used when the request is for a direct cluster resource (appId is not supplied).

-
object (K8sRequestObject)

Responses

Request samples

Content type
application/json
{
  • "appId": "my-app/env-1",
  • "clusterId": 1,
  • "k8sRequest": {
    }
}

Response samples

Content type
application/json
{
  • "code": 0,
  • "status": "string",
  • "result": [
    ]
}

Rotates the Pods

This API is used to rotate (restart) pods for the provided resources.

-
Authorizations:
bearerAuthapiKeyAuth
query Parameters
appId
required
string

Application ID.

-
Request Body schema: application/json
required

JSON payload specifying the resources for which pods should be rotated.

-
clusterId
required
number

ID of the cluster where resources reside.

-
required
Array of objects

Responses

Request samples

Content type
application/json
{
  • "clusterId": 1,
  • "resources": [
    ]
}

Response samples

Content type
application/json
{
  • "containsError": false,
  • "responses": [
    ]
}

Apply Resources

This API is used to apply (create or update) Kubernetes resources in a cluster.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required

JSON payload containing the manifest of resources to apply.

-
clusterId
required
number

ID of the cluster where resources will be applied.

-
manifest
required
string

A string containing one or more Kubernetes resource manifests, separated by '---'.

-

Responses

Request samples

Content type
application/json
{
  • "clusterId": 1,
  • "manifest": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: my-cm\ndata:\n key: value\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: my-app\nspec:\n replicas: 1\n selector:\n matchLabels:\n app: my-app\n template:\n metadata:\n labels:\n app: my-app\n spec:\n containers:\n - name: nginx\n image: nginx\n"
}

Response samples

Content type
application/json
[
  • {
    }
]

Workflow Management

Create an application workflow

Creates a new workflow for a given application.

-
Authorizations:
bearerAuthapiKeyAuth
Request Body schema: application/json
required
name
string

Name of the workflow.

-
appId
integer

ID of the application this workflow belongs to.

-
Array of objects (AppWorkflowMappingDto)

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "appId": 0,
  • "tree": [
    ]
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "appId": 0,
  • "tree": [
    ]
}

Delete an application workflow

Deletes an existing workflow for a given application.

-
Authorizations:
bearerAuthapiKeyAuth
path Parameters
app-wf-id
required
integer

ID of the application workflow to delete.

-
app-id
required
integer

ID of the application.

-

Responses

Response samples

Content type
application/json
{
  • "status": "OK"
}
- - - - diff --git a/specs/swagger/openapi.yaml b/specs/swagger/openapi.yaml deleted file mode 100644 index b611f714c1..0000000000 --- a/specs/swagger/openapi.yaml +++ /dev/null @@ -1,6524 +0,0 @@ -openapi: 3.0.0 -info: - version: 1.0.0 - title: Devtron APIs Specs - license: - name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0.html -servers: -- url: http://localhost/orchestrator - description: Local development server -tags: -- name: Metadata - description: Application metadata and information retrieval - x-displayName: Application Metadata -- name: Jobs - description: Job management operations for creating, cloning, and retrieving jobs - x-displayName: Job Management -- name: Helm Charts - description: Helm chart deployment management and operations - x-displayName: Helm Chart Management -- name: List Applications - x-displayName: List Applications - description: Application listing -- name: Applications - description: Application management operations including creation, listing, and - updates - x-displayName: Application Management -- name: Labels - x-displayName: Labels -- name: bulk_other - x-displayName: BulkGetData -- name: BulkUpdate - x-displayName: BulkUpdate -- name: SSO Configuration - description: Manage Single Sign-On (SSO) provider configurations. - x-displayName: SSO Configuration -- name: User Management - description: Operations related to user accounts (CRUD, listing, bulk actions). - x-displayName: User Management -- name: Role Group Management - description: Operations related to user role groups (CRUD, listing, bulk actions). - x-displayName: Role Group Management -- name: RBAC - description: Operations related to Role-Based Access Control, like fetching default - roles. - x-displayName: RBAC -- name: Authentication - description: Core authentication endpoints including login, token refresh, and auth - verification. - x-displayName: Authentication -- name: Policy Management - description: Endpoints for managing policies. - x-displayName: Policy Management -- name: Cache Management - description: Endpoints for managing authentication and authorization caches. - x-displayName: Cache Management -- name: Cluster Environment - description: Operations related to clusters and environments - x-displayName: Cluster Environment -- name: Cluster Management - description: Operations related to cluster creation, update, and validation - x-displayName: Cluster Management -- name: Environment Management - description: Operations for creating, updating, and deleting environments - x-displayName: Environment Management -- name: Change Chart - x-displayName: ChangeChartType -- name: Clone Workflow - x-displayName: CloneWorkflow (ENT) -- name: Deployment History - x-displayName: Get Deployment History (ENT) - description: Retrieves the deployment history for a specific CD pipeline based on - various filter criteria. -- name: K8s Resource - description: APIs for managing Kubernetes resources (get, create, update, delete, - list). - x-displayName: K8s Resource -- name: Workflow Management - x-displayName: Workflow Management -- name: Notifications - x-displayName: Notifiactions -- name: Devtron Server version - x-displayName: Devtron Server version -- name: GitOps Validation - x-displayName: GitOps Validation -paths: - /orchestrator/resource/history/deployment/cd-pipeline/v1: - get: - summary: Get Deployment History - description: Retrieves the deployment history for a specific CD pipeline based - on various filter criteria. - operationId: getDeploymentHistory - security: [] - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: filterCriteria - in: query - required: true - schema: - type: array - items: - type: string - description: 'Filter criteria for deployment history. Example: - - - application/devtron-application|id|1064 - - - environment|id|146 - - - release|id|203 - - ' - - name: offset - in: query - required: false - schema: - type: integer - description: The starting point for fetching records (pagination). - - name: limit - in: query - required: false - schema: - type: integer - description: The number of records to return (pagination). - responses: - '200': - description: Successful retrieval of deployment history. - content: - application/json: - schema: - type: object - properties: - code: - type: integer - example: 200 - status: - type: string - example: OK - result: - type: object - properties: - cdWorkflows: - type: array - items: - type: object - properties: - id: - type: integer - example: 19767 - cd_workflow_id: - type: integer - example: 19576 - name: - type: string - example: cd-1064-nu4s - status: - type: string - example: Succeeded - pod_status: - type: string - example: '' - message: - type: string - example: '' - started_on: - type: string - format: date-time - example: '2024-07-25T08:36:42.414376Z' - finished_on: - type: string - format: date-time - example: '2024-07-25T08:40:03.455303Z' - pipeline_id: - type: integer - example: 2082 - namespace: - type: string - example: devtron-cd - log_file_path: - type: string - example: '' - triggered_by: - type: integer - example: 23 - email_id: - type: string - example: deepak@devtron.ai - image: - type: string - example: devtroninc.azurecr.io/test:8a0c2298-fc94fa4b-956-18655 - ci_artifact_id: - type: integer - example: 14593 - workflow_type: - type: string - example: DEPLOY - blobStorageEnabled: - type: boolean - example: true - userApprovalMetadata: - type: object - nullable: true - gitTriggers: - type: object - additionalProperties: - type: object - properties: - Commit: - type: string - example: 8a0c22983ae7acae10abe7569026ae25d889e159 - Author: - type: string - example: jatin-jangir-0220 <122791251+jatin-jangir-0220@users.noreply.github.com> - Date: - type: string - format: date-time - example: '2024-04-29T18:49:39Z' - Message: - type: string - example: 'Update Dockerfile (#19) - - - ' - Changes: - type: string - nullable: true - WebhookData: - type: object - properties: - id: - type: integer - example: 0 - eventActionType: - type: string - example: '' - data: - type: string - nullable: true - CiConfigureSourceValue: - type: string - example: main - GitRepoUrl: - type: string - example: https://github.com/devtron-labs/casbin-enterprise - GitRepoName: - type: string - example: casbin-enterprise - CiConfigureSourceType: - type: string - example: SOURCE_TYPE_BRANCH_FIXED - ciMaterials: - type: array - items: - type: object - properties: - id: - type: integer - example: 1013 - gitMaterialId: - type: integer - example: 411 - gitMaterialUrl: - type: string - example: '' - gitMaterialName: - type: string - example: casbin-enterprise - type: - type: string - example: SOURCE_TYPE_BRANCH_FIXED - value: - type: string - example: main - active: - type: boolean - example: true - lastFetchTime: - type: string - format: date-time - example: '0001-01-01T00:00:00Z' - isRepoError: - type: boolean - example: false - repoErrorMsg: - type: string - example: '' - isBranchError: - type: boolean - example: false - branchErrorMsg: - type: string - example: '' - url: - type: string - example: https://github.com/devtron-labs/casbin-enterprise - regex: - type: string - example: '' - tagsEditable: - type: boolean - example: false - appReleaseTagNames: - type: array - items: - type: string - example: [] - hideImageTaggingHardDelete: - type: boolean - example: false - examples: - example-1: - value: - code: 200 - status: OK - result: - cdWorkflows: - - id: 19752 - cd_workflow_id: 19561 - name: cd-1064-nu4s - status: Failed - pod_status: '' - message: 'Unable to continue with install: could not get information - about the resource Job "" in namespace "devtroncd": resource - name may not be empty' - started_on: '2024-07-25T08:26:21.792068Z' - finished_on: '2024-07-25T08:26:23.855384Z' - pipeline_id: 2082 - namespace: devtron-cd - log_file_path: '' - triggered_by: 23 - email_id: deepak@devtron.ai - image: devtroninc.azurecr.io/test:8a0c2298-fc94fa4b-956-18655 - ci_artifact_id: 14593 - workflow_type: DEPLOY - blobStorageEnabled: true - userApprovalMetadata: null - gitTriggers: - '1013': - Commit: 8a0c22983ae7acae10abe7569026ae25d889e159 - Author: jatin-jangir-0220 <122791251+jatin-jangir-0220@users.noreply.github.com> - Date: '2024-04-29T18:49:39Z' - Message: 'Update Dockerfile (#19) - - - ' - Changes: null - WebhookData: - id: 0 - eventActionType: '' - data: null - CiConfigureSourceValue: main - GitRepoUrl: https://github.com/devtron-labs/casbin-enterprise - GitRepoName: casbin-enterprise - CiConfigureSourceType: SOURCE_TYPE_BRANCH_FIXED - '2072': - Commit: fc94fa4bad21460e822ce896b5166273aa3df1a8 - Author: Gireesh Naidu <111440205+gireesh-naidu@users.noreply.github.com> - Date: '2024-07-23T18:13:18+05:30' - Message: "fix: getting 500 while updating the branch of\ - \ linked CI (#1424)\n\n* fix: sync ci pipeline materials\ - \ for linked pipelines\r\n\r\n* fix: sync ci pipeline\ - \ materials for linked pipelines\r\n\r\n* fix: null\ - \ column fix\r\n\r\n* fix: null column fix\r\n\r\n*\ - \ fix: able to delete ci pipeline though it has linked\ - \ ci's using API" - Changes: null - WebhookData: - id: 0 - eventActionType: '' - data: null - CiConfigureSourceValue: main - GitRepoUrl: https://github.com/devtron-labs/devtron-enterprise - GitRepoName: devtron-enterprise - CiConfigureSourceType: SOURCE_TYPE_BRANCH_FIXED - ciMaterials: - - id: 1013 - gitMaterialId: 411 - gitMaterialUrl: '' - gitMaterialName: casbin-enterprise - type: SOURCE_TYPE_BRANCH_FIXED - value: main - active: true - lastFetchTime: '0001-01-01T00:00:00Z' - isRepoError: false - repoErrorMsg: '' - isBranchError: false - branchErrorMsg: '' - url: https://github.com/devtron-labs/casbin-enterprise - regex: '' - - id: 2072 - gitMaterialId: 1286 - gitMaterialUrl: '' - gitMaterialName: devtron-enterprise - type: SOURCE_TYPE_BRANCH_FIXED - value: main - active: true - lastFetchTime: '0001-01-01T00:00:00Z' - isRepoError: false - repoErrorMsg: '' - isBranchError: false - branchErrorMsg: '' - url: https://github.com/devtron-labs/devtron-enterprise - regex: '' - imageReleaseTags: null - imageComment: null - referenceCdWorkflowRunnerId: 0 - appliedFilters: null - appliedFiltersState: 0 - appliedFiltersTimestamp: '0001-01-01T00:00:00Z' - promotionApprovalMetadata: null - runSource: - kind: release - version: alpha1 - id: 203 - identifier: qa-releases-track-0.0.2 - releaseVersion: 0.0.2 - name: deepak-qa-release - releaseTrackName: qa-releases-track - targetConfig: - tenantId: qa-devtroncd-x - tenantName: QA Devtron Env - installationId: qa-devtroncd-2 - installationName: qa-devtroncd-2 - releaseChannelId: beta - releaseChannelName: beta-channel - tags: - - Deployment History - /orchestrator/app/labels/list: - get: - summary: List all app labels - description: This API will return all the labels available in the database. - operationId: listAppLabels - security: [] - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - responses: - '200': - description: list response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - allOf: - - type: object - properties: - appId: - type: integer - description: unique application id - required: - - appId - - $ref: '#/components/schemas/AppLabel' - '400': - description: Bad request - '401': - description: Unauthorized - '404': - description: Not found - '500': - description: Internal server error - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - tags: - - Metadata - /orchestrator/app/meta/info/{appId}: - get: - summary: Get application meta info - description: Application basic info, projects and labels - operationId: getAppMetaInfo - security: [] - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: appId - in: path - description: application id - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: application basic info, projects and labels - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: object - description: meta info project name and labels - $ref: '#/components/schemas/AppMetaInfo' - '400': - description: Bad request - '401': - description: Unauthorized - '404': - description: Not found - '500': - description: Internal server error - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - tags: - - Metadata - /orchestrator/helm/meta/info/{appId}: - get: - summary: Get Helm application meta info - description: Application info for all types of Helm apps - operationId: getHelmAppMetaInfo - security: [] - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: appId - in: path - description: application id - required: true - schema: - type: string - responses: - '200': - description: Helm application basic info - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: object - description: meta info project name and labels - $ref: '#/components/schemas/AppMetaInfo' - '400': - description: Bad request - '401': - description: Unauthorized - '404': - description: Not found - '500': - description: Internal server error - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - tags: - - Metadata - /orchestrator/job: - post: - summary: Create or clone a job - description: Create and clone a job - operationId: createOrCloneJob - security: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateJob' - responses: - '200': - description: Used to give response once a job is created - content: - application/json: - schema: - $ref: '#/components/schemas/ActionResponse' - '400': - description: Bad request - '401': - description: Unauthorized - '500': - description: Internal server error - tags: - - Jobs - /orchestrator/job/list: - post: - summary: List jobs - description: Get the list of all the jobs by applying filter - operationId: listJobs - security: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/JobList' - responses: - '200': - description: Used to give response of list of jobs - content: - application/json: - schema: - $ref: '#/components/schemas/JobListResponse' - '400': - description: Bad request - '401': - description: Unauthorized - '500': - description: Internal server error - tags: - - Jobs - /orchestrator/job/ci-pipeline/list/{jobId}: - get: - summary: Get job CI pipeline list - description: fetch details of job ci-pipelines for the overview page - operationId: getJobCiPipelineList - security: [] - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: jobId - in: path - required: true - description: Job Id - schema: - type: integer - responses: - '200': - description: Job CI pipeline list - '400': - description: Bad request - '401': - description: Unauthorized - '500': - description: Internal server error - tags: - - Jobs - /orchestrator/app-store/installed-app: - get: - summary: List deployed charts - operationId: listDeployedCharts - description: deployed chart listing, with search filters - security: [] - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: envs - in: query - description: environment ids - required: false - schema: - type: array - items: - type: string - - name: chartRepoId - in: query - description: chart repo ids - required: false - schema: - type: array - items: - type: string - - name: appStoreName - in: query - description: chart name - required: false - schema: - type: string - - name: appName - in: query - description: chart name as app name for devtron - required: false - schema: - type: string - - name: onlyDeprecated - in: query - description: show only deprecated or all - required: false - schema: - type: boolean - - name: offset - in: query - description: offset for result set - required: false - schema: - type: integer - - name: size - in: query - description: total request size. - required: false - schema: - type: integer - responses: - '200': - description: deployed chart listing, with search filters - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: array - description: deployed chart listing, with search filters - items: - $ref: '#/components/schemas/ChartInfo' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - tags: - - Helm Charts - /orchestrator/app-store/installed-app/notes: - get: - summary: Fetch notes.txt for deployed helm charts - operationId: fetchNotesTxt - description: Used to fetch notes.txt for helm charts deployed via gitOps - security: [] - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: env-id - in: query - description: it is an environment id of app - required: true - schema: - type: integer - - name: installed-app-id - in: query - description: it is a installed application id - required: true - schema: - type: integer - responses: - '200': - description: if it is able to fetch the notes.txt then status will be ok - content: - application/json: - schema: - properties: - notes: - type: string - description: it will provide notes - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - '500': - description: error while fetching notes.txt - tags: - - Helm Charts - /orchestrator/app/autocomplete: - get: - summary: List application autocomplete - operationId: listAppAutocomplete - description: list of namespaces group by clusters - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - in: query - name: appName - example: abc - description: app name, wildcard query - required: false - allowEmptyValue: true - schema: - type: string - - in: query - name: teamId - example: '1' - description: project id - required: false - allowEmptyValue: false - schema: - type: integer - responses: - '200': - description: list response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: array - description: app list - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - tags: - - List Applications - security: [] - /orchestrator/app: - post: - summary: Create a new application - operationId: createApplication - description: create new application - security: [] - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/App' - responses: - '200': - description: App create response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: object - description: string - allOf: - - type: object - properties: - id: - type: integer - description: unique application id - required: - - id - - $ref: '#/components/schemas/App' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - tags: - - Applications - /orchestrator/app/edit: - post: - summary: Update application projects and labels - operationId: updateApplicationProjectsAndLabels - description: update application projects and labels - security: [] - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/App' - responses: - '200': - description: App update response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: object - description: string - allOf: - - type: object - properties: - id: - type: integer - description: unique application id - required: - - id - - $ref: '#/components/schemas/App' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - tags: - - Applications - /orchestrator/app/list: - post: - summary: List applications - operationId: listApplications - description: app listing, collection of deployed applications or undeployed - or incomplete configured apps. - security: [] - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AppListingRequest' - responses: - '200': - description: App create response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: object - description: string - required: - - appCount - - appContainers - - deploymentGroup - properties: - appCount: - type: integer - description: app count, total number of apps available based - on filter provided in request. - appContainers: - type: array - description: app containers - items: - $ref: '#/components/schemas/AppContainer' - deploymentGroup: - type: object - description: deployment group - $ref: '#/components/schemas/DeploymentGroup' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - tags: - - Applications - /orchestrator/app/edit/projects: - post: - summary: Update project for app - operationId: updateProjectForApp - description: update project for app - security: [] - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AppProjectUpdateRequest' - responses: - '200': - description: App update response - content: - application/json: - schema: - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: object - description: string - $ref: '#/components/schemas/AppProjectUpdateRequest' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - tags: - - Applications - /orchestrator/app/labels/list: - get: - summary: List Application Labels - description: "Retrieves a list of application labels. By default, returns all\ - \ labels. \nUse the `showPropagatedOnly` parameter to filter for labels where\ - \ propagate = true.\n\n**Required Token Permission:**\n- Must have **View**\ - \ access to the applications in scope.\n" - operationId: getAppLabels - tags: - - Labels - security: [] - - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: showPropagatedOnly - in: query - description: "If true, only returns labels where propagate = true. \nIf false\ - \ or not provided, all labels are returned.\n" - required: false - schema: - type: boolean - default: false - example: false - responses: - '200': - description: Successfully retrieved labels list - content: - application/json: - schema: - type: object - properties: - code: - type: integer - description: HTTP status code - example: 200 - status: - type: string - description: Response status message - example: OK - result: - type: array - description: Array of label objects - items: - type: object - required: - - key - - value - - propagate - - appId - - appName - properties: - key: - type: string - description: The label key/name - example: environment - value: - type: string - description: The label value - example: production - propagate: - type: boolean - description: Whether this label should be propagated - example: true - appId: - type: integer - description: The unique identifier of the application - example: 1234 - appName: - type: string - description: The name of the application - example: web-service - examples: - all_labels: - summary: All labels response - description: Example response when showPropagatedOnly is false or - not provided - value: - code: 200 - status: OK - result: - - key: environment - value: production - propagate: true - appId: 1234 - appName: web-service - - key: team - value: backend - propagate: false - appId: 1234 - appName: web-service - propagated_only: - summary: Propagated labels only - description: Example response when showPropagatedOnly is true - value: - code: 200 - status: OK - result: - - key: environment - value: production - propagate: true - appId: 1234 - appName: web-service - '401': - description: Authentication required or token invalid - content: - application/json: - schema: - type: object - properties: - code: - type: integer - example: 401 - status: - type: string - example: Unauthorized - message: - type: string - example: Authentication token is required - '403': - description: Insufficient permissions to access the resource - content: - application/json: - schema: - type: object - properties: - code: - type: integer - example: 403 - status: - type: string - example: Forbidden - message: - type: string - example: Token does not have View access to the applications in - scope - '500': - description: Internal server error - content: - application/json: - schema: - type: object - properties: - code: - type: integer - example: 500 - status: - type: string - example: Internal Server Error - message: - type: string - example: An unexpected error occurred - /orchestrator/batch/{apiVersion}/{kind}/readme: - get: - summary: Get Readme for Bulk Update - description: Returns Readme for bulk update for different resource in the url - operationId: FindBulkUpdateReadme - security: [] - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: apiVersion - in: path - required: true - description: apiVersion of the resource - schema: - type: string - - name: kind - in: path - required: true - description: kind of the resource - schema: - type: string - responses: - '200': - description: Successful GET operation - content: - application/json: - schema: - $ref: '#/components/schemas/BulkUpdateSeeExampleResponse' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - tags: - - bulk_other - /orchestrator/batch/v1beta1/application/dryrun: - post: - summary: Dry Run for Bulk Application Update - description: Returns details(id, name, envId) of all apps to be impacted with - bulk update - operationId: GetBulkAppName - security: [] - - requestBody: - description: A JSON object containing information by which apps will be filtered - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkUpdateScript' - responses: - '200': - description: Successfully return all impacted app details. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ImpactedObjectsResponse' - '400': - description: Bad Request. Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - tags: - - bulk_other - /orchestrator/batch/v1beta1/hibernate: - post: - summary: Bulk Hibernate Applications - description: Bulk Hibernates applications - operationId: BulkHibernate - security: [] - - tags: - - BulkUpdate - requestBody: - description: A JSON object containing information about applications and environments - to hibernate. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionRequest' - responses: - '200': - description: Successfully hibernated applications. - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionResponse' - '400': - description: Bad Request. Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/batch/v1beta1/unhibernate: - post: - summary: Bulk Un-Hibernate Applications - description: Bulk Un-Hibernates applications - operationId: BulkUnHibernate - security: [] - - tags: - - BulkUpdate - requestBody: - description: A JSON object containing information about applications and environments - to un-hibernate. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionRequest' - responses: - '200': - description: Successfully un-hibernated applications. - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionResponse' - '400': - description: Bad Request. Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/batch/v1beta1/deploy: - post: - summary: Bulk Deploy Applications - description: Bulk Triggers deployment of applications - operationId: BulkDeploy - security: [] - - tags: - - BulkUpdate - requestBody: - description: A JSON object containing information for bulk deployment. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkDeployRequest' - responses: - '200': - description: Successfully triggered bulk deployment. - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionResponse' - '400': - description: Bad Request. Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/batch/v1beta1/build: - post: - summary: Bulk Trigger Application Builds - description: Bulk Triggers build of applications - operationId: BulkBuildTrigger - security: [] - - tags: - - BulkUpdate - requestBody: - description: A JSON object containing information for bulk build trigger. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkBuildTriggerRequest' - responses: - '200': - description: Successfully triggered bulk build. - content: - application/json: - schema: - $ref: '#/components/schemas/BulkActionResponse' - '400': - description: Bad Request. Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/batch/v1beta1/application: - post: - summary: Bulk Edit Applications - description: Bulk Updates (Edit) all impacted apps. This endpoint can be used - for bulk editing application configurations like deployment templates, configmaps, - and secrets. - operationId: BulkUpdate - security: [] - - tags: - - BulkUpdate - requestBody: - description: A JSON object containing information about update changes and - by which apps will be filtered for bulk editing. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkUpdateScript' - responses: - '200': - description: Successfully updated all impacted apps. - content: - application/json: - schema: - $ref: '#/components/schemas/BulkUpdateResponse' - '400': - description: Bad Request. Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/sso/create: - post: - tags: - - SSO Configuration - summary: Create SSO Login Configuration - operationId: CreateSSOLoginConfig - requestBody: - $ref: '#/components/requestBodies/SSOLoginDto' - responses: - '200': - $ref: '#/components/responses/SSOLoginConfigResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/sso/update: - put: - tags: - - SSO Configuration - summary: Update SSO Login Configuration - operationId: UpdateSSOLoginConfig - requestBody: - $ref: '#/components/requestBodies/SSOLoginDto' - responses: - '200': - $ref: '#/components/responses/SSOLoginConfigResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/sso/list: - get: - tags: - - SSO Configuration - summary: Get All SSO Login Configurations - operationId: GetAllSSOLoginConfig - responses: - '200': - description: List of SSO configurations. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/SSOLoginDto' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/sso/{id}: - get: - tags: - - SSO Configuration - summary: Get SSO Login Configuration by ID - operationId: GetSSOLoginConfig - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - $ref: '#/components/parameters/PathId' - responses: - '200': - $ref: '#/components/responses/SSOLoginConfigResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/sso: - get: - tags: - - SSO Configuration - summary: Get SSO Login Configuration by Name - operationId: GetSSOLoginConfigByName - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: name - in: query - required: true - description: Name of the SSO configuration. - schema: - type: string - responses: - '200': - $ref: '#/components/responses/SSOLoginConfigResponse' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/rbac/roles/default: - get: - tags: - - RBAC - summary: Get All Default Roles - operationId: GetAllDefaultRoles - responses: - '200': - description: List of default RBAC roles. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/RbacRoleDto' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/api/v1/session: - post: - tags: - - Authentication - summary: User Login - description: Authenticates a user and returns a session token. - operationId: LoginHandler - requestBody: - description: Username and password for login. - required: true - content: - application/json: - schema: - type: object - properties: - username: - type: string - description: Username - example: admin - password: - type: string - description: Password - format: password - example: password123 - required: - - username - - password - responses: - '200': - description: Login successful, token returned. - content: - application/json: - schema: - type: object - properties: - token: - type: string - headers: - Set-Cookie: - description: Sets the argocd.token cookie. - schema: - type: string - example: argocd.token=yourtokenvalue; Path=/ - '400': - $ref: '#/components/responses/BadRequest' - '403': - description: Invalid username or password. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - security: [] - - /orchestrator/refresh: - get: - tags: - - Authentication - summary: Refresh Session Token - operationId: RefreshTokenHandler - description: Handles token refresh (details depend on OIDC/OAuth flow). - responses: - '200': - description: Token refreshed successfully. - '401': - $ref: '#/components/responses/Unauthorized' - security: [] - - /orchestrator/admin/policy/default: - post: - tags: - - Policy Management - summary: Add Default Policy and Roles - operationId: AddDefaultPolicyAndRoles - description: Creates default policies and roles based on team, app, and environment. - This is a specialized endpoint. - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: team - in: query - required: true - description: Project Id - schema: - type: string - - name: app - in: query - required: true - description: Application Id - schema: - type: string - - name: env - in: query - required: true - description: Environment Id - schema: - type: string - responses: - '200': - description: Default policies and roles added successfully. - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/devtron/auth/verify: - get: - tags: - - Authentication - summary: Verify Authentication Status - operationId: AuthVerification - responses: - '200': - description: Authentication status. - content: - application/json: - schema: - type: boolean - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/devtron/auth/verify/v2: - get: - tags: - - Authentication - summary: Verify Authentication Status (V2) - operationId: AuthVerificationV2 - responses: - '200': - description: Detailed authentication status including super admin flag. - content: - application/json: - schema: - type: object - properties: - isSuperAdmin: - type: boolean - isVerified: - type: boolean - emailId: - type: string - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/v2: - get: - tags: - - User Management - summary: List Users (V2 - Paginated, Filtered) - operationId: GetAllUsersV2 - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - $ref: '#/components/parameters/SearchKeyQuery' - - $ref: '#/components/parameters/SortOrderQuery' - - $ref: '#/components/parameters/SortByQueryUser' - - $ref: '#/components/parameters/OffsetQuery' - - $ref: '#/components/parameters/SizeQuery' - responses: - '200': - $ref: '#/components/responses/UserListingResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - post: - tags: - - User Management - summary: Create User (V2) - operationId: CreateUserV2 - requestBody: - $ref: '#/components/requestBodies/UserInfo' - responses: - '200': - $ref: '#/components/responses/UserInfoResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '406': - $ref: '#/components/responses/NotAcceptable' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - put: - tags: - - User Management - summary: Update User (V2) - operationId: UpdateUserV2 - requestBody: - $ref: '#/components/requestBodies/UserInfo' - responses: - '200': - $ref: '#/components/responses/UserInfoResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '406': - $ref: '#/components/responses/NotAcceptable' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user: - get: - tags: - - User Management - summary: List All Users (V1) - operationId: GetAllUsers - responses: - '200': - description: List of all users. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/UserInfo' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - post: - tags: - - User Management - summary: Create User - operationId: CreateUser - requestBody: - $ref: '#/components/requestBodies/UserInfo' - responses: - '200': - $ref: '#/components/responses/UserInfoResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '406': - $ref: '#/components/responses/NotAcceptable' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - put: - tags: - - User Management - summary: Update User - operationId: UpdateUser - requestBody: - $ref: '#/components/requestBodies/UserInfo' - responses: - '200': - $ref: '#/components/responses/UserInfoResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '406': - $ref: '#/components/responses/NotAcceptable' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/{id}: - get: - tags: - - User Management - summary: Get User by ID - operationId: GetUserById - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - $ref: '#/components/parameters/PathId' - responses: - '200': - $ref: '#/components/responses/UserInfoResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - delete: - tags: - - User Management - summary: Delete User by ID - operationId: DeleteUser - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - $ref: '#/components/parameters/PathId' - responses: - '200': - $ref: '#/components/responses/GenericSuccess' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/v2/{id}: - get: - tags: - - User Management - summary: Get User by ID (V2) - operationId: GetUserByIdV2 - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - $ref: '#/components/parameters/PathId' - responses: - '200': - $ref: '#/components/responses/UserInfoResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/bulk: - delete: - tags: - - User Management - summary: Bulk Delete Users - operationId: BulkDeleteUsers - responses: - '200': - $ref: '#/components/responses/GenericSuccess' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/detail/get: - get: - tags: - - User Management - summary: List All Detailed Users - operationId: GetAllDetailedUsers - responses: - '200': - description: List of all users with detailed information. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/UserInfo' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/role/group/v2: - get: - tags: - - Role Group Management - summary: List Role Groups (V2 - Paginated, Filtered) - operationId: FetchRoleGroupsV2 - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - $ref: '#/components/parameters/SearchKeyQuery' - - $ref: '#/components/parameters/SortOrderQuery' - - $ref: '#/components/parameters/SortByQueryRoleGroup' - - $ref: '#/components/parameters/OffsetQuery' - - $ref: '#/components/parameters/SizeQuery' - responses: - '200': - $ref: '#/components/responses/RoleGroupListingResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - post: - tags: - - Role Group Management - summary: Create Role Group (V2) - operationId: CreateRoleGroupV2 - requestBody: - $ref: '#/components/requestBodies/RoleGroup' - responses: - '200': - $ref: '#/components/responses/RoleGroupResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - put: - tags: - - Role Group Management - summary: Update Role Group (V2) - operationId: UpdateRoleGroupV2 - requestBody: - $ref: '#/components/requestBodies/RoleGroup' - responses: - '200': - $ref: '#/components/responses/RoleGroupResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/role/group: - get: - tags: - - Role Group Management - summary: List All Role Groups (V1) - operationId: FetchRoleGroups - responses: - '200': - description: List of all role groups. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/RoleGroup' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - post: - tags: - - Role Group Management - summary: Create Role Group - operationId: CreateRoleGroup - requestBody: - $ref: '#/components/requestBodies/RoleGroup' - responses: - '200': - $ref: '#/components/responses/RoleGroupResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - put: - tags: - - Role Group Management - summary: Update Role Group - operationId: UpdateRoleGroup - requestBody: - $ref: '#/components/requestBodies/RoleGroup' - responses: - '200': - $ref: '#/components/responses/RoleGroupResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/role/group/{id}: - get: - tags: - - Role Group Management - summary: Get Role Group by ID - operationId: FetchRoleGroupById - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - $ref: '#/components/parameters/PathId' - responses: - '200': - $ref: '#/components/responses/RoleGroupResponse' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - delete: - tags: - - Role Group Management - summary: Delete Role Group by ID - operationId: DeleteRoleGroup - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - $ref: '#/components/parameters/PathId' - responses: - '200': - $ref: '#/components/responses/GenericSuccess' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/role/group/v2/{id}: - get: - tags: - - Role Group Management - summary: Get Role Group by ID (V2) - operationId: FetchRoleGroupByIdV2 - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - $ref: '#/components/parameters/PathId' - responses: - '200': - $ref: '#/components/responses/RoleGroupResponse' - '400': - $ref: '#/components/responses/BadRequest' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/role/group/detailed/get: - get: - tags: - - Role Group Management - summary: List All Detailed Role Groups - operationId: FetchDetailedRoleGroups - responses: - '200': - $ref: '#/components/responses/RoleGroupListingResponse' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/role/group/search: - get: - tags: - - Role Group Management - summary: Search Role Groups by Name - operationId: FetchRoleGroupsByName - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: name - in: query - required: true - description: Name of the role group to search for. - schema: - type: string - responses: - '200': - $ref: '#/components/responses/RoleGroupResponse' - '401': - $ref: '#/components/responses/Unauthorized' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/role/group/bulk: - delete: - tags: - - Role Group Management - summary: Bulk Delete Role Groups - operationId: BulkDeleteRoleGroups - responses: - '200': - $ref: '#/components/responses/GenericSuccess' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/check/roles: - get: - tags: - - Authentication - summary: Check Logged-in User's Roles - operationId: CheckUserRoles - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: appName - in: query - required: false - description: Optional application name to filter roles for. - schema: - type: string - responses: - '200': - description: User roles information. - content: - application/json: - schema: - type: object - properties: - role: - type: string - nullable: true - roles: - type: array - items: - type: string - superAdmin: - type: boolean - nullable: true - '401': - $ref: '#/components/responses/Unauthorized' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/sync/orchestratortocasbin: - get: - tags: - - Policy Management - summary: Sync Orchestrator to Casbin - operationId: SyncOrchestratorToCasbin - description: Synchronizes policies from orchestrator to Casbin. Requires admin - privileges. - responses: - '200': - description: Sync status. - content: - application/json: - schema: - type: boolean - '401': - $ref: '#/components/responses/Unauthorized' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/update/trigger/terminal: - put: - tags: - - Policy Management - summary: Update Trigger Policy for Terminal Access - operationId: UpdateTriggerPolicyForTerminalAccess - description: Updates trigger policies related to terminal access. Requires global - update privileges. - responses: - '200': - description: Policy update status. - content: - application/json: - schema: - type: string - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - security: [] - - /orchestrator/user/role/cache: - get: - tags: - - Cache Management - summary: Get Role Cache Dump - operationId: GetRoleCacheDump - description: Retrieves a dump of the role cache. Requires super admin privileges. - responses: - '200': - description: Cache dump data. - content: - application/json: - schema: - type: object - '403': - $ref: '#/components/responses/Forbidden' - security: [] - - /orchestrator/user/role/cache/invalidate: - get: - tags: - - Cache Management - summary: Invalidate Role Cache - operationId: InvalidateRoleCache - description: Clears the role cache. Requires super admin privileges. - responses: - '200': - description: Cache invalidation status. - content: - application/json: - schema: - type: string - '403': - $ref: '#/components/responses/Forbidden' - security: [] - - /orchestrator/login: - get: - tags: - - Authentication - summary: OIDC Login Redirect (Informational) - description: Initiates OIDC login flow. Handled by the OIDC client library. - operationId: HandleOIDCLogin - responses: - '302': - description: Redirect to OIDC provider. - security: [] - - /orchestrator/auth/login: - get: - tags: - - Authentication - summary: OIDC Login Redirect (Informational - Alternate Path) - description: Initiates OIDC login flow. Handled by the OIDC client library. - operationId: HandleOIDCAuthLogin - responses: - '302': - description: Redirect to OIDC provider. - security: [] - - /orchestrator/auth/callback: - get: - tags: - - Authentication - summary: OIDC Callback (Informational) - description: Handles the callback from the OIDC provider. Handled by the OIDC - client library. - operationId: HandleOIDCCallback - responses: - '302': - description: Redirect after successful authentication. - '400': - description: Error during OIDC callback. - '500': - description: Server error during OIDC callback. - security: [] - - /orchestrator/api/dex/{path}: - get: - tags: - - Authentication - summary: Dex Proxy (Informational) - description: Proxies requests to the Dex IdP. Handled by the Dex proxy mechanism. - operationId: DexProxyHandler - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: path - in: path - required: true - description: Path to be proxied to Dex. - schema: - type: string - responses: - default: - description: Response from Dex. - security: [] - - /orchestrator/env: - post: - summary: Create Environment - description: Create a new environment within a cluster. - operationId: CreateEnvironment - security: [] - - tags: - - Environment Management - requestBody: - description: Environment details - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EnvironmentCreateRequest' - responses: - '200': - description: Successfully created environment - content: - application/json: - schema: - $ref: '#/components/schemas/EnvironmentDetail' - '400': - description: Bad Request (e.g., validation error) - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - put: - summary: Update Environment - description: Update an existing environment. - operationId: UpdateEnvironment - security: [] - - tags: - - Environment Management - requestBody: - description: Environment details to update - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EnvironmentUpdateRequest' - responses: - '200': - description: Successfully updated environment - content: - application/json: - schema: - $ref: '#/components/schemas/EnvironmentDetail' - '400': - description: Bad Request (e.g., validation error, or ID not found) - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - get: - summary: Get Environment by ID - description: Get detailed information for a specific environment by its ID. - operationId: GetEnvironmentById - security: [] - - tags: - - Environment Management - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: id - in: query - required: true - description: ID of the environment - schema: - type: integer - responses: - '200': - description: Successfully retrieved environment details - content: - application/json: - schema: - $ref: '#/components/schemas/EnvironmentDetail' - '400': - description: Bad Request (e.g., invalid ID) - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Environment not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/cluster/delete: - post: - summary: Delete Cluster - description: Delete an existing cluster. - operationId: DeleteCluster - security: [] - tags: - - Cluster Management - requestBody: - description: A JSON object containing the cluster config (primarily ID is - used for deletion) - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ClusterBean' - responses: - '200': - description: Successfully deleted the cluster - content: - application/json: - schema: - type: object - properties: - message: - type: string - example: Cluster deleted successfully. - '400': - description: Bad Request. Input Validation(decode) error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/env/delete: - post: - summary: Delete Environment (via POST) - description: Delete an existing environment using POST method. - operationId: DeleteEnvironmentViaPost - security: [] - tags: - - Environment Management - requestBody: - description: A JSON object containing the env config (primarily ID is used - for deletion) - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EnvironmentDetail' - responses: - '200': - description: Successfully deleted the environment - content: - application/json: - schema: - type: object - properties: - message: - type: string - example: Environment deleted successfully. - '400': - description: Bad Request. Input Validation(decode) error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/env/clusters: - get: - summary: List clusters with their environments - description: Provides a list of all clusters and the environments within each. - operationId: getClustersWithEnvironments - security: [] - - tags: - - Cluster Environment - responses: - '200': - description: Successfully retrieved list of clusters and environments - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ClusterWithEnvironments' - '401': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/cluster/{cluster_id}/env: - get: - summary: List environments for a specific cluster - description: Provides a list of all environments for a given cluster ID. - operationId: getEnvironmentsForCluster - security: [] - - tags: - - Cluster Environment - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: cluster_id - in: path - required: true - description: ID of the cluster - schema: - type: integer - responses: - '200': - description: Successfully retrieved list of environments - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/Environment' - '400': - description: Bad Request. Invalid cluster ID. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Cluster not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/cluster: - put: - summary: Update Cluster - description: Update an existing cluster's configuration. - operationId: UpdateCluster - security: [] - - tags: - - Cluster Management - requestBody: - description: A JSON object containing the cluster config - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ClusterBean' - responses: - '200': - description: Successfully updated the cluster - content: - application/json: - schema: - $ref: '#/components/schemas/ClusterBean' - '400': - description: Bad Request. Input Validation(decode) error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - get: - summary: Get Cluster - description: Get details of a specific cluster by ID. - operationId: GetCluster - security: [] - - tags: - - Cluster Management - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: id - in: query - description: cluster id. - required: true - schema: - type: integer - responses: - '200': - description: Successfully get cluster - content: - application/json: - schema: - $ref: '#/components/schemas/ClusterBean' - '400': - description: Bad Request. Input Validation(decode) error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/cluster/auth-list: - get: - summary: List Accessible Clusters - description: list of clusters accessible to the authenticated user. - operationId: GetAuthClusterList - security: [] - - tags: - - Cluster Management - responses: - '200': - description: cluster list - content: - application/json: - schema: - type: object - properties: - code: - type: integer - description: status code - status: - type: string - description: status - result: - type: array - description: namespace list group by cluster - items: - $ref: '#/components/schemas/ClusterAuthDetail' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /orchestrator/cluster/validate: - post: - summary: Validate Cluster Configuration - description: Validate a cluster configuration using kubeconfig. - operationId: ValidateCluster - security: [] - tags: - - Cluster Management - requestBody: - content: - application/json: - schema: - type: object - properties: - kubeconfig: - $ref: '#/components/schemas/Kubeconfig' - required: - - kubeconfig - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/ValidateClusterBean' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /cluster/saveClusters: - post: - summary: Save Multiple Clusters - description: Save configurations for multiple clusters. - operationId: SaveClusters - security: [] - - tags: - - Cluster Management - requestBody: - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ValidateClusterBean' - responses: - '200': - description: OK - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ValidateClusterBean' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /app/env/patch: - patch: - summary: Patch Application Environment - description: change the deployment template for an app and environment - operationId: PatchAppEnv - security: [] - - requestBody: - content: - application/json: - schema: - properties: - envId: - type: integer - description: Environment Id - appId: - type: integer - description: Application Id - targetChartRefId: - type: integer - description: Chart ref Id of template - responses: - '200': - description: patched data - '422': - description: bad request - tags: - - Change Chart - /app/workflow/clone: - post: - summary: Clone Application Workflow - description: Clones an application workflow from a source environment to a target - environment - operationId: CloneApplicationWorkflow - security: [] - - requestBody: - description: A JSON object containing the details required to clone the workflow - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CloneApplicationWorkflowRequest' - responses: - '200': - description: Cloning operation response - content: - application/json: - schema: - $ref: '#/components/schemas/StandardResponse' - tags: - - Clone Workflow - /k8s/resource: - post: - summary: Get Resource Manifest - description: This API is used for fetching the manifest of a specified Kubernetes - resource. - operationId: getResourceManifest - security: [] - - requestBody: - description: JSON payload specifying the resource to fetch. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - '200': - description: Successfully retrieved the resource manifest. - content: - application/json: - schema: - type: object - properties: - code: - type: integer - description: Status code of the response. - status: - type: string - description: Status message of the response. - result: - $ref: '#/components/schemas/ResourceGetResponse' - tags: - - K8s Resource - put: - summary: Update Resource Manifest - description: This API is used for editing the manifest of a specified Kubernetes - resource. - operationId: updateResourceManifest - security: [] - - requestBody: - description: JSON payload containing the resource identifier and the patch. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - '200': - description: Successfully updated the resource manifest. - content: - application/json: - schema: - type: object - properties: - code: - type: integer - description: Status code of the response. - status: - type: string - description: Status message of the response. - result: - $ref: '#/components/schemas/ResourceGetResponse' - tags: - - K8s Resource - /k8s/resource/create: - post: - summary: Create Resource - description: This API is used for applying a desired manifest to create a Kubernetes - resource. - operationId: createResource - security: [] - - requestBody: - description: JSON payload containing the resource manifest to apply. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - '200': - description: Successfully created the resource. - content: - application/json: - schema: - type: object - properties: - code: - type: integer - description: Status code of the response. - status: - type: string - description: Status message of the response. - result: - $ref: '#/components/schemas/ResourceGetResponse' - tags: - - K8s Resource - /k8s/resource/delete: - post: - summary: Delete Resource - description: This API is used for deleting a specified Kubernetes resource. - operationId: deleteResource - security: [] - - requestBody: - description: JSON payload specifying the resource to delete. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - '200': - description: Successfully deleted the resource. - content: - application/json: - schema: - type: object - properties: - code: - type: integer - description: Status code of the response. - status: - type: string - description: Status message of the response. - result: - $ref: '#/components/schemas/ResourceGetResponse' - tags: - - K8s Resource - /k8s/events: - post: - summary: Get Resource Events - description: This API is used for fetching events for Kubernetes resources. - operationId: getResourceEvents - security: [] - - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - '200': - description: Successfully retrieved resource events. The response is a stream - of events. - content: - text/event-stream: - schema: - $ref: '#/components/schemas/EventsResponseObject' - tags: - - K8s Resource - /k8s/pods/logs/{podName}: - get: - summary: Get Pod Logs - description: This API is used for fetching logs for a specified container within - a pod. - operationId: getPodLogs - security: [] - - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: podName - in: path - required: true - description: Name of the pod. - schema: - type: string - - name: containerName - in: query - required: true - description: Name of the container within the pod. - schema: - type: string - - name: appId - in: query - required: false - description: Application ID. - schema: - type: string - - name: clusterId - in: query - required: false - description: Cluster ID. - schema: - type: integer - - name: namespace - in: query - description: Namespace of the pod. Required if clusterId is passed. - required: false - schema: - type: string - - name: follow - in: query - description: Whether to follow the log stream. - schema: - type: boolean - default: false - - name: sinceSeconds - in: query - description: Return logs newer than a relative duration like 5s, 2m, or 3h. - Defaults to all logs. - schema: - type: integer - - name: tailLines - in: query - description: If set, the number of lines from the end of the logs to show. - schema: - type: integer - responses: - '200': - description: Successfully retrieved pod logs. The response is a stream of - log lines. - content: - text/event-stream: - schema: - $ref: '#/components/schemas/LogsResponseObject' - tags: - - K8s Resource - /k8s/pod/exec/session/{identifier}/{namespace}/{pod}/{shell}/{container}: - get: - summary: Get Pod Exec Session - description: This API establishes a session for executing commands in a pod's - container (terminal access). - operationId: getPodExecSession - security: [] - - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: identifier - in: path - required: true - description: Application ID or Cluster ID. Example '2|devtroncd|devtron' or - '3'. - schema: - type: string - - name: namespace - in: path - required: true - description: Namespace of the pod. - schema: - type: string - example: devtroncd - - name: pod - in: path - required: true - description: Name of the pod. - schema: - type: string - example: inception-58d44d99fd-tfw4s - - name: shell - in: path - required: true - description: Shell to invoke. - schema: - type: string - enum: - - bash - - sh - - powershell - - cmd - example: bash - - name: container - in: path - required: true - description: Name of the container. - schema: - type: string - example: devtron - responses: - '200': - description: Successfully established exec session. - content: - application/json: - schema: - $ref: '#/components/schemas/TerminalMessage' - tags: - - K8s Resource - /k8s/api-resources/{clusterId}: - get: - summary: Get API Resources - description: Get all available API resources for a given cluster ID. - operationId: getApiResources - security: [] - - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: clusterId - in: path - description: ID of the cluster. - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: Successfully fetched all API resources for the given cluster - ID. - content: - application/json: - schema: - $ref: '#/components/schemas/GetAllApiResourcesResponse' - tags: - - K8s Resource - /k8s/resource/list: - post: - summary: List Resources - description: This API is used for fetching a list of Kubernetes resources based - on the request criteria. - operationId: listResources - security: [] - - requestBody: - description: JSON payload specifying the criteria for listing resources. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceRequestObject' - responses: - '200': - description: Successfully retrieved the list of resources. - content: - application/json: - schema: - type: object - properties: - code: - type: integer - description: Status code of the response. - status: - type: string - description: Status message of the response. - result: - type: array - description: List of resources. - items: - $ref: '#/components/schemas/ClusterResourceListResponse' - tags: - - K8s Resource - /k8s/resources/rotate: - post: - summary: Rotates the Pods - description: This API is used to rotate (restart) pods for the provided resources. - operationId: K8sResourceForResources - security: [] - - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: appId - in: query - description: Application ID. - required: true - schema: - type: string - requestBody: - description: JSON payload specifying the resources for which pods should be - rotated. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RotatePodRequest' - responses: - '200': - description: Response array indicating the status of rotation for each resource. - content: - application/json: - schema: - $ref: '#/components/schemas/RotatePodResponse' - tags: - - K8s Resource - /k8s/resources/apply: - post: - summary: Apply Resources - description: This API is used to apply (create or update) Kubernetes resources - in a cluster. - operationId: applyResources - security: [] - - requestBody: - description: JSON payload containing the manifest of resources to apply. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ApplyResourcesRequest' - responses: - '200': - description: Response array indicating the status of application for each - resource. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ApplyResourcesResponse' - tags: - - K8s Resource - /app/workflow: - post: - summary: Create an application workflow - description: Creates a new workflow for a given application. - operationId: CreateAppWorkflow - security: [] - - tags: - - Workflow Management - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AppWorkflowDto' - responses: - '200': - description: Successfully created workflow. - content: - application/json: - schema: - $ref: '#/components/schemas/AppWorkflowDto' - '400': - description: Bad Request. Validation error or wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden. User does not have permission. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /app/workflow/{app-wf-id}/app/{app-id}: - delete: - summary: Delete an application workflow - description: Deletes an existing workflow for a given application. - operationId: DeleteAppWorkflow - security: [] - - tags: - - Workflow Management - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: app-wf-id - in: path - required: true - description: ID of the application workflow to delete. - schema: - type: integer - - name: app-id - in: path - required: true - description: ID of the application. - schema: - type: integer - responses: - '200': - description: Successfully deleted workflow. - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: OK - '400': - description: Bad Request. Invalid path parameters. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized User. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden. User does not have permission. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /version: - get: - summary: Get Devtron server version information - security: [] - responses: - '200': - description: meta info about devtron server - content: - application/json: - schema: - type: object - properties: - gitCommit: - type: string - example: d252aa3e - description: git hash from which code was compiled - buildTime: - type: string - format: date-time - example: '2021-12-15T05:44:05Z' - description: time when code was complied - serverMode: - type: string - example: FULL - description: server mode FULL/EA_ONLY - enum: - - FULL - - EA_ONLY - tags: - - Devtron Server version - /validate: - post: - description: Validate gitops configuration by dry run - summary: Validate gitops configuration by dry run - security: [] - operationId: GitOpsValidateDryRun - requestBody: - description: A JSON object containing the gitops configuration - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GitOpsConfigDto' - responses: - '200': - description: Successfully return all validation stages results - content: - application/json: - schema: - $ref: '#/components/schemas/DetailedError' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - tags: - - GitOps Validation - /config: - post: - description: create/save new configuration and validate them before saving - summary: create/save new configuration and validate them before saving - security: [] - operationId: CreateGitOpsConfig - requestBody: - description: A JSON object containing the gitops configuration - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GitOpsConfigDto' - responses: - '200': - description: Successfully return all validation stages results and if validation - is correct then saves the configuration in the backend - content: - application/json: - schema: - $ref: '#/components/schemas/DetailedError' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - tags: - - GitOps Validation - put: - description: update configuration and validate them before saving(if last validation - is within 30 seconds then do not validate) - summary: update configuration and validate them before saving(if last validation - is within 30 seconds then do not validate) - operationId: UpdateGitOpsConfig - security: [] - requestBody: - description: A JSON object containing the gitops configuration - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/GitOpsConfigDto' - responses: - '200': - description: Successfully return all validation stages results and if validation - is correct then updates the configuration in the backend - content: - application/json: - schema: - $ref: '#/components/schemas/DetailedError' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - tags: - - GitOps Validation - /notification: - get: - summary: Returns all notification settings - description: Returns all notification settings - operationId: findNotificationSetting - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: offset - in: query - description: value can be regex search string. - required: true - schema: - type: integer - - name: size - in: query - description: value can be regex search string. - required: true - schema: - type: integer - security: [] - - tags: - - Notifications - responses: - '200': - description: list response - content: - application/json: - schema: - $ref: '#/components/schemas/NotificationSetting' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - post: - summary: Creates a new NotificationSetting - description: create NotificationSetting api. - operationId: addNotificationSetting - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/NotificationSetting' - security: [] - - tags: - - Notifications - responses: - '200': - description: create NotificationSetting response - content: - application/json: - schema: - $ref: '#/components/schemas/NotificationSetting' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - put: - summary: Update NotificationSetting - description: Update NotificationSetting api either recipients or events(trigger/success/failed). - operationId: updateNotificationSetting - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/NotificationSetting' - security: [] - - tags: - - Notifications - responses: - '200': - description: create NotificationSetting response - content: - application/json: - schema: - $ref: '#/components/schemas/NotificationSetting' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - delete: - summary: delete NotificationSetting - description: delete NotificationSetting. - operationId: deleteNotificationSetting - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/NotificationSetting' - security: [] - - tags: - - Notifications - responses: - '200': - description: create NotificationSetting response - content: - application/json: - schema: - $ref: '#/components/schemas/NotificationSetting' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /notification/recipient: - get: - summary: used to fetch providers(recipients) - description: recipients fetch by string search, it will return slacks providers - and email ids - operationId: deleteGroupPolicy - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: value - in: query - description: value can be regex search string. - required: true - schema: - type: string - security: [] - - tags: - - Notifications - responses: - '204': - description: list of recipients - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /notification/channel: - get: - summary: get all NotificationSettingConfig list - description: get all NotificationSettingConfig list - operationId: findNotificationSettingConfig - security: [] - - tags: - - Notifications - responses: - '200': - description: list response - content: - application/json: - schema: - $ref: '#/components/schemas/NotificationConfigResponse' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - post: - summary: Creates a new NotificationSettingConfig - description: create NotificationSettingConfig, Slack or SES - operationId: addNotificationSettingConfig - requestBody: - description: json as request body - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/NotificationConfig' - security: [] - - tags: - - Notifications - responses: - '200': - description: create NotificationSettingConfig response - content: - application/json: - schema: - $ref: '#/components/schemas/NotificationConfigResponse' - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/app/history/deployed-component/detail/{appId}/{pipelineId}/{id}: - get: - summary: Fetch component history - description: fetch detail of a history on the basis of the history component - and it's name - operationId: FetchHistoryByDeployedConfigurationDetail - tags: - - Deployment History - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - - name: id - in: path - required: true - schema: - type: integer - - name: historyComponent - in: query - required: true - schema: - type: string - enum: - - DEPLOYMENT_TEMPLATE - - CONFIGMAP - - SECRET - - PIPELINE_STRATEGY - - name: historyComponentName - in: query - required: false - description: name of config-map, secret - schema: - type: string - security: [] - - responses: - '200': - description: Successfully return history - content: - application/json: - schema: - $ref: '#/components/schemas/HistoryComponentDetailDto' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/app/history/deployed-component/list/{appId}/{pipelineId}: - get: - summary: fetch deployed history details list - description: fetch deployed history details list - operationId: FetchHistoryListByDeployedConfigurationDetail - tags: - - Deployment History - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - - name: historyComponent - in: query - required: true - schema: - type: string - enum: - - DEPLOYMENT_TEMPLATE - - CONFIGMAP - - SECRET - - PIPELINE_STRATEGY - - name: historyComponentName - in: query - required: false - description: name of config-map, secret - schema: - type: string - - name: baseConfigurationId - in: query - required: true - description: id of base configuration - schema: - type: integer - security: [] - - responses: - '200': - description: Successfully return history list - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/HistoryComponentListDto' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /orchestrator/app/history/deployed-configuration/{appId}/{pipelineId}/{wfrId}: - get: - summary: all deployed configuration history - description: fetch all deployed configurations history (deployment template, - pipeline strategy, configmaps, secrets) - operationId: FetchHistoryListForAllDeployedConfigurations - tags: - - Deployment History - parameters: - - name: token - in: header - required: true - description: Authentication token. - schema: - type: string - - name: appId - in: path - required: true - schema: - type: integer - - name: pipelineId - in: path - required: true - schema: - type: integer - - name: wfrId - in: path - required: true - schema: - type: integer - security: [] - - responses: - '200': - description: Successfully return history - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/HistoryConfigurationListDto' - '400': - description: Bad Request. Input Validation error/wrong request body. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Unauthorized User - content: - application/json: - schema: - $ref: '#/components/schemas/Error' -components: - schemas: - AppLabel: - type: object - required: - - key - - value - properties: - key: - type: string - description: label key - value: - type: string - description: label value - propagate: - type: boolean - description: Whether to propagate to kubernetes resources - AppLabels: - type: object - required: - - appId - - labels - properties: - appId: - type: integer - description: application id - labels: - type: array - items: - $ref: '#/components/schemas/AppLabel' - AppMetaInfo: - type: object - required: - - appId - - projectId - - appName - - projectName - - createdOn - - createdBy - - labels - properties: - appId: - type: integer - description: app id - projectId: - type: integer - description: team/project id - appName: - type: string - description: app name - projectName: - type: string - description: team/project name - labels: - type: array - items: - $ref: '#/components/schemas/AppLabel' - createdOn: - type: string - description: app creation date - createdBy: - type: string - description: app created by - ErrorResponse: - type: object - properties: - code: - type: integer - format: int32 - status: - type: string - result: - type: object - nullable: true - errors: - type: array - items: - type: object - properties: - userMessage: - type: string - nullable: true - internalMessage: - type: string - nullable: true - Error: - required: - - code - - message - properties: - code: - type: integer - description: Error code - message: - type: string - description: Error message - CreateJob: - type: object - properties: - appName: - type: string - description: Used to give the name of the job - example: my-job-1 - isJob: - type: boolean - description: States whether its a job or an app - example: true - teamId: - type: integer - description: Used to give project id - example: 1 - templateId: - type: integer - description: Used to give the id of the job it wants to clone - example: 18 - labels: - type: array - items: - type: object - properties: - key: - type: string - example: hello - value: - type: string - example: world - propogate: - type: boolean - example: false - description: - type: string - description: Used to give the description of the job once it is made. - example: This is my first Job - ActionResponse: - type: object - properties: - id: - type: integer - description: Used to give the id of job once its created - example: 25 - appName: - type: string - description: Used to give the name of job once its created - example: my-job-1 - material: - type: array - items: - $ref: '#/components/schemas/gitMaterial' - teamId: - type: integer - description: Used to give the team id - example: 1 - templateId: - type: integer - description: Used to give the templateId - example: 0 - description: - type: string - description: Used to give the description of the job once it is made. - example: This is my first Job - isJob: - type: boolean - description: used to tell whether it is a job or an app - example: true - JobList: - type: object - properties: - teams: - type: array - items: - type: integer - description: used to give the project id - example: - - 1 - - 2 - appStatuses: - type: array - items: - type: string - description: used to give the filter of app ci-build status - example: - - Succeeded - - Starting - sortBy: - type: string - description: used to give the sort by constraint - example: appNameSort - sortOrder: - type: string - description: used to give the sort order - example: ASC - offset: - type: integer - description: used to give the number from which we want our job (if the - offset is 20 means we want list of jobs from 20) - example: 0 - size: - type: integer - description: used to give the number of jobs we want - example: 20 - JobListResponse: - type: object - properties: - jobContainers: - type: array - items: - $ref: '#/components/schemas/jobContainer' - jobCount: - type: integer - gitMaterial: - type: object - properties: - name: - type: string - url: - type: string - id: - type: integer - gitProviderId: - type: integer - checkoutPath: - type: string - fetchSubmodules: - type: boolean - isUsedInCiConfig: - type: boolean - jobContainer: - type: object - properties: - jobId: - type: integer - jobName: - type: string - description: - type: string - ciPipelines: - type: array - items: - $ref: '#/components/schemas/jobCiPipeline' - jobCiPipeline: - type: object - properties: - ciPipelineId: - type: integer - status: - type: string - lastRunAt: - type: string - format: date-time - lastSuccessAt: - type: string - format: date-time - ChartInfo: - type: object - required: - - installedAppId - - environmentId - - installedAppVersionId - - appStoreApplicationVersionId - - appStoreApplicationName - - status - - appName - - environmentName - - deployedAt - - deployedBy - - readme - - deprecated - properties: - installedAppId: - type: integer - description: installed chart id - environmentId: - type: integer - description: environment id - installedAppVersionId: - type: integer - description: installed chart version id - appStoreApplicationVersionId: - type: integer - description: team/project id - appStoreApplicationName: - type: string - description: chart name externally - chartName: - type: string - description: chart repo name - icon: - type: string - description: image - status: - type: string - description: status of deployed chart - appName: - type: string - description: chart name is app name for devtron - environmentName: - type: string - description: env name - deployedAt: - type: string - description: deployement time - deployedBy: - type: string - description: user - readme: - type: string - description: readme - deprecated: - type: boolean - description: is deprecated or not - App: - type: object - required: - - appName - - teamId - - templateId - properties: - appName: - type: string - description: app name - teamId: - type: integer - description: project id - templateId: - type: integer - description: reference app id, used for clone, set default value 0 for blank - app. - labels: - type: array - description: each apps may have multiple labels. these are optional. - items: - $ref: '#/components/schemas/AppLabel' - AppProjectUpdateRequest: - type: object - required: - - teamId - - appId - properties: - teamId: - type: integer - description: project id - appId: - type: array - description: team id, teams ids are projects ids - items: - type: integer - AppListingRequest: - type: object - required: [] - properties: - appNameSearch: - type: string - description: app name search, wildcard match - offset: - type: integer - description: offset - size: - type: integer - description: result size - sortBy: - type: string - description: sort by - sortOrder: - type: string - description: sort order - environments: - type: array - description: environment id - items: - type: integer - teams: - type: array - description: team id, teams ids are projects ids - items: - type: integer - labels: - type: array - description: app labels - items: - type: string - statuses: - type: array - description: status - items: - type: string - AppContainer: - type: object - required: - - appId - - appName - - environments - properties: - appId: - type: integer - description: app id - appName: - type: string - description: app name - environments: - type: array - items: - $ref: '#/components/schemas/EnvContainer' - EnvContainer: - type: object - required: - - appId - - appName - - environmentId - - environmentName - properties: - appId: - type: integer - description: app id - appName: - type: string - description: app name - cdStageStatus: - type: string - description: app name - dataSource: - type: string - description: app name - ciArtifactId: - type: integer - description: app name - deleted: - type: boolean - description: app name - environmentId: - type: integer - description: app name - environmentName: - type: string - description: app name - status: - type: string - description: app name - appStatus: - type: string - description: app status for this environment - postStageStatus: - type: string - description: app name - preStageStatus: - type: string - description: app name - lastDeployedTime: - type: string - description: deployed time - materialInfo: - type: array - items: - type: object - DeploymentGroup: - type: object - required: - - id - properties: - id: - type: integer - description: id - ciPipelineId: - type: integer - description: ciPipelineId - environmentId: - type: integer - description: environmentId - appCount: - type: integer - description: appCount - name: - type: string - description: name - noOfApps: - type: string - description: noOfApps - BulkUpdateSeeExampleResponse: - type: object - required: - - Script - properties: - resource: - type: string - description: Resource from url path, i.e. {apiVersion} & {kind} - script: - $ref: '#/components/schemas/BulkUpdateScript' - description: Input Script for bulk update - readMe: - type: string - description: Readme for bulk update - BulkUpdateScript: - type: object - required: - - ApiVersion - - Kind - - Spec - properties: - apiVersion: - type: string - description: Api version from url - example: - - v1beta1 - kind: - type: string - description: Kind - example: - - application - spec: - $ref: '#/components/schemas/BulkUpdatePayload' - BulkUpdatePayload: - type: object - properties: - includes: - $ref: '#/components/schemas/NameIncludesExcludes' - excludes: - $ref: '#/components/schemas/NameIncludesExcludes' - envIds: - type: array - items: - type: integer - description: All Env Id's for updating dependent apps - global: - type: boolean - description: Global flag for updating dependent apps - DeploymentTemplate: - $ref: '#/components/schemas/Tasks' - ConfigMaps: - type: object - properties: - names: - type: array - items: - type: string - description: Name of All ConfigMaps to be updated - tasks: - $ref: '#/components/schemas/Spec' - Secrets: - type: object - properties: - names: - type: array - items: - type: string - description: Name of All Secrets to be updated - tasks: - $ref: '#/components/schemas/Spec' - Tasks: - type: object - properties: - spec: - $ref: '#/components/schemas/Spec' - description: Spec of the Task - Spec: - type: object - properties: - patchData: - type: string - description: string with details of the patch to be used for updating - NameIncludesExcludes: - type: object - properties: - names: - type: array - items: - type: string - description: All strings of app names to be included/excluded - ImpactedObjectsResponse: - type: object - properties: - deploymentTemplate: - type: array - items: - $ref: '#/components/schemas/DeploymentTemplateImpactedObjectsResponseForOneApp' - configMap: - type: array - items: - $ref: '#/components/schemas/CmAndSecretImpactedObjectsResponseForOneApp' - secret: - type: array - items: - $ref: '#/components/schemas/CmAndSecretImpactedObjectsResponseForOneApp' - DeploymentTemplateImpactedObjectsResponseForOneApp: - type: object - properties: - appId: - type: integer - description: Id of the impacted app - appName: - type: string - description: Name of the impacted app - envId: - type: string - description: Env Id of the impacted app - CmAndSecretImpactedObjectsResponseForOneApp: - type: object - properties: - appId: - type: integer - description: Id of the impacted app - appName: - type: string - description: Name of the impacted app - envId: - type: string - description: Env Id of the impacted app - names: - type: array - items: - type: string - description: Names of all configmaps/secrets impacted - BulkUpdateResponse: - type: object - properties: - deploymentTemplate: - $ref: '#/components/schemas/DeploymentTemplateBulkUpdateResponse' - configMap: - $ref: '#/components/schemas/CmAndSecretBulkUpdateResponse' - secret: - $ref: '#/components/schemas/CmAndSecretBulkUpdateResponse' - DeploymentTemplateBulkUpdateResponse: - type: object - properties: - message: - type: array - items: - type: string - description: All top-level messages in response of bulk update action - failure: - type: array - items: - $ref: '#/components/schemas/DeploymentTemplateBulkUpdateResponseForOneApp' - description: Details of all apps on which bulk update failed - successful: - type: array - items: - $ref: '#/components/schemas/DeploymentTemplateBulkUpdateResponseForOneApp' - description: Details of all apps on which bulk update applied successfully - CmAndSecretBulkUpdateResponse: - type: object - properties: - message: - type: array - items: - type: string - description: All top-level messages in response of bulk update action - failure: - type: array - items: - $ref: '#/components/schemas/CmAndSecretBulkUpdateResponseForOneApp' - description: Details of all apps on which bulk update failed - successful: - type: array - items: - $ref: '#/components/schemas/CmAndSecretBulkUpdateResponseForOneApp' - description: Details of all apps on which bulk update applied successfully - DeploymentTemplateBulkUpdateResponseForOneApp: - type: object - properties: - appId: - type: integer - description: Id of the concerned app - appName: - type: string - description: Name of the concerned app - envId: - type: integer - description: Env ID of the concerned app - message: - type: string - description: App-level message for the concerned app - CmAndSecretBulkUpdateResponseForOneApp: - type: object - properties: - appId: - type: integer - description: Id of the concerned app - appName: - type: string - description: Name of the concerned app - envId: - type: integer - description: Env ID of the concerned app - names: - type: array - items: - type: string - description: Names of all configmaps/secrets - message: - type: string - description: App-level message for the concerned app - BulkActionRequest: - type: object - properties: - includes: - $ref: '#/components/schemas/NameIncludesExcludes' - excludes: - $ref: '#/components/schemas/NameIncludesExcludes' - envIds: - type: array - items: - type: integer - description: All Env Id's for the bulk action - appIds: - type: array - items: - type: integer - description: All App Id's for the bulk action (alternative to includes/excludes - by name) - projectIds: - type: array - items: - type: integer - description: All Project Id's for the bulk action - BulkActionResponse: - type: object - properties: - message: - type: array - items: - type: string - description: Top-level messages in response of the bulk action - failure: - type: array - items: - $ref: '#/components/schemas/BulkActionFailureDetail' - description: Details of all items on which the bulk action failed - successful: - type: array - items: - $ref: '#/components/schemas/BulkActionSuccessDetail' - description: Details of all items on which the bulk action applied successfully - BulkActionFailureDetail: - type: object - properties: - appId: - type: integer - appName: - type: string - envId: - type: integer - message: - type: string - BulkActionSuccessDetail: - type: object - properties: - appId: - type: integer - appName: - type: string - envId: - type: integer - message: - type: string - BulkDeployRequest: - type: object - required: - - envIds - properties: - includes: - $ref: '#/components/schemas/NameIncludesExcludes' - excludes: - $ref: '#/components/schemas/NameIncludesExcludes' - envIds: - type: array - items: - type: integer - description: All Env Id's for the bulk deployment - appIds: - type: array - items: - type: integer - description: All App Id's for the bulk deployment (alternative to includes/excludes - by name) - projectIds: - type: array - items: - type: integer - description: All Project Id's for the bulk deployment - artifactId: - type: integer - description: ID of the CI artifact to be deployed - releaseId: - type: integer - description: ID of the release to be deployed - deploymentStrategy: - type: string - description: Deployment strategy to use (e.g., blue-green, canary, recreate) - BulkBuildTriggerRequest: - type: object - required: - - ciPipelineId - properties: - includes: - $ref: '#/components/schemas/NameIncludesExcludes' - excludes: - $ref: '#/components/schemas/NameIncludesExcludes' - appIds: - type: array - items: - type: integer - description: All App Id's for the bulk build trigger (alternative to includes/excludes - by name) - projectIds: - type: array - items: - type: integer - description: All Project Id's for the bulk build trigger - ciPipelineId: - type: integer - description: ID of the CI pipeline to trigger builds for - SSOLoginDto: - type: object - properties: - id: - type: integer - format: int32 - readOnly: true - name: - type: string - description: Type of auth ie google/github - label: - type: string - nullable: true - url: - type: string - format: url - description: Devtron Dashboard Url - example: https://devtron.example.com/orchestrator - nullable: true - config: - type: object - description: Configuration for the SSO provider (Dex connector config). - Structure varies. - active: - type: boolean - required: - - name - - url - - config - - active - UserInfo: - type: object - properties: - id: - type: integer - format: int32 - description: User ID. Should not be set for new user creation if auto-generated. - Not allowed to be system-admin-userid (1 or 2) by validation. - email_id: - type: string - format: email - description: User's email address. Cannot be system admin user email by - validation. - roles: - type: array - items: - type: string - description: List of direct roles assigned to the user (deprecated in favor - of roleFilters and userRoleGroups). - nullable: true - accessToken: - type: string - description: Access token for the user (typically not part of create/update - payload, but in response). - readOnly: true - nullable: true - roleFilters: - type: array - items: - $ref: '#/components/schemas/RoleFilter' - groups: - type: array - items: - type: string - description: Deprecated field for user groups. Use userRoleGroups instead. - nullable: true - userRoleGroups: - type: array - items: - $ref: '#/components/schemas/UserRoleGroup' - nullable: true - superAdmin: - type: boolean - description: Indicates if the user has super admin privileges. - lastLoginTime: - type: string - format: date-time - readOnly: true - description: The time the user last logged in. - required: - - email_id - RoleGroup: - type: object - properties: - id: - type: integer - format: int32 - readOnly: true - name: - type: string - description: Name of the Role group - description: - type: string - description: Descrition fo Role group - nullable: true - roleFilters: - type: array - description: Role filters - items: - $ref: '#/components/schemas/RoleFilter' - superAdmin: - type: boolean - description: Indicates if this role group grants super admin privileges. - required: - - name - - roleFilters - RoleFilter: - type: object - description: Defines a specific permission filter for a role. - properties: - entity: - type: string - description: The type of entity this filter applies to (e.g., apps, jobs, - chart-group, cluster). - enum: - - apps - - jobs - - chart-group - - cluster - team: - type: string - description: Team associated with this permission. Can be empty for some - global entities. - nullable: true - entityName: - type: string - description: Name of the specific entity (e.g., application name, job name, - chart group name). Can be empty for 'all' access. - nullable: true - environment: - type: string - description: Environment associated with this permission. Can be empty if - not applicable. - nullable: true - action: - type: string - description: Action permitted (e.g., get, create, update, delete, trigger, - *). - accessType: - type: string - description: Access type, typically for distinguishing app types like devtron-app - or helm-app. - enum: - - devtron-app - - helm-app - - '' - nullable: true - cluster: - type: string - description: Cluster name for cluster-scoped permissions. - nullable: true - namespace: - type: string - description: Namespace for cluster-scoped permissions. - nullable: true - group: - type: string - description: API group for K8s resources. - nullable: true - kind: - type: string - description: Kind of K8s resource. - nullable: true - resource: - type: string - description: Specific K8s resource name. - nullable: true - workflow: - type: string - description: Workflow name, applicable if entity is 'jobs'. - nullable: true - required: - - entity - - action - UserRoleGroup: - type: object - description: Associates a user with a role group. - properties: - roleGroup: - $ref: '#/components/schemas/RoleGroup' - RbacRoleDto: - type: object - description: Represents a default RBAC role. - properties: - id: - type: integer - format: int32 - roleName: - type: string - roleDisplayName: - type: string - roleDescription: - type: string - entity: - type: string - enum: - - apps - - cluster - - chart-group - - jobs - accessType: - type: string - nullable: true - BulkDeleteRequest: - type: object - properties: - ids: - type: array - items: - type: integer - format: int32 - description: List of IDs to delete. - listingRequest: - $ref: '#/components/schemas/ListingRequest' - required: - - ids - ListingRequest: - type: object - properties: - searchKey: - type: string - nullable: true - sortOrder: - type: string - enum: - - ASC - - DESC - nullable: true - sortBy: - type: string - nullable: true - offset: - type: integer - format: int32 - minimum: 0 - nullable: true - size: - type: integer - format: int32 - minimum: 1 - default: 20 - nullable: true - showAll: - type: boolean - nullable: true - readOnly: true - EnvironmentCreateRequest: - type: object - required: - - environment_name - - cluster_id - properties: - environment_name: - type: string - maxLength: 50 - description: Name of the Environment - cluster_id: - type: integer - description: Id of the target Cluster - active: - type: boolean - default: true - default: - type: boolean - default: false - prometheus_endpoint: - type: string - description: Prometheus Endpoint of cluster - namespace: - type: string - description: Name of the Namespace which will point to environment - maxLength: 50 - isClusterCdActive: - type: boolean - description: - type: string - maxLength: 40 - isVirtualEnvironment: - type: boolean - default: false - allowedDeploymentTypes: - type: array - items: - type: string - enum: - - helm - - argo_cd - EnvironmentUpdateRequest: - type: object - required: - - id - - environment_name - - cluster_id - properties: - id: - type: integer - environment_name: - type: string - description: Name of the Environment - maxLength: 50 - cluster_id: - type: integer - description: Id of the target Cluster - active: - type: boolean - default: - type: boolean - prometheus_endpoint: - type: string - description: Prometheus Endpoint of cluster - namespace: - type: string - description: Name of the Namespace pointing to environment - maxLength: 50 - isClusterCdActive: - type: boolean - description: - type: string - maxLength: 40 - isVirtualEnvironment: - type: boolean - allowedDeploymentTypes: - type: array - items: - type: string - enum: - - helm - - argo_cd - EnvironmentDetail: - type: object - properties: - id: - type: integer - environment_name: - type: string - description: Name of the Environment - cluster_id: - type: integer - description: Id of the target Cluster - cluster_name: - type: string - description: Name of the cluster - active: - type: boolean - default: - type: boolean - prometheus_endpoint: - type: string - description: Prometheus Endpoint of cluster - namespace: - type: string - description: Name of the Namespace pointing to environment - isClusterCdActive: - type: boolean - environmentIdentifier: - type: string - description: - type: string - appCount: - type: integer - isVirtualEnvironment: - type: boolean - allowedDeploymentTypes: - type: array - items: - type: string - enum: - - helm - - argo_cd - ClusterWithEnvironments: - type: object - properties: - id: - type: integer - description: Cluster ID - cluster_name: - type: string - description: Name of the cluster - server_url: - type: string - description: Server URL of the cluster - active: - type: boolean - description: Whether the cluster is active - environments: - type: array - items: - $ref: '#/components/schemas/Environment' - prometheus_url: - type: string - description: URL for Prometheus monitoring - k8sVersion: - type: string - description: Kubernetes version of the cluster - Environment: - type: object - properties: - environmentId: - type: integer - description: Environment ID - environmentName: - type: string - description: Name of the environment - environmentIdentifier: - type: string - description: Unique identifier for the environment - namespace: - type: string - description: Namespace associated with the environment - active: - type: boolean - description: Whether the environment is active - ClusterBean: - type: object - properties: - id: - type: integer - description: Id of the cluster - cluster_name: - type: string - description: Name of the cluster - server_url: - type: string - description: Server Url of the cluster - prometheus_url: - type: string - description: Prometheus Endpoint of cluster - active: - type: boolean - config: - type: object - properties: - bearer_token: - type: string - description: it will be empty while fetching, and if no change while - updating - prometheusAuth: - $ref: '#/components/schemas/PrometheusAuthGet' - defaultClusterComponents: - type: array - items: - $ref: '#/components/schemas/DefaultClusterComponentGet' - k8sversion: - type: string - description: K8s version of the cluster - ClusterAuthDetail: - type: object - properties: - clusterId: - type: integer - description: cluster id - clusterName: - type: string - description: cluster name - errorInConnecting: - type: string - description: error message if cluster failed to connect - Kubeconfig: - type: object - description: Kube config of target cluster - properties: - config: - type: string - ValidateClusterBean: - type: object - required: - - cluster_name - - server_url - properties: - userInfos: - type: object - additionalProperties: - $ref: '#/components/schemas/UserInfos' - id: - type: integer - description: Cluster Id - cluster_name: - type: string - description: Name of the cluster - server_url: - type: string - description: Server Url of the cluster - prometheus_url: - type: string - description: Prometheus Endpoint of the cluster - active: - type: boolean - config: - type: object - properties: - bearer_token: - type: string - description: it will be empty while fetching, and if no change while - updating - tls_key: - type: string - description: it will be empty while fetching, and if no change while - updating - cert_data: - type: string - description: it will be empty while fetching, and if no change while - updating - cert_auth_data: - type: string - description: it will be empty while fetching, and if no change while - updating - prometheusAuth: - $ref: '#/components/schemas/PrometheusAuthAdd' - defaultClusterComponent: - type: array - items: - $ref: '#/components/schemas/DefaultClusterComponentAdd' - agentInstallationStage: - type: integer - k8sVersion: - type: string - description: K8s version of the cluster - userName: - type: string - insecure-skip-tls-verify: - type: boolean - UserInfos: - type: object - properties: - userName: - type: string - config: - type: object - additionalProperties: - type: string - errorInConnecting: - type: string - PrometheusAuthAdd: - type: object - properties: - type: - type: string - enum: - - basic - - bearer - basic: - type: object - properties: - username: - type: string - password: - type: string - bearer: - type: object - properties: - token: - type: string - PrometheusAuthGet: - type: object - properties: - userName: - type: string - password: - type: string - tlsClientCert: - type: string - tlsClientKey: - type: string - DefaultClusterComponentAdd: - type: object - properties: - id: - type: string - name: - type: string - version: - type: string - status: - type: string - configuration: - $ref: '#/components/schemas/ComponentConfiguration' - DefaultClusterComponentGet: - type: object - properties: - name: - type: string - appId: - type: integer - installedAppId: - type: integer - envId: - type: integer - envname: - type: string - status: - type: string - ComponentConfiguration: - type: object - properties: - type: - type: string - enum: - - yaml - - json - CloneApplicationWorkflowRequest: - type: object - properties: - appId: - type: integer - description: ID of the application - appName: - type: string - description: Name of the application - sourceEnvironmentId: - type: integer - description: ID of the source environment - sourceEnvironmentName: - type: string - description: Name of the source environment - targetEnvironmentId: - type: integer - description: ID of the target environment - targetEnvironmentName: - type: string - description: Name of the target environment - cloneEnvInSameWorkflow: - type: boolean - description: Flag indicating if the environment should be cloned in the - same workflow - CloneApplicationWorkflowResponse: - type: object - properties: - status: - type: string - description: Status of the operation - enum: - - SUCCESS - - FAILED - - SKIPPED - message: - type: string - description: Detailed message about the operation result - required: - - status - - message - StandardResponse: - type: object - properties: - code: - type: integer - description: HTTP status code - example: 200 - status: - type: string - description: HTTP status text - example: OK - result: - type: object - properties: - status: - type: string - description: Status of the operation - enum: - - SUCCESS - - FAILED - - SKIPPED - message: - type: string - description: Detailed message about the operation result - required: - - status - - message - required: - - code - - status - - result - ResourceInfo: - type: object - required: - - podName - properties: - podName: - type: string - description: Name of the inception pod. - example: inception-pod-xyz - TerminalMessage: - type: object - properties: - Op: - type: string - description: Operation type for the terminal session. - example: stdin - Data: - type: string - description: Data for the terminal session (e.g., command or output). - example: ls -l - SessionID: - type: string - description: ID of the terminal session. - example: unique-session-id-123 - ResourceRequestObject: - type: object - properties: - appId: - type: string - description: Application ID. Used when the request is context-specific to - an application. - example: my-app/env-1 - clusterId: - type: number - description: Cluster ID. Used when the request is for a direct cluster resource - (appId is not supplied). - example: 1 - k8sRequest: - $ref: '#/components/schemas/K8sRequestObject' - K8sRequestObject: - type: object - properties: - resourceIdentifier: - type: object - properties: - groupVersionKind: - $ref: '#/components/schemas/GroupVersionKind' - namespace: - type: string - description: Namespace of the resource. - example: default - name: - type: string - description: Name of the resource. - example: my-deployment - required: - - name - - groupVersionKind - podLogsRequest: - type: object - properties: - containerName: - type: string - description: Name of the container for which logs are requested. - example: my-container - patch: - type: string - description: JSON patch or strategic merge patch to apply to the resource. - example: '[{"op": "replace", "path": "/spec/replicas", "value": 3}]' - ResourceGetResponse: - type: object - properties: - manifestResponse: - $ref: '#/components/schemas/ManifestResponse' - secretViewAccess: - type: boolean - description: 'Indicates whether a user can see obscured secret values or - not. True if the user has permission, false otherwise. - - ' - example: true - required: - - manifestResponse - - secretViewAccess - ManifestResponse: - type: object - properties: - manifest: - type: object - description: The Kubernetes resource manifest. - additionalProperties: true - example: - apiVersion: v1 - kind: ConfigMap - metadata: - name: my-config - namespace: default - data: - key1: value1 - key2: value2 - EventsResponseObject: - type: object - description: Represents a Kubernetes Event object. - properties: - metadata: - $ref: '#/components/schemas/ObjectMeta' - involvedObject: - $ref: '#/components/schemas/ObjectReference' - reason: - type: string - description: Short, machine-understandable string that describes the reason - for the transition into the object's current status. - example: Scheduled - message: - type: string - description: A human-readable description of the status of this operation. - example: Successfully assigned default/my-pod to node-1 - source: - $ref: '#/components/schemas/EventSource' - firstTimestamp: - type: string - format: date-time - description: The time at which the event was first recorded. - lastTimestamp: - type: string - format: date-time - description: The time at which the most recent occurrence of this event - was recorded. - count: - type: integer - format: int32 - description: The number of times this event has occurred. - type: - type: string - description: Type of this event (Normal, Warning), new types could be added - in the future. - example: Normal - eventTime: - type: string - format: date-time - nullable: true - description: MicroTime is version of Time with microsecond level precision. - reportingComponent: - type: string - example: kubelet - reportingInstance: - type: string - example: node-1 - ObjectMeta: - type: object - properties: - name: - type: string - namespace: - type: string - uid: - type: string - resourceVersion: - type: string - creationTimestamp: - type: string - format: date-time - ObjectReference: - type: object - properties: - kind: - type: string - namespace: - type: string - name: - type: string - uid: - type: string - apiVersion: - type: string - resourceVersion: - type: string - EventSource: - type: object - properties: - component: - type: string - host: - type: string - LogsResponseObject: - type: object - properties: - id: - type: string - description: Identifier for the log entry (if provided by the stream). - type: - type: string - description: Type of the log entry (e.g., 'stdout', 'stderr'). - data: - type: string - description: The actual log line content. - time: - type: string - format: date-time - description: Timestamp of the log entry. - GetAllApiResourcesResponse: - type: object - properties: - apiResources: - type: array - items: - $ref: '#/components/schemas/K8sApiResource' - allowedAll: - type: boolean - description: Whether all API resources are allowed for this user. - example: true - K8sApiResource: - type: object - properties: - gvk: - $ref: '#/components/schemas/GroupVersionKind' - namespaced: - type: boolean - description: Whether this API resource is namespace-scoped or cluster-scoped. - example: true - GroupVersionKind: - type: object - properties: - group: - type: string - description: Group of the API resource. - example: apps - version: - type: string - description: Version of the API resource. - example: v1 - kind: - type: string - description: Kind of the API resource. - example: Deployment - required: - - group - - version - - kind - ClusterResourceListResponse: - type: object - description: Represents a list of resources with dynamic headers and corresponding - data. - properties: - headers: - type: array - items: - type: string - description: An array of strings representing the column headers for the - resource list. - example: - - NAME - - NAMESPACE - - KIND - - AGE - data: - type: array - items: - type: object - additionalProperties: - type: string - description: 'An array of objects. Each object represents a resource, - and its keys correspond to the ''headers''. The values are the resource''s - data for those headers. - - ' - example: - - NAME: my-pod-1 - NAMESPACE: default - KIND: Pod - AGE: 2d - - NAME: my-service-abc - NAMESPACE: kube-system - KIND: Service - AGE: 10h - RotatePodRequest: - type: object - properties: - clusterId: - type: number - description: ID of the cluster where resources reside. - example: 1 - resources: - type: array - items: - type: object - properties: - groupVersionKind: - $ref: '#/components/schemas/GroupVersionKind' - namespace: - type: string - description: Namespace of the resource. - example: production - name: - type: string - description: Name of the resource (e.g., Deployment, StatefulSet name). - example: my-app-deployment - required: - - name - - groupVersionKind - - namespace - required: - - clusterId - - resources - RotatePodResponse: - type: object - properties: - containsError: - type: boolean - description: True if any error occurred during the rotation of one or more - pods. - example: false - responses: - type: array - items: - type: object - properties: - groupVersionKind: - $ref: '#/components/schemas/GroupVersionKind' - namespace: - type: string - description: Namespace of the resource. - name: - type: string - description: Name of the resource. - errorResponse: - type: string - nullable: true - description: Error message if rotation failed for this specific resource. - Otherwise null. - example: failed to find resource - ApplyResourcesRequest: - type: object - properties: - clusterId: - type: number - description: ID of the cluster where resources will be applied. - example: 1 - manifest: - type: string - description: 'A string containing one or more Kubernetes resource manifests, - separated by ''---''. - - ' - example: "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: my-cm\ndata:\n\ - \ key: value\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n\ - \ name: my-app\nspec:\n replicas: 1\n selector:\n matchLabels:\n\ - \ app: my-app\n template:\n metadata:\n labels:\n \ - \ app: my-app\n spec:\n containers:\n - name: nginx\n \ - \ image: nginx\n" - required: - - clusterId - - manifest - ApplyResourcesResponse: - type: object - properties: - kind: - type: string - description: Kind of the resource that was applied. - example: Deployment - name: - type: string - description: Name of the resource that was applied. - example: my-app - error: - type: string - nullable: true - description: Error message if applying this specific resource failed. Otherwise - null. - example: null - isUpdate: - type: boolean - description: True if the resource was updated, false if it was created (or - no change). - example: true - required: - - kind - - name - - isUpdate - AppWorkflowDto: - type: object - properties: - id: - type: integer - description: ID of the workflow. - readOnly: true - name: - type: string - description: Name of the workflow. - appId: - type: integer - description: ID of the application this workflow belongs to. - tree: - type: array - items: - $ref: '#/components/schemas/AppWorkflowMappingDto' - AppWorkflowMappingDto: - type: object - properties: - id: - type: integer - description: ID of the workflow mapping. - readOnly: true - appWorkflowId: - type: integer - description: ID of the parent application workflow. - type: - type: string - description: Type of the component (e.g., CI_PIPELINE, CD_PIPELINE). - componentId: - type: integer - description: ID of the component (e.g., CiPipelineId, CdPipelineId). - parentId: - type: integer - description: ID of the parent component in the workflow tree. - parentType: - type: string - description: Type of the parent component in the workflow tree. - deploymentAppDeleteRequest: - type: boolean - description: Indicates if a deployment app delete request is associated. - isLast: - type: boolean - description: Indicates if this is the last node in its branch of the tree. - GitOpsConfigDto: - type: object - properties: - id: - type: integer - description: GitOps Id (null for new configuration) - provider: - type: string - description: Gitops provider - example: github,gitlabs - username: - type: string - description: Username of GitOps provider - token: - type: string - description: Authentication token of GitOps provider - gitLabGroupId: - type: string - description: Group Id of gitLab - gitHubOrgId: - type: string - description: Group Id of gitHub - host: - type: string - description: Host of GitOps provider - active: - type: boolean - azureProjectName: - type: string - description: Project Name of Azure - userId: - type: integer - description: User Id of GitOps provider - DetailedError: - type: object - properties: - successfulStages: - type: array - items: - type: string - description: All successful stages - validatedOn: - type: string - description: Timestamp of validation - stageErrorMap: - type: array - items: - type: object - properties: - stage: - type: string - error: - type: string - description: map of stage and their respective errors - NotificationSetting: - type: object - required: - - configName - properties: - id: - type: integer - description: Unique id - configName: - type: string - description: Unique name of group - appId: - type: integer - description: app id - envId: - type: integer - description: env id - pipelineIds: - type: array - items: - type: integer - eventTypeIds: - type: array - items: - type: integer - pipelineType: - type: string - description: pipeline type CI or CD - providers: - type: array - items: - $ref: '#/components/schemas/providers' - description: role filters objects - providers: - type: object - required: - - dest - properties: - dest: - type: string - description: channel destination name - rule: - type: string - description: rule - configId: - type: integer - description: config id - NotificationConfig: - type: object - required: - - channel - properties: - channel: - type: string - description: channel type - enum: - - slack - - ses - configs: - type: array - items: - $ref: '#/components/schemas/configs' - description: config holds for either slack or ses - NotificationConfigResponse: - type: object - properties: - slackConfigs: - type: array - items: - $ref: '#/components/schemas/configs' - description: config holds for either slack or ses - sesConfigs: - type: array - items: - $ref: '#/components/schemas/configs' - description: config holds for either slack or ses - configs: - type: object - required: - - type - - configName - properties: - id: - type: integer - description: unique id for config either slack or ses on response or update - only - type: - type: string - description: channel destination type, slack or ses - configName: - type: string - description: configName - secretKey: - type: string - description: secretKey, only in case of ses - accessKey: - type: string - description: accessKey, only in case of ses - fromEmail: - type: string - description: fromEmail, only in case of ses - region: - type: string - description: region, only in case of ses - webhookUrl: - type: string - description: webhook url, only fill in case of type is slack - teamId: - type: integer - description: project id, only fill in case of type is slack - userId: - type: integer - description: project id, only fill in case of type is slack - entity: - type: object - properties: - id: - type: integer - description: it contains entity id - name: - type: string - description: it contains entity name - HistoryComponentDetailDto: - type: object - properties: - values: - type: array - items: - $ref: '#/components/schemas/HistoryComponentValuesDto' - codeEditorValue: - type: object - properties: - displayName: - type: string - value: - type: string - HistoryComponentValuesDto: - type: object - properties: - fieldName: - type: object - properties: - displayName: - type: string - value: - type: string - HistoryComponentListDto: - type: object - properties: - id: - type: integer - deployedOn: - type: string - format: timestamp - deployedBy: - type: string - deploymentStatus: - type: string - HistoryConfigurationListDto: - type: array - items: - $ref: '#/components/schemas/HistoryConfiguration' - HistoryConfiguration: - type: object - properties: - id: - type: integer - name: - type: string - enum: - - DEPLOYMENT_TEMPLATE - - CONFIGMAP - - SECRET - - PIPELINE_STRATEGY - childList: - type: array - items: - type: string - requestBodies: - SSOLoginDto: - description: SSO Login Configuration object - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/SSOLoginDto' - UserInfo: - description: User Information object - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UserInfo' - RoleGroup: - description: Role Group object - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RoleGroup' - BulkDeleteRequest: - description: Request for bulk deletion of items. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkDeleteRequest' - responses: - SSOLoginConfigResponse: - description: Response for SSO Login Configuration. - content: - application/json: - schema: - $ref: '#/components/schemas/SSOLoginDto' - UserInfoResponse: - description: Response containing User Information. - content: - application/json: - schema: - $ref: '#/components/schemas/UserInfo' - UserListingResponse: - description: Paginated list of users. - content: - application/json: - schema: - type: object - properties: - users: - type: array - items: - $ref: '#/components/schemas/UserInfo' - totalCount: - type: integer - format: int32 - RoleGroupResponse: - description: Response containing Role Group information. - content: - application/json: - schema: - $ref: '#/components/schemas/RoleGroup' - RoleGroupListingResponse: - description: Paginated list of role groups. - content: - application/json: - schema: - type: object - properties: - roleGroups: - type: array - items: - $ref: '#/components/schemas/RoleGroup' - totalCount: - type: integer - format: int32 - GenericSuccess: - description: Generic success response. - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - example: true - BadRequest: - description: Bad request. Invalid input parameters. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - Unauthorized: - description: Unauthorized. User is not logged in or token is invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - Forbidden: - description: Forbidden. User does not have permission. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - NotAcceptable: - description: Not Acceptable. Request cannot be processed. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - InternalServerError: - description: Internal server error. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - parameters: - PathId: - name: id - in: path - required: true - description: Identifier (typically integer ID). - schema: - type: integer - format: int32 - SearchKeyQuery: - name: searchKey - in: query - required: false - description: Search term. - schema: - type: string - SortOrderQuery: - name: sortOrder - in: query - required: false - description: Sort order (ASC or DESC). - schema: - type: string - enum: - - ASC - - DESC - SortByQueryUser: - name: sortBy - in: query - required: false - description: Field to sort users by (e.g., email_id, last_login). - schema: - type: string - enum: - - email_id - - last_login - SortByQueryRoleGroup: - name: sortBy - in: query - required: false - description: Field to sort role groups by (e.g., name). - schema: - type: string - enum: - - name - OffsetQuery: - name: offset - in: query - required: false - description: Offset for pagination. - schema: - type: integer - format: int32 - minimum: 0 - SizeQuery: - name: size - in: query - required: false - description: Number of items per page. - schema: - type: integer - format: int32 - minimum: 1 - default: 20 -x-tagGroups: -- name: Common Devtron automation APIs - tags: - - Metadata - - Jobs - - Helm Charts - - List Applications - - Applications - - Labels - - bulk_other - - BulkUpdate - - SSO Configuration - - User Management - - Role Group Management - - RBAC - - Authentication - - Policy Management - - Cache Management - - Cluster Environment - - Cluster Management - - Environment Management - - Change Chart - - Clone Workflow - - Deployment History - - K8s Resource - - Workflow Management - - Devtron Server version - - GitOps Validation - - Notifications diff --git a/tests/api-spec-validation/reports/live-server-validation-report.md b/tests/api-spec-validation/reports/live-server-validation-report.md new file mode 100644 index 0000000000..82d2975328 --- /dev/null +++ b/tests/api-spec-validation/reports/live-server-validation-report.md @@ -0,0 +1,2057 @@ +# API Spec Validation Report + +Generated: 2025-08-05T22:10:14+05:30 + +## Summary + +- Total Endpoints: 165 +- Passed: 59 +- Failed: 106 +- Warnings: 0 +- Success Rate: 35.76% + +## Detailed Results + +### ❌ GET /orchestrator/app/helm/meta/info/{appId} + +- **Status**: FAIL +- **Duration**: 435.672417ms +- **Spec File**: ../../specs/application/labels.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"sample_string\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"sample_strin... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ✅ GET /orchestrator/app/labels/list + +- **Status**: PASS +- **Duration**: 111.297791ms +- **Spec File**: ../../specs/application/labels.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[]} + +--- + +### ✅ GET /orchestrator/app/meta/info/{appId} + +- **Status**: PASS +- **Duration**: 117.284875ms +- **Spec File**: ../../specs/application/labels.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"appId":1,"appName":"helm-sanity-application","description":"","projectId":2,"projectName":"shared-devtron-demo1","createdBy":"admin","createdOn":"2025-07-15T07:30:... + +--- + +### ❌ POST /orchestrator/gitops/validate + +- **Status**: FAIL +- **Duration**: 110.391083ms +- **Spec File**: ../../specs/gitops/core.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/gitops/config + +- **Status**: PASS +- **Duration**: 112.942375ms +- **Spec File**: ../../specs/gitops/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"provider":"GITHUB","username":"systemsdt","token":"","gitLabGroupId":"","gitHubOrgId":"stage-gitops","host":"https://github.com/","active":true,"azureProje... + +--- + +### ❌ POST /orchestrator/gitops/config + +- **Status**: FAIL +- **Duration**: 107.511958ms +- **Spec File**: ../../specs/gitops/core.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{value is unsupported Key: 'GitOpsConfigDto.Provider' Error:Field validation for 'Provider' failed on the 'oneof' tag}]... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ PUT /orchestrator/gitops/config + +- **Status**: FAIL +- **Duration**: 105.382917ms +- **Spec File**: ../../specs/gitops/core.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ GET /orchestrator/gitops/config-by-provider + +- **Status**: FAIL +- **Duration**: 183.867208ms +- **Spec File**: ../../specs/gitops/core.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/gitops/config/{id} + +- **Status**: PASS +- **Duration**: 109.077583ms +- **Spec File**: ../../specs/gitops/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"provider":"GITHUB","username":"systemsdt","token":"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","gitLabGro... + +--- + +### ✅ GET /orchestrator/gitops/configured + +- **Status**: PASS +- **Duration**: 110.496458ms +- **Spec File**: ../../specs/gitops/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"allowCustomRepository":false,"authMode":"PASSWORD","exists":true,"provider":"GITHUB"}} + +--- + +### ❌ POST /orchestrator/batch/v1beta1/hibernate + +- **Status**: FAIL +- **Duration**: 108.301041ms +- **Spec File**: ../../specs/jobs/bulk-actions.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{ERROR #42601 syntax error at or near \")\"}]","userMessage":"ERROR #42601 syntax error at or near \")\""}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ POST /v1beta1/deploy + +- **Status**: FAIL +- **Duration**: 119.661834ms +- **Spec File**: ../../specs/jobs/bulk-actions.yaml +- **Response Code**: 404 +- **Error/Msg**: +404 Not Found + +

404 Not Found

+
nginx
+ + + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /v1beta1/unhibernate + +- **Status**: FAIL +- **Duration**: 104.9255ms +- **Spec File**: ../../specs/jobs/bulk-actions.yaml +- **Response Code**: 404 +- **Error/Msg**: +404 Not Found + +

404 Not Found

+
nginx
+ + + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ PUT /orchestrator/cluster + +- **Status**: FAIL +- **Duration**: 109.297583ms +- **Spec File**: ../../specs/kubernetes/cluster.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ClusterBean.ClusterName' Error:Field validation for 'ClusterName' failed on the 'required' tag","userMessage":"Key: 'ClusterBean.... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/cluster + +- **Status**: PASS +- **Duration**: 108.879583ms +- **Spec File**: ../../specs/kubernetes/cluster.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":6,"cluster_name":"abcd","description":"","active":true,"config":{"bearer_token":""},"prometheusAuth":{"isAnonymous":false},"defaultClusterComponent":[],"agent... + +--- + +### ✅ GET /orchestrator/cluster/auth-list + +- **Status**: PASS +- **Duration**: 109.895125ms +- **Spec File**: ../../specs/kubernetes/cluster.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":6,"cluster_name":"abcd","description":"","active":false,"defaultClusterComponent":null,"agentInstallationStage":0,"k8sVersion":"","insecureSkipTlsVerify":fals... + +--- + +### ❌ POST /orchestrator/webhook/git/{gitHostId} + +- **Status**: FAIL +- **Duration**: 109.933625ms +- **Spec File**: ../../specs/notifications/webhooks.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /orchestrator/webhook/git/{gitHostId}/{secret} + +- **Status**: FAIL +- **Duration**: 106.638042ms +- **Spec File**: ../../specs/notifications/webhooks.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /orchestrator/webhook/ci/workflow + +- **Status**: FAIL +- **Duration**: 110.802834ms +- **Spec File**: ../../specs/notifications/webhooks.yaml +- **Response Code**: 500 +- **Error/Msg**: internal server error + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ POST /orchestrator/webhook/ext-ci/{externalCiId} + +- **Status**: FAIL +- **Duration**: 106.369958ms +- **Spec File**: ../../specs/notifications/webhooks.yaml +- **Response Code**: 401 +- **Error/Msg**: {"code":401,"status":"Unauthorized","errors":[{"code":"6005","internalMessage":"no token provided"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 401 + +--- + +### ❌ POST /orchestrator/webhook/git + +- **Status**: FAIL +- **Duration**: 114.307416ms +- **Spec File**: ../../specs/notifications/webhooks.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /orchestrator/plugin/global/list/detail/v2 + +- **Status**: FAIL +- **Duration**: 163.790334ms +- **Spec File**: ../../specs/plugins/global.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","internalMessage":"Empty values for both pluginVersionIds and parentPluginIds. Please provide at least one of them","userMessage":"Empty valu... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/plugin/global/list/tags + +- **Status**: PASS +- **Duration**: 172.735041ms +- **Spec File**: ../../specs/plugins/global.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"tagNames":["Load testing","Kubernetes","gcs","Github","Code Review","Code quality","DevSecOps","Image source","cloud","AWS EKS","Security","CI task","Google Kubern... + +--- + +### ❌ POST /orchestrator/plugin/global/create + +- **Status**: FAIL +- **Duration**: 143.656625ms +- **Spec File**: ../../specs/plugins/global.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","internalMessage":"no step data provided to save, please provide a plugin step to proceed further","userMessage":"no step data provided to sa... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/plugin/global/detail/all + +- **Status**: PASS +- **Duration**: 756.330042ms +- **Spec File**: ../../specs/plugins/global.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"name":"K6 Load testing","description":"K6 is an open-source tool and cloud service that makes load testing easy for developers and QA engineers.","type":"P... + +--- + +### ❌ GET /orchestrator/plugin/global/list/global-variable + +- **Status**: FAIL +- **Duration**: 106.387625ms +- **Spec File**: ../../specs/plugins/global.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"\": invalid syntax}]","userMessage":"invalid appId"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/plugin/global/list/v2 + +- **Status**: PASS +- **Duration**: 122.855208ms +- **Spec File**: ../../specs/plugins/global.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"parentPlugins":[{"id":4,"name":"AWS ECR Retag","pluginIdentifier":"aws-retag","description":"AWS ECR Retag plugin that enables retagging of container images within... + +--- + +### ✅ GET /orchestrator/plugin/global/list/v2/min + +- **Status**: PASS +- **Duration**: 105.0705ms +- **Spec File**: ../../specs/plugins/global.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[]} + +--- + +### ✅ PUT /orchestrator/plugin/global/migrate + +- **Status**: PASS +- **Duration**: 108.638875ms +- **Spec File**: ../../specs/plugins/global.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK"} + +--- + +### ✅ GET /orchestrator/plugin/global/detail/{pluginId} + +- **Status**: PASS +- **Duration**: 116.877292ms +- **Spec File**: ../../specs/plugins/global.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"name":"K6 Load testing","description":"K6 is an open-source tool and cloud service that makes load testing easy for developers and QA engineers.","type":"PR... + +--- + +### ❌ POST /orchestrator/user/resource/options/{kind}/{version} + +- **Status**: FAIL +- **Duration**: 101.167125ms +- **Spec File**: ../../specs/userResource/userResource.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/app-store/installed-app + +- **Status**: PASS +- **Duration**: 108.455542ms +- **Spec File**: ../../specs/helm/charts.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"clusterIds":null,"applicationType":"DEVTRON-CHART-STORE","helmApps":[{"lastDeployedAt":"2025-07-15T10:48:16.504431Z","appName":"pk-chart-gitops","appId":"2","chart... + +--- + +### ❌ GET /orchestrator/app-store/installed-app/notes + +- **Status**: FAIL +- **Duration**: 103.081792ms +- **Spec File**: ../../specs/helm/charts.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/chartref/autocomplete/{appId} + +- **Status**: PASS +- **Duration**: 110.60575ms +- **Spec File**: ../../specs/helm/dynamic-charts.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"chartRefs":[{"id":10,"version":"3.9.0","name":"Rollout Deployment","description":"","userUploaded":false,"isAppMetricsSupported":true},{"id":11,"version":"3.10.0",... + +--- + +### ✅ GET /orchestrator/app/history/deployed-configuration/{appId}/{pipelineId}/{wfrId} + +- **Status**: PASS +- **Duration**: 110.757ms +- **Spec File**: ../../specs/audit/api-changes.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":8,"name":"DEPLOYMENT_TEMPLATE"},{"id":3,"name":"PIPELINE_STRATEGY"}]} + +--- + +### ❌ GET /orchestrator/app/history/deployed-component/detail/{appId}/{pipelineId}/{id} + +- **Status**: FAIL +- **Duration**: 107.952708ms +- **Spec File**: ../../specs/audit/api-changes.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","result":"invalid historyComponent"} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ GET /orchestrator/app/history/deployed-component/list/{appId}/{pipelineId} + +- **Status**: FAIL +- **Duration**: 107.582625ms +- **Spec File**: ../../specs/audit/api-changes.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","result":"invalid historyComponent"} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/version + +- **Status**: PASS +- **Duration**: 105.365875ms +- **Spec File**: ../../specs/common/version.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"result":{"gitCommit":"a73ff9ef","buildTime":"2025-07-16T13:44:58Z","serverMode":"FULL"}} + +--- + +### ✅ GET /orchestrator/external-links/tools + +- **Status**: PASS +- **Duration**: 108.95ms +- **Spec File**: ../../specs/external-links/external-links-specs.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"name":"Grafana","icon":"","category":2},{"id":2,"name":"Kibana","icon":"","category":2},{"id":3,"name":"Newrelic","icon":"","category":2},{"id":4,"name":"C... + +--- + +### ❌ DELETE /orchestrator/external-links + +- **Status**: FAIL +- **Duration**: 105.058209ms +- **Spec File**: ../../specs/external-links/external-links-specs.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 +- **RESPONSE_FORMAT_ERROR**: Response is not valid JSON: invalid character 'p' after top-level value + +--- + +### ✅ GET /orchestrator/external-links + +- **Status**: PASS +- **Duration**: 108.622542ms +- **Spec File**: ../../specs/external-links/external-links-specs.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[]} + +--- + +### ❌ POST /orchestrator/external-links + +- **Status**: FAIL +- **Duration**: 108.2415ms +- **Spec File**: ../../specs/external-links/external-links-specs.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{json: cannot unmarshal object into Go value of type []*externalLink.ExternalLinkDto}]","userMessage":"json: cannot unmar... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ PUT /orchestrator/external-links + +- **Status**: FAIL +- **Duration**: 107.402833ms +- **Spec File**: ../../specs/external-links/external-links-specs.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ GET /orchestrator/git/host/{id} + +- **Status**: FAIL +- **Duration**: 104.597875ms +- **Spec File**: ../../specs/gitops/submodules.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"{id}\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"{id}\": invalid synta... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ GET /orchestrator/git/host/{id}/event + +- **Status**: FAIL +- **Duration**: 106.339792ms +- **Spec File**: ../../specs/gitops/submodules.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"{id}\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"{id}\": invalid synta... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ✅ GET /orchestrator/git/host + +- **Status**: PASS +- **Duration**: 107.316ms +- **Spec File**: ../../specs/gitops/submodules.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"name":"Github","active":true,"webhookUrl":"","webhookSecret":"","eventTypeHeader":"","secretHeader":"","secretValidator":""},{"id":2,"name":"Bitbucket Clou... + +--- + +### ❌ POST /orchestrator/git/host + +- **Status**: FAIL +- **Duration**: 108.852792ms +- **Spec File**: ../../specs/gitops/submodules.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'GitHostRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag","userMessage":"Key: 'GitHostRequest.Name' Er... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ GET /orchestrator/git/host/event/{eventId} + +- **Status**: FAIL +- **Duration**: 115.740541ms +- **Spec File**: ../../specs/gitops/submodules.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"{eventId}\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"{eventId}\": inv... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ GET /orchestrator/git/host/webhook-meta-config/{gitProviderId} + +- **Status**: FAIL +- **Duration**: 388.766667ms +- **Spec File**: ../../specs/gitops/submodules.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{ERROR #22P02 invalid input syntax for type integer: \"{gitProviderId}\"}]","userMessage":"ERROR #22P02 invalid... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ✅ GET /orchestrator/module + +- **Status**: PASS +- **Duration**: 537.444041ms +- **Spec File**: ../../specs/modularisation/v1.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"name":"security.trivy","status":"installed","moduleResourcesStatus":null,"enabled":true,"moduleType":"security"},{"name":"security.clair","status":"installed","mo... + +--- + +### ❌ POST /orchestrator/module + +- **Status**: FAIL +- **Duration**: 103.11125ms +- **Spec File**: ../../specs/modularisation/v1.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/server + +- **Status**: PASS +- **Duration**: 107.528ms +- **Spec File**: ../../specs/modularisation/v1.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"status":"unknown","releaseName":"devtron","installationType":"enterprise"}} + +--- + +### ❌ POST /orchestrator/server + +- **Status**: FAIL +- **Duration**: 168.68225ms +- **Spec File**: ../../specs/modularisation/v1.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ServerActionRequestDto.Action' Error:Field validation for 'Action' failed on the 'oneof' tag","userMessage":"Key: 'ServerActionRe... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ POST /orchestrator/config/environment/cm + +- **Status**: FAIL +- **Duration**: 107.686584ms +- **Spec File**: ../../specs/plugins/config-maps.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{invalid request multiple config found for add or update}]","userMessage":"invalid request multiple config foun... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ GET /orchestrator/config/environment/cm/edit/{appId}/{envId}/{id} + +- **Status**: FAIL +- **Duration**: 102.67825ms +- **Spec File**: ../../specs/plugins/config-maps.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/config/environment/cm/{appId}/{envId} + +- **Status**: PASS +- **Duration**: 112.777417ms +- **Spec File**: ../../specs/plugins/config-maps.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"id":0,"appId":1,"environmentId":1,"configData":[],"isDeletable":false,"isExpressEdit":false}} + +--- + +### ❌ DELETE /orchestrator/config/environment/cm/{appId}/{envId}/{id} + +- **Status**: FAIL +- **Duration**: 105.252292ms +- **Spec File**: ../../specs/plugins/config-maps.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /orchestrator/config/global/cm + +- **Status**: FAIL +- **Duration**: 108.859ms +- **Spec File**: ../../specs/plugins/config-maps.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{invalid request multiple config found for add or update}]","userMessage":"invalid request multiple config foun... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ POST /orchestrator/config/bulk/patch + +- **Status**: FAIL +- **Duration**: 109.450916ms +- **Spec File**: ../../specs/plugins/config-maps.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{invalid request no payload found for sync}]","userMessage":"invalid request no payload found for sync"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ GET /orchestrator/config/global/cm/edit/{appId}/{id} + +- **Status**: FAIL +- **Duration**: 101.235417ms +- **Spec File**: ../../specs/plugins/config-maps.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/config/global/cm/{appId} + +- **Status**: PASS +- **Duration**: 107.309708ms +- **Spec File**: ../../specs/plugins/config-maps.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"id":0,"appId":1,"configData":[],"isDeletable":false,"isExpressEdit":false}} + +--- + +### ❌ DELETE /orchestrator/config/global/cm/{appId}/{id} + +- **Status**: FAIL +- **Duration**: 102.428916ms +- **Spec File**: ../../specs/plugins/config-maps.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/app-store/discover/application/chartInfo/{appStoreApplicationVersionId} + +- **Status**: PASS +- **Duration**: 520.679166ms +- **Spec File**: ../../specs/app-store.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"appStoreApplicationVersionId":1,"readme":"# cluster-autoscaler\n\nScales Kubernetes worker nodes within autoscaling groups.\n\n## TL;DR\n\n```console\n$ helm repo ... + +--- + +### ✅ GET /orchestrator/app-store/discover/application/{appStoreId}/version/autocomplete + +- **Status**: PASS +- **Duration**: 132.640375ms +- **Spec File**: ../../specs/app-store.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"version":"9.49.0","id":5507},{"version":"9.48.0","id":1},{"version":"9.47.0","id":2},{"version":"9.46.6","id":3},{"version":"9.46.5","id":4},{"version":"9.46.4","... + +--- + +### ✅ GET /orchestrator/app-store/discover/application/{id} + +- **Status**: PASS +- **Duration**: 169.7765ms +- **Spec File**: ../../specs/app-store.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"version":"9.48.0","appVersion":"1.33.0","created":"2025-07-11T21:16:00.149315Z","deprecated":false,"description":"Scales Kubernetes worker nodes within auto... + +--- + +### ❌ GET /orchestrator/app-store/discover/search + +- **Status**: FAIL +- **Duration**: 124.785ms +- **Spec File**: ../../specs/app-store.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/app-store/discover + +- **Status**: PASS +- **Duration**: 1.021184s +- **Spec File**: ../../specs/app-store.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":65,"appStoreApplicationVersionId":4028,"name":"ai-agent","chart_repo_id":2,"docker_artifact_store_id":"","chart_name":"devtron","icon":"","active":true,"chart... + +--- + +### ❌ GET /orchestrator/app/ci-pipeline/{ciPipelineId}/linked-ci/downstream/cd + +- **Status**: FAIL +- **Duration**: 107.782667ms +- **Spec File**: ../../specs/ci-pipeline/ciPipelineDownstream/downstream-linked-ci-view-spec.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{invalid CiPipelineId 1}]","userMessage":"invalid CiPipelineId 1"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ GET /orchestrator/app/ci-pipeline/{ciPipelineId}/linked-ci/downstream/env + +- **Status**: FAIL +- **Duration**: 105.740584ms +- **Spec File**: ../../specs/ci-pipeline/ciPipelineDownstream/downstream-linked-ci-view-spec.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{invalid CiPipelineId 1}]","userMessage":"invalid CiPipelineId 1"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ POST /orchestrator/app/cd-pipeline/patch/deployment + +- **Status**: FAIL +- **Duration**: 109.075375ms +- **Spec File**: ../../specs/deployment/app-type-change.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'DeploymentAppTypeChangeRequest.EnvId' Error:Field validation for 'EnvId' failed on the 'required' tag","userMessage":"Key: 'Deplo... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ POST /orchestrtor/batch/v1beta1/cd-pipeline + +- **Status**: FAIL +- **Duration**: 103.406625ms +- **Spec File**: ../../specs/environment/bulk-delete.yaml +- **Response Code**: 404 +- **Error/Msg**: +404 Not Found + +

404 Not Found

+
nginx
+ + + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ POST /orchestrator/job/list + +- **Status**: PASS +- **Duration**: 473.5475ms +- **Spec File**: ../../specs/jobs/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"jobContainers":[],"jobCount":0}} + +--- + +### ❌ POST /orchestrator/job + +- **Status**: FAIL +- **Duration**: 108.099375ms +- **Spec File**: ../../specs/jobs/core.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'CreateAppDTO.AppName' Error:Field validation for 'AppName' failed on the 'name-component' tag","userMessage":"Key: 'CreateAppDTO.... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ GET /orchestrator/job/ci-pipeline/list/{jobId} + +- **Status**: FAIL +- **Duration**: 110.828375ms +- **Spec File**: ../../specs/jobs/core.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","result":"Job with the given Id does not exist"} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ POST /orchestrator/notification/search + +- **Status**: PASS +- **Duration**: 169.025166ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"team":null,"app":null,"environment":null,"cluster":null,"pipeline":{"id":1,"name":"cd-3-pgxd","environmentName":"devtron-demo","appName":"pk-test","isVirtualEnvir... + +--- + +### ❌ POST /orchestrator/notification/v2 + +- **Status**: FAIL +- **Duration**: 143.0195ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'NotificationRequest.NotificationConfigRequest' Error:Field validation for 'NotificationConfigRequest' failed on the 'required' ta... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ POST /orchestrator/notification/channel + +- **Status**: FAIL +- **Duration**: 107.426792ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {} + +**Issues:** +- **RESPONSE_FORMAT_ERROR**: Response is not valid JSON: unexpected end of JSON input + +--- + +### ❌ DELETE /orchestrator/notification/channel + +- **Status**: FAIL +- **Duration**: 108.504292ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{ The channel you requested is not supported}]","userMessage":" The channel you requested is not supported"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/notification/channel + +- **Status**: PASS +- **Duration**: 111.193459ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"slackConfigs":[],"webhookConfigs":[],"sesConfigs":[{"userId":2,"teamId":0,"region":"ap-south-1","accessKey":"AKIAWEAVHFOOSNAORPHU","secretKey":"**********","fromEm... + +--- + +### ✅ GET /orchestrator/notification/channel/autocomplete/{type} + +- **Status**: PASS +- **Duration**: 106.45575ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[]} + +--- + +### ✅ GET /orchestrator/notification/channel/webhook/{id} + +- **Status**: PASS +- **Duration**: 107.74825ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"userId":0,"webhookUrl":"","configName":"","header":null,"payload":"","description":"","id":0}} + +--- + +### ✅ GET /orchestrator/notification/channel/slack/{id} + +- **Status**: PASS +- **Duration**: 125.669083ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"userId":0,"teamId":0,"webhookUrl":"","configName":"","description":"","id":0}} + +--- + +### ✅ GET /orchestrator/notification/channel/ses/{id} + +- **Status**: PASS +- **Duration**: 119.674333ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"userId":2,"teamId":0,"region":"ap-south-1","accessKey":"AKIAWEAVHFOOSNAORPHU","secretKey":"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","fromEmail":"watcher@devtron.i... + +--- + +### ❌ GET /orchestrator/notification/recipient + +- **Status**: FAIL +- **Duration**: 103.045458ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/notification/variables + +- **Status**: PASS +- **Duration**: 129.210916ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"devtronAppId":"{{devtronAppId}}","devtronAppName":"{{devtronAppName}}","devtronApprovedByEmail":"{{devtronApprovedByEmail}}","devtronBuildGitCommitHash":"{{devtron... + +--- + +### ❌ GET /orchestrator/notification + +- **Status**: FAIL +- **Duration**: 120.781583ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /orchestrator/notification + +- **Status**: FAIL +- **Duration**: 125.769709ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'NotificationRequest.NotificationConfigRequest' Error:Field validation for 'NotificationConfigRequest' failed on the 'required' ta... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ PUT /orchestrator/notification + +- **Status**: FAIL +- **Duration**: 120.040292ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'NotificationUpdateRequest.NotificationConfigRequest' Error:Field validation for 'NotificationConfigRequest' failed on the 'requir... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ DELETE /orchestrator/notification + +- **Status**: PASS +- **Duration**: 177.014667ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK"} + +--- + +### ✅ GET /orchestrator/notification/channel/smtp/{id} + +- **Status**: PASS +- **Duration**: 109.910917ms +- **Spec File**: ../../specs/notifications/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"id":0,"port":"","host":"","authType":"","authUser":"","authPassword":"","fromEmail":"","configName":"","description":"","ownerId":0,"default":false,"deleted":false... + +--- + +### ❌ PATCH /orchestrator/app/ci-pipeline/patch-source + +- **Status**: FAIL +- **Duration**: 107.972084ms +- **Spec File**: ../../specs/ci-pipeline/ci-pipeline-change-source.yaml +- **Response Code**: 500 +- **Error/Msg**: internal server error + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ PATCH /orchestrator/app/env/patch + +- **Status**: FAIL +- **Duration**: 106.570458ms +- **Spec File**: ../../specs/helm/deployment-chart-type.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","result":{"appId":0,"envId":0,"targetChartRefId":0}} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ POST /orchestrator/chart-repo/validate + +- **Status**: FAIL +- **Duration**: 108.843208ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","internalMessage":"Key: 'ChartRepoDto.Name' Error:Field validation for 'Name' failed on the 'required' tag\nKey: 'ChartRepoDto.AuthMode' Erro... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ POST /orchestrator/chart-repo/create + +- **Status**: FAIL +- **Duration**: 108.111667ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","internalMessage":"Key: 'ChartRepoDto.Name' Error:Field validation for 'Name' failed on the 'required' tag\nKey: 'ChartRepoDto.AuthMode' Erro... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ POST /orchestrator/chart-repo/sync-charts + +- **Status**: PASS +- **Duration**: 7.15860475s +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"status":"ok"}} + +--- + +### ❌ POST /orchestrator/chart-repo/update + +- **Status**: FAIL +- **Duration**: 108.224708ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","internalMessage":"Key: 'ChartRepoDto.Name' Error:Field validation for 'Name' failed on the 'required' tag\nKey: 'ChartRepoDto.AuthMode' Erro... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/app-store/chart-provider/list + +- **Status**: PASS +- **Duration**: 109.558958ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":"prakhar","name":"prakhar","active":true,"isEditable":true,"isOCIRegistry":true,"registryProvider":"docker-hub"},{"id":"1","name":"default-chartmuseum","activ... + +--- + +### ❌ POST /orchestrator/app-store/chart-provider/sync-chart + +- **Status**: FAIL +- **Duration**: 108.328375ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ChartProviderRequestDto.Id' Error:Field validation for 'Id' failed on the 'required' tag","userMessage":"Key: 'ChartProviderReque... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ POST /orchestrator/chart-group/ + +- **Status**: FAIL +- **Duration**: 118.224ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ChartGroupBean.Name' Error:Field validation for 'Name' failed on the 'name-component' tag","userMessage":"Key: 'ChartGroupBean.Na... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ PUT /orchestrator/chart-group/ + +- **Status**: FAIL +- **Duration**: 108.558833ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ChartGroupBean.Name' Error:Field validation for 'Name' failed on the 'name-component' tag","userMessage":"Key: 'ChartGroupBean.Na... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/chart-group/list + +- **Status**: PASS +- **Duration**: 106.122125ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":null} + +--- + +### ✅ GET /orchestrator/chart-repo/{id} + +- **Status**: PASS +- **Duration**: 116.164959ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"name":"default-chartmuseum","url":"http://devtron-chartmuseum.devtroncd:8080/","authMode":"ANONYMOUS","active":true,"default":true,"allow_insecure_connectio... + +--- + +### ❌ POST /orchestrator/app-store/chart-provider/update + +- **Status**: FAIL +- **Duration**: 105.508709ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ChartProviderRequestDto.Id' Error:Field validation for 'Id' failed on the 'required' tag","userMessage":"Key: 'ChartProviderReque... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ PUT /orchestrator/chart-group/entries + +- **Status**: FAIL +- **Duration**: 105.53ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ DELETE /orchestrator/chart-group/{id} + +- **Status**: FAIL +- **Duration**: 103.77225ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/chart-repo/list + +- **Status**: PASS +- **Duration**: 111.011625ms +- **Spec File**: ../../specs/helm/provider.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"name":"default-chartmuseum","url":"http://devtron-chartmuseum.devtroncd:8080/","authMode":"ANONYMOUS","active":true,"default":true,"allow_insecure_connecti... + +--- + +### ✅ GET /orchestrator/api-token + +- **Status**: PASS +- **Duration**: 109.104708ms +- **Spec File**: ../../specs/openapiClient/api/apiToken_api-openapi.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"description":"some description","expireAtInMs":12344546,"id":2,"name":"some-name","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6IkFQSS1UT0tFTjpzb21lLW... + +--- + +### ❌ POST /orchestrator/api-token + +- **Status**: FAIL +- **Duration**: 109.536917ms +- **Spec File**: ../../specs/openapiClient/api/apiToken_api-openapi.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'CreateApiTokenRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag","userMessage":"Key: 'CreateApiTokenRe... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/api-token/webhook + +- **Status**: PASS +- **Duration**: 109.142292ms +- **Spec File**: ../../specs/openapiClient/api/apiToken_api-openapi.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[]} + +--- + +### ❌ DELETE /orchestrator/api-token/{id} + +- **Status**: FAIL +- **Duration**: 107.791666ms +- **Spec File**: ../../specs/openapiClient/api/apiToken_api-openapi.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{api-token corresponds to apiTokenId '1' is not found}]","userMessage":"api-token corresponds to apiTokenId '1'... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ PUT /orchestrator/api-token/{id} + +- **Status**: FAIL +- **Duration**: 110.273667ms +- **Spec File**: ../../specs/openapiClient/api/apiToken_api-openapi.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'UpdateApiTokenRequest.Description' Error:Field validation for 'Description' failed on the 'required' tag","userMessage":"Key: 'Up... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/user/role/group/detailed/get + +- **Status**: PASS +- **Duration**: 120.157291ms +- **Spec File**: ../../specs/security/group-policy.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":2,"roleFilters":[],"superAdmin":false,"canManageAllAccess":false,"hasAccessManagerPermission":false}]} + +--- + +### ❌ GET /orchestrator/user/role/group/search + +- **Status**: FAIL +- **Duration**: 111.182083ms +- **Spec File**: ../../specs/security/group-policy.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"search\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"search\": invalid syntax"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/user/role/group/v2 + +- **Status**: PASS +- **Duration**: 127.43525ms +- **Spec File**: ../../specs/security/group-policy.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"roleGroups":[{"id":2,"roleFilters":[],"superAdmin":false,"canManageAllAccess":false,"hasAccessManagerPermission":false}],"totalCount":1}} + +--- + +### ❌ POST /orchestrator/user/role/group/v2 + +- **Status**: FAIL +- **Duration**: 113.402542ms +- **Spec File**: ../../specs/security/group-policy.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{role group already exist}]","userMessage":"role group already exist"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ PUT /orchestrator/user/role/group/v2 + +- **Status**: FAIL +- **Duration**: 192.148875ms +- **Spec File**: ../../specs/security/group-policy.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":""}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ DELETE /orchestrator/user/role/group/{id} + +- **Status**: FAIL +- **Duration**: 110.706666ms +- **Spec File**: ../../specs/security/group-policy.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":""}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ GET /orchestrator/user/role/group/{id} + +- **Status**: FAIL +- **Duration**: 112.249625ms +- **Spec File**: ../../specs/security/group-policy.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"Failed to get by id"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ PUT /orchestrator/user/role/group + +- **Status**: FAIL +- **Duration**: 109.076167ms +- **Spec File**: ../../specs/security/group-policy.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":""}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/user/role/group + +- **Status**: PASS +- **Duration**: 109.09175ms +- **Spec File**: ../../specs/security/group-policy.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":2,"roleFilters":[],"superAdmin":false,"canManageAllAccess":false,"hasAccessManagerPermission":false}]} + +--- + +### ❌ POST /orchestrator/user/role/group + +- **Status**: FAIL +- **Duration**: 160.916ms +- **Spec File**: ../../specs/security/group-policy.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{role group already exist}]","userMessage":"role group already exist"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ DELETE /orchestrator/user/role/group/bulk + +- **Status**: FAIL +- **Duration**: 110.531667ms +- **Spec File**: ../../specs/security/group-policy.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{ERROR #42601 syntax error at or near \")\"}]","userMessage":"ERROR #42601 syntax error at or near \")\""}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ GET /{appId}/ci-pipeline/{pipelineId}/workflow/{workflowId} + +- **Status**: FAIL +- **Duration**: 103.118625ms +- **Spec File**: ../../specs/ci-pipeline/ci-pipeline-build-spec.yaml +- **Response Code**: 404 +- **Error/Msg**: +404 Not Found + +

404 Not Found

+
nginx
+ + + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 +- **RESPONSE_FORMAT_ERROR**: Response is not valid JSON: invalid character '<' looking for beginning of value + +--- + +### ❌ POST /ci-pipeline/trigger + +- **Status**: FAIL +- **Duration**: 102.16925ms +- **Spec File**: ../../specs/ci-pipeline/ci-pipeline-build-spec.yaml +- **Response Code**: 404 +- **Error/Msg**: +404 Not Found + +

404 Not Found

+
nginx
+ + + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ GET /orchestrator/app/commit-info/{ciPipelineMaterialId}/{gitHash} + +- **Status**: FAIL +- **Duration**: 109.109291ms +- **Spec File**: ../../specs/ci-pipeline/ci-pipeline-build-spec.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ GET /orchestrator/deployment/pipeline/history + +- **Status**: FAIL +- **Duration**: 110.7765ms +- **Spec File**: ../../specs/deployment/pipeline.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /orchestrator/deployment/pipeline/rollback + +- **Status**: FAIL +- **Duration**: 105.640292ms +- **Spec File**: ../../specs/deployment/pipeline.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /orchestrator/deployment/pipeline/trigger + +- **Status**: FAIL +- **Duration**: 103.362625ms +- **Spec File**: ../../specs/deployment/pipeline.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /orchestrator/deployment/pipeline/configure + +- **Status**: FAIL +- **Duration**: 106.426125ms +- **Spec File**: ../../specs/deployment/pipeline.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ GET /orchestrator/flux-application + +- **Status**: FAIL +- **Duration**: 106.788833ms +- **Spec File**: ../../specs/gitops/fluxcd.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{error in getting cluster ids}]","userMessage":"error in getting cluster ids"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ GET /orchestrator/flux-application/app + +- **Status**: FAIL +- **Duration**: 106.9545ms +- **Spec File**: ../../specs/gitops/fluxcd.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /create + +- **Status**: FAIL +- **Duration**: 344.150333ms +- **Spec File**: ../../specs/helm/repo-validation.yaml +- **Response Code**: 404 +- **Error/Msg**: +404 Not Found + +

404 Not Found

+
nginx
+ + + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /orchestrator/validate + +- **Status**: FAIL +- **Duration**: 105.761834ms +- **Spec File**: ../../specs/helm/repo-validation.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /update + +- **Status**: FAIL +- **Duration**: 103.281125ms +- **Spec File**: ../../specs/helm/repo-validation.yaml +- **Response Code**: 404 +- **Error/Msg**: +404 Not Found + +

404 Not Found

+
nginx
+ + + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/app/history/deployed-configuration/{appId}/{pipelineId}/{wfrId} + +- **Status**: PASS +- **Duration**: 112.768834ms +- **Spec File**: ../../specs/audit/definitions.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":8,"name":"DEPLOYMENT_TEMPLATE"},{"id":3,"name":"PIPELINE_STRATEGY"}]} + +--- + +### ❌ GET /orchestrator/app/history/deployed-component/detail/{appId}/{pipelineId}/{id} + +- **Status**: FAIL +- **Duration**: 107.579042ms +- **Spec File**: ../../specs/audit/definitions.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","result":"invalid historyComponent"} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ GET /orchestrator/app/history/deployed-component/list/{appId}/{pipelineId} + +- **Status**: FAIL +- **Duration**: 110.888833ms +- **Spec File**: ../../specs/audit/definitions.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","result":"invalid historyComponent"} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/deployment/template/fetch + +- **Status**: PASS +- **Duration**: 215.775292ms +- **Spec File**: ../../specs/deployment/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":10,"name":"Rollout Deployment","chartDescription":"This chart deploys an advanced version of deployment that supports Blue/Green and Canary deployments. For f... + +--- + +### ✅ PUT /orchestrator/deployment/template/upload + +- **Status**: PASS +- **Duration**: 141.399542ms +- **Spec File**: ../../specs/deployment/core.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":"Processed successfully"} + +--- + +### ❌ POST /orchestrator/deployment/template/validate + +- **Status**: FAIL +- **Duration**: 108.184292ms +- **Spec File**: ../../specs/deployment/core.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{request Content-Type isn't multipart/form-data}]","userMessage":"request Content-Type isn't multipart/form-data"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ GET /orchestrator/app/history/deployed-configuration/all/latest/{appId}/{pipelineId} + +- **Status**: FAIL +- **Duration**: 107.507875ms +- **Spec File**: ../../specs/deployment/rollback.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"latest\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"latest\": invalid syntax"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/app/history/deployed-configuration/all/{appId}/{pipelineId}/{wfrId} + +- **Status**: PASS +- **Duration**: 172.705959ms +- **Spec File**: ../../specs/deployment/rollback.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"deploymentTemplate":{"templateName":"Deployment","templateVersion":"4.21.0","isAppMetricsEnabled":false,"codeEditorValue":{"displayName":"values.yaml","value":"{\"... + +--- + +### ❌ GET /orchestrator/app/template/default/{appId}/{chartRefId} + +- **Status**: FAIL +- **Duration**: 108.519ms +- **Spec File**: ../../specs/environment/templates.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ DELETE /orchestrator/k8s/resources/ephemeralContainers + +- **Status**: FAIL +- **Duration**: 104.236917ms +- **Spec File**: ../../specs/kubernetes/ephemeral-containers.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /orchestrator/k8s/resources/ephemeralContainers + +- **Status**: FAIL +- **Duration**: 111.923583ms +- **Spec File**: ../../specs/kubernetes/ephemeral-containers.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ PUT /orchestrator/application/rollback + +- **Status**: FAIL +- **Duration**: 108.570458ms +- **Spec File**: ../../specs/openapiClient/api/openapi.yaml +- **Response Code**: 500 +- **Error/Msg**: internal server error + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ POST /orchestrator/application/template-chart + +- **Status**: FAIL +- **Duration**: 105.56825ms +- **Spec File**: ../../specs/openapiClient/api/openapi.yaml +- **Response Code**: 500 +- **Error/Msg**: internal server error + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ❌ GET /orchestrator/app/deployment-status/timeline/{appId}/{envId} + +- **Status**: FAIL +- **Duration**: 161.653375ms +- **Spec File**: ../../specs/deployment/timeline.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ POST /orchestrator/app/ci-pipeline/patch + +- **Status**: FAIL +- **Duration**: 108.342041ms +- **Spec File**: ../../specs/infrastructure/docker-build.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/app/ci-pipeline/{appId} + +- **Status**: PASS +- **Duration**: 111.224292ms +- **Spec File**: ../../specs/infrastructure/docker-build.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"appId":1,"dockerRegistry":"quay","dockerRepository":"devtron/test","ciBuildConfig":{"id":1,"gitMaterialId":1,"buildContextGitMaterialId":1,"useRootBuildCont... + +--- + +### ✅ GET /orchestrator/app/wf/all/component-names/{appId} + +- **Status**: PASS +- **Duration**: 109.274375ms +- **Spec File**: ../../specs/infrastructure/docker-build.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"workflows":[{"id":1,"name":"wf-1-lcu5","ciPipelineId":0,"ciPipelineName":"","cdPipelines":null},{"id":2,"name":"wf-1-4rww","ciPipelineId":0,"ciPipelineName":"","cd... + +--- + +### ❌ POST /orchestrator/user + +- **Status**: FAIL +- **Duration**: 109.060167ms +- **Spec File**: ../../specs/security/user-management.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'UserInfo.EmailId' Error:Field validation for 'EmailId' failed on the 'required' tag","userMessage":"Key: 'UserInfo.EmailId' Error... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ PUT /orchestrator/user + +- **Status**: FAIL +- **Duration**: 107.529458ms +- **Spec File**: ../../specs/security/user-management.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'UserInfo.EmailId' Error:Field validation for 'EmailId' failed on the 'required' tag","userMessage":"Key: 'UserInfo.EmailId' Error... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ DELETE /orchestrator/user/bulk + +- **Status**: FAIL +- **Duration**: 109.0525ms +- **Spec File**: ../../specs/security/user-management.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{ERROR #42601 syntax error at or near \")\"}]","userMessage":"ERROR #42601 syntax error at or near \")\""}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ✅ GET /orchestrator/user/v2 + +- **Status**: PASS +- **Duration**: 109.714292ms +- **Spec File**: ../../specs/security/user-management.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"users":[{"id":2,"email_id":"admin","roleFilters":[],"groups":[],"superAdmin":false,"userRoleGroups":[],"lastLoginTime":"2025-08-05T16:40:13.674161Z","timeoutWindow... + +--- + +### ❌ DELETE /orchestrator/user/{id} + +- **Status**: FAIL +- **Duration**: 108.809292ms +- **Spec File**: ../../specs/security/user-management.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","userMessage":"cannot delete system or admin user"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ✅ GET /orchestrator/user/{id} + +- **Status**: PASS +- **Duration**: 127.785542ms +- **Spec File**: ../../specs/security/user-management.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"email_id":"system","roleFilters":[],"groups":[],"superAdmin":false,"userRoleGroups":[],"lastLoginTime":"0001-01-01T00:00:00Z","timeoutWindowExpression":"000... + +--- + +### ❌ GET /orchestrator/env/namespace/autocomplete + +- **Status**: FAIL +- **Duration**: 107.054334ms +- **Spec File**: ../../specs/environment/core.yaml +- **Response Code**: 500 +- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{ERROR #42601 syntax error at or near \")\"}]","userMessage":"ERROR #42601 syntax error at or near \")\""}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 + +--- + +### ✅ GET /orchestrator/gitops/configured + +- **Status**: PASS +- **Duration**: 108.961292ms +- **Spec File**: ../../specs/gitops/validation.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"allowCustomRepository":false,"authMode":"PASSWORD","exists":true,"provider":"GITHUB"}} + +--- + +### ❌ POST /orchestrator/validate + +- **Status**: FAIL +- **Duration**: 110.406625ms +- **Spec File**: ../../specs/gitops/validation.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ✅ GET /orchestrator/gitops/config + +- **Status**: PASS +- **Duration**: 108.276792ms +- **Spec File**: ../../specs/gitops/validation.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"provider":"GITHUB","username":"systemsdt","token":"","gitLabGroupId":"","gitHubOrgId":"stage-gitops","host":"https://github.com/","active":true,"azureProje... + +--- + +### ❌ POST /orchestrator/gitops/config + +- **Status**: FAIL +- **Duration**: 109.114625ms +- **Spec File**: ../../specs/gitops/validation.yaml +- **Response Code**: 400 +- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{value is unsupported Key: 'GitOpsConfigDto.Provider' Error:Field validation for 'Provider' failed on the 'oneof' tag}]... + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 + +--- + +### ❌ PUT /orchestrator/gitops/config + +- **Status**: FAIL +- **Duration**: 107.554459ms +- **Spec File**: ../../specs/gitops/validation.yaml +- **Response Code**: 404 +- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 + +--- + +### ❌ GET /orchestrator/gitops/config-by-provider + +- **Status**: FAIL +- **Duration**: 104.3385ms +- **Spec File**: ../../specs/gitops/validation.yaml +- **Response Code**: 404 +- **Error/Msg**: 404 page not found + + +**Issues:** +- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 +- **RESPONSE_FORMAT_ERROR**: Response is not valid JSON: invalid character 'p' after top-level value + +--- + +### ✅ GET /orchestrator/gitops/config/{id} + +- **Status**: PASS +- **Duration**: 108.533292ms +- **Spec File**: ../../specs/gitops/validation.yaml +- **Response Code**: 200 +- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"provider":"GITHUB","username":"systemsdt","token":"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","gitLabGro... + +--- + From 3a3db67d89616b151dc89b992c6b56d5bc4f7676 Mon Sep 17 00:00:00 2001 From: prakhar katiyar Date: Wed, 6 Aug 2025 01:19:38 +0530 Subject: [PATCH 9/9] Delete live-server-validation-report.md removed report --- .../reports/live-server-validation-report.md | 2057 ----------------- 1 file changed, 2057 deletions(-) delete mode 100644 tests/api-spec-validation/reports/live-server-validation-report.md diff --git a/tests/api-spec-validation/reports/live-server-validation-report.md b/tests/api-spec-validation/reports/live-server-validation-report.md deleted file mode 100644 index 82d2975328..0000000000 --- a/tests/api-spec-validation/reports/live-server-validation-report.md +++ /dev/null @@ -1,2057 +0,0 @@ -# API Spec Validation Report - -Generated: 2025-08-05T22:10:14+05:30 - -## Summary - -- Total Endpoints: 165 -- Passed: 59 -- Failed: 106 -- Warnings: 0 -- Success Rate: 35.76% - -## Detailed Results - -### ❌ GET /orchestrator/app/helm/meta/info/{appId} - -- **Status**: FAIL -- **Duration**: 435.672417ms -- **Spec File**: ../../specs/application/labels.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"sample_string\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"sample_strin... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ✅ GET /orchestrator/app/labels/list - -- **Status**: PASS -- **Duration**: 111.297791ms -- **Spec File**: ../../specs/application/labels.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[]} - ---- - -### ✅ GET /orchestrator/app/meta/info/{appId} - -- **Status**: PASS -- **Duration**: 117.284875ms -- **Spec File**: ../../specs/application/labels.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"appId":1,"appName":"helm-sanity-application","description":"","projectId":2,"projectName":"shared-devtron-demo1","createdBy":"admin","createdOn":"2025-07-15T07:30:... - ---- - -### ❌ POST /orchestrator/gitops/validate - -- **Status**: FAIL -- **Duration**: 110.391083ms -- **Spec File**: ../../specs/gitops/core.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/gitops/config - -- **Status**: PASS -- **Duration**: 112.942375ms -- **Spec File**: ../../specs/gitops/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"provider":"GITHUB","username":"systemsdt","token":"","gitLabGroupId":"","gitHubOrgId":"stage-gitops","host":"https://github.com/","active":true,"azureProje... - ---- - -### ❌ POST /orchestrator/gitops/config - -- **Status**: FAIL -- **Duration**: 107.511958ms -- **Spec File**: ../../specs/gitops/core.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{value is unsupported Key: 'GitOpsConfigDto.Provider' Error:Field validation for 'Provider' failed on the 'oneof' tag}]... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ PUT /orchestrator/gitops/config - -- **Status**: FAIL -- **Duration**: 105.382917ms -- **Spec File**: ../../specs/gitops/core.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ GET /orchestrator/gitops/config-by-provider - -- **Status**: FAIL -- **Duration**: 183.867208ms -- **Spec File**: ../../specs/gitops/core.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/gitops/config/{id} - -- **Status**: PASS -- **Duration**: 109.077583ms -- **Spec File**: ../../specs/gitops/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"provider":"GITHUB","username":"systemsdt","token":"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","gitLabGro... - ---- - -### ✅ GET /orchestrator/gitops/configured - -- **Status**: PASS -- **Duration**: 110.496458ms -- **Spec File**: ../../specs/gitops/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"allowCustomRepository":false,"authMode":"PASSWORD","exists":true,"provider":"GITHUB"}} - ---- - -### ❌ POST /orchestrator/batch/v1beta1/hibernate - -- **Status**: FAIL -- **Duration**: 108.301041ms -- **Spec File**: ../../specs/jobs/bulk-actions.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{ERROR #42601 syntax error at or near \")\"}]","userMessage":"ERROR #42601 syntax error at or near \")\""}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ POST /v1beta1/deploy - -- **Status**: FAIL -- **Duration**: 119.661834ms -- **Spec File**: ../../specs/jobs/bulk-actions.yaml -- **Response Code**: 404 -- **Error/Msg**: -404 Not Found - -

404 Not Found

-
nginx
- - - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /v1beta1/unhibernate - -- **Status**: FAIL -- **Duration**: 104.9255ms -- **Spec File**: ../../specs/jobs/bulk-actions.yaml -- **Response Code**: 404 -- **Error/Msg**: -404 Not Found - -

404 Not Found

-
nginx
- - - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ PUT /orchestrator/cluster - -- **Status**: FAIL -- **Duration**: 109.297583ms -- **Spec File**: ../../specs/kubernetes/cluster.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ClusterBean.ClusterName' Error:Field validation for 'ClusterName' failed on the 'required' tag","userMessage":"Key: 'ClusterBean.... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/cluster - -- **Status**: PASS -- **Duration**: 108.879583ms -- **Spec File**: ../../specs/kubernetes/cluster.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":6,"cluster_name":"abcd","description":"","active":true,"config":{"bearer_token":""},"prometheusAuth":{"isAnonymous":false},"defaultClusterComponent":[],"agent... - ---- - -### ✅ GET /orchestrator/cluster/auth-list - -- **Status**: PASS -- **Duration**: 109.895125ms -- **Spec File**: ../../specs/kubernetes/cluster.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":6,"cluster_name":"abcd","description":"","active":false,"defaultClusterComponent":null,"agentInstallationStage":0,"k8sVersion":"","insecureSkipTlsVerify":fals... - ---- - -### ❌ POST /orchestrator/webhook/git/{gitHostId} - -- **Status**: FAIL -- **Duration**: 109.933625ms -- **Spec File**: ../../specs/notifications/webhooks.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /orchestrator/webhook/git/{gitHostId}/{secret} - -- **Status**: FAIL -- **Duration**: 106.638042ms -- **Spec File**: ../../specs/notifications/webhooks.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /orchestrator/webhook/ci/workflow - -- **Status**: FAIL -- **Duration**: 110.802834ms -- **Spec File**: ../../specs/notifications/webhooks.yaml -- **Response Code**: 500 -- **Error/Msg**: internal server error - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ POST /orchestrator/webhook/ext-ci/{externalCiId} - -- **Status**: FAIL -- **Duration**: 106.369958ms -- **Spec File**: ../../specs/notifications/webhooks.yaml -- **Response Code**: 401 -- **Error/Msg**: {"code":401,"status":"Unauthorized","errors":[{"code":"6005","internalMessage":"no token provided"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 401 - ---- - -### ❌ POST /orchestrator/webhook/git - -- **Status**: FAIL -- **Duration**: 114.307416ms -- **Spec File**: ../../specs/notifications/webhooks.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /orchestrator/plugin/global/list/detail/v2 - -- **Status**: FAIL -- **Duration**: 163.790334ms -- **Spec File**: ../../specs/plugins/global.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","internalMessage":"Empty values for both pluginVersionIds and parentPluginIds. Please provide at least one of them","userMessage":"Empty valu... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/plugin/global/list/tags - -- **Status**: PASS -- **Duration**: 172.735041ms -- **Spec File**: ../../specs/plugins/global.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"tagNames":["Load testing","Kubernetes","gcs","Github","Code Review","Code quality","DevSecOps","Image source","cloud","AWS EKS","Security","CI task","Google Kubern... - ---- - -### ❌ POST /orchestrator/plugin/global/create - -- **Status**: FAIL -- **Duration**: 143.656625ms -- **Spec File**: ../../specs/plugins/global.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","internalMessage":"no step data provided to save, please provide a plugin step to proceed further","userMessage":"no step data provided to sa... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/plugin/global/detail/all - -- **Status**: PASS -- **Duration**: 756.330042ms -- **Spec File**: ../../specs/plugins/global.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"name":"K6 Load testing","description":"K6 is an open-source tool and cloud service that makes load testing easy for developers and QA engineers.","type":"P... - ---- - -### ❌ GET /orchestrator/plugin/global/list/global-variable - -- **Status**: FAIL -- **Duration**: 106.387625ms -- **Spec File**: ../../specs/plugins/global.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"\": invalid syntax}]","userMessage":"invalid appId"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/plugin/global/list/v2 - -- **Status**: PASS -- **Duration**: 122.855208ms -- **Spec File**: ../../specs/plugins/global.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"parentPlugins":[{"id":4,"name":"AWS ECR Retag","pluginIdentifier":"aws-retag","description":"AWS ECR Retag plugin that enables retagging of container images within... - ---- - -### ✅ GET /orchestrator/plugin/global/list/v2/min - -- **Status**: PASS -- **Duration**: 105.0705ms -- **Spec File**: ../../specs/plugins/global.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[]} - ---- - -### ✅ PUT /orchestrator/plugin/global/migrate - -- **Status**: PASS -- **Duration**: 108.638875ms -- **Spec File**: ../../specs/plugins/global.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK"} - ---- - -### ✅ GET /orchestrator/plugin/global/detail/{pluginId} - -- **Status**: PASS -- **Duration**: 116.877292ms -- **Spec File**: ../../specs/plugins/global.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"name":"K6 Load testing","description":"K6 is an open-source tool and cloud service that makes load testing easy for developers and QA engineers.","type":"PR... - ---- - -### ❌ POST /orchestrator/user/resource/options/{kind}/{version} - -- **Status**: FAIL -- **Duration**: 101.167125ms -- **Spec File**: ../../specs/userResource/userResource.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/app-store/installed-app - -- **Status**: PASS -- **Duration**: 108.455542ms -- **Spec File**: ../../specs/helm/charts.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"clusterIds":null,"applicationType":"DEVTRON-CHART-STORE","helmApps":[{"lastDeployedAt":"2025-07-15T10:48:16.504431Z","appName":"pk-chart-gitops","appId":"2","chart... - ---- - -### ❌ GET /orchestrator/app-store/installed-app/notes - -- **Status**: FAIL -- **Duration**: 103.081792ms -- **Spec File**: ../../specs/helm/charts.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/chartref/autocomplete/{appId} - -- **Status**: PASS -- **Duration**: 110.60575ms -- **Spec File**: ../../specs/helm/dynamic-charts.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"chartRefs":[{"id":10,"version":"3.9.0","name":"Rollout Deployment","description":"","userUploaded":false,"isAppMetricsSupported":true},{"id":11,"version":"3.10.0",... - ---- - -### ✅ GET /orchestrator/app/history/deployed-configuration/{appId}/{pipelineId}/{wfrId} - -- **Status**: PASS -- **Duration**: 110.757ms -- **Spec File**: ../../specs/audit/api-changes.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":8,"name":"DEPLOYMENT_TEMPLATE"},{"id":3,"name":"PIPELINE_STRATEGY"}]} - ---- - -### ❌ GET /orchestrator/app/history/deployed-component/detail/{appId}/{pipelineId}/{id} - -- **Status**: FAIL -- **Duration**: 107.952708ms -- **Spec File**: ../../specs/audit/api-changes.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","result":"invalid historyComponent"} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ GET /orchestrator/app/history/deployed-component/list/{appId}/{pipelineId} - -- **Status**: FAIL -- **Duration**: 107.582625ms -- **Spec File**: ../../specs/audit/api-changes.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","result":"invalid historyComponent"} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/version - -- **Status**: PASS -- **Duration**: 105.365875ms -- **Spec File**: ../../specs/common/version.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"result":{"gitCommit":"a73ff9ef","buildTime":"2025-07-16T13:44:58Z","serverMode":"FULL"}} - ---- - -### ✅ GET /orchestrator/external-links/tools - -- **Status**: PASS -- **Duration**: 108.95ms -- **Spec File**: ../../specs/external-links/external-links-specs.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"name":"Grafana","icon":"","category":2},{"id":2,"name":"Kibana","icon":"","category":2},{"id":3,"name":"Newrelic","icon":"","category":2},{"id":4,"name":"C... - ---- - -### ❌ DELETE /orchestrator/external-links - -- **Status**: FAIL -- **Duration**: 105.058209ms -- **Spec File**: ../../specs/external-links/external-links-specs.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 -- **RESPONSE_FORMAT_ERROR**: Response is not valid JSON: invalid character 'p' after top-level value - ---- - -### ✅ GET /orchestrator/external-links - -- **Status**: PASS -- **Duration**: 108.622542ms -- **Spec File**: ../../specs/external-links/external-links-specs.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[]} - ---- - -### ❌ POST /orchestrator/external-links - -- **Status**: FAIL -- **Duration**: 108.2415ms -- **Spec File**: ../../specs/external-links/external-links-specs.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{json: cannot unmarshal object into Go value of type []*externalLink.ExternalLinkDto}]","userMessage":"json: cannot unmar... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ PUT /orchestrator/external-links - -- **Status**: FAIL -- **Duration**: 107.402833ms -- **Spec File**: ../../specs/external-links/external-links-specs.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ GET /orchestrator/git/host/{id} - -- **Status**: FAIL -- **Duration**: 104.597875ms -- **Spec File**: ../../specs/gitops/submodules.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"{id}\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"{id}\": invalid synta... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ GET /orchestrator/git/host/{id}/event - -- **Status**: FAIL -- **Duration**: 106.339792ms -- **Spec File**: ../../specs/gitops/submodules.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"{id}\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"{id}\": invalid synta... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ✅ GET /orchestrator/git/host - -- **Status**: PASS -- **Duration**: 107.316ms -- **Spec File**: ../../specs/gitops/submodules.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"name":"Github","active":true,"webhookUrl":"","webhookSecret":"","eventTypeHeader":"","secretHeader":"","secretValidator":""},{"id":2,"name":"Bitbucket Clou... - ---- - -### ❌ POST /orchestrator/git/host - -- **Status**: FAIL -- **Duration**: 108.852792ms -- **Spec File**: ../../specs/gitops/submodules.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'GitHostRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag","userMessage":"Key: 'GitHostRequest.Name' Er... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ GET /orchestrator/git/host/event/{eventId} - -- **Status**: FAIL -- **Duration**: 115.740541ms -- **Spec File**: ../../specs/gitops/submodules.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"{eventId}\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"{eventId}\": inv... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ GET /orchestrator/git/host/webhook-meta-config/{gitProviderId} - -- **Status**: FAIL -- **Duration**: 388.766667ms -- **Spec File**: ../../specs/gitops/submodules.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{ERROR #22P02 invalid input syntax for type integer: \"{gitProviderId}\"}]","userMessage":"ERROR #22P02 invalid... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ✅ GET /orchestrator/module - -- **Status**: PASS -- **Duration**: 537.444041ms -- **Spec File**: ../../specs/modularisation/v1.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"name":"security.trivy","status":"installed","moduleResourcesStatus":null,"enabled":true,"moduleType":"security"},{"name":"security.clair","status":"installed","mo... - ---- - -### ❌ POST /orchestrator/module - -- **Status**: FAIL -- **Duration**: 103.11125ms -- **Spec File**: ../../specs/modularisation/v1.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/server - -- **Status**: PASS -- **Duration**: 107.528ms -- **Spec File**: ../../specs/modularisation/v1.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"status":"unknown","releaseName":"devtron","installationType":"enterprise"}} - ---- - -### ❌ POST /orchestrator/server - -- **Status**: FAIL -- **Duration**: 168.68225ms -- **Spec File**: ../../specs/modularisation/v1.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ServerActionRequestDto.Action' Error:Field validation for 'Action' failed on the 'oneof' tag","userMessage":"Key: 'ServerActionRe... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ POST /orchestrator/config/environment/cm - -- **Status**: FAIL -- **Duration**: 107.686584ms -- **Spec File**: ../../specs/plugins/config-maps.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{invalid request multiple config found for add or update}]","userMessage":"invalid request multiple config foun... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ GET /orchestrator/config/environment/cm/edit/{appId}/{envId}/{id} - -- **Status**: FAIL -- **Duration**: 102.67825ms -- **Spec File**: ../../specs/plugins/config-maps.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/config/environment/cm/{appId}/{envId} - -- **Status**: PASS -- **Duration**: 112.777417ms -- **Spec File**: ../../specs/plugins/config-maps.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"id":0,"appId":1,"environmentId":1,"configData":[],"isDeletable":false,"isExpressEdit":false}} - ---- - -### ❌ DELETE /orchestrator/config/environment/cm/{appId}/{envId}/{id} - -- **Status**: FAIL -- **Duration**: 105.252292ms -- **Spec File**: ../../specs/plugins/config-maps.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /orchestrator/config/global/cm - -- **Status**: FAIL -- **Duration**: 108.859ms -- **Spec File**: ../../specs/plugins/config-maps.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{invalid request multiple config found for add or update}]","userMessage":"invalid request multiple config foun... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ POST /orchestrator/config/bulk/patch - -- **Status**: FAIL -- **Duration**: 109.450916ms -- **Spec File**: ../../specs/plugins/config-maps.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{invalid request no payload found for sync}]","userMessage":"invalid request no payload found for sync"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ GET /orchestrator/config/global/cm/edit/{appId}/{id} - -- **Status**: FAIL -- **Duration**: 101.235417ms -- **Spec File**: ../../specs/plugins/config-maps.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/config/global/cm/{appId} - -- **Status**: PASS -- **Duration**: 107.309708ms -- **Spec File**: ../../specs/plugins/config-maps.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"id":0,"appId":1,"configData":[],"isDeletable":false,"isExpressEdit":false}} - ---- - -### ❌ DELETE /orchestrator/config/global/cm/{appId}/{id} - -- **Status**: FAIL -- **Duration**: 102.428916ms -- **Spec File**: ../../specs/plugins/config-maps.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/app-store/discover/application/chartInfo/{appStoreApplicationVersionId} - -- **Status**: PASS -- **Duration**: 520.679166ms -- **Spec File**: ../../specs/app-store.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"appStoreApplicationVersionId":1,"readme":"# cluster-autoscaler\n\nScales Kubernetes worker nodes within autoscaling groups.\n\n## TL;DR\n\n```console\n$ helm repo ... - ---- - -### ✅ GET /orchestrator/app-store/discover/application/{appStoreId}/version/autocomplete - -- **Status**: PASS -- **Duration**: 132.640375ms -- **Spec File**: ../../specs/app-store.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"version":"9.49.0","id":5507},{"version":"9.48.0","id":1},{"version":"9.47.0","id":2},{"version":"9.46.6","id":3},{"version":"9.46.5","id":4},{"version":"9.46.4","... - ---- - -### ✅ GET /orchestrator/app-store/discover/application/{id} - -- **Status**: PASS -- **Duration**: 169.7765ms -- **Spec File**: ../../specs/app-store.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"version":"9.48.0","appVersion":"1.33.0","created":"2025-07-11T21:16:00.149315Z","deprecated":false,"description":"Scales Kubernetes worker nodes within auto... - ---- - -### ❌ GET /orchestrator/app-store/discover/search - -- **Status**: FAIL -- **Duration**: 124.785ms -- **Spec File**: ../../specs/app-store.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/app-store/discover - -- **Status**: PASS -- **Duration**: 1.021184s -- **Spec File**: ../../specs/app-store.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":65,"appStoreApplicationVersionId":4028,"name":"ai-agent","chart_repo_id":2,"docker_artifact_store_id":"","chart_name":"devtron","icon":"","active":true,"chart... - ---- - -### ❌ GET /orchestrator/app/ci-pipeline/{ciPipelineId}/linked-ci/downstream/cd - -- **Status**: FAIL -- **Duration**: 107.782667ms -- **Spec File**: ../../specs/ci-pipeline/ciPipelineDownstream/downstream-linked-ci-view-spec.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{invalid CiPipelineId 1}]","userMessage":"invalid CiPipelineId 1"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ GET /orchestrator/app/ci-pipeline/{ciPipelineId}/linked-ci/downstream/env - -- **Status**: FAIL -- **Duration**: 105.740584ms -- **Spec File**: ../../specs/ci-pipeline/ciPipelineDownstream/downstream-linked-ci-view-spec.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{invalid CiPipelineId 1}]","userMessage":"invalid CiPipelineId 1"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ POST /orchestrator/app/cd-pipeline/patch/deployment - -- **Status**: FAIL -- **Duration**: 109.075375ms -- **Spec File**: ../../specs/deployment/app-type-change.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'DeploymentAppTypeChangeRequest.EnvId' Error:Field validation for 'EnvId' failed on the 'required' tag","userMessage":"Key: 'Deplo... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ POST /orchestrtor/batch/v1beta1/cd-pipeline - -- **Status**: FAIL -- **Duration**: 103.406625ms -- **Spec File**: ../../specs/environment/bulk-delete.yaml -- **Response Code**: 404 -- **Error/Msg**: -404 Not Found - -

404 Not Found

-
nginx
- - - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ POST /orchestrator/job/list - -- **Status**: PASS -- **Duration**: 473.5475ms -- **Spec File**: ../../specs/jobs/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"jobContainers":[],"jobCount":0}} - ---- - -### ❌ POST /orchestrator/job - -- **Status**: FAIL -- **Duration**: 108.099375ms -- **Spec File**: ../../specs/jobs/core.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'CreateAppDTO.AppName' Error:Field validation for 'AppName' failed on the 'name-component' tag","userMessage":"Key: 'CreateAppDTO.... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ GET /orchestrator/job/ci-pipeline/list/{jobId} - -- **Status**: FAIL -- **Duration**: 110.828375ms -- **Spec File**: ../../specs/jobs/core.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","result":"Job with the given Id does not exist"} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ POST /orchestrator/notification/search - -- **Status**: PASS -- **Duration**: 169.025166ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"team":null,"app":null,"environment":null,"cluster":null,"pipeline":{"id":1,"name":"cd-3-pgxd","environmentName":"devtron-demo","appName":"pk-test","isVirtualEnvir... - ---- - -### ❌ POST /orchestrator/notification/v2 - -- **Status**: FAIL -- **Duration**: 143.0195ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'NotificationRequest.NotificationConfigRequest' Error:Field validation for 'NotificationConfigRequest' failed on the 'required' ta... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ POST /orchestrator/notification/channel - -- **Status**: FAIL -- **Duration**: 107.426792ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {} - -**Issues:** -- **RESPONSE_FORMAT_ERROR**: Response is not valid JSON: unexpected end of JSON input - ---- - -### ❌ DELETE /orchestrator/notification/channel - -- **Status**: FAIL -- **Duration**: 108.504292ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{ The channel you requested is not supported}]","userMessage":" The channel you requested is not supported"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/notification/channel - -- **Status**: PASS -- **Duration**: 111.193459ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"slackConfigs":[],"webhookConfigs":[],"sesConfigs":[{"userId":2,"teamId":0,"region":"ap-south-1","accessKey":"AKIAWEAVHFOOSNAORPHU","secretKey":"**********","fromEm... - ---- - -### ✅ GET /orchestrator/notification/channel/autocomplete/{type} - -- **Status**: PASS -- **Duration**: 106.45575ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[]} - ---- - -### ✅ GET /orchestrator/notification/channel/webhook/{id} - -- **Status**: PASS -- **Duration**: 107.74825ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"userId":0,"webhookUrl":"","configName":"","header":null,"payload":"","description":"","id":0}} - ---- - -### ✅ GET /orchestrator/notification/channel/slack/{id} - -- **Status**: PASS -- **Duration**: 125.669083ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"userId":0,"teamId":0,"webhookUrl":"","configName":"","description":"","id":0}} - ---- - -### ✅ GET /orchestrator/notification/channel/ses/{id} - -- **Status**: PASS -- **Duration**: 119.674333ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"userId":2,"teamId":0,"region":"ap-south-1","accessKey":"AKIAWEAVHFOOSNAORPHU","secretKey":"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","fromEmail":"watcher@devtron.i... - ---- - -### ❌ GET /orchestrator/notification/recipient - -- **Status**: FAIL -- **Duration**: 103.045458ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/notification/variables - -- **Status**: PASS -- **Duration**: 129.210916ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"devtronAppId":"{{devtronAppId}}","devtronAppName":"{{devtronAppName}}","devtronApprovedByEmail":"{{devtronApprovedByEmail}}","devtronBuildGitCommitHash":"{{devtron... - ---- - -### ❌ GET /orchestrator/notification - -- **Status**: FAIL -- **Duration**: 120.781583ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /orchestrator/notification - -- **Status**: FAIL -- **Duration**: 125.769709ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'NotificationRequest.NotificationConfigRequest' Error:Field validation for 'NotificationConfigRequest' failed on the 'required' ta... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ PUT /orchestrator/notification - -- **Status**: FAIL -- **Duration**: 120.040292ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'NotificationUpdateRequest.NotificationConfigRequest' Error:Field validation for 'NotificationConfigRequest' failed on the 'requir... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ DELETE /orchestrator/notification - -- **Status**: PASS -- **Duration**: 177.014667ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK"} - ---- - -### ✅ GET /orchestrator/notification/channel/smtp/{id} - -- **Status**: PASS -- **Duration**: 109.910917ms -- **Spec File**: ../../specs/notifications/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"id":0,"port":"","host":"","authType":"","authUser":"","authPassword":"","fromEmail":"","configName":"","description":"","ownerId":0,"default":false,"deleted":false... - ---- - -### ❌ PATCH /orchestrator/app/ci-pipeline/patch-source - -- **Status**: FAIL -- **Duration**: 107.972084ms -- **Spec File**: ../../specs/ci-pipeline/ci-pipeline-change-source.yaml -- **Response Code**: 500 -- **Error/Msg**: internal server error - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ PATCH /orchestrator/app/env/patch - -- **Status**: FAIL -- **Duration**: 106.570458ms -- **Spec File**: ../../specs/helm/deployment-chart-type.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","result":{"appId":0,"envId":0,"targetChartRefId":0}} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ POST /orchestrator/chart-repo/validate - -- **Status**: FAIL -- **Duration**: 108.843208ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","internalMessage":"Key: 'ChartRepoDto.Name' Error:Field validation for 'Name' failed on the 'required' tag\nKey: 'ChartRepoDto.AuthMode' Erro... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ POST /orchestrator/chart-repo/create - -- **Status**: FAIL -- **Duration**: 108.111667ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","internalMessage":"Key: 'ChartRepoDto.Name' Error:Field validation for 'Name' failed on the 'required' tag\nKey: 'ChartRepoDto.AuthMode' Erro... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ POST /orchestrator/chart-repo/sync-charts - -- **Status**: PASS -- **Duration**: 7.15860475s -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"status":"ok"}} - ---- - -### ❌ POST /orchestrator/chart-repo/update - -- **Status**: FAIL -- **Duration**: 108.224708ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","internalMessage":"Key: 'ChartRepoDto.Name' Error:Field validation for 'Name' failed on the 'required' tag\nKey: 'ChartRepoDto.AuthMode' Erro... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/app-store/chart-provider/list - -- **Status**: PASS -- **Duration**: 109.558958ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":"prakhar","name":"prakhar","active":true,"isEditable":true,"isOCIRegistry":true,"registryProvider":"docker-hub"},{"id":"1","name":"default-chartmuseum","activ... - ---- - -### ❌ POST /orchestrator/app-store/chart-provider/sync-chart - -- **Status**: FAIL -- **Duration**: 108.328375ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ChartProviderRequestDto.Id' Error:Field validation for 'Id' failed on the 'required' tag","userMessage":"Key: 'ChartProviderReque... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ POST /orchestrator/chart-group/ - -- **Status**: FAIL -- **Duration**: 118.224ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ChartGroupBean.Name' Error:Field validation for 'Name' failed on the 'name-component' tag","userMessage":"Key: 'ChartGroupBean.Na... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ PUT /orchestrator/chart-group/ - -- **Status**: FAIL -- **Duration**: 108.558833ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ChartGroupBean.Name' Error:Field validation for 'Name' failed on the 'name-component' tag","userMessage":"Key: 'ChartGroupBean.Na... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/chart-group/list - -- **Status**: PASS -- **Duration**: 106.122125ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":null} - ---- - -### ✅ GET /orchestrator/chart-repo/{id} - -- **Status**: PASS -- **Duration**: 116.164959ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"name":"default-chartmuseum","url":"http://devtron-chartmuseum.devtroncd:8080/","authMode":"ANONYMOUS","active":true,"default":true,"allow_insecure_connectio... - ---- - -### ❌ POST /orchestrator/app-store/chart-provider/update - -- **Status**: FAIL -- **Duration**: 105.508709ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'ChartProviderRequestDto.Id' Error:Field validation for 'Id' failed on the 'required' tag","userMessage":"Key: 'ChartProviderReque... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ PUT /orchestrator/chart-group/entries - -- **Status**: FAIL -- **Duration**: 105.53ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ DELETE /orchestrator/chart-group/{id} - -- **Status**: FAIL -- **Duration**: 103.77225ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/chart-repo/list - -- **Status**: PASS -- **Duration**: 111.011625ms -- **Spec File**: ../../specs/helm/provider.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"name":"default-chartmuseum","url":"http://devtron-chartmuseum.devtroncd:8080/","authMode":"ANONYMOUS","active":true,"default":true,"allow_insecure_connecti... - ---- - -### ✅ GET /orchestrator/api-token - -- **Status**: PASS -- **Duration**: 109.104708ms -- **Spec File**: ../../specs/openapiClient/api/apiToken_api-openapi.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"description":"some description","expireAtInMs":12344546,"id":2,"name":"some-name","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6IkFQSS1UT0tFTjpzb21lLW... - ---- - -### ❌ POST /orchestrator/api-token - -- **Status**: FAIL -- **Duration**: 109.536917ms -- **Spec File**: ../../specs/openapiClient/api/apiToken_api-openapi.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'CreateApiTokenRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag","userMessage":"Key: 'CreateApiTokenRe... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/api-token/webhook - -- **Status**: PASS -- **Duration**: 109.142292ms -- **Spec File**: ../../specs/openapiClient/api/apiToken_api-openapi.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[]} - ---- - -### ❌ DELETE /orchestrator/api-token/{id} - -- **Status**: FAIL -- **Duration**: 107.791666ms -- **Spec File**: ../../specs/openapiClient/api/apiToken_api-openapi.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{api-token corresponds to apiTokenId '1' is not found}]","userMessage":"api-token corresponds to apiTokenId '1'... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ PUT /orchestrator/api-token/{id} - -- **Status**: FAIL -- **Duration**: 110.273667ms -- **Spec File**: ../../specs/openapiClient/api/apiToken_api-openapi.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'UpdateApiTokenRequest.Description' Error:Field validation for 'Description' failed on the 'required' tag","userMessage":"Key: 'Up... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/user/role/group/detailed/get - -- **Status**: PASS -- **Duration**: 120.157291ms -- **Spec File**: ../../specs/security/group-policy.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":2,"roleFilters":[],"superAdmin":false,"canManageAllAccess":false,"hasAccessManagerPermission":false}]} - ---- - -### ❌ GET /orchestrator/user/role/group/search - -- **Status**: FAIL -- **Duration**: 111.182083ms -- **Spec File**: ../../specs/security/group-policy.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"search\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"search\": invalid syntax"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/user/role/group/v2 - -- **Status**: PASS -- **Duration**: 127.43525ms -- **Spec File**: ../../specs/security/group-policy.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"roleGroups":[{"id":2,"roleFilters":[],"superAdmin":false,"canManageAllAccess":false,"hasAccessManagerPermission":false}],"totalCount":1}} - ---- - -### ❌ POST /orchestrator/user/role/group/v2 - -- **Status**: FAIL -- **Duration**: 113.402542ms -- **Spec File**: ../../specs/security/group-policy.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{role group already exist}]","userMessage":"role group already exist"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ PUT /orchestrator/user/role/group/v2 - -- **Status**: FAIL -- **Duration**: 192.148875ms -- **Spec File**: ../../specs/security/group-policy.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":""}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ DELETE /orchestrator/user/role/group/{id} - -- **Status**: FAIL -- **Duration**: 110.706666ms -- **Spec File**: ../../specs/security/group-policy.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":""}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ GET /orchestrator/user/role/group/{id} - -- **Status**: FAIL -- **Duration**: 112.249625ms -- **Spec File**: ../../specs/security/group-policy.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"Failed to get by id"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ PUT /orchestrator/user/role/group - -- **Status**: FAIL -- **Duration**: 109.076167ms -- **Spec File**: ../../specs/security/group-policy.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":""}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/user/role/group - -- **Status**: PASS -- **Duration**: 109.09175ms -- **Spec File**: ../../specs/security/group-policy.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":2,"roleFilters":[],"superAdmin":false,"canManageAllAccess":false,"hasAccessManagerPermission":false}]} - ---- - -### ❌ POST /orchestrator/user/role/group - -- **Status**: FAIL -- **Duration**: 160.916ms -- **Spec File**: ../../specs/security/group-policy.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{role group already exist}]","userMessage":"role group already exist"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ DELETE /orchestrator/user/role/group/bulk - -- **Status**: FAIL -- **Duration**: 110.531667ms -- **Spec File**: ../../specs/security/group-policy.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{ERROR #42601 syntax error at or near \")\"}]","userMessage":"ERROR #42601 syntax error at or near \")\""}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ GET /{appId}/ci-pipeline/{pipelineId}/workflow/{workflowId} - -- **Status**: FAIL -- **Duration**: 103.118625ms -- **Spec File**: ../../specs/ci-pipeline/ci-pipeline-build-spec.yaml -- **Response Code**: 404 -- **Error/Msg**: -404 Not Found - -

404 Not Found

-
nginx
- - - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 -- **RESPONSE_FORMAT_ERROR**: Response is not valid JSON: invalid character '<' looking for beginning of value - ---- - -### ❌ POST /ci-pipeline/trigger - -- **Status**: FAIL -- **Duration**: 102.16925ms -- **Spec File**: ../../specs/ci-pipeline/ci-pipeline-build-spec.yaml -- **Response Code**: 404 -- **Error/Msg**: -404 Not Found - -

404 Not Found

-
nginx
- - - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ GET /orchestrator/app/commit-info/{ciPipelineMaterialId}/{gitHash} - -- **Status**: FAIL -- **Duration**: 109.109291ms -- **Spec File**: ../../specs/ci-pipeline/ci-pipeline-build-spec.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ GET /orchestrator/deployment/pipeline/history - -- **Status**: FAIL -- **Duration**: 110.7765ms -- **Spec File**: ../../specs/deployment/pipeline.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /orchestrator/deployment/pipeline/rollback - -- **Status**: FAIL -- **Duration**: 105.640292ms -- **Spec File**: ../../specs/deployment/pipeline.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /orchestrator/deployment/pipeline/trigger - -- **Status**: FAIL -- **Duration**: 103.362625ms -- **Spec File**: ../../specs/deployment/pipeline.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /orchestrator/deployment/pipeline/configure - -- **Status**: FAIL -- **Duration**: 106.426125ms -- **Spec File**: ../../specs/deployment/pipeline.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ GET /orchestrator/flux-application - -- **Status**: FAIL -- **Duration**: 106.788833ms -- **Spec File**: ../../specs/gitops/fluxcd.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{error in getting cluster ids}]","userMessage":"error in getting cluster ids"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ GET /orchestrator/flux-application/app - -- **Status**: FAIL -- **Duration**: 106.9545ms -- **Spec File**: ../../specs/gitops/fluxcd.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /create - -- **Status**: FAIL -- **Duration**: 344.150333ms -- **Spec File**: ../../specs/helm/repo-validation.yaml -- **Response Code**: 404 -- **Error/Msg**: -404 Not Found - -

404 Not Found

-
nginx
- - - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /orchestrator/validate - -- **Status**: FAIL -- **Duration**: 105.761834ms -- **Spec File**: ../../specs/helm/repo-validation.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /update - -- **Status**: FAIL -- **Duration**: 103.281125ms -- **Spec File**: ../../specs/helm/repo-validation.yaml -- **Response Code**: 404 -- **Error/Msg**: -404 Not Found - -

404 Not Found

-
nginx
- - - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/app/history/deployed-configuration/{appId}/{pipelineId}/{wfrId} - -- **Status**: PASS -- **Duration**: 112.768834ms -- **Spec File**: ../../specs/audit/definitions.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":8,"name":"DEPLOYMENT_TEMPLATE"},{"id":3,"name":"PIPELINE_STRATEGY"}]} - ---- - -### ❌ GET /orchestrator/app/history/deployed-component/detail/{appId}/{pipelineId}/{id} - -- **Status**: FAIL -- **Duration**: 107.579042ms -- **Spec File**: ../../specs/audit/definitions.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","result":"invalid historyComponent"} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ GET /orchestrator/app/history/deployed-component/list/{appId}/{pipelineId} - -- **Status**: FAIL -- **Duration**: 110.888833ms -- **Spec File**: ../../specs/audit/definitions.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","result":"invalid historyComponent"} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/deployment/template/fetch - -- **Status**: PASS -- **Duration**: 215.775292ms -- **Spec File**: ../../specs/deployment/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":10,"name":"Rollout Deployment","chartDescription":"This chart deploys an advanced version of deployment that supports Blue/Green and Canary deployments. For f... - ---- - -### ✅ PUT /orchestrator/deployment/template/upload - -- **Status**: PASS -- **Duration**: 141.399542ms -- **Spec File**: ../../specs/deployment/core.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":"Processed successfully"} - ---- - -### ❌ POST /orchestrator/deployment/template/validate - -- **Status**: FAIL -- **Duration**: 108.184292ms -- **Spec File**: ../../specs/deployment/core.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{request Content-Type isn't multipart/form-data}]","userMessage":"request Content-Type isn't multipart/form-data"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ GET /orchestrator/app/history/deployed-configuration/all/latest/{appId}/{pipelineId} - -- **Status**: FAIL -- **Duration**: 107.507875ms -- **Spec File**: ../../specs/deployment/rollback.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{strconv.Atoi: parsing \"latest\": invalid syntax}]","userMessage":"strconv.Atoi: parsing \"latest\": invalid syntax"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/app/history/deployed-configuration/all/{appId}/{pipelineId}/{wfrId} - -- **Status**: PASS -- **Duration**: 172.705959ms -- **Spec File**: ../../specs/deployment/rollback.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"deploymentTemplate":{"templateName":"Deployment","templateVersion":"4.21.0","isAppMetricsEnabled":false,"codeEditorValue":{"displayName":"values.yaml","value":"{\"... - ---- - -### ❌ GET /orchestrator/app/template/default/{appId}/{chartRefId} - -- **Status**: FAIL -- **Duration**: 108.519ms -- **Spec File**: ../../specs/environment/templates.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ DELETE /orchestrator/k8s/resources/ephemeralContainers - -- **Status**: FAIL -- **Duration**: 104.236917ms -- **Spec File**: ../../specs/kubernetes/ephemeral-containers.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /orchestrator/k8s/resources/ephemeralContainers - -- **Status**: FAIL -- **Duration**: 111.923583ms -- **Spec File**: ../../specs/kubernetes/ephemeral-containers.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ PUT /orchestrator/application/rollback - -- **Status**: FAIL -- **Duration**: 108.570458ms -- **Spec File**: ../../specs/openapiClient/api/openapi.yaml -- **Response Code**: 500 -- **Error/Msg**: internal server error - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ POST /orchestrator/application/template-chart - -- **Status**: FAIL -- **Duration**: 105.56825ms -- **Spec File**: ../../specs/openapiClient/api/openapi.yaml -- **Response Code**: 500 -- **Error/Msg**: internal server error - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ❌ GET /orchestrator/app/deployment-status/timeline/{appId}/{envId} - -- **Status**: FAIL -- **Duration**: 161.653375ms -- **Spec File**: ../../specs/deployment/timeline.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ POST /orchestrator/app/ci-pipeline/patch - -- **Status**: FAIL -- **Duration**: 108.342041ms -- **Spec File**: ../../specs/infrastructure/docker-build.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/app/ci-pipeline/{appId} - -- **Status**: PASS -- **Duration**: 111.224292ms -- **Spec File**: ../../specs/infrastructure/docker-build.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"appId":1,"dockerRegistry":"quay","dockerRepository":"devtron/test","ciBuildConfig":{"id":1,"gitMaterialId":1,"buildContextGitMaterialId":1,"useRootBuildCont... - ---- - -### ✅ GET /orchestrator/app/wf/all/component-names/{appId} - -- **Status**: PASS -- **Duration**: 109.274375ms -- **Spec File**: ../../specs/infrastructure/docker-build.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"workflows":[{"id":1,"name":"wf-1-lcu5","ciPipelineId":0,"ciPipelineName":"","cdPipelines":null},{"id":2,"name":"wf-1-4rww","ciPipelineId":0,"ciPipelineName":"","cd... - ---- - -### ❌ POST /orchestrator/user - -- **Status**: FAIL -- **Duration**: 109.060167ms -- **Spec File**: ../../specs/security/user-management.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'UserInfo.EmailId' Error:Field validation for 'EmailId' failed on the 'required' tag","userMessage":"Key: 'UserInfo.EmailId' Error... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ PUT /orchestrator/user - -- **Status**: FAIL -- **Duration**: 107.529458ms -- **Spec File**: ../../specs/security/user-management.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"internalMessage":"Key: 'UserInfo.EmailId' Error:Field validation for 'EmailId' failed on the 'required' tag","userMessage":"Key: 'UserInfo.EmailId' Error... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ DELETE /orchestrator/user/bulk - -- **Status**: FAIL -- **Duration**: 109.0525ms -- **Spec File**: ../../specs/security/user-management.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{ERROR #42601 syntax error at or near \")\"}]","userMessage":"ERROR #42601 syntax error at or near \")\""}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ✅ GET /orchestrator/user/v2 - -- **Status**: PASS -- **Duration**: 109.714292ms -- **Spec File**: ../../specs/security/user-management.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"users":[{"id":2,"email_id":"admin","roleFilters":[],"groups":[],"superAdmin":false,"userRoleGroups":[],"lastLoginTime":"2025-08-05T16:40:13.674161Z","timeoutWindow... - ---- - -### ❌ DELETE /orchestrator/user/{id} - -- **Status**: FAIL -- **Duration**: 108.809292ms -- **Spec File**: ../../specs/security/user-management.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"400","userMessage":"cannot delete system or admin user"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ✅ GET /orchestrator/user/{id} - -- **Status**: PASS -- **Duration**: 127.785542ms -- **Spec File**: ../../specs/security/user-management.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"email_id":"system","roleFilters":[],"groups":[],"superAdmin":false,"userRoleGroups":[],"lastLoginTime":"0001-01-01T00:00:00Z","timeoutWindowExpression":"000... - ---- - -### ❌ GET /orchestrator/env/namespace/autocomplete - -- **Status**: FAIL -- **Duration**: 107.054334ms -- **Spec File**: ../../specs/environment/core.yaml -- **Response Code**: 500 -- **Error/Msg**: {"code":500,"status":"Internal Server Error","errors":[{"code":"000","internalMessage":"[{ERROR #42601 syntax error at or near \")\"}]","userMessage":"ERROR #42601 syntax error at or near \")\""}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 500 - ---- - -### ✅ GET /orchestrator/gitops/configured - -- **Status**: PASS -- **Duration**: 108.961292ms -- **Spec File**: ../../specs/gitops/validation.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"allowCustomRepository":false,"authMode":"PASSWORD","exists":true,"provider":"GITHUB"}} - ---- - -### ❌ POST /orchestrator/validate - -- **Status**: FAIL -- **Duration**: 110.406625ms -- **Spec File**: ../../specs/gitops/validation.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ✅ GET /orchestrator/gitops/config - -- **Status**: PASS -- **Duration**: 108.276792ms -- **Spec File**: ../../specs/gitops/validation.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":[{"id":1,"provider":"GITHUB","username":"systemsdt","token":"","gitLabGroupId":"","gitHubOrgId":"stage-gitops","host":"https://github.com/","active":true,"azureProje... - ---- - -### ❌ POST /orchestrator/gitops/config - -- **Status**: FAIL -- **Duration**: 109.114625ms -- **Spec File**: ../../specs/gitops/validation.yaml -- **Response Code**: 400 -- **Error/Msg**: {"code":400,"status":"Bad Request","errors":[{"code":"000","internalMessage":"[{value is unsupported Key: 'GitOpsConfigDto.Provider' Error:Field validation for 'Provider' failed on the 'oneof' tag}]... - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 400 - ---- - -### ❌ PUT /orchestrator/gitops/config - -- **Status**: FAIL -- **Duration**: 107.554459ms -- **Spec File**: ../../specs/gitops/validation.yaml -- **Response Code**: 404 -- **Error/Msg**: {"code":404,"status":"Not Found","errors":[{"code":"000","internalMessage":"[{pg: no rows in result set}]","userMessage":"pg: no rows in result set"}]} - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 - ---- - -### ❌ GET /orchestrator/gitops/config-by-provider - -- **Status**: FAIL -- **Duration**: 104.3385ms -- **Spec File**: ../../specs/gitops/validation.yaml -- **Response Code**: 404 -- **Error/Msg**: 404 page not found - - -**Issues:** -- **STATUS_CODE_MISMATCH**: Expected status 200, got 404 -- **RESPONSE_FORMAT_ERROR**: Response is not valid JSON: invalid character 'p' after top-level value - ---- - -### ✅ GET /orchestrator/gitops/config/{id} - -- **Status**: PASS -- **Duration**: 108.533292ms -- **Spec File**: ../../specs/gitops/validation.yaml -- **Response Code**: 200 -- **Error/Msg**: {"code":200,"status":"OK","result":{"id":1,"provider":"GITHUB","username":"systemsdt","token":"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","gitLabGro... - ---- -