diff --git a/api.html b/api.html new file mode 100644 index 0000000..b71061a --- /dev/null +++ b/api.html @@ -0,0 +1,41 @@ + + + + + + ACE Platform API (b3) — API Reference + + + + +
AppsCode Cloud Engine (ACE) — b3 API Reference + OpenAPI 3.0.3 · generated from the b3 source · 443 paths / 530 operations +
+
+ + + + + \ No newline at end of file diff --git a/docs/platform/api/_index.md b/docs/platform/api/_index.md new file mode 100644 index 0000000..591c3e8 --- /dev/null +++ b/docs/platform/api/_index.md @@ -0,0 +1,62 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api + name: API Reference + weight: 40 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# ACE Platform API Reference + +Low-level reference for the AppsCode Cloud Engine (ACE) platform backend (`b3`) +REST API. Every endpoint lists its HTTP method, path, authentication, path/query +parameters, and request/response shapes so you can implement a client directly +against it. + +All routes are served under the `/api/v1` prefix unless noted otherwise. The +marketplace webhook service is a separate listener rooted at `/marketplace/api/v1`. + +## Authentication + +Most endpoints require a personal access token. Send it as an HTTP header: + +``` +Authorization: token +``` + +You can also pass it as a `token` or `access_token` query parameter. Token-management +endpoints accept HTTP Basic auth. The web console uses a session cookie +(`i_like_ace`); a session cookie alone does **not** authenticate the token-guarded +REST endpoints — use a token. + +A machine-readable [OpenAPI 3.0.3 specification](../openapi.yaml) of this API is also +available (`openapi.yaml`) — load it into any OpenAPI tool (Swagger UI, Redoc, +`openapi-generator`) to explore the API or generate a client. A self-contained +Swagger UI viewer (`api.html`, with the spec inlined) is available at the repository +root. + +## API groups + +| Group | What it covers | +|---|---| +| [Identity: Users & Settings](../users-settings/) | Accounts, profile/security settings, tokens, credentials | +| [Identity: Organizations & Teams](../organizations-teams/) | Orgs, members, teams, org tokens | +| [Administration](../administration/) | Admin console, site settings | +| [Authorization](../authorization/) | Custom roles & permissions | +| [Cluster Management v1](../cluster-management-v1/) | Cluster lifecycle, Kubernetes proxy, Helm | +| [Cluster Management v2](../cluster-management-v2/) | Hub-aware cluster API, subscriptions, gateways | +| [Multi-cluster (OCM)](../multicluster-ocm/) | Hub/spoke, cluster sets, feature sets | +| [Client Organizations](../client-organizations/) | Managed-service client orgs | +| [Cloud Providers](../cloud-providers/) | Provider discovery for provisioning | +| [ACE Installer](../ace-installer/) | Self-host installer bundles | +| [ACE Upgrade](../ace-upgrade/) | Platform & cluster upgrades | +| [Licensing & Contracts](../licensing-contracts/) | Contracts, licenses, registration | +| [Billing Dashboard](../billing-dashboard/) | Usage reports & billing dashboards | +| [Marketplace](../marketplace/) | Cloud-marketplace webhooks & metering | +| [Monitoring & Telemetry](../monitoring-telemetry/) | Telemetry stack, Trickster auth proxy | +| [Rancher Integration](../rancher/) | Rancher sync & proxy | +| [Chart Repositories](../chart-repositories/) | Public Helm chart repositories | +| [Miscellaneous](../miscellaneous/) | Version, markdown, health | diff --git a/docs/platform/api/ace-installer/_index.md b/docs/platform/api/ace-installer/_index.md new file mode 100644 index 0000000..0380756 --- /dev/null +++ b/docs/platform/api/ace-installer/_index.md @@ -0,0 +1,32 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-ace-installer + name: ACE Installer + parent: api + weight: 100 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# ACE Installer API + +The ACE Installer API generates and manages self-host installer bundles for the +AppsCode Container Engine (ACE) platform. It serves the installer options schema, +generates and imports installer bundles, lists and inspects generated installers, +and supports reconfigure/upgrade/versioning and marketplace-installer status. + +> **AppsCode-hosted only.** Every route under `/api/v1/ace-installer/...` is available +> only on the AppsCode-hosted (SaaS) deployment. On self-hosted ACE installations these +> routes are not registered and return `404 Not Found`. All calls require a bearer token, +> an org context (resolved from the `org` query param), and per-action authorization +> checks (`view_installers`, `create_installers`, `import_installers`, +> `reconfigure_installers`, `upgrade_installers`, `download_installers`, +> `delete_installers`). + +## Pages + +- [ACE Installer](../ace-installer.md) — schema/model, generate/import, + installer metadata and latest version, installers CRUD, reconfigure/upgrade, + versions/archives, and marketplace installer status. diff --git a/docs/platform/api/ace-installer/ace-installer.md b/docs/platform/api/ace-installer/ace-installer.md new file mode 100644 index 0000000..85baef9 --- /dev/null +++ b/docs/platform/api/ace-installer/ace-installer.md @@ -0,0 +1,457 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-ace-installer-ace-installer + name: ACE Installer + parent: api-ace-installer + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# ACE Installer + +The ACE Installer endpoints generate and manage self-host installer bundles for the +AppsCode Container Engine (ACE) platform. All paths on this page are relative to the +API root `/api/v1` — for example `/ace-installer/schema.json` is +`/api/v1/ace-installer/schema.json`. + +> **AppsCode-hosted only.** These routes exist only on the AppsCode-hosted (SaaS) +> deployment. On self-hosted ACE installations the `/ace-installer` routes are not +> registered and every call returns `404 Not Found`. (This was confirmed live — see the +> verification notes below.) + +## Authentication and authorization + +All endpoints accept a bearer token via any of the supported schemes +(`Authorization: token `, the `Token` cookie, or an `AccessToken`). Requests are +scoped to an organization that is resolved from the `org` query parameter. Beyond the +base token/org check, most endpoints enforce a per-action authorization on the +organization's hosted-mode capability: + +| Action | Required authorization | +|--------|------------------------| +| View / list / versions | `view_installers` (`Organization_HostedModeCanViewInstallers`) | +| Generate | `create_installers` (`Organization_HostedModeCanCreateInstallers`) | +| Import | `import_installers` (`Organization_HostedModeCanImportInstallers`) | +| Reconfigure | `reconfigure_installers` (`Organization_HostedModeCanReconfigureInstallers`) | +| Upgrade | `upgrade_installers` (`Organization_HostedModeCanUpgradeInstallers`) | +| Download archive | `download_installers` (`Organization_HostedModeCanDownloadInstallers`) | +| Delete | `delete_installers` (`Organization_HostedModeCanDeleteInstallers`) | +| Serve installer options (`model.json`) | `create_installers` | + +A documented call looks like: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https://appscode.com/api/v1/ace-installer/latest-version?org=appscode" +``` + +## Common query parameter + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `org` | string | yes | Organization slug used to resolve the org context (e.g. `appscode`). | + +## Data models + +### InstallerMetadata + +Metadata describing a generated or imported ACE installer. + +```json +{ + "ID": "inst-01hxyz", + "installerName": "acme-prod", + "deploymentType": "SelfHosted", + "requestedDomain": "ace.example.com", + "host": "ace.example.com", + "hostType": "Custom", + "hostedDomain": "acme.ace.appscode.com", + "ownerName": "appscode", + "requesterDisplayName": "Example User", + "requesterUsername": "user", + "adminDisplayName": "Example Admin", + "adminEmail": "user@example.com", + "accessTokenID": 12345, + "clusterID": "", + "version": "v2025.7.14", + "promotedToProduction": false, + "createTimestamp": "2026-07-14T10:00:00Z", + "expiryTimestamp": "2026-08-14T10:00:00Z", + "lastUpgradeTimestamp": "2026-07-14T10:00:00Z", + "lastUpdateTimestamp": "2026-07-14T10:00:00Z" +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `ID` | string | Installer ID. | +| `installerName` | string | Installer name (installers are grouped by name). | +| `deploymentType` | string | ACE deployment type. | +| `requestedDomain` | string | Domain requested for the installer. | +| `host` | string | Effective host for the deployment. | +| `hostType` | string | Host type. | +| `hostedDomain` | string | AppsCode-hosted domain assigned to the deployment. | +| `ownerName` | string | Owner organization slug. | +| `requesterDisplayName` | string | Display name of the requester. | +| `requesterUsername` | string | Username of the requester. | +| `adminDisplayName` | string | Display name of the platform admin. | +| `adminEmail` | string | Email of the platform admin. | +| `accessTokenID` | integer (int64) | ID of the access token that created the installer. | +| `clusterID` | string | Cluster identifier bound to the installer. | +| `version` | string | ACE installer chart version. | +| `promotedToProduction` | boolean | Whether the installer has been promoted to production. | +| `createTimestamp` | string (date-time) | Creation time. | +| `expiryTimestamp` | string (date-time) | Expiry time. | +| `lastUpgradeTimestamp` | string (date-time) | Last upgrade time. | +| `lastUpdateTimestamp` | string (date-time) | Last update time. | + +### InstallerDetails + +```json +{ + "meta": { "...": "InstallerMetadata" }, + "readme": "", + "archiveZipURL": "https://.../installer.zip", + "archiveTarURL": "https://.../installer.tar.gz" +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `meta` | InstallerMetadata | Installer metadata. | +| `readme` | string (byte) | Base64-encoded readme content. | +| `archiveZipURL` | string | Download URL for the `.zip` archive. | +| `archiveTarURL` | string | Download URL for the `.tar.gz` archive. | + +### InstallerVersion + +| Field | Type | Description | +|-------|------|-------------| +| `version` | string | Version string. | +| `creationTime` | string (date-time) | When the version/archive was created. | +| `archiveURL` | string | Archive download URL. | +| `archiveName` | string | Archive file name. | +| `createdBy` | User | User who created the version. | +| `lastOperation` | string | The last operation applied for this version. | +| `latestInstaller` | boolean | Whether this is the latest installer version. | + +### MarketplaceInstallerStatus + +| Field | Type | Description | +|-------|------|-------------| +| `status` | string | Either `Pending` or `Bound`. | +| `link` | string | Marketplace / self-host link. | +| `meta` | InstallerMetadata | Installer metadata. | +| `isExpired` | boolean | Whether the subscription has expired. | + +--- + +## Schema and default options + +### GET /ace-installer/schema.json + +Returns the raw OpenAPI v3 JSON schema for ACE installer options +(`ace-options/values.openapiv3_schema.yaml`) as a dynamic JSON object. + +- **Auth:** token; org resolved from the `org` query param. +- **Query parameters:** + + | Name | Type | Required | Description | + |------|------|----------|-------------| + | `org` | string | yes | Organization slug. | + +- **Response `200`:** an arbitrary Kubernetes-style JSON object (the OpenAPI v3 schema + document). The body is free-form and passed through verbatim, so no fixed field set is + documented here. + +> **Verified:** returned `404` against `appscode` on the self-hosted platform +> (``) on 2026-07-14 — the ace-installer routes are AppsCode-hosted only and are +> not registered on this install (body: `{"message":"Not Found"}`). + +### GET /ace-installer/model.json + +Returns the default ACE options model (`AceOptionsSpec`) pre-filled with the requesting +user's admin details, as a dynamic JSON object. + +- **Auth:** token; org context. +- **Query parameters:** `org` (string, required). +- **Response `200`:** an arbitrary Kubernetes-style options JSON object (`AceOptionsSpec`). + +> **Verified:** returned `404` against `appscode` on the self-hosted platform on +> 2026-07-14 (AppsCode-hosted only; route not registered). + +--- + +## Generate and import + +### POST /ace-installer/generate + +Generates a new ACE installer from the supplied `AceOptionsSpec` options and returns the +resulting installer metadata. + +- **Auth:** token; org context; requires `create_installers`. +- **Query parameters:** `org` (string, required). +- **Request body:** a free-form `AceOptionsSpec` object, bound as a dynamic JSON map and + then decoded into `AceOptionsSpec`. The set of options mirrors the schema served by + `GET /ace-installer/schema.json` (a Kubernetes-style values object); the exact fields are + defined by that schema rather than a fixed request model. + + ```json + { + "...": "AceOptionsSpec (see GET /ace-installer/schema.json for the field set)" + } + ``` + +- **Response `200`:** [`InstallerMetadata`](#installermetadata) for the generated installer. +- **Errors:** `401` unauthorized, `403` missing `create_installers`, `422` invalid body, + `500` server error. + +> Not verified live (POST — mutating call not issued against the platform). + +### POST /ace-installer/import + +Imports an existing installer described by the supplied `AceOptionsSpec` options and +returns the resulting installer metadata. + +- **Auth:** token; org context; requires `import_installers`. +- **Query parameters:** `org` (string, required). +- **Request body:** a free-form `AceOptionsSpec` object (same shape as `generate`). +- **Response `200`:** [`InstallerMetadata`](#installermetadata). +- **Errors:** `401`, `403` missing `import_installers`, `422` invalid body, `500`. + +> Not verified live (POST — mutating call not issued against the platform). + +--- + +## Installer metadata and latest version + +### GET /ace-installer/installer-meta + +Returns the installer metadata associated with the access token used to authenticate the +request. + +- **Auth:** token; org context; requires `view_installers`. +- **Query parameters:** `org` (string, required). +- **Response `200`:** [`InstallerMetadata`](#installermetadata). + +> **Verified:** returned `404` against `appscode` on the self-hosted platform on +> 2026-07-14 (AppsCode-hosted only; route not registered). + +### GET /ace-installer/latest-version + +Returns the latest available ACE installer chart version. + +- **Auth:** token; org context; requires `view_installers`. +- **Query parameters:** `org` (string, required). +- **Response `200`:** + + ```json + { "version": "v2025.7.14" } + ``` + + | Field | Type | Description | + |-------|------|-------------| + | `version` | string | Latest ACE installer chart version. | + +> **Verified:** returned `404` against `appscode` on the self-hosted platform on +> 2026-07-14 (AppsCode-hosted only; route not registered). + +--- + +## Installers CRUD + +### GET /ace-installer/installers/ + +Lists the installers for the owner organization, grouped by installer name (one metadata +entry per group). + +- **Auth:** token; org context; requires `view_installers`. +- **Query parameters:** `org` (string, required). +- **Response `200`:** an array of [`InstallerMetadata`](#installermetadata). + +> **Verified:** returned `404` against `appscode` on the self-hosted platform on +> 2026-07-14 (AppsCode-hosted only; route not registered). + +### GET /ace-installer/installers/{name} + +Lists all generated installers matching the given installer name for the owner +organization. + +- **Auth:** token; org context; requires `view_installers`. +- **Path parameters:** + + | Name | Type | Description | + |------|------|-------------| + | `name` | string | Installer name. | + +- **Query parameters:** `org` (string, required). +- **Response `200`:** an array of [`InstallerMetadata`](#installermetadata). +- **Errors:** `401`, `403` missing `view_installers`, `404` not found, `500`. + +> Not verified live (requires a real installer name; not present on this self-hosted +> platform — parent list route returns `404`). + +### GET /ace-installer/installers/{name}/{id} + +Returns detailed metadata for a single generated installer, including readme content and +archive download URLs. + +- **Auth:** token; org context; requires `view_installers`. +- **Path parameters:** + + | Name | Type | Description | + |------|------|-------------| + | `name` | string | Installer name. | + | `id` | string | Installer ID. | + +- **Query parameters:** `org` (string, required). +- **Response `200`:** [`InstallerDetails`](#installerdetails). +- **Errors:** `401`, `403`, `404` installer not found, `428` Precondition Required + (a marketplace installer that is not yet in a bound phase returns a redirect to the + marketplace URL), `500`. + +> Not verified live (requires a real installer name/ID; ace-installer routes not present +> on this self-hosted platform). + +### DELETE /ace-installer/installers/{name}/{id} + +Deletes a generated installer by ID. Installers owned by a marketplace organization +cannot be deleted. + +- **Auth:** token; org context; requires `delete_installers`. +- **Path parameters:** `name` (string), `id` (string). +- **Query parameters:** `org` (string, required). +- **Response `200`:** installer deleted (empty body). +- **Errors:** `401`, `403` missing `delete_installers` or the installer belongs to a + marketplace organization, `500`. + +> Not verified live (DELETE — mutating call not issued against the platform). + +--- + +## Reconfigure and upgrade + +### POST /ace-installer/installers/{name}/{id}/reconfigure + +Reconfigures an existing installer using the supplied `AceOptionsSpec` options. + +- **Auth:** token; org context; requires `reconfigure_installers`. +- **Path parameters:** `name` (string), `id` (string). +- **Query parameters:** + + | Name | Type | Required | Description | + |------|------|----------|-------------| + | `org` | string | yes | Organization slug. | + | `installerOps` | string | yes | Operation to perform — `reconfigure` or `promote-to-prod`. | + +- **Request body:** a free-form `AceOptionsSpec` object (same shape as `generate`). +- **Response `200`:** [`InstallerMetadata`](#installermetadata). +- **Errors:** `400` invalid `installerOps` or installer mismatch, `401`, + `403` missing `reconfigure_installers`, `422` invalid body, `500`. + +> Not verified live (POST — mutating call not issued against the platform). + +### POST /ace-installer/installers/{name}/{id}/upgrade + +Upgrades an existing installer to the latest ACE installer version and returns the updated +installer metadata. + +- **Auth:** token; org context; requires `upgrade_installers`. +- **Path parameters:** `name` (string), `id` (string). +- **Query parameters:** `org` (string, required). +- **Response `200`:** [`InstallerMetadata`](#installermetadata). +- **Errors:** `400` installer not found, `401`, `403` missing `upgrade_installers`, `500`. + +> Not verified live (POST — mutating call not issued against the platform). + +--- + +## Versions and archives + +### GET /ace-installer/installers/{name}/{id}/versions + +Lists the available versions (archives) for a generated installer. + +- **Auth:** token; org context; requires `view_installers`. +- **Path parameters:** `name` (string), `id` (string). +- **Query parameters:** `org` (string, required). +- **Response `200`:** an array of [`InstallerVersion`](#installerversion). +- **Errors:** `400` installer not found, `401`, `403` missing `view_installers`, `500`. + +> Not verified live (requires a real installer name/ID; ace-installer routes not present +> on this self-hosted platform). + +### GET /ace-installer/installers/{name}/{id}/archives/{archiveName} + +Extracts and returns installer details (readme, archive URL) from the specified tar +archive of a generated installer. + +- **Auth:** token; org context; requires `download_installers`. +- **Path parameters:** + + | Name | Type | Description | + |------|------|-------------| + | `name` | string | Installer name. | + | `id` | string | Installer ID. | + | `archiveName` | string | Archive file name. | + +- **Query parameters:** `org` (string, required). +- **Response `200`:** [`InstallerDetails`](#installerdetails). +- **Errors:** `400` installer not found, `401`, `403` missing `download_installers`, `500`. + +> Not verified live (requires a real installer name/ID/archive; ace-installer routes not +> present on this self-hosted platform). + +### GET /ace-installer/installers/{name}/{id}/model.json + +Returns the stored `AceOptionsSpec` options for a generated installer. + +- **Auth:** token; org context; requires `create_installers`. +- **Path parameters:** `name` (string), `id` (string). +- **Query parameters:** + + | Name | Type | Required | Description | + |------|------|----------|-------------| + | `org` | string | yes | Organization slug. | + | `configureProductionOptions` | boolean | no | When `true`, adjust options for a self-hosted production deployment. | + +- **Response `200`:** an arbitrary Kubernetes-style options JSON object (`AceOptionsSpec`). +- **Errors:** `401`, `403` missing `create_installers`, `500`. + +> Not verified live (requires a real installer name/ID; ace-installer routes not present +> on this self-hosted platform). + +--- + +## Marketplace installer status + +### GET /ace-installer/deployment/marketplace/installers/{installerID}/status + +Returns the marketplace subscription status (`Pending` or `Bound`) for a marketplace-type +installer, along with its metadata, download link, and expiry state. This route does not +carry an additional installer-specific authorization check beyond the base org token/authz. + +- **Auth:** token; org context. +- **Path parameters:** + + | Name | Type | Description | + |------|------|-------------| + | `installerID` | string | Installer ID. | + +- **Query parameters:** + + | Name | Type | Required | Description | + |------|------|----------|-------------| + | `org` | string | yes | Organization slug. | + | `redirect` | boolean | no | When `true` and the installer is bound, redirect to the self-host URL. | + +- **Response `200`:** [`MarketplaceInstallerStatus`](#marketplaceinstallerstatus). +- **Errors:** `400` installer not found or not a marketplace deployment type, `401`, + `403`, `428` Precondition Required (when bound and `redirect=true`, a redirect to the + self-host URL is returned), `500`. + +> Not verified live (requires a real marketplace installer ID; ace-installer routes not +> present on this self-hosted platform). diff --git a/docs/platform/api/ace-upgrade/_index.md b/docs/platform/api/ace-upgrade/_index.md new file mode 100644 index 0000000..a98b114 --- /dev/null +++ b/docs/platform/api/ace-upgrade/_index.md @@ -0,0 +1,46 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-ace-upgrade + name: ACE Upgrade + parent: api + weight: 110 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# ACE Upgrade + +APIs for upgrading the ACE platform itself and for upgrading the ACE feature +stack running inside imported and spoke clusters. Upgrades are FluxCD/Helm-driven +and run asynchronously; progress and history are tracked in upgrader `ConfigMap` +data, which these endpoints surface as dynamic key/value maps. + +All routes are served under the `/api/v1` prefix. Every endpoint authenticates +with a personal access token sent as `Authorization: token ` (it may +also be supplied as a `token` or `access_token` query parameter). + +There are two distinct authorization models, which is why the endpoints are split +across two pages: + +- **Platform upgrade** routes (`/api/v1/upgrade*`) act on the ACE platform as a + whole. They require an organization context (`?org=`) and **site-admin + organization authorization** — `view_upgrade_history:org` for the read routes + and `upgrade_platform:org` for the trigger route. +- **Cluster upgrade** routes (`/api/v1/clusters/{owner}/{cluster}/upgrade*` and + `.../spoke/upgrade*`) act on a specific member cluster and are gated by + **cluster assignment** for the given owner/cluster (plus a runtime client to + that cluster). + +## Pages + +- [Platform Upgrade](../platform-upgrade.md) — the + `/api/v1/upgrade*` endpoints: platform upgrade status, job status, history, and + current version, plus triggering a platform upgrade. Requires site-admin org + authorization. +- [Cluster Upgrade](../cluster-upgrade.md) — the + `/api/v1/clusters/{owner}/{cluster}/upgrade*` and `.../spoke/upgrade*` + endpoints: imported-cluster and spoke-cluster upgrade status, history, current + and latest versions, plus triggering cluster/spoke upgrades. Gated by cluster + assignment. diff --git a/docs/platform/api/ace-upgrade/cluster-upgrade.md b/docs/platform/api/ace-upgrade/cluster-upgrade.md new file mode 100644 index 0000000..7fd0367 --- /dev/null +++ b/docs/platform/api/ace-upgrade/cluster-upgrade.md @@ -0,0 +1,269 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-ace-upgrade-cluster-upgrade + name: Cluster Upgrade + parent: api-ace-upgrade + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Cluster Upgrade + +Endpoints for upgrading the ACE feature stack running inside a member cluster. +There are two flavours: + +- **Imported cluster** routes (`/clusters/{owner}/{cluster}/upgrade*`) upgrade the + `opscenter-features` Helm release and its managed features in the target + cluster. +- **Spoke cluster** routes (`/clusters/{owner}/{cluster}/spoke/upgrade*`) upgrade + a spoke cluster by updating its managed cluster profile binding to the hub's + `opscenter-features` version. Spoke status/history are read from the hub + cluster's upgrader `ConfigMap`. + +Paths below are relative to the API root `/api/v1` (so +`/clusters/{owner}/{cluster}/upgrade` means +`https:///api/v1/clusters/{owner}/{cluster}/upgrade`). + +**Authentication & authorization.** All routes require a personal access token +(`Authorization: token `). Access is gated by **cluster assignment** +for the given `owner`/`cluster` (the server also needs a runtime client to that +cluster). A caller without an assignment to the cluster receives `403`. Unlike +the platform upgrade routes, these do **not** use site-admin org authorization and +do not take an `org` query parameter — the owner is part of the path. + +The upgrade status and history responses are dynamic key/value maps read from an +upgrader `ConfigMap` — the exact keys depend on the cluster's installer and are +not a fixed schema. + +## Path parameters + +These apply to every endpoint on this page. + +| Name | Type | Description | +|---|---|---| +| `owner` | string | Organization slug or username that owns the cluster. | +| `cluster` | string | Cluster name within the owner scope. | + +--- + +## GET /clusters/{owner}/{cluster}/upgrade + +Returns the most recent upgrade status for an imported cluster, read from the +latest upgrader `ConfigMap` data in that cluster. The response is a dynamic +key/value map. + +- **Auth:** token; cluster assignment for `{owner}/{cluster}`. + +**Response — `200 OK`.** A free-form JSON object (arbitrary `ConfigMap` `data` +keys). Example shape: + +```json +{ + "status": "completed", + "version": "v2026.6.19" +} +``` + +Returns `400` when no upgrade status is recorded in the cluster yet. + +> **Verified:** `GET /clusters/appscode/ace/upgrade` returned `400` against +> `appscode/ace` (hub) ("no upgrade status found") — no feature-stack upgrade has +> been run on this cluster, so there is no upgrader ConfigMap. On 2026-07-14. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/ace/upgrade +``` + +--- + +## GET /clusters/{owner}/{cluster}/upgrade/history + +Returns the upgrade history for an imported cluster as a list of `ConfigMap` data +maps. + +- **Auth:** token; cluster assignment for `{owner}/{cluster}`. + +**Response — `200 OK`.** A JSON array of dynamic key/value maps. Example: + +```json +[ + { + "status": "completed", + "version": "v2026.6.19" + } +] +``` + +> **Verified:** `GET /clusters/appscode/ace/upgrade/history` returned `200` +> against `appscode/ace` (hub) (empty list `[]`) on 2026-07-14. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/ace/upgrade/history +``` + +--- + +## GET /clusters/{owner}/{cluster}/upgrade/current-version + +Returns the currently installed `opscenter-features` chart version in an imported +cluster. + +- **Auth:** token; cluster assignment for `{owner}/{cluster}`. + +**Response — `200 OK`.** + +```json +{ + "version": "v2026.6.19" +} +``` + +| Field | Type | Description | +|---|---|---| +| `version` | string | Currently installed `opscenter-features` chart version in the cluster. | + +> **Verified:** `GET /clusters/appscode/ace/upgrade/current-version` returned +> `200` against `appscode/ace` (hub) (`{"version":"v2026.6.19"}`) on 2026-07-14. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/ace/upgrade/current-version +``` + +--- + +## GET /clusters/{owner}/{cluster}/upgrade/latest-version + +Returns the latest available `opscenter-features` chart version from the server — +the target used for imported-cluster upgrades. + +- **Auth:** token; cluster assignment for `{owner}/{cluster}`. + +**Response — `200 OK`.** + +```json +{ + "version": "v2026.6.19" +} +``` + +| Field | Type | Description | +|---|---|---| +| `version` | string | Latest available chart version the cluster can be upgraded to. | + +> **Verified:** `GET /clusters/appscode/ace/upgrade/latest-version` returned `200` +> against `appscode/ace` (hub) (`{"version":"v2026.6.19"}`) on 2026-07-14. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/ace/upgrade/latest-version +``` + +--- + +## POST /clusters/{owner}/{cluster}/upgrade + +Triggers an upgrade of the `opscenter-features` Helm release and managed features +in an imported cluster to the server's current version. Runs asynchronously; +progress is tracked in an upgrader `ConfigMap` (poll +`GET /clusters/{owner}/{cluster}/upgrade`). + +- **Auth:** token; cluster assignment for `{owner}/{cluster}`. +- **Request body:** none. + +**Response.** `200` when the upgrade has started. Returns `403` when the cluster +is not assigned to the caller. + +``` +curl -X POST -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/ace/upgrade +``` + +> Not verified live: this is a mutating (`POST`) endpoint and is documented from +> the schema only. + +--- + +## GET /clusters/{owner}/{cluster}/spoke/upgrade + +Returns the most recent upgrade status for a spoke cluster, read from the hub +cluster's upgrader `ConfigMap` data for that spoke. The response is a dynamic +key/value map. + +- **Auth:** token; cluster assignment for `{owner}/{cluster}`. + +**Response — `200 OK`.** A free-form JSON object (arbitrary `ConfigMap` `data` +keys). Example shape: + +```json +{ + "status": "completed", + "version": "v2026.6.19" +} +``` + +Returns `400` when no upgrade status is recorded for the spoke yet. + +> **Verified:** `GET /clusters/appscode/arnob-dev/spoke/upgrade` returned `400` +> against `appscode/arnob-dev` (spoke) ("no upgrade status found") — no spoke +> upgrade recorded on the hub for this cluster. On 2026-07-14. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/arnob-dev/spoke/upgrade +``` + +--- + +## GET /clusters/{owner}/{cluster}/spoke/upgrade/history + +Returns the upgrade history for a spoke cluster as a list of `ConfigMap` data maps +(read from the hub cluster). + +- **Auth:** token; cluster assignment for `{owner}/{cluster}`. + +**Response — `200 OK`.** A JSON array of dynamic key/value maps. Example: + +```json +[ + { + "status": "completed", + "version": "v2026.6.19" + } +] +``` + +> **Verified:** `GET /clusters/appscode/arnob-dev/spoke/upgrade/history` returned +> `200` against `appscode/arnob-dev` (spoke) (empty list `[]`) on 2026-07-14. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/arnob-dev/spoke/upgrade/history +``` + +--- + +## POST /clusters/{owner}/{cluster}/spoke/upgrade + +Triggers an upgrade of a spoke cluster by updating its managed cluster profile +binding and related features to the hub's `opscenter-features` version. Runs +asynchronous post-processing. + +- **Auth:** token; cluster assignment for `{owner}/{cluster}`. +- **Request body:** none. + +**Response.** `200` when the spoke upgrade has started. Returns `403` when the +cluster is not assigned to the caller. + +``` +curl -X POST -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/arnob-dev/spoke/upgrade +``` + +> Not verified live: this is a mutating (`POST`) endpoint and is documented from +> the schema only. diff --git a/docs/platform/api/ace-upgrade/platform-upgrade.md b/docs/platform/api/ace-upgrade/platform-upgrade.md new file mode 100644 index 0000000..042ab0a --- /dev/null +++ b/docs/platform/api/ace-upgrade/platform-upgrade.md @@ -0,0 +1,202 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-ace-upgrade-platform-upgrade + name: Platform Upgrade + parent: api-ace-upgrade + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Platform Upgrade + +Endpoints for upgrading the ACE platform (the `ace-installer` Helm release) as a +whole and for inspecting its upgrade state. Paths below are relative to the API +root `/api/v1` (so `/upgrade` means `https:///api/v1/upgrade`). + +**Authentication & authorization.** All routes require a personal access token +(`Authorization: token `). Platform upgrade routes are scoped to an +organization — pass `?org=` — and require **site-admin organization +authorization**: + +- read routes (`GET`) require `view_upgrade_history:org` + (`Organization_SiteAdminCanViewUpgradeHistory`); +- the trigger route (`POST /upgrade`) requires `upgrade_platform:org` + (`Organization_SiteAdminCanUpgradePlatform`). + +A request without the required site-admin authorization returns `403`. + +The upgrade status and history responses are dynamic key/value maps read from the +latest upgrader `ConfigMap` — the exact keys depend on the installer and are not +a fixed schema. + +## Query parameters + +These apply to every endpoint on this page. + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug providing the site-admin authorization context. | + +--- + +## GET /upgrade + +Returns the most recent ACE platform upgrade status, taken from the latest +upgrader `ConfigMap` data. The response is a dynamic key/value map. + +- **Auth:** token; site-admin org authz `view_upgrade_history:org`. +- **Query parameters:** `org` (see above). + +**Response — `200 OK`.** A free-form JSON object (arbitrary Kubernetes +`ConfigMap` `data` keys). Example shape: + +```json +{ + "status": "completed", + "version": "v2026.6.19", + "startedAt": "2026-06-19T10:02:11Z" +} +``` + +Returns `400` when no upgrade status is recorded yet. + +> **Verified:** `GET /upgrade?org=appscode` returned `400` against `appscode` +> ("no upgrade status found") — no platform upgrade has been run on this +> environment, so there is no upgrader ConfigMap to report. On 2026-07-14. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/upgrade?org=appscode" +``` + +--- + +## GET /upgrade/status + +Returns the status of the most recent ACE platform upgrade job — either `pending` +(with the target `version`) or `completed`. + +- **Auth:** token; site-admin org authz `view_upgrade_history:org`. +- **Query parameters:** `org` (see above). + +**Response — `200 OK`.** + +```json +{ + "status": "completed" +} +``` + +| Field | Type | Description | +|---|---|---| +| `status` | string | Job status (`pending` or `completed`). | +| `version` | string | Target version; present when a job is `pending`. | + +> **Verified:** `GET /upgrade/status?org=appscode` returned `200` against +> `appscode` (`{"status":"completed"}`) on 2026-07-14. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/upgrade/status?org=appscode" +``` + +--- + +## GET /upgrade/history + +Returns the ACE platform upgrade history as a list of `ConfigMap` data maps, each +augmented with a `status` field. + +- **Auth:** token; site-admin org authz `view_upgrade_history:org`. +- **Query parameters:** `org` (see above). + +**Response — `200 OK`.** A JSON array of dynamic key/value maps (each map's keys +are `ConfigMap` `data` entries plus a `status`). Example: + +```json +[ + { + "status": "completed", + "version": "v2026.6.19", + "startedAt": "2026-06-19T10:02:11Z" + } +] +``` + +> **Verified:** `GET /upgrade/history?org=appscode` returned `200` against +> `appscode` (empty list `[]` — no upgrades recorded) on 2026-07-14. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/upgrade/history?org=appscode" +``` + +--- + +## GET /upgrade/current-version + +Returns the currently installed ACE platform version (the `ace-installer` Helm +release version). + +- **Auth:** token; site-admin org authz `view_upgrade_history:org`. +- **Query parameters:** `org` (see above). + +**Response — `200 OK`.** + +```json +{ + "version": "v2026.6.19" +} +``` + +| Field | Type | Description | +|---|---|---| +| `version` | string | Currently installed platform version. | + +Returns `400` when no version can be determined. + +> **Verified:** `GET /upgrade/current-version?org=appscode` returned `200` +> against `appscode` (`{"version":"v2026.6.19"}`) on 2026-07-14. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/upgrade/current-version?org=appscode" +``` + +--- + +## POST /upgrade + +Triggers an ACE platform upgrade. The request is a `multipart/form-data` body +carrying the target version, a Helm values file, and an optional flag to use the +latest upgrader image. The upgrade runs asynchronously; poll `GET /upgrade/status` +for progress. + +- **Auth:** token; site-admin org authz `upgrade_platform:org`. +- **Query parameters:** `org` (see above). + +**Request body — `multipart/form-data` (`UpgradeOptions`):** + +| Field | Type | Required | Description | +|---|---|---|---| +| `version` | string | yes | Target upgrade version. May be overridden by an `installerVersion` field inside the uploaded values file. | +| `valuesFile` | file (binary) | no | Helm values file (`values.yaml`) applied for the upgrade. | +| `useLatestImage` | boolean | no | When true, use the latest upgrader image for the target version. | + +**Response.** `200` when the upgrade job is accepted and started. Returns `422` +for an invalid form or values file, and `403` when the caller lacks +`upgrade_platform:org` authorization. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + -F "version=v2026.6.19" \ + -F "valuesFile=@values.yaml" \ + -F "useLatestImage=false" \ + "https:///api/v1/upgrade?org=appscode" +``` + +> Not verified live: this is a mutating (`POST`) endpoint and is documented from +> the schema only. diff --git a/docs/platform/api/administration/_index.md b/docs/platform/api/administration/_index.md new file mode 100644 index 0000000..0acbd3b --- /dev/null +++ b/docs/platform/api/administration/_index.md @@ -0,0 +1,36 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-administration + name: Administration + parent: api + weight: 30 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Administration + +The Administration APIs cover two admin surfaces plus the platform's site-settings +routes. All paths are served under the `/api/v1` prefix. + +- **Administrative-org admin** (`/api/v1/admin/*`) — user and organization management + performed by admins of the platform's administrative organization. +- **Site admin console** (`/api/v1/accounts/admin/*`) — the endpoints powering the + ACE site-administration UI: usage analytics, users, organizations, clusters, and + authentication-source management. +- **Site settings** (`/allowed-domains`, `/disable-registration`, `/branding`) — a + small set of global settings whose read endpoints are **public** and whose write + endpoints require site-admin (or org-admin, for branding) authorization. + +Almost every write endpoint (and every admin read endpoint) requires **org context**, +supplied via the `?org=` query parameter, plus a relationship-based +authorization check. The tables on each page state the exact authorization relation +required. + +## Pages + +- [Administrative-Org Admin](../admin-org.md) — `/api/v1/admin/*`: manage users and their organizations. +- [Site Admin Console](../site-admin-console.md) — `/api/v1/accounts/admin/*`: dashboard, users, orgs, clusters, auth sources. +- [Site Settings](../site-settings.md) — `/allowed-domains`, `/disable-registration`, `/branding`. diff --git a/docs/platform/api/administration/admin-org.md b/docs/platform/api/administration/admin-org.md new file mode 100644 index 0000000..8acb5d3 --- /dev/null +++ b/docs/platform/api/administration/admin-org.md @@ -0,0 +1,321 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-administration-admin-org + name: Administrative-Org Admin + parent: api-administration + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Administrative-Org Admin + +User and organization management performed by admins of the platform's +**administrative organization**. All paths below are relative to `/api/v1`. + +**Auth:** every endpoint requires a valid token, an organization supplied via the +`?org=` query parameter, and the `admin_of_administrative_org` authorization +relation. Send the token as a header: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/admin/orgs?org=appscode" +``` + +All endpoints accept the common **query parameter**: + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `org` | string | yes | Organization slug providing org context (resolved from `?org=`). | + +--- + +## Organizations + +### GET /admin/orgs + +List all organizations on the platform. + +- **Auth:** token + `?org=` + `admin_of_administrative_org`. +- **Response:** `200` — an array of `Organization` objects. + +```json +[ + { + "id": 3, + "username": "appscode", + "full_name": "", + "avatar_url": "https:///accounts/avatars?obj=avatars/3-", + "description": "", + "website": "", + "location": "", + "rancherManagementClusterEndPoint": "", + "visibility": "public", + "orgType": 6 + } +] +``` + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +--- + +## Users + +### GET /admin/users + +List all users on the platform. + +- **Auth:** token + `?org=` + `admin_of_administrative_org`. +- **Response:** `200` — an array of `User` objects. + +```json +[ + { + "id": 5, + "login": "example-user", + "username": "example-user", + "full_name": "Example User", + "email": "user@example.com", + "avatar_url": "https:///accounts/avatars?obj=avatars/5-", + "is_admin": false, + "active": true, + "type": 0, + "created": "2026-01-01T00:00:00Z", + "last_login": "2026-07-01T00:00:00Z" + } +] +``` + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +### POST /admin/users + +Create a user. + +- **Auth:** token + `?org=` + `admin_of_administrative_org`. +- **Request body:** `CreateUserOption`. + +```json +{ + "username": "example-user", + "email": "user@example.com", + "password": "", + "full_name": "Example User", + "login_name": "example-user", + "source_id": 0, + "must_change_password": true, + "send_notify": true +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `username` | string | yes | The new user's username. | +| `email` | string | yes | Primary email address. | +| `password` | string | yes | Initial password. | +| `full_name` | string | no | Display name. | +| `login_name` | string | no | External login name (for non-local auth sources). | +| `source_id` | int64 | no | Authentication source ID (0 = built-in). | +| `must_change_password` | boolean | no | Force a password change on first login. | +| `send_notify` | boolean | no | Send a registration notification email. | + +- **Response:** `201` — the created `User`. + +### PATCH /admin/users/{username} + +Edit an existing user. + +- **Auth:** token + `?org=` + `admin_of_administrative_org`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Username of the user to edit. | + +- **Request body:** `EditUserOption`. + +```json +{ + "email": "user@example.com", + "full_name": "Example User", + "active": true, + "admin": false, + "prohibit_login": false, + "allow_create_organization": true +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `email` | string | yes | Primary email address. | +| `source_id` | int64 | no | Authentication source ID. | +| `login_name` | string | no | External login name. | +| `full_name` | string | no | Display name. | +| `password` | string | no | New password (if changing). | +| `must_change_password` | boolean | no | Force a password change on next login. | +| `website` | string | no | Website URL. | +| `location` | string | no | Location. | +| `active` | boolean | no | Whether the account is active. | +| `admin` | boolean | no | Grant platform-admin. | +| `allow_git_hook` | boolean | no | Allow git hooks. | +| `allow_import_local` | boolean | no | Allow importing local repositories. | +| `prohibit_login` | boolean | no | Prevent the user from signing in. | +| `allow_create_organization` | boolean | no | Allow the user to create organizations. | + +- **Response:** `200` — the updated `User`. + +### DELETE /admin/users/{username} + +Delete a user. + +- **Auth:** token + `?org=` + `admin_of_administrative_org`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Username of the user to delete. | + +- **Response:** `204` — no content. + +### POST /admin/users/{username}/update + +Update a user's profile as admin. + +- **Auth:** token + `?org=` + `admin_of_administrative_org`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Username of the user to update. | + +- **Request body:** `Profile`. + +```json +{ + "name": "example-user", + "full_name": "Example User", + "email": "user@example.com", + "keep_email_private": false, + "website": "https://example.com", + "location": "Earth", + "language": "en-US", + "description": "Platform user" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | no | Username. | +| `full_name` | string | no | Display name. | +| `email` | string | no | Primary email. | +| `keep_email_private` | boolean | no | Hide the email from public profile. | +| `website` | string | no | Website URL. | +| `location` | string | no | Location. | +| `language` | string | no | Preferred language/locale. | +| `description` | string | no | Profile description. | + +- **Response:** `200` — the updated `Profile`. + +### POST /admin/users/{username}/change-password + +Change a user's password as admin. + +- **Auth:** token + `?org=` + `admin_of_administrative_org`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Username of the user. | + +- **Request body:** `UpdatePasswordParams`. + +```json +{ + "old_password": "", + "password": "", + "retype": "" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `old_password` | string | no | Current password. | +| `password` | string | no | New password. | +| `retype` | string | no | New password, confirmed. | + +- **Response:** `200` — password updated. + +### GET /admin/users/{username}/orgs + +List the organizations a user belongs to. + +- **Auth:** token + `?org=` + `admin_of_administrative_org`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Username of the user. | + +- **Response:** `200` — a list of organizations (the response shape is delegated to + the org listing handler; it is returned as an untyped JSON object/array). + +> **Verified:** `GET` returned `200` against `appscode` (user `appscode`) on 2026-07-14. + +### POST /admin/users/{username}/orgs + +Create an organization owned by the given user. + +- **Auth:** token + `?org=` + `admin_of_administrative_org`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Username that will own the new organization. | + +- **Request body:** `CreateOrgOption`. + +```json +{ + "username": "new-org", + "full_name": "New Org", + "description": "Example organization", + "website": "https://example.com", + "location": "Earth", + "orgType": "public", + "visibility": "public" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `username` | string | yes | Organization slug. | +| `full_name` | string | no | Display name. | +| `description` | string | no | Description. | +| `website` | string | no | Website URL. | +| `location` | string | no | Location. | +| `orgType` | string | no | One of `public` (default), `limited`, `private`. | +| `rancherManagementClusterEndPoint` | string | no | Rancher management cluster endpoint. | +| `visibility` | string | no | One of ``, `public`, `limited`, `private`. | + +- **Response:** `201` — the created `Organization`. + +### GET /admin/users/{uid} + +Get user information by numeric user ID. + +- **Auth:** token + `?org=` + `admin_of_administrative_org`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `uid` | int64 | Numeric user ID. | + +> Note: this shares the `/admin/users/{...}` path with the username-based routes +> above; supply a numeric ID here to look a user up by ID. + +- **Response:** `200` — a `User` object. + +> **Verified:** returned `404` against `appscode` (uid `1`) on 2026-07-14 — no user with that ID exists; the endpoint is reachable and authorized. diff --git a/docs/platform/api/administration/site-admin-console.md b/docs/platform/api/administration/site-admin-console.md new file mode 100644 index 0000000..6b1b0ae --- /dev/null +++ b/docs/platform/api/administration/site-admin-console.md @@ -0,0 +1,486 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-administration-site-admin-console + name: Site Admin Console + parent: api-administration + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Site Admin Console + +The endpoints powering the ACE site-administration UI: usage analytics, users, +organizations, clusters, and authentication-source management. All paths below are +relative to `/api/v1`. + +**Auth:** every endpoint requires a valid token, an organization supplied via the +`?org=` query parameter, membership of that organization, and (for most +endpoints) a specific `:site_admin` authorization relation named per endpoint below. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/accounts/admin/users?org=appscode" +``` + +All endpoints accept the common **query parameter**: + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `org` | string | yes | Organization slug providing org context (resolved from `?org=`). | + +Several list endpoints return raw internal records (`models.User`, +`models.Organization`, `models.ClusterInfo`, `models.LoginSource`, ...). In the +OpenAPI these are represented generically as untyped JSON objects; the examples below +show the salient fields only. + +--- + +## Dashboard & configuration + +### GET /accounts/admin + +Site administration usage-analytics dashboard. + +- **Auth:** token + `?org=` + membership + `view_usage_analytics:site_admin`. +- **Response:** `200` — an untyped JSON object with `stats` and `sysStatus` keys. + +```json +{ + "stats": { "userCount": 12, "orgCount": 5, "clusterCount": 3 }, + "sysStatus": { "uptime": "5d3h", "goroutines": 210 } +} +``` + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +### GET /accounts/admin/config + +Site administration configuration page. Renders an HTML template rather than a JSON +body. + +- **Auth:** token + `?org=` + membership + site-admin. +- **Response:** `200` — `text/html`. + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14 (HTML page). + +### POST /accounts/admin/config/test_mail + +Send a test email, then redirect to the config page. + +- **Auth:** token + `?org=` + membership + `send_test_mails:site_admin`. +- **Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `email` | string | no | Destination address for the test email. | + +- **Response:** `302` — redirect to the config page. + +### GET /accounts/admin/monitor + +Site administration monitor page. Renders an HTML template rather than a JSON body. + +- **Auth:** token + `?org=` + membership + site-admin. +- **Response:** `200` — `text/html`. + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14 (HTML page). + +--- + +## Users + +### GET /accounts/admin/users + +List all users. + +- **Auth:** token + `?org=` + membership + `view_users:site_admin`. +- **Response:** `200` — an array of raw user records. + +```json +[ + { + "ID": 5, + "Name": "example-user", + "FullName": "Example User", + "Email": "user@example.com", + "IsActive": true, + "IsAdmin": false + } +] +``` + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +### GET /accounts/admin/users/deleted_accounts + +List deactivated user accounts. + +- **Auth:** token + `?org=` + membership + `view_deleted_members:site_admin`. +- **Response:** `200` — an array of raw user records (deactivated). + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +### POST /accounts/admin/users/deleted_accounts/{id}/reactivate + +Reactivate a deactivated user. + +- **Auth:** token + `?org=` + membership + `reactivate_members:site_admin`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | int64 | Numeric user ID. | + +- **Response:** `200` — user reactivated. + +### POST /accounts/admin/users/new + +Create a new user. + +- **Auth:** token + `?org=` + membership + `create_users:site_admin`. +- **Request body:** `AdminCreateUserPayload`. + +```json +{ + "loginType": "local", + "userName": "example-user", + "email": "user@example.com", + "fullName": "Example User", + "loginName": "example-user", + "password": "", + "sendNotify": true, + "mustChangePassword": true +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `loginType` | string | yes | Authentication source type (e.g. `local`). | +| `userName` | string | yes | The new user's username. | +| `email` | string | yes | Primary email address. | +| `loginName` | string | no | External login name. | +| `fullName` | string | no | Display name. | +| `password` | string | no | Initial password. | +| `sendNotify` | boolean | no | Send a registration notification email. | +| `mustChangePassword` | boolean | no | Force a password change on first login. | + +- **Response:** `201` — user created. + +### POST /accounts/admin/users/{userid} + +Edit a user. + +- **Auth:** token + `?org=` + membership + `update_users:site_admin`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `userid` | int64 | Numeric user ID. | + +- **Request body:** `AdminEditUserPayload`. + +```json +{ + "loginType": "local", + "email": "user@example.com", + "fullName": "Example User", + "active": true, + "admin": false, + "prohibitLogin": false, + "allowCreateOrganization": true, + "disableTwoFactor": false +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `loginType` | string | yes | Authentication source type. | +| `email` | string | yes | Primary email address. | +| `loginName` | string | no | External login name. | +| `fullName` | string | no | Display name. | +| `password` | string | no | New password (if changing). | +| `website` | string | no | Website URL. | +| `location` | string | no | Location. | +| `active` | boolean | no | Whether the account is active. | +| `admin` | boolean | no | Grant platform-admin. | +| `allowGitHook` | boolean | no | Allow git hooks. | +| `allowImportLocal` | boolean | no | Allow importing local repositories. | +| `allowCreateOrganization` | boolean | no | Allow the user to create organizations. | +| `prohibitLogin` | boolean | no | Prevent the user from signing in. | +| `disableTwoFactor` | boolean | no | Disable the user's two-factor authentication. | + +- **Response:** `200` — user updated. + +### POST /accounts/admin/users/{userid}/delete + +Deactivate a user. + +- **Auth:** token + `?org=` + membership + `delete_users:site_admin`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `userid` | int64 | Numeric user ID. | + +- **Response:** `200` — user deactivated. Returns `400` with a `message` if the user + still owns organizations. + +### DELETE /accounts/admin/delete/inactive-users + +Purge deactivated users that have been inactive for more than 30 days. + +- **Auth:** token + `?org=` + membership + `purge_deactivated_users:site_admin`. +- **Response:** `200` — inactive users purged. + +--- + +## Organizations + +### GET /accounts/admin/orgs + +List all organizations. + +- **Auth:** token + `?org=` + membership + `view_orgs:site_admin`. +- **Response:** `200` — an array of raw organization records. + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +### GET /accounts/admin/orgs/orphaned/ + +List orphaned organizations (organizations with no remaining owner). + +- **Auth:** token + `?org=` + membership. +- **Response:** `200` — an array of `Organization` objects. + +> **Verified:** returned `400` ("invalid org id") against `appscode` on 2026-07-14 — the handler rejected the request context on this deployment; the route is reachable and authorized. + +### DELETE /accounts/admin/orgs/orphaned/delete/{id} + +Delete an orphaned organization. + +- **Auth:** token + `?org=` + membership + `delete:orphaned-org`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | int64 | Numeric organization ID. | + +- **Response:** `200` — organization deleted. + +--- + +## Clusters + +### GET /accounts/admin/clusters + +List all clusters known to the platform. + +- **Auth:** token + `?org=` + membership. +- **Response:** `200` — an array of raw cluster records (`models.ClusterInfo`). + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +--- + +## Authentication sources + +Manage the platform's login sources (LDAP, PAM, SMTP, OAuth2/OIDC, ...). + +### GET /accounts/admin/auths + +List authentication sources. + +- **Auth:** token + `?org=` + membership + `site_admin_editor_authn_source`. +- **Response:** `200` — an array of raw login-source records. + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +### GET /accounts/admin/auths/auth-types + +List the available authentication source types (name/type pairs). + +- **Auth:** token + `?org=` + membership + `site_admin_editor_authn_source`. +- **Response:** `200` — an array of type descriptors. + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +### POST /accounts/admin/auths/new + +Create an authentication source. + +- **Auth:** token + `?org=` + membership + `site_admin_editor_authn_source`. +- **Request body:** `AuthenticationPayload` (fields vary by source type; the common + ones are shown below — LDAP, SMTP, and OAuth2/OIDC fields are all part of the same + payload). + +```json +{ + "type": 2, + "name": "corporate-ldap", + "host": "ldap.example.com", + "port": 636, + "bindDN": "cn=admin,dc=example,dc=com", + "bindPassword": "", + "userBase": "ou=users,dc=example,dc=com", + "attributeUsername": "uid", + "attributeMail": "mail", + "isActive": true, + "tls": true, + "skipVerify": false +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | yes | Display name of the source. | +| `id` | int64 | no | Source ID (on edit). | +| `type` | integer | no | Numeric source type (LDAP, SMTP, PAM, OAuth2, ...). | +| `host` | string | no | Server host (LDAP/SMTP). | +| `port` | integer | no | Server port. | +| `bindDN` | string | no | LDAP bind DN. | +| `bindPassword` | string | no | LDAP bind password. | +| `userBase` | string | no | LDAP user search base. | +| `userDN` | string | no | LDAP user DN pattern. | +| `attributeUsername` | string | no | LDAP username attribute. | +| `attributeName` | string | no | LDAP given-name attribute. | +| `attributeSurname` | string | no | LDAP surname attribute. | +| `attributeMail` | string | no | LDAP email attribute. | +| `attributeSSHPublicKey` | string | no | LDAP SSH public-key attribute. | +| `attributesInBind` | boolean | no | Fetch attributes during bind. | +| `usePagedSearch` | boolean | no | Use LDAP paged search. | +| `searchPageSize` | integer | no | Paged-search page size. | +| `filter` | string | no | LDAP user filter. | +| `adminFilter` | string | no | LDAP admin filter. | +| `isActive` | boolean | no | Whether the source is enabled. | +| `isSyncEnabled` | boolean | no | Enable periodic user sync. | +| `smtpAuth` | string | no | SMTP auth mechanism. | +| `smtpHost` | string | no | SMTP host. | +| `smtpPort` | integer | no | SMTP port. | +| `allowedDomains` | string | no | Comma-separated allowed email domains. | +| `securityProtocol` | integer | no | Security protocol (none/StartTLS/LDAPS). | +| `tls` | boolean | no | Use TLS. | +| `skipVerify` | boolean | no | Skip TLS certificate verification. | +| `pamServiceName` | string | no | PAM service name. | +| `oauth2Provider` | string | no | OAuth2 provider name. | +| `oauth2Key` | string | no | OAuth2 client key/ID. | +| `oauth2Secret` | string | no | OAuth2 client secret. | +| `openIDConnectAutoDiscoveryURL` | string | no | OIDC auto-discovery URL. | +| `oauth2UseCustomURL` | boolean | no | Use custom OAuth2 URLs. | +| `oauth2TokenURL` | string | no | Custom token URL. | +| `oauth2AuthURL` | string | no | Custom authorize URL. | +| `oauth2ProfileURL` | string | no | Custom profile URL. | +| `oauth2EmailURL` | string | no | Custom email URL. | + +- **Response:** `201` — authentication source created. + +### GET /accounts/admin/auths/{authid} + +Get a single authentication source. + +- **Auth:** token + `?org=` + membership + `site_admin_editor_authn_source`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `authid` | int64 | Numeric authentication source ID. | + +- **Response:** `200` — a raw login-source record. + +> **Verified:** returned `500` against `appscode` (authid `1`) on 2026-07-14 — no login source with that ID exists on this deployment; the route is reachable and authorized. + +### POST /accounts/admin/auths/{authid} + +Edit an authentication source. + +- **Auth:** token + `?org=` + membership + `site_admin_editor_authn_source`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `authid` | int64 | Numeric authentication source ID. | + +- **Request body:** `AuthenticationPayload` (same fields as create, above). +- **Response:** `200` — authentication source updated. + +### POST /accounts/admin/auths/{authid}/delete + +Delete an authentication source. + +- **Auth:** token + `?org=` + membership + `site_admin_editor_authn_source`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `authid` | int64 | Numeric authentication source ID. | + +- **Response:** `200` — authentication source deleted. + +--- + +## External OAuth2 sources + +Manage external OAuth2/social-login providers. + +### GET /accounts/admin/external_oauth + +List external OAuth2 authentication sources. + +- **Auth:** token + `?org=` + membership + `site_admin_editor_external_authn_source`. +- **Response:** `200` — an array of raw external OAuth2 application records. + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +### POST /accounts/admin/external_oauth/new + +Create an external OAuth2 authentication source. + +- **Auth:** token + `?org=` + membership + `site_admin_editor_external_authn_source`. +- **Request body:** `ExternalOAuth2AppPayload`. + +```json +{ + "provider": "github", + "clientID": "", + "clientSecret": "", + "callbackURL": "https:///user/oauth2/github/callback" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `provider` | string | no | Provider name (e.g. `github`, `google`). | +| `clientID` | string | no | OAuth2 client ID. | +| `clientSecret` | string | no | OAuth2 client secret. | +| `callbackURL` | string | no | OAuth2 callback/redirect URL. | + +- **Response:** `201` — external OAuth2 source created. + +### POST /accounts/admin/external_oauth/{provider} + +Edit an external OAuth2 authentication source. + +- **Auth:** token + `?org=` + membership + `site_admin_editor_external_authn_source`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `provider` | string | Provider name to edit. | + +- **Request body:** `ExternalOAuth2AppPayload` (same fields as create, above). +- **Response:** `200` — external OAuth2 source updated. + +### POST /accounts/admin/external_oauth/{provider}/delete + +Delete an external OAuth2 authentication source. + +- **Auth:** token + `?org=` + membership + `site_admin_editor_external_authn_source`. +- **Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `provider` | string | Provider name to delete. | + +- **Response:** `200` — external OAuth2 source deleted. diff --git a/docs/platform/api/administration/site-settings.md b/docs/platform/api/administration/site-settings.md new file mode 100644 index 0000000..4f00585 --- /dev/null +++ b/docs/platform/api/administration/site-settings.md @@ -0,0 +1,198 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-administration-site-settings + name: Site Settings + parent: api-administration + weight: 30 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Site Settings + +Global platform settings: branding, the email-domain whitelist, and the +new-user-registration toggle. All paths below are relative to `/api/v1`. + +**Auth:** each of these settings has a **public** read endpoint (no authentication) +and a write endpoint gated by a site-admin (or, for branding, org-admin) +authorization relation. Write endpoints require org context via `?org=`. + +``` +curl https:///api/v1/branding +``` + +--- + +## Branding + +### GET /branding + +Get the current branding configuration (logo, favicons, app name, colors). + +- **Auth:** public. +- **Response:** `200` — a `BrandingResponse` object; `304` if not modified. + +```json +{ + "logo": "data:image/png;base64,", + "favicons": { "16x16": "data:image/png;base64," }, + "primaryColor": "#326ce5", + "runMode": "prod", + "deploymentType": "Hosted", + "isOfflineInstaller": false, + "showAppTag": true, + "appName": "ACE" +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `logo` | string | Base64-encoded logo image (`data:` URI). | +| `favicons` | object | Map of favicon sizes to base64-encoded images. | +| `primaryColor` | string | Primary UI color (hex). | +| `runMode` | string | Server run mode. | +| `deploymentType` | string | Deployment type (e.g. `Hosted`). | +| `isOfflineInstaller` | boolean | Whether this is an offline-installer deployment. | +| `showAppTag` | boolean | Whether to show the app tag/badge. | +| `appName` | string | Application display name. | + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14 (logo returned as a base64 `data:image/png` URI). + +### POST /branding + +Update the branding options. + +- **Auth:** token + membership of the organization + `edit_branding_options:org`. +- **Request body:** `BrandingOptions`. + +```json +{ + "logo": "data:image/png;base64,", + "favicon": "data:image/png;base64,", + "primaryColor": "#326ce5", + "showAppTag": true, + "appName": "ACE" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `logo` | string | no | Base64-encoded logo image. | +| `favicon` | string | no | Base64-encoded favicon image. | +| `primaryColor` | string | no | Primary UI color (hex). | +| `showAppTag` | boolean | no | Whether to show the app tag/badge. | +| `appName` | string | no | Application display name. | + +- **Response:** `200` — branding options updated. `400` for an invalid branding option. + +--- + +## Allowed email domains + +The whitelist of email domains permitted to register on the platform. + +### GET /allowed-domains + +List the configured email-domain whitelist. + +- **Auth:** public. +- **Response:** `200` — an array of domain strings (empty when no whitelist is set). + +```json +["example.com", "acme.io"] +``` + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14 (empty list `[]` — no whitelist configured). + +### POST /allowed-domains + +Add an email domain to the whitelist. + +- **Auth:** token + `?org=` + `edit_allowed_domains:site_admin`. +- **Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `org` | string | yes | Organization slug providing org context. | + +- **Request body:** `DomainOpts`. + +```json +{ "name": "example.com" } +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | no | The email domain to add. | + +- **Response:** `200` — domain added. `400` for an invalid domain name; `409` if the + domain already exists. + +### PATCH /allowed-domains + +Remove an email domain from the whitelist. + +- **Auth:** token + `?org=` + `edit_allowed_domains:site_admin`. +- **Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `org` | string | yes | Organization slug providing org context. | + +- **Request body:** `DomainOpts`. + +```json +{ "name": "example.com" } +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | no | The email domain to remove. | + +- **Response:** `200` — domain removed. `400` if the domain is not in the whitelist. + +--- + +## User registration + +### GET /disable-registration + +Get whether new-user registration is disabled. + +- **Auth:** public. +- **Response:** `200` — a `RegistrationOpts` object. + +```json +{ "disableRegistration": false } +``` + +| Field | Type | Description | +|-------|------|-------------| +| `disableRegistration` | boolean | `true` if new-user registration is disabled. | + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14 (`{"disableRegistration":false}`). + +### POST /disable-registration + +Enable or disable new-user registration. + +- **Auth:** token + `?org=` + `update_user_registration:site_admin`. +- **Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `org` | string | yes | Organization slug providing org context. | + +- **Request body:** `RegistrationOpts`. + +```json +{ "disableRegistration": true } +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `disableRegistration` | boolean | no | Set to `true` to disable new-user registration. | + +- **Response:** `200` — registration status updated. diff --git a/docs/platform/api/authorization/_index.md b/docs/platform/api/authorization/_index.md new file mode 100644 index 0000000..778da9f --- /dev/null +++ b/docs/platform/api/authorization/_index.md @@ -0,0 +1,31 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-authorization + name: Authorization + parent: api + weight: 40 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Authorization + +The Authorization API exposes ACE's custom role management and permission +inspection, backed by the platform's relationship-based authorization model +(OpenFGA-style checks). It lets you list the permissions the caller holds on a +given object, discover the permissions that can be assigned within an +organization, and create/manage custom roles that bundle permissions and assign +them to teams. + +All endpoints live under the `/api/v1/authz` prefix and require organization +context. That context is **not** taken from the path — it is supplied as a +`?org=` query parameter (for example `?org=appscode`). A valid token +and membership of that organization are required. + +## Pages + +- [Roles & Permissions](../roles-permissions.md) — object + allowed-permissions lookups (single and batch), the available-permissions + catalog, role CRUD, and role principal listings. diff --git a/docs/platform/api/authorization/roles-permissions.md b/docs/platform/api/authorization/roles-permissions.md new file mode 100644 index 0000000..2d9d09c --- /dev/null +++ b/docs/platform/api/authorization/roles-permissions.md @@ -0,0 +1,433 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-authorization-roles-permissions + name: Roles & Permissions + parent: api-authorization + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Roles & Permissions + +This page documents ACE's custom authorization API: inspecting the permissions +the caller holds on an object, discovering assignable permissions, and managing +custom roles. + +All paths on this page are relative to the API root `/api/v1`. The full prefix +for every endpoint here is `/api/v1/authz`. + +## Authentication & org context + +Every endpoint requires a valid personal access token (or access token). Send it +as a header: + +``` +Authorization: token +``` + +In addition, **organization context is mandatory and is supplied via the `?org=` +query parameter** (not the path). For example, `?org=appscode`. Most endpoints +also require that the caller be a member of that organization, and several add a +relationship-based authorization check (`create_role:org`, `view:role`, +`edit:role`, `delete:role`, `viewer:role`) noted per endpoint. + +Error responses use a standard envelope: + +```json +{ + "message": "human-readable error", + "url": "https:///api/swagger" +} +``` + +--- + +## Object allowed-permissions + +These endpoints answer "what may the current requester do to this object?" They +resolve the caller's relationships to the target object and return the list of +permission relations they hold. + +### Object types + +The `objectType` accepted by these endpoints is one of: + +| objectType | Refers to | +|---|---| +| `user` | A user account (the `objectID` must equal the requester's own user ID) | +| `organization` | An organization | +| `team` | A team | +| `cluster` | A cluster | +| `contract` | A billing contract | +| `robot_ac` | A robot account | +| `token` | An access token | + +Any other value yields `400 Bad Request` with an `invalid object type` message. + +### GET /authz/objects/{objectType}/{objID}/allowed-permissions + +Returns the requester's allowed permissions on a single identified object. + +- **Auth:** token (`Authorization: token`, `?token=`, or `?access_token=`) + `?org=` context. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `objectType` | string | The kind of object being inspected. See [Object types](#object-types). | +| `objID` | integer (int64) | The numeric ID of the object. For `user`, must equal the requester's own user ID. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug providing org context. | + +**Response:** `200 OK` — an `AuthObjectAllowedPermissions` object. + +```json +{ + "objectType": "team", + "objectID": 1, + "allowedPermissions": [ + "can_view", + "can_edit", + "can_add_member" + ] +} +``` + +Fields: `objectType` and `objectID` echo the request; `allowedPermissions` is the +list of relation strings the requester holds on that object (empty array if none). +`400` is returned for an invalid object type/ID, `401` if unauthenticated, `403` +if forbidden. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/authz/objects/team/1/allowed-permissions?org=appscode" +``` + +> **Verified:** `GET` returned `200` against `appscode` (org context) on 2026-07-14 for `objectType=team`, `objID=1` (returned `["can_view","can_edit","can_add_member"]`). Note: `objectType=organization` returned `500` in this environment ("Team does not exist"), and an unsupported `objectType` returns `400`. + +### POST /authz/objects/allowed-permissions + +Batch variant of the above: returns the requester's allowed permissions for each +supplied object identifier, in the same order. + +- **Auth:** token + `?org=` context. + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug providing org context. | + +**Request body:** a JSON array of `AuthObjectIdentifier` objects. + +```json +[ + { "objectType": "team", "objectID": 1 }, + { "objectType": "cluster", "objectID": 42 } +] +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `objectType` | string | yes | The kind of object. See [Object types](#object-types). | +| `objectID` | integer (int64) | yes | The numeric ID of the object. | + +**Response:** `200 OK` — a JSON array of `AuthObjectAllowedPermissions`, one entry +per requested identifier. + +```json +[ + { + "objectType": "team", + "objectID": 1, + "allowedPermissions": ["can_view", "can_edit", "can_add_member"] + }, + { + "objectType": "cluster", + "objectID": 42, + "allowedPermissions": ["can_view_kubeconfig"] + } +] +``` + +`400` for an invalid object type/ID in any element, `401` unauthenticated, `403` +forbidden, `422` for a malformed body. + +--- + +## Available permissions + +### GET /authz/roles/available_permissions + +Returns the catalog of permissions that can be assigned within the caller's +organization context — the building blocks used when creating or updating a role. + +- **Auth:** token + `?org=` context + membership of that organization. + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug providing org context. | + +**Response:** `200 OK`. The body is an `authzstores.VirtualPermissionsData` +structure (represented generically in the OpenAPI schema). In practice it is a +`permissions` array where each entry has a `namespace`, an `action`, a +human-readable `description`, and an optional `associated` list of permissions +that are implied or required alongside it. + +```json +{ + "permissions": [ + { + "namespace": "org_mgmt", + "action": "edit", + "description": "Update organization details and configuration" + }, + { + "namespace": "cluster_mgmt", + "action": "view clusters", + "description": "View clusters associated with the organization and their details", + "associated": [ + { "namespace": "cluster_mgmt", "action": "import clusters", "required": false } + ] + } + ] +} +``` + +The `namespace`/`action` pairs are exactly the values you supply in a role's +`permissions` list (see below). `401` unauthenticated, `403` forbidden. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/authz/roles/available_permissions?org=appscode" +``` + +> **Verified:** `GET` returned `200` against `appscode` (org context) on 2026-07-14; returned a `permissions` catalog spanning namespaces such as `org_mgmt` and `cluster_mgmt`. + +--- + +## Roles + +Custom roles bundle a set of permissions and can be attached to one or more teams +within an organization. + +### GET /authz/roles + +Lists the custom roles defined in the organization. + +- **Auth:** token + `?org=` context + membership of that organization. + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug providing org context. | + +**Response:** `200 OK` — an array of `RoleResponse` objects. + +```json +[ + { + "id": 12, + "name": "Cluster Operators", + "owner_id": 3, + "description": "Can view and reconfigure clusters", + "permissions": [ + { "namespace": "cluster_mgmt", "action": "view clusters" }, + { "namespace": "cluster_mgmt", "action": "reconfigure clusters" } + ], + "team_ids": [7], + "created_at": "2026-07-01T10:00:00Z", + "updated_at": "2026-07-01T10:00:00Z" + } +] +``` + +`401` unauthenticated, `403` forbidden. An organization with no custom roles +returns an empty array `[]`. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/authz/roles?org=appscode" +``` + +> **Verified:** `GET` returned `200` against `appscode` (org context) on 2026-07-14; the response was `[]` (no custom roles defined in this org). + +### POST /authz/roles + +Creates a custom role. + +- **Auth:** token + `?org=` context + membership + the `create_role:org` authorization relation. + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug providing org context. | + +**Request body:** a `CreateRoleRequest`. + +```json +{ + "name": "Cluster Operators", + "description": "Can view and reconfigure clusters", + "permissions": [ + { "namespace": "cluster_mgmt", "action": "view clusters" }, + { "namespace": "cluster_mgmt", "action": "reconfigure clusters" } + ], + "teamIDs": [7] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `name` | string | yes | Display name of the role. | +| `permissions` | array of `PermissionInput` | yes | Permissions granted by the role. | +| `description` | string | no | Human-readable description. | +| `teamIDs` | array of integer (int64) | no | Teams the role is assigned to. | + +Each `PermissionInput` has a `namespace` (a `PermissionNamespace` value) and an +`action`; use the pairs returned by +[available_permissions](#get-authzrolesavailablepermissions). + +**Response:** `201 Created` — the created `RoleResponse` (same shape as the list +entry above, with server-assigned `id`, `owner_id`, and timestamps). `400` +invalid request, `401` unauthenticated, `403` forbidden (missing +`create_role:org`), `422` validation error. + +### GET /authz/roles/{id} + +Fetches a single role by ID. + +- **Auth:** token + `?org=` context + membership + the `view:role` authorization relation. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `id` | integer (int64) | The role ID. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug providing org context. | + +**Response:** `200 OK` — a `RoleResponse` (see the list example above). `401` +unauthenticated, `403` forbidden (missing `view:role`), `404` role not found. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/authz/roles/12?org=appscode" +``` + +> **Verified:** `GET /authz/roles/1?org=appscode` returned `403` against `appscode` on 2026-07-14 — the caller lacks the `view:role` relation on that role (no matching role exists in this org, so no relation is granted). + +### PUT /authz/roles/{id} + +Updates a role. + +- **Auth:** token + `?org=` context + membership + the `edit:role` authorization relation. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `id` | integer (int64) | The role ID. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug providing org context. | + +**Request body:** an `UpdateRoleRequest` (all fields optional; supplied fields +replace the current values). + +```json +{ + "name": "Cluster Operators", + "description": "Can view, reconfigure and connect to clusters", + "permissions": [ + { "namespace": "cluster_mgmt", "action": "view clusters" }, + { "namespace": "cluster_mgmt", "action": "reconfigure clusters" }, + { "namespace": "cluster_mgmt", "action": "connect to clusters" } + ], + "teamIDs": [7, 8] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `name` | string | no | New display name. | +| `description` | string | no | New description. | +| `permissions` | array of `PermissionInput` | no | Replacement permission set. | +| `teamIDs` | array of integer (int64) | no | Replacement team assignments. | + +**Response:** `200 OK` — the updated `RoleResponse`. `400` invalid request, `401` +unauthenticated, `403` forbidden (missing `edit:role`), `404` role not found, +`422` validation error. + +### DELETE /authz/roles/{id} + +Deletes a role. + +- **Auth:** token + `?org=` context + membership + the `delete:role` authorization relation. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `id` | integer (int64) | The role ID. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug providing org context. | + +**Response:** `204 No Content` on success. `401` unauthenticated, `403` forbidden +(missing `delete:role`), `404` role not found. + +--- + +## Role principals + +### GET /authz/roles/{id}/principals + +Lists the principals (users/teams) assigned to a role. + +- **Auth:** token + `?org=` context + membership + the `viewer:role` authorization relation. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `id` | integer (int64) | The role ID. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug providing org context. | + +**Response:** `200 OK` — an array. The body is the raw output of +`models.ListPrincipalsOfARole` (represented generically in the OpenAPI schema), +one entry per principal assigned to the role. `401` unauthenticated, `403` +forbidden (missing `viewer:role`). + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/authz/roles/12/principals?org=appscode" +``` + +> **Verified:** `GET /authz/roles/1/principals?org=appscode` returned `403` against `appscode` on 2026-07-14 — the caller lacks the `viewer:role` relation (no matching role exists in this org). diff --git a/docs/platform/api/billing-dashboard/_index.md b/docs/platform/api/billing-dashboard/_index.md new file mode 100644 index 0000000..5564fd3 --- /dev/null +++ b/docs/platform/api/billing-dashboard/_index.md @@ -0,0 +1,58 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-billing-dashboard + name: Billing Dashboard + parent: api + weight: 130 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Billing Dashboard + +APIs that power the license, usage, and billing screens of the ACE web console. +They report on licensed users and their clusters, per-cluster licenses and licensed +products, resource event histories, marketplace subscriptions, system-outage +records, and month-by-month usage summaries (KubeDB, KubeStash, KubeVault, Voyager) +and DBaaS namespace billing reports. + +All routes are served under the `/api/v1` prefix. Every endpoint in this group +authenticates with a personal access token sent as `Authorization: token ` +(it may also be supplied as a `token` or `access_token` query parameter). + +> **Billing-enabled deployments only.** This entire group is registered only when +> the `b3` backend runs with billing enabled. On a deployment without billing, all +> of these routes return `404 Not Found` — even with a valid token. The +> owner-scoped and usage-report routes additionally resolve the acting organization +> from the `org` query parameter, so include `?org=` on those calls. + +## Authorization tiers + +Routes in this group fall into three authorization tiers: + +- **Site-admin (licensed users):** the `/dashboard/users/*`, + `/dashboard/clusters/:cid/licenses/active`, `/dashboard/system-outages/*`, and + `/dashboard/marketplaces/*` routes require site-admin authorization + (`view_licensed_users`, `view_system_outages`, or `view_marketplace_usage`). +- **Owner-scoped (`view:contracts`):** the `/dashboard/clusters/*` routes resolve + the owner from `?org=` and require the `view:contracts` permission on that + organization — this is the "self-service" billing dashboard an org sees for its + own clusters. +- **Usage analytics (site-admin):** the `/dashboard/summary/*` usage-report and + download routes require `view_usage_analytics:site_admin`; the `/dbaas/billing/*` + reports require org ownership when an org is set. + +## Pages + +- [Admin Billing Dashboard](../admin-dashboard.md) — the + site-admin `/api/v1/dashboard/*` routes: licensed users, their clusters, + per-cluster licenses and licensed products, resource/event histories, marketplace + subscriptions, and system-outage records. +- [User Billing Dashboard](../user-dashboard.md) — the + owner-scoped `/api/v1/dashboard/clusters/*` routes (`view:contracts`): an + organization's own active clusters, licenses, licensed products, and event counts. +- [Usage Reports](../usage-reports.md) — the + `/api/v1/dashboard/summary/*` monthly usage-report views and PDF download, plus + the `/api/v1/dbaas/billing/*` namespace billing reports. diff --git a/docs/platform/api/billing-dashboard/admin-dashboard.md b/docs/platform/api/billing-dashboard/admin-dashboard.md new file mode 100644 index 0000000..4790228 --- /dev/null +++ b/docs/platform/api/billing-dashboard/admin-dashboard.md @@ -0,0 +1,644 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-billing-dashboard-admin-dashboard + name: Admin Billing Dashboard + parent: api-billing-dashboard + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Admin Billing Dashboard + +Site-admin endpoints under `/api/v1/dashboard` that back the platform-wide license +and billing administration screens: licensed users and their clusters, per-cluster +licenses and licensed products, resource/event histories, marketplace +subscriptions, and system-outage records. + +All paths on this page are relative to `/api/v1`. Every endpoint requires +`Authorization: token `, resolves the acting organization from the +`org` query parameter (`?org=`), and requires site-admin authorization on +that org. This whole group is available only on **billing-enabled deployments**. + +> **Verified:** every endpoint on this page returned `404 Not Found` against +> `appscode` on `` on 2026-07-14 — this deployment is not billing-enabled, +> so none of the `/dashboard/*` routes are registered. (Sanity: `GET /version` and +> `GET /user` returned `200` with the same token, confirming the platform and token +> are live.) Response bodies were the standard `{"message":"Not Found"}`. + +Shared conventions on this page: + +- **`uid`** is the numeric user (account) ID; **`cid`** is a cluster UID string; + **`lid`** is a license ID string. +- **`limit`** (query, optional) sets the "active" window: a Go duration such as + `720h` or a `YYYY-MM-DD` date. When omitted it defaults to roughly the last six + months. +- Timestamps in these forms are Unix epoch values (`int64`) unless noted. + +## Licensed users + +### GET /dashboard/users/ + +Lists all users that have ever reported a license to this deployment. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug used to resolve site-admin context. | + +- **Response:** `200 OK` — an array of licensed users. + +```json +[ + { + "username": "alice", + "userType": "user", + "email": "user@example.com", + "userID": 42, + "lastReceivedAt": 1718000000 + } +] +``` + +`403` is returned when the caller is not a site admin; `401` when unauthenticated. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/dashboard/users/?org=appscode" +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled on this deployment. + +### GET /dashboard/users/active + +Lists licensed users that have reported within the `limit` window (defaults to the +last ~6 months). + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug. | +| `limit` | string | no | Activity window: Go duration (e.g. `720h`) or `YYYY-MM-DD` date. | + +- **Response:** `200 OK` — an array of `LicensedUserAPIForm` (same shape as above). + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/users/inactive + +Lists licensed users that have never reported a licensed product. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Response:** `200 OK` — an array of `LicensedUserAPIForm`. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## A user's clusters + +### GET /dashboard/users/{uid}/clusters/ + +Lists cluster information for the given licensed user. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `uid` | integer | User (account) ID. | + +- **Response:** `200 OK` — an array of `ClusterInfo` objects. + +```json +[ + { + "id": 101, + "displayName": "ACE Hub", + "name": "ace", + "uid": "", + "ownerID": 42, + "ownerName": "appscode", + "provider": "GKE", + "kubernetesVersion": "v1.29.4", + "nodeCount": 3, + "createdAt": "2026-01-10T09:00:00Z", + "status": { "...": "rsapi.ClusterStatus (free-form Kubernetes-style object)" } + } +] +``` + +The `status` field is a free-form Kubernetes-style object passed through verbatim. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/users/{uid}/clusters/active + +Lists clusters that reported for the given user within the `limit` window. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** `uid` (integer) — user ID. +- **Query parameters:** `limit` (string, optional) — activity window. +- **Response:** `200 OK` — an array of `ActiveClustersAPIForm`. + +```json +[ + { + "username": "alice", + "clusterID": "", + "firstReceivedAt": 1700000000, + "lastReceivedAt": 1718000000, + "noOfAssociatedContracts": 2 + } +] +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/users/{uid}/clusters/{cid} + +Returns cluster information for a specific user/cluster. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `uid` | integer | User (account) ID. | +| `cid` | string | Cluster UID. | + +- **Response:** `200 OK` — a single `ClusterInfo` object (see above). `404` if the + user/cluster pair is unknown. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## A user's licenses on a cluster + +### GET /dashboard/users/{uid}/clusters/{cid}/licenses/ + +Lists licensed plans associated with the given user and cluster. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** `uid` (integer), `cid` (string). +- **Response:** `200 OK` — an array of `LicensedPlan`. + +```json +[ + { + "uid": 42, + "email": "user@example.com", + "licenseID": "", + "clusters": [""], + "planName": "kubedb-enterprise", + "notBefore": 1700000000, + "notAfter": 1731600000, + "registeredAt": 1700000000, + "createdAt": 1700000000, + "updatedAt": 1718000000 + } +] +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/users/{uid}/clusters/{cid}/licenses/active + +Lists licenses that reported within the `limit` window for the given user and cluster. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** `uid` (integer), `cid` (string). +- **Query parameters:** `limit` (string, optional) — activity window. +- **Response:** `200 OK` — an array of `ActiveLicenseAPIForm`. + +```json +[ + { + "username": "alice", + "email": "user@example.com", + "userId": 42, + "licenseID": "", + "firstReceivedAt": 1700000000, + "lastReceivedAt": 1718000000 + } +] +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/users/{uid}/clusters/{cid}/licenses/{lid} + +Returns a licensed plan together with the latest reported `SiteInfo`. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** `uid` (integer), `cid` (string), `lid` (string) — license ID. +- **Response:** `200 OK` — an object with a `license` (a `LicensedPlan`, see above) + and a `siteinfo` (a kmodules identity `SiteInfo`, a free-form Kubernetes-style + object). + +```json +{ + "license": { "licenseID": "", "planName": "kubedb-enterprise", "clusters": [""] }, + "siteinfo": { "...": "kmodules SiteInfo (free-form Kubernetes object)" } +} +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## Licensed products for a license + +### GET /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products/ + +Lists reported licensed products for the given user/cluster/license. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** `uid` (integer), `cid` (string), `lid` (string). +- **Query parameters:** `limit` (string, optional) — activity window. +- **Response:** `200 OK` — an array of `ReceivedLicensedProduct`. + +```json +[ + { + "userName": "alice", + "userType": "user", + "email": "user@example.com", + "userID": 42, + "clusterID": "", + "licenseID": "", + "productName": "kube-db", + "firstReceivedAt": 1700000000, + "lastReceivedAt": 1718000000 + } +] +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products/{productName} + +Returns the reported licensed product for a specific product. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** `uid` (integer), `cid` (string), `lid` (string), + `productName` (string). +- **Query parameters:** `limit` (string, optional) — activity window. +- **Response:** `200 OK` — a single `ReceivedLicensedProduct` (see above). + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products/{productName}/resources + +Fetches the badger resource history for a product from the member cluster over NATS. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** `uid` (integer), `cid` (string), `lid` (string), + `productName` (string). +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `group` | string | no | Kubernetes API group filter. | +| `resource` | string | no | Kubernetes resource filter. | + +- **Response:** `200 OK` — a `BadgerEntryList` of resource-history entries. Each + entry carries a `key`, a `lastSeen` timestamp, and a list of `BadgerValue` + versions; the `resource`/`resourceID` inside each value are free-form Kubernetes + objects passed through from the member cluster. + +```json +{ + "items": [ + { + "key": "", + "lastSeen": 1718000000, + "values": [ + { + "resourceID": { "...": "free-form Kubernetes object" }, + "licenseID": "", + "version": 3, + "timestamp": 1718000000 + } + ] + } + ] +} +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products/{productName}/events-histories + +Returns an events-history report for a specific resource (admin/testing use). + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** `uid` (integer), `cid` (string), `lid` (string), + `productName` (string). +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `group` | string | no | Kubernetes API group. | +| `resource` | string | no | Kubernetes resource. | +| `rid` | string | no | Resource ID (object UID). | + +- **Response:** `200 OK` — an `EventsReport`. + +```json +{ + "userID": 42, + "clusterID": "", + "licenseID": "", + "group": "kubedb.com", + "resource": "mongodbs", + "resourceID": "", + "totalEvents": 128, + "eventsTimeHistories": ["2026-06-01T00:00:00Z", "2026-06-02T00:00:00Z"], + "eventsDurationHours": 720.0, + "averageEventsPerHour": 0.18 +} +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products/{productName}/events/ + +Returns the tabular event list for a licensed user's cluster/license/product. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** `uid` (integer), `cid` (string), `lid` (string), + `productName` (string). +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `lastDays` | integer | no | Look-back window in days (max 14; defaults to 14). | + +- **Response:** `200 OK` — an array of `ClusterResourceTabularForm`, newest first. + +```json +[ + { + "key": "", + "version": 3, + "timestamp": 1718000000, + "partialResource": { + "partialObjectMeta": { "...": "free-form partial Kubernetes object metadata" } + } + } +] +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products/{productName}/events/raw-event + +Returns the raw badger value for a specific event key/version. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** `uid` (integer), `cid` (string), `lid` (string), + `productName` (string). +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `key` | string | yes | Badger event key. | +| `version` | integer | yes | Event version (uint). | + +- **Response:** `200 OK` — a single `BadgerValue` (see the resources endpoint + above). `400` when `key`/`version` are missing or invalid. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## Active licenses for a cluster + +### GET /dashboard/clusters/{cid}/licenses/active + +Lists licenses that reported within the `limit` window for the given cluster, across +all users. + +- **Auth:** token; site-admin (`view_licensed_users:site_admin`). Requires `?org=`. +- **Path parameters:** `cid` (string) — cluster UID. +- **Query parameters:** `limit` (string, optional) — activity window. +- **Response:** `200 OK` — an array of `ActiveLicenseAPIForm` (see above). + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## System outages + +### POST /dashboard/system-outages/ + +Records a system-outage window for an account/cluster. + +- **Auth:** token; site-admin (`view_system_outages:site_admin`). Requires `?org=`. +- **Request body:** a `SystemOutageRequest`. + +```json +{ + "accountName": "appscode", + "clusterID": "", + "start": "2026-06-01T00:00:00Z", + "end": "2026-06-01T02:30:00Z", + "tags": ["network", "planned"], + "comments": "Planned maintenance window." +} +``` + +| Name | Type | Required | Description | +|---|---|---|---| +| `accountName` | string | no | Account (organization/user) name the outage applies to. | +| `clusterID` | string | no | Cluster UID the outage applies to. | +| `start` | date-time | yes | Outage start (RFC3339). | +| `end` | date-time | yes | Outage end (RFC3339). | +| `tags` | string[] | no | Free-form tags for grouping/reporting. | +| `comments` | string | no | Human-readable notes. | + +- **Response:** `201 Created` — the stored `SystemOutageApiForm` (fields as above + plus a server-assigned `id`, `accountID`, and `createdAt`). `409` if an + overlapping entry already exists; `422` on validation failure. + +### GET /dashboard/system-outages/report + +Lists system-outage entries with an aggregated report (top tags, accounts, and +clusters by duration). + +- **Auth:** token; site-admin (`view_system_outages:site_admin`). Requires `?org=`. +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `start` | string | no | RFC3339 start-time filter. | +| `account_id` | string | no | Filter by account ID. | +| `cluster_id` | string | no | Filter by cluster ID. | +| `tags` | string[] | no | Filter by tags (repeatable). | + +- **Response:** `200 OK` — a `SystemOutagesAndReportAPIForm` with an aggregated + `report` and the matching `entries`. + +```json +{ + "report": { + "totalOutages": 3, + "totalDurationHours": 6.5, + "topTagsPercentage": [{ "tag": "network", "percentage": 66.7 }], + "topAccountsDuration": [ + { "entity": "account", "entityName": "appscode", "durationHours": 4.0, "percentage": 61.5 } + ], + "topClustersDuration": [ + { "entity": "cluster", "entityName": "ace", "durationHours": 2.5, "percentage": 38.5 } + ] + }, + "entries": [ + { + "id": 1, + "accountID": 42, + "accountName": "appscode", + "clusterID": "", + "start": "2026-06-01T00:00:00Z", + "end": "2026-06-01T02:30:00Z", + "tags": ["network"], + "comments": "Planned maintenance window.", + "createdAt": "2026-06-01T03:00:00Z" + } + ] +} +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/system-outages/tags + +Lists all unique tags used across system-outage entries. + +- **Auth:** token; site-admin (`view_system_outages:site_admin`). Requires `?org=`. +- **Response:** `200 OK` — an array of tag strings. + +```json +["network", "planned", "storage"] +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## Marketplace subscriptions + +### GET /dashboard/marketplaces/subscriptions + +Lists all marketplace subscriptions (minimal API form), newest-updated first. + +- **Auth:** token; site-admin (`view_marketplace_usage:site_admin`). Requires `?org=`. +- **Response:** `200 OK` — an array of `Subscription`. + +```json +[ + { + "marketplace": "Azure", + "subscriptionId": "", + "subscriberId": 42, + "requesterId": 42, + "boundedInstallerId": "", + "state": "Running", + "isRevocable": true, + "noOfBillingEventSent": 12, + "createdAt": "2026-01-10T09:00:00Z", + "lastUpdatedAt": "2026-06-01T00:00:00Z" + } +] +``` + +`marketplace` is one of `Aws`, `Azure`, `Gcp`; `state` is one of `Pending`, +`Bounded`, `Running`, `Failed`, `Deleting`, `DeletionFailed`, `Deleted`, `Revoked`. +The per-marketplace `awsBillingDetails` / `azureBillingDetails` / `gcpBillingDetails` +objects are omitted here for brevity (they carry marketplace-specific billing +identifiers). + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/marketplaces/settings/warnings + +Returns configuration warnings for marketplace integrations (e.g. Azure +client-secret expiry). + +- **Auth:** token; site-admin (`view_marketplace_usage:site_admin`). Requires `?org=`. +- **Response:** `200 OK` — a `SettingWarnings` object: a `warnings` map keyed by + marketplace, each value a list of `{ "Level": "...", "Msg": "..." }` warnings. + +```json +{ + "warnings": { + "Azure": [{ "Level": "warning", "Msg": "Client secret expires in 14 days." }] + } +} +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/marketplaces/{marketplace}/{subscriptionId} + +Returns the full API form of a marketplace subscription. + +- **Auth:** token; site-admin (`view_marketplace_usage:site_admin`). Requires `?org=`. +- **Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `marketplace` | string | Marketplace identifier (`Aws`, `Azure`, `Gcp`). | +| `subscriptionId` | string | Marketplace subscription ID. | + +- **Response:** `200 OK` — a `Subscription` (see above). `400` if the subscription + is not found or invalid. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### DELETE /dashboard/marketplaces/{marketplace}/{subscriptionId} + +Revokes a revocable marketplace subscription and all associated contracts. + +- **Auth:** token; site-admin (`view_marketplace_usage:site_admin`). Requires `?org=`. +- **Path parameters:** `marketplace` (string), `subscriptionId` (string). +- **Response:** `200 OK` on success. `400` if the subscription is not found or not + revocable. + +### GET /dashboard/marketplaces/{marketplace}/{subscriptionId}/ping + +Pings the hosted `b3` metering-readiness endpoint for a subscription (AWS or GCP +only). + +- **Auth:** token; site-admin (`view_marketplace_usage:site_admin`). Requires `?org=`. +- **Path parameters:** `marketplace` (string), `subscriptionId` (string). +- **Response:** `200 OK` when the endpoint is reachable. `400` if the subscription + is not found or the marketplace is unsupported. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/marketplaces/{marketplace}/{subscriptionId}/audit-logs + +Returns audit-event reports for a marketplace subscription, grouped by audit period. + +- **Auth:** token; site-admin (`view_marketplace_usage:site_admin`). Requires `?org=`. +- **Path parameters:** `marketplace` (string), `subscriptionId` (string). +- **Response:** `200 OK` — an `AuditReportsResp`: an `auditReports` map keyed by + audit period, each value a list of `MarketplaceAuditEvent`. + +```json +{ + "auditReports": { + "2026-06": [ + { + "marketplace": "Azure", + "subscriptionID": "", + "status": "success", + "operationType": "report-usage", + "description": "Reported metered usage.", + "data": { "...": "free-form event payload" }, + "timestamp": "2026-06-01T00:00:00Z" + } + ] + } +} +``` + +`400` if the subscription is not found. + +> **Verified:** returned `404` against `appscode` — billing not enabled. diff --git a/docs/platform/api/billing-dashboard/usage-reports.md b/docs/platform/api/billing-dashboard/usage-reports.md new file mode 100644 index 0000000..aae06d9 --- /dev/null +++ b/docs/platform/api/billing-dashboard/usage-reports.md @@ -0,0 +1,309 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-billing-dashboard-usage-reports + name: Usage Reports + parent: api-billing-dashboard + weight: 30 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Usage Reports + +Endpoints that serve the pre-generated monthly usage summaries under +`/api/v1/dashboard/summary` (KubeDB, KubeStash, KubeVault, Voyager) and the DBaaS +namespace billing reports under `/api/v1/dbaas/billing`. + +All paths on this page are relative to `/api/v1`. Every endpoint requires +`Authorization: token ` and resolves the acting organization from the +`org` query parameter (`?org=`). The `/dashboard/summary/*` routes require +`view_usage_analytics:site_admin`; the `/dbaas/billing/*` routes require org +ownership when an org is set. This group is available only on **billing-enabled +deployments**. + +> **Verified:** every endpoint on this page returned `404 Not Found` against +> `appscode` on `` on 2026-07-14 — this deployment is not billing-enabled, +> so neither the `/dashboard/summary/*` nor the `/dbaas/billing/*` routes are +> registered. (Sanity: `GET /version` and `GET /user` returned `200` with the same +> token.) + +## About usage-report views + +Usage summaries are generated per month and per product. The individual view +endpoints (`objects`, `clusters`, `namespaces`, `gks`, `contracts`, quota-history, +cluster-mode) all return a **`UsageView`** — a complex, deeply-nested aggregation +structure whose exact shape varies by product and by the `view_type` query +parameter. It is modeled as a free-form JSON object, so the examples below show the +envelope rather than an exhaustive field list. + +Common path parameters for the `summary` routes: + +| Name | Type | Description | +|---|---|---| +| `year` | string | Four-digit report year (e.g. `2026`). | +| `month` | string | Report month (e.g. `06` or `June`, per the generated-months list). | + +## Generated months + +### GET /dashboard/summary/generated-months + +Returns the year/month combinations for which a usage summary has been generated for +the owner. + +- **Auth:** token; site-admin (`view_usage_analytics:site_admin`). Requires `?org=`. +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug. | + +- **Response:** `200 OK` — a `GeneratedDates` object. `yearMonthList` is keyed by + year, with a list of generated month names per year. + +```json +{ + "yearMonthList": { + "2026": ["January", "February", "March", "April", "May", "June"] + } +} +``` + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/dashboard/summary/generated-months?org=appscode" +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled on this deployment. + +### GET /dashboard/summary/object-quota-history/clusters/{clusterUID}/objects/{objectID} + +Returns the quota-history usage view for a specific KubeDB object (not scoped to a +month). + +- **Auth:** token; site-admin (`view_usage_analytics:site_admin`). Requires `?org=`. +- **Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `clusterUID` | string | Cluster UID. | +| `objectID` | string | Object (database) ID. | + +- **Response:** `200 OK` — a `UsageView` (free-form object quota-history view). + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## KubeDB usage views + +All routes below are rooted at +`/dashboard/summary/{year}/{month}/usage-report/products/kubeDb/views` and require +`view_usage_analytics:site_admin` and `?org=`. Each returns a `UsageView`. + +### GET .../kubeDb/views/objects-usage-view + +Returns the KubeDB objects usage view for the month, enriched with each object's +daily event count. + +- **Query parameters (all optional):** `view_type` (string), `group` (string), + `kind` (string), `clusterUID` (string), `namespace` (string), `namespaceUID` + (string). +- **Response:** `200 OK` — a `UsageView`. `400` on invalid parameters. + +```json +{ + "...": "free-form KubeDB objects usage view (varies by view_type)" +} +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../kubeDb/views/clusters-usage-view + +Returns the KubeDB clusters usage view for the month. + +- **Query parameters (all optional):** `view_type` (string), `group` (string), + `kind` (string), `contractID` (integer). +- **Response:** `200 OK` — a `UsageView`. `400` on invalid parameters. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../kubeDb/views/namespaces-usage-view + +Returns the KubeDB namespaces usage view for the month. + +- **Query parameters (all optional):** `view_type` (string), `clusterUID` (string). +- **Response:** `200 OK` — a `UsageView`. `400` on invalid parameters. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../kubeDb/views/gks-usage-view + +Returns the KubeDB "GKs" (group/kind) usage view for the month, with the total +monthly usage matrix. + +- **Query parameters (all optional):** `view_type` (string), `clusterUID` (string). +- **Response:** `200 OK` — a `UsageView`. `400` on invalid parameters. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../kubeDb/views/contracts-usage-view + +Returns the KubeDB contracts usage view for the month. + +- **Query parameters (all optional):** `view_type` (string). +- **Response:** `200 OK` — a `UsageView`. `400` on invalid parameters. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../kubeDb/views/object-quota-history-summaries-view + +Returns the month-specific KubeDB object quota-history summaries. + +- **Response:** `200 OK` — a `UsageView`. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../kubeDb/views/object-quota-history-summaries-view/clusters/{clusterUID}/objects/{objectID} + +Returns the month-specific KubeDB object quota-history summary for a specific +cluster/object. + +- **Path parameters:** `clusterUID` (string), `objectID` (string). +- **Response:** `200 OK` — a `UsageView`. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../kubeDb/views/objects-cluster-mode-usage-view + +Returns the KubeDB objects cluster-mode usage history list for the month. + +- **Response:** `200 OK` — a `UsageView`. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../kubeDb/views/objects-cluster-mode-usage-view/clusters/{clusterUID}/objects/{objectID} + +Returns the KubeDB cluster-mode usage history for a specific cluster/object. + +- **Path parameters:** `clusterUID` (string), `objectID` (string). +- **Response:** `200 OK` — a `UsageView`. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## KubeStash, KubeVault, and Voyager usage views + +Each of these products exposes a `clusters-usage-view` and a `contracts-usage-view` +for the month, rooted at +`/dashboard/summary/{year}/{month}/usage-report/products/{product}/views`. They +require `view_usage_analytics:site_admin` and `?org=`, and each returns a +`UsageView`. + +### GET .../kubeStash/views/clusters-usage-view + +Returns the KubeStash clusters usage view for the month. + +- **Query parameters (all optional):** `view_type` (string), `contractID` (integer). +- **Response:** `200 OK` — a `UsageView`. `400` on invalid parameters. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../kubeStash/views/contracts-usage-view + +Returns the KubeStash contracts usage view for the month. + +- **Query parameters (all optional):** `view_type` (string). +- **Response:** `200 OK` — a `UsageView`. `400` on invalid parameters. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../kubeVault/views/clusters-usage-view + +Returns the KubeVault clusters usage view for the month. + +- **Query parameters (all optional):** `view_type` (string), `contractID` (integer). +- **Response:** `200 OK` — a `UsageView`. `400` on invalid parameters. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../kubeVault/views/contracts-usage-view + +Returns the KubeVault contracts usage view for the month. + +- **Query parameters (all optional):** `view_type` (string). +- **Response:** `200 OK` — a `UsageView`. `400` on invalid parameters. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../voyager/views/clusters-usage-view + +Returns the Voyager clusters usage view for the month. + +- **Query parameters (all optional):** `view_type` (string), `contractID` (integer). +- **Response:** `200 OK` — a `UsageView`. `400` on invalid parameters. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET .../voyager/views/contracts-usage-view + +Returns the Voyager contracts usage view for the month. + +- **Query parameters (all optional):** `view_type` (string). +- **Response:** `200 OK` — a `UsageView`. `400` on invalid parameters. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## Download + +### GET /dashboard/summary/{year}/{month}/download + +Renders and returns the KubeDB usage summary as a PDF document for the given month. + +- **Auth:** token; site-admin (`view_usage_analytics:site_admin`). Requires `?org=`. +- **Path parameters:** `year` (string), `month` (string). +- **Response:** `200 OK` — the usage-report PDF (`application/pdf`, or + `application/octet-stream`) as a binary body. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/dashboard/summary/2026/June/download?org=appscode" \ + -o usage-report.pdf +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## DBaaS billing reports + +These routes are rooted at `/dbaas/billing/reports`, require a token and `?org=`, +and are checked for org ownership when an org is set (rather than site-admin). Each +returns a pre-marshaled report view, modeled as a free-form `UsageView`. + +### GET /dbaas/billing/reports/namespaces + +Returns the DBaaS namespace report list (V1) for the owner. + +- **Auth:** token; org-ownership when `org` is set. Requires `?org=`. +- **Response:** `200 OK` — a `UsageView` (free-form namespace report list). + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/dbaas/billing/reports/namespaces?org=appscode" +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled on this deployment. + +### GET /dbaas/billing/reports/clusters/{clusterID}/namespaces/{namespaceName} + +Returns the DBaaS namespace report (V1) for a specific cluster/namespace. + +- **Auth:** token; org-ownership when `org` is set. Requires `?org=`. +- **Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `clusterID` | string | Cluster ID. | +| `namespaceName` | string | Namespace name. | + +- **Response:** `200 OK` — a `UsageView` (free-form namespace report). + +> **Verified:** returned `404` against `appscode` — billing not enabled. diff --git a/docs/platform/api/billing-dashboard/user-dashboard.md b/docs/platform/api/billing-dashboard/user-dashboard.md new file mode 100644 index 0000000..7a66c43 --- /dev/null +++ b/docs/platform/api/billing-dashboard/user-dashboard.md @@ -0,0 +1,269 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-billing-dashboard-user-dashboard + name: User Billing Dashboard + parent: api-billing-dashboard + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# User Billing Dashboard + +Owner-scoped endpoints under `/api/v1/dashboard/clusters` that back the self-service +billing dashboard an organization sees for its **own** clusters: active clusters, +their licenses and licensed products, and per-cluster / per-license / per-resource +event counts. + +All paths on this page are relative to `/api/v1`. Every endpoint requires +`Authorization: token `, resolves the owner from the `org` query +parameter (`?org=`), and requires the `view:contracts` permission on that +organization (this is the org's "hosted mode / view contracts" grant — not +site-admin). This group is available only on **billing-enabled deployments**. + +> **Verified:** every endpoint on this page returned `404 Not Found` against +> `appscode` on `` on 2026-07-14 — this deployment is not billing-enabled, +> so the `/dashboard/clusters/*` routes are not registered. (Sanity: `GET /version` +> and `GET /user` returned `200` with the same token.) + +Shared conventions on this page: + +- **`cid`** is a cluster UID string; **`lid`** is a license ID string; **`product`** + is a product name. +- **`limit`** (query, optional) sets the "active" window: a Go duration such as + `720h` or a `YYYY-MM-DD` date; defaults to roughly the last six months. + +## Clusters + +### GET /dashboard/clusters/active + +Lists clusters that reported within the `limit` window for the owner resolved from +the query. + +- **Auth:** token; owner-scoped (`view:contracts`). Requires `?org=`. +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | yes | Organization slug that owns the clusters. | +| `limit` | string | no | Activity window (Go duration or `YYYY-MM-DD` date). | + +- **Response:** `200 OK` — an array of `ActiveClustersAPIForm`. + +```json +[ + { + "username": "appscode", + "clusterID": "", + "firstReceivedAt": 1700000000, + "lastReceivedAt": 1718000000, + "noOfAssociatedContracts": 2 + } +] +``` + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/dashboard/clusters/active?org=appscode" +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled on this deployment. + +### GET /dashboard/clusters/{cid} + +Returns cluster information for a cluster owned by the request owner. + +- **Auth:** token; owner-scoped (`view:contracts`). Requires `?org=`. +- **Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `cid` | string | Cluster UID. | + +- **Response:** `200 OK` — a single `ClusterInfo` object (the same shape documented + on the [Admin Billing Dashboard](../admin-dashboard.md) page; + `status` is a free-form Kubernetes-style object). `404` if the cluster is unknown + or not owned by the org. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/clusters/{cid}/events-count + +Returns today's event count for the cluster. + +- **Auth:** token; owner-scoped (`view:contracts`). Requires `?org=`. +- **Path parameters:** `cid` (string) — cluster UID. +- **Response:** `200 OK` — an `EventsCounterResponse`. + +```json +{ + "clusterID": "", + "date": "2026-07-14", + "noOfEvents": 27 +} +``` + +The `product`, `licenseID`, `group`, `resource`, and `RID` fields are populated on +the license/resource-scoped counter endpoints below; `error` is set instead of +`noOfEvents` when the count could not be computed. + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## Licenses + +### GET /dashboard/clusters/{cid}/licenses/ + +Lists licensed plans associated with the request owner and cluster. + +- **Auth:** token; owner-scoped (`view:contracts`). Requires `?org=`. +- **Path parameters:** `cid` (string) — cluster UID. +- **Response:** `200 OK` — an array of `LicensedPlan` (see the Admin Billing + Dashboard page for the full shape). + +```json +[ + { + "uid": 42, + "email": "user@example.com", + "licenseID": "", + "clusters": [""], + "planName": "kubedb-enterprise", + "notBefore": 1700000000, + "notAfter": 1731600000 + } +] +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/clusters/{cid}/licenses/{lid} + +Returns a licensed plan (API form) associated with the request owner. + +- **Auth:** token; owner-scoped (`view:contracts`). Requires `?org=`. +- **Path parameters:** `cid` (string), `lid` (string) — license ID. +- **Response:** `200 OK` — a `LicensePlanApiForm`. + +```json +{ + "uid": 42, + "email": "user@example.com", + "licenseID": "", + "clusters": [""], + "planName": "kubedb-enterprise", + "notBefore": 1700000000, + "notAfter": 1731600000, + "reconciledAt": 1718000000, + "registeredAt": 1700000000, + "createdAt": 1700000000, + "updatedAt": 1718000000 +} +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +## Event counts and events + +### GET /dashboard/clusters/{cid}/licenses/{lid}/products/{product}/events-count + +Returns today's event count for a license/product. + +- **Auth:** token; owner-scoped (`view:contracts`). Requires `?org=`. +- **Path parameters:** `cid` (string), `lid` (string), `product` (string). +- **Response:** `200 OK` — an `EventsCounterResponse` (with `product` and + `licenseID` populated). + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/clusters/{cid}/licenses/{lid}/products/{product}/groups/{group}/resources/{resource}/{rid}/events-count + +Returns today's event count for a specific resource object. + +- **Auth:** token; owner-scoped (`view:contracts`). Requires `?org=`. +- **Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `cid` | string | Cluster UID. | +| `lid` | string | License ID. | +| `product` | string | Product name. | +| `group` | string | Kubernetes API group. | +| `resource` | string | Kubernetes resource. | +| `rid` | string | Resource ID (object UID). | + +- **Response:** `200 OK` — an `EventsCounterResponse` (with `group`, `resource`, and + `RID` populated). + +```json +{ + "clusterID": "", + "product": "kube-db", + "licenseID": "", + "group": "kubedb.com", + "resource": "mongodbs", + "RID": "", + "date": "2026-07-14", + "noOfEvents": 4 +} +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/clusters/{cid}/licenses/{lid}/products/{product}/events/ + +Returns the tabular event list for the caller's cluster/license/product. + +- **Auth:** token; owner-scoped (`view:contracts`). Requires `?org=`. +- **Path parameters:** `cid` (string), `lid` (string), `product` (string). +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `lastDays` | integer | no | Look-back window in days (max 14; defaults to 14). | + +- **Response:** `200 OK` — an array of `ClusterResourceTabularForm`, newest first. + +```json +[ + { + "key": "", + "version": 3, + "timestamp": 1718000000, + "partialResource": { + "partialObjectMeta": { "...": "free-form partial Kubernetes object metadata" } + } + } +] +``` + +> **Verified:** returned `404` against `appscode` — billing not enabled. + +### GET /dashboard/clusters/{cid}/licenses/{lid}/products/{product}/events/raw-event + +Returns the raw badger value for a specific event key/version. + +- **Auth:** token; owner-scoped (`view:contracts`). Requires `?org=`. +- **Path parameters:** `cid` (string), `lid` (string), `product` (string). +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `key` | string | yes | Badger event key. | +| `version` | integer | yes | Event version (uint). | + +- **Response:** `200 OK` — a single `BadgerValue`. + +```json +{ + "resourceID": { "...": "free-form Kubernetes object" }, + "licenseID": "", + "version": 3, + "timestamp": 1718000000 +} +``` + +`400` when `key`/`version` are missing or invalid. + +> **Verified:** returned `404` against `appscode` — billing not enabled. diff --git a/docs/platform/api/chart-repositories/_index.md b/docs/platform/api/chart-repositories/_index.md new file mode 100644 index 0000000..d814f41 --- /dev/null +++ b/docs/platform/api/chart-repositories/_index.md @@ -0,0 +1,30 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-chart-repositories + name: Chart Repositories + parent: api + weight: 170 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Chart Repositories + +The Chart Repositories API exposes ACE's read-only view over the public Helm Hub +chart repository index. It lets you enumerate the known Helm chart repositories, +load an individual repository and list the charts it contains, and inspect the +available versions of a specific chart. + +All endpoints live under the `/api/v1/chartrepositories` prefix and are +**public** — they carry no `security` requirement in the API definition and can +be called without organization context. In practice clients still send their +bearer token on every request (the platform accepts it), but no membership or +role is required. Only `GET` requests are exposed here. + +## Pages + +- [Chart Repositories](../chart-repositories.md) — list the + known chart repositories, list the charts inside a repository, and list the + versions of a named chart. diff --git a/docs/platform/api/chart-repositories/chart-repositories.md b/docs/platform/api/chart-repositories/chart-repositories.md new file mode 100644 index 0000000..3191ac4 --- /dev/null +++ b/docs/platform/api/chart-repositories/chart-repositories.md @@ -0,0 +1,206 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-chart-repositories-chart-repositories + name: Chart Repositories + parent: api-chart-repositories + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Chart Repositories + +These endpoints provide a read-only view over the public Helm Hub chart +repository index used by ACE. You can list the known repositories, load a +repository by URL and list the charts inside it, and list the versions of a +named chart. + +All paths on this page are relative to `/api/v1`. The full base path is +`/api/v1/chartrepositories`. + +All three endpoints are **public** (no `security` requirement, no organization +context). Clients typically still send their bearer token, but no membership or +role is required. Only `GET` is supported. + +Examples below use a placeholder host `` and a `$ACE_TOKEN` +environment variable holding the caller's token. + +--- + +## List chart repositories + +### GET /chartrepositories + +Returns the list of known Helm Hub chart repositories. + +- **Auth:** public. No organization context required. + +**Path parameters:** none. + +**Query parameters:** none. + +**Response:** `200 OK` — a JSON array of chart repository entries. Each entry is +a Helm repository configuration (Helm's `repo.Entry`). In practice only `name` +and `url` are populated for the public Helm Hub index; the credential-related +fields are part of the schema but are empty for public repositories. + +```json +[ + { "name": "appscode", "url": "https://charts.appscode.com/stable" }, + { "name": "bitnami", "url": "https://charts.bitnami.com/bitnami" }, + { "name": "argo", "url": "https://argoproj.github.io/argo-helm" } +] +``` + +Fields of each `ChartRepositoryEntry`: + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Repository name. | +| `url` | string | Repository index URL. | +| `username` | string | Basic-auth username (empty for public repos). | +| `password` | string | Basic-auth password (empty for public repos). | +| `certFile` | string | Client TLS certificate file. | +| `keyFile` | string | Client TLS key file. | +| `caFile` | string | CA bundle file. | +| `insecure_skip_tls_verify` | boolean | Skip TLS verification for the repo. | +| `pass_credentials_all` | boolean | Pass credentials to all hosts. | + +**Example:** + +```bash +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/chartrepositories +``` + +> **Verified:** `GET` returned `200` on 2026-07-14 (public endpoint; not +> cluster-scoped). Returned a large array of repositories; live entries populate +> only `name` and `url`. + +--- + +## List charts in a repository + +### GET /chartrepositories/charts + +Loads the chart repository at the given `url` and returns the names of the charts +it contains. + +- **Auth:** public. No organization context required. + +**Path parameters:** none. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `url` | string | yes | URL of the chart repository to load (for example `https://charts.appscode.com/stable`). | + +**Response:** `200 OK` — a JSON array of chart names (strings) found in the +repository index. + +```json +[ + "kubedb", + "stash", + "cert-manager-crds", + "prometheus" +] +``` + +Other statuses: + +| Status | Meaning | +|--------|---------| +| `400` | Missing chart repo `url`. | +| `500` | Internal server error (for example the repository index could not be loaded). | + +**Example:** + +```bash +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/chartrepositories/charts?url=https://charts.appscode.com/stable" +``` + +> **Verified:** `GET` returned `200` on 2026-07-14 for +> `url=https://charts.appscode.com/stable` (public endpoint; not cluster-scoped). +> Response was a JSON array of chart-name strings (264 charts). + +--- + +## List versions of a chart + +### GET /chartrepositories/charts/{name}/versions + +Loads the chart repository at the given `url` and returns the available versions +of the named chart. + +- **Auth:** public. No organization context required. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `name` | string | Name of the chart (for example `kubedb`). | + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `url` | string | yes | URL of the chart repository that contains the chart. | + +**Response:** `200 OK` — a JSON array of chart version entries (Helm's +`repo.ChartVersion` / chart metadata). The schema models the common chart +metadata fields; a given repository only populates the fields it publishes. In +practice the public Helm Hub index returns `version`, `appVersion`, `created`, +and (when set) `kubeVersion`. + +```json +[ + { + "version": "v2026.7.10", + "appVersion": "v2026.7.10", + "kubeVersion": ">=1.26.0-0", + "created": "2026-07-13T07:15:34.541887Z" + } +] +``` + +Fields of each `ChartVersion` (as defined by the API schema): + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Chart name. | +| `version` | string | Chart version (SemVer). | +| `description` | string | Chart description. | +| `apiVersion` | string | Chart API version (`v1` or `v2`). | +| `appVersion` | string | Version of the application packaged by the chart. | +| `type` | string | Chart type (`application` or `library`). | +| `deprecated` | boolean | Whether this chart version is deprecated. | +| `icon` | string | URL of the chart icon. | +| `home` | string | Home page URL of the project. | +| `keywords` | array of string | Search keywords. | +| `sources` | array of string | Source URLs for the project. | +| `urls` | array of string | Download URLs for the chart archive. | +| `created` | string (date-time) | Publication timestamp. | +| `digest` | string | Digest of the chart archive. | + +Other statuses: + +| Status | Meaning | +|--------|---------| +| `400` | Missing chart repo `url` or chart `name`. | +| `500` | Internal server error (for example the repository index could not be loaded). | + +**Example:** + +```bash +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/chartrepositories/charts/kubedb/versions?url=https://charts.appscode.com/stable" +``` + +> **Verified:** `GET` returned `200` on 2026-07-14 for chart `kubedb` with +> `url=https://charts.appscode.com/stable` (public endpoint; not cluster-scoped). +> Response was a JSON array of 106 version entries. diff --git a/docs/platform/api/client-organizations/_index.md b/docs/platform/api/client-organizations/_index.md new file mode 100644 index 0000000..b42e1f1 --- /dev/null +++ b/docs/platform/api/client-organizations/_index.md @@ -0,0 +1,35 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-client-organizations + name: Client Organizations + parent: api + weight: 80 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Client Organizations + +These endpoints support the **managed-service-provider** model. A platform site +admin creates dedicated "client organizations" (a specialized kind of ACE +organization), imports spoke clusters into them, and then manages per-cluster +user access on behalf of each client. + +There are two concerns, split across two pages: + +- [Client Org Management](../management.md) — site-admin + lifecycle of client organizations: list/get/create/delete client orgs, add or + remove clusters, and query client-org status. Routes live under + `/api/v1/user/client*`. +- [Cluster User Permissions](../cluster-user-permissions.md) + — organization-admin management of the OCM users belonging to a client org on + a specific cluster: list users, create a user with permissions, inspect and + update permissions, generate a kubeconfig, and remove a user. Routes live + under `/api/v1/clusters/{owner}/{cluster}/permission/*`. + +All routes are served under the `/api/v1` prefix and require a personal access +token (`Authorization: token `). Client-org **management** routes are +site-admin only; the per-cluster **permission** routes require organization-admin +authorization on the `owner` (which must resolve to a client organization). diff --git a/docs/platform/api/client-organizations/cluster-user-permissions.md b/docs/platform/api/client-organizations/cluster-user-permissions.md new file mode 100644 index 0000000..339a70b --- /dev/null +++ b/docs/platform/api/client-organizations/cluster-user-permissions.md @@ -0,0 +1,285 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-client-organizations-cluster-user-permissions + name: Cluster User Permissions + parent: api-client-organizations + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Cluster User Permissions + +Manage the OCM users belonging to a client organization on a specific cluster: +list them, create a user with permissions, inspect and update those permissions, +generate a kubeconfig, remove specific grants, and delete the user entirely. + +All paths on this page are relative to the API root **`/api/v1`** and require a +personal access token: + +``` +Authorization: token +``` + +**Path parameters common to every endpoint here:** + +| Name | Type | Description | +|------|------|-------------| +| `owner` | string | Organization slug that owns the cluster. **Must resolve to a client organization** (`reqClientOrg`); otherwise the request is rejected. | +| `cluster` | string | Cluster name within the `owner` scope. | + +**Auth:** `GET /permission/users` requires a valid token and that `owner` is a +client org. Every other endpoint additionally requires **organization-admin** +authorization on `owner` (`Organization_Admin`). + +Illustrative curl calls use a placeholder host `` and `$ACE_TOKEN`. + +--- + +### GET /clusters/{owner}/{cluster}/permission/users + +List the users of the client organization (`owner`) that have been granted access +on this cluster. + +- **Auth:** token; `owner` must resolve to a client organization. + +**Response:** `200 OK` — a JSON array of `User` objects. + +```json +[ + { + "id": 101, + "login": "acme-admin", + "username": "acme-admin", + "full_name": "Acme Admin", + "email": "user@example.com", + "active": true, + "orgAdmin": true, + "clientOrgUser": true + } +] +``` + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/acme-client/acme-prod/permission/users +``` + +> **Verified:** returned `500` against `appscode/ace` — `appscode` is not a client +> organization on this platform (`user isn't a client organization`), so the +> `reqClientOrg` check fails. Expected `200` with a `User` array when `owner` is a +> real client org. + +--- + +### POST /clusters/{owner}/{cluster}/permission/user/create + +Create an OCM user for the client organization on this cluster and assign the +requested permissions (creating the necessary RBAC role / cluster-role bindings and +importing/connecting clusters for the user). + +- **Auth:** token; **organization-admin** on `owner`. + +**Request body:** `UserOptions` (see [below](#useroptions)). + +```json +{ + "userName": "acme-dev", + "email": "user@example.com", + "permissions": [ + { + "name": "acme-prod", + "isClusterSet": false, + "roleType": "ClusterRole", + "roleRefName": "ace:admin", + "roleRefNamespace": ["team-a"] + } + ], + "importCluster": true, + "clientOrg": true +} +``` + +**Responses:** `200` user created and permissions assigned · `400` invalid +permission options for the client org · `422` validation error. + +--- + +### POST /clusters/{owner}/{cluster}/permission/user/{id} + +Get the roles and cluster-roles assigned to a client-org user on this cluster, +scoped to the namespaces supplied in the request body. (This is a `POST` because it +takes a namespace-scope selector in the body, but it is a read operation.) + +- **Auth:** token; **organization-admin** on `owner`. + +**Path parameters:** `owner`, `cluster` (above), plus: + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | Numeric ID of the user. | + +**Request body:** `PermissionScopes`. + +```json +{ + "namespaceList": ["team-a", "team-b"], + "allNamespaces": false +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `namespaceList` | string[] | no | Namespaces to scope the query to. | +| `allNamespaces` | boolean | no | When true, return permissions across all namespaces. | + +**Response:** `200 OK` — a `ClientOrgUserPermission` object. `400` if the user is +not part of the client org. + +```json +{ + "ClusterRoles": [ + { + "ResourceName": "acme-dev-binding", + "ResourceNamespace": "", + "RoleName": "ace:admin", + "RoleNamespace": "" + } + ], + "Roles": [ + { + "ResourceName": "acme-dev-team-a-binding", + "ResourceNamespace": "team-a", + "RoleName": "ace:editor", + "RoleNamespace": "team-a" + } + ] +} +``` + +> Field names are capitalized because the source Go structs (`ocm.ClientOrgUserPermission`, +> `ocm.ClientOrgUserPermissionDetails`) carry no JSON tags. + +--- + +### GET /clusters/{owner}/{cluster}/permission/user/{id}/kubeconfig + +Generate a kubeconfig for a client-org user to access this cluster, provided the +user has permission in the client organization's cluster. + +- **Auth:** token; **organization-admin** on `owner`. + +**Path parameters:** `owner`, `cluster`, plus: + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | Numeric ID of the user. | + +**Response:** `200 OK` — the generated kubeconfig, returned as a JSON string +containing a YAML document. `400` if the user does not have permission in the +client-org cluster. + +```json +"apiVersion: v1\nkind: Config\nclusters:\n- cluster:\n server: https://\n name: acme-prod\n..." +``` + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/acme-client/acme-prod/permission/user/101/kubeconfig +``` + +> **Verified:** not called live — requires a real client-org user ID, which does +> not exist on this platform (no client orgs). Documented from schema. + +--- + +### POST /clusters/{owner}/{cluster}/permission/user/{id}/update + +Re-assign a client-org user's permissions on this cluster. + +- **Auth:** token; **organization-admin** on `owner`. + +**Path parameters:** `owner`, `cluster`, plus `id` (integer, int64 — the user ID). + +**Request body:** `UserOptions` (see [below](#useroptions)) — same shape as +`user/create`. + +**Responses:** `200` permissions updated · `400` invalid permission options · +`404` user not found · `422` validation error. + +--- + +### POST /clusters/{owner}/{cluster}/permission/user/{id}/remove + +Delete the named cluster-scoped and namespace-scoped RBAC bindings for a client-org +user on this cluster (removes specific grants without deleting the user). + +- **Auth:** token; **organization-admin** on `owner`. + +**Path parameters:** `owner`, `cluster`, plus `id` (integer, int64 — the user ID). + +**Request body:** `RemovePermissionOpts`. + +```json +{ + "clusterScopedResources": ["acme-dev-binding"], + "namespaceScopedResources": [ + { "Namespace": "team-a", "Name": "acme-dev-team-a-binding" } + ] +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `clusterScopedResources` | string[] | no | Names of cluster-scoped RBAC bindings to delete. | +| `namespaceScopedResources` | `NamespacedName[]` | no | Namespaced bindings to delete. Each item marshals with capitalized keys `Namespace` and `Name` (the source struct has no JSON tags). | + +**Responses:** `200` permissions removed · `404` user not found · `422` validation +error. + +--- + +### DELETE /clusters/{owner}/{cluster}/permission/user/{id}/delete + +Remove a client-org user entirely from this cluster: strips the hub-owner and +client-org annotations and deletes all associated RBAC role and cluster-role +bindings. + +- **Auth:** token; **organization-admin** on `owner`. + +**Path parameters:** `owner`, `cluster`, plus `id` (integer, int64 — the user ID). + +**Responses:** `200` user removed from the cluster · `404` user not found. + +--- + +## Schemas + +### UserOptions + +Options for creating or updating an OCM user's permissions. Used by +`user/create`, `user/{id}/update`, and by the `userPermission` field of the +client-org create call. + +| Field | Type | Description | +|-------|------|-------------| +| `id` | integer (int64) | User ID (for updates). | +| `userName` | string | The user's username. | +| `email` | string | The user's email. | +| `permissions` | `Permission[]` | Cluster / cluster-set permission grants (see below). | +| `importCluster` | boolean | Import/connect the referenced clusters for the user. | +| `clientOrg` | boolean | Whether this user belongs to a client organization. | + +**Permission** — a single cluster or cluster-set permission grant: + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Cluster or cluster-set name. | +| `isClusterSet` | boolean | True if `name` refers to a cluster set. | +| `roleType` | string | Role scope: `ClusterRole` or `Role`. | +| `roleRefName` | string | Name of the referenced (cluster-)role. | +| `roleRefNamespace` | string[] | Namespaces the role applies to (for `Role` scope). | +| `managedClusterRoleBindingName` | string | Name of the generated managed cluster role binding. | +| `managedClusterSetRoleBindingName` | string | Name of the generated managed cluster-set role binding. | diff --git a/docs/platform/api/client-organizations/management.md b/docs/platform/api/client-organizations/management.md new file mode 100644 index 0000000..c8c826e --- /dev/null +++ b/docs/platform/api/client-organizations/management.md @@ -0,0 +1,328 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-client-organizations-management + name: Client Org Management + parent: api-client-organizations + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Client Org Management + +Site-admin lifecycle of client organizations: list them, fetch one, create a new +client org (which also provisions its admin user and imports clusters), add or +remove clusters, query status, and delete a client org. + +All paths on this page are relative to the API root **`/api/v1`** and require a +personal access token: + +``` +Authorization: token +``` + +Every endpoint here is **site-admin only** — the caller must be a platform site +admin acting within an organization. Non-admin callers receive `403`. + +Illustrative curl calls use a placeholder host `` and `$ACE_TOKEN`. + +> **Platform note:** On the verification platform there are currently **no client +> organizations** — `GET /user/clients` returns an empty list (`[]`, HTTP `200`). +> An empty/`null` list is a valid, verified success response. + +--- + +## List & inspect + +### GET /user/clients + +List all client organizations known to the platform. + +- **Auth:** token; **site-admin only** (`Organization_SiteAdminCanViewClientOrg`). + The caller must be acting within an organization (`reqMustFromOrg`). + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `org` | string | recommended | Organization slug providing the caller's org context. | + +**Response:** `200 OK` — a JSON array of `Organization` objects. Empty when no +client orgs exist. + +```json +[ + { + "id": 42, + "username": "acme-client", + "full_name": "Acme Client Org", + "description": "Managed client organization", + "website": "https://example.com", + "location": "", + "rancherManagementClusterEndPoint": "", + "visibility": "private", + "orgType": 2 + } +] +``` + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/user/clients?org=appscode" +``` + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14; the platform +> has no client orgs, so the body was `[]` (a valid empty result). + +--- + +### GET /user/client/{id} + +Fetch a single client organization by its numeric ID. + +- **Auth:** token; **site-admin only** (`Organization_SiteAdminCanViewClientOrg`). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | Numeric ID of the client organization. | + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `org` | string | recommended | Caller's organization context. | + +**Response:** `200 OK` — a single `Organization` object (same shape as the list +items above). `404` if no client org has that ID. + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/user/client/42?org=appscode" +``` + +> **Verified:** returned `500` against `appscode` — no client org exists with the +> probed ID on this platform (`user does not exist`). Expected to return `200` +> with an `Organization` once a client org exists. + +--- + +### GET /user/client/{orgname}/status + +Aggregate deletion/active status across all clusters of the client organization. + +- **Auth:** token; **site-admin only** (`Organization_SiteAdminCanViewClientOrg`). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `orgname` | string | Client organization slug. | + +**Response:** `200 OK` — a `ClientOrgStatus` envelope. `status` is one of +`Active`, `Deleting`, `Partially Deleted`, `Deleted`, or `NotFound`. + +```json +{ + "status": "Active" +} +``` + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/user/client/acme-client/status?org=appscode" +``` + +> **Verified:** returned `500` against `appscode` — `appscode` is not itself a +> client org (`org does not exist`). Expected `200` with a `ClientOrgStatus` for a +> real client-org slug. + +--- + +### GET /user/client/{orgname}/cluster/{cluster}/status + +Deletion/active status of a single cluster within the client organization. + +- **Auth:** token; **site-admin only** (`Organization_SiteAdminCanViewClientOrg`). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `orgname` | string | Client organization slug. | +| `cluster` | string | Cluster name within the client organization. | + +**Response:** `200 OK` — a `ClientOrgStatus` envelope (see above). + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/user/client/acme-client/cluster/acme-prod/status?org=appscode" +``` + +> **Verified:** returned `500` against `appscode/ace` — `appscode` is not a client +> org on this platform. Expected `200` with a `ClientOrgStatus` for a real +> client-org cluster. + +--- + +## Mutations + +The endpoints below change state. They are documented from the OpenAPI schema and +were **not** called against the live platform. + +### POST /user/client/create + +Create a client organization. This also provisions the org admin user, grants that +user permission on the hub cluster, and imports the requested spoke cluster(s) with +the client org as owner. + +- **Auth:** token; **site-admin only** (`Organization_SiteAdminCanCreateClientOrg`). + +**Request body:** `ClientOrgParams`. + +```json +{ + "clientOrg": { + "orgName": "acme-client", + "orgFullName": "Acme Client Org", + "description": "Managed client organization", + "website": "https://example.com", + "orgType": "client", + "visibility": "private" + }, + "hubClusterUID": "", + "hubClusterOwnerName": "appscode", + "userPermission": { + "userName": "acme-admin", + "email": "user@example.com", + "permissions": [ + { + "name": "acme-prod", + "isClusterSet": false, + "roleType": "ClusterRole", + "roleRefName": "ace:admin" + } + ], + "importCluster": true, + "clientOrg": true + }, + "useGateway": true +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `clientOrg` | `CreateOrgParams` | yes | The organization to create (name, full name, type, visibility, optional Rancher sync token, etc.). | +| `hubClusterUID` | string | yes | UID of the hub cluster imported by the site admin. | +| `hubClusterOwnerName` | string | yes | Owner (org slug) of the hub cluster. | +| `userPermission` | `UserOptions` | yes | The org-admin user to provision and the permissions to grant (see [Cluster User Permissions](../cluster-user-permissions.md#useroptions)). | +| `annotations` | map[string]string | no | Annotations applied to created resources. | +| `kubeDBConfig` | `KubeDBConfig` | no | KubeDB scheduling config (node selector, tolerations). | +| `useGateway` | boolean | no | Provision a gateway for the client org. | +| `usableAsShared` | boolean | no | Whether the org's gateway config may be shared by other orgs. | +| `gatewayConfig` / `gatewayConfigRef` | object | no | Inline gateway config or a reference to an existing one (Kubernetes object). | +| `telemetryParams` | `TelemetryParams` | no | Monitoring cluster and retention periods. | + +**Responses:** `200` created · `400` invalid params (e.g. missing Rancher +management cluster endpoint) · `409` an org with the same name already exists · +`422` validation error. + +--- + +### POST /user/client/{orgname}/add-cluster + +Import an additional spoke cluster into a client organization, granting the org +admins access and setting up namespaces, gateway presets, and telemetry. + +- **Auth:** token; **site-admin only** (`Organization_SiteAdminCanAddClusterToClientOrg`). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `orgname` | string | Client organization slug. | + +**Request body:** `AddClusterParams`. + +```json +{ + "hubClusterOwnerName": "appscode", + "hubClusterName": "ace", + "hubClusterUID": "", + "spokeClusterName": "acme-staging", + "useGateway": true +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `hubClusterOwnerName` | string | yes | Owner (org slug) of the hub cluster. | +| `hubClusterName` | string | yes | Hub cluster name. | +| `hubClusterUID` | string | yes | Hub cluster UID. | +| `spokeClusterName` | string | yes | Spoke cluster to import into the client org. | +| `annotations` | map[string]string | no | Annotations applied to created resources. | +| `kubeDBConfig` | `KubeDBConfig` | no | KubeDB scheduling config. | +| `useGateway` | boolean | no | Provision a gateway for the added cluster. | +| `gatewayConfig` / `gatewayPresetRef` | object | no | Inline gateway config or a preset reference. | +| `telemetryParams` | `TelemetryParams` | no | Monitoring cluster and retention periods. | + +**Responses:** `200` added · `400` the cluster is already imported for this org · +`422` validation error. + +--- + +### POST /user/client/{orgname}/delete-cluster + +Remove a spoke cluster from a client organization, cleaning up the client-org +namespace and associated hub/spoke resources. + +- **Auth:** token; **site-admin only** (`Organization_SiteAdminCanRemoveClusterFromClientOrg`). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `orgname` | string | Client organization slug. | + +**Request body:** `RemoveClusterParams`. + +```json +{ + "hubClusterOwnerName": "appscode", + "hubClusterName": "ace", + "hubClusterUID": "", + "spokeClusterName": "acme-staging" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `hubClusterOwnerName` | string | yes | Owner (org slug) of the hub cluster. | +| `hubClusterName` | string | yes | Hub cluster name. | +| `hubClusterUID` | string | yes | Hub cluster UID. | +| `spokeClusterName` | string | yes | Spoke cluster to remove. | + +**Responses:** `200` removal accepted (cleanup runs asynchronously) · `422` +validation error. + +--- + +### DELETE /user/client/delete/{id} + +Delete a client organization, tearing down its namespaces and cluster resources +across all spoke clusters. Rejected if another organization still references this +client org's gateway config. + +- **Auth:** token; **site-admin only** (`Organization_SiteAdminCanDeleteClientOrg`). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | Numeric ID of the client organization. | + +**Responses:** `200` deletion accepted (teardown runs asynchronously) · `400` the +client org is still in use by another organization · `404` not found. diff --git a/docs/platform/api/cloud-providers/_index.md b/docs/platform/api/cloud-providers/_index.md new file mode 100644 index 0000000..aed604b --- /dev/null +++ b/docs/platform/api/cloud-providers/_index.md @@ -0,0 +1,34 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-cloud-providers + name: Cloud Providers + parent: api + weight: 90 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Cloud Providers + +Discovery APIs used by the cluster-provisioning wizard. Given stored cloud +credentials for an owner (organization or user), these endpoints enumerate the +projects, regions, zones, Kubernetes versions, machine types, and existing +managed clusters available on each supported cloud provider — so the console can +offer them as choices when provisioning or importing a cluster. A single public +endpoint lists the providers the platform supports, and a provisioning endpoint +creates a new Cluster API (CAPI) cluster on a provider. + +All routes are served under the `/api/v1` prefix. Except for the public provider +list (`GET /clouds`), every endpoint requires a personal access token sent as +`Authorization: token ` (it may also be supplied as a `token` or +`access_token` query parameter). The per-provider discovery routes additionally +require **stored cloud credentials** for the referenced provider under the owner +scope; without a matching credential these routes fail. + +## Pages + +- [Cloud Providers](../cloud-providers.md) — the public provider + list, CAPI cluster provisioning, and per-provider discovery for GKE, AKS, EKS, + DigitalOcean, Linode, Rancher, Hetzner, and KubeVirt. diff --git a/docs/platform/api/cloud-providers/cloud-providers.md b/docs/platform/api/cloud-providers/cloud-providers.md new file mode 100644 index 0000000..9f6d91b --- /dev/null +++ b/docs/platform/api/cloud-providers/cloud-providers.md @@ -0,0 +1,598 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-cloud-providers-cloud-providers + name: Cloud Providers + parent: api-cloud-providers + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Cloud Providers + +Discovery and provisioning APIs for cloud Kubernetes providers. All paths on this +page are relative to the API base **`/api/v1`** — for example the discovery route +written `GET /clouds/{owner}/providers/gke/projects` is served at +`/api/v1/clouds/{owner}/providers/gke/projects`. + +Except for the public provider list, every endpoint requires a personal access +token: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clouds/appscode/providers/eks/regions +``` + +The per-provider discovery routes talk to the cloud provider's API using a +**stored cloud credential** for the referenced provider under the `{owner}` +scope. If no matching credential is stored for the owner (or the provider needs +extra configuration, such as a configured Rancher client), the route returns an +error. Cloud credentials are managed via the +[user/organization credentials APIs](../../users-settings/authenticated-user.md). + +## Common path parameter + +Every owner-scoped route below takes an `{owner}` path parameter: + +| Name | Type | Description | +|---|---|---| +| `owner` | string | Organization slug or username that owns the stored cloud credentials. | + +Other path parameters (`project`, `region`, `resourcegroup`, `cluster`, `id`) are +described per endpoint. + +## Common response shapes + +Several discovery endpoints share these response schemas. + +`Locations` — a cloud region with its availability zones: + +```json +{ + "region": "us-east1", + "description": "South Carolina", + "zones": ["us-east1-b", "us-east1-c", "us-east1-d"] +} +``` + +`VMInfo` — a machine type / server type: + +```json +{ + "name": "e2-standard-4", + "description": "4 vCPU, 16 GB", + "cpu": 4, + "core": 2, + "memoryMb": 16384, + "disksSizeGb": 0, + "iops": 0, + "shared": false, + "baremetal": false, + "gpus": 0, + "category": "general-purpose", + "family": "e2", + "instanceHypervisor": "kvm", + "architecture": ["amd64"], + "capacityType": ["on-demand", "spot"], + "networkBW": "up to 10 Gbps", + "ebsBW": "", + "monthlyCost": "97.09" +} +``` + +`ClusterInfo` — summary of a managed cluster on the provider (used when listing or +inspecting clusters for import): + +```json +{ + "id": 0, + "displayName": "prod", + "name": "prod", + "uid": "", + "provider": "gce", + "vendor": "gke", + "endpoint": "https://34.x.x.x", + "location": "us-east1", + "project": "my-gcp-project", + "kubernetesVersion": "1.30.1", + "nodeCount": 3, + "createdAt": "2026-01-01T00:00:00Z", + "age": "6mo", + "clusterManagers": ["gke"], + "isCapiClusterUpgradeable": false, + "status": {} +} +``` + +`ClusterInfo` fields include `id`/`uid`/`externalID` identifiers, `displayName` +and `name`, provider metadata (`provider`, `vendor`, `endpoint`, `location`, +`project`), `kubernetesVersion`, `nodeCount`, `createdAt`/`age`, and a +Kubernetes-style `status` object. Not all fields are populated for every provider. + +--- + +## Provider catalog + +### GET /clouds + +Lists the cloud providers the platform supports for cluster provisioning and +discovery. + +- **Auth:** public — no authentication required. +- **Path parameters:** none. +- **Query parameters:** none. + +**Response** `200` — a `CloudProviderList` (a Kubernetes-style list whose `items` +carry the provider name in `metadata.name`): + +```json +{ + "metadata": {}, + "items": [ + { "metadata": { "name": "gce" }, "spec": {} }, + { "metadata": { "name": "digitalocean" }, "spec": {} }, + { "metadata": { "name": "packet" }, "spec": {} }, + { "metadata": { "name": "aws" }, "spec": {} }, + { "metadata": { "name": "azure" }, "spec": {} }, + { "metadata": { "name": "vultr" }, "spec": {} }, + { "metadata": { "name": "linode" }, "spec": {} }, + { "metadata": { "name": "scaleway" }, "spec": {} } + ] +} +``` + +Each item's `spec` may optionally carry `regions` (region + zones + location) and +`machineTypes`, but is typically empty in the list response — use the per-provider +discovery endpoints below to enumerate regions and machine types. + +> **Verified:** `GET` returned `200` against the live platform on 2026-07-14; the +> response shown above is the sanitized live payload. + +--- + +## Provisioning + +### POST /clouds/{owner}/{provider}/cluster + +Provisions a new Cluster API (CAPI) based cluster on the given cloud provider and +imports it into the platform. For `kubevirt` the CAPI cluster config is validated +(worker pools, machine count, cpu, memory are required). + +- **Auth:** token. Requires stored cloud credentials for the referenced provider + under the owner scope. +- **Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `owner` | string | Organization slug or username that owns the cloud credentials. | +| `provider` | string | Target cloud provider name (e.g. `gke`, `aks`, `eks`, `kubevirt`). | + +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `response-id` | string | no | Correlation id for the asynchronous provisioning response. | + +**Request body** — a `ClusterProvisionConfig`: + +```json +{ + "capiClusterConfig": { + "clusterName": "demo", + "region": "us-east1", + "networkCIDR": "10.0.0.0/16", + "kubernetesVersion": "1.30.1", + "googleProjectID": "my-gcp-project", + "controlPlane": { + "machineType": "e2-standard-4", + "machineCount": 1, + "cpu": 4, + "memory": 16384 + }, + "workerPools": [ + { + "machineType": "e2-standard-4", + "machineCount": 3, + "cpu": 4, + "memory": 16384 + } + ] + }, + "importOptions": { + "basicInfo": { "name": "demo", "displayName": "Demo" }, + "provider": { "name": "gce", "credential": "my-gcp-cred" }, + "components": { "fluxCD": true, "allFeatures": false } + } +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `capiClusterConfig` | object | yes | CAPI cluster configuration (see below). | +| `capiClusterConfig.clusterName` | string | — | Name for the new cluster. | +| `capiClusterConfig.region` | string | — | Provider region. | +| `capiClusterConfig.networkCIDR` | string | — | Pod/network CIDR. | +| `capiClusterConfig.kubernetesVersion` | string | — | Kubernetes version. | +| `capiClusterConfig.googleProjectID` | string | — | GCP project id (GKE only). | +| `capiClusterConfig.controlPlane` | object | — | Control-plane machine pool (`machineType`, `machineCount`, `cpu`, `memory` — all required within a pool). | +| `capiClusterConfig.workerPools` | array | — | Worker machine pools; each pool requires `machineType`, `machineCount`, `cpu`, `memory`. | +| `importOptions` | object | — | How to import the resulting cluster: `basicInfo`, `provider` (credential/region/project), and `components` (feature sets, FluxCD). | + +**Response** `200` — a `ProviderOptions` describing the provisioned cluster: + +```json +{ + "name": "demo", + "credential": "my-gcp-cred", + "clusterID": "", + "project": "my-gcp-project", + "region": "us-east1", + "kubeConfig": "" +} +``` + +`ProviderOptions` fields: `name`, `credential`, `eksAuthMode` (`IRSA` or +`PodIdentity`, EKS only), `clusterID`, `project`, `region`, `resourceGroup`, and +`kubeConfig`. Error responses: `400` (invalid CAPI config, e.g. missing worker +pools), `401` (unauthenticated), `403` (forbidden), `422` (body failed +validation). + +> **Not verified:** write endpoint — not called against the live platform per +> GET-only policy. + +--- + +## GKE discovery + +Google Kubernetes Engine discovery routes. All are `GET`, token-authenticated, and +require stored GKE credentials for `{owner}`. + +### GET /clouds/{owner}/providers/gke/projects + +Lists the Google Cloud projects accessible with the stored GKE credentials. + +- **Auth:** token + stored GKE credentials. +- **Response** `200` — an array of project id strings: `["my-gcp-project", "..."]`. + +> **Verified:** returned `302` (redirect to `/500`) against `appscode` on +> 2026-07-14 — no GKE cloud credential is stored for the `appscode` owner, so the +> handler cannot reach the GCP API. + +### GET /clouds/{owner}/providers/gke/projects/{project}/regions/ + +Lists available regions (with zones) for the given GKE project. + +- **Path parameters:** `project` (string) — GKE project id. +- **Response** `200` — an array of [`Locations`](#common-response-shapes). + +> **Verified:** requires stored GKE credentials; not reachable for `appscode` +> (same missing-credential condition as `.../gke/projects`). + +### GET /clouds/{owner}/providers/gke/projects/{project}/regions/{region}/kubernetesversions + +Lists the supported Kubernetes versions for the given GKE project and region. + +- **Path parameters:** `project` (string), `region` (string). +- **Response** `200` — an array of version strings, e.g. `["1.29.5", "1.30.1"]`. + +> **Verified:** requires stored GKE credentials; not reachable for `appscode`. + +### GET /clouds/{owner}/providers/gke/projects/{project}/regions/{region}/vms + +Lists available machine types for the given GKE project, region and zone, grouped +by family. + +- **Path parameters:** `project` (string), `region` (string). +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `zone` | string | yes | GKE zone (e.g. `us-east1-b`). | + +- **Response** `200` — an object mapping family name → array of + [`VMInfo`](#common-response-shapes): + +```json +{ + "e2": [ { "name": "e2-standard-4", "cpu": 4, "memoryMb": 16384 } ], + "n2": [ { "name": "n2-standard-8", "cpu": 8, "memoryMb": 32768 } ] +} +``` + +> **Verified:** requires stored GKE credentials; not reachable for `appscode`. + +### GET /clouds/{owner}/providers/gke/projects/{project}/clusters + +Lists the GKE clusters that exist in the given project. + +- **Path parameters:** `project` (string). +- **Response** `200` — an array of [`ClusterInfo`](#common-response-shapes). + +> **Verified:** requires stored GKE credentials; not reachable for `appscode`. + +### GET /clouds/{owner}/providers/gke/projects/{project}/clusters/{cluster} + +Returns detailed information for a single GKE cluster (for import). + +- **Path parameters:** `project` (string), `cluster` (string) — GKE cluster name. +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `location` | string | no | GKE cluster location. | + +- **Response** `200` — a [`ClusterInfo`](#common-response-shapes). Errors: `404` + (not found), `409` (already imported). + +> **Verified:** requires stored GKE credentials; not reachable for `appscode`. + +--- + +## AKS discovery + +Azure Kubernetes Service discovery routes. All are `GET`, token-authenticated, and +require stored AKS credentials for `{owner}`. + +### GET /clouds/{owner}/providers/aks/regions/ + +Lists the supported Azure (AKS) regions. + +- **Response** `200` — an array of [`Locations`](#common-response-shapes). + +> **Verified:** returned `302` (redirect to `/500`) against `appscode` on +> 2026-07-14 — no AKS cloud credential is stored for the `appscode` owner. + +### GET /clouds/{owner}/providers/aks/regions/{region}/vms + +Lists available machine types for the given AKS region, grouped by family. + +- **Path parameters:** `region` (string). +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `zones` | string | yes | Comma-separated availability zones (e.g. `1,2,3`). | + +- **Response** `200` — an object mapping family name → array of + [`VMInfo`](#common-response-shapes). + +> **Verified:** requires stored AKS credentials; not reachable for `appscode`. + +### GET /clouds/{owner}/providers/aks/regions/{region}/kubernetesversions + +Lists the supported Kubernetes versions for the given AKS region. + +- **Path parameters:** `region` (string). +- **Response** `200` — an array of version strings. + +> **Verified:** requires stored AKS credentials; not reachable for `appscode`. + +### GET /clouds/{owner}/providers/aks/resourcegroups + +Lists the Azure resource groups accessible with the stored AKS credentials. + +- **Response** `200` — an array of resource group name strings. + +> **Verified:** requires stored AKS credentials; not reachable for `appscode`. + +### GET /clouds/{owner}/providers/aks/resourcegroups/{resourcegroup}/clusters + +Lists the AKS managed clusters in the given Azure resource group. + +- **Path parameters:** `resourcegroup` (string). +- **Response** `200` — an array of [`ClusterInfo`](#common-response-shapes). + +> **Verified:** requires stored AKS credentials; not reachable for `appscode`. + +### GET /clouds/{owner}/providers/aks/resourcegroups/{resourcegroup}/clusters/{cluster} + +Returns detailed information for a single AKS cluster (for import). + +- **Path parameters:** `resourcegroup` (string), `cluster` (string). +- **Response** `200` — a [`ClusterInfo`](#common-response-shapes). Errors: `404`, + `409` (import conflict). + +> **Verified:** requires stored AKS credentials; not reachable for `appscode`. + +--- + +## EKS discovery + +Amazon Elastic Kubernetes Service discovery routes. All are `GET`, +token-authenticated, and require stored EKS credentials for `{owner}` (region +listing may fall back to a default credential). + +### GET /clouds/{owner}/providers/eks/regions + +Lists the supported AWS (EKS) regions. If no credential is stored, a default +credential may be used. + +- **Response** `200` — an array of [`Locations`](#common-response-shapes). + +> **Verified:** returned `302` (redirect to `/500`) against `appscode` on +> 2026-07-14 — resolving AWS regions failed with no usable AWS credential for the +> `appscode` owner. + +### GET /clouds/{owner}/providers/eks/regions/{region}/kubernetesversions + +Lists the supported Kubernetes versions for EKS. + +- **Path parameters:** `region` (string). +- **Response** `200` — an array of version strings. + +> **Verified:** requires stored EKS credentials; not reachable for `appscode`. + +### GET /clouds/{owner}/providers/eks/regions/{region}/vms + +Lists available machine types for the given EKS region, grouped by family. + +- **Path parameters:** `region` (string). +- **Response** `200` — an object mapping family name → array of + [`VMInfo`](#common-response-shapes). + +> **Verified:** requires stored EKS credentials; not reachable for `appscode`. + +### GET /clouds/{owner}/providers/eks/regions/{region}/clusters + +Lists the EKS clusters in the given AWS region. + +- **Path parameters:** `region` (string). +- **Response** `200` — an array of [`ClusterInfo`](#common-response-shapes). + +> **Verified:** requires stored EKS credentials; not reachable for `appscode`. + +### GET /clouds/{owner}/providers/eks/regions/{region}/clusters/{cluster} + +Returns detailed information for a single EKS cluster (for import). + +- **Path parameters:** `region` (string), `cluster` (string). +- **Response** `200` — a [`ClusterInfo`](#common-response-shapes). Errors: `404`, + `409` (import conflict). + +> **Verified:** requires stored EKS credentials; not reachable for `appscode`. + +--- + +## DigitalOcean discovery + +DigitalOcean Kubernetes (DOKS) discovery routes. All are `GET`, +token-authenticated, and require stored DigitalOcean credentials for `{owner}`. + +### GET /clouds/{owner}/providers/digitalocean/clusters + +Lists the DigitalOcean managed Kubernetes (DOKS) clusters. + +- **Response** `200` — an array of [`ClusterInfo`](#common-response-shapes). + +> **Verified:** returned `302` (redirect to `/500`) against `appscode` on +> 2026-07-14 — no DigitalOcean cloud credential is stored for the `appscode` +> owner. + +### GET /clouds/{owner}/providers/digitalocean/clusters/{id} + +Returns detailed information for a single DigitalOcean cluster (for import). + +- **Path parameters:** `id` (string) — DigitalOcean cluster id. +- **Response** `200` — a [`ClusterInfo`](#common-response-shapes). Errors: `404`, + `409` (import conflict). + +> **Verified:** requires stored DigitalOcean credentials; not reachable for +> `appscode`. + +--- + +## Linode discovery + +Linode Kubernetes Engine (LKE) discovery routes. All are `GET`, +token-authenticated, and require stored Linode credentials for `{owner}`. + +### GET /clouds/{owner}/providers/linode/clusters + +Lists the Linode Kubernetes Engine (LKE) clusters. + +- **Response** `200` — an array of [`ClusterInfo`](#common-response-shapes). + +> **Verified:** returned `302` (redirect to `/500`) against `appscode` on +> 2026-07-14 — no Linode cloud credential is stored for the `appscode` owner. + +### GET /clouds/{owner}/providers/linode/clusters/{id} + +Returns detailed information for a single Linode cluster (for import). + +- **Path parameters:** `id` (integer, int64) — numeric LKE cluster id. +- **Response** `200` — a [`ClusterInfo`](#common-response-shapes). Errors: `404`, + `409` (import conflict). + +> **Verified:** requires stored Linode credentials; not reachable for `appscode`. + +--- + +## Rancher discovery + +Rancher-managed cluster discovery routes. All are `GET`, token-authenticated, and +require both stored cloud credentials and a configured Rancher client for +`{owner}`. + +### GET /clouds/{owner}/providers/rancher/clusters/ + +Lists the clusters managed by the configured Rancher server. + +- **Response** `200` — an array of [`ClusterInfo`](#common-response-shapes). + +> **Verified:** requires stored credentials and a configured Rancher client; not +> reachable for `appscode`. + +### GET /clouds/{owner}/providers/rancher/clusters/{id} + +Returns detailed information for a single Rancher-managed cluster (for import). + +- **Path parameters:** `id` (string) — Rancher cluster id. +- **Response** `200` — a [`ClusterInfo`](#common-response-shapes). Errors: `404`, + `409` (import conflict). + +> **Verified:** requires stored credentials and a configured Rancher client; not +> reachable for `appscode`. + +--- + +## Hetzner discovery + +Hetzner Cloud discovery routes. All are `GET`, token-authenticated, and require +stored Hetzner credentials for `{owner}`. + +### GET /clouds/{owner}/providers/hetzner/servers + +Lists all Hetzner Cloud server types (machine types). + +- **Response** `200` — an array of [`VMInfo`](#common-response-shapes). + +> **Verified:** returned `302` (redirect to `/500`) against `appscode` on +> 2026-07-14 — no Hetzner cloud credential is stored for the `appscode` owner. + +### GET /clouds/{owner}/providers/hetzner/kubernetesversions + +Lists the supported Kubernetes versions for Hetzner. + +- **Response** `200` — an array of version strings. + +> **Verified:** returned `302` (redirect to `/500`) against `appscode` on +> 2026-07-14 — the handler resolves the Hetzner credential before returning +> versions, and none is stored for `appscode`. + +### GET /clouds/{owner}/providers/hetzner/regions/ + +Lists the available Hetzner Cloud regions (locations). + +- **Response** `200` — an array of [`Locations`](#common-response-shapes). + +> **Verified:** requires stored Hetzner credentials; not reachable for `appscode`. + +### GET /clouds/{owner}/providers/hetzner/regions/{region}/servers + +Lists the Hetzner Cloud server types available in the given region. + +- **Path parameters:** `region` (string) — Hetzner region (location). +- **Response** `200` — an array of [`VMInfo`](#common-response-shapes). + +> **Verified:** requires stored Hetzner credentials; not reachable for `appscode`. + +--- + +## KubeVirt discovery + +### GET /clouds/{owner}/providers/kubevirt/kubernetesversions + +Lists the supported Kubernetes versions for KubeVirt-based clusters. + +- **Auth:** token. +- **Response** `200` — an array of version strings: + +```json +["1.27.14", "1.28.10", "1.29.5", "1.30.1"] +``` + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14 (this list +> is served from static configuration and does not need a cloud credential); the +> response shown above is the sanitized live payload. diff --git a/docs/platform/api/cluster-management-v1/_index.md b/docs/platform/api/cluster-management-v1/_index.md new file mode 100644 index 0000000..2b8d36b --- /dev/null +++ b/docs/platform/api/cluster-management-v1/_index.md @@ -0,0 +1,44 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-cluster-management-v1 + name: Cluster Management v1 + parent: api + weight: 50 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Cluster Management v1 + +The core cluster API. Every endpoint is scoped to a single cluster identified by +`{owner}` (the organization slug or username that owns the cluster) and `{cluster}` +(the cluster name), and is served under: + +``` +/api/v1/clusters/{owner}/{cluster}/... +``` + +All routes require a personal access token sent as +`Authorization: token ` (it may also be supplied as a `token` or +`access_token` query parameter). Cluster routes additionally resolve the cluster's +stored credentials and build a Kubernetes client for it ("cluster assignment"); a +few routes layer on extra authorization checks, which are called out per endpoint. + +This group covers three related surfaces: + +## Pages + +- [Cluster Lifecycle & Info](../lifecycle.md) — get, update, and + delete a cluster; fetch its kubeconfig; discover available resource types; database + status/bundle; feature values; execute whitelisted commands; create resources; + install/uninstall deploy orders; and read resource history. +- [Kubernetes Proxy](../kubernetes-proxy.md) — the generic + `/proxy/*` passthrough for any Kubernetes group/version/resource (CRUD, status, + events, controller, scale, HPAs), plus pod logs/exec, node/pod metrics, access + reviews, the `meta.k8s.appscode.com` render endpoints, scanner/policy reports, and + batch delete. +- [Helm](../helm.md) — Helm console (tiller) configuration, Helm + v3 release management (list/install/upgrade/uninstall/rollback, content, status, + history), bundle/package views, and the resource editor. diff --git a/docs/platform/api/cluster-management-v1/helm.md b/docs/platform/api/cluster-management-v1/helm.md new file mode 100644 index 0000000..267d8a4 --- /dev/null +++ b/docs/platform/api/cluster-management-v1/helm.md @@ -0,0 +1,407 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-cluster-management-v1-helm + name: Helm + parent: api-cluster-management-v1 + weight: 30 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Helm + +Manage Helm on a member cluster: the Helm console (tiller) configuration, Helm v3 +release lifecycle (list/install/upgrade/uninstall/rollback, plus content, status, and +history), chart bundle/package views, and the resource editor used to generate and +apply installations. + +All paths on this page are relative to: + +``` +/api/v1/clusters/{owner}/{cluster} +``` + +All endpoints require a token (`Authorization: token `). Common path +parameters used throughout this page: + +| Name | Type | Description | +|---|---|---| +| `owner` | string | Organization slug or username that owns the cluster. | +| `cluster` | string | Cluster name. | +| `name` | string | Helm release name (on release endpoints). | + +Several install/upgrade/uninstall/rollback/editor operations are submitted as async +tasks and return a `TaskResponse` (`{ "id": "...", "subject": "..." }`) rather than +completing synchronously. Many request/response bodies are opaque Kubernetes-style or +Helm library objects, passed through verbatim; those are noted per endpoint. + +A documented call looks like: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/ace/helm/v3/releases/ +``` + +--- + +## Console (tiller) configuration + +### GET /clusters/{owner}/{cluster}/helm/tiller-config + +Get the Helm console (tiller/driver) config. + +- **Auth:** token. +- **Response:** `200` with a `ConsoleConfig`. + +```json +{ + "id": 1, + "userID": 2, + "clusterID": "", + "type": 1, + "data": { "driver": { "helm3": { "driverName": "Secret" } } }, + "createdUnix": 1783967505, + "updatedUnix": 1783967505 +} +``` + +| Field | Type | Description | +|---|---|---| +| `id` | integer | Config record ID. | +| `userID` | integer | Owning user ID. | +| `clusterID` | string | Cluster UID. | +| `type` | string/int | Setting type (`models.SettingType`). | +| `data` | object | Config payload (e.g. the Helm driver options). | +| `createdUnix` / `updatedUnix` | integer | Unix create/update timestamps. | + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) and +> `appscode/arnob-dev` (spoke) on 2026-07-14. + +### PUT /clusters/{owner}/{cluster}/helm/tiller-config + +Update the Helm console (tiller/driver) config. + +- **Auth:** token. +- **Request body:** a `TillerOptions` object. + +```json +{ "driver": { "helm3": { "driverName": "Secret" } } } +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `driver.helm3.driverName` | string | no | Helm 3 storage driver (e.g. `Secret`, `ConfigMap`). | + +- **Response:** `200` with the updated `ConsoleConfig`. + +### GET /clusters/{owner}/{cluster}/helm/tiller-config/default + +Get the default Helm console (tiller) config. + +- **Auth:** token. +- **Response:** `200` with a `ConsoleConfig` (same shape as above). + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +--- + +## Helm v3 releases + +### GET /clusters/{owner}/{cluster}/helm/v3/releases/ + +List Helm v3 releases in the cluster. + +- **Auth:** token. +- **Request body:** optional Helm list options (`action.ListOptions`), passed as an + opaque object. +- **Response:** `200` with an array of Helm `release.Release` objects. + +```json +[ + { + "name": "ace", + "info": { + "first_deployed": "2026-07-05T06:42:46Z", + "last_deployed": "2026-07-05T06:49:03Z", + "status": "deployed", + "description": "Upgrade complete" + }, + "chart": { "metadata": { "name": "ace" } } + } +] +``` + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) and +> `appscode/arnob-dev` (spoke) on 2026-07-14. + +### POST /clusters/{owner}/{cluster}/helm/v3/releases/ + +Install a Helm v3 release. Submitted as an async task. + +- **Auth:** token. +- **Request body:** Helm install options (`action.InstallOptions`), passed as an + opaque object. +- **Response:** `200` with a `TaskResponse`. + +```json +{ "id": "task-9f8e7d", "subject": "tasks.helm.install" } +``` + +### GET /clusters/{owner}/{cluster}/helm/v3/releases/{name}/ + +Get the revision history of a Helm release. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, plus `name` (release name). +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `max` | integer | no | Maximum number of history revisions to return. | + +- **Response:** `200` with an array of Helm `release.Release` objects (one per + revision); `404` if the release is not found. + +### PUT /clusters/{owner}/{cluster}/helm/v3/releases/{name}/ + +Upgrade a Helm v3 release. Submitted as an async task. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, plus `name` (release name). +- **Request body:** Helm upgrade options (`action.UpgradeOptions`), passed as an + opaque object. +- **Response:** `200` with a `TaskResponse`; `404` if the release is not found. + +### DELETE /clusters/{owner}/{cluster}/helm/v3/releases/{name}/ + +Uninstall a Helm v3 release. Submitted as an async task. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, plus `name` (release name). +- **Request body:** an `UninstallReleaseRequest`. + +```json +{ + "namespace": "default", + "disable_hooks": false, + "purge": true, + "timeout": 300 +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `namespace` | string | no | Namespace of the release. | +| `disable_hooks` | boolean | no | Skip running lifecycle hooks. | +| `purge` | boolean | no | Remove the release history. | +| `timeout` | integer (int64) | no | Operation timeout (seconds). | + +- **Response:** `200` with a `TaskResponse`; `404` if the release is not found. + +### GET /clusters/{owner}/{cluster}/helm/v3/releases/{name}/content + +Get the content (manifest and metadata) of a Helm release. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, plus `name` (release name). +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `version` | integer | no | Specific release revision. | +| `namespace` | string | no | Namespace of the release. | + +- **Response:** `200` with the Helm `release.Release` object. + +### GET /clusters/{owner}/{cluster}/helm/v3/releases/{name}/status + +Get the status of a Helm release. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, plus `name` (release name). +- **Query parameters:** `version` (integer, optional revision) and `namespace` + (string, optional). +- **Response:** `200` with the Helm `release.Release` object. + +### POST /clusters/{owner}/{cluster}/helm/v3/releases/{name}/rollback + +Roll back a Helm v3 release to a previous revision. Submitted as an async task. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, plus `name` (release name). +- **Request body:** a `RollbackReleaseRequest`. + +```json +{ + "namespace": "default", + "version": 2, + "dry_run": false, + "recreate": false, + "wait": true, + "force": false, + "timeout": 300, + "description": "rollback to v2" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `namespace` | string | no | Namespace of the release. | +| `version` | integer (int32) | no | Target revision to roll back to. | +| `dry_run` | boolean | no | Simulate the rollback. | +| `disable_hooks` | boolean | no | Skip lifecycle hooks. | +| `recreate` | boolean | no | Recreate pods. | +| `wait` | boolean | no | Wait until resources are ready. | +| `force` | boolean | no | Force resource updates. | +| `cleanup_on_fail` | boolean | no | Delete new resources on failure. | +| `timeout` | integer (int64) | no | Operation timeout (seconds). | +| `description` | string | no | Rollback description. | + +- **Response:** `200` with a `TaskResponse`; `404` if the release is not found. + +--- + +## Bundle & package views + +These endpoints let you inspect a chart before installing it. The bundle/package +request and response bodies are `releasesapi`/`chartsapi` objects passed through as +opaque objects. + +### GET /clusters/{owner}/{cluster}/helm/bundleview + +Get the bundle view for a chart. + +- **Auth:** token. +- **Request body:** a chart source reference (`releasesapi.ChartSourceFlatRef`). +- **Response:** `200` with the bundle view (`releasesapi.BundleView`). + +### POST /clusters/{owner}/{cluster}/helm/bundleview/orders + +Create an order for a bundle view. + +- **Auth:** token. +- **Request body:** a bundle view (`releasesapi.BundleView`). +- **Response:** `200` with the generated order (`releasesapi.Order`). + +### GET /clusters/{owner}/{cluster}/helm/packageview + +Get the package view for a chart. + +- **Auth:** token. +- **Request body:** a chart source reference (`releasesapi.ChartSourceFlatRef`). +- **Response:** `200` with the package view (`releasesapi.PackageView`). + +### GET /clusters/{owner}/{cluster}/helm/packageview/files + +List the files inside a chart package. + +- **Auth:** token. +- **Request body:** a chart source reference (`releasesapi.ChartSourceFlatRef`). +- **Response:** `200` with an array of file-path strings. + +```json +["Chart.yaml", "values.yaml", "templates/deployment.yaml"] +``` + +### GET /clusters/{owner}/{cluster}/helm/packageview/files/{path} + +Get a single file from a chart package. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, plus `path` (the file path within the chart + package). +- **Request body:** a chart source reference (`releasesapi.ChartSourceFlatRef`). +- **Response:** `200` with the raw file content (`application/octet-stream`; + content-type varies); `404` if the file is not found. + +### POST /clusters/{owner}/{cluster}/helm/packageview/orders + +Create an order for an editor package view / chart. + +- **Auth:** token. +- **Request body:** a chart order (`releasesapi.ChartOrder`). +- **Response:** `200` with the generated order (`releasesapi.Order`). + +### GET /clusters/{owner}/{cluster}/helm/packageview/values + +Get the merged values file for a chart preset. + +- **Auth:** token. +- **Request body:** a chart preset reference (`chartsapi.ChartPresetFlatRef`). +- **Response:** `200` with the merged chart values (a dynamic map). + +--- + +## Resource editor + +The editor generates an editor model from options, previews the resulting manifest +and resources, applies (installs/updates) or deletes an installation, and loads state +back from an existing install. The `options` bodies are arbitrary JSON objects; the +load/apply bodies are `releasesapi` objects passed through opaquely. + +### PUT /clusters/{owner}/{cluster}/helm/options/model + +Generate an editor model from options. + +- **Auth:** token. +- **Request body:** an arbitrary JSON options object. +- **Response:** `200` with the generated editor model (unstructured object; YAML when + requested). + +### PUT /clusters/{owner}/{cluster}/helm/options/manifest + +Preview the editor manifest from options. + +- **Auth:** token. +- **Request body:** an arbitrary JSON options object. +- **Response:** `200` with the rendered manifest as raw `text/plain` YAML. + +### PUT /clusters/{owner}/{cluster}/helm/options/resources + +Preview the editor resources from options. + +- **Auth:** token. +- **Request body:** an arbitrary JSON options object. +- **Response:** `200` with the rendered resources (`releasesapi.ResourceOutput`). + +### PUT /clusters/{owner}/{cluster}/helm/editor/ + +Apply (create/update/install) a resource editor model. Submitted as an async task. + +- **Auth:** token. +- **Request body:** an arbitrary JSON editor model object. +- **Response:** `200` with a `TaskResponse`. + +### DELETE /clusters/{owner}/{cluster}/helm/editor/ + +Delete a resource editor installation. Submitted as an async task. + +- **Auth:** token. +- **Request body:** resource metadata (`releasesapi.MetadataFlat`). +- **Response:** `200` with a `TaskResponse`. + +### PUT /clusters/{owner}/{cluster}/helm/editor/model + +Load an editor model from an existing installation. + +- **Auth:** token. +- **Request body:** an editor model (`releasesapi.Model`). +- **Response:** `200` with the editor model values (raw JSON/YAML). + +### PUT /clusters/{owner}/{cluster}/helm/editor/manifest + +Load the editor manifest from an existing installation. + +- **Auth:** token. +- **Request body:** an editor model (`releasesapi.Model`). +- **Response:** `200` with the rendered manifest as raw `text/plain` YAML. + +### PUT /clusters/{owner}/{cluster}/helm/editor/resources + +Load the editor resources from an existing installation. + +- **Auth:** token. +- **Request body:** editor model metadata (`releasesapi.ModelMetadata`). +- **Response:** `200` with the rendered resources (`releasesapi.ResourceOutput`). diff --git a/docs/platform/api/cluster-management-v1/kubernetes-proxy.md b/docs/platform/api/cluster-management-v1/kubernetes-proxy.md new file mode 100644 index 0000000..53930f1 --- /dev/null +++ b/docs/platform/api/cluster-management-v1/kubernetes-proxy.md @@ -0,0 +1,533 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-cluster-management-v1-kubernetes-proxy + name: Kubernetes Proxy + parent: api-cluster-management-v1 + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Kubernetes Proxy + +A generic passthrough to a member cluster's Kubernetes API, powering the ACE +console's resource pages. You can perform CRUD on any group/version/resource (GVR), +read subresources (status, scale, events, controller), stream pod logs, exec into +pods, read node/pod metrics, run access reviews, drive the `meta.k8s.appscode.com` +render/report endpoints, and batch-delete resources. + +All paths on this page are relative to: + +``` +/api/v1/clusters/{owner}/{cluster} +``` + +All endpoints require a token (`Authorization: token `). Common path +parameters used throughout this page: + +| Name | Type | Description | +|---|---|---| +| `owner` | string | Organization slug or username that owns the cluster. | +| `cluster` | string | Cluster name. | +| `group` | string | Kubernetes API group. Use `core` for the legacy core group. | +| `version` | string | Kubernetes API version (e.g. `v1`). | +| `resource` | string | Kubernetes resource (plural, e.g. `deployments`). | +| `namespace` | string | Namespace (for namespaced paths). | +| `name` | string | Object name. | + +Request and response bodies are arbitrary Kubernetes objects (`K8sObject`) — +free-form objects with an arbitrary group/version/kind, passed to and from the member +cluster verbatim. List responses are Kubernetes list objects; when `convertToTable` +is set they are returned as a `Table`. Most list/get endpoints support standard +Kubernetes label/field selectors as query parameters, plus a `filter` query for +content filtering and `convertToTable` for table output. + +A documented list call looks like: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/ace/proxy/apps/v1/namespaces/kube-system/deployments/ +``` + +--- + +## Cluster-scoped resources + +### POST /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/ + +Create a cluster-scoped Kubernetes object of the given GVR. + +- **Auth:** token. +- **Request body:** an arbitrary Kubernetes object. +- **Response:** `200` with the created object. + +### GET /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/ + +List cluster-scoped resources of the given GVR. Supports label/field selectors, +`filter`, and `convertToTable`. + +- **Auth:** token. +- **Response:** `200` with a Kubernetes list (or a `Table`); `304` when the ETag + matches. + +```json +{ + "apiVersion": "v1", + "kind": "NodeList", + "items": [ + { "apiVersion": "v1", "kind": "Node", "metadata": { "name": "node-1" } } + ] +} +``` + +> **Verified:** `GET .../proxy/core/v1/nodes/` returned `200` against `appscode/ace` +> (hub) on 2026-07-14. + +### DELETE /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/ + +Delete a collection of cluster-scoped resources. The optional request body carries a +`metav1.DeleteOptions` object. + +- **Auth:** token. +- **Response:** `200` on success. + +### GET /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/{name} + +Get a single cluster-scoped resource by name. + +- **Auth:** token. +- **Response:** `200` with the object (or a `Table`); `304` when the ETag matches; + `404` if not found. + +### PUT /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/{name} + +Replace a cluster-scoped resource. + +- **Auth:** token. +- **Request body:** the full replacement Kubernetes object. +- **Response:** `200` with the updated object. + +### PATCH /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/{name} + +Patch a cluster-scoped resource. Supports JSON/merge/strategic-merge patch types via +the `Content-Type` header; a plain JSON body is diffed against the current object to +build a JSON patch. + +- **Auth:** token. +- **Request body:** the patch (or a desired object to diff). +- **Response:** `200` with the patched object. + +### DELETE /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/{name} + +Delete a cluster-scoped resource by name. The optional request body carries +`metav1.DeleteOptions`. + +- **Auth:** token. +- **Response:** `200` on success. + +### PUT · PATCH /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/{name}/status + +Update (PUT) or patch (PATCH) the `status` subresource of a cluster-scoped object. + +- **Auth:** token. +- **Request body:** the object (or patch) carrying the new status. +- **Response:** `200` with the object with updated status. + +### GET /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/{name}/events + +List Kubernetes events referencing the named cluster-scoped object. + +- **Auth:** token. +- **Response:** `200` with an event list. + +### GET /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/{name}/controller + +Get the controlling owner object of the named cluster-scoped object. + +- **Auth:** token. +- **Response:** `200` with the controller object; `404` if none. + +--- + +## Namespaced resources + +These mirror the cluster-scoped operations under a `namespaces/{namespace}` segment. + +### POST /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/ + +Create a namespaced resource of the given GVR. + +- **Auth:** token. +- **Request body:** an arbitrary Kubernetes object. +- **Response:** `200` with the created object. + +### GET /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/ + +List namespaced resources. Supports label/field selectors, `filter`, and +`convertToTable`. + +- **Auth:** token. +- **Response:** `200` with a Kubernetes list (or a `Table`); `304` when the ETag + matches. + +```json +{ + "apiVersion": "apps/v1", + "kind": "DeploymentList", + "items": [ + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { "name": "coredns", "namespace": "kube-system" } + } + ] +} +``` + +> **Verified:** `GET .../proxy/apps/v1/namespaces/kube-system/deployments/` returned +> `200` against `appscode/ace` (hub) and `appscode/arnob-dev` (spoke) on 2026-07-14. + +### DELETE /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/ + +Delete a collection of namespaced resources. Optional body carries +`metav1.DeleteOptions`. + +- **Auth:** token. +- **Response:** `200` on success. + +### GET /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name} + +Get a namespaced resource by name. + +- **Auth:** token. +- **Response:** `200` with the object (or a `Table`); `304` when the ETag matches; + `404` if not found. + +> **Verified:** `GET .../deployments/coredns` returned `200` against `appscode/ace` +> (hub) on 2026-07-14. + +### PUT /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name} + +Replace a namespaced resource. + +- **Auth:** token. +- **Request body:** the full replacement Kubernetes object. +- **Response:** `200` with the updated object. + +### PATCH /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name} + +Patch a namespaced resource (JSON/merge/strategic-merge, or a plain JSON body diffed +against the current object). + +- **Auth:** token. +- **Response:** `200` with the patched object. + +### DELETE /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name} + +Delete a namespaced resource by name. Optional body carries `metav1.DeleteOptions`. + +- **Auth:** token. +- **Response:** `200` on success. + +### PUT · PATCH /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}/status + +Update (PUT) or patch (PATCH) the `status` subresource of a namespaced object. + +- **Auth:** token. +- **Response:** `200` with the object with updated status. + +### GET /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}/events + +List Kubernetes events referencing the named namespaced object. + +- **Auth:** token. +- **Response:** `200` with an event list. + +> **Verified:** `GET .../deployments/coredns/events` returned `200` against +> `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}/controller + +Get the controlling owner object of the named namespaced object. + +- **Auth:** token. +- **Response:** `200` with the controller object; `404` if none. + +--- + +## Scale & autoscaling + +### GET /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}/scale + +Read the `scale` subresource of a namespaced object. + +- **Auth:** token. +- **Response:** `200` with the scale object. + +> **Verified:** `GET .../deployments/coredns/scale` returned `200` against +> `appscode/ace` (hub) on 2026-07-14. + +### PUT /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}/scale + +Update the replica count of a namespaced object via its `scale` subresource. + +- **Auth:** token. +- **Request body:** + +```json +{ "replicas": 3 } +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `replicas` | integer (int32) | yes | Desired replica count. | + +- **Response:** `200` with the updated scale object. + +### GET /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}/horizontalpodautoscalers + +List the HorizontalPodAutoscalers whose scale target matches the named namespaced +object. + +- **Auth:** token. +- **Response:** `200` with a filtered HPA list. + +--- + +## Pods: logs, exec & metrics + +### GET /clusters/{owner}/{cluster}/proxy/core/v1/namespaces/{namespace}/{resource}/{name}/log + +Stream container logs for the named pod. The response is a streaming plain-text body. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, `namespace`, `resource` (`pods`), `name`. +- **Response:** `200` streaming `text/plain` log output; `404` if the pod is not + found. + +### GET /clusters/{owner}/{cluster}/proxy/core/v1/namespaces/{namespace}/{resource}/{name}/exec + +Establish an interactive exec session into a container of the named pod. This +endpoint is upgraded to a **WebSocket** connection — it is not a plain HTTP +request/response. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, `namespace`, `resource` (`pods`), `name`. +- **Response:** `101` Switching Protocols (WebSocket exec stream); `404` if the pod is + not found. + +### GET /clusters/{owner}/{cluster}/proxy/core/v1/nodes/{name}/metrics + +Get resource-usage metrics for the named node. + +- **Auth:** token. +- **Response:** `200` with a metrics object; `404` if the node is not found. + +### GET /clusters/{owner}/{cluster}/proxy/core/v1/namespaces/{namespace}/pods/{name}/metrics + +Get resource-usage metrics for the named pod. + +- **Auth:** token. +- **Response:** `200` with a metrics object; `404` if the pod is not found. + +--- + +## Access reviews & discovery + +### POST /clusters/{owner}/{cluster}/proxy/authorization.k8s.io/v1/selfsubjectaccessreviews + +Submit a `SelfSubjectAccessReview` to check whether the current user can perform an +action ("can I" check). + +- **Auth:** token. +- **Request body:** a `SelfSubjectAccessReview` Kubernetes object. + +```json +{ + "apiVersion": "authorization.k8s.io/v1", + "kind": "SelfSubjectAccessReview", + "spec": { + "resourceAttributes": { + "namespace": "default", + "verb": "list", + "resource": "pods" + } + } +} +``` + +- **Response:** `200` with the review and its populated `status`. + +### GET /clusters/{owner}/{cluster}/proxy/{group}/{version}/all-available + +Discover all resources under the given API group/version and return, per Kind, the +list of object names available in the cluster. + +- **Auth:** token. +- **Response:** `200` with a map of Kind to an array of object names. + +```json +{ + "Deployment": ["coredns", "metrics-server"], + "StatefulSet": ["prometheus"] +} +``` + +> **Verified:** returned `404` against `appscode/ace` for `apps/v1` and `core/v1` — +> this discovery endpoint was not available/enabled on the verification cluster. + +--- + +## Render endpoints (meta.k8s.appscode.com) + +These endpoints render `meta.k8s.appscode.com/v1alpha1` UI objects. They are +implemented as **cacheable creates**: the request object is passed JSON-encoded via +the `q` query parameter so the response can be cached (supporting `304 Not Modified` +via ETags). + +Common query parameter: + +| Name | Type | Required | Description | +|---|---|---|---| +| `q` | string | yes | JSON-encoded request object for the render. | + +### GET /clusters/{owner}/{cluster}/proxy/meta.k8s.appscode.com/v1alpha1/renders + +Render a `Render` object (resource layout). + +- **Auth:** token. +- **Response:** `200` with the rendered object; `304` when the ETag matches. + +### GET /clusters/{owner}/{cluster}/proxy/meta.k8s.appscode.com/v1alpha1/renderdashboards + +Render a `RenderDashboard` object. + +- **Auth:** token. +- **Response:** `200` with the rendered dashboards object; `304` when the ETag + matches. + +### GET /clusters/{owner}/{cluster}/proxy/meta.k8s.appscode.com/v1alpha1/rendermenus + +Render a `RenderMenu` object. + +- **Auth:** token. +- **Response:** `200` with the rendered menus object; `304` when the ETag matches. + +> **Verified:** returned `400` against `appscode/ace` when passed a minimal `q` +> object — the endpoint is reachable but requires a fully-formed `RenderMenu` request +> object; only GET was exercised. + +### GET /clusters/{owner}/{cluster}/proxy/meta.k8s.appscode.com/v1alpha1/resourcegraphs + +Render a `ResourceGraph` object. + +- **Auth:** token. +- **Response:** `200` with the rendered resource-graph object; `304` when the ETag + matches. + +### GET /clusters/{owner}/{cluster}/proxy/meta.k8s.appscode.com/v1alpha1/{resource}/{menu}/available + +Get the available user menu entries for the given `meta.k8s.appscode.com` resource and +menu. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, plus `resource` (the + `meta.k8s.appscode.com` resource name) and `menu` (menu identifier). +- **Response:** `200` with an available-user-menus object. + +--- + +## Scanner & policy reports + +Like the render endpoints, these are cacheable creates driven by a JSON-encoded `q` +query parameter. + +| Name | Type | Required | Description | +|---|---|---|---| +| `q` | string | yes | JSON-encoded report request object. | + +### GET /clusters/{owner}/{cluster}/proxy/reports.scanner.appscode.com/v1alpha1/images + +Produce a `reports.scanner.appscode.com` `Image` report. + +- **Auth:** token. +- **Response:** `200` with the image report object; `304` when the ETag matches. + +> **Verified:** returned `500` against `appscode/ace` when the `q` query parameter is +> omitted — the endpoint requires a JSON-encoded `Image` report request object; only +> GET was exercised. + +### GET /clusters/{owner}/{cluster}/proxy/reports.scanner.appscode.com/v1alpha1/cvereports + +Produce a `reports.scanner.appscode.com` `CVEReport`. + +- **Auth:** token. +- **Response:** `200` with the CVE report object; `304` when the ETag matches. + +### GET /clusters/{owner}/{cluster}/proxy/policy.k8s.appscode.com/v1alpha1/policyreports + +Produce a `policy.k8s.appscode.com` `PolicyReport`. + +- **Auth:** token. +- **Response:** `200` with the policy report object; `304` when the ETag matches. + +> **Verified:** returned `500` against `appscode/ace` when the `q` query parameter is +> omitted — the endpoint requires a JSON-encoded `PolicyReport` request object; only +> GET was exercised. + +--- + +## Batch delete + +### POST /clusters/{owner}/{cluster}/proxy/batch-delete + +Delete multiple Kubernetes objects in a single request. Each entry is deleted +independently; the response reports the per-resource deletion status for any that +failed. + +- **Auth:** token. +- **Request body:** a `BatchDeleteRequest`. + +```json +{ + "resources": [ + { + "namespace": "default", + "name": "example", + "group": "", + "version": "v1", + "resource": "configmaps" + } + ] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `resources` | array | yes | The resources to delete. | +| `resources[].namespace` | string | no | Namespace (empty for cluster-scoped resources). | +| `resources[].name` | string | no | Object name. | +| `resources[].group` | string | no | Kubernetes API group. | +| `resources[].version` | string | no | Kubernetes API version. | +| `resources[].resource` | string | no | Kubernetes resource (plural). | + +- **Response:** `200` with a `BatchDeleteResponse`. The `resourcesStatus` array is + populated for resources whose deletion failed, each carrying its identifiers plus a + `metav1.Status` describing the result. + +```json +{ + "resourcesStatus": [ + { + "namespace": "default", + "name": "example", + "group": "", + "version": "v1", + "resource": "configmaps", + "status": { "kind": "Status", "status": "Failure", "message": "not found" } + } + ] +} +``` diff --git a/docs/platform/api/cluster-management-v1/lifecycle.md b/docs/platform/api/cluster-management-v1/lifecycle.md new file mode 100644 index 0000000..421f31a --- /dev/null +++ b/docs/platform/api/cluster-management-v1/lifecycle.md @@ -0,0 +1,361 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-cluster-management-v1-lifecycle + name: Cluster Lifecycle & Info + parent: api-cluster-management-v1 + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Cluster Lifecycle & Info + +Manage the lifecycle of an imported cluster and read information about it. All paths +on this page are relative to: + +``` +/api/v1/clusters/{owner}/{cluster} +``` + +All endpoints require a token (`Authorization: token `). `{owner}` is the +organization slug or username that owns the cluster, and `{cluster}` is the cluster +name. Common path parameters used throughout this page: + +| Name | Type | Description | +|---|---|---| +| `owner` | string | Organization slug or username that owns the cluster. | +| `cluster` | string | Cluster name. | + +A documented call looks like: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/ace/ +``` + +--- + +## Cluster details + +### GET /clusters/{owner}/{cluster}/ + +Get summary information about a cluster. + +- **Auth:** token. +- **Response:** `200` with a `ClusterInfo` object. + +```json +{ + "id": 2, + "displayName": "ace", + "name": "ace", + "uid": "", + "ownerID": 3, + "externalID": "", + "ownerName": "appscode", + "provider": "Generic", + "vendor": "", + "infraNamespace": "", + "isMonitoringCluster": false, + "endpoint": "https://:6443", + "location": "", + "project": "", + "kubernetesVersion": "v1.36.2+k3s1", + "nodeCount": 1, + "createdAt": "2026-07-05T06:49:31Z", + "age": "8d", + "clusterManagers": ["ACE", "OCMHub"], + "status": { "response": { "phase": "Active" } } +} +``` + +Key fields: `name`/`displayName`/`uid` identify the cluster, `ownerName`/`ownerID` +the owning account, `provider`/`vendor`/`kubernetesVersion`/`nodeCount` describe the +Kubernetes cluster, `clusterManagers` lists the managers (e.g. `ACE`, `OCMHub`, +`Rancher`), and `status` is a Kubernetes-style `ClusterStatus` object. + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) and `appscode/arnob-dev` (spoke) on 2026-07-14. + +### PUT /clusters/{owner}/{cluster}/ + +Update an imported cluster's import options (display name, provider, kubeconfig). + +- **Auth:** token + `authzCheck(update:cluster)` (Cluster_Editor). +- **Request body:** an `ImportClusterOption`. + +```json +{ + "displayName": "my-cluster", + "name": "my-cluster", + "provider": "Generic", + "kubeConfig": "" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `displayName` | string | no | Human-friendly name. | +| `name` | string | no | Cluster name. | +| `provider` | string | yes | Cluster provider (e.g. `Generic`, `GKE`, `EKS`). | +| `kubeConfig` | string | yes | Raw kubeconfig for the cluster. | + +- **Response:** `200` with the persisted cluster info model (`ClusterInfoModel`, an + open/DB-backed object). + +### DELETE /clusters/{owner}/{cluster}/ + +Submit a cluster deletion command as an async task. Returns the command to run rather +than deleting synchronously. + +- **Auth:** token + `authzCheck(delete:cluster)` (Cluster_Editor). +- **Response:** `200` with a `TaskResponse`. + +```json +{ "id": "task-1a2b3c", "subject": "tasks.cluster.delete" } +``` + +### POST /clusters/{owner}/{cluster}/remove + +Remove a cluster's registration from ACE (does not delete the underlying cluster). + +- **Auth:** token. +- **Response:** `200` with an empty body. + +--- + +## Cluster access & discovery + +### GET /clusters/{owner}/{cluster}/client-config + +Get the cluster's client kubeconfig, returned as a JSON string. + +- **Auth:** token + `authzCheck(view:kube-config)` (Cluster_CanViewKubeconfig). +- **Response:** `200` with the kubeconfig as a JSON-encoded string. + +```json +"apiVersion: v1\nkind: Config\nclusters:\n- cluster: { ... }\n..." +``` + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/available-types + +Discover the resource types available in the cluster. Returns a nested mapping of +`group -> version -> [ { Kind, Resource } ]`. + +- **Auth:** token. +- **Response:** `200` with a dynamic object. + +```json +{ + "": { + "v1": [ + { "Kind": "ConfigMap", "Resource": "configmaps" }, + { "Kind": "Pod", "Resource": "pods" }, + { "Kind": "Endpoints", "Resource": "endpoints" } + ] + }, + "apps": { + "v1": [ + { "Kind": "Deployment", "Resource": "deployments" } + ] + } +} +``` + +The empty-string key (`""`) is the legacy Kubernetes core group. + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) and `appscode/arnob-dev` (spoke) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/is-server + +Check whether this cluster is the ACE server (hub) cluster. + +- **Auth:** token. +- **Response:** `200` with `{"server": "yes"|"no"}`. + +```json +{ "server": "yes" } +``` + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub, `"server":"yes"`) on 2026-07-14. + +--- + +## Database & features + +### GET /clusters/{owner}/{cluster}/db-status + +Get a dynamic map of database feature gates / status for the cluster. + +- **Auth:** token. +- **Response:** `200` with a dynamic map (empty `{}` when no DB features are present). + +```json +{} +``` + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/db-bundle + +Get database bundle information — a dynamic map of string to an array of strings. + +- **Auth:** token. +- **Response:** `200` with a dynamic map. + +```json +{ + "kubedb": ["MongoDB", "PostgreSQL", "MySQL"] +} +``` + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/feature/factory-values + +Get the factory (default) values for one or more features. + +- **Auth:** token. +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `features` | string | yes | Feature name(s) to fetch default values for. | + +- **Response:** `200` with a dynamic map of factory feature values. + +> **Verified:** `GET` returned `200` against `appscode/ace` with `?features=kubedb`; +> returned `400` (`missing features query parameter`) when the `features` query +> parameter is omitted, on 2026-07-14. + +### POST /clusters/{owner}/{cluster}/update-presets/{preset} + +Update the named preset in a spoke cluster by applying the supplied FluxCD +`HelmRelease` object. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, plus `preset` (string, the preset name). +- **Request body:** an arbitrary FluxCD `HelmRelease` Kubernetes object. See the + [Kubernetes proxy](../kubernetes-proxy.md) page for how + arbitrary Kubernetes objects are passed through verbatim. +- **Response:** `200` with an empty body. + +--- + +## Commands & resources + +### POST /clusters/{owner}/{cluster}/execute-command + +Run one of the whitelisted `kubectl` plugin commands against the cluster +(`kubectl-kubestash`, `kubectl-stash`, `kubectl-dba`, `kubectl-vault`). + +- **Auth:** token. +- **Request body:** an `ExecuteCommandPayload`. + +```json +{ "command": "kubectl-dba version --client" } +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `command` | string | yes | The whitelisted command to execute. | + +- **Response:** `200` with a `CommandResponse`. + +```json +{ "stdout": "kubectl-dba version ...", "stderr": "" } +``` + +Returns `422` for an invalid or unsupported command. + +### POST /clusters/{owner}/{cluster}/resources + +Create a generic Kubernetes resource in the cluster. + +- **Auth:** token. +- **Request body:** the raw YAML/JSON of any Kubernetes object (parsed into an + unstructured object). This is an arbitrary Kubernetes object rather than a fixed + schema. + +```json +{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": { "name": "example", "namespace": "default" }, + "data": { "key": "value" } +} +``` + +- **Response:** `200` with the created Kubernetes object. + +--- + +## Deploy orders + +### POST /clusters/{owner}/{cluster}/deploy/{id} + +Install a previously generated product deploy order (`order.yaml` identified by +`{id}`) into the cluster. No request body. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, plus `id` (string, the deploy order ID). +- **Response:** `200` (empty body). `404` if the deploy order is not found. + +### DELETE /clusters/{owner}/{cluster}/deploy/{id} + +Uninstall the product deploy order identified by `{id}` from the cluster. No request +body. + +- **Auth:** token. +- **Path parameters:** `owner`, `cluster`, plus `id` (string, the deploy order ID). +- **Response:** `200` (empty body). `404` if the deploy order is not found. + +--- + +## Resource history + +### GET /clusters/{owner}/{cluster}/resource-history + +Get the change history for resources from NATS, optionally filtered by query +parameters. + +- **Auth:** token. +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `product` | string | no | Filter by product. | +| `group` | string | no | Filter by Kubernetes API group. | +| `resource` | string | no | Filter by resource (plural). | +| `rid` | string | no | Filter by resource ID. | + +- **Response:** `200` with a `BadgerEntryList`. + +```json +{ + "items": [ + { + "key": "kubedb.com/mongodbs/", + "values": [ + { + "resourceID": { "group": "kubedb.com", "kind": "MongoDB", "name": "mongo-1" }, + "licenseID": "", + "version": 3, + "timestamp": 1783967505 + } + ], + "lastSeen": 1783967505 + } + ] +} +``` + +Each entry has a `key`, one or more `values` (each carrying the `resource`, +`resourceID`, `licenseID`, `version`, and `timestamp`), and a `lastSeen` timestamp. + +> **Verified:** returned `500` (`nats: no responders available for request`) against +> `appscode/ace` — this endpoint depends on the NATS resource-history responder, +> which was not available on the verification cluster. diff --git a/docs/platform/api/cluster-management-v2/_index.md b/docs/platform/api/cluster-management-v2/_index.md new file mode 100644 index 0000000..8e42c7e --- /dev/null +++ b/docs/platform/api/cluster-management-v2/_index.md @@ -0,0 +1,43 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-cluster-management-v2 + name: Cluster Management v2 + parent: api + weight: 60 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Cluster Management v2 + +The Cluster Management v2 API is the newer, hub-aware cluster surface served under +`/api/v1/clustersv2`. It builds on [Cluster Management v1](../../cluster-management-v1/) +and adds: + +- **Hub awareness** — list hub clusters, resolve hub connection info, and check hub + presence for an owner (Open Cluster Management, or OCM, integration). +- **Import & lifecycle** — check/validate/import clusters, connect or re-connect to an + already-imported cluster, reconcile Helm releases, reconfigure components, and remove + a cluster. +- **Kubernetes version upgrades** — inspect upgradeable versions and trigger CAPI + cluster upgrades. +- **Gateway configurations** — list gateway configs and update them to the current ACE + chart version. +- **vcluster support** — create or import virtual clusters on a host cluster. +- **Inbox subscriptions** — subscribe the current user to cluster-, namespace-, or + resource-level inbox notifications, plus obtain an inbox agent token for a cluster. + +All routes require a personal access token (`Authorization: token `). Most routes are +scoped to an `owner` (organization slug or username) and, for cluster-scoped routes, a +`cluster` name; a few (skip-credentials, all-hubs, identity, all-clusters) require +site-admin privileges. + +## Pages + +- [Clusters](../clusters.md) — providers, hubs, cluster identity, + listing, status, import/connect/remove, reconcile, reconfigure, Kubernetes version + upgrades, gateway configs, feature conversion, and vclusters. +- [Subscriptions & Inbox](../subscriptions.md) — cluster, + namespace, and resource notification subscriptions, plus the inbox agent token. diff --git a/docs/platform/api/cluster-management-v2/clusters.md b/docs/platform/api/cluster-management-v2/clusters.md new file mode 100644 index 0000000..caea3f0 --- /dev/null +++ b/docs/platform/api/cluster-management-v2/clusters.md @@ -0,0 +1,879 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-cluster-management-v2-clusters + name: Clusters + parent: api-cluster-management-v2 + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Clusters (v2) + +Cluster lifecycle and hub-aware operations under `/api/v1/clustersv2`. All paths on this +page are relative to `/api/v1`; the full path for the first endpoint, for example, is +`/api/v1/clustersv2/providers/{provider}/skip-credentials`. + +Common conventions: + +- **owner** — the organization slug or username that owns the cluster (e.g. `appscode`). +- **cluster** — the cluster name within that owner's scope (e.g. `ace`, `arnob-dev`, + `arnob-monitoring`). +- **Auth** — every endpoint requires a token unless noted; send it as + `Authorization: token ` (or a `token` / `access_token` query parameter). +- **K8s object responses** — some endpoints return an arbitrary Kubernetes object or + list (for example an `UnstructuredList` of `clusterprofiles`, a `ConfigMapList`, or a + cluster `status`). These are passed through verbatim from the member cluster and are + documented as opaque objects rather than fixed schemas. + +Example request: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clustersv2/appscode/ace/status +``` + +--- + +## Provider & hub discovery + +### GET /clustersv2/providers/{provider}/skip-credentials + +Check whether manual cloud credentials can be skipped for a provider. Only EKS is +supported; it verifies the current environment has the AWS IAM permissions needed to skip +manual credentials. + +**Auth:** token. Requires **site-admin** privileges +(`admin_of_administrative_org:site_admin`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| provider | string | Cloud provider identifier. Only `eks` is supported. | + +**Response:** `200` when credentials can be skipped, `400` when they cannot (unsupported +provider or insufficient permissions). Both return a `SkipCredentialsResponse`: + +```json +{ + "skipCredentials": true, + "reason": "", + "message": "IAM permissions verified" +} +``` + +| Field | Type | Description | +|---|---|---| +| skipCredentials | boolean | Whether credentials can be skipped. | +| reason | string | Machine-readable reason (when not skippable). | +| message | string | Human-readable detail. | + +> **Verified:** `GET` returned `400` for `providers/eks/skip-credentials` on 2026-07-14 — this ACE instance is not an EKS environment with the required IAM permissions, which is the expected non-skippable outcome. + +--- + +### GET /clustersv2/all-hubs + +List all hub clusters owned by the user across their organizations. + +**Auth:** token. + +**Response:** `200` — an array of `HubCluster`. `400` if the user owns no organization. + +```json +[ + { + "name": "ace", + "ownerName": "appscode", + "displayName": "ace", + "hubClusterUID": "", + "spokeClusters": 0, + "addOns": 0, + "clusterNode": 1, + "provider": "Generic", + "hubType": "OCM", + "locations": "", + "age": "43m", + "createdAt": "2026-07-05T06:49:31Z" + } +] +``` + +| Field | Type | Description | +|---|---|---| +| name | string | Hub cluster name. | +| ownerName | string | Owner (org/user) name. | +| displayName | string | Display name. | +| hubClusterUID | string | Hub cluster UID. | +| spokeClusters | integer | Number of spoke clusters. | +| addOns | integer | Number of add-ons installed. | +| clusterNode | integer | Node count. | +| provider | string | Cloud/infra provider. | +| hubType | string | Hub type (e.g. `OCM`). | +| locations | string | Locations summary. | +| age | string | Human-readable age. | +| createdAt | string (date-time) | Creation timestamp. | + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14 (one hub, `ace`). + +--- + +### GET /clustersv2/{owner}/hub-info + +Get hub cluster connection info (API server and token) for the owner's OCM hub clusters. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | + +**Response:** `200` — a map keyed by cluster name; each value contains `apiServer` and a +bearer `token`. `400` if listing OCM manager clusters fails. + +```json +{ + "ace": { + "apiServer": "https://:6443", + "token": "" + } +} +``` + +> **Note:** the `token` value is a live service-account bearer token — treat it as a +> secret. + +> **Verified:** `GET` returned `200` against `appscode` (hub `ace`) on 2026-07-14. + +--- + +### GET /clustersv2/{owner}/has-hub + +Check whether the owner has any hub cluster. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | + +**Response:** `200` — `{ "has-hub": }`. `400` if listing OCM manager clusters +fails. + +```json +{ "has-hub": true } +``` + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14 (`{"has-hub":true}`). + +--- + +### GET /clustersv2/cluster-profiles + +List available cluster profiles. + +**Auth:** token. + +**Response:** `200` — an `UnstructuredList` of `clusterprofiles` +(`meta.k8s.appscode.com/v1alpha1`). This is an arbitrary Kubernetes list object; see the +[cluster features guide](../../../guides/cluster-management/cluster-features.md) for how +profiles are used. + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +--- + +### GET /clustersv2/identity/{clusterID} + +Get cluster identity metadata by cluster UID. + +**Auth:** token. (Used for cross-cluster identity resolution; intended for +platform/admin flows.) + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| clusterID | string | Cluster UID. | + +**Response:** `200` — a `ClusterMetadata` object. `404` if the cluster info is not found. + +```json +{ + "uid": "", + "name": "ace", + "displayName": "ace", + "provider": "Generic", + "ownerID": "3", + "ownerType": "org", + "apiEndpoint": "https://:6443", + "caBundle": "", + "managerID": "", + "hubClusterID": "", + "cloudServiceAuthMode": "", + "mode": "prod" +} +``` + +| Field | Type | Description | +|---|---|---| +| uid | string | Cluster UID. | +| name | string | Cluster name. | +| displayName | string | Display name. | +| provider | string | Provider. | +| ownerID | string | Owner ID. | +| ownerType | string | Owner type (org/user). | +| apiEndpoint | string | Kubernetes API server endpoint. | +| caBundle | string | Base64-encoded CA bundle. | +| managerID | string | Managing cluster ID. | +| hubClusterID | string | Hub cluster UID. | +| cloudServiceAuthMode | string | Cloud service auth mode. | +| mode | string | One of `prod`, `qa`, `staging`, `dev`. | + +> **Verified:** `GET` returned `404` for the hub cluster UID on 2026-07-14 — the identity +> registry lookup is keyed differently from the imported-cluster list, so this UID is not +> resolvable here on this instance (the route itself is reachable and authorized). + +--- + +## Listing & status + +### GET /clustersv2/{owner}/all-clusters + +List all imported clusters for an owner. + +**Auth:** token. Requires **site-admin** privileges (`view_orgs:site_admin`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | + +**Response:** `200` — an array of `ClusterInfo` (see the schema under +[`GET /clustersv2/{owner}`](#get-clustersv2owner)). + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +--- + +### GET /clustersv2/{owner} + +List clusters for an owner (each with a resolved provider). + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | + +**Response:** `200` — an array of `ClusterInfo`: + +```json +[ + { + "id": 2, + "displayName": "ace", + "name": "ace", + "uid": "", + "ownerID": 3, + "ownerName": "appscode", + "provider": "Generic", + "vendor": "", + "infraNamespace": "", + "isMonitoringCluster": false, + "endpoint": "https://:6443", + "kubernetesVersion": "v1.36.2+k3s1", + "nodeCount": 1, + "createdAt": "2026-07-05T06:49:31Z", + "age": "43m", + "clusterManagers": ["ACE", "OCMHub"], + "isCapiClusterUpgradeable": false, + "status": { "response": { "phase": "Registered" } } + } +] +``` + +| Field | Type | Description | +|---|---|---| +| id | integer (int64) | Internal cluster record ID. | +| displayName | string | Display name. | +| name | string | Cluster name. | +| uid | string | Cluster UID. | +| ownerID | integer (int64) | Owner ID. | +| managerID | integer (int64) | Managing cluster ID. | +| externalID | string | External (provider) ID. | +| hubClusterName / hubClusterUID / hubClusterOwnerName | string | Associated hub cluster. | +| clusterSetName | string | Cluster-set name. | +| ownerName | string | Owner (org/user) name. | +| provider | string | Provider (e.g. `Generic`, `eks`). | +| vendor | string | Kubernetes vendor. | +| infraNamespace | string | Infrastructure namespace. | +| isMonitoringCluster | boolean | Whether this is a monitoring cluster. | +| endpoint | string | Kubernetes API endpoint. | +| location / project | string | Location / project. | +| kubernetesVersion | string | Kubernetes version. | +| nodeCount | integer (int32) | Node count. | +| createdAt | string (date-time) | Creation time. | +| age | string | Human-readable age. | +| clusterManagers | string[] | Managers (e.g. `ACE`, `OCMHub`). | +| isCapiClusterUpgradeable | boolean | Whether a CAPI upgrade is available. | +| status | object | Kubernetes-style `ClusterStatus` (opaque). | + +> **Verified:** `GET` returned `200` against `appscode` on 2026-07-14. + +--- + +### GET /clustersv2/{owner}/{cluster}/exist + +Check whether the cluster is imported for the given owner. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | + +**Response:** `200` — `{ "exist": }`. + +```json +{ "exist": true } +``` + +> **Verified:** `GET` returned `200` against `appscode/arnob-dev` on 2026-07-14 (`{"exist":true}`). + +--- + +### GET /clustersv2/{owner}/{cluster}/status + +Get the current status of a cluster. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | + +**Response:** `200` — a `ClusterInfo` with its `status` field resolved (same schema as +[`GET /clustersv2/{owner}`](#get-clustersv2owner)). + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14; also +> `200` against `appscode/arnob-monitoring` (spoke). + +--- + +## Lifecycle & reconciliation + +### GET /clustersv2/{owner}/{cluster}/reconcile + +Reconcile Helm releases for the specified features. Adds reconcile annotations to the +`HelmRelease` objects of the features passed in the `features` query parameter. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| features | string | No | Comma-separated list of feature names to reconcile. | + +**Response:** `200` when reconcile is triggered. `400` if a feature or its `HelmRelease` +is not found. + +> **Verified:** `GET` returned `500` against `appscode/ace` on 2026-07-14 when called +> with no `features` argument — the handler requires valid feature names to resolve +> `HelmRelease` objects. + +--- + +### POST /clustersv2/{owner}/check + +Check whether a cluster already exists / is importable. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | + +**Request body:** a `CheckOptions` object. + +```json +{ + "basicInfo": { + "name": "my-cluster", + "displayName": "My Cluster", + "clusterUID": "" + }, + "provider": { + "name": "eks", + "credential": "aws-cred", + "region": "us-east-1", + "clusterID": "my-eks" + } +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| basicInfo | object (`BasicInfo`) | No | Cluster basic info (name, displayName, ownerID, managerID, userID, clusterUID, hubClusterID, infraNamespace). | +| provider | object (`ProviderOptions`) | No | Provider details (name, credential, eksAuthMode `IRSA`/`PodIdentity`, clusterID, project, region, resourceGroup, kubeConfig). | + +**Response:** `200` — a `ClusterInfo` describing existence / import status. `422` for an +invalid body. + +--- + +### POST /clustersv2/{owner}/validate + +Validate cluster import options. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| operation | string | No | Set to `connect` to skip Flux/feature-set detection. | + +**Request body:** an `ImportOptions` object. + +```json +{ + "basicInfo": { "name": "my-cluster", "displayName": "My Cluster" }, + "provider": { "name": "eks", "credential": "aws-cred", "region": "us-east-1" }, + "components": { + "fluxCD": true, + "allFeatures": false, + "clusterProfile": "default", + "featureSets": [ { "name": "opscenter-core", "features": ["kube-ui-server"] } ] + } +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| basicInfo | object (`BasicInfo`) | No | Cluster basic info. | +| provider | object (`ProviderOptions`) | No | Provider details. | +| components | object (`ComponentOptions`) | No | Components to install: `fluxCD` (bool), `featureSets` (array of `{name, features[]}`), `allFeatures` (bool), `clusterProfile` (string), `monitoringClusterName` (string), `spokeComponent` (bool). | + +**Response:** `200` — a `ValidationResponse`: + +```json +{ + "alreadyImported": false, + "displayName": { "valid": true, "reason": "" }, + "clusterId": { "valid": true, "reason": "" }, + "message": "", + "monitoringClusterList": ["arnob-monitoring"] +} +``` + +| Field | Type | Description | +|---|---|---| +| alreadyImported | boolean | Whether the cluster is already imported. | +| displayName / clusterId | object (`FieldValidation`) | Per-field `{valid, reason}`. | +| fluxCD / availableFeatureSets / clusterAPI | object | Opaque Kubernetes objects (detected state). | +| message | string | Validation message. | +| clusterMetadata | object (`ClusterMetadata`) | Detected cluster metadata. | +| monitoringClusterList | string[] | Candidate monitoring clusters. | + +`422` for an invalid body. + +--- + +### POST /clustersv2/{owner}/import + +Import a cluster. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | + +**Request body:** an `ImportOptions` object (same schema as +[`/validate`](#post-clustersv2ownervalidate)). + +**Response:** `200` — the imported `ClusterInfo`. `422` for an invalid body. + +--- + +### POST /clustersv2/{owner}/{cluster}/connect + +Connect (or re-connect) to an already-imported cluster. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| operation | string | No | Set to `re-connect` to update existing credentials. | + +**Request body:** a `ConnectOptions` object. + +```json +{ + "name": "my-cluster", + "credential": "aws-cred", + "kubeConfig": "" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| name | string | No | Cluster name. | +| credential | string | No | Stored cloud credential name. | +| kubeConfig | string | No | Kubeconfig contents. | + +**Response:** `200` — `ClusterInfo` after connecting. `400` if connecting fails (e.g. +existing user auth on a non-reconnect), `422` for an invalid body. + +--- + +### POST /clustersv2/{owner}/{cluster}/remove + +Remove a cluster and its components. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| response-id | string | No | Optional response identifier for progress notifications. | +| notify | boolean | No | Whether to send progress notifications (defaults to `true`). | + +**Request body:** a `RemovalOptions` object. + +```json +{ + "name": "my-cluster", + "components": { "fluxCD": true, "allFeatures": true } +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| name | string | No | Cluster name. | +| components | object (`ComponentOptions`) | No | Components to remove. | + +**Response:** `200` when the removal task is submitted. `422` for an invalid body. + +--- + +### POST /clustersv2/{owner}/{cluster}/reconfigure + +Reconfigure a cluster's components. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | + +**Request body:** a `ReconfigureOptions` object. + +```json +{ + "basicInfo": { "name": "my-cluster" }, + "components": { + "allFeatures": false, + "featureSets": [ { "name": "opscenter-core", "features": ["kube-ui-server"] } ] + } +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| basicInfo | object (`BasicInfo`) | No | Cluster basic info. | +| components | object (`ComponentOptions`) | No | Components to reconfigure. | + +**Response:** `200` — the internal cluster info record (modeled as a generic Kubernetes +object). `422` for an invalid body. + +--- + +### POST /clustersv2/{owner}/{cluster}/feature/{feature}/convert + +Convert a feature to be UI-managed. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | +| feature | string | Name of the feature to convert. | + +**Response:** `200` when the feature is converted. `400` if the feature is not enabled or +already UI-managed. + +--- + +## Kubernetes version upgrades + +### GET /clustersv2/{owner}/{cluster}/update-version/operations + +List cluster version update operations. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | + +**Response:** `200` — a `ConfigMapList` of upgrade operations (an arbitrary Kubernetes +list object). + +> **Verified:** `GET` returned `200` against `appscode/ace` on 2026-07-14. + +--- + +### GET /clustersv2/{owner}/{cluster}/update-version/list + +List upgradeable Kubernetes versions for a cluster. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | + +**Response:** `200` — an array of version strings. + +```json +["v1.37.0", "v1.38.0"] +``` + +> **Verified:** `GET` returned `500` against `appscode/ace` on 2026-07-14 — `ace` is a +> k3s hub cluster, not a CAPI-managed cluster, so upgradeable-version discovery does not +> apply. This endpoint targets CAPI clusters. + +--- + +### GET /clustersv2/{owner}/{cluster}/update-version/{version} + +Upgrade a CAPI cluster to a target Kubernetes version. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | +| version | string | Target Kubernetes version. | + +**Response:** `200` when the upgrade task is submitted. + +> **Note:** although this is an HTTP `GET`, it triggers a state change (a CAPI cluster +> upgrade). It was **not** exercised against the live platform. + +--- + +## Gateway configurations + +### GET /clustersv2/{owner}/{cluster}/gateway-configs + +List gateway configurations. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | + +**Response:** `200` — an array of `GatewayConfigInfo`: + +```json +[ + { + "presetName": "ace", + "presetNamespace": "ace", + "configName": "ace", + "configNamespace": "ace", + "version": "v2026.6.19", + "host": "", + "hostType": "ip", + "isDefault": true, + "updateAvailable": false + } +] +``` + +| Field | Type | Description | +|---|---|---| +| presetName / presetNamespace | string | Gateway preset name and namespace. | +| configName / configNamespace | string | GatewayConfig object name and namespace. | +| version | string | Chart version of the config. | +| host | string | Gateway host (IP or hostname). | +| hostType | string | Host type (e.g. `ip`, `domain`). | +| isDefault | boolean | Whether this is the default gateway. | +| updateAvailable | boolean | Whether an update to the ace chart version is available. | + +> **Verified:** `GET` returned `200` against `appscode/ace` on 2026-07-14. + +--- + +### PUT /clustersv2/{owner}/{cluster}/gateway-configs + +Update all non-`ace` gateway configurations to the ace chart version. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | + +**Request body:** none. + +**Response:** `200` when the gateway configurations are updated. + +--- + +### PUT /clustersv2/{owner}/{cluster}/gateway-configs/{namespace}/{name} + +Update a single gateway configuration to the ace chart version. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | +| namespace | string | Namespace of the GatewayConfig. | +| name | string | Name of the GatewayConfig. | + +**Request body:** none. + +**Response:** `200` when updated. `400` if the target is the `ace` gateway config (which +cannot be updated this way). + +--- + +## Virtual clusters (vcluster) + +### POST /clustersv2/{owner}/vcluster/create + +Create a virtual cluster on a host cluster. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | + +**Request body:** a `ClusterOptions` object. + +```json +{ + "clusterName": "my-vcluster", + "hostClusterName": "ace", + "hostClusterUID": "", + "hostClusterOwnerID": 3, + "hubClusterName": "ace", + "hubClusterUID": "", + "hubClusterOwnerID": 3 +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| clusterName | string | No | Name for the new virtual cluster. | +| hostClusterName | string | No | Host cluster name. | +| hostClusterUID | string | No | Host cluster UID. | +| hostClusterOwnerID | integer (int64) | No | Host cluster owner ID. | +| hubClusterName | string | No | Hub cluster name. | +| hubClusterUID | string | No | Hub cluster UID. | +| hubClusterOwnerID | integer (int64) | No | Hub cluster owner ID. | + +**Response:** `200` when the creation task is submitted. `422` for an invalid body. + +--- + +### POST /clustersv2/{owner}/vcluster/import + +Import a virtual cluster from a host cluster. + +**Auth:** token. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | + +**Request body:** a `ClusterOptions` object (same schema as +[`/vcluster/create`](#post-clustersv2ownervclustercreate)). + +**Response:** `200` when the import task is submitted. `422` for an invalid body. diff --git a/docs/platform/api/cluster-management-v2/subscriptions.md b/docs/platform/api/cluster-management-v2/subscriptions.md new file mode 100644 index 0000000..969c4bd --- /dev/null +++ b/docs/platform/api/cluster-management-v2/subscriptions.md @@ -0,0 +1,189 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-cluster-management-v2-subscriptions + name: Subscriptions & Inbox + parent: api-cluster-management-v2 + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Subscriptions & Inbox + +Inbox notification subscriptions let the current user opt in to receive notifications +about a cluster, a namespace, or a specific resource. A companion endpoint issues an +**inbox agent token** that a cluster's inbox agent uses to authenticate. + +All paths on this page are relative to `/api/v1` (the subscription routes live under +`/api/v1/clustersv2/...`; the agent-token route is `/api/v1/agent/...`). Every endpoint +requires a token (`Authorization: token `). + +Common conventions: + +- **owner** — the organization slug or username that owns the cluster (e.g. `appscode`). +- **cluster** — the cluster name within that owner's scope (e.g. `ace`, `arnob-dev`). +- Subscriptions are **per current user** — the authenticated caller is the subscriber. +- Each subscription resource supports three verbs on the same path: `POST` to subscribe, + `GET` to check the subscription, and `DELETE` to unsubscribe. All return `200` on + success (with no body). + +Example request: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clustersv2/appscode/ace/subscriptions/ +``` + +--- + +## Cluster-level subscription + +Subscribe to inbox notifications for the entire cluster. + +Path: `/clustersv2/{owner}/{cluster}/subscriptions/` + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | + +### POST /clustersv2/{owner}/{cluster}/subscriptions/ + +Subscribe the current user to cluster-level inbox notifications. + +**Auth:** token. **Response:** `200` — subscription created (no body). + +### GET /clustersv2/{owner}/{cluster}/subscriptions/ + +Check the current user's cluster-level inbox subscription. + +**Auth:** token. **Response:** `200` — subscription exists (no body). + +> **Verified:** `GET` returned `500` against `appscode/ace` on 2026-07-14 — checking a +> subscription requires the inbox/notification backend, which is not provisioned on this +> test instance. The route is reachable and authorized (no 401/403). + +### DELETE /clustersv2/{owner}/{cluster}/subscriptions/ + +Remove the cluster-level inbox subscription. + +**Auth:** token. **Response:** `200` — subscription removed (no body). + +--- + +## Namespace-level subscription + +Subscribe to inbox notifications for a single namespace in the cluster. + +Path: `/clustersv2/{owner}/{cluster}/subscriptions/namespaces/{namespace}/` + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | +| namespace | string | Namespace to subscribe to / check / unsubscribe from. | + +### POST /clustersv2/{owner}/{cluster}/subscriptions/namespaces/{namespace}/ + +Subscribe the current user to namespace-level inbox notifications. + +**Auth:** token. **Response:** `200` — subscription created (no body). + +### GET /clustersv2/{owner}/{cluster}/subscriptions/namespaces/{namespace}/ + +Check the current user's namespace-level inbox subscription. + +**Auth:** token. **Response:** `200` — subscription exists (no body). + +### DELETE /clustersv2/{owner}/{cluster}/subscriptions/namespaces/{namespace}/ + +Remove the namespace-level inbox subscription. + +**Auth:** token. **Response:** `200` — subscription removed (no body). + +--- + +## Resource-level subscription + +Subscribe to inbox notifications for one specific Kubernetes resource object, identified +by its group/version/resource and name within a namespace. + +Path: +`/clustersv2/{owner}/{cluster}/subscriptions/namespaces/{namespace}/{group}/{version}/{resource}/{resourceName}` + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| owner | string | Organization slug or username. | +| cluster | string | Cluster name. | +| namespace | string | Namespace of the resource. | +| group | string | API group of the resource (use `core` or an empty-equivalent for the core group, per the resource's GVR). | +| version | string | API version of the resource (e.g. `v1`, `v1alpha2`). | +| resource | string | Resource plural name (e.g. `mongodbs`, `deployments`). | +| resourceName | string | Name of the specific resource object. | + +Example path for a KubeDB MongoDB named `mg-shard` in namespace `demo`: + +``` +/clustersv2/appscode/arnob-dev/subscriptions/namespaces/demo/kubedb.com/v1/mongodbs/mg-shard +``` + +### POST .../{group}/{version}/{resource}/{resourceName} + +Subscribe the current user to resource-level inbox notifications. + +**Auth:** token. **Response:** `200` — subscription created (no body). + +### GET .../{group}/{version}/{resource}/{resourceName} + +Check the current user's resource-level inbox subscription. + +**Auth:** token. **Response:** `200` — subscription exists (no body). + +### DELETE .../{group}/{version}/{resource}/{resourceName} + +Remove the resource-level inbox subscription. + +**Auth:** token. **Response:** `200` — subscription removed (no body). + +--- + +## Inbox agent token + +### GET /agent/{clusterName}/{clusterID}/token + +Get an inbox agent JWT token for a cluster. The cluster's inbox agent uses this token +(and CA bundle) to authenticate when delivering notifications. + +**Auth:** token. + +> **Note:** this route lives under `/api/v1/agent/...`, not `/api/v1/clustersv2/...`, but +> it belongs to the Cluster Management v2 group. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| clusterName | string | Cluster name. | +| clusterID | string | Cluster UID. | + +**Response:** `200` — an `InboxTokenRequestResponse`: + +```json +{ + "agentJwtToken": "", + "caBundle": "" +} +``` + +| Field | Type | Description | +|---|---|---| +| agentJwtToken | string | JWT the inbox agent uses to authenticate. Treat as a secret. | +| caBundle | string | Base64-encoded CA bundle for verifying the endpoint. | diff --git a/docs/platform/api/licensing-contracts/_index.md b/docs/platform/api/licensing-contracts/_index.md new file mode 100644 index 0000000..13a3612 --- /dev/null +++ b/docs/platform/api/licensing-contracts/_index.md @@ -0,0 +1,50 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-licensing-contracts + name: Licensing & Contracts + parent: api + weight: 120 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Licensing & Contracts + +Contracts bind an organization (or user) to products, clusters, and usage quotas; +licenses are issued per contract-cluster. This group covers three related concerns: + +- **License registration** — the always-available endpoints that member clusters + (via `license-proxyserver`) use to validate a license and obtain a fresh one. +- **Contracts (admin)** — the AppsCode-hosted, site-admin console for managing every + contract across accounts. +- **Contracts (user)** — the AppsCode-hosted, token-scoped API an organization uses to + manage its own contracts, bind clusters, and issue offline licenses. + +All routes are served under the `/api/v1` prefix. + +> **Deployment note.** The `/contracts/*` and `/user/contracts/*` families — plus +> `POST /user/license-proxy` — are **AppsCode-hosted-only**. On a self-hosted platform +> these routes are not registered and return `404 Not Found`. They are documented here +> for completeness; the verification notes below record the observed behavior on the +> self-hosted test platform. + +## Pages + +- [License Registration](../registration.md) — `POST /register`, + `POST /license/issue`, `POST /user/license-proxy`. +- [Contracts — Admin](../contracts-admin.md) — `/contracts/*` + (AppsCode-hosted, site-admin). +- [Contracts — User](../contracts-user.md) — `/user/contracts/*` + (AppsCode-hosted, token). + +## Common concepts + +- **Owner scope.** Contract endpoints accept an owner (organization) context via the + optional `?org=` query parameter. When omitted, the caller's own account is used. +- **Contract IDs** (`id`) are numeric (`int64`). A **contract-cluster ID** (`ccID`) is + the numeric ID of a cluster's binding within a specific contract — distinct from the + cluster UUID. +- **Cluster UUID** (`clusterID` / `cluster`) is the cluster's UUID string. +- Timestamps on the `Contract` object (`start`, `end`) are Unix seconds. diff --git a/docs/platform/api/licensing-contracts/contracts-admin.md b/docs/platform/api/licensing-contracts/contracts-admin.md new file mode 100644 index 0000000..f640439 --- /dev/null +++ b/docs/platform/api/licensing-contracts/contracts-admin.md @@ -0,0 +1,322 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-licensing-contracts-contracts-admin + name: Contracts — Admin + parent: api-licensing-contracts + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Contracts — Admin + +The site-admin console for managing every contract across accounts. All routes on this +page are rooted at `/api/v1/contracts` (paths below are shown relative to that root, so +`GET /` is `GET /api/v1/contracts`). + +- **Auth:** token plus **site-admin** authorization (the specific permission is noted + per endpoint, e.g. `view_contracts:site_admin`). **AppsCode-hosted only.** +- **Owner scope:** every endpoint accepts the optional `?org=` query parameter to + scope the target account; when omitted the caller's account is used. + +> **Deployment note.** These routes are AppsCode-hosted-only and are **not registered on +> self-hosted platforms**. See the verification notes below. + +--- + +## Shared object: `Contract` + +Most read/write endpoints return a `Contract`. Its fields: + +| Field | Type | Description | +|---|---|---| +| `id` | int64 | Contract ID. | +| `uid` | int64 | Owner account ID. | +| `orgOrUser` | string | Owner org/user slug. | +| `name` | string | Contract name. | +| `product` | string | Product alias the contract covers. | +| `features` | array of string | Licensed features. | +| `clusters` | array of `ContractClusterStatus` | Clusters bound to the contract (see below). | +| `associatedCluster` | `ContractClusterStatus` | The cluster currently in context, when applicable. | +| `emails` | `ContractEmail` | Notification recipients (`contactPerson`, `signingAuthority`, `licenseUsers`, `financeTeam`, `usageAlertClient`, `usageAlertAdmin`; each a string array). | +| `quota` | `QuotaRule` | `enabled`, `metric` (e.g. `memory_gib_month`), `limit`, `alertThresholds` (int array), `disableLicenseOnLimitReached`. | +| `start` | int64 | Contract start time (Unix seconds). | +| `end` | int64 | Contract end time (Unix seconds). | +| `documentPath` | string | Stored contract-document path. | +| `allowOffline` | boolean | Whether offline (air-gapped) licenses are permitted. | +| `autoAssignCluster` | boolean | Auto-assign newly imported clusters. | +| `disableAnalytics` | boolean | Disable analytics reporting. | +| `enableClientBilling` | boolean | Enable client (managed-service) billing. | +| `revoked` | boolean | Whether the contract is revoked. | +| `restrictions` | string | JSON-encoded restrictions data. | + +`ContractClusterStatus`: `{ id (int64, the contract-cluster ID), contractId, cluster +(UUID), displayName, clusterStatus { isImported, name, tags[], associatedContractId }, +duplicateContractFeatures[] { contractId, product, features[] }, error }`. + +--- + +## `GET /` — list all contracts + +List all contracts across accounts (scoped by `org`). + +- **Auth:** site-admin (`view_contracts:site_admin`). +- **Query:** `org` (string, optional) — owner context. +- **Response:** `200 OK` — array of [`Contract`](#shared-object-contract). + +```json +[ + { + "id": 42, + "orgOrUser": "appscode", + "name": "Acme KubeDB 2026", + "product": "kubedb", + "features": ["kubedb", "kubedb-provisioner"], + "start": 1767225600, + "end": 1798761600, + "allowOffline": true, + "revoked": false + } +] +``` + +> **Verified:** `GET /contracts?org=appscode` returned `404` against the self-hosted platform on 2026-07-14 — contracts APIs are AppsCode-hosted-only and not registered here (token confirmed valid: `GET /user` returned `200`). + +Errors: `401` Unauthorized, `403` Forbidden (site-admin authorization required). + +```bash +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/contracts?org=appscode" +``` + +--- + +## `POST /` — create contract(s) + +Create one or more contracts (one per product listed in `products`). + +- **Auth:** site-admin (`create_contracts:site_admin`). +- **Request body:** `multipart/form-data` (so an optional contract `document` file may be + uploaded). Fields mirror [`Contract`](#shared-object-contract) except it takes a + `products` array (creating one contract per product) instead of a single `product`, + and an optional `document` file part. +- **Response:** `201 Created`. Errors: `400` (empty products, invalid emails, + unsupported product, or bad quota), `401`, `403`, `422`. + +--- + +## `GET /{id}` — get a contract + +- **Auth:** site-admin (`view_contracts:site_admin`). +- **Path:** `id` (int64, required) — contract ID. +- **Response:** `200 OK` — a [`Contract`](#shared-object-contract). Errors: `401`, `403`, `404` (not found). + +--- + +## `PUT /{id}` — update a contract + +- **Auth:** site-admin (`update_contracts:site_admin`). +- **Path:** `id` (int64, required). +- **Request body:** `multipart/form-data` (optional replacement `document` file); fields + mirror [`Contract`](#shared-object-contract). +- **Response:** `200 OK` — updated [`Contract`](#shared-object-contract). Errors: `400` + (invalid quota or emails), `401`, `403`, `404`, `422`. + +--- + +## `DELETE /{id}` — delete a contract + +- **Auth:** site-admin (`delete_contracts:site_admin`). +- **Path:** `id` (int64, required). +- **Response:** `200 OK`. Errors: `401`, `403`, `404`. + +--- + +## `POST /{id}/extend` — extend a contract + +Extend a contract's end time using the `end` field of the request body. + +- **Auth:** site-admin (`extend_contracts:site_admin`). +- **Path:** `id` (int64, required). +- **Request body** (`application/json`): a `Contract` object; only `end` (Unix seconds) + is used. + +```json +{ "end": 1830297600 } +``` + +- **Response:** `200 OK` — extended [`Contract`](#shared-object-contract). Errors: + `401`, `403`, `404`, `422`. + +--- + +## `POST /{id}/revoke` — revoke a contract + +- **Auth:** site-admin (`revoke_contracts:site_admin`). +- **Path:** `id` (int64, required). +- **Response:** `200 OK`. Errors: `401`, `403`, `404`. + +--- + +## `GET /{id}/document` — download contract document + +Return a time-limited signed URL (as a JSON string, valid 30 minutes) to download the +contract document. + +- **Auth:** site-admin (`view_contracts:site_admin`). +- **Path:** `id` (int64, required). +- **Response:** `200 OK` — a JSON string URL, e.g. `"https://storage.example.com/…?sig="`. + Errors: `401`, `403`, `404`. + +--- + +## `GET /{id}/audit` — contract audit history + +- **Auth:** contract-management (`view_contracts:contract_mgmt`). +- **Path:** `id` (int64, required). +- **Response:** `200 OK` — array of audit events: + +```json +[ + { "id": 1, "contractID": 42, "addedBy": "user@example.com", "event": "contract.created", "createdUnix": 1767225600 } +] +``` + +Errors: `401`, `403`, `404`. + +--- + +## `GET /{id}/clusters` — list bound clusters + +- **Auth:** site-admin (`add_cluster:site_admin`). +- **Path:** `id` (int64, required). +- **Response:** `200 OK` — array of `ContractClusterStatus` (see + [shared object](#shared-object-contract)). Errors: `401`, `403`. + +--- + +## `POST /{id}/clusters` — bind clusters + +Bind one or more clusters to the contract. + +- **Auth:** site-admin (`add_cluster:site_admin`). +- **Path:** `id` (int64, required). +- **Request body** (`application/json`): array of cluster references. + +```json +[ + { "displayName": "prod-east", "cluster": "c122d5e0-8d6b-4025-a2ff-63f5716053b1", "tags": ["prod"] } +] +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `cluster` | string | yes | Cluster UUID (validated as a UUID). | +| `displayName` | string | no | Display name for the binding. | +| `tags` | array of string | no | Tags for the cluster. | + +- **Response:** `201 Created` — updated `ContractClusterStatus` list. Errors: `400` + (empty list, invalid UUID, or already associated), `401`, `403`, `422`. + +--- + +## `GET /{id}/clusters/imported/non-associated` — importable clusters + +List the owner's imported clusters not yet bound to the contract. + +- **Auth:** site-admin (`add_cluster:site_admin`). +- **Path:** `id` (int64, required). +- **Response:** `200 OK` — array of cluster-info records (`id`, `displayName`, `name`, + `uid`, `provider`, `kubernetesVersion`, `nodeCount`, `status` (a Kubernetes-style + `rsapi.ClusterStatus` object), and related fields). Errors: `400` (contract not + found), `401`, `403`. + +--- + +## `DELETE /{id}/clusters/{ccID}` — remove a cluster + +- **Auth:** site-admin (`remove_cluster:site_admin`). +- **Path:** `id` (int64), `ccID` (int64, the contract-cluster ID). Both required. +- **Response:** `200 OK`. Errors: `401`, `403`. + +--- + +## `POST /{id}/clusters/{ccID}/issue-license` — issue full license + +Issue a full (offline-capable) license for the given contract cluster. + +- **Auth:** site-admin (`issue_license:site_admin`). +- **Path:** `id` (int64), `ccID` (int64). Both required. +- **Response:** `200 OK` — a license object (same shape as + [`POST /license/issue`](../registration.md)): `{ contract { id, + startTimestamp, expiryTimestamp }, license }`. Errors: `401`, `403` (quota exceeded or + authorization required), `404`, `405` (revoked contract or offline not allowed). + +--- + +## `PATCH /{id}/clusters/{ccID}/name` — rename a contract cluster + +- **Auth:** site-admin (`update_cluster_name:site_admin`). +- **Path:** `id` (int64), `ccID` (int64). Both required. +- **Request body** (`application/json`): `{ "clusterName": "prod-east" }`. +- **Response:** `200 OK`. Errors: `401`, `403`, `422`. + +--- + +## `PATCH /{id}/clusters/{ccID}/tags` — retag a contract cluster + +Replace the tag set for a cluster and sync it across contracts sharing the same cluster +UUID. + +- **Auth:** site-admin (`update_cluster_tags:site_admin`). +- **Path:** `id` (int64), `ccID` (int64). Both required. +- **Request body** (`application/json`): `{ "tags": ["prod", "east"] }`. +- **Response:** `200 OK`. Errors: `401`, `403`, `422`. + +--- + +## `GET /active/associated-clusters/{clusterID}/status` — single-cluster status + +Return the association/validity status of a single cluster for the target user. + +- **Auth:** site-admin (`view_contracts:site_admin`). +- **Path:** `clusterID` (string, required) — cluster UUID. +- **Query:** `orgOrUserId` (int64, optional — target account ID; defaults to the caller + when omitted or `0`), `contract` (int64, optional — contract ID to check against), + `org` (string, optional). +- **Response:** `200 OK` — a `ContractClusterStatus`. Errors: `401`, `403`, `500`. + +--- + +## `POST /active/associated-clusters/batch-status` — batch-cluster status + +Return association/validity status for a batch of clusters for the target user. + +- **Auth:** site-admin (`view_contracts:site_admin`). +- **Query:** `orgOrUserId` (int64, optional), `contract` (int64, optional), `org` (string, optional). +- **Request body** (`application/json`): `{ "clusters": ["", ""] }`. +- **Response:** `200 OK` — array of `ContractClusterStatus`. Errors: `401`, `403`, `422`, `500`. + +--- + +## `GET /available_products` — products available for contracts + +Return the map of non-community products supported for contracts, keyed by product alias. + +- **Auth:** site-admin (`create_contracts:site_admin`). +- **Query:** `org` (string, optional). +- **Response:** `200 OK` — a JSON object mapping product alias → plan info (free-form + object). + +```json +{ + "kubedb": { "name": "KubeDB", "plans": ["enterprise"] }, + "stash": { "name": "Stash", "plans": ["enterprise"] } +} +``` + +> **Verified:** `GET /contracts/available_products?org=appscode` returned `404` against the self-hosted platform on 2026-07-14 — AppsCode-hosted-only route, not registered here (token confirmed valid via `GET /user` → `200`). + +Errors: `401`, `403`. diff --git a/docs/platform/api/licensing-contracts/contracts-user.md b/docs/platform/api/licensing-contracts/contracts-user.md new file mode 100644 index 0000000..9742613 --- /dev/null +++ b/docs/platform/api/licensing-contracts/contracts-user.md @@ -0,0 +1,296 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-licensing-contracts-contracts-user + name: Contracts — User + parent: api-licensing-contracts + weight: 30 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Contracts — User + +The token-scoped API an organization uses to manage its own contracts, bind clusters, +and issue offline licenses. All routes on this page are rooted at +`/api/v1/user/contracts` (paths below are relative to that root, so `GET /` is +`GET /api/v1/user/contracts`). + +- **Auth:** token (`Authorization: token `). Some write endpoints require an + extra authorization check, noted per endpoint. **AppsCode-hosted only.** +- **Owner scope:** every endpoint accepts the optional `?org=` query parameter to + scope the target account; when omitted the caller's account is used. + +The `Contract` and `ContractClusterStatus` object shapes are the same as documented on +the [Contracts — Admin](../contracts-admin.md) page (user responses +sanitize admin-only email fields). + +> **Deployment note.** These routes are AppsCode-hosted-only and are **not registered on +> self-hosted platforms**. See the verification notes below. + +--- + +## `GET /` — list my contracts + +List the contracts owned by the resolved owner. + +- **Auth:** token. +- **Query:** `org` (string, optional). +- **Response:** `200 OK` — array of `Contract`. + +```json +[ + { + "id": 42, + "orgOrUser": "appscode", + "name": "Acme KubeDB 2026", + "product": "kubedb", + "features": ["kubedb"], + "start": 1767225600, + "end": 1798761600, + "allowOffline": true, + "autoAssignCluster": false, + "revoked": false + } +] +``` + +> **Verified:** `GET /user/contracts?org=appscode` returned `404` against the self-hosted platform on 2026-07-14 — contracts APIs are AppsCode-hosted-only and not registered here (token confirmed valid: `GET /user` returned `200`). + +Errors: `401`, `403`. + +```bash +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/user/contracts?org=appscode" +``` + +--- + +## `GET /active-offline-contracts` — list active offline contracts + +List the owner's active offline (air-gapped) contracts. + +- **Auth:** token. **Query:** `org` (optional). +- **Response:** `200 OK` — array of `Contract`. + +> **Verified:** `GET /user/contracts/active-offline-contracts?org=appscode` returned `404` on 2026-07-14 — AppsCode-hosted-only route, not registered on the self-hosted platform. + +Errors: `401`, `403`. + +--- + +## `POST /assign-cluster` — assign a cluster to multiple contracts + +Assign a single cluster to multiple contracts owned by the caller. + +- **Auth:** token plus contract-management authorization (`add_cluster:contract_mgmt`). +- **Query:** `org` (optional). +- **Request body** (`application/json`): + +```json +{ + "clusterId": "c122d5e0-8d6b-4025-a2ff-63f5716053b1", + "displayName": "prod-east", + "contractIds": [42, 43] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `clusterId` | string | yes | Cluster UUID. | +| `displayName` | string | no | Display name for the cluster. | +| `contractIds` | array of int64 | yes | Contracts to assign the cluster to. | + +- **Response:** `200 OK`. Errors: `400` (empty contract list or invalid cluster UUID), + `401`, `403`, `422`. + +--- + +## `GET /active/associated-with/clusters/{clusterID}` — contracts on a cluster + +List the owner's active contracts associated with the given cluster. + +- **Auth:** token. +- **Path:** `clusterID` (string, required) — cluster UUID. +- **Query:** `onlyOffline` (boolean, optional — restrict to offline contracts), `org` (optional). +- **Response:** `200 OK` — array of `Contract`. Errors: `401`, `403`. + +--- + +## `GET /active/not-associated-with/clusters/{clusterID}` — contracts not on a cluster + +List the owner's active contracts that are **not** associated with the given cluster. + +- **Auth:** token. **Path:** `clusterID` (string, required). **Query:** `org` (optional). +- **Response:** `200 OK` — array of `Contract`. Errors: `401`, `403`. + +--- + +## `GET /active/associated-clusters` — clusters of my active offline contracts + +List the unique clusters associated with the owner's offline active contracts. + +- **Auth:** token. **Query:** `org` (optional). +- **Response:** `200 OK` — array of cluster records: + +```json +[ + { + "associatedContractIDs": [42, 43], + "cluster": "c122d5e0-8d6b-4025-a2ff-63f5716053b1", + "displayName": "prod-east", + "tags": ["prod"] + } +] +``` + +> **Verified:** `GET /user/contracts/active/associated-clusters?org=appscode` returned `404` on 2026-07-14 — AppsCode-hosted-only route, not registered on the self-hosted platform (token confirmed valid via `GET /user` → `200`). + +Errors: `401`, `403`. + +--- + +## `GET /active/associated-clusters/{clusterID}/status` — single-cluster status + +Return the association/validity status of a single cluster for the caller. + +- **Auth:** token. +- **Path:** `clusterID` (string, required) — cluster UUID. +- **Query:** `contract` (int64, optional — contract ID to check against), `org` (optional). +- **Response:** `200 OK` — a `ContractClusterStatus`. Errors: `401`, `403`, `500`. + +--- + +## `POST /active/associated-clusters/batch-status` — batch-cluster status + +Return association/validity status for a batch of clusters for the caller. + +- **Auth:** token. +- **Query:** `contract` (int64, optional), `org` (optional). +- **Request body** (`application/json`): `{ "clusters": ["", ""] }`. +- **Response:** `200 OK` — array of `ContractClusterStatus`. Errors: `401`, `403`, `422`, `500`. + +--- + +## `GET /{id}` — get one of my contracts + +Return a single contract owned by the caller (admin-only email fields sanitized). + +- **Auth:** token. **Path:** `id` (int64, required). **Query:** `org` (optional). +- **Response:** `200 OK` — a `Contract`. Errors: `401`, `403`, `404`. + +--- + +## `PUT /{id}/preferences` — update contract preferences + +Update the caller-editable preferences (auto-assign clusters, usage-alert client +recipients) for one of the caller's contracts. + +- **Auth:** token plus authorization (`updated_preferences:contracts`). +- **Path:** `id` (int64, required). **Query:** `org` (optional). +- **Request body** (`application/json`): + +```json +{ + "autoAssignCluster": true, + "usageAlertClient": ["ops@example.com"] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `autoAssignCluster` | boolean | no | Auto-assign newly imported clusters to this contract. | +| `usageAlertClient` | array of string | no | Usage-alert recipient emails (a single string is normalized to a one-element array). | + +- **Response:** `200 OK` — updated `Contract`. Errors: `400` (invalid recipients), + `401`, `403`, `422`. + +--- + +## `GET /{id}/audit` — contract audit history + +- **Auth:** token. **Path:** `id` (int64, required). **Query:** `org` (optional). +- **Response:** `200 OK` — array of audit events (`id`, `contractID`, `addedBy`, + `event`, `createdUnix`). Errors: `401`, `403` (not found or authorization denied). + +--- + +## `GET /{id}/document` — download contract document + +Return a time-limited signed URL (as a JSON string, valid 30 minutes) to download the +contract document. + +- **Auth:** token. **Path:** `id` (int64, required). **Query:** `org` (optional). +- **Response:** `200 OK` — a JSON string URL. Errors: `401`, `403`, `404`. + +--- + +## `GET /{id}/clusters` — list bound clusters + +- **Auth:** token. **Path:** `id` (int64, required). **Query:** `org` (optional). +- **Response:** `200 OK` — array of `ContractClusterStatus`. Errors: `401`, `403`. + +--- + +## `POST /{id}/clusters` — bind clusters + +Bind one or more clusters to one of the caller's contracts. + +- **Auth:** token plus authorization. +- **Path:** `id` (int64, required). **Query:** `org` (optional). +- **Request body** (`application/json`): array of `{ cluster (UUID, required), + displayName, tags[] }` — same shape as the admin bind endpoint. +- **Response:** `201 Created` — updated `ContractClusterStatus` list. Errors: `400` + (empty list, invalid UUID, invalid contract, or already associated), `401`, `403`, `422`. + +--- + +## `GET /{id}/clusters/imported/non-associated` — importable clusters + +List the owner's imported clusters not yet bound to the contract. + +- **Auth:** token. **Path:** `id` (int64, required). **Query:** `org` (optional). +- **Response:** `200 OK` — array of cluster-info records (same shape as the admin + equivalent). Errors: `400` (contract not found), `401`, `403`. + +--- + +## `DELETE /{id}/clusters/{ccID}` — remove a cluster + +- **Auth:** token. **Path:** `id` (int64), `ccID` (int64, contract-cluster ID). Both + required. **Query:** `org` (optional). +- **Response:** `200 OK`. Errors: `401`, `403`. + +--- + +## `POST /{id}/clusters/{ccID}/issue-license` — issue full license + +Issue a full (offline-capable) license for one of the caller's contract clusters. + +- **Auth:** token plus authorization (`issue-license:cluster`). +- **Path:** `id` (int64), `ccID` (int64). Both required. **Query:** `org` (optional). +- **Response:** `200 OK` — a license object (`{ contract { id, startTimestamp, + expiryTimestamp }, license }`, same shape as + [`POST /license/issue`](../registration.md)). Errors: `401`, `403` + (quota exceeded or authorization denied), `404`, `405` (revoked contract or offline + not allowed). + +--- + +## `PATCH /{id}/clusters/{ccID}/name` — rename a contract cluster + +- **Auth:** token. **Path:** `id` (int64), `ccID` (int64). Both required. **Query:** `org` (optional). +- **Request body** (`application/json`): `{ "clusterName": "prod-east" }`. +- **Response:** `200 OK`. Errors: `401`, `403`, `422`. + +--- + +## `PATCH /{id}/clusters/{ccID}/tags` — retag a contract cluster + +Replace the tag set for a cluster and sync it across the owner's contracts sharing the +same cluster UUID. + +- **Auth:** token. **Path:** `id` (int64), `ccID` (int64). Both required. **Query:** `org` (optional). +- **Request body** (`application/json`): `{ "tags": ["prod", "east"] }`. +- **Response:** `200 OK`. Errors: `401`, `403`, `422`. diff --git a/docs/platform/api/licensing-contracts/registration.md b/docs/platform/api/licensing-contracts/registration.md new file mode 100644 index 0000000..be635bb --- /dev/null +++ b/docs/platform/api/licensing-contracts/registration.md @@ -0,0 +1,153 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-licensing-contracts-registration + name: License Registration + parent: api-licensing-contracts + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# License Registration + +Endpoints that member clusters (via `license-proxyserver`) and the console use to +validate a license, obtain a fresh license, and generate a proxy-server installer. + +All paths on this page are relative to `/api/v1` (for example, `POST /register` is +`POST /api/v1/register`). + +--- + +## `POST /register` + +Register / validate a licensed user against a previously issued license. Used by +on-prem / air-gapped deployments; only available when self-registration is permitted +for the deployment type. + +- **Auth:** public — no token required. The request must carry a valid `license` + payload, which is cryptographically verified; a license-validation middleware also + gates the request. + +**Request body** (`application/json`): + +```json +{ + "clusterUID": "c122d5e0-8d6b-4025-a2ff-63f5716053b1", + "features": "kubedb", + "caCert": "", + "license": "" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `clusterUID` | string | yes | UUID of the cluster being registered. | +| `features` | string | yes | Feature/product the license covers (empty value is rejected). | +| `caCert` | string (base64 bytes) | no | CA certificate used to verify the license chain. | +| `license` | string (base64 bytes) | yes | The license payload to validate. | + +**Response:** `200 OK` — user registered (no body). Error responses: + +| Status | Meaning | +|---|---| +| `400` | Bad request (empty `features` or unregistered `clusterUID`). | +| `403` | Registration not supported for this deployment type. | +| `422` | Unprocessable entity (invalid request body or license). | +| `500` | License verification or user creation failed. | + +```bash +curl -X POST https:///api/v1/register \ + -H "Content-Type: application/json" \ + -d '{"clusterUID":"","features":"kubedb","license":""}' +``` + +--- + +## `POST /license/issue` + +Issue a license for the caller's cluster/product based on the caller's active contract. + +- **Auth:** token (`Authorization: token `, or `token`/`access_token` query + parameter). + +**Request body** (`application/json`): + +```json +{ + "cluster": "c122d5e0-8d6b-4025-a2ff-63f5716053b1", + "features": ["kubedb", "kubedb-provisioner"] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `cluster` | string | no | Cluster UUID the license is issued for. | +| `features` | array of string | no | Features to include on the license. | + +**Response:** `200 OK` — the issued license. + +```json +{ + "contract": { + "id": "42", + "startTimestamp": "2026-01-01T00:00:00Z", + "expiryTimestamp": "2027-01-01T00:00:00Z" + }, + "license": "" +} +``` + +`contract` echoes the contract the license was issued under; `license` is the license +certificate bytes (base64-encoded in JSON). Error responses: + +| Status | Meaning | +|---|---| +| `401` | Unauthorized. | +| `403` | Forbidden (contract quota exceeded). | +| `405` | Contract invalid (revoked or expired). | +| `422` | Unprocessable entity (invalid request body). | +| `500` | Internal server error. | + +```bash +curl -X POST -H "Authorization: token $ACE_TOKEN" \ + -H "Content-Type: application/json" \ + https:///api/v1/license/issue \ + -d '{"cluster":"","features":["kubedb"]}' +``` + +--- + +## `POST /user/license-proxy` + +Generate a `license-proxyserver` installer script for the resolved organization. When +`clusterID` / `contractIDs` are supplied an **offline** installer is generated; +otherwise an **online** installer. + +- **Auth:** token plus dynamic authorization on the organization. **AppsCode-hosted only.** + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `org` | string | no | Owner (organization) context. Defaults to the caller. | + +**Request body** (`application/json`): + +```json +{ + "clusterID": "c122d5e0-8d6b-4025-a2ff-63f5716053b1", + "contractIDs": [42, 43] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `clusterID` | string | no | Cluster UUID; presence selects the offline installer. | +| `contractIDs` | array of int64 | no | Contract IDs to bake into the offline installer. | + +**Response:** `200 OK` — a dynamic JSON object (`map[string]any`) containing the +generated YAML / Helm 3 installer scripts (free-form object; keys depend on the +installer flavor). Error responses: `401` Unauthorized, `403` Forbidden, `422` +Unprocessable entity, `500` Internal server error. diff --git a/docs/platform/api/marketplace/_index.md b/docs/platform/api/marketplace/_index.md new file mode 100644 index 0000000..7f4f818 --- /dev/null +++ b/docs/platform/api/marketplace/_index.md @@ -0,0 +1,42 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-marketplace + name: Marketplace + parent: api + weight: 140 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Marketplace + +The Marketplace APIs integrate ACE with the public cloud marketplaces (AWS, Azure, +GCP). They cover two distinct surfaces served by two different processes: + +- **Marketplace webhook service** — a **separate listener** rooted at + `/marketplace/api/v1` (not `/api/v1`). It receives subscription lifecycle + notifications from the cloud marketplaces, answers the standalone-organization + claimable check, and serves a version endpoint. These routes only exist when the + b3 binary runs its `marketplace` subcommand as part of a marketplace deployment. +- **Metered-billing proxy** (`/api/v1/proxy/metered-billing/marketplaces/*`) — a + site-admin proxy on the **main** API server that forwards metered-usage reports + and readiness probes to the AWS Marketplace Metering / GCP Service Control APIs. + Each provider's routes are registered **only** for the matching deployment type + (`AWSMarketplaceDeployment` / `GCPMarketplaceDeployment`); on any other deployment + they do not exist and return `404`. + +Because these endpoints are gated by marketplace deployment types, most of them are +**unavailable on a standard ACE installation**. Each page notes the gating and, for +GET endpoints, the observed behaviour on a non-marketplace deployment. + +> **Note on the two listeners:** the webhook service listens on its own root +> `/marketplace/api/v1`, which is **different** from the main server's `/api/v1` +> prefix used everywhere else in this reference. It shares the `GET /version` +> response shape with the main server but runs as a separate process. + +## Pages + +- [Webhook Service](../webhook-service.md) — `/marketplace/api/v1/*`: claimable check, AWS/Azure/GCP subscription notifications, and version (separate listener). +- [Metered Billing](../metered-billing.md) — `/api/v1/proxy/metered-billing/marketplaces/*`: AWS/GCP usage reporting and readiness probes (site-admin, deployment-gated). diff --git a/docs/platform/api/marketplace/metered-billing.md b/docs/platform/api/marketplace/metered-billing.md new file mode 100644 index 0000000..7ee2e98 --- /dev/null +++ b/docs/platform/api/marketplace/metered-billing.md @@ -0,0 +1,183 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-marketplace-metered-billing + name: Metered Billing + parent: api-marketplace + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Metered Billing Proxy + +These endpoints live on the **main** API server under +`/api/v1/proxy/metered-billing/marketplaces/*`. Paths on this page are shown +relative to the `/api/v1` prefix. They proxy metered-usage reports and readiness +probes to the underlying cloud metering APIs — **AWS Marketplace Metering** and +**GCP Service Control**. + +**Authentication & authorization.** All four endpoints require a **site-admin** +token. Send it as `Authorization: token ` (or as a `token` / +`access_token` query parameter). Non-site-admin callers receive `403`; +unauthenticated callers receive `401`. + +> **Deployment gating.** Each provider's routes are registered **only** for the +> matching b3 deployment type: +> - `aws/*` → `AWSMarketplaceDeployment` +> - `gcp/*` → `GCPMarketplaceDeployment` +> +> On any other deployment the routes **do not exist** and requests return `404`. +> Azure has no metering proxy wired up (Azure metering is handled via the webhook's +> `billingDetails.resourceUsageId` on the subscription side instead). + +> **Availability on this platform.** The reference deployment (`appscode`) is a +> standard, non-marketplace install, so none of these routes are registered — the +> GET readiness probes below both returned `404`. The endpoints are documented from +> the OpenAPI schema. + +--- + +## AWS metering + +### POST /proxy/metered-billing/marketplaces/aws/report-usage + +Forward a usage report to the AWS Marketplace Metering `MeterUsage` API. + +- **Auth:** token, **site-admin** required. +- **Gated by:** `AWSMarketplaceDeployment`. + +**Request body** (`MeterUsageInput`): + +```json +{ + "DryRun": false, + "ProductCode": "", + "Timestamp": "2026-07-14T10:00:00Z", + "UsageDimension": "nodes", + "UsageQuantity": 3, + "UsageAllocations": [ + { + "AllocatedUsageQuantity": 3, + "Tags": [ + { "Key": "cluster", "Value": "ace" } + ] + } + ] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `ProductCode` | string | yes | AWS Marketplace product code. | +| `Timestamp` | string (date-time) | yes | Timestamp of the metering record. | +| `UsageDimension` | string | yes | The metered dimension being reported. | +| `DryRun` | boolean | no | If true, validate without recording usage. | +| `UsageQuantity` | integer (int64) | no | Quantity of the dimension consumed. | +| `UsageAllocations` | array (`UsageAllocation`) | no | Per-bucket allocation of the usage. | + +**`UsageAllocation` fields:** `AllocatedUsageQuantity` (integer, required) and an +optional `Tags` array of `{ "Key", "Value" }` pairs. + +**Response — `200`** (`MeterUsageOutput`): + +```json +{ "MeteringRecordId": "" } +``` + +**Other statuses:** `400` AWS rejected the request — e.g. customer not entitled, +duplicate request, invalid product code, or throttling (`AwsMeteringProxyErr` +body); `401` auth required; `403` site-admin required; `422` unprocessable body; +`500` failed to report / unmapped AWS error code (`AwsMeteringProxyErr`). + +`AwsMeteringProxyErr` shape: + +```json +{ + "code": "CustomerNotEntitledException", + "message": "the customer is not entitled to the product", + "origErr": {} +} +``` + +### GET /proxy/metered-billing/marketplaces/aws/check/readiness + +Readiness probe for the AWS metering proxy. + +- **Auth:** token, **site-admin** required. +- **Gated by:** `AWSMarketplaceDeployment`. + +**Response:** `200` proxy ready (empty body). `401` auth required; `403` site-admin +required. + +**Example** + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/proxy/metered-billing/marketplaces/aws/check/readiness?org=appscode" +``` + +> **Verified:** returned `404` against `appscode` on 2026-07-14 — the AWS metering +> proxy route is not registered (this is not an `AWSMarketplaceDeployment`). + +--- + +## GCP metering + +### POST /proxy/metered-billing/marketplaces/gcp/report-usage + +Forward a usage report to the GCP Service Control reporting API. + +- **Auth:** token, **site-admin** required. +- **Gated by:** `GCPMarketplaceDeployment`. + +**Request body** (`GcpUsageReport`): + +```json +{ + "name": "services/ace.endpoints..cloud.goog", + "startTime": "2026-07-14T09:00:00Z", + "endTime": "2026-07-14T10:00:00Z", + "labels": { "cluster": "ace" }, + "value": { "int64Value": 3 }, + "dimension": "nodes", + "serviceName": "ace.endpoints..cloud.goog" +} +``` + +| Field | Type | Description | +|---|---|---| +| `name` | string | Operation / consumer resource name. | +| `startTime` | string (date-time) | Start of the usage window. | +| `endTime` | string (date-time) | End of the usage window. | +| `labels` | object (string→string) | Metric labels. | +| `value` | object (`GcpUsageValue`) | Usage value: `int64Value` and/or `doubleValue`. | +| `dimension` | string | The metered dimension. | +| `serviceName` | string | GCP managed service name. | + +**Response — `200`:** the GCP Service Control report response (an arbitrary +Kubernetes-style / free-form object — passed through as-is). + +**Other statuses:** `401` auth required; `403` site-admin required; `422` +unprocessable body; `500` failed to report to GCP Service Control. + +### GET /proxy/metered-billing/marketplaces/gcp/check/readiness + +Readiness probe for the GCP metering proxy. + +- **Auth:** token, **site-admin** required. +- **Gated by:** `GCPMarketplaceDeployment`. + +**Response:** `200` proxy ready (empty body). `401` auth required; `403` site-admin +required. + +**Example** + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/proxy/metered-billing/marketplaces/gcp/check/readiness?org=appscode" +``` + +> **Verified:** returned `404` against `appscode` on 2026-07-14 — the GCP metering +> proxy route is not registered (this is not a `GCPMarketplaceDeployment`). diff --git a/docs/platform/api/marketplace/webhook-service.md b/docs/platform/api/marketplace/webhook-service.md new file mode 100644 index 0000000..a91b30a --- /dev/null +++ b/docs/platform/api/marketplace/webhook-service.md @@ -0,0 +1,292 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-marketplace-webhook-service + name: Webhook Service + parent: api-marketplace + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Marketplace Webhook Service + +> **Separate listener.** Unlike every other page in this reference, these routes are +> **not** served under `/api/v1`. They live on a dedicated marketplace webhook +> listener rooted at **`/marketplace/api/v1`**, run by the b3 `marketplace` +> subcommand. Paths below are relative to that root +> (`/marketplace/api/v1/...`). This listener exists only on marketplace +> deployments (AWS / Azure / GCP marketplace modes). + +The webhook service handles inbound subscription lifecycle events pushed by the cloud +marketplaces, answers the public "is this standalone org claimable?" check used by +the claim flow, and exposes a version endpoint identical in shape to the main +server's `/api/v1/version`. + +**Authentication model.** None of these endpoints use a platform bearer token. The +claimable check and version endpoint are **public**. The three notification +endpoints are authenticated by the **webhook itself** — by verifying the payload and +either the source IP range (AWS) or a per-installer `secret` query parameter +(Azure / GCP) — not by ACE token/session security. + +> **Availability on this platform.** The `/marketplace/api/v1/*` root is **not +> served** on the reference deployment (`appscode`, a standard non-marketplace +> install). Requests to it fall through to the web frontend and return HTTP `200` +> with `Content-Type: text/html` (the SPA), rather than the JSON documented here. +> The endpoints below are therefore documented from the OpenAPI schema and marked +> as not deployed; treat the JSON examples as the shapes returned by an actual +> marketplace deployment. + +--- + +## Claimable check + +### GET /marketplaces/standalone-organizations/{claimID}/claimable + +Evaluate the claim-rules flags of a standalone (marketplace-created) organization, +identified by its claim ID, and report whether it can currently be claimed. The +check is proxied to the central marketplace server. + +- **Auth:** public (`security: []`). No token required. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `claimID` | string | The claim ID of the standalone organization. | + +**Response — `200`** (`OrgClaimableCheckResp`). Returned both when the org is +claimable and when the retry backoff has not yet expired but the org is already +flagged claimable. + +```json +{ + "isClaimable": true, + "claimID": "01HZK9" +} +``` + +| Field | Type | Description | +|---|---|---| +| `isClaimable` | boolean | Whether the standalone organization can currently be claimed. | +| `claimID` | string | Echo of the claim ID that was checked. | + +**Other statuses:** `404` standalone org not found; `409` already claimed; `429` +retry backoff not yet expired — try again later; `500` error while evaluating claim +rules. Error bodies use the marketplace `ApiError` shape: + +```json +{ "message": "standalone organization already claimed" } +``` + +**Example** + +``` +curl https:///marketplace/api/v1/marketplaces/standalone-organizations//claimable +``` + +> **Verified:** returned `200` with `Content-Type: text/html` against the reference +> host on 2026-07-14 — i.e. the marketplace webhook listener is **not deployed** +> here and the request was served by the web frontend SPA (catch-all), not the +> webhook service. Documented from schema. + +--- + +## Subscription notifications (webhook callbacks) + +These three endpoints are the callback targets registered with each cloud +marketplace. They are **POST** only and are called by the marketplace, not by +platform clients — they are documented here for completeness. On a successful bind +they return the generated installer archive **download link**. + +### POST /marketplaces/aws/notification/resource + +Handle an AWS Marketplace bind-event notification. + +- **Auth:** enforced by the webhook. The payload is verified (`marketplace` must be + `Aws`; cluster ID and options validated) and, outside dev run mode, the source IP + must fall within the allowed AWS EC2 IP ranges. No platform bearer-token security. + +**Request body** (`AwsWebhookNotification`): + +```json +{ + "eventType": "subscribe-success", + "eventTime": "2026-07-14T10:00:00Z", + "bindingInfo": { + "marketplace": "Aws", + "installerId": "inst-abc123", + "clusterId": "cls-abc123", + "AWSAccountID": "111122223333", + "adminUsername": "admin", + "adminPassword": "", + "domainWhiteList": ["example.com"], + "options": {} + } +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `eventType` | string | no | Marketplace event type. | +| `eventTime` | string (date-time) | no | Time the event was emitted. | +| `bindingInfo` | object (`BindingInfo`) | yes | Subscription binding details (see below). | + +**`BindingInfo` fields** (shared by AWS/Azure/GCP; embeds `InitialInput`): + +| Field | Type | Description | +|---|---|---| +| `marketplace` | string (`Aws`/`Azure`/`Gcp`) | Marketplace identifier. | +| `installerId` | string | Installer this subscription binds to. | +| `clusterId` | string | Target cluster ID. | +| `AWSAccountID` | string | AWS account ID (AWS only). | +| `adminUsername` | string | Initial admin username for the deployment. | +| `adminPassword` | string | Initial admin password (sensitive). | +| `domainWhiteList` | string[] | Allowed email/login domains. | +| `options` | object | Free-form installer options. | + +**Response — `200`:** subscription bound; returns the installer archive link. + +```json +{ "link": "https:///.../installer-archive.tgz" } +``` + +**Other statuses:** `400` payload / binding-info / option processing failed; `403` +request from an unauthorized IP; `500` provisioning error (`ApiError` body). + +### POST /marketplaces/azure/notification/resource + +Handle an Azure Marketplace lifecycle notification (`PUT`, `DELETE`, `BIND`). + +- **Auth:** enforced by the webhook via a per-installer `secret` query parameter + that must match the configured marketplace API secret. No platform bearer-token + security. + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `secret` | string | no | Marketplace API secret used to authenticate the Azure webhook call. | + +**Request body** (`AzureWebhookNotification`). Note: `managedResourceGroupId` and +`resourceIdParts` are populated server-side and are **not** part of the incoming +JSON payload. + +```json +{ + "eventType": "BIND", + "applicationId": "/subscriptions//resourceGroups//providers/...", + "eventTime": "2026-07-14T10:00:00Z", + "provisioningState": "Succeeded", + "billingDetails": { "resourceUsageId": "" }, + "plan": { + "publisher": "appscode", + "product": "ace", + "name": "standard", + "version": "v2026.6.19" + }, + "bindingInfo": { + "marketplace": "Azure", + "installerId": "inst-abc123", + "clusterId": "cls-abc123" + } +} +``` + +| Field | Type | Description | +|---|---|---| +| `eventType` | string | Lifecycle event (`PUT`, `DELETE`, `BIND`). | +| `applicationId` | string | Azure application resource ID. | +| `managedResourceGroupId` | string | Managed resource group (server-populated). | +| `resourceIdParts` | object | Parsed resource-ID parts (server-populated). | +| `eventTime` | string (date-time) | Event time. | +| `provisioningState` | string | Azure provisioning state. | +| `billingDetails.resourceUsageId` | string | Azure metered-billing resource usage ID. | +| `plan` | object | Publisher / product / name / version of the plan. | +| `error` | object | Error code/message/details, when the event reports a failure. | +| `bindingInfo` | object (`BindingInfo`) | Subscription binding details. | + +**Response — `200`:** notification processed. For `PUT`/`DELETE` an empty body with +status `200`; for `BIND` the installer archive `link` is returned. + +**Other statuses:** `400` invalid subscription ID / unknown event type / invalid +binding info; `403` secret mismatch (or subscription not found while revoking +contracts on delete); `500` processing error. + +### POST /marketplaces/gcp/notification/resource + +Handle a GCP Marketplace bind-event notification. + +- **Auth:** enforced by the webhook via a per-installer `secret` query parameter + that must match the configured marketplace API secret (bypassed only for the + designated GCP Marketplace test installer). No platform bearer-token security. + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `secret` | string | no | Marketplace API secret used to authenticate the GCP webhook call. | + +**Request body** (`GcpWebhookNotification`): + +```json +{ + "eventType": "subscribe-success", + "eventTime": "2026-07-14T10:00:00Z", + "bindingInfo": { + "marketplace": "Gcp", + "installerId": "inst-abc123", + "clusterId": "cls-abc123" + } +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `eventType` | string | no | Marketplace event type. | +| `eventTime` | string (date-time) | no | Event time. | +| `bindingInfo` | object (`BindingInfo`) | yes | Subscription binding details. | + +**Response — `200`:** subscription bound; returns the installer archive link. + +```json +{ "link": "https:///.../installer-archive.tgz" } +``` + +**Other statuses:** `400` invalid binding info / installer lookup failure; `403` +secret mismatch or installer already bound; `500` provisioning error. + +--- + +## Version + +### GET /version + +Return the version of the marketplace webhook service. Identical in shape to the +main server's `GET /api/v1/version`. + +- **Auth:** public (`security: []`). + +**Response — `200`** (`ServerVersion`): + +```json +{ "version": "v2026.6.19" } +``` + +| Field | Type | Description | +|---|---|---| +| `version` | string | Server application version. | + +**Example** + +``` +curl https:///marketplace/api/v1/version +``` + +> **Verified:** returned `200` with `Content-Type: text/html` against the reference +> host on 2026-07-14 — the `/marketplace/api/v1` listener is **not deployed** here, +> so the request was served by the web frontend SPA, not the webhook service. For +> comparison, the main server's `GET /api/v1/version` returned `200` with +> `{"version":"v2026.6.19"}` (`application/json`) — that is the shape this endpoint +> returns on an actual marketplace deployment. diff --git a/docs/platform/api/miscellaneous/_index.md b/docs/platform/api/miscellaneous/_index.md new file mode 100644 index 0000000..fdfd299 --- /dev/null +++ b/docs/platform/api/miscellaneous/_index.md @@ -0,0 +1,29 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-miscellaneous + name: Miscellaneous + parent: api + weight: 180 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Miscellaneous + +Small utility and infrastructure endpoints exposed by the `b3` backend: the server +version, a markdown-to-HTML renderer, the Swagger UI page, a health check, and the +OpenID Connect discovery document. These are all public (no authentication) and back +various parts of the ACE web console and its OIDC provider. + +Most of these routes live under the `/api/v1` prefix like the rest of the API. Two of +them — the health check and the OIDC discovery document — are served at the **host +root**, not under `/api/v1`; their full paths are documented as-is. + +## Pages + +- [Miscellaneous Endpoints](../miscellaneous.md) — server version + (`/api/v1/version`), markdown rendering (`/api/v1/markdown`, `/api/v1/markdown/raw`), + the Swagger UI (`/api/v1/swagger`), the health check (`/healthz`), and OIDC discovery + (`/.well-known/openid-configuration`). diff --git a/docs/platform/api/miscellaneous/miscellaneous.md b/docs/platform/api/miscellaneous/miscellaneous.md new file mode 100644 index 0000000..7b0538b --- /dev/null +++ b/docs/platform/api/miscellaneous/miscellaneous.md @@ -0,0 +1,184 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-miscellaneous-miscellaneous + name: Miscellaneous Endpoints + parent: api-miscellaneous + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Miscellaneous Endpoints + +Utility endpoints of the `b3` backend. Unless noted otherwise, paths on this page are +relative to `/api/v1` — the full base path is `https:///api/v1`. Two +endpoints (`/healthz` and `/.well-known/openid-configuration`) are served at the +**host root** and are shown with their full path. + +All endpoints on this page are **public** — no authentication is required. + +## Server version + +### GET /version + +Returns the version of the server application. + +- **Auth:** Public (no authentication). + +**Response:** `200 OK` with a JSON object. + +```json +{ + "version": "v2026.6.19" +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `version` | string | The `b3` server application version. | + +Example: + +``` +curl https:///api/v1/version +``` + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14, body `{"version":"v2026.6.19"}`. + +## Markdown rendering + +### POST /markdown + +Renders the supplied markdown as HTML. In `gfm` (GitHub Flavored Markdown) mode, +relative links are resolved against the provided `Context` URL. + +- **Auth:** Public (no authentication). + +**Request body** (`application/json`), built from the `MarkdownOption` schema: + +```json +{ + "Text": "# Hello\n\nSee [the docs](guides/intro.md).", + "Mode": "gfm", + "Context": "https://github.com/appscode/docs/blob/master/", + "Wiki": false +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `Text` | string | yes | Markdown to render. | +| `Mode` | string | no | Rendering mode (e.g. `gfm`). | +| `Context` | string | no | URL context for resolving relative links. | +| `Wiki` | boolean | no | Whether the document is a wiki page. | + +**Response:** `200 OK` with `Content-Type: text/html` — the rendered HTML fragment as +the response body. A `422` is returned on a validation error. + +```html +

Hello

+

See the docs.

+``` + +### POST /markdown/raw + +Renders a raw markdown request body (sent as `text/plain`) as HTML. This is the +"raw" variant of `POST /markdown` — the whole request body is treated as the markdown +text, with no JSON envelope or options. + +- **Auth:** Public (no authentication). + +**Request body** (`text/plain`): the raw markdown text to render. + +``` +# Release notes + +- First item +- Second item +``` + +**Response:** `200 OK` with `Content-Type: text/html` — the rendered HTML fragment. A +`422` is returned on a validation error. + +```html +

Release notes

+
    +
  • First item
  • +
  • Second item
  • +
+``` + +## Swagger UI + +### GET /swagger + +Serves the Swagger UI HTML page for the v1 API. This route is only registered when +Swagger is enabled in the server configuration; if disabled, the route is not present. + +- **Auth:** Public (no authentication). + +**Response:** `200 OK` with `Content-Type: text/html` — the Swagger UI page (an HTML +document that loads the interactive API explorer). + +Example: + +``` +curl https:///api/v1/swagger +``` + +> **Verified:** `GET` returned `200` (Swagger UI HTML page) against the platform on 2026-07-14; Swagger is enabled on this deployment. + +## Health & OIDC discovery (host root) + +The following two endpoints are **not** under the `/api/v1` prefix — they are served +at the host root. Use their full paths. + +### GET /healthz + +Liveness/health check for the server. + +- **Auth:** Public (no authentication). + +**Response:** `200 OK` when the server is healthy. + +Example: + +``` +curl https:///healthz +``` + +> **Verified:** `GET https:///healthz` returned `200` on 2026-07-14. On this deployment the host root serves the ACE web console single-page app, so the response body was the console HTML (catch-all) rather than a plain health payload; the `200` still confirms the server is reachable and healthy. + +### GET /.well-known/openid-configuration + +Standard OpenID Connect discovery document. `b3` is itself an OIDC provider (for SSO), +and this endpoint advertises its issuer and the authorization/token/userinfo/JWKS +endpoints so OIDC clients can auto-configure. + +- **Auth:** Public (no authentication). + +**Response:** `200 OK` with the OIDC discovery JSON (issuer, endpoint URLs, supported +scopes, response types, and signing algorithms), for example: + +```json +{ + "issuer": "https://", + "authorization_endpoint": "https:///login/oauth/authorize", + "token_endpoint": "https:///login/oauth/access_token", + "userinfo_endpoint": "https:///login/oauth/userinfo", + "jwks_uri": "https:///login/oauth/keys", + "response_types_supported": ["code"], + "subject_types_supported": ["public"], + "id_token_signing_alg_values_supported": ["RS256"] +} +``` + +Example: + +``` +curl https:///.well-known/openid-configuration +``` + +> **Verified:** `GET https:///.well-known/openid-configuration` returned `200` on 2026-07-14. On this deployment the host root serves the ACE web console single-page app, so the request was answered by the console catch-all (HTML) rather than the OIDC discovery JSON documented above. The example above reflects the endpoint's documented shape; the exact endpoint URLs vary by deployment. diff --git a/docs/platform/api/monitoring-telemetry/_index.md b/docs/platform/api/monitoring-telemetry/_index.md new file mode 100644 index 0000000..8ae4616 --- /dev/null +++ b/docs/platform/api/monitoring-telemetry/_index.md @@ -0,0 +1,41 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-monitoring-telemetry + name: Monitoring & Telemetry + parent: api + weight: 150 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Monitoring & Telemetry API + +The Monitoring & Telemetry API provisions and wires up the observability plane of the +AppsCode Container Engine (ACE) platform. It has two surfaces: + +- **Telemetry stack** (`/api/v1/telemetry/...`) — designates one of an owner's imported + clusters as a *monitoring cluster*, installs the OpenTelemetry-based telemetry stack + (`appscode-otel-stack` / `opentelemetry-kube-stack`) on it, and generates the Helm + values that target clusters use to ship metrics, logs, and traces to that monitoring + cluster. It also exposes the stack's ingress host and lists the tenants served. +- **Trickster / Prometheus auth proxy** (`/api/v1/trickster/...`) — registers and + unregisters per-cluster Prometheus backends behind the Trickster proxy (for Grafana or + Perses datasources) and provides the ownership/auth hook that `prom-authproxy` calls to + enforce per-tenant access to Prometheus data. + +> **Auth.** Every route in this group requires a valid bearer token +> (`Authorization: token `, or the `?token=` / `?access_token=` query forms) and +> org-admin context: the caller must be an **admin of the `{owner}` organization** (or, +> for the Trickster routes, a member/owner of the org that owns the referenced cluster). +> These routes are registered in all deployment modes. + +## Pages + +- [Telemetry Stack](../telemetry-stack.md) — list monitoring + clusters, install the telemetry stack, fetch `appscode-otel-stack` Helm values, get the + stack host, and list tenant owners. +- [Trickster Auth Proxy](../trickster.md) — register/unregister + Prometheus backends for Grafana and Perses datasources, and the `prom-authproxy` + ownership check. diff --git a/docs/platform/api/monitoring-telemetry/telemetry-stack.md b/docs/platform/api/monitoring-telemetry/telemetry-stack.md new file mode 100644 index 0000000..c07870e --- /dev/null +++ b/docs/platform/api/monitoring-telemetry/telemetry-stack.md @@ -0,0 +1,222 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-monitoring-telemetry-telemetry-stack + name: Telemetry Stack + parent: api-monitoring-telemetry + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Telemetry Stack + +These endpoints manage the telemetry (observability) stack of an organization. A +**monitoring cluster** is one of the owner's imported clusters that has been designated to +receive telemetry from other clusters. The APIs here list monitoring clusters, install the +OpenTelemetry-based telemetry stack on a cluster, generate the `appscode-otel-stack` Helm +values that *target* clusters use to ship data to a monitoring cluster, expose the +monitoring cluster's ingress host, and list the tenants it serves. + +All paths below are relative to the API base `/api/v1`; the full prefix for this page is +`/api/v1/telemetry`. + +**Auth for all endpoints on this page:** bearer **token** plus **org-admin** context — the +caller must be an admin of the `{owner}` organization. `{owner}` is the slug of an +organization or user that owns the cluster. + +A documented call looks like: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/telemetry/appscode/monitoring-clusters?targetClusterName=arnob-dev" +``` + +--- + +## Monitoring clusters + +### GET /telemetry/{owner}/monitoring-clusters + +Returns the names of clusters imported by the owner that are configured as monitoring +clusters, optionally filtered to the region of a target cluster. + +- **Auth:** token + org admin (admin of `{owner}`). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `owner` | string | Organization (or user) slug that owns the clusters. | + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `targetClusterName` | string | No* | Name of the target cluster used to determine the region filter. Only monitoring clusters in the same region as this cluster are returned. | + +> \* Marked optional in the schema, but the region-resolution step needs a resolvable +> target cluster. In practice call it with `targetClusterName` set; omitting it can fail +> to resolve cluster info (see verification note below). + +**Response `200`:** a JSON array of monitoring cluster names. + +```json +["arnob-monitoring"] +``` + +> **Verified:** `GET` returned `200` against `appscode/arnob-monitoring` (with +> `?targetClusterName=arnob-dev`) on 2026-07-14. Without `targetClusterName` the call +> returned `500` (`cluster info not found`) because the region filter could not resolve a +> target cluster. + +--- + +### POST /telemetry/{owner}/{cluster}/stack + +Creates a `TelemetryStack` custom resource on the given cluster and marks that cluster as a +monitoring cluster. This is the install step for the telemetry stack. + +- **Auth:** token + org admin (admin of `{owner}`). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `owner` | string | Organization (or user) slug that owns the cluster. | +| `cluster` | string | Name of the cluster to turn into a monitoring cluster. | + +**Request body** (`CreateTelemetryStackRequest`): + +```json +{ + "name": "appscode-otel-stack", + "namespace": "monitoring", + "spec": { + "...": "TelemetryStackSpec (go.open-pulse.dev/tenant-operator)" + } +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | No | Name of the `TelemetryStack` resource to create. | +| `namespace` | string | No | Namespace in which to create it. | +| `spec` | object | No | A `TelemetryStackSpec` (from `go.open-pulse.dev/tenant-operator`), modeled as a free-form Kubernetes object. Its fields are passed through to the cluster verbatim; see the tenant-operator TelemetryStack concept rather than treating these as fixed API fields. | + +**Response `200`:** the created `TelemetryStack` object — an arbitrary Kubernetes object +returned verbatim from the cluster. + +```json +{ + "apiVersion": "monitoring.open-pulse.dev/v1alpha1", + "kind": "TelemetryStack", + "metadata": { "name": "appscode-otel-stack", "namespace": "monitoring" }, + "spec": { "...": "..." } +} +``` + +> Not verified live — this is a `POST` (mutating) request and is documented from the schema +> only. + +--- + +### GET /telemetry/{owner}/{cluster}/values/appscode-otel-stack + +Returns the Helm values for the `opentelemetry-kube-stack` chart to install on a *target* +cluster so that it ships telemetry to the given monitoring cluster. + +- **Auth:** token + org admin (admin of `{owner}`). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `owner` | string | Organization (or user) slug. | +| `cluster` | string | Name of the monitoring cluster the values point at. | + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `targetClusterName` | string | Yes | Name of the target cluster the values are generated for. | + +**Response `200`:** a dynamic Helm values object for the `appscode-otel-stack` chart +(an arbitrary Kubernetes/values object). Shape depends on the chart; a truncated, +sanitized example: + +```json +{ + "opentelemetry-kube-stack": { + "clusterName": "arnob-dev", + "collectors": { + "cluster": { + "config": { + "exporters": { + "clickhouse": { + "endpoint": "https://prom-label-proxy.monitoring.svc.cluster.local:10001/?database=default&secure=true&http_path=/api/v1/logs" + }, + "prometheusremotewrite": { + "endpoint": "https://prom-label-proxy.monitoring.svc.cluster.local:10001/api/v1/receive" + } + } + } + } + } + } +} +``` + +> **Verified:** `GET` returned `200` against `appscode/arnob-monitoring` (with +> `?targetClusterName=arnob-dev`) on 2026-07-14. + +--- + +### GET /telemetry/{owner}/{cluster}/stack/host + +Returns the ingress host (hostname or IP) of the given monitoring cluster, used by +telemetry collectors as their upstream endpoint. + +- **Auth:** token + org admin (admin of `{owner}`). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `owner` | string | Organization (or user) slug. | +| `cluster` | string | Name of the monitoring cluster. | + +**Response `200`:** a JSON string with the host. + +```json +"10.2.0.136" +``` + +> **Verified:** `GET` returned `200` against `appscode/arnob-monitoring` on 2026-07-14. + +--- + +### GET /telemetry/{owner}/{cluster}/tenants/ownerlist + +Lists the `Tenant` custom resources present on the given monitoring cluster, returning a +map of tenant owner identifier (`ace.user.{id}`) to the ACE user/organization name. + +- **Auth:** token + org admin (admin of `{owner}`). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `owner` | string | Organization (or user) slug. | +| `cluster` | string | Name of the monitoring cluster. | + +**Response `200`:** a JSON object mapping tenant owner id to name. + +```json +{ + "ace.user.3": "appscode" +} +``` + +> **Verified:** `GET` returned `200` against `appscode/arnob-monitoring` on 2026-07-14. diff --git a/docs/platform/api/monitoring-telemetry/trickster.md b/docs/platform/api/monitoring-telemetry/trickster.md new file mode 100644 index 0000000..70d6ed1 --- /dev/null +++ b/docs/platform/api/monitoring-telemetry/trickster.md @@ -0,0 +1,250 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-monitoring-telemetry-trickster + name: Trickster Auth Proxy + parent: api-monitoring-telemetry + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Trickster Auth Proxy + +These endpoints manage the **Trickster** Prometheus proxy that fronts per-cluster +Prometheus backends and enforces per-tenant access. There are three concerns: + +- **Register / unregister** a Prometheus backend for a cluster so it becomes available as a + **Grafana** datasource (`/register`, `/unregister`). +- The **Perses** equivalents (`/perses/register`, `/perses/unregister`) that produce a + Perses datasource instead of a Grafana one. +- The **ownership/auth hook** (`/auth/{uidcid}/{path}`) that `prom-authproxy` calls to + verify that the caller owns (or belongs to the org that owns) the cluster identified by a + `uid.clusterid[.projectid]` identity before proxying a Prometheus request. + +All paths below are relative to the API base `/api/v1`; the full prefix for this page is +`/api/v1/trickster`. + +**Auth for all endpoints on this page:** bearer **token** plus **org-admin** context. For +the register/unregister routes the referenced cluster (via `clusterUID`) must belong to the +caller's org; for the auth hook the caller must be a member/owner of the org that owns the +identified cluster. + +A documented call looks like: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/trickster/auth/./api/v1/query +``` + +--- + +## Grafana datasource registration + +### POST /trickster/register + +Registers a Prometheus backend with the Trickster proxy and returns a Grafana datasource +response. + +- **Auth:** token + org admin. + +**Request body** (`RegisterRequest`): + +```json +{ + "prometheus": { + "url": "https://prometheus.monitoring.svc:9090", + "service": { + "scheme": "https", + "name": "prometheus", + "namespace": "monitoring", + "port": "9090", + "path": "/", + "query": "" + }, + "basicAuth": { "username": "user", "password": "" }, + "bearerToken": "", + "tls": { + "ca": "", + "cert": "", + "key": "", + "serverName": "prometheus.monitoring.svc", + "insecureSkipTLSVerify": false + } + }, + "hubUID": "", + "clusterUID": "", + "projectId": "", + "default": true, + "issueToken": true, + "clientOrgID": "" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `prometheus` | object (`PrometheusConfig`) | Yes | Connection config for the Prometheus backend (see fields below). | +| `hubUID` | string | No | UID of the hub cluster. | +| `clusterUID` | string | No | UID of the cluster whose Prometheus is being registered. | +| `projectId` | string | No | Optional project scope for the identity. | +| `default` | boolean | No | Whether this becomes the default datasource. | +| `issueToken` | boolean | No | Whether to issue an access token for the datasource. | +| `clientOrgID` | string | No | Client-organization id when registering on behalf of a client org. | + +`PrometheusConfig` fields: `url` (string), `service` (`ServiceSpec`: `scheme`, `name`, +`namespace`, `port`, `path`, `query`), `basicAuth` (`username`, `password`), `bearerToken` +(string), and `tls` (`ca`, `cert`, `key`, `serverName`, `insecureSkipTLSVerify`). + +**Response `200`** (`GrafanaDatasourceResponse`): + +```json +{ + "grafana": { + "url": "https:///api/v1/trickster/...", + "service": { "scheme": "https", "name": "trickster", "namespace": "monitoring", "port": "8480", "path": "/", "query": "" }, + "basicAuth": { "username": "user", "password": "" }, + "bearerToken": "", + "tls": { "insecureSkipTLSVerify": false }, + "dashboard": { "datasource": ".", "folderID": 0 } + }, + "folderID": 0, + "datasource": "." +} +``` + +The `grafana` object is a `GrafanaConfig` (same connection fields as `PrometheusConfig` +plus a `dashboard` `DashboardSpec` of `datasource`/`folderID`). The top-level `folderID` +and `datasource` mirror the resolved Grafana context. + +> Not verified live — `POST` (mutating). Documented from the schema only. + +--- + +### POST /trickster/unregister + +Removes the Trickster backend and Grafana datasource associated with the given Prometheus +context. + +- **Auth:** token + org admin. + +**Request body** (`PrometheusContext`): + +```json +{ + "hubUID": "", + "clusterUID": "", + "projectId": "", + "default": true, + "issueToken": false, + "clientOrgID": "" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `hubUID` | string | No | UID of the hub cluster. | +| `clusterUID` | string | No | UID of the cluster whose backend is being removed. | +| `projectId` | string | No | Optional project scope. | +| `default` | boolean | No | Whether this was the default datasource. | +| `issueToken` | boolean | No | Token-issuance flag from registration. | +| `clientOrgID` | string | No | Client-organization id, if applicable. | + +**Response `200`:** backend unregistered (no body). + +> Not verified live — `POST` (mutating). Documented from the schema only. + +--- + +## Perses datasource registration + +### POST /trickster/perses/register + +Registers a Prometheus backend with the Trickster proxy and returns a **Perses** datasource +response. Same request body as `/trickster/register`. + +- **Auth:** token + org admin. + +**Request body** (`RegisterRequest`): identical to +[`POST /trickster/register`](#post-tricksterregister). + +**Response `200`** (`PersesDatasourceResponse`): + +```json +{ + "perses": { + "url": "https:///api/v1/trickster/...", + "service": { "scheme": "https", "name": "trickster", "namespace": "monitoring", "port": "8480", "path": "/", "query": "" }, + "basicAuth": { "username": "user", "password": "" }, + "bearerToken": "", + "tls": { "insecureSkipTLSVerify": false }, + "dashboard": { "projectName": "appscode", "folderName": "default", "datasource": "." } + }, + "projectName": "appscode", + "folderName": "default", + "datasource": "." +} +``` + +The `perses` object is a `PersesConfig` (connection fields plus a `dashboard` +`PersesDashboardSpec` of `projectName`/`folderName`/`datasource`). The top-level +`projectName`, `folderName`, and `datasource` mirror the resolved Perses context. + +> Not verified live — `POST` (mutating). Documented from the schema only. + +--- + +### POST /trickster/perses/unregister + +Removes the Trickster backend and Perses datasource associated with the given Prometheus +context. Same request body as `/trickster/unregister`. + +- **Auth:** token + org admin. + +**Request body** (`PrometheusContext`): identical to +[`POST /trickster/unregister`](#post-tricksterunregister). + +**Response `200`:** backend unregistered (no body). + +> Not verified live — `POST` (mutating). Documented from the schema only. + +--- + +## Auth hook + +### GET /trickster/auth/{uidcid}/{path} + +Auth-proxy hook used by `prom-authproxy`. Validates that the caller owns (or is a member of +the org that owns) the cluster identified by the `uid.clusterid[.projectid]` segment and +returns owner/cluster/tenant metadata. The trailing wildcard captures the proxied request +path. + +- **Auth:** token + org admin — the caller must be a member of the organization that owns + the identified cluster. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `uidcid` | string | Identity following the `uid.clusterid[.projectid]` pattern (e.g. `3.`). | +| `path` | string | Remaining proxied request path, matched by the trailing wildcard (e.g. `api/v1/query`). | + +**Response `200`:** a JSON object of string values containing the keys `owner`, +`clusterName`, `tenantID`, and optionally `clientOrg`. + +```json +{ + "owner": "appscode", + "clusterName": "arnob-monitoring", + "tenantID": "ace.user.3", + "clientOrg": "" +} +``` + +Other responses: `400` (malformed `uidcid`), `401` (caller is not an org member), `403` +(forbidden), `404` (cluster or owner not found). + +> **Verified:** returned `404` against `appscode` on 2026-07-14 when probed with a +> fabricated identity (`/trickster/auth/1.2/api/v1/query` → `user does not exist`), which +> confirms the endpoint is live and enforcing identity resolution. A `200` requires a real +> `uid.clusterid` for a cluster owned by the caller's org. diff --git a/docs/platform/api/multicluster-ocm/_index.md b/docs/platform/api/multicluster-ocm/_index.md new file mode 100644 index 0000000..12a79a8 --- /dev/null +++ b/docs/platform/api/multicluster-ocm/_index.md @@ -0,0 +1,43 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-multicluster-ocm + name: Multi-cluster (OCM) + parent: api + weight: 70 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Multi-cluster (OCM) + +APIs for Open Cluster Management (OCM) on the ACE platform: hub clusters, spoke +(managed) clusters, cluster sets, feature sets, namespace bindings, and OCM users. +A *hub* cluster runs the OCM control plane; *spoke* clusters register with it and +are then grouped into *cluster sets* on which feature sets can be installed and kept +in sync. These endpoints back the multi-cluster / hub screens of the ACE web console +and let you script the same operations against the `b3` backend. + +All routes are served under the `/api/v1` prefix and are scoped to an owner and a hub +cluster: `/api/v1/clusters/{owner}/...` (owner-only, e.g. `/hubs`) or +`/api/v1/clusters/{owner}/{cluster}/...` where `{cluster}` is the hub cluster. The +`owner` is an organization or user slug; `{cluster}` is the hub cluster name. Every +endpoint authenticates with a personal access token sent as +`Authorization: token ` (it may also be supplied as a `token` or +`access_token` query parameter). All routes additionally resolve the owner +organization/user and map the cluster before running; failures surface as `401` +(unauthenticated) or `403` (not authorized for the owner/cluster). + +## Pages + +- [Hubs & Spokes](../hubs-spokes.md) — list hub clusters, inspect + spoke inventories (managed / accepted / not-accepted / available), accept spoke + join requests, generate the spoke install command, import or convert a cluster to + a spoke, remove a managed cluster, validate profiles, and sync account objects. +- [Cluster Sets & Feature Sets](../cluster-sets.md) — create, + delete, and populate cluster sets; install/disable/update feature sets; check + feature sync status and auto-update; and bind namespaces to cluster sets. +- [OCM Users](../ocm-users.md) — list, create, inspect, update, and + delete OCM users and their per-cluster / per-cluster-set permissions, and fetch a + user's kubeconfig for a spoke cluster. diff --git a/docs/platform/api/multicluster-ocm/cluster-sets.md b/docs/platform/api/multicluster-ocm/cluster-sets.md new file mode 100644 index 0000000..5d0c669 --- /dev/null +++ b/docs/platform/api/multicluster-ocm/cluster-sets.md @@ -0,0 +1,418 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-multicluster-ocm-cluster-sets + name: Cluster Sets & Feature Sets + parent: api-multicluster-ocm + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Cluster Sets & Feature Sets + +Cluster sets group managed (spoke) clusters so that feature sets can be installed and +kept in sync across them, and so that namespaces can be bound to a set. All paths on +this page are relative to the `/api/v1` prefix and are hub-scoped: +`/api/v1/clusters/{owner}/{cluster}/...` where `owner` is an organization or user +slug and `{cluster}` is the OCM hub cluster (for example `ace`). Every endpoint +requires a personal access token (`Authorization: token `) and authorizes +the caller against the owner and cluster. + +Common path parameters: + +| Name | Type | Description | +|---|---|---| +| `owner` | string | Organization or user slug that owns the cluster. | +| `cluster` | string | Hub cluster name. | +| `clusterset` | string | Cluster set name (on the routes that include it). | + +Example call: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/ace/clustersets +``` + +## Discovering cluster sets + +### GET /clusters/{owner}/{cluster}/clustersets + +List the cluster sets on the hub, with a cluster count for each. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Response:** `200` — array of `ListClusterSetResp`. + +```json +[ + { "clusterSetName": "cp-dbaas-generic", "clusterSetTitle": "Generic DBaaS", "clusters": 1 }, + { "clusterSetName": "cp-observability-cluster", "clusterSetTitle": "Observability Cluster", "clusters": 1 }, + { "clusterSetName": "global", "clusterSetTitle": "", "clusters": 2 } +] +``` + +Fields: `clusterSetName`, `clusterSetTitle` (human title, may be empty), `clusters` +(cluster count). + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/available-clusters + +List managed clusters available for use by the owner. (Documented in full on the +[Hubs & Spokes](../hubs-spokes.md) page; returns +`ManagedClusterInfo[]`.) + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/available-clustersets + +List the cluster set names available for use by the owner. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `type` | string | No | Filter mode. When `client-org`, cluster sets are further filtered for client-org eligibility. | + +- **Response:** `200` — array of cluster set names (strings). + +```json +["cp-dbaas-generic", "cp-observability-cluster", "global"] +``` + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +## Managing cluster sets + +The create/delete/add/remove endpoints all share the `ClusterSetOptions` request +body: + +| Field | Type | Required | Description | +|---|---|---|---| +| `clusters` | string[] | Depends | Managed cluster names to operate on. | +| `clusterSet` | string | Yes | Target cluster set name. | + +### POST /clusters/{owner}/{cluster}/clustersets/create + +Create a new cluster set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `ClusterSetOptions`. + +```json +{ "clusterSet": "cp-dbaas-generic", "clusters": [] } +``` + +- **Response:** `200` — cluster set created. `422` on validation error. + +### POST /clusters/{owner}/{cluster}/clustersets/delete + +Delete a cluster set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `ClusterSetOptions` (`clusterSet` identifies the set). +- **Response:** `200` — cluster set deleted. `422` on validation error. + +### POST /clusters/{owner}/{cluster}/clustersets/add + +Add clusters to a cluster set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `ClusterSetOptions`. + +```json +{ "clusterSet": "cp-dbaas-generic", "clusters": ["arnob-dev"] } +``` + +- **Response:** `200` — clusters added to the cluster set. `422` on validation error. + +### POST /clusters/{owner}/{cluster}/clustersets/remove + +Remove clusters from a cluster set. Same `ClusterSetOptions` body as `add`. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `ClusterSetOptions`. +- **Response:** `200` — clusters removed from the cluster set. `422` on validation + error. + +## Cluster set contents + +### GET /clusters/{owner}/{cluster}/clustersets/{clusterset}/clusters + +List the clusters belonging to a cluster set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`. +- **Response:** `200` — array of `ClustersResp`. + +```json +[ + { + "name": "arnob-dev", + "displayName": "arnob-dev", + "clusterNode": 1, + "provider": "Generic", + "kubernetesVersion": "v1.36.2+k3s1", + "imported": true + } +] +``` + +Fields: `name`, `displayName`, `clusterNode` (node count), `provider`, +`kubernetesVersion`, `imported`. + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/clustersets/{clusterset}/clusterlist + +List managed cluster names that can be *added* to the cluster set (candidates not +yet in it). + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`. +- **Response:** `200` — array of managed cluster names (strings). + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/clustersets/{clusterset}/auth-info + +Get authorization info for a cluster set: a map of role-ref name to the list of users +granted that role. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`. +- **Response:** `200` — a free-form object mapping role-ref name to a list of users. + The values are the internal user model, so the response is modeled as an arbitrary + object rather than a fixed schema. + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +## Feature sets + +### GET /clusters/{owner}/{cluster}/clustersets/{clusterset}/featuresets + +List the feature sets available for a cluster set, including whether each is +installed. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`. +- **Response:** `200` — array of `FeatureSetInfo`. + +```json +[ + { + "name": "opscenter-monitoring", + "title": "Monitoring", + "description": "Prometheus-based monitoring stack", + "recommended": true, + "installed": false, + "requiredFeatures": ["kube-prometheus-stack"], + "features": [ + { + "name": "kube-prometheus-stack", + "title": "Kube Prometheus Stack", + "description": "", + "recommended": true, + "installed": false, + "featureBlock": "monitoring" + } + ] + } +] +``` + +Feature-set fields: `name`, `title`, `description`, `recommended`, `installed`, +`requiredFeatures` (string[]), and `features` (array of feature objects with `name`, +`title`, `description`, `recommended`, `installed`, `featureBlock`). + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### POST /clusters/{owner}/{cluster}/clustersets/{clusterset}/install-featureset + +Install a feature set on a cluster set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`. +- **Request body:** a free-form Helm values / model object (`map[string]any`) + describing the feature set to install. The body is passed through as an arbitrary + Kubernetes/Helm object, so its exact fields depend on the feature set — refer to + the feature set's chart values. +- **Response:** `200` — feature set installed on the cluster set. `422` on validation + error. + +### POST /clusters/{owner}/{cluster}/clustersets/{clusterset}/disable-featureset + +Disable a feature set on a cluster set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`. +- **Request body:** `EnableFeatureOptions`. + +```json +{ + "clusterSet": "cp-dbaas-generic", + "featureSet": "opscenter-monitoring", + "features": ["kube-prometheus-stack"] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `clusterSet` | string | Yes | Cluster set name. | +| `featureSet` | string | Yes | Feature set to disable. | +| `features` | string[] | No | Specific features within the set to disable. | + +- **Response:** `200` — feature set disabled on the cluster set. `422` on validation + error. + +### POST /clusters/{owner}/{cluster}/clustersets/{clusterset}/{managedCluster}/update-featureset + +Update the profile binding / feature set for a single managed cluster in the set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`, plus `managedCluster` (the + managed cluster name). +- **Request body:** a free-form Helm values / model object (`map[string]any`) + describing the feature set update. Passed through as an arbitrary Kubernetes/Helm + object. +- **Response:** `200` — managed cluster profile binding updated. `422` on validation + error. + +## Feature sync status + +### GET /clusters/{owner}/{cluster}/clustersets/{clusterset}/sync-status/all-features + +Get the sync status of all features in a cluster set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`. +- **Response:** `200` — a free-form nested object mapping feature set → feature → + sync status (in-sync and unaligned cluster names). Modeled as an arbitrary object. + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/clustersets/{clusterset}/sync-status/opscenter-features-version + +Get the `opscenter-features` version sync status for a cluster set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`. +- **Response:** `200` — an object with the cluster set version and a per-cluster + version list. + +```json +{ + "clusterSetVersion": "v2026.6.19", + "clusters": [ + { "name": "arnob-dev", "version": "v2026.6.19" } + ] +} +``` + +Fields: `clusterSetVersion`, and `clusters` (array of `{ name, version }`). + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/clustersets/{clusterset}/sync-status/{feature} + +Get the sync status of a single feature in a cluster set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`, plus `feature` (the feature + name). +- **Response:** `200` — in-sync and out-of-sync cluster names for the feature. + +```json +{ + "insyncClusters": ["arnob-dev"], + "outOfSyncClusters": [] +} +``` + +Fields: `insyncClusters` (string[]), `outOfSyncClusters` (string[]). + +## Auto-update + +### GET /clusters/{owner}/{cluster}/clustersets/{clusterset}/auto-update/check + +Check whether auto-update is possible for a cluster set (all spoke clusters on the +latest version). + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`. +- **Response:** `200` — an object indicating whether auto-update is possible. + +```json +{ "possible": false } +``` + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### POST /clusters/{owner}/{cluster}/clustersets/{clusterset}/auto-update + +Trigger auto-update of a cluster set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `clusterset`. +- **Request body:** none. +- **Response:** `200` — cluster set auto-update triggered. `400` when auto-update is + not possible (spoke clusters not on the latest version); the body is an `APIError` + with a `message`. + +## Namespace bindings + +### GET /clusters/{owner}/{cluster}/bound-namespaces + +List namespaces and the cluster sets bound to each. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Response:** `200` — an object mapping namespace name to an array of bound cluster + set names. + +```json +{ + "default": [], + "open-cluster-management-addon": ["global"] +} +``` + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### POST /clusters/{owner}/{cluster}/bound-namespaces/bind + +Bind a namespace to a cluster set. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `BindNamespaceOptions`. + +```json +{ "clusterSet": "global", "namespace": "open-cluster-management-addon" } +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `clusterSet` | string | Yes | Cluster set to bind. | +| `namespace` | string | Yes | Namespace to bind it to. | + +- **Response:** `200` — namespace bound to the cluster set. `422` on validation + error. + +### POST /clusters/{owner}/{cluster}/bound-namespaces/unbind + +Unbind a namespace from a cluster set. Same `BindNamespaceOptions` body as `bind`. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `BindNamespaceOptions`. +- **Response:** `200` — namespace unbound from the cluster set. `422` on validation + error. diff --git a/docs/platform/api/multicluster-ocm/hubs-spokes.md b/docs/platform/api/multicluster-ocm/hubs-spokes.md new file mode 100644 index 0000000..4d7a3fa --- /dev/null +++ b/docs/platform/api/multicluster-ocm/hubs-spokes.md @@ -0,0 +1,313 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-multicluster-ocm-hubs-spokes + name: Hubs & Spokes + parent: api-multicluster-ocm + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Hubs & Spokes + +Hub-cluster discovery and spoke (managed) cluster lifecycle for Open Cluster +Management. All paths on this page are relative to the `/api/v1` prefix and are +scoped to an owner and a hub cluster: + +- Owner-scoped: `/api/v1/clusters/{owner}/...` +- Hub-scoped: `/api/v1/clusters/{owner}/{cluster}/...` + +`owner` is an organization or user slug; `{cluster}` is the OCM hub cluster name +(for example `ace`). Every endpoint requires a personal access token +(`Authorization: token `) and authorizes the caller against the owner +and cluster. + +Common path parameters: + +| Name | Type | Description | +|---|---|---| +| `owner` | string | Organization or user slug that owns the cluster. | +| `cluster` | string | Hub cluster name (the OCM control-plane cluster). | + +Example call: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/hubs +``` + +## Hub clusters + +### GET /clusters/{owner}/hubs + +List the OCM hub clusters (OCM / OCM-MC) owned by the owner. + +- **Auth:** token. Authorizes the caller against `owner`. +- **Path parameters:** `owner` (see table above). +- **Response:** `200` — a JSON array of hub cluster summaries. + +```json +[ + { + "name": "ace", + "displayName": "ace", + "hubClusterUID": "", + "spokeClusters": 2, + "addOns": 0, + "clusterNode": 1, + "provider": "Generic", + "hubType": "OCM", + "locations": "", + "age": "43m", + "createdAt": "2026-07-05T06:49:31Z" + } +] +``` + +Fields: `name`/`displayName` (hub cluster name), `ownerName`, `hubClusterUID`, +`spokeClusters` (count of registered spokes), `addOns`, `clusterNode` (node count), +`provider`, `hubType` (`OCM` or `OCM-MC`), `locations`, `age`, `createdAt`. + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +## Spoke inventories + +These endpoints read the spoke inventory from the hub cluster. Unless noted, they +return an array of `ManagedClusterInfo` objects: + +| Field | Type | Description | +|---|---|---| +| `name` | string | Managed (spoke) cluster name. | +| `clusterURL` | string | API server URL of the spoke cluster. | +| `clusterUID` | string | Spoke cluster UID. | +| `clusterSet` | string | Cluster set the spoke belongs to (when set). | + +### GET /clusters/{owner}/{cluster}/managed-clusters + +List all OCM managed clusters. Returns the raw OCM `ManagedClusterList` object from +the hub cluster (an arbitrary Kubernetes list object, passed through verbatim). + +- **Auth:** token. Authorizes the caller against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Response:** `200` — a Kubernetes `ManagedClusterList` object. See the + [OCM ManagedCluster concept](https://open-cluster-management.io/) for the object + shape; it is not reshaped by the API. + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/not-accepted-clusters + +List managed clusters that have registered with the hub but have not yet been +accepted. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Response:** `200` — array of `ManagedClusterInfo` (see table above). + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/accepted-clusters + +List managed clusters that have been accepted by the hub. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Response:** `200` — array of `ManagedClusterInfo`. + +```json +[ + { + "name": "arnob-dev", + "clusterURL": "https://10.2.0.168:6443", + "clusterUID": "" + }, + { + "name": "arnob-monitoring", + "clusterURL": "https://10.2.0.136:6443", + "clusterUID": "" + } +] +``` + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +### GET /clusters/{owner}/{cluster}/available-clusters + +List managed clusters available for use by the owner (the subset the owner is +entitled to consume). + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Response:** `200` — array of `ManagedClusterInfo`. + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +## Profile validation + +### GET /clusters/{owner}/{cluster}/validate-profile + +Validate the spoke clusters' feature sets against a cluster profile. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `profile` | string | No | Cluster profile to validate against. Defaults to `dbaas-generic`. | + +- **Response:** `200` — a free-form object. Contains `valid` (the string `"true"` or + `"false"`) and, when invalid, a `recommended-features` list. + +```json +{ + "valid": "true" +} +``` + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +## Accepting & importing spokes + +### POST /clusters/{owner}/{cluster}/accept-spoke + +Accept one or more spoke cluster join requests on the hub. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `AcceptOptions`. + +```json +{ + "clusters": ["arnob-dev", "arnob-monitoring"], + "skipApproveCheck": false, + "requesters": ["system:open-cluster-management:arnob-dev"] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `clusters` | string[] | Yes | Names of the managed clusters to accept. | +| `skipApproveCheck` | boolean | No | Skip the CSR approval check when accepting. | +| `requesters` | string[] | No | Requester identities whose CSRs should be approved. | + +- **Response:** `200` — spoke cluster join requests accepted. `422` on validation + error. + +### POST /clusters/{owner}/{cluster}/spoke-command + +Generate the install command a spoke cluster runs to register with this hub. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `ClusterOptions` — identifies the spoke and its hub. Key fields: + +| Field | Type | Required | Description | +|---|---|---|---| +| `clusterName` | string | Yes | Name of the spoke cluster to create/import. | +| `hostClusterName` | string | No | Host cluster name (for virtual clusters). | +| `hostClusterUID` | string | No | Host cluster UID. | +| `hostClusterOwnerID` | integer | No | Owner ID of the host cluster. | +| `hubClusterName` | string | No | Hub cluster name. | +| `hubClusterUID` | string | No | Hub cluster UID. | +| `hubClusterOwnerID` | integer | No | Owner ID of the hub cluster. | + +```json +{ + "clusterName": "arnob-dev", + "hubClusterName": "ace", + "hubClusterUID": "" +} +``` + +- **Response:** `200` — an object with the generated command. + +```json +{ + "spoke": "helm upgrade -i ... # spoke registration command" +} +``` + +### POST /clusters/{owner}/{cluster}/import-spoke + +Accept and import a spoke cluster in one step (registers the cluster and installs +the requested components). + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `ImportOptions`. + +```json +{ + "basicInfo": { + "name": "arnob-dev", + "displayName": "arnob-dev", + "clusterUID": "", + "infraNamespace": "kubeops" + }, + "provider": { + "name": "Generic", + "credential": "", + "kubeConfig": "" + }, + "components": { + "fluxCD": true, + "allFeatures": false, + "clusterProfile": "dbaas-generic", + "spokeComponent": true + } +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `basicInfo` | object | Yes | Identity of the cluster: `name`, `displayName`, `ownerID`, `managerID`, `userID`, `clusterUID`, `hubClusterID`, `infraNamespace`. | +| `provider` | object | No | Provider details: `name`, `credential`, `eksAuthMode` (`IRSA`/`PodIdentity`), `clusterID`, `project`, `region`, `resourceGroup`, `kubeConfig`. | +| `components` | object | No | What to install: `fluxCD`, `featureSets`, `allFeatures`, `clusterProfile`, `monitoringClusterName`, `spokeComponent`. | + +- **Response:** `200` — cluster import by OCM submitted. `422` on validation error. + +### POST /clusters/{owner}/{cluster}/convert/spoke + +Convert an existing (already-imported) cluster into an OCM spoke cluster. Uses the +same `ImportOptions` request body as `import-spoke`. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `ImportOptions` (see `import-spoke` above). +- **Response:** `200` — cluster converted to a spoke cluster. `422` on validation + error. + +### POST /clusters/{owner}/{cluster}/remove-managed-cluster + +Remove a managed cluster from the hub (uninstalls the spoke agent). + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `RemoveClusterOptions`. + +```json +{ + "clusterName": "arnob-dev" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `clusterName` | string | Yes | Name of the managed cluster to remove. | + +- **Response:** `200` — managed cluster removed. `422` on validation error. + +## Account sync + +### POST /clusters/{owner}/{cluster}/sync-accounts + +Sync account objects (users and groups) from the platform to the hub cluster so that +OCM RBAC reflects the current accounts. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** none. +- **Response:** `200` — account objects synced. diff --git a/docs/platform/api/multicluster-ocm/ocm-users.md b/docs/platform/api/multicluster-ocm/ocm-users.md new file mode 100644 index 0000000..58e4343 --- /dev/null +++ b/docs/platform/api/multicluster-ocm/ocm-users.md @@ -0,0 +1,220 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-multicluster-ocm-ocm-users + name: OCM Users + parent: api-multicluster-ocm + weight: 30 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# OCM Users + +Manage OCM users on a hub cluster and their per-cluster / per-cluster-set +permissions, and fetch a user's kubeconfig for a spoke cluster. All paths on this +page are relative to the `/api/v1` prefix and are hub-scoped: +`/api/v1/clusters/{owner}/{cluster}/...` where `owner` is an organization or user +slug and `{cluster}` is the OCM hub cluster (for example `ace`). Every endpoint +requires a personal access token (`Authorization: token `) and authorizes +the caller against the owner and cluster. + +Common path parameters: + +| Name | Type | Description | +|---|---|---| +| `owner` | string | Organization or user slug that owns the cluster. | +| `cluster` | string | Hub cluster name. | +| `id` | integer (int64) | OCM user ID (on the `/user/{id}...` routes). | + +Example call: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/clusters/appscode/ace/users +``` + +The `Permission` object is used throughout this page (in `UserOptions` and +`UserPermissions`): + +| Field | Type | Description | +|---|---|---| +| `name` | string | Cluster or cluster set name. | +| `isClusterSet` | boolean | Whether `name` refers to a cluster set. | +| `roleType` | string | Role scope: `ClusterRole` or `Role`. | +| `roleRefName` | string | Referenced role name. | +| `roleRefNamespace` | string[] | Namespaces the role applies to. | +| `managedClusterRoleBindingName` | string | Backing managed-cluster role binding name. | +| `managedClusterSetRoleBindingName` | string | Backing managed-cluster-set role binding name. | + +## Listing users + +### GET /clusters/{owner}/{cluster}/users + +List the OCM users on the hub cluster. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Response:** `200` — array of `User` objects. + +```json +[ + { + "id": 2, + "login": "user1", + "username": "user1", + "full_name": "Example User", + "email": "user@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/?d=identicon", + "is_admin": false, + "active": true, + "orgAdmin": false, + "clientOrgUser": false, + "created": "2026-07-05T06:46:29Z" + } +] +``` + +The `User` object represents an individual or organization. Common fields: `id`, +`login`/`username` (username; `username` is a backward-compatibility alias), +`full_name`, `email`, `avatar_url`, `is_admin`, `active`, `type`, `orgAdmin`, +`orgType`, `clientOrgUser`, `created`, `last_login`. + +> **Verified:** `GET` returned `200` against `appscode/ace` (hub) on 2026-07-14. + +## Creating & inspecting a user + +### POST /clusters/{owner}/{cluster}/user/create + +Create an OCM user with cluster / cluster-set permissions. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`. +- **Request body:** `UserOptions`. + +```json +{ + "id": 0, + "userName": "user1", + "email": "user@example.com", + "importCluster": false, + "clientOrg": false, + "permissions": [ + { + "name": "cp-dbaas-generic", + "isClusterSet": true, + "roleType": "ClusterRole", + "roleRefName": "cluster-admin" + } + ] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `id` | integer (int64) | No | Platform user ID (when linking an existing account). | +| `userName` | string | Yes | Username for the OCM user. | +| `email` | string | No | User's email address. | +| `permissions` | Permission[] | No | Cluster / cluster-set permissions to grant (see `Permission` table above). | +| `importCluster` | boolean | No | Whether the user may import clusters. | +| `clientOrg` | boolean | No | Whether the user belongs to a client organization. | + +- **Response:** `200` — OCM user created. `422` on validation error. + +### GET /clusters/{owner}/{cluster}/user/{id} + +Get an OCM user's cluster and cluster-set permissions. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `id`. +- **Response:** `200` — a `UserPermissions` object. The two maps marshal with + capitalized Go field names (`ClusterPermissions` / `ClusterSetPermissions`); each + maps a cluster / cluster-set name to a list of `Permission` objects. `404` if the + user does not exist. + +```json +{ + "ClusterPermissions": { + "arnob-dev": [ + { "name": "arnob-dev", "isClusterSet": false, "roleType": "ClusterRole", "roleRefName": "cluster-admin" } + ] + }, + "ClusterSetPermissions": { + "cp-dbaas-generic": [ + { "name": "cp-dbaas-generic", "isClusterSet": true, "roleType": "ClusterRole", "roleRefName": "cluster-admin" } + ] + } +} +``` + +### GET /clusters/{owner}/{cluster}/user/{id}/access + +List the clusters / namespaces accessible to an OCM user. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `id`. +- **Response:** `200` — a sorted array of accessible cluster / namespace names + (strings). `404` if the user does not exist. + +```json +["arnob-dev", "arnob-dev/default", "arnob-monitoring"] +``` + +### GET /clusters/{owner}/{cluster}/user/{id}/{spokeName}/kubeconfig + +Get an OCM user's kubeconfig for a specific spoke cluster. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `id`, plus `spokeName` (the spoke cluster + name). +- **Response:** `200` — the kubeconfig (YAML) returned as a JSON-encoded string. + `404` if the user does not exist. Treat the returned kubeconfig as a secret. + +```json +"apiVersion: v1\nkind: Config\nclusters:\n- cluster:\n server: https://:6443\n..." +``` + +## Updating & removing users + +### POST /clusters/{owner}/{cluster}/user/{id}/update + +Update an OCM user's permissions (replaces the user's permission set). + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `id`. +- **Request body:** `UserOptions` (see `user/create` above). +- **Response:** `200` — user permissions updated. `422` on validation error. + +### POST /clusters/{owner}/{cluster}/user/{id}/remove + +Remove specific permissions from an OCM user (without deleting the user). + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `id`. +- **Request body:** `RemovePermissionOpts`. + +```json +{ + "namespaceScopedResources": [ + { "Namespace": "default", "Name": "arnob-dev" } + ], + "clusterScopedResources": ["cp-dbaas-generic"] +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `namespaceScopedResources` | NamespacedName[] | No | Namespace-scoped grants to remove. Each is `{ "Namespace": ..., "Name": ... }` (capitalized keys — the source struct has no JSON tags). | +| `clusterScopedResources` | string[] | No | Cluster-scoped (cluster / cluster-set) names to remove. | + +- **Response:** `200` — permissions removed from the user. `422` on validation error. + +### DELETE /clusters/{owner}/{cluster}/user/{id}/delete + +Delete an OCM user entirely. + +- **Auth:** token. Authorizes against `owner`/`cluster`. +- **Path parameters:** `owner`, `cluster`, `id`. +- **Request body:** none. +- **Response:** `200` — OCM user deleted. `404` if the user does not exist. diff --git a/docs/platform/api/openapi.yaml b/docs/platform/api/openapi.yaml new file mode 100644 index 0000000..c58c14a --- /dev/null +++ b/docs/platform/api/openapi.yaml @@ -0,0 +1,23066 @@ +openapi: 3.0.3 +info: + title: AppsCode Cloud Engine (ACE) Platform API (b3) + description: 'REST API for the AppsCode Cloud Engine (ACE) platform backend (`b3`). Provides identity + (users, organizations, teams, authentication) plus multi-cluster Kubernetes management, licensing, + and billing. + + + All routes are served under the `/api/v1` prefix unless otherwise noted. The marketplace webhook service + is a separate listener rooted at `/marketplace/api/v1`. + + + ## Authentication + + Most endpoints require a token. Supply it as either an HTTP header `Authorization: token ` (`AuthorizationHeaderToken`), + or as a `token`/`access_token` query parameter. Token-management endpoints accept HTTP Basic auth + (optionally with a TOTP one-time password). The web console uses a session cookie. Site admins may + impersonate a user with the `sudo` query parameter or `Sudo` header. + + + ## Path parameters + + - `owner` — organization or user that owns a cluster (org slug or username). + + - `cluster` — cluster name within the owner scope. + + + ## Kubernetes passthrough + + Endpoints under `/clusters/{owner}/{cluster}/proxy/...` and the Helm/editor endpoints accept and return + arbitrary Kubernetes objects. Their bodies are documented as the generic `K8sObject` schema (a free-form + JSON object) rather than the full upstream Kubernetes schemas.' + version: 1.1.1 + license: + name: MIT + url: http://opensource.org/licenses/MIT +servers: +- url: https://{host}/api/v1 + description: ACE platform API server + variables: + host: + default: appscode.com + description: Deployment host +- url: https://{host}/marketplace/api/v1 + description: Marketplace webhook service (separate listener) + variables: + host: + default: appscode.com + description: Deployment host +security: +- AuthorizationHeaderToken: [] +- Token: [] +- AccessToken: [] +tags: +- name: Identity - Users & Settings +- name: Identity - Organizations & Teams +- name: Administration +- name: Authorization +- name: Cluster Management v1 +- name: Kubernetes Proxy +- name: Helm +- name: Cluster Management v2 +- name: Multi-cluster (OCM) +- name: Client Organizations +- name: Cloud Providers +- name: ACE Installer +- name: ACE Upgrade +- name: Licensing & Contracts +- name: Billing Dashboard +- name: Marketplace +- name: Monitoring & Telemetry +- name: Rancher +- name: Chart Repositories +- name: Miscellaneous +paths: + /users/search: + get: + tags: + - Identity - Users & Settings + summary: Search for users + operationId: users_Search + security: [] + parameters: + - name: q + in: query + required: false + description: Keyword to search for. + schema: + type: string + - name: uid + in: query + required: false + description: ID of the user to search for. + schema: + type: integer + format: int64 + - name: limit + in: query + required: false + description: Maximum number of users to return. + schema: + type: integer + responses: + '200': + description: Search results wrapper with an `ok` flag and a `data` list of users. + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + data: + type: array + items: + $ref: '#/components/schemas/User' + /users/{username}: + get: + tags: + - Identity - Users & Settings + summary: Get a user by username + operationId: users_GetInfo + security: [] + parameters: + - $ref: '#/components/parameters/usernameParam' + responses: + '200': + description: The requested user. + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '404': + $ref: '#/components/responses/NotFound' + /users/{username}/tokens: + get: + tags: + - Identity - Users & Settings + summary: List a user's access tokens + operationId: users_ListAccessTokens + description: Requires basic authentication. Tokens are always for the authenticated user. + security: + - BasicAuth: [] + parameters: + - $ref: '#/components/parameters/usernameParam' + responses: + '200': + description: List of access tokens. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AccessToken' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Create an access token for a user + operationId: users_CreateAccessToken + description: Requires basic authentication. Creates a token for the authenticated user. + security: + - BasicAuth: [] + parameters: + - $ref: '#/components/parameters/usernameParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateAccessTokenOption' + responses: + '201': + description: The created access token (includes the plaintext token value). + content: + application/json: + schema: + $ref: '#/components/schemas/AccessToken' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /users/{username}/tokens/{id}: + delete: + tags: + - Identity - Users & Settings + summary: Delete a user's access token + operationId: users_DeleteAccessToken + description: Requires basic authentication. Deletes a token of the authenticated user. + security: + - BasicAuth: [] + parameters: + - $ref: '#/components/parameters/usernameParam' + - name: id + in: path + required: true + description: ID of the access token to delete. + schema: + type: integer + format: int64 + responses: + '204': + description: Access token deleted. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /users/{username}/followers: + get: + tags: + - Identity - Users & Settings + summary: List a user's followers + operationId: users_ListFollowers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/usernameParam' + - $ref: '#/components/parameters/pageParam' + responses: + '200': + description: List of followers. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /users/{username}/following: + get: + tags: + - Identity - Users & Settings + summary: List the users a given user is following + operationId: users_ListFollowing + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/usernameParam' + - $ref: '#/components/parameters/pageParam' + responses: + '200': + description: List of followed users. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /users/{username}/following/{target}: + get: + tags: + - Identity - Users & Settings + summary: Check if one user follows another + operationId: users_CheckFollowing + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/usernameParam' + - name: target + in: path + required: true + description: Username of the possibly-followed user. + schema: + type: string + responses: + '204': + description: The follower is following the target user. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /users/{username}/orgs: + get: + tags: + - Identity - Users & Settings + summary: List a user's organizations + operationId: users_ListUserOrgs + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/usernameParam' + responses: + '200': + description: List of organizations the user belongs to. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Organization' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /user/signin: + post: + tags: + - Identity - Users & Settings + summary: Sign in with username and password + operationId: users_SignIn + description: 'Public sign-in endpoint. On success sets session/CSRF/NATS cookies and returns 200 + with no body. Users enrolled in 2FA cannot sign in through this endpoint (405). + + ' + security: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SignInParams' + responses: + '200': + description: Signed in successfully (session cookies set). + '404': + description: User does not exist. + '405': + description: Login prohibited, user inactive, or 2FA enabled. + '409': + description: Email already in use. + '422': + $ref: '#/components/responses/ValidationError' + /user: + get: + tags: + - Identity - Users & Settings + summary: Get the authenticated user + operationId: users_GetAuthenticatedUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: check_client_org + in: query + required: false + description: When "true", populate the clientOrgUser field on the response. + schema: + type: string + responses: + '200': + description: The authenticated user. + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/firebase-token: + get: + tags: + - Identity - Users & Settings + summary: Get a Firebase custom token for the authenticated user + operationId: users_GetFirebaseToken + description: Only registered when the deployment is AppsCode-hosted. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Firebase custom token. + content: + application/json: + schema: + $ref: '#/components/schemas/FirebaseToken' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/nats/credentials: + get: + tags: + - Identity - Users & Settings + summary: Get the authenticated user's NATS credentials + operationId: users_GetNatsCredentials + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: NATS endpoints and credential bytes for the primary NATS user. + content: + application/json: + schema: + $ref: '#/components/schemas/NatsCredentialsResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/nats/admin_credentials: + get: + tags: + - Identity - Users & Settings + summary: Get NATS admin credentials + operationId: users_GetNatsAdminCredentials + description: Requires site-admin. Response body is deployment-specific; modeled as an opaque object. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: NATS admin credentials (opaque object). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/nats/user_credentials: + get: + tags: + - Identity - Users & Settings + summary: Get NATS user credentials + operationId: users_GetNatsUserCredentials + description: Requires site-admin. Response body is deployment-specific; modeled as an opaque object. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: NATS user credentials (opaque object). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/nats/cluster-resource-history: + get: + tags: + - Identity - Users & Settings + summary: Get cluster resource history from NATS + operationId: users_GetClusterResourceHistoryFromNats + description: Requires site-admin. Response body is deployment-specific; modeled as an opaque object. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Cluster resource history (opaque object). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/signout: + get: + tags: + - Identity - Users & Settings + summary: Sign out the authenticated user + operationId: users_SignOut + description: Clears session and auth cookies. Returns 200 with no body. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Signed out (cookies cleared). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/emails: + get: + tags: + - Identity - Users & Settings + summary: List the authenticated user's email addresses + operationId: users_ListEmails + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of email addresses. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Email' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Add email addresses + operationId: users_AddEmail + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateEmailOption' + responses: + '201': + description: The updated list of email addresses. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Email' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + delete: + tags: + - Identity - Users & Settings + summary: Delete email addresses + operationId: users_DeleteEmail + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/DeleteEmailOption' + responses: + '204': + description: Email addresses deleted. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/followers: + get: + tags: + - Identity - Users & Settings + summary: List the authenticated user's followers + operationId: users_ListMyFollowers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/pageParam' + responses: + '200': + description: List of followers. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/following: + get: + tags: + - Identity - Users & Settings + summary: List the users the authenticated user is following + operationId: users_ListMyFollowing + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/pageParam' + responses: + '200': + description: List of followed users. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/following/{username}: + get: + tags: + - Identity - Users & Settings + summary: Check whether the authenticated user follows a user + operationId: users_CheckMyFollowing + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/usernameParam' + responses: + '204': + description: The authenticated user is following this user. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + put: + tags: + - Identity - Users & Settings + summary: Follow a user + operationId: users_Follow + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/usernameParam' + responses: + '204': + description: User followed. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + delete: + tags: + - Identity - Users & Settings + summary: Unfollow a user + operationId: users_Unfollow + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/usernameParam' + responses: + '204': + description: User unfollowed. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /user/clusters: + get: + tags: + - Identity - Users & Settings + summary: List clusters the authenticated user owns or can access + operationId: users_ListUserClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: all + in: query + required: false + description: When "true", include clusters the user has access to (not just owned). + schema: + type: string + responses: + '200': + description: List of clusters. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/validate/username: + post: + tags: + - Identity - Users & Settings + summary: Validate username availability + operationId: users_ValidateUserName + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: user_name + in: query + required: false + description: Username to validate. + schema: + type: string + responses: + '200': + description: Validation result. + content: + application/json: + schema: + $ref: '#/components/schemas/Validation' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/validate/orgname: + post: + tags: + - Identity - Users & Settings + summary: Validate organization name availability + operationId: users_ValidateOrgName + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: org + in: query + required: false + description: Existing organization name (when renaming). + schema: + type: string + - name: user_name + in: query + required: false + description: Proposed organization name to validate. + schema: + type: string + responses: + '200': + description: Validation result. + content: + application/json: + schema: + $ref: '#/components/schemas/Validation' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/validate/email: + post: + tags: + - Identity - Users & Settings + summary: Validate email availability + operationId: users_ValidateEmail + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: email + in: query + required: false + description: Email address to validate. + schema: + type: string + responses: + '200': + description: Validation result. + content: + application/json: + schema: + $ref: '#/components/schemas/Validation' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/teams: + get: + tags: + - Identity - Users & Settings + summary: List all teams the authenticated user belongs to + operationId: users_ListUserTeams + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of teams. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Team' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/credentials: + get: + tags: + - Identity - Users & Settings + summary: List the authenticated user's cloud credentials + operationId: users_ListUserCloudCredentials + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: credential_type + in: query + required: false + description: Filter by one or more credential types. + schema: + type: array + items: + type: string + - name: rancher_endpoint + in: query + required: false + description: For Rancher credentials, only return those matching this endpoint. + schema: + type: string + responses: + '200': + description: List of cloud credentials. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/CloudCredentialApiForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Create a cloud credential for the authenticated user + operationId: users_CreateUserCloudCredential + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + description: cloudv1alpha1.CredentialSpec (Kubernetes-style object). + responses: + '201': + description: Cloud credential created (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + put: + tags: + - Identity - Users & Settings + summary: Update a cloud credential for the authenticated user + operationId: users_UpdateCloudCredentials + description: Registered at path "/user/credentials/" (trailing slash). + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + description: cloudv1alpha1.CredentialSpec (Kubernetes-style object). + responses: + '204': + description: Cloud credential updated (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/credentials/{credName}: + get: + tags: + - Identity - Users & Settings + summary: Get a cloud credential by name + operationId: users_GetUserCloudCredential + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: credName + in: path + required: true + description: Name of the cloud credential. + schema: + type: string + responses: + '200': + description: The requested cloud credential. + content: + application/json: + schema: + $ref: '#/components/schemas/CloudCredentialApiForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + delete: + tags: + - Identity - Users & Settings + summary: Delete a cloud credential by name + operationId: users_DeleteCloudCredential + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: credName + in: path + required: true + description: Name of the cloud credential. + schema: + type: string + responses: + '204': + description: Cloud credential deleted (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /user/clouds/{cloud}/buckets: + get: + tags: + - Identity - Users & Settings + summary: List storage buckets for a cloud + operationId: users_ListBuckets + description: 'Bound to a JSON body (BucketListOptions) despite being a GET. Either a cloud credential + or a secret namespace + name must be provided, plus a cluster UID. + + ' + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: cloud + in: path + required: true + description: Cloud provider identifier. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BucketListOptions' + responses: + '200': + description: List of bucket names. + content: + application/json: + schema: + $ref: '#/components/schemas/BucketListResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/profile: + get: + tags: + - Identity - Users & Settings + summary: Get the authenticated user's profile + operationId: users_GetUserProfile + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: The user profile. + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Update the authenticated user's profile + operationId: users_UpdateUserProfile + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + responses: + '200': + description: The updated profile. + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/avatar: + get: + tags: + - Identity - Users & Settings + summary: Get the authenticated user's avatar settings + operationId: users_GetUserAvatar + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: The avatar settings. + content: + application/json: + schema: + $ref: '#/components/schemas/AvatarParams' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Update the authenticated user's avatar + operationId: users_UpdateUserAvatar + description: Accepts multipart/form-data (AvatarParams). + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/AvatarParams' + responses: + '200': + description: Avatar updated (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/avatar/delete: + post: + tags: + - Identity - Users & Settings + summary: Delete the authenticated user's avatar + operationId: users_DeleteUserAvatar + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Avatar deleted (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/account/password: + post: + tags: + - Identity - Users & Settings + summary: Update the authenticated user's password + operationId: users_UpdatePassword + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdatePasswordParams' + responses: + '200': + description: Password updated (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/account/email: + get: + tags: + - Identity - Users & Settings + summary: Get the authenticated user's email addresses + operationId: users_GetEmailAddresses + description: Returns the raw models.EmailAddress records (modeled as an opaque object). + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of email address records. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Add or make primary an email address + operationId: users_UpdateEmail + description: 'With query "_method=PRIMARY" and "id", makes an existing email primary. Otherwise + adds the email in the body. Returns 200 (with or without a string body). + + ' + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: _method + in: query + required: false + description: Set to "PRIMARY" to mark an existing email as primary. + schema: + type: string + - name: id + in: query + required: false + description: Email address ID (used with _method=PRIMARY). + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AddEmailParams' + responses: + '200': + description: Email added or made primary. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/account/email/delete: + post: + tags: + - Identity - Users & Settings + summary: Delete an email address + operationId: users_DeleteEmailSetting + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: query + required: false + description: ID of the email address to delete. + schema: + type: integer + format: int64 + responses: + '200': + description: Email address deleted (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/account/delete: + post: + tags: + - Identity - Users & Settings + summary: Delete the authenticated user's account + operationId: users_DeleteAccount + description: Requires the current password (query param "password"). Signs the user out on success. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: password + in: query + required: false + description: Current password for confirmation. + schema: + type: string + responses: + '200': + description: Account deleted and user signed out. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/pagination: + get: + tags: + - Identity - Users & Settings + summary: Get the authenticated user's pagination settings + operationId: users_GetUserPagination + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: The user's pagination settings. + content: + application/json: + schema: + $ref: '#/components/schemas/Pagination' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Update the authenticated user's pagination settings + operationId: users_UpdateUserPagination + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Pagination' + responses: + '200': + description: The updated pagination settings. + content: + application/json: + schema: + $ref: '#/components/schemas/Pagination' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/security/: + get: + tags: + - Identity - Users & Settings + summary: Get two-factor authentication status + operationId: users_GetTwoFactorStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Two-factor enrollment status. + content: + application/json: + schema: + $ref: '#/components/schemas/TwoFAStatus' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/security/twofa/enroll: + get: + tags: + - Identity - Users & Settings + summary: Begin two-factor enrollment (generate secret and QR) + operationId: users_EnrollTwoFactor + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: TOTP secret and QR image URL. + content: + application/json: + schema: + $ref: '#/components/schemas/Security' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Complete two-factor enrollment + operationId: users_EnrollTwoFactorPost + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TwoFactorAuthParams' + responses: + '200': + description: Scratch token string. + content: + application/json: + schema: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/security/twofa/regenerate_scratch: + post: + tags: + - Identity - Users & Settings + summary: Regenerate the two-factor scratch token + operationId: users_RegenerateScratchToken + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: New scratch token string. + content: + application/json: + schema: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/security/twofa/disable: + post: + tags: + - Identity - Users & Settings + summary: Disable two-factor authentication + operationId: users_DisableTwoFactor + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Two-factor authentication disabled (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/security/webauthn/keys: + get: + tags: + - Identity - Users & Settings + summary: List WebAuthn security keys + operationId: users_GetWebauthnSecurityKeys + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of WebAuthn security keys. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/WebAuthnSecurityKeys' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/security/webauthn/request_register: + post: + tags: + - Identity - Users & Settings + summary: Begin WebAuthn registration + operationId: users_WebAuthnRegister + description: Returns the WebAuthn credential creation options (opaque, protocol-defined object). + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/WebauthnRegistrationOptions' + responses: + '200': + description: WebAuthn credential creation options. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/security/webauthn/register: + post: + tags: + - Identity - Users & Settings + summary: Complete WebAuthn registration + operationId: users_WebauthnRegisterPost + description: Reads the security key response from the request. Returns the created credential (opaque + object). + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '201': + description: WebAuthn credential created (opaque object). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/security/webauthn/keys/{id}: + delete: + tags: + - Identity - Users & Settings + summary: Delete a WebAuthn security key + operationId: users_WebauthnDelete + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + description: ID of the WebAuthn security key. + schema: + type: integer + format: int64 + responses: + '200': + description: WebAuthn security key deleted (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /user/settings/security/sessions/: + get: + tags: + - Identity - Users & Settings + summary: List the authenticated user's active sessions + operationId: users_ListUserSessions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of sessions. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SessionInfoAPIForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/security/sessions/{sid}/revoke: + delete: + tags: + - Identity - Users & Settings + summary: Revoke a session + operationId: users_RevokeUserSession + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: sid + in: path + required: true + description: Session ID to revoke. + schema: + type: string + responses: + '200': + description: The remaining list of sessions. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SessionInfoAPIForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /user/settings/security/account_link: + get: + tags: + - Identity - Users & Settings + summary: List linked external accounts + operationId: users_GetAccountLinks + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of linked accounts. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AccountLink' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Delete a linked external account + operationId: users_DeleteAccountLink + description: Despite the POST verb, this removes an account link. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AccountLinkParams' + responses: + '200': + description: Account link removed (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/organizations: + get: + tags: + - Identity - Users & Settings + summary: List the authenticated user's organizations + operationId: users_ListOrganizations + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of organizations. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Organization' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/organizations/create: + get: + tags: + - Identity - Users & Settings + summary: Check if the authenticated user can create organizations + operationId: users_CreateOrganizationPermission + description: Returns 200 if allowed, 403 if not. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: User can create organizations. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Create an organization + operationId: users_CreateOrganization + description: Accepts multipart/form-data (CreateOrgParams). + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/CreateOrgParams' + responses: + '200': + description: Organization created; optional message about Rancher sync. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponseMessage' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/tokens/access-tokens/: + get: + tags: + - Identity - Users & Settings + summary: List the authenticated user's access tokens (settings) + operationId: users_SettingsListAccessTokens + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of access tokens. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SettingsAccessToken' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Create a new access token (settings) + operationId: users_CreateNewAccessToken + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NewAccessTokenParam' + responses: + '201': + description: The created access token (includes the plaintext token value). + content: + application/json: + schema: + $ref: '#/components/schemas/SettingsAccessToken' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/tokens/access-tokens/delete-records: + post: + tags: + - Identity - Users & Settings + summary: Delete multiple access tokens + operationId: users_DeleteMultipleAccessTokens + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AccessTokenIdList' + responses: + '200': + description: Result message describing how many records were deleted. + content: + application/json: + schema: + type: object + properties: + message: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/tokens/access-tokens/{id}: + delete: + tags: + - Identity - Users & Settings + summary: Delete an access token (settings) + operationId: users_SettingsDeleteAccessToken + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + description: ID of the access token to delete. + schema: + type: integer + format: int64 + responses: + '200': + description: Access token deleted (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /user/settings/tokens/nats-tokens/: + get: + tags: + - Identity - Users & Settings + summary: List the authenticated user's NATS user-type tokens + operationId: users_ListNatsUserTypeTokens + description: Returns NATS user-type token accounts (modeled as an opaque object list). + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of NATS user-type token accounts. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/tokens/nats-tokens/{id}/revoke/: + post: + tags: + - Identity - Users & Settings + summary: Revoke a NATS user-type token + operationId: users_RevokeNatsUserTypeToken + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + description: ID of the NATS token to revoke. + schema: + type: integer + format: int64 + responses: + '200': + description: NATS token revoked (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /user/settings/applications/oauth2: + get: + tags: + - Identity - Users & Settings + summary: List the authenticated user's OAuth2 applications + operationId: users_ListOAuth2Applications + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of OAuth2 applications. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2Application' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + post: + tags: + - Identity - Users & Settings + summary: Create an OAuth2 application + operationId: users_CreateOAuth2Application + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2ApplicationParams' + responses: + '200': + description: The created OAuth2 application (includes the client secret). + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Application' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/settings/applications/oauth2/{id}: + get: + tags: + - Identity - Users & Settings + summary: Get an OAuth2 application + operationId: users_GetOAuth2Application + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + description: ID of the OAuth2 application. + schema: + type: integer + format: int64 + responses: + '200': + description: The OAuth2 application. + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Application' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + put: + tags: + - Identity - Users & Settings + summary: Update an OAuth2 application + operationId: users_UpdateOAuth2Application + description: Accepts multipart/form-data (OAuth2ApplicationParams). + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + description: ID of the OAuth2 application. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/OAuth2ApplicationParams' + responses: + '200': + description: The updated OAuth2 application. + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Application' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '422': + $ref: '#/components/responses/ValidationError' + delete: + tags: + - Identity - Users & Settings + summary: Delete an OAuth2 application + operationId: users_DeleteOAuth2Application + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + description: ID of the OAuth2 application. + schema: + type: integer + format: int64 + responses: + '200': + description: OAuth2 application deleted (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /user/settings/applications/oauth2/{id}/regenerate_secret: + post: + tags: + - Identity - Users & Settings + summary: Regenerate an OAuth2 application's client secret + operationId: users_OAuth2ApplicationRegenerateSecret + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + description: ID of the OAuth2 application. + schema: + type: integer + format: int64 + responses: + '200': + description: The new client secret string. + content: + application/json: + schema: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /user/settings/applications/oauth2/{id}/revoke: + post: + tags: + - Identity - Users & Settings + summary: Revoke an OAuth2 grant + operationId: users_RevokeOAuth2Grant + description: The path {id} is the OAuth2 grant ID. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + description: ID of the OAuth2 grant to revoke. + schema: + type: integer + format: int64 + responses: + '200': + description: OAuth2 grant revoked (no body). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/settings/applications/oauth2/grants: + get: + tags: + - Identity - Users & Settings + summary: List the authenticated user's OAuth2 grants + operationId: users_ListOAuth2Grants + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of OAuth2 grants. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2Grant' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /orgs: + post: + tags: + - Identity - Organizations & Teams + summary: Create an organization + description: Creates a new organization owned by the authenticated user. The user must be permitted + to create organizations (CanCreateOrganization), otherwise 403 is returned. + operationId: orgs_CreateOrg + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateOrgOption' + responses: + '201': + description: Organization created + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '422': + $ref: '#/components/responses/validationError' + /orgs/claim/{claimID}: + patch: + tags: + - Identity - Organizations & Teams + summary: Claim a standalone organization + description: Claims a previously created standalone organization identified by claimID and assigns + ownership to the authenticated user. Only registered when the deployment is AppsCode-hosted (setting.AppsCodeHosted). + operationId: orgs_ClaimStandaloneOrg + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: claimID + in: path + required: true + description: Claim identifier of the standalone organization + schema: + type: string + responses: + '200': + description: Organization claimed. Returns the claimed organization (models.User.APIFormat, + dynamic payload). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + '409': + description: Organization already claimed + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /orgs/claim/: + get: + tags: + - Identity - Organizations & Teams + summary: Get the oldest claimable standalone organization claim ID + description: Returns the claim ID of the oldest claimable standalone organization, by proxying an + eligibility check to the central marketplace server. Only registered for marketplace deployments + or in dev run mode, and requires site-admin (reqSiteAdmin). + operationId: orgs_GetStandAloneOrgClaimId + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Claimable check result + content: + application/json: + schema: + $ref: '#/components/schemas/OrgClaimableCheckResp' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + /orgs/{orgname}/user/{username}: + get: + tags: + - Identity - Organizations & Teams + summary: Check whether a user exists (in the org context) + description: Looks up a user by username and returns their profile if the user exists and is active. + Returns 400 if the user does not exist or is inactive. + operationId: orgs_CheckUserExists + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + - $ref: '#/components/parameters/usernameParam' + responses: + '200': + description: User profile + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + '400': + description: User does not exist or is inactive + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + /orgs/{orgname}/is-owner: + get: + tags: + - Identity - Organizations & Teams + summary: Check if the current user is the organization owner + description: Returns 200 if the authenticated user is an owner of the organization. Ownership is + enforced by upstream middleware. + operationId: orgs_IsOwner + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: Current user is the organization owner + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + /orgs/{orgname}: + get: + tags: + - Identity - Organizations & Teams + summary: Get an organization + description: Returns the organization if it is visible to the requesting user. + operationId: orgs_GetOrg + security: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: Organization + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + '404': + $ref: '#/components/responses/notFound' + patch: + tags: + - Identity - Organizations & Teams + summary: Edit an organization + description: Updates the organization's profile fields. Requires a token and org-edit authorization + (Organization_CanEditOrg / edit:org). + operationId: orgs_EditOrg + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/EditOrgOption' + responses: + '200': + description: Updated organization + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + '422': + $ref: '#/components/responses/validationError' + delete: + tags: + - Identity - Organizations & Teams + summary: Delete an organization + description: Deletes the organization. Requires a token and delete authorization (Organization_CanDeleteOrg + / delete:org); the requester must be the last admin per the orgLastAdmin condition. + operationId: orgs_DeleteOrg + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '204': + description: Organization deleted + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + /orgs/{orgname}/avatar/: + get: + tags: + - Identity - Organizations & Teams + summary: Get the organization avatar + description: Returns the organization's avatar URL. Requires viewer authorization (Organization_Viewer + / view:avatar). + operationId: orgs_GetAvatar + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: Avatar URL (string) + content: + application/json: + schema: + type: string + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + post: + tags: + - Identity - Organizations & Teams + summary: Update the organization avatar + description: Uploads or sets the organization avatar via multipart form. Requires editor authorization + (Organization_Editor / update:avatar). + operationId: orgs_UpdateAvatar + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/AvatarParams' + responses: + '200': + description: Avatar updated (response body depends on avatar handler). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '422': + $ref: '#/components/responses/validationError' + /orgs/{orgname}/avatar/delete: + post: + tags: + - Identity - Organizations & Teams + summary: Delete the organization avatar + description: Removes the organization's avatar. Requires editor authorization (Organization_Editor + / delete:avatar). + operationId: orgs_DeleteAvatar + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: Avatar deleted + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + /orgs/{orgname}/members: + get: + tags: + - Identity - Organizations & Teams + summary: List an organization's members + description: Lists organization members. Non-members (and unauthenticated callers) see only public + members. + operationId: orgs_ListMembers + security: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: List of members + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + /orgs/{orgname}/members/action/{action}: + post: + tags: + - Identity - Organizations & Teams + summary: Perform a membership action + description: Performs a membership action (private, public, remove, leave) for a member identified + by the uid query parameter. Requires a token and org membership. + operationId: orgs_MemberAction + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + - name: action + in: path + required: true + description: Membership action to perform + schema: + type: string + enum: + - private + - public + - remove + - leave + - name: uid + in: query + required: true + description: User ID of the member the action applies to + schema: + type: integer + format: int64 + responses: + '200': + description: Action performed + '400': + description: uid missing or invalid + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + /orgs/{orgname}/members/{username}: + get: + tags: + - Identity - Organizations & Teams + summary: Check if a user is a member of an organization + description: Returns 204 if the user is a member, 404 if not. May redirect (302) to the public-members + endpoint for non-members of the org. + operationId: orgs_IsMember + security: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + - $ref: '#/components/parameters/usernameParam' + responses: + '204': + description: User is a member + '302': + description: Redirect to the public-members check + '404': + description: User is not a member + delete: + tags: + - Identity - Organizations & Teams + summary: Remove a member from an organization + description: Removes a member from the organization. Requires a token and org ownership plus remove-member + authorization (Organization_CanRemoveMember / admin:org, orgLastMember condition). Site admins + cannot be removed from the administrative org. + operationId: orgs_DeleteMember + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + - $ref: '#/components/parameters/usernameParam' + responses: + '204': + description: Member removed + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + /orgs/{orgname}/public_members: + get: + tags: + - Identity - Organizations & Teams + summary: List an organization's public members + operationId: orgs_ListPublicMembers + security: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: List of public members + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + /orgs/{orgname}/public_members/{username}: + get: + tags: + - Identity - Organizations & Teams + summary: Check if a user is a public member of an organization + operationId: orgs_IsPublicMember + security: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + - $ref: '#/components/parameters/usernameParam' + responses: + '204': + description: User is a public member + '404': + description: User is not a public member + put: + tags: + - Identity - Organizations & Teams + summary: Publicize a user's membership + description: Makes the caller's own organization membership public. Requires a token and org membership; + a user cannot publicize another member (403). + operationId: orgs_PublicizeMember + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + - $ref: '#/components/parameters/usernameParam' + responses: + '204': + description: Membership publicized + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + delete: + tags: + - Identity - Organizations & Teams + summary: Conceal a user's membership + description: Makes the caller's own organization membership private. Requires a token and org membership; + a user cannot conceal another member (403). + operationId: orgs_ConcealMember + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + - $ref: '#/components/parameters/usernameParam' + responses: + '204': + description: Membership concealed + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + /orgs/{orgname}/teams: + get: + tags: + - Identity - Organizations & Teams + summary: List an organization's teams + description: Lists the teams of the organization. Requires a token, org membership, and viewer authorization + (Organization_Viewer / list:team). + operationId: orgs_ListTeams + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: List of teams + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Team' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + post: + tags: + - Identity - Organizations & Teams + summary: Create a team + description: Creates a team in the organization. Requires a token, org membership, and team-editor + authorization (create:team). + operationId: orgs_CreateTeam + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateTeamOption' + responses: + '201': + description: Team created + content: + application/json: + schema: + $ref: '#/components/schemas/Team' + '400': + description: Invalid team type or too many assigned roles + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '422': + $ref: '#/components/responses/validationError' + /orgs/{orgname}/teams/{teamid}/action/{action}: + post: + tags: + - Identity - Organizations & Teams + summary: Perform a team action + description: Performs a team action (join, leave, remove, add) for the user identified by the uid + query parameter (or uname for add). Requires a token, org membership, and team-member authorization + (Team_Member / ctx.param.action:team). + operationId: orgs_TeamAction + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + - name: teamid + in: path + required: true + description: ID of the team + schema: + type: integer + format: int64 + - name: action + in: path + required: true + description: Team action to perform + schema: + type: string + enum: + - join + - leave + - remove + - add + - name: uid + in: query + required: true + description: User ID the action applies to + schema: + type: integer + format: int64 + - name: uname + in: query + required: false + description: Username to add (used with the add action) + schema: + type: string + responses: + '200': + description: Action performed + '400': + description: uid missing or user is an organization + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + '409': + description: User already a member of the team + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /orgs/{orgname}/rancher/sync-token: + get: + tags: + - Identity - Organizations & Teams + summary: Get the Rancher organization sync token + description: Returns the organization's Rancher synchronization token. Requires a token and viewer + authorization (Organization_Viewer / view:sync-token). + operationId: orgs_GetRancherOrgSyncToken + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: Rancher sync token + content: + application/json: + schema: + $ref: '#/components/schemas/RancherAPIToken' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + delete: + tags: + - Identity - Organizations & Teams + summary: Remove the Rancher organization sync token + description: Deletes the organization's Rancher synchronization token. Requires a token and editor + authorization (Organization_Editor / remove:rancher-sync-token). + operationId: orgs_RemoveRancherOrgSyncToken + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: Token removed + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + post: + tags: + - Identity - Organizations & Teams + summary: Create a Rancher organization sync token + description: Creates a Rancher organization synchronization token from the provided access key. + The organization must be of Rancher origin. Requires a token and editor authorization (Organization_Editor + / create:rancher-org-sync-token). + operationId: orgs_CreateRancherOrgSyncToken + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AccessToken' + responses: + '200': + description: Token created + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponseMessage' + '400': + description: Organization origin is not Rancher + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '422': + $ref: '#/components/responses/validationError' + /orgs/{orgname}/rancher/user-token: + get: + tags: + - Identity - Organizations & Teams + summary: Get the Rancher user token (deprecated) + description: Deprecated. Returns the caller's Rancher API token for the organization. Requires a + token, org membership, and viewer authorization (Organization_Viewer / view:sync-token). + operationId: orgs_GetRancherToken + deprecated: true + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: Rancher API token + content: + application/json: + schema: + $ref: '#/components/schemas/RancherAPIToken' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + delete: + tags: + - Identity - Organizations & Teams + summary: Remove the Rancher user token (deprecated) + description: Deprecated. Deletes the caller's Rancher API token for the organization. Requires a + token, org membership, and editor authorization (Organization_Editor / remove:rancher-sync-token). + operationId: orgs_RemoveRancherToken + deprecated: true + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: Token removed + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + post: + tags: + - Identity - Organizations & Teams + summary: Add a Rancher user token (deprecated) + description: Deprecated. Stores a Rancher API token for the caller in the organization. Requires + a token, org membership, and editor authorization (Organization_Editor / create:rancher-org-sync-token). + operationId: orgs_AddRancherToken + deprecated: true + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AccessToken' + responses: + '200': + description: Token added + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '422': + $ref: '#/components/responses/validationError' + /orgs/{orgname}/tokens/access-tokens/: + get: + tags: + - Identity - Organizations & Teams + summary: List the organization's access tokens + description: Lists access tokens of the organization's system admin. Requires org membership and + viewer authorization (Organization_Viewer / list:access-token). + operationId: orgs_ListAccessTokens + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: List of access tokens + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AccessTokenInfo' + '400': + description: Organization system admin does not exist + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + /orgs/{orgname}/tokens/access-tokens/{id}: + delete: + tags: + - Identity - Organizations & Teams + summary: Delete an organization access token + description: Deletes an access token of the organization's system admin. Requires org membership + and editor authorization (Organization_Editor / delete:access-token). + operationId: orgs_DeleteAccessToken + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + - name: id + in: path + required: true + description: ID of the access token + schema: + type: integer + format: int64 + responses: + '200': + description: Access token deleted + '400': + description: Organization system admin does not exist + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + /orgs/{orgname}/tokens/nats-tokens/: + get: + tags: + - Identity - Organizations & Teams + summary: List the organization's NATS user-type tokens + description: Lists NATS user-type tokens of the organization's system admin. Requires org membership + and viewer authorization (Organization_Viewer / list:nats-token). + operationId: orgs_ListNatsUserTypeTokens + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: List of NATS accounts + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/NatsAccount' + '400': + description: Organization system admin does not exist + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + /orgs/{orgname}/tokens/nats-tokens/{id}/revoke: + post: + tags: + - Identity - Organizations & Teams + summary: Revoke a NATS user-type token + description: Revokes a NATS user-type token of the organization's system admin. Requires org membership + and editor authorization (Organization_Editor / revoke:nats-token). + operationId: orgs_RevokeNatsUserTypeToken + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + - name: id + in: path + required: true + description: ID of the NATS token + schema: + type: integer + format: int64 + responses: + '200': + description: Token revoked + '400': + description: Organization system admin missing or NATS user not found + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + /teams/{teamid}: + get: + tags: + - Identity - Organizations & Teams + summary: Get a team + description: Returns a team by ID. Requires a token and view authorization (Team_CanView / view:team). + operationId: orgs_GetTeam + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: teamid + in: path + required: true + description: ID of the team + schema: + type: integer + format: int64 + responses: + '200': + description: Team + content: + application/json: + schema: + $ref: '#/components/schemas/Team' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + patch: + tags: + - Identity - Organizations & Teams + summary: Edit a team + description: Updates a team. Requires a token and edit authorization (Team_CanEdit / edit:team). + Owner-team permission cannot be changed. + operationId: orgs_EditTeam + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: teamid + in: path + required: true + description: ID of the team + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/EditTeamOption' + responses: + '200': + description: Updated team + content: + application/json: + schema: + $ref: '#/components/schemas/Team' + '400': + description: Invalid team type or team name + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + '422': + $ref: '#/components/responses/validationError' + delete: + tags: + - Identity - Organizations & Teams + summary: Delete a team + description: Deletes a team. Requires a token and delete authorization (Team_CanDelete / delete:team). + operationId: orgs_DeleteTeam + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: teamid + in: path + required: true + description: ID of the team + schema: + type: integer + format: int64 + responses: + '204': + description: Team deleted + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + /teams/{teamid}/members: + get: + tags: + - Identity - Organizations & Teams + summary: List a team's members + description: Lists the members of a team. Requires a token, org membership, and view authorization + (Team_CanView / list:team-members). + operationId: orgs_GetTeamMembers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: teamid + in: path + required: true + description: ID of the team + schema: + type: integer + format: int64 + responses: + '200': + description: List of team members + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + /teams/{teamid}/members/{username}: + get: + tags: + - Identity - Organizations & Teams + summary: Get a particular member of a team + description: Returns a specific team member. Requires a token and view authorization (Team_CanView + / view:team-member). + operationId: orgs_GetTeamMember + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: teamid + in: path + required: true + description: ID of the team + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/usernameParam' + responses: + '200': + description: Team member + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + put: + tags: + - Identity - Organizations & Teams + summary: Add a team member + description: Adds a user to the team. Requires a token and add authorization (Team_CanAddMember + / add:team-member). For the owner team, the autoConnectClusters query flag can trigger cluster + auto-connect. + operationId: orgs_AddTeamMember + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: teamid + in: path + required: true + description: ID of the team + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/usernameParam' + - name: autoConnectClusters + in: query + required: false + description: When adding to the owner team, auto-connect the user to org clusters + schema: + type: boolean + responses: + '204': + description: Member added + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + delete: + tags: + - Identity - Organizations & Teams + summary: Remove a team member + description: Removes a user from the team. Requires a token and remove authorization (Team_CanRemoveMember + / remove:team-member, ownerTeamLastMember condition). Site admins cannot be removed from the administrative + org. + operationId: orgs_RemoveTeamMember + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: teamid + in: path + required: true + description: ID of the team + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/usernameParam' + responses: + '204': + description: Member removed + '401': + $ref: '#/components/responses/unauthorized' + '403': + $ref: '#/components/responses/forbidden' + '404': + $ref: '#/components/responses/notFound' + /admin/orgs: + get: + tags: + - Administration + summary: List all organizations + description: Requires a valid token, an organization supplied via query, and the `admin_of_administrative_org` + authorization relation. + operationId: admin_GetAllOrgs + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of organizations + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Organization' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /admin/users: + get: + tags: + - Administration + summary: List all users + description: Requires a valid token, an organization supplied via query, and the `admin_of_administrative_org` + authorization relation. + operationId: admin_GetAllUsers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of users + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + post: + tags: + - Administration + summary: Create a user + description: Requires a valid token, an organization supplied via query, and the `admin_of_administrative_org` + authorization relation. + operationId: admin_CreateUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateUserOption' + responses: + '201': + description: Created user + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /admin/users/{username}: + patch: + tags: + - Administration + summary: Edit an existing user + description: Requires a valid token, an organization supplied via query, and the `admin_of_administrative_org` + authorization relation. + operationId: admin_EditUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/username' + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/EditUserOption' + responses: + '200': + description: Updated user + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: User not found + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Administration + summary: Delete a user + description: Requires a valid token, an organization supplied via query, and the `admin_of_administrative_org` + authorization relation. + operationId: admin_DeleteUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/username' + - $ref: '#/components/parameters/orgnameQuery' + responses: + '204': + description: User deleted + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: User not found + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /admin/users/{username}/update: + post: + tags: + - Administration + summary: Update a user's profile as admin + description: Requires a valid token, an organization supplied via query, and the `admin_of_administrative_org` + authorization relation. + operationId: admin_UpdateUserProfileByAdmin + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/username' + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + responses: + '200': + description: Updated profile + content: + application/json: + schema: + $ref: '#/components/schemas/Profile' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: User not found + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /admin/users/{username}/change-password: + post: + tags: + - Administration + summary: Change a user's password as admin + description: Requires a valid token, an organization supplied via query, and the `admin_of_administrative_org` + authorization relation. + operationId: admin_UpdateUserPassword + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/username' + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdatePasswordParams' + responses: + '200': + description: Password updated + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /admin/users/{username}/orgs: + get: + tags: + - Administration + summary: List a user's organizations + description: Requires a valid token, an organization supplied via query, and the `admin_of_administrative_org` + authorization relation. + operationId: admin_ListUserOrgs + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/username' + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of organizations for the user. Response shape is delegated to org.ListUserOrgs; + represented here generically. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + post: + tags: + - Administration + summary: Create an organization owned by a user + description: Requires a valid token, an organization supplied via query, and the `admin_of_administrative_org` + authorization relation. + operationId: admin_CreateOrg + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/username' + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateOrgOption' + responses: + '201': + description: Created organization + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: User not found + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /admin/users/{uid}: + get: + tags: + - Administration + summary: Get user information by user ID + description: Requires a valid token, an organization supplied via query, and the `admin_of_administrative_org` + authorization relation. + operationId: admin_GetInfoByUserId + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: User information + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: User not found + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin: + get: + tags: + - Administration + summary: Site administration dashboard + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `view_usage_analytics:site_admin` authorization relation. + operationId: admin_Dashboard + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: Dashboard payload. Returns an untyped map with `stats` and `sysStatus` keys; represented + generically. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/config: + get: + tags: + - Administration + summary: Site administration configuration page + description: Requires a valid token, an organization supplied via query, membership of that organization, + and site-admin privileges. Renders an HTML template rather than a JSON body. + operationId: admin_Config + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: HTML config page + content: + text/html: + schema: + type: string + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/config/test_mail: + post: + tags: + - Administration + summary: Send a test email + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `send_test_mails:site_admin` authorization relation. Redirects to the config page on completion. + operationId: admin_SendTestMail + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: email + in: query + required: false + schema: + type: string + - $ref: '#/components/parameters/orgnameQuery' + responses: + '302': + description: Redirect to the config page + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/monitor: + get: + tags: + - Administration + summary: Site administration monitor page + description: Requires a valid token, an organization supplied via query, membership of that organization, + and site-admin privileges. Renders an HTML template rather than a JSON body. + operationId: admin_Monitor + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: HTML monitor page + content: + text/html: + schema: + type: string + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/delete/inactive-users: + delete: + tags: + - Administration + summary: Purge deactivated users inactive for more than 30 days + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `purge_deactivated_users:site_admin` authorization relation. + operationId: admin_DeleteInActiveUsers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: Inactive users purged + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/users: + get: + tags: + - Administration + summary: List all users (site administration) + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `view_users:site_admin` authorization relation. + operationId: admin_Users + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of users. Returns raw models.User records; represented generically. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/users/deleted_accounts: + get: + tags: + - Administration + summary: List deactivated user accounts + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `view_deleted_members:site_admin` authorization relation. + operationId: admin_DeletedAccounts + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of deactivated users. Returns raw models.User records; represented generically. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/users/deleted_accounts/{id}/reactivate: + post: + tags: + - Administration + summary: Reactivate a deactivated user + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `reactivate_members:site_admin` authorization relation. + operationId: admin_ReactivateUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: User reactivated + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/users/new: + post: + tags: + - Administration + summary: Create a new user (site administration) + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `create_users:site_admin` authorization relation. + operationId: admin_NewUserPost + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AdminCreateUserPayload' + responses: + '201': + description: User created + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/users/{userid}: + post: + tags: + - Administration + summary: Edit a user (site administration) + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `update_users:site_admin` authorization relation. + operationId: admin_EditUserPost + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: userid + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AdminEditUserPayload' + responses: + '200': + description: User updated + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/users/{userid}/delete: + post: + tags: + - Administration + summary: Deactivate a user (site administration) + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `delete_users:site_admin` authorization relation. + operationId: admin_DeleteUserSiteAdmin + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: userid + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: User deactivated + '400': + description: User still owns organizations + content: + application/json: + schema: + type: object + properties: + message: + type: string + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/orgs: + get: + tags: + - Administration + summary: List all organizations (site administration) + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `view_orgs:site_admin` authorization relation. + operationId: admin_Organizations + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of organizations. Returns raw models.Organization records; represented generically. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/orgs/orphaned/: + get: + tags: + - Administration + summary: List orphaned organizations + description: Requires a valid token, an organization supplied via query, and membership of that + organization. + operationId: admin_GetAllOrphanedOrganizations + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of orphaned organizations + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Organization' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/orgs/orphaned/delete/{id}: + delete: + tags: + - Administration + summary: Delete an orphaned organization + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `delete:orphaned-org` authorization relation. + operationId: admin_DeleteOrganizations + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: Organization deleted + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/clusters: + get: + tags: + - Administration + summary: List all clusters (site administration) + description: Requires a valid token, an organization supplied via query, and membership of that + organization. + operationId: admin_Clusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of clusters. Returns raw models.ClusterInfo records; represented generically. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/auths: + get: + tags: + - Administration + summary: List authentication sources + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `site_admin_editor_authn_source` authorization relation. + operationId: admin_Authentications + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of login sources. Returns raw models.LoginSource records; represented generically. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/auths/auth-types: + get: + tags: + - Administration + summary: List available authentication source types + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `site_admin_editor_authn_source` authorization relation. + operationId: admin_AuthenticationsTypes + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of authentication source types (name/type pairs); represented generically. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/auths/new: + post: + tags: + - Administration + summary: Create an authentication source + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `site_admin_editor_authn_source` authorization relation. + operationId: admin_NewAuthSourcePost + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AuthenticationPayload' + responses: + '201': + description: Authentication source created + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/auths/{authid}: + get: + tags: + - Administration + summary: Get an authentication source + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `site_admin_editor_authn_source` authorization relation. + operationId: admin_GetAuthenticationSource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: authid + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: Login source. Returns a raw models.LoginSource record; represented generically. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + post: + tags: + - Administration + summary: Edit an authentication source + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `site_admin_editor_authn_source` authorization relation. + operationId: admin_EditAuthSourcePost + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: authid + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AuthenticationPayload' + responses: + '200': + description: Authentication source updated + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/auths/{authid}/delete: + post: + tags: + - Administration + summary: Delete an authentication source + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `site_admin_editor_authn_source` authorization relation. + operationId: admin_DeleteAuthSource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: authid + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: Authentication source deleted + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/external_oauth: + get: + tags: + - Administration + summary: List external OAuth2 authentication sources + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `site_admin_editor_external_authn_source` authorization relation. + operationId: admin_ExternalAuthentications + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of external OAuth2 applications. Returns raw models.ExternalOAuth2Application + records; represented generically. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/external_oauth/new: + post: + tags: + - Administration + summary: Create an external OAuth2 authentication source + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `site_admin_editor_external_authn_source` authorization relation. + operationId: admin_NewExternalAuthSourcePost + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalOAuth2AppPayload' + responses: + '201': + description: External OAuth2 source created + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/external_oauth/{provider}: + post: + tags: + - Administration + summary: Edit an external OAuth2 authentication source + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `site_admin_editor_external_authn_source` authorization relation. + operationId: admin_EditExternalAuthSourcePost + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: provider + in: path + required: true + schema: + type: string + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalOAuth2AppPayload' + responses: + '200': + description: External OAuth2 source updated + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /accounts/admin/external_oauth/{provider}/delete: + post: + tags: + - Administration + summary: Delete an external OAuth2 authentication source + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `site_admin_editor_external_authn_source` authorization relation. + operationId: admin_DeleteExternalAuthSource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: provider + in: path + required: true + schema: + type: string + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: External OAuth2 source deleted + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /branding: + get: + tags: + - Administration + summary: Get branding options + description: Public endpoint. Returns the current branding configuration. + operationId: admin_GetBrandingOptions + security: [] + responses: + '200': + description: Branding options + content: + application/json: + schema: + $ref: '#/components/schemas/BrandingResponse' + '304': + description: Not modified + post: + tags: + - Administration + summary: Set branding options + description: Requires a valid token, membership of the organization, and the `edit_branding_options:org` + authorization relation. + operationId: admin_SetBrandingOptions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BrandingOptions' + responses: + '200': + description: Branding options updated + '400': + description: Invalid branding option + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /allowed-domains: + get: + tags: + - Administration + summary: List allowed email domains + description: Public endpoint. Returns the configured email domain whitelist. + operationId: admin_GetAllowedEmailDomains + security: [] + responses: + '200': + description: List of allowed email domains + content: + application/json: + schema: + type: array + items: + type: string + post: + tags: + - Administration + summary: Add an email domain to the whitelist + description: Requires a valid token, an organization supplied via query, and the `edit_allowed_domains:site_admin` + authorization relation. + operationId: admin_AddNewEmailDomainIntoWhiteList + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/DomainOpts' + responses: + '200': + description: Domain added + '400': + description: Invalid domain name + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '409': + description: Domain already exists + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + patch: + tags: + - Administration + summary: Remove an email domain from the whitelist + description: Requires a valid token, an organization supplied via query, and the `edit_allowed_domains:site_admin` + authorization relation. + operationId: admin_DeleteEmailDomainFromWhiteList + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/DomainOpts' + responses: + '200': + description: Domain removed + '400': + description: Domain not found in whitelist + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /disable-registration: + get: + tags: + - Administration + summary: Get user registration status + description: Public endpoint. Returns whether user registration is disabled. + operationId: admin_GetUserRegistrationStatus + security: [] + responses: + '200': + description: Registration status + content: + application/json: + schema: + $ref: '#/components/schemas/RegistrationOpts' + post: + tags: + - Administration + summary: Update user registration status + description: Requires a valid token, an organization supplied via query, and the `update_user_registration:site_admin` + authorization relation. + operationId: admin_UpdateUserRegistrationStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RegistrationOpts' + responses: + '200': + description: Registration status updated + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /authz/objects/{objectType}/{objID}/allowed-permissions: + get: + tags: + - Authorization + summary: Get allowed permissions on an object + description: Requires a valid token and an organization supplied via query. Returns the requester's + allowed permissions on the identified object. + operationId: authz_GetAllowedPermissions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: objectType + in: path + required: true + schema: + type: string + - name: objID + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: Allowed permissions for the object + content: + application/json: + schema: + $ref: '#/components/schemas/AuthObjectAllowedPermissions' + '400': + description: Invalid object type or ID + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /authz/objects/allowed-permissions: + post: + tags: + - Authorization + summary: Batch get allowed permissions on objects + description: Requires a valid token and an organization supplied via query. Returns the requester's + allowed permissions for each supplied object identifier. + operationId: authz_GetBatchAllowedPermissions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AuthObjectIdentifier' + responses: + '200': + description: Allowed permissions for each object + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AuthObjectAllowedPermissions' + '400': + description: Invalid object type or ID + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /authz/roles/available_permissions: + get: + tags: + - Authorization + summary: List available permissions + description: Requires a valid token, an organization supplied via query, and membership of that + organization. Returns the set of permissions assignable in the caller's context. + operationId: authz_ListAvailablePermissions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: Available permissions. Returns an authzstores.VirtualPermissionsData structure; + represented generically. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /authz/roles: + get: + tags: + - Authorization + summary: List roles + description: Requires a valid token, an organization supplied via query, and membership of that + organization. + operationId: authz_ListRoles + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: List of roles + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/RoleResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + post: + tags: + - Authorization + summary: Create a role + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `create_role:org` authorization relation. + operationId: authz_CreateRole + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateRoleRequest' + responses: + '201': + description: Role created + content: + application/json: + schema: + $ref: '#/components/schemas/RoleResponse' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /authz/roles/{id}: + get: + tags: + - Authorization + summary: Get a role + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `view:role` authorization relation. + operationId: authz_GetRole + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: Role + content: + application/json: + schema: + $ref: '#/components/schemas/RoleResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Role not found + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + put: + tags: + - Authorization + summary: Update a role + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `edit:role` authorization relation. + operationId: authz_UpdateRole + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateRoleRequest' + responses: + '200': + description: Role updated + content: + application/json: + schema: + $ref: '#/components/schemas/RoleResponse' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Role not found + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Authorization + summary: Delete a role + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `delete:role` authorization relation. + operationId: authz_DeleteRole + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + responses: + '204': + description: Role deleted + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Role not found + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /authz/roles/{id}/principals: + get: + tags: + - Authorization + summary: Get principals assigned to a role + description: Requires a valid token, an organization supplied via query, membership of that organization, + and the `viewer:role` authorization relation. + operationId: authz_GetAssignedPrincipalsOfARole + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + - $ref: '#/components/parameters/orgnameQuery' + responses: + '200': + description: Principals assigned to the role. Returns the raw output of models.ListPrincipalsOfARole; + represented generically. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/resources: + post: + tags: + - Cluster Management v1 + summary: Create a generic Kubernetes resource in the cluster + operationId: clustersV1_GenericCreate + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Raw YAML/JSON of the Kubernetes object to create (parsed into an unstructured object). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The created Kubernetes resource. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/deploy/{id}: + post: + tags: + - Cluster Management v1 + summary: Install a product deploy order in the cluster + description: Loads the previously generated order.yaml identified by {id} and installs it into the + cluster. No request body. + operationId: clustersV1_InstallProduct + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: Deploy order ID. + schema: + type: string + responses: + '200': + description: Product installed successfully (empty body). + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Deploy order not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Cluster Management v1 + summary: Uninstall a product deploy order from the cluster + description: Loads the previously generated order.yaml identified by {id} and uninstalls it from + the cluster. No request body. + operationId: clustersV1_UninstallProduct + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: Deploy order ID. + schema: + type: string + responses: + '200': + description: Product uninstalled successfully (empty body). + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Deploy order not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/resource-history: + get: + tags: + - Cluster Management v1 + summary: Get resource history from NATS + description: Returns the change history for resources, filtered by query params (product, group, + resource, rid). + operationId: clustersV1_GetResourceHistoryFromNats + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: product + in: query + required: false + schema: + type: string + - name: group + in: query + required: false + schema: + type: string + - name: resource + in: query + required: false + schema: + type: string + - name: rid + in: query + required: false + schema: + type: string + responses: + '200': + description: Resource history entries. + content: + application/json: + schema: + $ref: '#/components/schemas/BadgerEntryList' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}: + get: + tags: + - Cluster Management v1 + summary: Get a cluster + operationId: clustersV1_GetCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: The cluster info. + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Cluster not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + put: + tags: + - Cluster Management v1 + summary: Update a cluster + description: 'Requires authz: update:cluster (Cluster_Editor).' + operationId: clustersV1_UpdateCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ImportClusterOption' + responses: + '200': + description: The updated cluster info. + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfoModel' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Cluster not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Cluster Management v1 + summary: Delete a cluster + description: 'Submits a cluster deletion command as an async task. Requires authz: delete:cluster + (Cluster_Editor).' + operationId: clustersV1_ClusterDeletionCommand + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: The submitted task response. + content: + application/json: + schema: + $ref: '#/components/schemas/TaskResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Cluster not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/remove: + post: + tags: + - Cluster Management v1 + summary: Remove a cluster + operationId: clustersV1_RemoveCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: Cluster removed successfully (empty body). + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/client-config: + get: + tags: + - Cluster Management v1 + summary: Get the cluster client (kube) config + description: 'Requires authz: view:kube-config (Cluster_CanViewKubeconfig). Returns the raw kubeconfig + as a JSON string.' + operationId: clustersV1_GetClientConfig + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: The kubeconfig as a string. + content: + application/json: + schema: + type: string + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/available-types: + get: + tags: + - Cluster Management v1 + summary: Find available resource types in the cluster + description: Returns a nested mapping of group -> version -> list of available kinds/resources. + operationId: clustersV1_FindAvailableTypes + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: Nested map of available types (dynamic structure). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/db-status: + get: + tags: + - Cluster Management v1 + summary: Get database feature status + description: Returns a dynamic map of feature gates / DB status for the cluster. + operationId: clustersV1_GetDBStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: DB status (dynamic map). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/db-bundle: + get: + tags: + - Cluster Management v1 + summary: Get database bundle information + description: Returns a dynamic map of DB bundle info (map of string to list of strings). + operationId: clustersV1_GetDBBundle + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: DB bundle (dynamic map of string to string array). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/update-presets/{preset}: + post: + tags: + - Cluster Management v1 + summary: Update presets in a spoke cluster + description: Updates the given preset by applying the supplied HelmRelease (fluxcd HelmRelease) + in the spoke cluster. + operationId: clustersV1_UpdatePresetsInSpokeCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: preset + in: path + required: true + description: Preset name. + schema: + type: string + requestBody: + description: fluxcd HelmRelease object. + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Presets updated successfully (empty body). + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/is-server: + get: + tags: + - Cluster Management v1 + summary: Check if this is the server cluster + description: 'Returns {"server": "yes"|"no"}.' + operationId: clustersV1_CheckIfThisIsServerCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: Server check result. + content: + application/json: + schema: + type: object + properties: + server: + type: string + enum: + - 'yes' + - 'no' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/feature/factory-values: + get: + tags: + - Cluster Management v1 + summary: Get feature factory values + description: Returns a dynamic map of factory (default) feature values. + operationId: clustersV1_GetFeatureValues + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: Feature factory values (dynamic map). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/execute-command: + post: + tags: + - Cluster Management v1 + summary: Execute a whitelisted kubectl plugin command + description: Runs one of the supported commands (kubectl-kubestash, kubectl-stash, kubectl-dba, + kubectl-vault) against the cluster. + operationId: clustersV1_ExecuteCommand + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ExecuteCommandPayload' + responses: + '200': + description: Command output. + content: + application/json: + schema: + $ref: '#/components/schemas/CommandResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid or unsupported command. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/tiller-config: + get: + tags: + - Helm + summary: Get the tiller (helm driver) config + operationId: helm_GetTillerConfig + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: The console/tiller config. + content: + application/json: + schema: + $ref: '#/components/schemas/ConsoleConfig' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + put: + tags: + - Helm + summary: Update the tiller (helm driver) config + operationId: helm_UpdateTillerConfig + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TillerOptions' + responses: + '200': + description: The updated console/tiller config. + content: + application/json: + schema: + $ref: '#/components/schemas/ConsoleConfig' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Config not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/tiller-config/default: + get: + tags: + - Helm + summary: Get the default tiller (helm driver) config + operationId: helm_GetDefaultTillerConfig + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: The default console/tiller config. + content: + application/json: + schema: + $ref: '#/components/schemas/ConsoleConfig' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/v3/releases/: + get: + tags: + - Helm + summary: List helm v3 releases + operationId: helm_ListReleases + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Helm list options (lib-helm action.ListOptions). + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: List of helm releases (helm release.Release objects). + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + post: + tags: + - Helm + summary: Install a helm v3 release + description: Submits an install command as an async task. + operationId: helm_InstallReleaseCommand + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Helm install options (lib-helm action.InstallOptions). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The submitted task response. + content: + application/json: + schema: + $ref: '#/components/schemas/TaskResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/v3/releases/{name}/: + get: + tags: + - Helm + summary: Get the history of a helm release + operationId: helm_GetHistory + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: name + in: path + required: true + description: Release name. + schema: + type: string + - name: max + in: query + required: false + description: Maximum number of history revisions to return. + schema: + type: integer + responses: + '200': + description: List of release revisions (helm release.Release objects). + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Release not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + put: + tags: + - Helm + summary: Upgrade a helm v3 release + description: Submits an upgrade command as an async task. + operationId: helm_UpgradeReleaseCommand + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: name + in: path + required: true + description: Release name. + schema: + type: string + requestBody: + description: Helm upgrade options (lib-helm action.UpgradeOptions). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The submitted task response. + content: + application/json: + schema: + $ref: '#/components/schemas/TaskResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Release not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Helm + summary: Uninstall a helm v3 release + description: Submits an uninstall command as an async task. + operationId: helm_UninstallReleaseCommand + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: name + in: path + required: true + description: Release name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UninstallReleaseRequest' + responses: + '200': + description: The submitted task response. + content: + application/json: + schema: + $ref: '#/components/schemas/TaskResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Release not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/v3/releases/{name}/content: + get: + tags: + - Helm + summary: Get the content of a helm release + operationId: helm_GetReleaseContent + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: name + in: path + required: true + description: Release name. + schema: + type: string + - name: version + in: query + required: false + schema: + type: integer + - name: namespace + in: query + required: false + schema: + type: string + responses: + '200': + description: The release content (helm release.Release object). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Release not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/v3/releases/{name}/status: + get: + tags: + - Helm + summary: Get the status of a helm release + operationId: helm_GetReleaseStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: name + in: path + required: true + description: Release name. + schema: + type: string + - name: version + in: query + required: false + schema: + type: integer + - name: namespace + in: query + required: false + schema: + type: string + responses: + '200': + description: The release status (helm release.Release object). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Release not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/v3/releases/{name}/rollback: + post: + tags: + - Helm + summary: Rollback a helm v3 release + description: Submits a rollback command as an async task. + operationId: helm_RollbackReleaseCommand + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: name + in: path + required: true + description: Release name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RollbackReleaseRequest' + responses: + '200': + description: The submitted task response. + content: + application/json: + schema: + $ref: '#/components/schemas/TaskResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Release not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/bundleview: + get: + tags: + - Helm + summary: Get the bundle view for a chart + operationId: helm_GetBundleViewForChart + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Chart source reference (releasesapi.ChartSourceFlatRef). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The bundle view (releasesapi.BundleView). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/bundleview/orders: + post: + tags: + - Helm + summary: Create an order for a bundle view + operationId: helm_CreateOrderForBundle + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Bundle view (releasesapi.BundleView). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The generated order (releasesapi.Order). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/packageview: + get: + tags: + - Helm + summary: Get the package view for a chart + operationId: helm_GetPackageViewForChart + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Chart source reference (releasesapi.ChartSourceFlatRef). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The package view (releasesapi.PackageView, serialized as raw JSON). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/packageview/files: + get: + tags: + - Helm + summary: List the files of a chart package + operationId: helm_ListPackageFiles + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Chart source reference (releasesapi.ChartSourceFlatRef). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: List of package file paths. + content: + application/json: + schema: + type: array + items: + type: string + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/packageview/files/{path}: + get: + tags: + - Helm + summary: Get a single file from a chart package + operationId: helm_GetPackageFile + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: path + in: path + required: true + description: Path of the file within the chart package. + schema: + type: string + requestBody: + description: Chart source reference (releasesapi.ChartSourceFlatRef). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The requested file content (raw bytes; content-type varies). + content: + application/octet-stream: + schema: + type: string + format: binary + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: File not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/packageview/orders: + post: + tags: + - Helm + summary: Create an order for an editor package view / chart + operationId: helm_CreateOrderForPackage + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Chart order (releasesapi.ChartOrder). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The generated order (releasesapi.Order). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/packageview/values: + get: + tags: + - Helm + summary: Get the values file for a chart preset + operationId: helm_GetValuesFile + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Chart preset reference (chartsapi.ChartPresetFlatRef). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The merged chart values (dynamic map). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/options/model: + put: + tags: + - Helm + summary: Generate an editor model from options + operationId: helm_GenerateEditorModelFromOptions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Options (arbitrary JSON object). + required: true + content: + application/json: + schema: + type: object + additionalProperties: true + responses: + '200': + description: The generated editor model (unstructured object; YAML when requested). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/options/manifest: + put: + tags: + - Helm + summary: Preview the editor manifest from options + operationId: helm_PreviewEditorManifest + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Options (arbitrary JSON object). + required: true + content: + application/json: + schema: + type: object + additionalProperties: true + responses: + '200': + description: The rendered manifest (raw YAML/text). + content: + text/plain: + schema: + type: string + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/options/resources: + put: + tags: + - Helm + summary: Preview the editor resources from options + operationId: helm_PreviewEditorResources + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Options (arbitrary JSON object). + required: true + content: + application/json: + schema: + type: object + additionalProperties: true + responses: + '200': + description: The rendered resources (releasesapi.ResourceOutput). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/editor/: + put: + tags: + - Helm + summary: Apply (create/update/install) a resource editor model + description: Submits an apply command as an async task. + operationId: helm_ApplyResourceCommand + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Editor model (arbitrary JSON object). + required: true + content: + application/json: + schema: + type: object + additionalProperties: true + responses: + '200': + description: The submitted task response. + content: + application/json: + schema: + $ref: '#/components/schemas/TaskResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Helm + summary: Delete a resource editor installation + description: Submits a delete command as an async task. + operationId: helm_DeleteResourceCommand + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Resource metadata (releasesapi.MetadataFlat). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The submitted task response. + content: + application/json: + schema: + $ref: '#/components/schemas/TaskResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/editor/model: + put: + tags: + - Helm + summary: Load an editor model from an existing installation + operationId: helm_LoadEditorModel + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Editor model (releasesapi.Model). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The editor model values (raw JSON/YAML). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/editor/manifest: + put: + tags: + - Helm + summary: Load the editor manifest from an existing installation + operationId: helm_LoadEditorManifest + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Editor model (releasesapi.Model). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The rendered manifest (raw YAML/text). + content: + text/plain: + schema: + type: string + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/helm/editor/resources: + put: + tags: + - Helm + summary: Load the editor resources from an existing installation + operationId: helm_LoadEditorResources + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + description: Editor model metadata (releasesapi.ModelMetadata). + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: The rendered resources (releasesapi.ResourceOutput). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/all-available: + get: + tags: + - Kubernetes Proxy + summary: List available object versions for a group/version + description: Discovers all resources under the given API group/version and returns, per Kind, the + list of object names available in the cluster. + operationId: proxy_ListAvailableObjectsByGroupVersion + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + responses: + '200': + description: Map of Kind to available object names. + content: + application/json: + schema: + type: object + additionalProperties: + type: array + items: + type: string + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/core/v1/namespaces/{namespace}/{resource}/{name}/log: + get: + tags: + - Kubernetes Proxy + summary: Stream pod logs + description: Streams container logs for the named pod. The response is a streaming plain-text body. + operationId: proxy_StreamPodLogs + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: namespace + in: path + required: true + description: Namespace of the pod. + schema: + type: string + - name: resource + in: path + required: true + description: Resource type (pods). + schema: + type: string + - name: name + in: path + required: true + description: Name of the pod. + schema: + type: string + responses: + '200': + description: Streaming log output. + content: + text/plain: + schema: + type: string + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Pod not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/core/v1/namespaces/{namespace}/{resource}/{name}/exec: + get: + tags: + - Kubernetes Proxy + summary: Exec into a pod container + description: Establishes an interactive exec session into a container of the named pod. This endpoint + is upgraded to a WebSocket connection; it is not a plain HTTP request/response. + operationId: proxy_ExecPod + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: namespace + in: path + required: true + description: Namespace of the pod. + schema: + type: string + - name: resource + in: path + required: true + description: Resource type (pods). + schema: + type: string + - name: name + in: path + required: true + description: Name of the pod. + schema: + type: string + responses: + '101': + description: Switching Protocols; connection upgraded to a WebSocket exec stream. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Pod not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/core/v1/nodes/{name}/metrics: + get: + tags: + - Kubernetes Proxy + summary: Get node metrics + description: Returns resource usage metrics for the named node. + operationId: proxy_GetNodeMetrics + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: name + in: path + required: true + description: Name of the node. + schema: + type: string + responses: + '200': + description: Node metrics object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Node not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/core/v1/namespaces/{namespace}/pods/{name}/metrics: + get: + tags: + - Kubernetes Proxy + summary: Get pod metrics + description: Returns resource usage metrics for the named pod. + operationId: proxy_GetPodMetrics + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: namespace + in: path + required: true + description: Namespace of the pod. + schema: + type: string + - name: name + in: path + required: true + description: Name of the pod. + schema: + type: string + responses: + '200': + description: Pod metrics object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Pod not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/authorization.k8s.io/v1/selfsubjectaccessreviews: + post: + tags: + - Kubernetes Proxy + summary: Create a SelfSubjectAccessReview + description: Submits a SelfSubjectAccessReview to check whether the current user can perform an + action, returning the review with its populated status. + operationId: proxy_CreateSelfSubjectAccessReview + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: SelfSubjectAccessReview with populated status. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/meta.k8s.appscode.com/v1alpha1/{resource}/{menu}/available: + get: + tags: + - Kubernetes Proxy + summary: Get available user menus for a resource + description: Returns the available user menu entries for the given meta.k8s.appscode.com resource + and menu. + operationId: proxy_GetAvailableUserMenus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: resource + in: path + required: true + description: meta.k8s.appscode.com resource name. + schema: + type: string + - name: menu + in: path + required: true + description: Menu identifier. + schema: + type: string + responses: + '200': + description: Available user menus object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/meta.k8s.appscode.com/v1alpha1/renders: + get: + tags: + - Kubernetes Proxy + summary: Render a resource layout (cacheable create) + description: Renders a meta.k8s.appscode.com Render object. Implemented as a cacheable create where + the request object is passed via the "q" query parameter (JSON-encoded) so the response can be + cached. + operationId: proxy_RenderResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: q + in: query + required: true + description: JSON-encoded Render request object. + schema: + type: string + responses: + '200': + description: Rendered object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '304': + description: Not Modified (Etag matched). + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/meta.k8s.appscode.com/v1alpha1/renderdashboards: + get: + tags: + - Kubernetes Proxy + summary: Render dashboards (cacheable create) + description: Renders a meta.k8s.appscode.com RenderDashboard object. The request object is passed + via the "q" query parameter (JSON-encoded). + operationId: proxy_RenderDashboards + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: q + in: query + required: true + description: JSON-encoded RenderDashboard request object. + schema: + type: string + responses: + '200': + description: Rendered dashboards object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '304': + description: Not Modified (Etag matched). + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/meta.k8s.appscode.com/v1alpha1/rendermenus: + get: + tags: + - Kubernetes Proxy + summary: Render menus (cacheable create) + description: Renders a meta.k8s.appscode.com RenderMenu object. The request object is passed via + the "q" query parameter (JSON-encoded). + operationId: proxy_RenderMenus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: q + in: query + required: true + description: JSON-encoded RenderMenu request object. + schema: + type: string + responses: + '200': + description: Rendered menus object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '304': + description: Not Modified (Etag matched). + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/meta.k8s.appscode.com/v1alpha1/resourcegraphs: + get: + tags: + - Kubernetes Proxy + summary: Render resource graph (cacheable create) + description: Renders a meta.k8s.appscode.com ResourceGraph object. The request object is passed + via the "q" query parameter (JSON-encoded). + operationId: proxy_RenderResourceGraphs + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: q + in: query + required: true + description: JSON-encoded ResourceGraph request object. + schema: + type: string + responses: + '200': + description: Rendered resource graph object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '304': + description: Not Modified (Etag matched). + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/reports.scanner.appscode.com/v1alpha1/images: + get: + tags: + - Kubernetes Proxy + summary: Get scanner image report (cacheable create) + description: Produces a reports.scanner.appscode.com Image report. The request object is passed + via the "q" query parameter (JSON-encoded). + operationId: proxy_GetScannerImageReport + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: q + in: query + required: true + description: JSON-encoded Image report request object. + schema: + type: string + responses: + '200': + description: Image report object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '304': + description: Not Modified (Etag matched). + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/reports.scanner.appscode.com/v1alpha1/cvereports: + get: + tags: + - Kubernetes Proxy + summary: Get scanner CVE report (cacheable create) + description: Produces a reports.scanner.appscode.com CVEReport. The request object is passed via + the "q" query parameter (JSON-encoded). + operationId: proxy_GetScannerCVEReport + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: q + in: query + required: true + description: JSON-encoded CVEReport request object. + schema: + type: string + responses: + '200': + description: CVE report object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '304': + description: Not Modified (Etag matched). + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/policy.k8s.appscode.com/v1alpha1/policyreports: + get: + tags: + - Kubernetes Proxy + summary: Get policy report (cacheable create) + description: Produces a policy.k8s.appscode.com PolicyReport. The request object is passed via the + "q" query parameter (JSON-encoded). + operationId: proxy_GetPolicyReport + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: q + in: query + required: true + description: JSON-encoded PolicyReport request object. + schema: + type: string + responses: + '200': + description: Policy report object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '304': + description: Not Modified (Etag matched). + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/: + post: + tags: + - Kubernetes Proxy + summary: Create a cluster-scoped resource + description: Creates an arbitrary cluster-scoped Kubernetes object of the given GVR. + operationId: proxy_CreateClusterScopedResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Created object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + get: + tags: + - Kubernetes Proxy + summary: List cluster-scoped resources + description: Lists arbitrary cluster-scoped Kubernetes objects of the given GVR. Supports label/field + selectors, a "filter" query for content filtering and "convertToTable" for table output. + operationId: proxy_ListClusterScopedResources + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + responses: + '200': + description: List of objects (or a Table when convertToTable is set). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '304': + description: Not Modified (Etag matched). + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Kubernetes Proxy + summary: Delete a collection of cluster-scoped resources + description: Deletes a collection of cluster-scoped Kubernetes objects of the given GVR. The optional + request body carries metav1.DeleteOptions. + operationId: proxy_DeleteClusterScopedCollection + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Collection deleted. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/{name}: + get: + tags: + - Kubernetes Proxy + summary: Get a cluster-scoped resource + description: Reads an arbitrary cluster-scoped Kubernetes object by name. + operationId: proxy_GetClusterScopedResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + responses: + '200': + description: The object (or a Table when convertToTable is set). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '304': + description: Not Modified (Etag matched). + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Object not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + put: + tags: + - Kubernetes Proxy + summary: Update a cluster-scoped resource + description: Replaces an arbitrary cluster-scoped Kubernetes object. + operationId: proxy_UpdateClusterScopedResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Updated object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + patch: + tags: + - Kubernetes Proxy + summary: Patch a cluster-scoped resource + description: Patches an arbitrary cluster-scoped Kubernetes object. Supports JSON/merge/strategic-merge + patch types via Content-Type; a plain JSON body is diffed against the current object to build + a JSON patch. + operationId: proxy_PatchClusterScopedResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Patched object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Kubernetes Proxy + summary: Delete a cluster-scoped resource + description: Deletes an arbitrary cluster-scoped Kubernetes object by name. The optional request + body carries metav1.DeleteOptions. + operationId: proxy_DeleteClusterScopedResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Object deleted. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/{name}/status: + put: + tags: + - Kubernetes Proxy + summary: Update a cluster-scoped resource status + description: Patches the status subresource of an arbitrary cluster-scoped Kubernetes object. + operationId: proxy_UpdateClusterScopedResourceStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Object with updated status. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + patch: + tags: + - Kubernetes Proxy + summary: Patch a cluster-scoped resource status + description: Patches the status subresource of an arbitrary cluster-scoped Kubernetes object. + operationId: proxy_PatchClusterScopedResourceStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Object with updated status. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/{name}/events: + get: + tags: + - Kubernetes Proxy + summary: List events for a cluster-scoped resource + description: Lists Kubernetes events referencing the named cluster-scoped object. + operationId: proxy_ListClusterScopedResourceEvents + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + responses: + '200': + description: Event list. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/{resource}/{name}/controller: + get: + tags: + - Kubernetes Proxy + summary: Get controller of a cluster-scoped resource + description: Returns the controlling owner object of the named cluster-scoped object. + operationId: proxy_GetClusterScopedResourceController + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + responses: + '200': + description: Controller object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Controller not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}/scale: + get: + tags: + - Kubernetes Proxy + summary: Get the scale subresource + description: Reads the scale subresource of the named namespaced object. + operationId: proxy_GetScale + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Namespace of the object. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + responses: + '200': + description: Scale object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + put: + tags: + - Kubernetes Proxy + summary: Update the scale subresource + description: Updates the replica count of the named namespaced object via its scale subresource. + The request body carries a JSON object with a "replicas" integer field. + operationId: proxy_UpdateScale + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Namespace of the object. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + replicas: + type: integer + format: int32 + description: Desired replica count. + required: + - replicas + responses: + '200': + description: Updated scale object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}/horizontalpodautoscalers: + get: + tags: + - Kubernetes Proxy + summary: List HPAs targeting a namespaced resource + description: Returns the HorizontalPodAutoscalers whose scale target matches the named namespaced + object. + operationId: proxy_ListResourceHPAs + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Namespace of the object. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + responses: + '200': + description: Filtered HorizontalPodAutoscaler list. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/: + post: + tags: + - Kubernetes Proxy + summary: Create a namespaced resource + description: Creates an arbitrary namespaced Kubernetes object of the given GVR. + operationId: proxy_CreateNamespacedResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Target namespace. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Created object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + get: + tags: + - Kubernetes Proxy + summary: List namespaced resources + description: Lists arbitrary namespaced Kubernetes objects of the given GVR. Supports label/field + selectors, "filter" and "convertToTable" query parameters. + operationId: proxy_ListNamespacedResources + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Target namespace. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + responses: + '200': + description: List of objects (or a Table when convertToTable is set). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '304': + description: Not Modified (Etag matched). + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Kubernetes Proxy + summary: Delete a collection of namespaced resources + description: Deletes a collection of namespaced Kubernetes objects of the given GVR. The optional + request body carries metav1.DeleteOptions. + operationId: proxy_DeleteNamespacedCollection + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Target namespace. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Collection deleted. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}: + get: + tags: + - Kubernetes Proxy + summary: Get a namespaced resource + description: Reads an arbitrary namespaced Kubernetes object by name. + operationId: proxy_GetNamespacedResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Namespace of the object. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + responses: + '200': + description: The object (or a Table when convertToTable is set). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '304': + description: Not Modified (Etag matched). + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Object not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + put: + tags: + - Kubernetes Proxy + summary: Update a namespaced resource + description: Replaces an arbitrary namespaced Kubernetes object. + operationId: proxy_UpdateNamespacedResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Namespace of the object. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Updated object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + patch: + tags: + - Kubernetes Proxy + summary: Patch a namespaced resource + description: Patches an arbitrary namespaced Kubernetes object. Supports JSON/merge/strategic-merge + patch types via Content-Type; a plain JSON body is diffed against the current object to build + a JSON patch. + operationId: proxy_PatchNamespacedResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Namespace of the object. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Patched object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Kubernetes Proxy + summary: Delete a namespaced resource + description: Deletes an arbitrary namespaced Kubernetes object by name. The optional request body + carries metav1.DeleteOptions. + operationId: proxy_DeleteNamespacedResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Namespace of the object. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Object deleted. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}/status: + put: + tags: + - Kubernetes Proxy + summary: Update a namespaced resource status + description: Patches the status subresource of an arbitrary namespaced Kubernetes object. + operationId: proxy_UpdateNamespacedResourceStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Namespace of the object. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Object with updated status. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + patch: + tags: + - Kubernetes Proxy + summary: Patch a namespaced resource status + description: Patches the status subresource of an arbitrary namespaced Kubernetes object. + operationId: proxy_PatchNamespacedResourceStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Namespace of the object. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Object with updated status. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}/events: + get: + tags: + - Kubernetes Proxy + summary: List events for a namespaced resource + description: Lists Kubernetes events referencing the named namespaced object. + operationId: proxy_ListNamespacedResourceEvents + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Namespace of the object. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + responses: + '200': + description: Event list. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/{group}/{version}/namespaces/{namespace}/{resource}/{name}/controller: + get: + tags: + - Kubernetes Proxy + summary: Get controller of a namespaced resource + description: Returns the controlling owner object of the named namespaced object. + operationId: proxy_GetNamespacedResourceController + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + - name: group + in: path + required: true + description: Kubernetes API group (use "core" for the legacy core group). + schema: + type: string + - name: version + in: path + required: true + description: Kubernetes API version. + schema: + type: string + - name: namespace + in: path + required: true + description: Namespace of the object. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource (plural). + schema: + type: string + - name: name + in: path + required: true + description: Object name. + schema: + type: string + responses: + '200': + description: Controller object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Controller not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/{cluster}/proxy/batch-delete: + post: + tags: + - Kubernetes Proxy + summary: Batch delete resources + description: Deletes multiple Kubernetes objects in a single request. Each entry is deleted independently; + the response reports the per-resource deletion status for any that failed. + operationId: proxy_BatchDeleteResources + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BatchDeleteRequest' + responses: + '200': + description: Per-resource deletion status. + content: + application/json: + schema: + $ref: '#/components/schemas/BatchDeleteResponse' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/providers/{provider}/skip-credentials: + get: + tags: + - Cluster Management v2 + summary: Check whether credentials can be skipped for a provider + description: Requires site-admin privileges (admin_of_administrative_org:site_admin). Only EKS is + supported; verifies the current environment has the AWS IAM permissions needed to skip manual + credentials. + operationId: clustersV2_CheckSkipCredentials + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: provider + in: path + required: true + description: Cloud provider identifier (only "eks" is supported). + schema: + type: string + responses: + '200': + description: Credentials can be skipped. + content: + application/json: + schema: + $ref: '#/components/schemas/SkipCredentialsResponse' + '400': + description: Credentials cannot be skipped (unsupported provider or insufficient permissions). + content: + application/json: + schema: + $ref: '#/components/schemas/SkipCredentialsResponse' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/all-hubs: + get: + tags: + - Cluster Management v2 + summary: List all hub clusters owned by the user across their organizations + operationId: clustersV2_ListAllHubClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of active hub clusters. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/HubCluster' + '400': + description: User does not own any organization. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/all-clusters: + get: + tags: + - Cluster Management v2 + summary: List all imported clusters for an owner + description: Requires site-admin privileges (view_orgs:site_admin). + operationId: clustersV2_ListImportedCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + responses: + '200': + description: List of imported clusters. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/identity/{clusterID}: + get: + tags: + - Cluster Management v2 + summary: Get cluster identity metadata by cluster UID + operationId: clustersV2_GetClusterIdentity + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: clusterID + in: path + required: true + description: Cluster UID. + schema: + type: string + responses: + '200': + description: Cluster metadata. + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterMetadata' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '404': + description: Cluster info not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/cluster-profiles: + get: + tags: + - Cluster Management v2 + summary: List available cluster profiles + operationId: clustersV2_GetClusterProfiles + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: An UnstructuredList of clusterprofiles (meta.k8s.appscode.com/v1alpha1). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/exist: + get: + tags: + - Cluster Management v2 + summary: Check whether the cluster is imported for the given owner + operationId: clustersV2_IsClusterImportedForThisUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + responses: + '200': + description: Existence flag. + content: + application/json: + schema: + type: object + properties: + exist: + type: boolean + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}: + get: + tags: + - Cluster Management v2 + summary: List clusters for an owner + operationId: clustersV2_ListClusters2 + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + responses: + '200': + description: List of clusters (with a provider set). + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/hub-info: + get: + tags: + - Cluster Management v2 + summary: Get hub cluster connection info (token and API server) for OCM hub clusters + operationId: clustersV2_GetHubInfo + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + responses: + '200': + description: Map keyed by cluster name; each value contains apiServer and token. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '400': + description: Failed to list OCM manager clusters. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/has-hub: + get: + tags: + - Cluster Management v2 + summary: Check whether the owner has any hub cluster + operationId: clustersV2_HasHubCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + responses: + '200': + description: Hub presence flag. + content: + application/json: + schema: + type: object + properties: + has-hub: + type: boolean + '400': + description: Failed to list OCM manager clusters. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/reconcile: + get: + tags: + - Cluster Management v2 + summary: Reconcile Helm releases for specified features + description: Adds reconcile annotations to the HelmReleases of the features passed in the "features" + query parameter (comma-separated). + operationId: clustersV2_ReconcileHelmRelease + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: features + in: query + required: false + description: Comma-separated list of feature names to reconcile. + schema: + type: string + responses: + '200': + description: Reconcile triggered. + '400': + description: A feature or its HelmRelease was not found. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/status: + get: + tags: + - Cluster Management v2 + summary: Get the current status of a cluster + operationId: clustersV2_GetClusterStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + responses: + '200': + description: Cluster info with resolved status. + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/connect: + post: + tags: + - Cluster Management v2 + summary: Connect (or re-connect) to an already-imported cluster + operationId: clustersV2_Connect + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: operation + in: query + required: false + description: Set to "re-connect" to update existing credentials. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ConnectOptions' + responses: + '200': + description: Cluster info after connecting. + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '400': + description: Failed to connect (already-existing user auth on non-reconnect). + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/remove: + post: + tags: + - Cluster Management v2 + summary: Remove a cluster and its components + operationId: clustersV2_RemoveClusterV2 + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: response-id + in: query + required: false + description: Optional response identifier for progress notifications. + schema: + type: string + - name: notify + in: query + required: false + description: Whether to send progress notifications (defaults to true). + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RemovalOptions' + responses: + '200': + description: Removal task submitted. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/update-version/operations: + get: + tags: + - Cluster Management v2 + summary: List cluster version update operations + operationId: clustersV2_ListUpdateVersionOperations + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + responses: + '200': + description: A ConfigMapList of upgrade operations. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/update-version/list: + get: + tags: + - Cluster Management v2 + summary: List upgradeable Kubernetes versions for a cluster + operationId: clustersV2_GetUpgradeableK8SVersions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + responses: + '200': + description: List of upgradeable Kubernetes versions. + content: + application/json: + schema: + type: array + items: + type: string + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/update-version/{version}: + get: + tags: + - Cluster Management v2 + summary: Upgrade a CAPI cluster to a target Kubernetes version + operationId: clustersV2_UpdateK8sVersion + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: version + in: path + required: true + description: Target Kubernetes version. + schema: + type: string + responses: + '200': + description: Upgrade task submitted. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/gateway-configs: + get: + tags: + - Cluster Management v2 + summary: List gateway configurations + operationId: clustersV2_ListGatewayConfigs + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + responses: + '200': + description: List of gateway configuration rows. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/GatewayConfigInfo' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + put: + tags: + - Cluster Management v2 + summary: Update all non-ace gateway configurations to the ace chart version + operationId: clustersV2_UpdateAllGatewayConfigs + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + responses: + '200': + description: Gateway configurations updated. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/gateway-configs/{namespace}/{name}: + put: + tags: + - Cluster Management v2 + summary: Update a single gateway configuration to the ace chart version + operationId: clustersV2_UpdateGatewayConfig + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: namespace + in: path + required: true + description: Namespace of the GatewayConfig. + schema: + type: string + - name: name + in: path + required: true + description: Name of the GatewayConfig. + schema: + type: string + responses: + '200': + description: Gateway configuration updated. + '400': + description: The ace gateway config cannot be updated. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/reconfigure: + post: + tags: + - Cluster Management v2 + summary: Reconfigure a cluster's components + operationId: clustersV2_Reconfigure + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ReconfigureOptions' + responses: + '200': + description: Reconfiguration accepted. Returns the internal cluster info record (modeled as + a generic object). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/feature/{feature}/convert: + post: + tags: + - Cluster Management v2 + summary: Convert a feature to be UI-managed + operationId: clustersV2_ConvertFeature + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: feature + in: path + required: true + description: Name of the feature to convert. + schema: + type: string + responses: + '200': + description: Feature converted to UI-managed. + '400': + description: Feature is not enabled or already UI-managed. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/subscriptions/: + post: + tags: + - Cluster Management v2 + summary: Subscribe the current user to cluster-level inbox notifications + operationId: clustersV2_CreateClusterSubscription + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + responses: + '200': + description: Subscription created. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + get: + tags: + - Cluster Management v2 + summary: Check the current user's cluster-level inbox subscription + operationId: clustersV2_CheckClusterSubscription + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + responses: + '200': + description: Subscription exists. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Cluster Management v2 + summary: Remove the cluster-level inbox subscription + operationId: clustersV2_RemoveClusterSubscription + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + responses: + '200': + description: Subscription removed. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/subscriptions/namespaces/{namespace}/: + post: + tags: + - Cluster Management v2 + summary: Subscribe the current user to namespace-level inbox notifications + operationId: clustersV2_CreateNamespaceSubscription + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: namespace + in: path + required: true + description: Namespace to subscribe to. + schema: + type: string + responses: + '200': + description: Subscription created. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + get: + tags: + - Cluster Management v2 + summary: Check the current user's namespace-level inbox subscription + operationId: clustersV2_CheckNamespaceSubscription + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: namespace + in: path + required: true + description: Namespace to check. + schema: + type: string + responses: + '200': + description: Subscription exists. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Cluster Management v2 + summary: Remove the namespace-level inbox subscription + operationId: clustersV2_RemoveNamespaceSubscription + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: namespace + in: path + required: true + description: Namespace to unsubscribe from. + schema: + type: string + responses: + '200': + description: Subscription removed. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/{cluster}/subscriptions/namespaces/{namespace}/{group}/{version}/{resource}/{resourceName}: + post: + tags: + - Cluster Management v2 + summary: Subscribe the current user to resource-level inbox notifications + operationId: clustersV2_CreateResourceSubscription + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: namespace + in: path + required: true + description: Namespace of the resource. + schema: + type: string + - name: group + in: path + required: true + description: API group of the resource. + schema: + type: string + - name: version + in: path + required: true + description: API version of the resource. + schema: + type: string + - name: resource + in: path + required: true + description: Resource (plural) name. + schema: + type: string + - name: resourceName + in: path + required: true + description: Name of the specific resource object. + schema: + type: string + responses: + '200': + description: Subscription created. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + get: + tags: + - Cluster Management v2 + summary: Check the current user's resource-level inbox subscription + operationId: clustersV2_CheckResourceSubscription + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: namespace + in: path + required: true + description: Namespace of the resource. + schema: + type: string + - name: group + in: path + required: true + description: API group of the resource. + schema: + type: string + - name: version + in: path + required: true + description: API version of the resource. + schema: + type: string + - name: resource + in: path + required: true + description: Resource (plural) name. + schema: + type: string + - name: resourceName + in: path + required: true + description: Name of the specific resource object. + schema: + type: string + responses: + '200': + description: Subscription exists. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + delete: + tags: + - Cluster Management v2 + summary: Remove the resource-level inbox subscription + operationId: clustersV2_RemoveResourceSubscription + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - $ref: '#/components/parameters/clusterPathParam' + - name: namespace + in: path + required: true + description: Namespace of the resource. + schema: + type: string + - name: group + in: path + required: true + description: API group of the resource. + schema: + type: string + - name: version + in: path + required: true + description: API version of the resource. + schema: + type: string + - name: resource + in: path + required: true + description: Resource (plural) name. + schema: + type: string + - name: resourceName + in: path + required: true + description: Name of the specific resource object. + schema: + type: string + responses: + '200': + description: Subscription removed. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/check: + post: + tags: + - Cluster Management v2 + summary: Check whether a cluster already exists / is importable + operationId: clustersV2_CheckClusterExistence + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CheckOptions' + responses: + '200': + description: Cluster info describing existence / import status. + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/validate: + post: + tags: + - Cluster Management v2 + summary: Validate cluster import options + operationId: clustersV2_ValidateHandler + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + - name: operation + in: query + required: false + description: Set to "connect" to skip flux/feature-set detection. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ImportOptions' + responses: + '200': + description: Validation result. + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationResponse' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/import: + post: + tags: + - Cluster Management v2 + summary: Import a cluster + operationId: clustersV2_ImportClusterHandler + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ImportOptions' + responses: + '200': + description: Imported cluster info. + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/vcluster/create: + post: + tags: + - Cluster Management v2 + summary: Create a virtual cluster on a host cluster + operationId: clustersV2_CreateVirtualCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterOptions' + responses: + '200': + description: Virtual cluster creation task submitted. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clustersv2/{owner}/vcluster/import: + post: + tags: + - Cluster Management v2 + summary: Import a virtual cluster from a host cluster + operationId: clustersV2_ImportVirtualCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerPathParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterOptions' + responses: + '200': + description: Virtual cluster import task submitted. + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + description: Invalid request body. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /agent/{clusterName}/{clusterID}/token: + get: + tags: + - Cluster Management v2 + summary: Get an inbox agent JWT token for a cluster + operationId: clustersV2_GetInboxAgentToken + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: clusterName + in: path + required: true + description: Cluster name. + schema: + type: string + - name: clusterID + in: path + required: true + description: Cluster UID. + schema: + type: string + responses: + '200': + description: Inbox agent token response. + content: + application/json: + schema: + $ref: '#/components/schemas/InboxTokenRequestResponse' + '401': + description: Unauthorized. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '403': + description: Forbidden. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + /clusters/{owner}/hubs: + get: + tags: + - Multi-cluster (OCM) + summary: List OCM hub clusters owned by the owner + operationId: ocm_ListHubClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of hub clusters (OCM / OCM-MC) owned by the owner. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/HubCluster' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/accept-spoke: + post: + tags: + - Multi-cluster (OCM) + summary: Accept spoke cluster join requests on the hub + operationId: ocm_AcceptSpokeClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AcceptOptions' + responses: + '200': + description: Spoke cluster join requests accepted. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/managed-clusters: + get: + tags: + - Multi-cluster (OCM) + summary: List all OCM managed clusters + operationId: ocm_ListManagedClusters + description: Returns the raw OCM ManagedClusterList object from the hub cluster. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: OCM ManagedClusterList object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/not-accepted-clusters: + get: + tags: + - Multi-cluster (OCM) + summary: List managed clusters not yet accepted by the hub + operationId: ocm_ListNotAcceptedClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: List of managed clusters that have not been accepted. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ManagedClusterInfo' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/accepted-clusters: + get: + tags: + - Multi-cluster (OCM) + summary: List managed clusters accepted by the hub + operationId: ocm_ListAcceptedClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: List of accepted managed clusters. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ManagedClusterInfo' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/validate-profile: + get: + tags: + - Multi-cluster (OCM) + summary: Validate spoke cluster feature sets against a profile + operationId: ocm_ValidateSpokeClustersFeatureSets + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: profile + in: query + required: false + description: Cluster profile to validate against (defaults to "dbaas-generic"). + schema: + type: string + responses: + '200': + description: Validation result. Contains "valid" ("true"/"false" string) and, when invalid, + a "recommended-features" list. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/available-clusters: + get: + tags: + - Multi-cluster (OCM) + summary: List managed clusters available for use by the owner + operationId: ocm_GetAvailableManagedClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: List of available managed clusters. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ManagedClusterInfo' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/available-clustersets: + get: + tags: + - Multi-cluster (OCM) + summary: List cluster sets available for use by the owner + operationId: ocm_GetAvailableManagedClusterSets + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: type + in: query + required: false + description: Filter mode. When set to "client-org", cluster sets are further filtered for client-org + eligibility. + schema: + type: string + responses: + '200': + description: List of available cluster set names. + content: + application/json: + schema: + type: array + items: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/clustersets: + get: + tags: + - Multi-cluster (OCM) + summary: List cluster sets on the hub + operationId: ocm_ListClusterSets + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: List of cluster sets with cluster counts. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ListClusterSetResp' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/clustersets/add: + post: + tags: + - Multi-cluster (OCM) + summary: Add clusters to a cluster set + operationId: ocm_AddToClusterSet + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterSetOptions' + responses: + '200': + description: Clusters added to the cluster set. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/clustersets/remove: + post: + tags: + - Multi-cluster (OCM) + summary: Remove clusters from a cluster set + operationId: ocm_RemoveFromClusterSet + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterSetOptions' + responses: + '200': + description: Clusters removed from the cluster set. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/clustersets/create: + post: + tags: + - Multi-cluster (OCM) + summary: Create a cluster set + operationId: ocm_CreateClusterSet + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterSetOptions' + responses: + '200': + description: Cluster set created. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/clustersets/delete: + post: + tags: + - Multi-cluster (OCM) + summary: Delete a cluster set + operationId: ocm_DeleteClusterSet + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterSetOptions' + responses: + '200': + description: Cluster set deleted. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/featuresets: + get: + tags: + - Multi-cluster (OCM) + summary: List available feature sets of a cluster set + operationId: ocm_GetAvailableFeatureSetsOfClusterSet + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + responses: + '200': + description: List of feature set info for the cluster set. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FeatureSetInfo' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/clusters: + get: + tags: + - Multi-cluster (OCM) + summary: List clusters belonging to a cluster set + operationId: ocm_GetClusterOfClusterSet + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + responses: + '200': + description: Clusters belonging to the cluster set. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClustersResp' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/clusterlist: + get: + tags: + - Multi-cluster (OCM) + summary: List clusters that can be added to a cluster set + operationId: ocm_ListAddableClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + responses: + '200': + description: List of managed cluster names addable to the cluster set. + content: + application/json: + schema: + type: array + items: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/disable-featureset: + post: + tags: + - Multi-cluster (OCM) + summary: Disable a feature set on a cluster set + operationId: ocm_DisableFeatureSetFromClusterSet + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/EnableFeatureOptions' + responses: + '200': + description: Feature set disabled on the cluster set. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/install-featureset: + post: + tags: + - Multi-cluster (OCM) + summary: Install a feature set on a cluster set + operationId: ocm_InstallFeatureSetOnClusterSet + description: The request body is a free-form Helm values / model object (map[string]any) describing + the feature set to install. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Feature set installed on the cluster set. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/{managedCluster}/update-featureset: + post: + tags: + - Multi-cluster (OCM) + summary: Update the profile binding / feature set for a managed cluster + operationId: ocm_UpdateManagedClusterProfileBinding + description: The request body is a free-form Helm values / model object (map[string]any) describing + the feature set update. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + - name: managedCluster + in: path + required: true + description: Managed cluster name. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Managed cluster profile binding updated. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/auth-info: + get: + tags: + - Multi-cluster (OCM) + summary: Get authorization info for a cluster set + operationId: ocm_GetAuthInfoOfClusterSet + description: Returns a map of role-ref name to the list of users granted that role on the cluster + set. Users are returned as the internal user model. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + responses: + '200': + description: Map of role-ref name to a list of users. Modeled as a free-form object because + the value is the internal user model. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/auto-update: + post: + tags: + - Multi-cluster (OCM) + summary: Trigger auto-update of a cluster set + operationId: ocm_AutoUpdateClusterSet + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + responses: + '200': + description: Cluster set auto-update triggered. + '400': + description: Auto-update is not possible (spoke clusters not on the latest version). + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/auto-update/check: + get: + tags: + - Multi-cluster (OCM) + summary: Check whether auto-update is possible for a cluster set + operationId: ocm_IsAutoUpdatePossible + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + responses: + '200': + description: Whether auto-update is possible. + content: + application/json: + schema: + type: object + properties: + possible: + type: boolean + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/sync-status/all-features: + get: + tags: + - Multi-cluster (OCM) + summary: Get sync status of all features in a cluster set + operationId: ocm_AllFeaturesSyncStatus + description: Returns a nested map of feature set to feature to sync status (in-sync and unaligned + cluster names). + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + responses: + '200': + description: Nested feature-set / feature sync status map. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/sync-status/opscenter-features-version: + get: + tags: + - Multi-cluster (OCM) + summary: Get opscenter-features version sync status for a cluster set + operationId: ocm_OpscenterFeaturesVersionSyncStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + responses: + '200': + description: Cluster set opscenter-features version and per-cluster version list. + content: + application/json: + schema: + type: object + properties: + clusterSetVersion: + type: string + clusters: + type: array + items: + $ref: '#/components/schemas/versionObj' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/clustersets/{clusterset}/sync-status/{feature}: + get: + tags: + - Multi-cluster (OCM) + summary: Get sync status of a single feature in a cluster set + operationId: ocm_FeatureSyncStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: clusterset + in: path + required: true + description: Cluster set name. + schema: + type: string + - name: feature + in: path + required: true + description: Feature name. + schema: + type: string + responses: + '200': + description: In-sync and out-of-sync cluster names for the feature. + content: + application/json: + schema: + type: object + properties: + insyncClusters: + type: array + items: + type: string + outOfSyncClusters: + type: array + items: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/bound-namespaces: + get: + tags: + - Multi-cluster (OCM) + summary: List namespaces and their bound cluster sets + operationId: ocm_GetBoundNamespaces + description: Returns a map of namespace name to the list of cluster sets bound to that namespace. + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: Map of namespace name to bound cluster set names. + content: + application/json: + schema: + type: object + additionalProperties: + type: array + items: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/bound-namespaces/bind: + post: + tags: + - Multi-cluster (OCM) + summary: Bind a namespace to a cluster set + operationId: ocm_BindNamespaceWithClusterSet + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BindNamespaceOptions' + responses: + '200': + description: Namespace bound to the cluster set. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/bound-namespaces/unbind: + post: + tags: + - Multi-cluster (OCM) + summary: Unbind a namespace from a cluster set + operationId: ocm_UnBindNamespaceWithClusterSet + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BindNamespaceOptions' + responses: + '200': + description: Namespace unbound from the cluster set. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/spoke-command: + post: + tags: + - Multi-cluster (OCM) + summary: Generate the spoke cluster install command + operationId: ocm_GenerateSpokeInstallCommand + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterOptions' + responses: + '200': + description: The generated spoke install command. + content: + application/json: + schema: + type: object + properties: + spoke: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/import-spoke: + post: + tags: + - Multi-cluster (OCM) + summary: Accept and import a spoke cluster + operationId: ocm_AcceptAndImportCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ImportOptions' + responses: + '200': + description: Cluster import by OCM submitted. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/convert/spoke: + post: + tags: + - Multi-cluster (OCM) + summary: Convert a cluster to a spoke cluster + operationId: ocm_ConvertToSpokeCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ImportOptions' + responses: + '200': + description: Cluster converted to a spoke cluster. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/remove-managed-cluster: + post: + tags: + - Multi-cluster (OCM) + summary: Remove a managed cluster (uninstall the spoke agent) + operationId: ocm_RemoveManagedCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RemoveClusterOptions' + responses: + '200': + description: Managed cluster removed. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/sync-accounts: + post: + tags: + - Multi-cluster (OCM) + summary: Sync account objects (users/groups) to the hub cluster + operationId: ocm_SyncAccountObjects + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: Account objects synced. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/users: + get: + tags: + - Multi-cluster (OCM) + summary: List OCM users on the hub cluster + operationId: ocm_GetUserList + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: List of OCM users. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/user/create: + post: + tags: + - Multi-cluster (OCM) + summary: Create an OCM user with cluster/cluster-set permissions + operationId: ocm_CreateOCMUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UserOptions' + responses: + '200': + description: OCM user created. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/user/{id}: + get: + tags: + - Multi-cluster (OCM) + summary: Get an OCM user's permissions + operationId: ocm_GetUserInfo + description: Returns the user's cluster and cluster-set permissions. The two maps marshal with capitalized + Go field names (ClusterPermissions / ClusterSetPermissions). + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: OCM user ID. + schema: + type: integer + format: int64 + responses: + '200': + description: The user's permissions. + content: + application/json: + schema: + $ref: '#/components/schemas/UserPermissions' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /clusters/{owner}/{cluster}/user/{id}/access: + get: + tags: + - Multi-cluster (OCM) + summary: List clusters/namespaces accessible to an OCM user + operationId: ocm_GetAccessibleClusterList + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: OCM user ID. + schema: + type: integer + format: int64 + responses: + '200': + description: Sorted list of accessible cluster/namespace names. + content: + application/json: + schema: + type: array + items: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /clusters/{owner}/{cluster}/user/{id}/{spokeName}/kubeconfig: + get: + tags: + - Multi-cluster (OCM) + summary: Get an OCM user's kubeconfig for a spoke cluster + operationId: ocm_GetUserKubeConfig + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: OCM user ID. + schema: + type: integer + format: int64 + - name: spokeName + in: path + required: true + description: Spoke cluster name. + schema: + type: string + responses: + '200': + description: The kubeconfig (YAML) as a JSON-encoded string. + content: + application/json: + schema: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /clusters/{owner}/{cluster}/user/{id}/remove: + post: + tags: + - Multi-cluster (OCM) + summary: Remove specific permissions from an OCM user + operationId: ocm_RemoveOCMUserPermission + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: OCM user ID. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RemovePermissionOpts' + responses: + '200': + description: Permissions removed from the user. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/user/{id}/update: + post: + tags: + - Multi-cluster (OCM) + summary: Update an OCM user's permissions + operationId: ocm_UpdateOCMUserPermission + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: OCM user ID. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UserOptions' + responses: + '200': + description: User permissions updated. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/user/{id}/delete: + delete: + tags: + - Multi-cluster (OCM) + summary: Delete an OCM user + operationId: ocm_RemoveOCMUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: OCM user ID. + schema: + type: integer + format: int64 + responses: + '200': + description: OCM user deleted. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /clusters/{owner}/{cluster}/permission/users: + get: + tags: + - Client Organizations + summary: List users of a client organization + description: Returns the list of users belonging to the client organization (`owner`) that have + been granted access on this cluster. Requires a valid token and that `owner` resolves to a client + organization (`reqClientOrg`). + operationId: clientOrg_ListUsers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + responses: + '200': + description: The list of users of the client organization. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /clusters/{owner}/{cluster}/permission/user/create: + post: + tags: + - Client Organizations + summary: Create a client-org user and assign permissions + description: Creates an OCM user for the client organization (`owner`) on this cluster and assigns + the requested permissions (creating the necessary RBAC role/cluster-role bindings and importing/connecting + clusters for the user). Requires organization-admin authorization on `owner` (`Organization_Admin`). + operationId: clientOrg_CreateUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UserOptions' + responses: + '200': + description: The user was created and permissions were assigned. + '400': + description: Invalid permission options for the client organization. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/permission/user/{id}: + post: + tags: + - Client Organizations + summary: Get a client-org user's permissions on a cluster + description: Returns the roles and cluster-roles assigned to the client-org user (`id`) on this + cluster, scoped to the namespaces supplied in the request body. Requires organization-admin authorization + on `owner`. + operationId: clientOrg_GetUserInfo + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: Numeric ID of the user. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PermissionScopes' + responses: + '200': + description: The user's permissions on the cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/ClientOrgUserPermission' + '400': + description: The user is not part of the client organization. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/permission/user/{id}/kubeconfig: + get: + tags: + - Client Organizations + summary: Get a kubeconfig for a client-org user + description: Generates a kubeconfig for the client-org user (`id`) to access this cluster, provided + the user has permission in the client organization's cluster. Requires organization-admin authorization + on `owner`. + operationId: clientOrg_GetUserKubeConfig + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: Numeric ID of the user. + schema: + type: integer + format: int64 + responses: + '200': + description: The generated kubeconfig (YAML document as a JSON string). + content: + application/json: + schema: + type: string + '400': + description: The user does not have permission in the client-org cluster. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /clusters/{owner}/{cluster}/permission/user/{id}/remove: + post: + tags: + - Client Organizations + summary: Remove specific permissions from a client-org user + description: Deletes the named cluster-scoped and namespace-scoped RBAC bindings for the client-org + user (`id`) on this cluster. Requires organization-admin authorization on `owner`. + operationId: clientOrg_RemoveUserPermission + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: Numeric ID of the user. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RemovePermissionOpts' + responses: + '200': + description: The specified permissions were removed. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/permission/user/{id}/update: + post: + tags: + - Client Organizations + summary: Update a client-org user's permissions + description: Re-assigns permissions for the client-org user on this cluster. Requires organization-admin + authorization on `owner`. + operationId: clientOrg_UpdateUserPermission + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: Numeric ID of the user. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UserOptions' + responses: + '200': + description: The user's permissions were updated. + '400': + description: Invalid permission options for the client organization. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + '422': + $ref: '#/components/responses/ValidationError' + /clusters/{owner}/{cluster}/permission/user/{id}/delete: + delete: + tags: + - Client Organizations + summary: Remove a client-org user + description: 'Removes the client-org user (`id`) entirely from this cluster: strips the hub-owner + and client-org annotations and deletes all associated RBAC role and cluster-role bindings. Requires + organization-admin authorization on `owner`.' + operationId: clientOrg_DeleteUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - $ref: '#/components/parameters/clusterParam' + - name: id + in: path + required: true + description: Numeric ID of the user. + schema: + type: integer + format: int64 + responses: + '200': + description: The user was removed from the cluster. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /user/clients: + get: + tags: + - Client Organizations + summary: List client organizations + description: Returns all client organizations known to the platform. Site-admin only (`Organization_SiteAdminCanViewClientOrg`); + the caller must be acting within an organization (`reqMustFromOrg`). + operationId: clientOrg_List + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: The list of client organizations. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Organization' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/client/{id}: + get: + tags: + - Client Organizations + summary: Get a client organization + description: Returns a single client organization by its numeric ID. Site-admin only (`Organization_SiteAdminCanViewClientOrg`). + operationId: clientOrg_Get + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + description: Numeric ID of the client organization. + schema: + type: integer + format: int64 + responses: + '200': + description: The client organization. + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /user/client/create: + post: + tags: + - Client Organizations + summary: Create a client organization + description: Creates a client organization, provisions the org admin user, grants permission on + the hub cluster, and imports the requested spoke cluster(s) with the client org as owner. Site-admin + only (`Organization_SiteAdminCanCreateClientOrg`). + operationId: clientOrg_Create + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClientOrgParams' + responses: + '200': + description: The client organization was created. + '400': + description: Invalid parameters (e.g. missing Rancher management cluster endpoint). + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '409': + description: An organization with the same name already exists. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '422': + $ref: '#/components/responses/ValidationError' + /user/client/{orgname}/add-cluster: + post: + tags: + - Client Organizations + summary: Add a cluster to a client organization + description: Imports an additional spoke cluster into the client organization (`orgname`), granting + the org admins access and setting up the associated namespaces/gateway presets and telemetry. + Site-admin only (`Organization_SiteAdminCanAddClusterToClientOrg`). + operationId: clientOrg_AddCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AddClusterParams' + responses: + '200': + description: The cluster was added to the client organization. + '400': + description: The cluster is already imported for this organization. + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/client/{orgname}/delete-cluster: + post: + tags: + - Client Organizations + summary: Remove a cluster from a client organization + description: Removes a spoke cluster from the client organization (`orgname`), cleaning up the client-org + namespace and associated hub/spoke resources. Site-admin only (`Organization_SiteAdminCanRemoveClusterFromClientOrg`). + operationId: clientOrg_RemoveCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RemoveClusterParams' + responses: + '200': + description: The cluster removal was accepted (cleanup runs asynchronously). + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '422': + $ref: '#/components/responses/ValidationError' + /user/client/{orgname}/cluster/{cluster}/status: + get: + tags: + - Client Organizations + summary: Get a client-org cluster's status + description: Returns the deletion/active status of a single cluster within the client organization + (`orgname`). Site-admin only (`Organization_SiteAdminCanViewClientOrg`). + operationId: clientOrg_GetClusterStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + - name: cluster + in: path + required: true + description: Cluster name within the client organization. + schema: + type: string + responses: + '200': + description: The cluster status. + content: + application/json: + schema: + $ref: '#/components/schemas/ClientOrgStatus' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/client/{orgname}/status: + get: + tags: + - Client Organizations + summary: Get a client organization's aggregate status + description: Returns the aggregate deletion/active status across all clusters of the client organization + (`orgname`). Site-admin only (`Organization_SiteAdminCanViewClientOrg`). + operationId: clientOrg_GetStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: The aggregate status of the client organization. + content: + application/json: + schema: + $ref: '#/components/schemas/ClientOrgStatus' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /user/client/delete/{id}: + delete: + tags: + - Client Organizations + summary: Delete a client organization + description: Deletes the client organization (`id`), tearing down its namespaces and cluster resources + across all spoke clusters. Deletion is rejected if another organization still references this + client org's gateway config. Site-admin only (`Organization_SiteAdminCanDeleteClientOrg`). + operationId: clientOrg_Delete + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: id + in: path + required: true + description: Numeric ID of the client organization. + schema: + type: integer + format: int64 + responses: + '200': + description: The deletion was accepted (teardown runs asynchronously). + '400': + description: The client organization cannot be deleted because another organization is using + resources from it. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /clouds: + get: + tags: + - Cloud Providers + summary: List supported cloud providers + description: Returns the list of cloud providers supported by the platform for cluster provisioning + and discovery. This endpoint is public and requires no authentication. + operationId: clouds_ListClouds + security: [] + parameters: [] + responses: + '200': + description: List of supported cloud providers + content: + application/json: + schema: + $ref: '#/components/schemas/CloudProviderList' + /clouds/{owner}/{provider}/cluster: + post: + tags: + - Cloud Providers + summary: Provision a managed (CAPI) cluster on a cloud provider + description: Provisions a new Cluster API (CAPI) based cluster on the given cloud provider and imports + it into the platform. Requires a valid authentication token and stored cloud credentials for the + referenced provider. The `provider` path parameter selects the target cloud provider (e.g. `kubevirt`); + for `kubevirt` the CAPI cluster config is validated (worker pools, machine count, cpu, memory + are required). An optional `response-id` query parameter correlates the async provisioning response. + operationId: clouds_ProvisionClusterCommand + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: provider + in: path + required: true + description: Target cloud provider name (e.g. gke, aks, eks, kubevirt). + schema: + type: string + - name: response-id + in: query + required: false + description: Correlation id for the asynchronous provisioning response. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterProvisionConfig' + responses: + '200': + description: Provider options for the provisioned cluster + content: + application/json: + schema: + $ref: '#/components/schemas/ProviderOptions' + '400': + description: Invalid CAPI cluster config (e.g. missing worker pools) + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + '422': + description: Unprocessable entity - request body failed validation + /clouds/{owner}/providers/gke/projects: + get: + tags: + - Cloud Providers + summary: List GKE projects + description: Lists Google Cloud projects accessible with the stored GKE credentials. Requires a + valid authentication token and stored cloud credentials. + operationId: clouds_GetGKEProjects + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of GKE project names + content: + application/json: + schema: + type: array + items: + type: string + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/gke/projects/{project}/regions/: + get: + tags: + - Cloud Providers + summary: List GKE regions + description: Lists available regions (with zones) for the given GKE project. Requires a valid authentication + token and stored cloud credentials. + operationId: clouds_GetGKERegions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: project + in: path + required: true + description: GKE project id. + schema: + type: string + responses: + '200': + description: List of regions and their zones + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Locations' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/gke/projects/{project}/regions/{region}/kubernetesversions: + get: + tags: + - Cloud Providers + summary: List GKE Kubernetes versions + description: Lists the supported Kubernetes versions for the given GKE project and region. Requires + a valid authentication token and stored cloud credentials. + operationId: clouds_GetGKEKubernetesVersions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: project + in: path + required: true + description: GKE project id. + schema: + type: string + - name: region + in: path + required: true + description: GKE region. + schema: + type: string + responses: + '200': + description: List of supported Kubernetes versions + content: + application/json: + schema: + type: array + items: + type: string + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/gke/projects/{project}/regions/{region}/vms: + get: + tags: + - Cloud Providers + summary: List GKE machine types (VMs) + description: Lists available machine types for the given GKE project, region and zone, grouped by + family. The `zone` query parameter is required (e.g. `zone=us-east1-b`). Requires a valid authentication + token and stored cloud credentials. + operationId: clouds_GetGKEVMs + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: project + in: path + required: true + description: GKE project id. + schema: + type: string + - name: region + in: path + required: true + description: GKE region. + schema: + type: string + - name: zone + in: query + required: true + description: GKE zone (e.g. us-east1-b). + schema: + type: string + responses: + '200': + description: Machine types grouped by family + content: + application/json: + schema: + type: object + additionalProperties: + type: array + items: + $ref: '#/components/schemas/VMInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/gke/projects/{project}/clusters: + get: + tags: + - Cloud Providers + summary: List GKE clusters in a project + description: Lists the GKE clusters that exist in the given project. Requires a valid authentication + token and stored cloud credentials. + operationId: clouds_GetGKEProjectClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: project + in: path + required: true + description: GKE project id. + schema: + type: string + responses: + '200': + description: List of GKE clusters + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/gke/projects/{project}/clusters/{cluster}: + get: + tags: + - Cloud Providers + summary: Get GKE cluster info + description: 'Returns detailed information for a single GKE cluster (for import). The `location` + query parameter identifies the cluster location. Requires a valid authentication token and stored + cloud credentials. Note: the response is serialized from the internal `models.ClusterInfo` type, + which shares the same JSON shape as ClusterInfo.' + operationId: clouds_GetGKEClusterInfo + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: project + in: path + required: true + description: GKE project id. + schema: + type: string + - name: cluster + in: path + required: true + description: GKE cluster name. + schema: + type: string + - name: location + in: query + required: false + description: GKE cluster location. + schema: + type: string + responses: + '200': + description: GKE cluster info + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + '404': + description: Cluster not found + '409': + description: Cluster already exists (import conflict) + /clouds/{owner}/providers/aks/regions/: + get: + tags: + - Cloud Providers + summary: List AKS regions + description: Lists the supported Azure (AKS) regions. Requires a valid authentication token and + stored cloud credentials. + operationId: clouds_GetAKSRegions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of AKS regions + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Locations' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/aks/regions/{region}/vms: + get: + tags: + - Cloud Providers + summary: List AKS machine types (VMs) + description: Lists available machine types for the given AKS region, grouped by family. The `zones` + query parameter is required (comma-separated, e.g. `zones=1,2,3`). Requires a valid authentication + token and stored cloud credentials. + operationId: clouds_GetAKSVMs + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: region + in: path + required: true + description: AKS region. + schema: + type: string + - name: zones + in: query + required: true + description: Comma-separated availability zones (e.g. 1,2,3). + schema: + type: string + responses: + '200': + description: Machine types grouped by family + content: + application/json: + schema: + type: object + additionalProperties: + type: array + items: + $ref: '#/components/schemas/VMInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/aks/regions/{region}/kubernetesversions: + get: + tags: + - Cloud Providers + summary: List AKS Kubernetes versions + description: Lists the supported Kubernetes versions for the given AKS region. Requires a valid + authentication token and stored cloud credentials. + operationId: clouds_GetAKSKubernetesVersions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: region + in: path + required: true + description: AKS region. + schema: + type: string + responses: + '200': + description: List of supported Kubernetes versions + content: + application/json: + schema: + type: array + items: + type: string + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/aks/resourcegroups: + get: + tags: + - Cloud Providers + summary: List Azure resource groups + description: Lists the Azure resource groups accessible with the stored AKS credentials. Requires + a valid authentication token and stored cloud credentials. + operationId: clouds_GetAzureResourceGroups + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of Azure resource group names + content: + application/json: + schema: + type: array + items: + type: string + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/aks/resourcegroups/{resourcegroup}/clusters: + get: + tags: + - Cloud Providers + summary: List AKS clusters in a resource group + description: Lists the AKS managed clusters in the given Azure resource group. Requires a valid + authentication token and stored cloud credentials. + operationId: clouds_GetAzureClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: resourcegroup + in: path + required: true + description: Azure resource group name. + schema: + type: string + responses: + '200': + description: List of AKS clusters + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/aks/resourcegroups/{resourcegroup}/clusters/{cluster}: + get: + tags: + - Cloud Providers + summary: Get AKS cluster info + description: 'Returns detailed information for a single AKS cluster (for import). Requires a valid + authentication token and stored cloud credentials. Note: the response is serialized from the internal + `models.ClusterInfo` type, which shares the same JSON shape as ClusterInfo.' + operationId: clouds_GetAzureClusterInfo + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: resourcegroup + in: path + required: true + description: Azure resource group name. + schema: + type: string + - name: cluster + in: path + required: true + description: AKS cluster name. + schema: + type: string + responses: + '200': + description: AKS cluster info + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + '404': + description: Cluster not found + '409': + description: Cluster already exists (import conflict) + /clouds/{owner}/providers/eks/regions: + get: + tags: + - Cloud Providers + summary: List EKS regions + description: Lists the supported AWS (EKS) regions. If no credential is stored, a default credential + is used. Requires a valid authentication token and stored cloud credentials. + operationId: clouds_GetAWSRegions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of EKS regions + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Locations' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/eks/regions/{region}/kubernetesversions: + get: + tags: + - Cloud Providers + summary: List EKS Kubernetes versions + description: Lists the supported Kubernetes versions for EKS. Requires a valid authentication token + and stored cloud credentials. + operationId: clouds_GetAWSKubernetesVersions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: region + in: path + required: true + description: EKS region. + schema: + type: string + responses: + '200': + description: List of supported Kubernetes versions + content: + application/json: + schema: + type: array + items: + type: string + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/eks/regions/{region}/vms: + get: + tags: + - Cloud Providers + summary: List EKS machine types (VMs) + description: Lists available machine types for the given EKS region, grouped by family. Requires + a valid authentication token and stored cloud credentials. + operationId: clouds_GetAWSVMs + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: region + in: path + required: true + description: EKS region. + schema: + type: string + responses: + '200': + description: Machine types grouped by family + content: + application/json: + schema: + type: object + additionalProperties: + type: array + items: + $ref: '#/components/schemas/VMInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/eks/regions/{region}/clusters: + get: + tags: + - Cloud Providers + summary: List EKS clusters in a region + description: Lists the EKS clusters in the given AWS region. Requires a valid authentication token + and stored cloud credentials. + operationId: clouds_GetAWSClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: region + in: path + required: true + description: EKS region. + schema: + type: string + responses: + '200': + description: List of EKS clusters + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/eks/regions/{region}/clusters/{cluster}: + get: + tags: + - Cloud Providers + summary: Get EKS cluster info + description: 'Returns detailed information for a single EKS cluster (for import). Requires a valid + authentication token and stored cloud credentials. Note: the response is serialized from the internal + `models.ClusterInfo` type, which shares the same JSON shape as ClusterInfo.' + operationId: clouds_GetAWSClusterInfo + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: region + in: path + required: true + description: EKS region. + schema: + type: string + - name: cluster + in: path + required: true + description: EKS cluster name. + schema: + type: string + responses: + '200': + description: EKS cluster info + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + '404': + description: Cluster not found + '409': + description: Cluster already exists (import conflict) + /clouds/{owner}/providers/digitalocean/clusters: + get: + tags: + - Cloud Providers + summary: List DigitalOcean clusters + description: Lists the DigitalOcean managed Kubernetes (DOKS) clusters. Requires a valid authentication + token and stored cloud credentials. + operationId: clouds_GetDigitalOceanClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of DigitalOcean clusters + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/digitalocean/clusters/{id}: + get: + tags: + - Cloud Providers + summary: Get DigitalOcean cluster info + description: 'Returns detailed information for a single DigitalOcean cluster (for import). Requires + a valid authentication token and stored cloud credentials. Note: the response is serialized from + the internal `models.ClusterInfo` type, which shares the same JSON shape as ClusterInfo.' + operationId: clouds_GetDigitalOceanClusterInfo + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: id + in: path + required: true + description: DigitalOcean cluster id. + schema: + type: string + responses: + '200': + description: DigitalOcean cluster info + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + '404': + description: Cluster not found + '409': + description: Cluster already exists (import conflict) + /clouds/{owner}/providers/linode/clusters: + get: + tags: + - Cloud Providers + summary: List Linode (LKE) clusters + description: Lists the Linode Kubernetes Engine (LKE) clusters. Requires a valid authentication + token and stored cloud credentials. + operationId: clouds_GetLinodeClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of Linode clusters + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/linode/clusters/{id}: + get: + tags: + - Cloud Providers + summary: Get Linode (LKE) cluster info + description: 'Returns detailed information for a single Linode cluster (for import). The `id` path + parameter is the numeric LKE cluster id. Requires a valid authentication token and stored cloud + credentials. Note: the response is serialized from the internal `models.ClusterInfo` type, which + shares the same JSON shape as ClusterInfo.' + operationId: clouds_GetLinodeClusterInfo + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: id + in: path + required: true + description: Linode (LKE) cluster id. + schema: + type: integer + format: int64 + responses: + '200': + description: Linode cluster info + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + '404': + description: Cluster not found + '409': + description: Cluster already exists (import conflict) + /clouds/{owner}/providers/rancher/clusters/: + get: + tags: + - Cloud Providers + summary: List Rancher managed clusters + description: Lists the clusters managed by the configured Rancher server. Requires a valid authentication + token, stored cloud credentials, and a configured Rancher client. + operationId: clouds_GetRancherClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of Rancher clusters + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/rancher/clusters/{id}: + get: + tags: + - Cloud Providers + summary: Get Rancher cluster info + description: 'Returns detailed information for a single Rancher managed cluster (for import). Requires + a valid authentication token, stored cloud credentials, and a configured Rancher client. Note: + the response is serialized from the internal `models.ClusterInfo` type, which shares the same + JSON shape as ClusterInfo.' + operationId: clouds_GetRancherClusterInfo + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: id + in: path + required: true + description: Rancher cluster id. + schema: + type: string + responses: + '200': + description: Rancher cluster info + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + '404': + description: Cluster not found + '409': + description: Cluster already exists (import conflict) + /clouds/{owner}/providers/hetzner/servers: + get: + tags: + - Cloud Providers + summary: List all Hetzner server types + description: Lists all Hetzner Cloud server types (machine types). Requires a valid authentication + token and stored cloud credentials. + operationId: clouds_GetHetznerAllServerTypes + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of Hetzner server types + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/VMInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/hetzner/kubernetesversions: + get: + tags: + - Cloud Providers + summary: List Hetzner Kubernetes versions + description: Lists the supported Kubernetes versions for Hetzner. Requires a valid authentication + token and stored cloud credentials. + operationId: clouds_GetHetznerKubernetesVersions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of supported Kubernetes versions + content: + application/json: + schema: + type: array + items: + type: string + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/hetzner/regions/: + get: + tags: + - Cloud Providers + summary: List Hetzner regions + description: Lists the available Hetzner Cloud regions (locations). Requires a valid authentication + token and stored cloud credentials. + operationId: clouds_GetHetznerRegions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of Hetzner regions + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Locations' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/hetzner/regions/{region}/servers: + get: + tags: + - Cloud Providers + summary: List Hetzner server types for a region + description: Lists the Hetzner Cloud server types available in the given region. Requires a valid + authentication token and stored cloud credentials. + operationId: clouds_GetHetznerServerTypes + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: region + in: path + required: true + description: Hetzner region (location). + schema: + type: string + responses: + '200': + description: List of Hetzner server types + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/VMInfo' + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /clouds/{owner}/providers/kubevirt/kubernetesversions: + get: + tags: + - Cloud Providers + summary: List KubeVirt Kubernetes versions + description: Lists the supported Kubernetes versions for KubeVirt-based clusters. Requires a valid + authentication token and stored cloud credentials. + operationId: clouds_GetKubeVirtKubernetesVersions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + responses: + '200': + description: List of supported Kubernetes versions + content: + application/json: + schema: + type: array + items: + type: string + '401': + description: Unauthorized - missing or invalid authentication token + '403': + description: Forbidden - insufficient permissions + /ace-installer/schema.json: + get: + tags: + - ACE Installer + summary: Serve the ACE options OpenAPI v3 JSON schema + description: Returns the raw OpenAPI v3 JSON schema for ACE installer options (ace-options/values.openapiv3_schema.yaml) + as a dynamic JSON object. The ace-installer APIs are AppsCode-hosted only. Requires an org resolved + from the `org` query param. + operationId: installer_ServeACESchema + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Raw OpenAPI v3 JSON schema. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Not permitted. + '500': + description: Internal server error. + /ace-installer/model.json: + get: + tags: + - ACE Installer + summary: Serve default ACE installer options + description: Returns the default ACE options model (AceOptionsSpec) pre-filled with the requesting + user's admin details. The response is a complex Kubernetes-style options object returned as dynamic + JSON. The ace-installer APIs are AppsCode-hosted only. + operationId: installer_ServeDefaultOptions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Default AceOptionsSpec options object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Not permitted. + /ace-installer/generate: + post: + tags: + - ACE Installer + summary: Generate a new ACE installer + description: Generates a new ACE installer from the supplied AceOptionsSpec options and returns + the resulting installer metadata. The request body is a free-form AceOptionsSpec object (bound + as a dynamic JSON map, then decoded into AceOptionsSpec). The ace-installer APIs are AppsCode-hosted + only. Requires the `create_installers` authorization (Organization_HostedModeCanCreateInstallers). + operationId: installer_GenerateInstaller + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Generated installer metadata. + content: + application/json: + schema: + $ref: '#/components/schemas/InstallerMetadata' + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `create_installers` authorization. + '422': + description: Unprocessable entity. Invalid request body. + '500': + description: Internal server error. + /ace-installer/import: + post: + tags: + - ACE Installer + summary: Import an existing ACE installer + description: Imports an existing installer described by the supplied AceOptionsSpec options and + returns the resulting installer metadata. The request body is a free-form AceOptionsSpec object + (bound as a dynamic JSON map, then decoded into AceOptionsSpec). The ace-installer APIs are AppsCode-hosted + only. Requires the `import_installers` authorization (Organization_HostedModeCanImportInstallers). + operationId: installer_ImportInstaller + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Imported installer metadata. + content: + application/json: + schema: + $ref: '#/components/schemas/InstallerMetadata' + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `import_installers` authorization. + '422': + description: Unprocessable entity. Invalid request body. + '500': + description: Internal server error. + /ace-installer/installer-meta: + get: + tags: + - ACE Installer + summary: Get installer metadata for the current access token + description: Returns the installer metadata associated with the access token used to authenticate + the request. The ace-installer APIs are AppsCode-hosted only. Requires the `view_installers` authorization + (Organization_HostedModeCanViewInstallers). + operationId: installer_GetInstallerMetadata + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Installer metadata. + content: + application/json: + schema: + $ref: '#/components/schemas/InstallerMetadata' + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `view_installers` authorization. + '500': + description: Internal server error. + /ace-installer/latest-version: + get: + tags: + - ACE Installer + summary: Get the latest ACE installer version + description: Returns the latest available ACE installer chart version. The ace-installer APIs are + AppsCode-hosted only. Requires the `view_installers` authorization (Organization_HostedModeCanViewInstallers). + operationId: installer_GetAceLatestInstallerVersion + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Latest installer version. + content: + application/json: + schema: + type: object + properties: + version: + type: string + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `view_installers` authorization. + /ace-installer/installers/: + get: + tags: + - ACE Installer + summary: List installers grouped by name + description: Lists the installers for the owner organization, grouped by installer name (one metadata + entry per group). The ace-installer APIs are AppsCode-hosted only. Requires the `view_installers` + authorization (Organization_HostedModeCanViewInstallers). + operationId: installer_ListInstallers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of installer metadata grouped by name. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/InstallerMetadata' + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `view_installers` authorization. + '500': + description: Internal server error. + /ace-installer/installers/{name}: + get: + tags: + - ACE Installer + summary: List generated installers for an installer name + description: Lists all generated installers matching the given installer name for the owner organization. + The ace-installer APIs are AppsCode-hosted only. Requires the `view_installers` authorization + (Organization_HostedModeCanViewInstallers). + operationId: installer_ListGeneratedInstallers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: name + in: path + required: true + description: Installer name. + schema: + type: string + responses: + '200': + description: List of generated installer metadata. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/InstallerMetadata' + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `view_installers` authorization. + '404': + description: Not found. + '500': + description: Internal server error. + /ace-installer/installers/{name}/{id}: + get: + tags: + - ACE Installer + summary: Get installer details + description: Returns detailed metadata for a single generated installer, including readme and archive + download URLs. May return 428 Precondition Required (redirect) when a marketplace installer is + not yet in a bound phase. The ace-installer APIs are AppsCode-hosted only. Requires the `view_installers` + authorization (Organization_HostedModeCanViewInstallers). + operationId: installer_GetInstallerDetails + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: name + in: path + required: true + description: Installer name. + schema: + type: string + - name: id + in: path + required: true + description: Installer ID. + schema: + type: string + responses: + '200': + description: Installer details. + content: + application/json: + schema: + $ref: '#/components/schemas/InstallerDetails' + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `view_installers` authorization. + '404': + description: Installer not found. + '428': + description: Precondition Required. Marketplace installer not yet bound; a redirect to the marketplace + URL is returned. + '500': + description: Internal server error. + delete: + tags: + - ACE Installer + summary: Delete a generated installer + description: Deletes a generated installer by ID. Installers owned by a marketplace organization + cannot be deleted. The ace-installer APIs are AppsCode-hosted only. Requires the `delete_installers` + authorization (Organization_HostedModeCanDeleteInstallers). + operationId: installer_DeleteGeneratedInstaller + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: name + in: path + required: true + description: Installer name. + schema: + type: string + - name: id + in: path + required: true + description: Installer ID. + schema: + type: string + responses: + '200': + description: Installer deleted. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `delete_installers` authorization, or the installer belongs + to a marketplace organization. + '500': + description: Internal server error. + /ace-installer/installers/{name}/{id}/reconfigure: + post: + tags: + - ACE Installer + summary: Reconfigure a generated installer + description: Reconfigures an existing installer using the supplied AceOptionsSpec options. The `installerOps` + query parameter selects the operation (`reconfigure` or `promote-to-prod`). The request body is + a free-form AceOptionsSpec object (bound as a dynamic JSON map, then decoded into AceOptionsSpec). + The ace-installer APIs are AppsCode-hosted only. Requires the `reconfigure_installers` authorization + (Organization_HostedModeCanReconfigureInstallers). + operationId: installer_ReconfigureInstaller + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: name + in: path + required: true + description: Installer name. + schema: + type: string + - name: id + in: path + required: true + description: Installer ID. + schema: + type: string + - name: installerOps + in: query + required: true + description: Operation to perform (`reconfigure` or `promote-to-prod`). + schema: + type: string + enum: + - reconfigure + - promote-to-prod + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + responses: + '200': + description: Reconfigured installer metadata. + content: + application/json: + schema: + $ref: '#/components/schemas/InstallerMetadata' + '400': + description: Bad request. Invalid installerOps or installer mismatch. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `reconfigure_installers` authorization. + '422': + description: Unprocessable entity. Invalid request body. + '500': + description: Internal server error. + /ace-installer/installers/{name}/{id}/upgrade: + post: + tags: + - ACE Installer + summary: Upgrade a generated installer + description: Upgrades an existing installer to the latest ACE installer version and returns the + updated installer metadata. The ace-installer APIs are AppsCode-hosted only. Requires the `upgrade_installers` + authorization (Organization_HostedModeCanUpgradeInstallers). + operationId: installer_UpgradeInstaller + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: name + in: path + required: true + description: Installer name. + schema: + type: string + - name: id + in: path + required: true + description: Installer ID. + schema: + type: string + responses: + '200': + description: Upgraded installer metadata. + content: + application/json: + schema: + $ref: '#/components/schemas/InstallerMetadata' + '400': + description: Bad request. Installer not found. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `upgrade_installers` authorization. + '500': + description: Internal server error. + /ace-installer/installers/{name}/{id}/versions: + get: + tags: + - ACE Installer + summary: List installer versions + description: Lists the available versions (archives) for a generated installer. The ace-installer + APIs are AppsCode-hosted only. Requires the `view_installers` authorization (Organization_HostedModeCanViewInstallers). + operationId: installer_ListInstallerVersions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: name + in: path + required: true + description: Installer name. + schema: + type: string + - name: id + in: path + required: true + description: Installer ID. + schema: + type: string + responses: + '200': + description: List of installer versions. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/InstallerVersion' + '400': + description: Bad request. Installer not found. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `view_installers` authorization. + '500': + description: Internal server error. + /ace-installer/installers/{name}/{id}/archives/{archiveName}: + get: + tags: + - ACE Installer + summary: Get installer details from a tar archive + description: Extracts and returns installer details (readme, archive URL) from the specified tar + archive of a generated installer. The ace-installer APIs are AppsCode-hosted only. Requires the + `download_installers` authorization (Organization_HostedModeCanDownloadInstallers). + operationId: installer_GetInstallerDetailsFromTarArchive + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: name + in: path + required: true + description: Installer name. + schema: + type: string + - name: id + in: path + required: true + description: Installer ID. + schema: + type: string + - name: archiveName + in: path + required: true + description: Archive file name. + schema: + type: string + responses: + '200': + description: Installer details extracted from the tar archive. + content: + application/json: + schema: + $ref: '#/components/schemas/InstallerDetails' + '400': + description: Bad request. Installer not found. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `download_installers` authorization. + '500': + description: Internal server error. + /ace-installer/installers/{name}/{id}/model.json: + get: + tags: + - ACE Installer + summary: Serve installer options + description: Returns the stored AceOptionsSpec options for a generated installer. When `configureProductionOptions=true`, + options are adjusted for a self-hosted production deployment. The response is a complex Kubernetes-style + options object returned as dynamic JSON. The ace-installer APIs are AppsCode-hosted only. Requires + the `create_installers` authorization (Organization_HostedModeCanCreateInstallers). + operationId: installer_ServeInstallerOptions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: name + in: path + required: true + description: Installer name. + schema: + type: string + - name: id + in: path + required: true + description: Installer ID. + schema: + type: string + - name: configureProductionOptions + in: query + required: false + description: When true, adjust options for a production deployment. + schema: + type: boolean + responses: + '200': + description: AceOptionsSpec options object for the installer. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `create_installers` authorization. + '500': + description: Internal server error. + /ace-installer/deployment/marketplace/installers/{installerID}/status: + get: + tags: + - ACE Installer + summary: Get marketplace installer status + description: Returns the marketplace subscription status (`Pending` or `Bound`) for a marketplace-type + installer, along with its metadata, download link, and expiry state. When `redirect=true` and + the installer is bound, a redirect to the self-host URL is returned. The ace-installer APIs are + AppsCode-hosted only. This route does not carry an additional installer-specific authorization + check beyond the base org token/authz. + operationId: installer_GetMarketplaceInstallerStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: installerID + in: path + required: true + description: Installer ID. + schema: + type: string + - name: redirect + in: query + required: false + description: When true and installer is bound, redirect to the self-host URL. + schema: + type: boolean + responses: + '200': + description: Marketplace installer status. + content: + application/json: + schema: + $ref: '#/components/schemas/MarketplaceInstallerStatus' + '400': + description: Bad request. Installer not found or not a marketplace deployment type. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Not permitted. + '428': + description: Precondition Required. When bound and redirect requested, a redirect to the self-host + URL is returned. + '500': + description: Internal server error. + /upgrade: + get: + tags: + - ACE Upgrade + summary: Get platform upgrade status + description: Returns the most recent ACE platform upgrade status (from the latest upgrader ConfigMap + data). Platform upgrade routes require site-admin organization authorization `view_upgrade_history:org` + (Organization_SiteAdminCanViewUpgradeHistory). The response is dynamic ConfigMap key/value data. + operationId: upgrade_GetUpgradeStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Upgrade status ConfigMap data (dynamic key/value map). + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '400': + description: Bad request. No upgrade status found. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `view_upgrade_history:org` authorization. + '500': + description: Internal server error. + post: + tags: + - ACE Upgrade + summary: Upgrade the ACE platform + description: Triggers an ACE platform upgrade using a multipart form containing a target version, + a values file, and an optional flag to use the latest image. The version may be overridden by + an `installerVersion` field inside the uploaded values file. Platform upgrade routes require site-admin + organization authorization `upgrade_platform:org` (Organization_SiteAdminCanUpgradePlatform). + operationId: upgrade_UpgradeACE + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/UpgradeOptions' + responses: + '200': + description: Upgrade job accepted and started. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `upgrade_platform:org` authorization. + '422': + description: Unprocessable entity. Invalid form or values file. + '500': + description: Internal server error. + /upgrade/status: + get: + tags: + - ACE Upgrade + summary: Get platform upgrade job status + description: Returns the status of the most recent ACE platform upgrade job (`pending` with version, + or `completed`). Platform upgrade routes require site-admin organization authorization `view_upgrade_history:org` + (Organization_SiteAdminCanViewUpgradeHistory). + operationId: upgrade_GetJobStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Upgrade job status. + content: + application/json: + schema: + type: object + properties: + status: + type: string + version: + type: string + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `view_upgrade_history:org` authorization. + '500': + description: Internal server error. + /upgrade/history: + get: + tags: + - ACE Upgrade + summary: Get platform upgrade history + description: Returns the ACE platform upgrade history as a list of ConfigMap data maps (each augmented + with a `status` field). Platform upgrade routes require site-admin organization authorization + `view_upgrade_history:org` (Organization_SiteAdminCanViewUpgradeHistory). + operationId: upgrade_UpgradeHistory + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Upgrade history (list of dynamic key/value maps). + content: + application/json: + schema: + type: array + items: + type: object + additionalProperties: + type: string + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `view_upgrade_history:org` authorization. + '500': + description: Internal server error. + /upgrade/current-version: + get: + tags: + - ACE Upgrade + summary: Get the current ACE platform version + description: Returns the currently installed ACE platform (ace-installer helm release) version. + Platform upgrade routes require site-admin organization authorization `view_upgrade_history:org` + (Organization_SiteAdminCanViewUpgradeHistory). + operationId: upgrade_CurrentVersion + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Current platform version. + content: + application/json: + schema: + type: object + properties: + version: + type: string + '400': + description: Bad request. No version found. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Missing `view_upgrade_history:org` authorization. + '500': + description: Internal server error. + /clusters/{owner}/{cluster}/upgrade: + get: + tags: + - ACE Upgrade + summary: Get imported cluster upgrade status + description: Returns the most recent upgrade status for an imported cluster (from the latest upgrader + ConfigMap data in the cluster). Access is controlled by cluster assignment for the given owner/cluster. + The response is dynamic ConfigMap key/value data. + operationId: upgrade_GetUpgradeStatus_ImportedCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + responses: + '200': + description: Imported cluster upgrade status ConfigMap data. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '400': + description: Bad request. No upgrade status found. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Cluster not assigned or not permitted. + '500': + description: Internal server error. + post: + tags: + - ACE Upgrade + summary: Upgrade imported cluster resources + description: Triggers an upgrade of the opscenter-features helm release and managed features in + an imported cluster to the server's current version. Runs asynchronously; progress is tracked + in a ConfigMap. Access is controlled by cluster assignment for the given owner/cluster. + operationId: upgrade_UpgradeClusterResources + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + responses: + '200': + description: Upgrade started. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Cluster not assigned or not permitted. + '500': + description: Internal server error. + /clusters/{owner}/{cluster}/upgrade/history: + get: + tags: + - ACE Upgrade + summary: Get imported cluster upgrade history + description: Returns the upgrade history for an imported cluster as a list of ConfigMap data maps. + Access is controlled by cluster assignment for the given owner/cluster. + operationId: upgrade_UpgradeHistoryOfImportedCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + responses: + '200': + description: Imported cluster upgrade history (list of key/value maps). + content: + application/json: + schema: + type: array + items: + type: object + additionalProperties: + type: string + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Cluster not assigned or not permitted. + '500': + description: Internal server error. + /clusters/{owner}/{cluster}/upgrade/current-version: + get: + tags: + - ACE Upgrade + summary: Get imported cluster current version + description: Returns the currently installed opscenter-features chart version in an imported cluster. + Access is controlled by cluster assignment for the given owner/cluster. + operationId: upgrade_GetClusterCurrentVersion + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + responses: + '200': + description: Imported cluster current version. + content: + application/json: + schema: + type: object + properties: + version: + type: string + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Cluster not assigned or not permitted. + '500': + description: Internal server error. + /clusters/{owner}/{cluster}/upgrade/latest-version: + get: + tags: + - ACE Upgrade + summary: Get latest ACE version for imported cluster + description: Returns the latest available opscenter-features chart version from the server, used + as the target for imported cluster upgrades. Access is controlled by cluster assignment for the + given owner/cluster. + operationId: upgrade_GetACELatestVersion + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + responses: + '200': + description: Latest available version. + content: + application/json: + schema: + type: object + properties: + version: + type: string + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Cluster not assigned or not permitted. + '500': + description: Internal server error. + /clusters/{owner}/{cluster}/spoke/upgrade: + get: + tags: + - ACE Upgrade + summary: Get spoke cluster upgrade status + description: Returns the most recent upgrade status for a spoke cluster (read from the hub cluster's + upgrader ConfigMap data for the spoke). Access is controlled by cluster assignment for the given + owner/cluster. The response is dynamic ConfigMap key/value data. + operationId: upgrade_GetSpokeClusterUpgradeStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + responses: + '200': + description: Spoke cluster upgrade status ConfigMap data. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '400': + description: Bad request. No upgrade status found. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Cluster not assigned or not permitted. + '500': + description: Internal server error. + post: + tags: + - ACE Upgrade + summary: Upgrade spoke cluster resources + description: Triggers an upgrade of a spoke cluster by updating its managed cluster profile binding + and related features to the hub's opscenter-features version. Runs asynchronous post-processing. + Access is controlled by cluster assignment for the given owner/cluster. + operationId: upgrade_UpgradeSpokeClusterResources + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + responses: + '200': + description: Spoke cluster upgrade started. + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Cluster not assigned or not permitted. + '500': + description: Internal server error. + /clusters/{owner}/{cluster}/spoke/upgrade/history: + get: + tags: + - ACE Upgrade + summary: Get spoke cluster upgrade history + description: Returns the upgrade history for a spoke cluster as a list of ConfigMap data maps (read + from the hub cluster). Access is controlled by cluster assignment for the given owner/cluster. + operationId: upgrade_UpgradeHistoryOfSpokeCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/owner' + - $ref: '#/components/parameters/cluster' + responses: + '200': + description: Spoke cluster upgrade history (list of key/value maps). + content: + application/json: + schema: + type: array + items: + type: object + additionalProperties: + type: string + '401': + description: Unauthorized. Missing or invalid token. + '403': + description: Forbidden. Cluster not assigned or not permitted. + '500': + description: Internal server error. + /contracts: + get: + tags: + - Licensing & Contracts + summary: List all contracts (admin) + description: Site-admin API. Lists all contracts across accounts. Requires a token plus site-admin + authorization (`view_contracts:site_admin`) and is only available on AppsCode-hosted deployments. + The target org/user is scoped via the `orgOrUserId`/`org` query parameter. + operationId: contracts_ListContracts + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + responses: + '200': + description: List of contracts + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Contract' + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + post: + tags: + - Licensing & Contracts + summary: Create a contract (admin) + description: Site-admin API. Creates one or more contracts (one per product listed in `products`). + Accepts a multipart/form-data body so an optional contract `document` file can be uploaded. Requires + a token plus site-admin authorization (`create_contracts:site_admin`); AppsCode-hosted only. + operationId: contracts_AddContract + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/AddContractParams' + responses: + '201': + description: Contract(s) created + '400': + description: Bad request (empty products, invalid emails, unsupported product, or bad quota) + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '422': + description: Unprocessable entity (invalid request body) + /contracts/active/associated-clusters/{clusterID}/status: + get: + tags: + - Licensing & Contracts + summary: Get contract-cluster status for a user (admin) + description: Site-admin API. Returns the association/validity status of a single cluster for the + target user. Requires a token plus site-admin authorization (`view_contracts:site_admin`); AppsCode-hosted + only. + operationId: contracts_GetContractClusterStatusOfAUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: clusterID + in: path + required: true + description: Cluster UUID. + schema: + type: string + - name: orgOrUserId + in: query + required: false + description: Target account ID; defaults to the caller when omitted or 0. + schema: + type: integer + format: int64 + - name: contract + in: query + required: false + description: Optional contract ID to check the cluster against. + schema: + type: integer + format: int64 + responses: + '200': + description: Cluster status + content: + application/json: + schema: + $ref: '#/components/schemas/ContractClusterStatus' + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '500': + description: Internal server error + /contracts/active/associated-clusters/batch-status: + post: + tags: + - Licensing & Contracts + summary: Get batch contract-cluster status for a user (admin) + description: Site-admin API. Returns association/validity status for a batch of clusters for the + target user. Requires a token plus site-admin authorization (`view_contracts:site_admin`); AppsCode-hosted + only. + operationId: contracts_GetBatchContractClusterStatusOfAUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: orgOrUserId + in: query + required: false + description: Target account ID; defaults to the caller when omitted or 0. + schema: + type: integer + format: int64 + - name: contract + in: query + required: false + description: Optional contract ID to check the clusters against. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BatchClusterStatusRequest' + responses: + '200': + description: List of cluster statuses + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ContractClusterStatus' + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '422': + description: Unprocessable entity (invalid request body) + '500': + description: Internal server error + /contracts/{id}: + get: + tags: + - Licensing & Contracts + summary: Get a contract (admin) + description: Site-admin API. Requires a token plus site-admin authorization (`view_contracts:site_admin`); + AppsCode-hosted only. + operationId: contracts_GetContract + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: Contract + content: + application/json: + schema: + $ref: '#/components/schemas/Contract' + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '404': + description: Contract not found + put: + tags: + - Licensing & Contracts + summary: Update a contract (admin) + description: Site-admin API. Accepts a multipart/form-data body so an optional replacement contract + `document` file can be uploaded. Requires a token plus site-admin authorization (`update_contracts:site_admin`); + AppsCode-hosted only. + operationId: contracts_UpdateContract + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/Contract' + responses: + '200': + description: Updated contract + content: + application/json: + schema: + $ref: '#/components/schemas/Contract' + '400': + description: Bad request (invalid quota or emails) + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '404': + description: Contract not found + '422': + description: Unprocessable entity (invalid request body) + delete: + tags: + - Licensing & Contracts + summary: Delete a contract (admin) + description: Site-admin API. Requires a token plus site-admin authorization (`delete_contracts:site_admin`); + AppsCode-hosted only. + operationId: contracts_DeleteContract + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: Contract deleted + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '404': + description: Contract not found + /contracts/{id}/extend: + post: + tags: + - Licensing & Contracts + summary: Extend a contract (admin) + description: Site-admin API. Extends a contract's end time using the `end` field of the request + body. Requires a token plus site-admin authorization (`extend_contracts:site_admin`); AppsCode-hosted + only. + operationId: contracts_ExtendContract + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Contract' + responses: + '200': + description: Extended contract + content: + application/json: + schema: + $ref: '#/components/schemas/Contract' + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '404': + description: Contract not found + '422': + description: Unprocessable entity (invalid request body) + /contracts/{id}/document: + get: + tags: + - Licensing & Contracts + summary: Get contract document signed URL (admin) + description: Site-admin API. Returns a time-limited signed URL (as a JSON string) to download the + contract document. Requires a token plus site-admin authorization (`view_contracts:site_admin`); + AppsCode-hosted only. + operationId: contracts_GetContractDocument + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: A signed URL string pointing to the contract document (valid for 30 minutes). The + handler returns the URL as a JSON string, not the file bytes. + content: + application/json: + schema: + type: string + format: uri + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '404': + description: Contract not found + /contracts/{id}/revoke: + post: + tags: + - Licensing & Contracts + summary: Revoke a contract (admin) + description: Site-admin API. Requires a token plus site-admin authorization (`revoke_contracts:site_admin`); + AppsCode-hosted only. + operationId: contracts_RevokeContract + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: Contract revoked + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '404': + description: Contract not found + /contracts/{id}/audit: + get: + tags: + - Licensing & Contracts + summary: List contract audit events (admin) + description: Site-admin API. Lists the audit trail of a contract. Requires a token plus contract-management + authorization (`view_contracts:contract_mgmt`); AppsCode-hosted only. + operationId: contracts_ListContractAudit + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: List of contract audit events + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ContractAudit' + '401': + description: Unauthorized + '403': + description: Forbidden (authorization required) + '404': + description: Contract not found + /contracts/{id}/clusters/imported/non-associated: + get: + tags: + - Licensing & Contracts + summary: List imported clusters not associated with a contract (admin) + description: Site-admin API. Lists the owner's imported clusters that are not yet bound to the contract. + Requires a token plus site-admin authorization (`add_cluster:site_admin`); AppsCode-hosted only. + operationId: contracts_ListImportedNonAssociatedClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: List of cluster info records + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '400': + description: Contract not found + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + /contracts/{id}/clusters: + get: + tags: + - Licensing & Contracts + summary: List clusters bound to a contract (admin) + description: Site-admin API. Requires a token plus site-admin authorization (`add_cluster:site_admin`); + AppsCode-hosted only. + operationId: contracts_GetContractClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: List of contract-cluster status records + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ContractClusterStatus' + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + post: + tags: + - Licensing & Contracts + summary: Bind multiple clusters to a contract (admin) + description: Site-admin API. Binds one or more clusters to the contract. Requires a token plus site-admin + authorization (`add_cluster:site_admin`); AppsCode-hosted only. + operationId: contracts_BindMultipleClustersToContract + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/BindContractCluster' + responses: + '201': + description: Clusters bound; returns updated contract-cluster list + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ContractClusterStatus' + '400': + description: Bad request (empty list, invalid cluster UUID, or cluster already associated) + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '422': + description: Unprocessable entity (invalid request body) + /contracts/{id}/clusters/{ccID}: + delete: + tags: + - Licensing & Contracts + summary: Remove a cluster from a contract (admin) + description: Site-admin API. Requires a token plus site-admin authorization (`remove_cluster:site_admin`); + AppsCode-hosted only. + operationId: contracts_RemoveContractCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + - name: ccID + in: path + required: true + description: Contract-cluster ID. + schema: + type: integer + format: int64 + responses: + '200': + description: Cluster removed from contract + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + /contracts/{id}/clusters/{ccID}/issue-license: + post: + tags: + - Licensing & Contracts + summary: Issue a full license for a contract cluster (admin) + description: Site-admin API. Issues a full (offline-capable) license for the given contract cluster. + Requires a token plus site-admin authorization (`issue_license:site_admin`); AppsCode-hosted only. + operationId: contracts_IssueFullLicense + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + - name: ccID + in: path + required: true + description: Contract-cluster ID. + schema: + type: integer + format: int64 + responses: + '200': + description: Issued license + content: + application/json: + schema: + $ref: '#/components/schemas/License' + '401': + description: Unauthorized + '403': + description: Forbidden (quota exceeded or authorization required) + '404': + description: Contract not found + '405': + description: License issuance not allowed (revoked contract or offline not allowed) + /contracts/{id}/clusters/{ccID}/name: + patch: + tags: + - Licensing & Contracts + summary: Update a contract cluster display name (admin) + description: Site-admin API. Requires a token plus site-admin authorization (`update_cluster_name:site_admin`); + AppsCode-hosted only. + operationId: contracts_UpdateAdminContractClusterName + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + - name: ccID + in: path + required: true + description: Contract-cluster ID. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PatchUserContractClusterName' + responses: + '200': + description: Cluster name updated + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '422': + description: Unprocessable entity (invalid request body) + /contracts/{id}/clusters/{ccID}/tags: + patch: + tags: + - Licensing & Contracts + summary: Update a contract cluster tags (admin) + description: Site-admin API. Replaces the tag set for a cluster and syncs it across contracts sharing + the same cluster UUID. Requires a token plus site-admin authorization (`update_cluster_tags:site_admin`); + AppsCode-hosted only. + operationId: contracts_UpdateAdminContractClusterTags + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + - name: ccID + in: path + required: true + description: Contract-cluster ID. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PatchUserContractClusterTags' + responses: + '200': + description: Cluster tags updated + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + '422': + description: Unprocessable entity (invalid request body) + /contracts/available_products: + get: + tags: + - Licensing & Contracts + summary: List products available for contracts (admin) + description: Site-admin API. Returns the map of non-community products supported for contracts, + keyed by product alias. Requires a token plus site-admin authorization (`create_contracts:site_admin`); + AppsCode-hosted only. + operationId: contracts_GetAvailableProductsForContracts + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + responses: + '200': + description: Map of product alias to plan info + content: + application/json: + schema: + type: object + additionalProperties: + $ref: '#/components/schemas/PlanInfo' + '401': + description: Unauthorized + '403': + description: Forbidden (site-admin authorization required) + /user/contracts: + get: + tags: + - Licensing & Contracts + summary: List the owner's contracts + description: Lists contracts owned by the resolved owner (org/user). Requires a token; AppsCode-hosted + only. + operationId: contracts_ListUserContracts + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + responses: + '200': + description: List of contracts + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Contract' + '401': + description: Unauthorized + '403': + description: Forbidden + /user/contracts/active-offline-contracts: + get: + tags: + - Licensing & Contracts + summary: List the owner's active offline contracts + description: Lists the owner's active offline (air-gapped) contracts. Requires a token; AppsCode-hosted + only. + operationId: contracts_ListActiveUserOfflineContracts + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + responses: + '200': + description: List of active offline contracts + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Contract' + '401': + description: Unauthorized + '403': + description: Forbidden + /user/contracts/assign-cluster: + post: + tags: + - Licensing & Contracts + summary: Assign a cluster to multiple contracts + description: Assigns a single cluster to multiple contracts owned by the caller. Requires a token + plus contract-management authorization (`add_cluster:contract_mgmt`); AppsCode-hosted only. + operationId: contracts_AssignClusterToMultipleContracts + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterContractList' + responses: + '200': + description: Cluster assigned + '400': + description: Bad request (empty contract list or invalid cluster UUID) + '401': + description: Unauthorized + '403': + description: Forbidden + '422': + description: Unprocessable entity (invalid request body) + /user/contracts/active/associated-with/clusters/{clusterID}: + get: + tags: + - Licensing & Contracts + summary: List active contracts associated with a cluster + description: Lists the owner's active contracts associated with the given cluster. Pass `onlyOffline=true` + to restrict to offline contracts. Requires a token; AppsCode-hosted only. + operationId: contracts_ListActiveContractsAssociatedWithACluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: clusterID + in: path + required: true + description: Cluster UUID. + schema: + type: string + - name: onlyOffline + in: query + required: false + description: Restrict the result to offline contracts only. + schema: + type: boolean + responses: + '200': + description: List of active associated contracts + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Contract' + '401': + description: Unauthorized + '403': + description: Forbidden + /user/contracts/active/not-associated-with/clusters/{clusterID}: + get: + tags: + - Licensing & Contracts + summary: List active contracts not associated with a cluster + description: Lists the owner's active contracts that are not associated with the given cluster. + Requires a token; AppsCode-hosted only. + operationId: contracts_ListActiveContractsNotAssociatedWithACluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: clusterID + in: path + required: true + description: Cluster UUID. + schema: + type: string + responses: + '200': + description: List of active non-associated contracts + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Contract' + '401': + description: Unauthorized + '403': + description: Forbidden + /user/contracts/active/associated-clusters: + get: + tags: + - Licensing & Contracts + summary: List clusters of the owner's active offline contracts + description: Lists the unique clusters associated with the owner's offline active contracts. Requires + a token; AppsCode-hosted only. + operationId: contracts_ListClustersAssociatedWithAUsersOfflineActiveContracts + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + responses: + '200': + description: List of clusters with associated contracts + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterWithAssociatedContracts' + '401': + description: Unauthorized + '403': + description: Forbidden + /user/contracts/active/associated-clusters/{clusterID}/status: + get: + tags: + - Licensing & Contracts + summary: Get contract-cluster status for the owner + description: Returns the association/validity status of a single cluster for the caller. Requires + a token; AppsCode-hosted only. + operationId: contracts_GetContractClusterStatus + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: clusterID + in: path + required: true + description: Cluster UUID. + schema: + type: string + - name: contract + in: query + required: false + description: Optional contract ID to check the cluster against. + schema: + type: integer + format: int64 + responses: + '200': + description: Cluster status + content: + application/json: + schema: + $ref: '#/components/schemas/ContractClusterStatus' + '401': + description: Unauthorized + '403': + description: Forbidden + '500': + description: Internal server error + /user/contracts/active/associated-clusters/batch-status: + post: + tags: + - Licensing & Contracts + summary: Get batch contract-cluster status for the owner + description: Returns association/validity status for a batch of clusters for the caller. Requires + a token; AppsCode-hosted only. + operationId: contracts_GetBatchClusterStatusForAContract + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: contract + in: query + required: false + description: Optional contract ID to check the clusters against. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BatchClusterStatusRequest' + responses: + '200': + description: List of cluster statuses + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ContractClusterStatus' + '401': + description: Unauthorized + '403': + description: Forbidden + '422': + description: Unprocessable entity (invalid request body) + '500': + description: Internal server error + /user/contracts/{id}: + get: + tags: + - Licensing & Contracts + summary: Get one of the owner's contracts + description: Returns a single contract owned by the caller (admin-only email fields sanitized). + Requires a token; AppsCode-hosted only. + operationId: contracts_GetUserContract + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: Contract + content: + application/json: + schema: + $ref: '#/components/schemas/Contract' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Contract not found + /user/contracts/{id}/document: + get: + tags: + - Licensing & Contracts + summary: Get the owner's contract document signed URL + description: Returns a time-limited signed URL (as a JSON string) to download the contract document. + Requires a token; AppsCode-hosted only. + operationId: contracts_GetUserContractDocument + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: A signed URL string pointing to the contract document (valid for 30 minutes). The + handler returns the URL as a JSON string, not the file bytes. + content: + application/json: + schema: + type: string + format: uri + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Contract not found + /user/contracts/{id}/audit: + get: + tags: + - Licensing & Contracts + summary: List the owner's contract audit events + description: Lists the audit trail of one of the caller's contracts. Requires a token; AppsCode-hosted + only. + operationId: contracts_ListUserContractAudit + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: List of contract audit events + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ContractAudit' + '401': + description: Unauthorized + '403': + description: Forbidden (contract not found or authorization denied) + /user/contracts/{id}/preferences: + put: + tags: + - Licensing & Contracts + summary: Update the owner's contract preferences + description: Updates the caller-editable preferences (auto-assign clusters, usage alert client recipients) + for one of the caller's contracts. Requires a token plus authorization (`updated_preferences:contracts`); + AppsCode-hosted only. + operationId: contracts_UpdateUserContractPreferences + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateUserContractPreferences' + responses: + '200': + description: Updated contract + content: + application/json: + schema: + $ref: '#/components/schemas/Contract' + '400': + description: Bad request (invalid usage alert client recipients) + '401': + description: Unauthorized + '403': + description: Forbidden + '422': + description: Unprocessable entity (invalid request body) + /user/contracts/{id}/clusters/imported/non-associated: + get: + tags: + - Licensing & Contracts + summary: List the owner's imported clusters not associated with a contract + description: Lists the owner's imported clusters not yet bound to the contract. Requires a token; + AppsCode-hosted only. + operationId: contracts_ListUserImportedNonAssociatedClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: List of cluster info records + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '400': + description: Contract not found + '401': + description: Unauthorized + '403': + description: Forbidden + /user/contracts/{id}/clusters: + get: + tags: + - Licensing & Contracts + summary: List clusters bound to the owner's contract + description: Requires a token; AppsCode-hosted only. + operationId: contracts_GetUserContractClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + responses: + '200': + description: List of contract-cluster status records + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ContractClusterStatus' + '401': + description: Unauthorized + '403': + description: Forbidden + post: + tags: + - Licensing & Contracts + summary: Bind multiple clusters to the owner's contract + description: Binds one or more clusters to one of the caller's contracts. Requires a token plus + authorization; AppsCode-hosted only. + operationId: contracts_BindUserMultipleClustersToContract + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/BindContractCluster' + responses: + '201': + description: Clusters bound; returns updated contract-cluster list + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ContractClusterStatus' + '400': + description: Bad request (empty list, invalid UUID, invalid contract, or already associated) + '401': + description: Unauthorized + '403': + description: Forbidden + '422': + description: Unprocessable entity (invalid request body) + /user/contracts/{id}/clusters/{ccID}: + delete: + tags: + - Licensing & Contracts + summary: Remove a cluster from the owner's contract + description: Requires a token; AppsCode-hosted only. + operationId: contracts_RemoveUserContractCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + - name: ccID + in: path + required: true + description: Contract-cluster ID. + schema: + type: integer + format: int64 + responses: + '200': + description: Cluster removed from contract + '401': + description: Unauthorized + '403': + description: Forbidden + /user/contracts/{id}/clusters/{ccID}/name: + patch: + tags: + - Licensing & Contracts + summary: Update a cluster display name on the owner's contract + description: Requires a token; AppsCode-hosted only. + operationId: contracts_UpdateUserContractClusterName + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + - name: ccID + in: path + required: true + description: Contract-cluster ID. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PatchUserContractClusterName' + responses: + '200': + description: Cluster name updated + '401': + description: Unauthorized + '403': + description: Forbidden + '422': + description: Unprocessable entity (invalid request body) + /user/contracts/{id}/clusters/{ccID}/tags: + patch: + tags: + - Licensing & Contracts + summary: Update cluster tags on the owner's contract + description: Replaces the tag set for a cluster and syncs it across the owner's contracts sharing + the same cluster UUID. Requires a token; AppsCode-hosted only. + operationId: contracts_UpdateUserContractClusterTags + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + - name: ccID + in: path + required: true + description: Contract-cluster ID. + schema: + type: integer + format: int64 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PatchUserContractClusterTags' + responses: + '200': + description: Cluster tags updated + '401': + description: Unauthorized + '403': + description: Forbidden + '422': + description: Unprocessable entity (invalid request body) + /user/contracts/{id}/clusters/{ccID}/issue-license: + post: + tags: + - Licensing & Contracts + summary: Issue a full license for the owner's contract cluster + description: Issues a full (offline-capable) license for one of the caller's contract clusters. + Requires a token plus authorization (`issue-license:cluster`); AppsCode-hosted only. + operationId: contracts_IssueUserFullLicense + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + - name: id + in: path + required: true + description: Contract ID. + schema: + type: integer + format: int64 + - name: ccID + in: path + required: true + description: Contract-cluster ID. + schema: + type: integer + format: int64 + responses: + '200': + description: Issued license + content: + application/json: + schema: + $ref: '#/components/schemas/License' + '401': + description: Unauthorized + '403': + description: Forbidden (quota exceeded or authorization denied) + '404': + description: Contract not found + '405': + description: License issuance not allowed (revoked contract or offline not allowed) + /user/license-proxy: + post: + tags: + - Licensing & Contracts + summary: Generate a license-proxy server installer + description: Generates a license-proxy server installer script for the resolved organization. When + `clusterID`/`contractIDs` are supplied an offline installer is generated; otherwise an online + installer. Requires a token plus dynamic authorization on the organization; AppsCode-hosted only. + operationId: contracts_GenerateLicenseProxyServerInstaller + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/OwnerQueryParam' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/InstallerOptions' + responses: + '200': + description: Installer scripts. The handler returns a dynamic JSON object (map[string]any) containing + the generated YAML/Helm3 installer scripts; modeled as a free-form object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized + '403': + description: Forbidden + '422': + description: Unprocessable entity (invalid request body) + '500': + description: Internal server error + /register: + post: + tags: + - Licensing & Contracts + summary: Register a licensed user + description: Public-ish endpoint used by on-prem/air-gapped deployments to register a user against + a previously issued license. No auth token is required, but the request must carry a valid license + payload (`license`) which is cryptographically verified; a license-validation middleware also + gates the request. Only available when self-registration is permitted for the deployment type. + operationId: contracts_RegisterLicensedUser + security: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/VerifierOptions' + responses: + '200': + description: User registered + '400': + description: Bad request (empty features or unregistered cluster-uid) + '403': + description: Registration not supported for this deployment type + '422': + description: Unprocessable entity (invalid request body or license) + '500': + description: Internal server error (license verification or user creation failed) + /license/issue: + post: + tags: + - Licensing & Contracts + summary: Issue a license for a cluster + description: Issues a license for the caller's cluster/product based on the caller's active contract. + Requires a valid token. + operationId: contracts_GetLicense + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LicenseOpts' + responses: + '200': + description: Issued license + content: + application/json: + schema: + $ref: '#/components/schemas/License' + '401': + description: Unauthorized + '403': + description: Forbidden (contract quota exceeded) + '405': + description: Contract invalid (revoked or expired) + '422': + description: Unprocessable entity (invalid request body) + '500': + description: Internal server error + /dashboard/users: + get: + tags: + - Billing Dashboard + summary: List licensed users + description: Lists all users that have ever reported a license to this deployment. Site-admin only + (`view_licensed_users:site_admin`). Requires a billing-enabled b3 deployment. + operationId: dashboard_ListLicensedUsers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of licensed users. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/LicensedUserAPIForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/users/active: + get: + tags: + - Billing Dashboard + summary: List active licensed users + description: Lists licensed users that have reported within the `limit` window (defaults to the + last 6 months). Site-admin only (`view_licensed_users:site_admin`). Requires a billing-enabled + deployment. + operationId: dashboard_ListActiveLicensedUsers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: limit + in: query + required: false + description: Activity window. A Go duration (e.g. `720h`) or a `YYYY-MM-DD` date; defaults to + the last ~6 months when omitted. + schema: + type: string + responses: + '200': + description: List of active licensed users. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/LicensedUserAPIForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/users/inactive: + get: + tags: + - Billing Dashboard + summary: List inactive licensed users + description: Lists licensed users that have never reported a licensed product. Site-admin only (`view_licensed_users:site_admin`). + Requires a billing-enabled deployment. + operationId: dashboard_ListInactiveLicensedUsers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of inactive licensed users. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/LicensedUserAPIForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/users/{uid}/clusters: + get: + tags: + - Billing Dashboard + summary: List a user's clusters + description: Lists cluster information for the given licensed user. Site-admin only (`view_licensed_users:site_admin`). + Requires a billing-enabled deployment. + operationId: dashboard_ListUserClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + responses: + '200': + description: List of cluster information objects. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterInfo' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '500': + description: Internal error. + /dashboard/users/{uid}/clusters/active: + get: + tags: + - Billing Dashboard + summary: List a user's active clusters + description: Lists clusters that reported for the given user within the `limit` window. Site-admin + only (`view_licensed_users:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_ListActiveUserClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + - name: limit + in: query + required: false + description: Activity window (Go duration or `YYYY-MM-DD` date). + schema: + type: string + responses: + '200': + description: List of active clusters for the user. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ActiveClustersAPIForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/users/{uid}/clusters/{cid}: + get: + tags: + - Billing Dashboard + summary: Get a user's cluster information + description: Returns cluster information for a specific user/cluster. Site-admin only (`view_licensed_users:site_admin`). + Requires a billing-enabled deployment. + operationId: dashboard_GetUserClusterInformation + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + responses: + '200': + description: Cluster information. + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/users/{uid}/clusters/{cid}/licenses: + get: + tags: + - Billing Dashboard + summary: List a user's licenses on a cluster + description: Lists licensed plans associated with the given user and cluster. Site-admin only (`view_licensed_users:site_admin`). + Requires a billing-enabled deployment. + operationId: dashboard_ListUserLicenses + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + responses: + '200': + description: List of licensed plans. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/LicensedPlan' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/users/{uid}/clusters/{cid}/licenses/active: + get: + tags: + - Billing Dashboard + summary: List active licenses for a user's cluster + description: Lists licenses that reported within the `limit` window for the given user and cluster. + Site-admin only (`view_licensed_users:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_ListActiveLicensesForSpecificUserCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: limit + in: query + required: false + description: Activity window (Go duration or `YYYY-MM-DD` date). + schema: + type: string + responses: + '200': + description: List of active licenses. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ActiveLicenseAPIForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}: + get: + tags: + - Billing Dashboard + summary: Get a user's license (with site info) + description: Returns a licensed plan together with the latest reported SiteInfo. Site-admin only + (`view_licensed_users:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_GetUserLicense + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + responses: + '200': + description: Object with `license` (the licensed plan) and `siteinfo` (a kmodules identity SiteInfo, + free-form). + content: + application/json: + schema: + type: object + properties: + license: + $ref: '#/components/schemas/LicensedPlan' + siteinfo: + $ref: '#/components/schemas/K8sObject' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products: + get: + tags: + - Billing Dashboard + summary: List active products for a license + description: Lists reported licensed products for the given user/cluster/license. Site-admin only + (`view_licensed_users:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_ListActiveProductsForSpecificLicense + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + - name: limit + in: query + required: false + description: Activity window (Go duration or `YYYY-MM-DD` date). + schema: + type: string + responses: + '200': + description: List of received licensed products. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ReceivedLicensedProduct' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products/{productName}: + get: + tags: + - Billing Dashboard + summary: Get an active product for a license + description: Returns the reported licensed product for the given user/cluster/license/product. Site-admin + only (`view_licensed_users:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_GetActiveProductForSpecificLicense + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + - name: productName + in: path + required: true + description: Product name. + schema: + type: string + - name: limit + in: query + required: false + description: Activity window (Go duration or `YYYY-MM-DD` date). + schema: + type: string + responses: + '200': + description: Received licensed product. + content: + application/json: + schema: + $ref: '#/components/schemas/ReceivedLicensedProduct' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products/{productName}/resources: + get: + tags: + - Billing Dashboard + summary: Get cluster resource history (from NATS) + description: Fetches the badger resource history for a product from the member cluster over NATS. + Site-admin only (`view_licensed_users:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_GetClusterResourceHistoryFromNats + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + - name: productName + in: path + required: true + description: Product name. + schema: + type: string + - name: group + in: query + required: false + description: Kubernetes API group filter. + schema: + type: string + - name: resource + in: query + required: false + description: Kubernetes resource filter. + schema: + type: string + responses: + '200': + description: Badger entry list of resource history. + content: + application/json: + schema: + $ref: '#/components/schemas/BadgerEntryList' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products/{productName}/events-histories: + get: + tags: + - Billing Dashboard + summary: Get auditor events history for a resource + description: Returns an events history report for a specific resource (admin/testing use). Site-admin + only (`view_licensed_users:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_GetAuditorEventsHistoryForSpecificResource + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + - name: productName + in: path + required: true + description: Product name. + schema: + type: string + - name: group + in: query + required: false + description: Kubernetes API group. + schema: + type: string + - name: resource + in: query + required: false + description: Kubernetes resource. + schema: + type: string + - name: rid + in: query + required: false + description: Resource ID (object UID). + schema: + type: string + responses: + '200': + description: Events history report. + content: + application/json: + schema: + $ref: '#/components/schemas/EventsReport' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products/{productName}/events: + get: + tags: + - Billing Dashboard + summary: List events for a license (admin) + description: Returns the tabular event list for a licensed user's cluster/license/ product. Site-admin + only (`view_licensed_users:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_GetEventsListForLicense + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + - name: productName + in: path + required: true + description: Product name. + schema: + type: string + - name: lastDays + in: query + required: false + description: Look-back window in days (max 14; defaults to 14). + schema: + type: integer + responses: + '200': + description: Tabular event list, newest first. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterResourceTabularForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/users/{uid}/clusters/{cid}/licenses/{lid}/products/{productName}/events/raw-event: + get: + tags: + - Billing Dashboard + summary: Get raw event data (admin) + description: Returns the raw badger value for a specific event key/version. Site-admin only (`view_licensed_users:site_admin`). + Requires a billing-enabled deployment. + operationId: dashboard_GetRawEventData + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uid + in: path + required: true + description: User (account) ID. + schema: + type: integer + format: int64 + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + - name: productName + in: path + required: true + description: Product name. + schema: + type: string + - name: key + in: query + required: true + description: Badger event key. + schema: + type: string + - name: version + in: query + required: true + description: Event version (uint). + schema: + type: integer + format: int64 + responses: + '200': + description: Raw badger value. + content: + application/json: + schema: + $ref: '#/components/schemas/BadgerValue' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/clusters/{cid}/licenses/active: + get: + tags: + - Billing Dashboard + summary: List active licenses for a cluster + description: Lists licenses that reported within the `limit` window for the given cluster, across + users. Site-admin only (`view_licensed_users:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_ListActiveLicensesForSpecificCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: limit + in: query + required: false + description: Activity window (Go duration or `YYYY-MM-DD` date). + schema: + type: string + responses: + '200': + description: List of received licensed products (one per active license). + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ReceivedLicensedProduct' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/system-outages: + post: + tags: + - Billing Dashboard + summary: Create a system outage entry + description: Records a system outage window for an account/cluster. Site-admin only (`view_system_outages:site_admin`). + Requires a billing-enabled deployment. + operationId: dashboard_CreateSystemOutageEntry + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SystemOutageRequest' + responses: + '201': + description: Created system outage entry. + content: + application/json: + schema: + $ref: '#/components/schemas/SystemOutageApiForm' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '409': + description: An overlapping system outage entry already exists. + '422': + $ref: '#/components/responses/ValidationError' + /dashboard/system-outages/report: + get: + tags: + - Billing Dashboard + summary: List system outages with extended report + description: Lists system outage entries with an aggregated report (top tags, accounts and clusters + by duration). Site-admin only (`view_system_outages:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_ListSystemOutageEntriesWithExtendedReport + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: start + in: query + required: false + description: RFC3339 start time filter. + schema: + type: string + format: date-time + - name: account_id + in: query + required: false + description: Filter by account ID. + schema: + type: string + - name: cluster_id + in: query + required: false + description: Filter by cluster ID. + schema: + type: string + - name: tags + in: query + required: false + description: Filter by tags (repeatable). + schema: + type: array + items: + type: string + responses: + '200': + description: System outages and aggregated report. + content: + application/json: + schema: + $ref: '#/components/schemas/SystemOutagesAndReportAPIForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/system-outages/tags: + get: + tags: + - Billing Dashboard + summary: List all system outage tags + description: Lists all unique tags used across system outage entries. Site-admin only (`view_system_outages:site_admin`). + Requires a billing-enabled deployment. + operationId: dashboard_ListAllUniqueTagsUsedInSystemOutagesEntries + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of unique tags. + content: + application/json: + schema: + type: array + items: + type: string + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/marketplaces/subscriptions: + get: + tags: + - Billing Dashboard + summary: List all marketplace subscriptions + description: Lists all marketplace subscriptions (minimal API form), newest updated first. Site-admin + only (`view_marketplace_usage:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_ListAllMarketplaceSubscriptions + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: List of marketplace subscriptions. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Subscription' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/marketplaces/settings/warnings: + get: + tags: + - Billing Dashboard + summary: Get marketplace setting warnings + description: Returns configuration warnings for marketplace integrations (e.g. Azure client-secret + expiry). Site-admin only (`view_marketplace_usage:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_GetMarketplaceSettingWarnings + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Marketplace setting warnings. + content: + application/json: + schema: + $ref: '#/components/schemas/SettingWarnings' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/marketplaces/{marketplace}/{subscriptionId}: + get: + tags: + - Billing Dashboard + summary: Get a marketplace subscription + description: Returns the full API form of a marketplace subscription. Site-admin only (`view_marketplace_usage:site_admin`). + Requires a billing-enabled deployment. + operationId: dashboard_GetMarketplaceSubscription + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: marketplace + in: path + required: true + description: Marketplace identifier (e.g. `Aws`, `Azure`, `Gcp`). + schema: + $ref: '#/components/schemas/Marketplace' + - name: subscriptionId + in: path + required: true + description: Marketplace subscription ID. + schema: + type: string + responses: + '200': + description: Marketplace subscription. + content: + application/json: + schema: + $ref: '#/components/schemas/Subscription' + '400': + description: Subscription not found or invalid. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + delete: + tags: + - Billing Dashboard + summary: Revoke a marketplace subscription + description: Revokes a revocable marketplace subscription and all associated contracts. Site-admin + only (`view_marketplace_usage:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_RevokeMarketplaceSubscription + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: marketplace + in: path + required: true + description: Marketplace identifier. + schema: + $ref: '#/components/schemas/Marketplace' + - name: subscriptionId + in: path + required: true + description: Marketplace subscription ID. + schema: + type: string + responses: + '200': + description: Subscription revoked. + '400': + description: Subscription not found or not revocable. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/marketplaces/{marketplace}/{subscriptionId}/ping: + get: + tags: + - Billing Dashboard + summary: Ping a marketplace subscription endpoint + description: Pings the hosted b3 metering readiness endpoint for a subscription (AWS or GCP only). + Site-admin only (`view_marketplace_usage:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_PingMarketplaceEndpoint + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: marketplace + in: path + required: true + description: Marketplace identifier. + schema: + $ref: '#/components/schemas/Marketplace' + - name: subscriptionId + in: path + required: true + description: Marketplace subscription ID. + schema: + type: string + responses: + '200': + description: Endpoint reachable. + '400': + description: Subscription not found or marketplace unsupported. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/marketplaces/{marketplace}/{subscriptionId}/audit-logs: + get: + tags: + - Billing Dashboard + summary: Get marketplace subscription audit reports + description: Returns audit event reports for a marketplace subscription, grouped by audit period. + Site-admin only (`view_marketplace_usage:site_admin`). Requires a billing-enabled deployment. + operationId: dashboard_GetAuditReports + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: marketplace + in: path + required: true + description: Marketplace identifier. + schema: + $ref: '#/components/schemas/Marketplace' + - name: subscriptionId + in: path + required: true + description: Marketplace subscription ID. + schema: + type: string + responses: + '200': + description: Audit reports grouped by period. + content: + application/json: + schema: + $ref: '#/components/schemas/AuditReportsResp' + '400': + description: Subscription not found. + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/clusters/active: + get: + tags: + - Billing Dashboard + summary: List the caller's active clusters + description: Lists clusters that reported within the `limit` window for the owner resolved from + the query. Requires `view:contracts` authorization and a billing-enabled deployment. + operationId: dashboard_ListActiveClusters + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: limit + in: query + required: false + description: Activity window (Go duration or `YYYY-MM-DD` date). + schema: + type: string + responses: + '200': + description: List of active clusters. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ActiveClustersAPIForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/clusters/{cid}: + get: + tags: + - Billing Dashboard + summary: Get cluster information (caller) + description: Returns cluster information for a cluster owned by the request owner. Requires `view:contracts` + authorization and a billing-enabled deployment. + operationId: dashboard_GetClusterInformation + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + responses: + '200': + description: Cluster information. + content: + application/json: + schema: + $ref: '#/components/schemas/ClusterInfo' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/clusters/{cid}/events-count: + get: + tags: + - Billing Dashboard + summary: Get cluster events count (caller) + description: Returns today's event count for the cluster. Requires `view:contracts` authorization + and a billing-enabled deployment. + operationId: dashboard_GetClusterEventsCount + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + responses: + '200': + description: Events counter response. + content: + application/json: + schema: + $ref: '#/components/schemas/EventsCounterResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/clusters/{cid}/licenses: + get: + tags: + - Billing Dashboard + summary: List licenses on a cluster (caller) + description: Lists licensed plans associated with the request owner and cluster. Requires `view:contracts` + authorization and a billing-enabled deployment. + operationId: dashboard_ListLicenses + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + responses: + '200': + description: List of licensed plans. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/LicensedPlan' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/clusters/{cid}/licenses/{lid}: + get: + tags: + - Billing Dashboard + summary: Get a license (caller) + description: Returns a licensed plan (API form) associated with the request owner. Requires `view:contracts` + authorization and a billing-enabled deployment. + operationId: dashboard_GetLicense + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + responses: + '200': + description: Licensed plan (API form). + content: + application/json: + schema: + $ref: '#/components/schemas/LicensePlanApiForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/clusters/{cid}/licenses/{lid}/products/{product}/events-count: + get: + tags: + - Billing Dashboard + summary: Get license events count (caller) + description: Returns today's event count for a license/product. Requires `view:contracts` authorization + and a billing-enabled deployment. + operationId: dashboard_GetLicenseEventsCount + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + - name: product + in: path + required: true + description: Product name. + schema: + type: string + responses: + '200': + description: Events counter response. + content: + application/json: + schema: + $ref: '#/components/schemas/EventsCounterResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/clusters/{cid}/licenses/{lid}/products/{product}/groups/{group}/resources/{resource}/{rid}/events-count: + get: + tags: + - Billing Dashboard + summary: Get resource events count (caller) + description: Returns today's event count for a specific resource object. Requires `view:contracts` + authorization and a billing-enabled deployment. + operationId: dashboard_GetResourceEventsCount + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + - name: product + in: path + required: true + description: Product name. + schema: + type: string + - name: group + in: path + required: true + description: Kubernetes API group. + schema: + type: string + - name: resource + in: path + required: true + description: Kubernetes resource. + schema: + type: string + - name: rid + in: path + required: true + description: Resource ID (object UID). + schema: + type: string + responses: + '200': + description: Events counter response. + content: + application/json: + schema: + $ref: '#/components/schemas/EventsCounterResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/clusters/{cid}/licenses/{lid}/products/{product}/events: + get: + tags: + - Billing Dashboard + summary: List events for a license (caller) + description: Returns the tabular event list for the caller's cluster/license/product. Requires `view:contracts` + authorization and a billing-enabled deployment. + operationId: dashboard_GetEventsListForLicenseUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + - name: product + in: path + required: true + description: Product name. + schema: + type: string + - name: lastDays + in: query + required: false + description: Look-back window in days (max 14; defaults to 14). + schema: + type: integer + responses: + '200': + description: Tabular event list, newest first. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClusterResourceTabularForm' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/clusters/{cid}/licenses/{lid}/products/{product}/events/raw-event: + get: + tags: + - Billing Dashboard + summary: Get raw event data (caller) + description: Returns the raw badger value for a specific event key/version. Requires `view:contracts` + authorization and a billing-enabled deployment. + operationId: dashboard_GetRawEventDataUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: cid + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: lid + in: path + required: true + description: License ID. + schema: + type: string + - name: product + in: path + required: true + description: Product name. + schema: + type: string + - name: key + in: query + required: true + description: Badger event key. + schema: + type: string + - name: version + in: query + required: true + description: Event version (uint). + schema: + type: integer + format: int64 + responses: + '200': + description: Raw badger value. + content: + application/json: + schema: + $ref: '#/components/schemas/BadgerValue' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /dashboard/summary/generated-months: + get: + tags: + - Billing Dashboard + summary: List generated summary months + description: Returns the year/month combinations for which a usage summary has been generated for + the owner. Requires `view_usage_analytics:site_admin` and a billing-enabled deployment. + operationId: dashboard_GetGeneratedMonthsForUser + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Generated year/month list. + content: + application/json: + schema: + $ref: '#/components/schemas/GeneratedDates' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/object-quota-history/clusters/{clusterUID}/objects/{objectID}: + get: + tags: + - Billing Dashboard + summary: Get KubeDB object quota history + description: Returns the quota-history usage view for a specific KubeDB object. Requires `view_usage_analytics:site_admin` + and a billing-enabled deployment. Response is a complex, deeply-nested usage view modeled as a + free-form object. + operationId: dashboard_GetKubeDbObjectQuotaHistoryView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: clusterUID + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: objectID + in: path + required: true + description: Object (database) ID. + schema: + type: string + responses: + '200': + description: Object quota history view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/kubeDb/views/objects-usage-view: + get: + tags: + - Billing Dashboard + summary: KubeDB objects usage view + description: Returns the KubeDB objects usage view for the month, enriched with each object's daily + event count. Requires `view_usage_analytics:site_admin` and a billing-enabled deployment. + operationId: dashboard_GetKubeDbObjectsUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: view_type + in: query + required: false + description: View type selector. + schema: + type: string + - name: group + in: query + required: false + schema: + type: string + - name: kind + in: query + required: false + schema: + type: string + - name: clusterUID + in: query + required: false + schema: + type: string + - name: namespace + in: query + required: false + schema: + type: string + - name: namespaceUID + in: query + required: false + schema: + type: string + responses: + '200': + description: KubeDB objects usage view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/kubeDb/views/clusters-usage-view: + get: + tags: + - Billing Dashboard + summary: KubeDB clusters usage view + description: Returns the KubeDB clusters usage view for the month. Requires `view_usage_analytics:site_admin` + and a billing-enabled deployment. + operationId: dashboard_GetKubeDbClustersUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: view_type + in: query + required: false + schema: + type: string + - name: group + in: query + required: false + schema: + type: string + - name: kind + in: query + required: false + schema: + type: string + - name: contractID + in: query + required: false + schema: + type: integer + format: int64 + responses: + '200': + description: KubeDB clusters usage view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/kubeDb/views/namespaces-usage-view: + get: + tags: + - Billing Dashboard + summary: KubeDB namespaces usage view + description: Returns the KubeDB namespaces usage view for the month. Requires `view_usage_analytics:site_admin` + and a billing-enabled deployment. + operationId: dashboard_GetKubeDbNamespacesUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: view_type + in: query + required: false + schema: + type: string + - name: clusterUID + in: query + required: false + schema: + type: string + responses: + '200': + description: KubeDB namespaces usage view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/kubeDb/views/gks-usage-view: + get: + tags: + - Billing Dashboard + summary: KubeDB GKs usage view + description: Returns the KubeDB "GKs" (group/kind) usage view for the month, with total monthly + usage matrix. Requires `view_usage_analytics:site_admin` and a billing-enabled deployment. + operationId: dashboard_GetKubeDbGksUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: view_type + in: query + required: false + schema: + type: string + - name: clusterUID + in: query + required: false + schema: + type: string + responses: + '200': + description: KubeDB GKs usage view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/kubeDb/views/contracts-usage-view: + get: + tags: + - Billing Dashboard + summary: KubeDB contracts usage view + description: Returns the KubeDB contracts usage view for the month. Requires `view_usage_analytics:site_admin` + and a billing-enabled deployment. + operationId: dashboard_GetKubeDbContractsUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: view_type + in: query + required: false + schema: + type: string + responses: + '200': + description: KubeDB contracts usage view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/kubeDb/views/object-quota-history-summaries-view: + get: + tags: + - Billing Dashboard + summary: KubeDB object quota history summaries view + description: Returns the month-specific KubeDB object quota-history summaries. Requires `view_usage_analytics:site_admin` + and a billing-enabled deployment. + operationId: dashboard_GetKubeDbQuotaHistoryMonthSpecificSummariesView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + responses: + '200': + description: Object quota history summaries view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + ? /dashboard/summary/{year}/{month}/usage-report/products/kubeDb/views/object-quota-history-summaries-view/clusters/{clusterUID}/objects/{objectID} + : get: + tags: + - Billing Dashboard + summary: KubeDB object quota history summary (specific object) + description: Returns the month-specific KubeDB object quota-history summary for a specific cluster/object. + Requires `view_usage_analytics:site_admin` and a billing-enabled deployment. + operationId: dashboard_GetSpecificGetKubeDbQuotaHistoryMonthSpecificSummaryView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: clusterUID + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: objectID + in: path + required: true + description: Object (database) ID. + schema: + type: string + responses: + '200': + description: Object quota history summary view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/kubeDb/views/objects-cluster-mode-usage-view: + get: + tags: + - Billing Dashboard + summary: KubeDB objects cluster-mode usage view + description: Returns the KubeDB objects cluster-mode usage history list for the month. Requires + `view_usage_analytics:site_admin` and a billing-enabled deployment. + operationId: dashboard_GetAllObjectsClusterModeUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + responses: + '200': + description: Objects cluster-mode usage history list view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + ? /dashboard/summary/{year}/{month}/usage-report/products/kubeDb/views/objects-cluster-mode-usage-view/clusters/{clusterUID}/objects/{objectID} + : get: + tags: + - Billing Dashboard + summary: KubeDB object cluster-mode usage view (specific object) + description: Returns the KubeDB cluster-mode usage history for a specific cluster/ object. Requires + `view_usage_analytics:site_admin` and a billing-enabled deployment. + operationId: dashboard_GetSpecificKubeDbObjectClusterModeUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: clusterUID + in: path + required: true + description: Cluster UID. + schema: + type: string + - name: objectID + in: path + required: true + description: Object (database) ID. + schema: + type: string + responses: + '200': + description: Object cluster-mode usage history view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/kubeStash/views/clusters-usage-view: + get: + tags: + - Billing Dashboard + summary: KubeStash clusters usage view + description: Returns the KubeStash clusters usage view for the month. Requires `view_usage_analytics:site_admin` + and a billing-enabled deployment. + operationId: dashboard_GetKubeStashClustersUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: view_type + in: query + required: false + schema: + type: string + - name: contractID + in: query + required: false + schema: + type: integer + format: int64 + responses: + '200': + description: KubeStash clusters usage view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/kubeStash/views/contracts-usage-view: + get: + tags: + - Billing Dashboard + summary: KubeStash contracts usage view + description: Returns the KubeStash contracts usage view for the month. Requires `view_usage_analytics:site_admin` + and a billing-enabled deployment. + operationId: dashboard_GetKubeStashContractsUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: view_type + in: query + required: false + schema: + type: string + responses: + '200': + description: KubeStash contracts usage view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/kubeVault/views/clusters-usage-view: + get: + tags: + - Billing Dashboard + summary: KubeVault clusters usage view + description: Returns the KubeVault clusters usage view for the month. Requires `view_usage_analytics:site_admin` + and a billing-enabled deployment. + operationId: dashboard_GetKubeVaultClustersUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: view_type + in: query + required: false + schema: + type: string + - name: contractID + in: query + required: false + schema: + type: integer + format: int64 + responses: + '200': + description: KubeVault clusters usage view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/kubeVault/views/contracts-usage-view: + get: + tags: + - Billing Dashboard + summary: KubeVault contracts usage view + description: Returns the KubeVault contracts usage view for the month. Requires `view_usage_analytics:site_admin` + and a billing-enabled deployment. + operationId: dashboard_GetKubeVaultContractsUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: view_type + in: query + required: false + schema: + type: string + responses: + '200': + description: KubeVault contracts usage view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/voyager/views/clusters-usage-view: + get: + tags: + - Billing Dashboard + summary: Voyager clusters usage view + description: Returns the Voyager clusters usage view for the month. Requires `view_usage_analytics:site_admin` + and a billing-enabled deployment. + operationId: dashboard_GetVoyagerClustersUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: view_type + in: query + required: false + schema: + type: string + - name: contractID + in: query + required: false + schema: + type: integer + format: int64 + responses: + '200': + description: Voyager clusters usage view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/usage-report/products/voyager/views/contracts-usage-view: + get: + tags: + - Billing Dashboard + summary: Voyager contracts usage view + description: Returns the Voyager contracts usage view for the month. Requires `view_usage_analytics:site_admin` + and a billing-enabled deployment. + operationId: dashboard_GetVoyagerContractsUsageView + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + - name: view_type + in: query + required: false + schema: + type: string + responses: + '200': + description: Voyager contracts usage view. + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '400': + $ref: '#/components/responses/ValidationError' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dashboard/summary/{year}/{month}/download: + get: + tags: + - Billing Dashboard + summary: Download the monthly usage report (PDF) + description: Renders and returns the KubeDB usage summary as a PDF document for the given month. + Requires `view_usage_analytics:site_admin` and a billing-enabled deployment. + operationId: dashboard_DownloadKubeDbPdfReport + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/summaryYearParam' + - $ref: '#/components/parameters/summaryMonthParam' + responses: + '200': + description: The usage report PDF. + content: + application/pdf: + schema: + type: string + format: binary + application/octet-stream: + schema: + type: string + format: binary + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dbaas/billing/reports/namespaces: + get: + tags: + - Billing Dashboard + summary: List DBaaS namespace reports + description: Returns the DBaaS namespace report list (V1) for the owner. Requires a billing-enabled + deployment. + operationId: dashboard_GetNamespaceReportList + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: Namespace report list (pre-marshaled view, free-form). + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /dbaas/billing/reports/clusters/{clusterID}/namespaces/{namespaceName}: + get: + tags: + - Billing Dashboard + summary: Get a DBaaS namespace report + description: Returns the DBaaS namespace report (V1) for a specific cluster/namespace. Requires + a billing-enabled deployment. + operationId: dashboard_GetNamespaceReport + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: clusterID + in: path + required: true + description: Cluster ID. + schema: + type: string + - name: namespaceName + in: path + required: true + description: Namespace name. + schema: + type: string + responses: + '200': + description: Namespace report (pre-marshaled view, free-form). + content: + application/json: + schema: + $ref: '#/components/schemas/UsageView' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /marketplaces/standalone-organizations/{claimID}/claimable: + get: + tags: + - Marketplace + summary: Check whether a standalone marketplace organization is claimable + description: 'Served by the marketplace webhook listener (rooted at `/marketplace/api/v1`). Evaluates + the claim-rules flags of a standalone (marketplace-created) organization identified by its claim + ID and reports whether it can currently be claimed. This endpoint is public. Note: this webhook + listener also serves GET /version (identical to the main server /version).' + operationId: marketplace_CheckClaimRulesOfStandaloneOrg + x-listener: marketplace + security: [] + parameters: + - name: claimID + in: path + required: true + description: The claim ID of the standalone organization. + schema: + type: string + responses: + '200': + description: Claimable check result. Returned both when the organization is claimable and when + the retry backoff has not yet expired but the organization is already flagged claimable. + content: + application/json: + schema: + $ref: '#/components/schemas/OrgClaimableCheckResp' + '404': + description: Standalone organization not found. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '409': + description: The organization is already claimed. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '429': + description: Retry backoff is not expired; try again later. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + description: Internal server error while evaluating claim rules. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + servers: &id001 + - url: https://{host}/marketplace/api/v1 + description: Marketplace webhook listener (separate service) + variables: + host: + default: appscode.com + description: Deployment host + /marketplaces/aws/notification/resource: + post: + tags: + - Marketplace + summary: Handle an AWS Marketplace webhook notification + description: 'Served by the marketplace webhook listener (rooted at `/marketplace/api/v1`). Receives + AWS Marketplace bind-event notifications. Authentication is enforced by the webhook itself: the + request payload is verified (`marketplace` must be `Aws`, cluster ID and options validated) and, + outside dev run mode, the source IP must fall within the allowed AWS EC2 IP ranges. No platform + bearer-token security applies.' + operationId: marketplace_HandleAwsWebhookCalls + x-listener: marketplace + security: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AwsWebhookNotification' + responses: + '200': + description: Subscription bound successfully. Returns the installer archive download link. + content: + application/json: + schema: + type: object + properties: + link: + type: string + '400': + description: Payload verification, binding-info validation, or installer option processing failed. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '403': + description: Request originated from an unauthorized IP address. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + description: Internal server error while provisioning the subscription. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + servers: *id001 + /marketplaces/azure/notification/resource: + post: + tags: + - Marketplace + summary: Handle an Azure Marketplace webhook notification + description: Served by the marketplace webhook listener (rooted at `/marketplace/api/v1`). Receives + Azure Marketplace lifecycle notifications (`PUT`, `DELETE`, `BIND`). Authentication is enforced + by the webhook itself via a per-installer `secret` query parameter that must match the configured + marketplace API secret. No platform bearer-token security applies. + operationId: marketplace_HandleAzureWebhookCalls + x-listener: marketplace + security: [] + parameters: + - name: secret + in: query + required: false + description: Marketplace API secret used to authenticate the Azure webhook call. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AzureWebhookNotification' + responses: + '200': + description: Notification processed successfully. For `PUT`/`DELETE` events an empty body with + status 200 is returned; for `BIND` events the installer archive link is returned. + '400': + description: Invalid subscription ID, unknown event type, or invalid binding info. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '403': + description: Marketplace API secret mismatch, or subscription not found while revoking contracts + on delete. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + description: Internal server error while processing the notification. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + servers: *id001 + /marketplaces/gcp/notification/resource: + post: + tags: + - Marketplace + summary: Handle a GCP Marketplace webhook notification + description: Served by the marketplace webhook listener (rooted at `/marketplace/api/v1`). Receives + GCP Marketplace bind-event notifications. Authentication is enforced by the webhook itself via + a per-installer `secret` query parameter that must match the configured marketplace API secret + (bypassed only for the designated GCP Marketplace test installer). No platform bearer-token security + applies. + operationId: marketplace_HandleGcpWebhookCalls + x-listener: marketplace + security: [] + parameters: + - name: secret + in: query + required: false + description: Marketplace API secret used to authenticate the GCP webhook call. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GcpWebhookNotification' + responses: + '200': + description: Subscription bound successfully. Returns the installer archive download link. + content: + application/json: + schema: + type: object + properties: + link: + type: string + '400': + description: Invalid binding info or installer lookup failure. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '403': + description: Marketplace API secret mismatch or installer already bound. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + '500': + description: Internal server error while provisioning the subscription. + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + servers: *id001 + /proxy/metered-billing/marketplaces/aws/report-usage: + post: + tags: + - Marketplace + summary: Proxy a metered-usage report to AWS Marketplace Metering + description: Forwards a usage report to the AWS Marketplace Metering service. Requires site-admin + privileges. This route is only registered when the b3 deployment type is `AWSMarketplaceDeployment`; + on other deployments it does not exist. + operationId: marketplace_ReportAwsUsage + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/MeterUsageInput' + responses: + '200': + description: Usage reported successfully. Returns the AWS metering record. + content: + application/json: + schema: + $ref: '#/components/schemas/MeterUsageOutput' + '400': + description: AWS Marketplace Metering rejected the request (e.g. customer not entitled, duplicate + request, invalid product code, or throttling). + content: + application/json: + schema: + $ref: '#/components/schemas/AwsMeteringProxyErr' + '401': + description: Authentication required. + '403': + description: Site-admin privileges required. + '422': + description: Unprocessable request body. + '500': + description: Failed to report usage to AWS, or an unmapped AWS error code was returned. + content: + application/json: + schema: + $ref: '#/components/schemas/AwsMeteringProxyErr' + /proxy/metered-billing/marketplaces/aws/check/readiness: + get: + tags: + - Marketplace + summary: Check readiness of the AWS metering proxy endpoint + description: Readiness probe for the AWS metering proxy. Requires site-admin privileges. This route + is only registered when the b3 deployment type is `AWSMarketplaceDeployment`; on other deployments + it does not exist. + operationId: marketplace_ReadinessCheckAwsMeteringEndpoint + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: The AWS metering proxy is ready. + '401': + description: Authentication required. + '403': + description: Site-admin privileges required. + /proxy/metered-billing/marketplaces/gcp/report-usage: + post: + tags: + - Marketplace + summary: Proxy a metered-usage report to GCP Service Control + description: Forwards a usage report to the GCP Service Control reporting API. Requires site-admin + privileges. This route is only registered when the b3 deployment type is `GCPMarketplaceDeployment`; + on other deployments it does not exist. + operationId: marketplace_ReportGcpUsage + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GcpUsageReport' + responses: + '200': + description: Usage reported successfully. Returns the GCP Service Control report response. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Authentication required. + '403': + description: Site-admin privileges required. + '422': + description: Unprocessable request body. + '500': + description: Failed to report usage to GCP Service Control. + /proxy/metered-billing/marketplaces/gcp/check/readiness: + get: + tags: + - Marketplace + summary: Check readiness of the GCP metering proxy endpoint + description: Readiness probe for the GCP metering proxy. Requires site-admin privileges. This route + is only registered when the b3 deployment type is `GCPMarketplaceDeployment`; on other deployments + it does not exist. + operationId: marketplace_ReadinessCheckGcpMeteringEndpoint + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: The GCP metering proxy is ready. + '401': + description: Authentication required. + '403': + description: Site-admin privileges required. + /telemetry/{owner}/monitoring-clusters: + get: + tags: + - Monitoring & Telemetry + summary: List monitoring clusters of the owner + description: Returns the names of clusters imported by the owner that are configured as monitoring + clusters, optionally filtered to the region of the target cluster given by the `targetClusterName` + query parameter. Requires the caller to be an admin of the {owner} organization. + operationId: telemetry_GetMonitoringClustersOfThisOwner + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: targetClusterName + in: query + required: false + schema: + type: string + description: Name of the target cluster used to determine the region filter. + responses: + '200': + description: List of monitoring cluster names. + content: + application/json: + schema: + type: array + items: + type: string + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not an org admin. + '500': + description: Internal server error. + /telemetry/{owner}/{cluster}/stack: + post: + tags: + - Monitoring & Telemetry + summary: Create a TelemetryStack on the monitoring cluster + description: Creates a TelemetryStack custom resource on the given monitoring cluster and marks + the cluster as a monitoring cluster. Requires the caller to be an admin of the {owner} organization. + operationId: telemetry_CreateTelemetryStack + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: cluster + in: path + required: true + schema: + type: string + description: Name of the monitoring cluster. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateTelemetryStackRequest' + responses: + '200': + description: The created TelemetryStack object. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not an org admin. + '500': + description: Internal server error. + /telemetry/{owner}/{cluster}/values/appscode-otel-stack: + get: + tags: + - Monitoring & Telemetry + summary: Get appscode-otel-stack Helm values for a cluster + description: Returns the Helm values for the `opentelemetry-kube-stack` chart to be installed on + the target cluster (given by the `targetClusterName` query parameter) so it ships telemetry to + the given monitoring cluster. Requires the caller to be an admin of the {owner} organization. + operationId: telemetry_GetOtelKubestackValuesOfCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: cluster + in: path + required: true + schema: + type: string + description: Name of the monitoring cluster. + - name: targetClusterName + in: query + required: true + schema: + type: string + description: Name of the target cluster the values are generated for. + responses: + '200': + description: A dynamic Helm values object for the appscode-otel-stack chart. + content: + application/json: + schema: + $ref: '#/components/schemas/K8sObject' + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not an org admin. + '500': + description: Internal server error. + /telemetry/{owner}/{cluster}/stack/host: + get: + tags: + - Monitoring & Telemetry + summary: Get the host of a monitoring cluster + description: Returns the ingress host (hostname or IP) of the given monitoring cluster used by telemetry + collectors. Requires the caller to be an admin of the {owner} organization. + operationId: telemetry_GetHostOfMonitoringCluster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: cluster + in: path + required: true + schema: + type: string + description: Name of the monitoring cluster. + responses: + '200': + description: The host string of the monitoring cluster. + content: + application/json: + schema: + type: string + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not an org admin. + '500': + description: Internal server error. + /telemetry/{owner}/{cluster}/tenants/ownerlist: + get: + tags: + - Monitoring & Telemetry + summary: List tenant owners on a monitoring cluster + description: Lists the Tenant custom resources present on the given monitoring cluster, returning + a map of tenant owner identifier (`ace.user.{id}`) to the ACE user name. Requires the caller to + be an admin of the {owner} organization. + operationId: telemetry_GetTenantOwner + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/ownerParam' + - name: cluster + in: path + required: true + schema: + type: string + description: Name of the monitoring cluster. + responses: + '200': + description: Map of tenant owner identifier to ACE user name. + content: + application/json: + schema: + type: object + additionalProperties: + type: string + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not an org admin. + '500': + description: Internal server error. + /trickster/register: + post: + tags: + - Monitoring & Telemetry + summary: Register a Trickster (Grafana) backend + description: Registers a Prometheus backend with the Trickster proxy and returns a Grafana datasource + response. Requires a valid token and org-admin context. + operationId: trickster_RegisterTricksterBackend + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RegisterRequest' + responses: + '200': + description: Grafana datasource response. + content: + application/json: + schema: + $ref: '#/components/schemas/GrafanaDatasourceResponse' + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not an org admin. + '404': + description: Cluster not found. + '500': + description: Internal server error. + /trickster/perses/register: + post: + tags: + - Monitoring & Telemetry + summary: Register a Trickster (Perses) backend + description: Registers a Prometheus backend with the Trickster proxy and returns a Perses datasource + response. Requires a valid token and org-admin context. + operationId: trickster_RegisterTricksterBackendForPerses + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RegisterRequest' + responses: + '200': + description: Perses datasource response. + content: + application/json: + schema: + $ref: '#/components/schemas/PersesDatasourceResponse' + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not an org admin. + '404': + description: Cluster not found. + '500': + description: Internal server error. + /trickster/unregister: + post: + tags: + - Monitoring & Telemetry + summary: Unregister a Trickster (Grafana) backend + description: Removes the Trickster backend and Grafana datasource associated with the given Prometheus + context. Requires a valid token and org-admin context. + operationId: trickster_UnregisterTricksterBackend + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PrometheusContext' + responses: + '200': + description: Backend unregistered. + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not an org admin. + '404': + description: Cluster not found. + '500': + description: Internal server error. + /trickster/perses/unregister: + post: + tags: + - Monitoring & Telemetry + summary: Unregister a Trickster (Perses) backend + description: Removes the Trickster backend and Perses datasource associated with the given Prometheus + context. Requires a valid token and org-admin context. + operationId: trickster_UnregisterTricksterBackendForPerses + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PrometheusContext' + responses: + '200': + description: Backend unregistered. + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not an org admin. + '404': + description: Cluster not found. + '500': + description: Internal server error. + /trickster/auth/{uidcid}/{path}: + get: + tags: + - Monitoring & Telemetry + summary: Check cluster ownership for Trickster auth + description: Auth-proxy hook used by prom-authproxy. Validates that the caller owns (or is a member + of the org that owns) the cluster identified by the `uid.clusterid[.projectid]` path segment and + returns owner/cluster/tenant metadata. The trailing wildcard path captures the proxied request + path. Requires a valid token and org-admin context. + operationId: trickster_CheckClusterOwnershipForTrickster + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - name: uidcid + in: path + required: true + schema: + type: string + description: Identifier following the `uid.clusterid[.projectid]` pattern. + - name: path + in: path + required: true + schema: + type: string + description: Remaining proxied request path (matched by the trailing wildcard). + responses: + '200': + description: Cluster ownership metadata. + content: + application/json: + schema: + type: object + additionalProperties: + type: string + description: Contains keys `owner`, `clusterName`, `tenantID`, and optionally `clientOrg`. + '400': + description: Bad request — malformed id parameter. + '401': + description: Unauthorized — caller is not an organization member. + '403': + description: Forbidden. + '404': + description: Cluster or owner not found. + '500': + description: Internal server error. + /rancher/org/{orgname}/sync/users: + get: + tags: + - Rancher + summary: Sync Rancher users into the organization + description: Imports users from the org's Rancher management cluster into ACE, creating ACE users + and adding them to the viewer team. Requires site-admin privileges and a Rancher-managed organization. + operationId: rancher_SyncRancherUsers + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: Result of the sync operation. + content: + application/json: + schema: + type: object + properties: + synced_users: + type: array + items: + type: string + failed_users: + type: array + items: + type: object + additionalProperties: + type: string + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not a site admin. + '500': + description: Internal server error. + /rancher/org/{orgname}/acerproxy: + get: + tags: + - Rancher + summary: Get the acerproxy Helm installation command + description: Returns a ready-to-run Helm command to install the acerproxy chart, wired with a freshly + issued Rancher extended server token and the platform base URL. Requires site-admin privileges + and a Rancher-managed organization. + operationId: rancher_GetAcerProxyInstallationCommand + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: Object containing the Helm installation command. + content: + application/json: + schema: + type: object + properties: + helm: + type: string + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not a site admin. + '500': + description: Internal server error. + /rancher/org/{orgname}/ca/download: + get: + tags: + - Rancher + summary: Download the platform CA certificate + description: Returns the platform CA certificate as a downloadable text file (`ace-ca.txt`). Requires + site-admin privileges and a Rancher-managed organization. + operationId: rancher_DownloadCA + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + parameters: + - $ref: '#/components/parameters/orgnameParam' + responses: + '200': + description: The CA certificate file. + content: + text/plain: + schema: + type: string + '400': + description: No CA certificate found. + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not a site admin. + '500': + description: Internal server error. + /rancher/proxy-token: + post: + tags: + - Rancher + summary: Create a Rancher proxy server token + description: Creates a Rancher extended server token for the given Rancher URL and returns it in + access-token API format. Requires site-admin privileges. + operationId: rancher_CreateRancherProxyServerToken + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + requestBody: + required: true + description: A string map; the `rancherUrl` key specifies the Rancher management cluster endpoint. + content: + application/json: + schema: + type: object + additionalProperties: + type: string + responses: + '201': + description: The created access token. + content: + application/json: + schema: + $ref: '#/components/schemas/AccessToken' + '401': + description: Unauthorized. + '403': + description: Forbidden — caller is not a site admin. + '500': + description: Internal server error. + /rancher/nats-cred: + get: + tags: + - Rancher + summary: Get NATS user credentials for the Rancher user + description: Returns the primary NATS user JWT and seed for the authenticated Rancher user, recreating + the primary NATS account if the existing credentials are no longer authorized. Requires a valid + token (Rancher user context injected by injectRancherUserInfo). + operationId: rancher_GetNatsUserCredentials + security: + - AuthorizationHeaderToken: [] + - Token: [] + - AccessToken: [] + responses: + '200': + description: NATS user credentials. + content: + application/json: + schema: + type: object + properties: + user-jwt: + type: string + user-seed: + type: string + url: + type: string + description: Present only when two external NATS addresses are configured. + '401': + description: Unauthorized. + '403': + description: Forbidden. + '500': + description: Internal server error. + /chartrepositories: + get: + tags: + - Chart Repositories + summary: List Helm Hub chart repositories + description: Returns the list of known Helm Hub chart repositories. Public endpoint. + operationId: charts_repo_GetChartRepos + security: [] + responses: + '200': + description: List of chart repository entries. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ChartRepositoryEntry' + '500': + description: Internal server error. + /chartrepositories/charts: + get: + tags: + - Chart Repositories + summary: List charts in a chart repository + description: Loads the chart repository at the given `url` and returns the list of charts it contains. + Public endpoint. + operationId: charts_repo_GetCharts + security: [] + parameters: + - name: url + in: query + required: true + schema: + type: string + description: URL of the chart repository. + responses: + '200': + description: List of charts in the repository. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ChartVersion' + '400': + description: Missing chart repo url. + '500': + description: Internal server error. + /chartrepositories/charts/{name}/versions: + get: + tags: + - Chart Repositories + summary: List versions of a chart + description: Loads the chart repository at the given `url` and returns the available versions of + the named chart. Public endpoint. + operationId: charts_repo_GetChartVersions + security: [] + parameters: + - name: name + in: path + required: true + schema: + type: string + description: Name of the chart. + - name: url + in: query + required: true + schema: + type: string + description: URL of the chart repository. + responses: + '200': + description: List of chart versions. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ChartVersion' + '400': + description: Missing chart repo url or chart name. + '500': + description: Internal server error. + /version: + get: + tags: + - Miscellaneous + summary: Get the server version + description: Returns the version of the server application. Public endpoint. + operationId: misc_Version + security: [] + responses: + '200': + description: The server version. + content: + application/json: + schema: + $ref: '#/components/schemas/ServerVersion' + /markdown: + post: + tags: + - Miscellaneous + summary: Render a markdown document as HTML + description: Renders the supplied markdown as HTML. In `gfm` mode links are resolved relative to + the provided context. Public endpoint. + operationId: misc_Markdown + security: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/MarkdownOption' + responses: + '200': + description: The rendered HTML. + content: + text/html: + schema: + type: string + '422': + description: Validation error. + /markdown/raw: + post: + tags: + - Miscellaneous + summary: Render raw markdown as HTML + description: Renders the raw markdown request body (text/plain) as HTML. Public endpoint. + operationId: misc_MarkdownRaw + security: [] + requestBody: + required: true + description: Raw markdown text to render. + content: + text/plain: + schema: + type: string + responses: + '200': + description: The rendered HTML. + content: + text/html: + schema: + type: string + '422': + description: Validation error. + /swagger: + get: + tags: + - Miscellaneous + summary: Render the Swagger UI page + description: Serves the Swagger UI HTML page for the v1 API. Only registered when swagger is enabled + in the server configuration. Public endpoint. + operationId: misc_Swagger + security: [] + responses: + '200': + description: The Swagger UI HTML page. + content: + text/html: + schema: + type: string +components: + securitySchemes: + AuthorizationHeaderToken: + type: apiKey + in: header + name: Authorization + description: 'Personal access token, prefixed with the literal "token ": `Authorization: token `.' + Token: + type: apiKey + in: query + name: token + description: Personal access token supplied as a query parameter. + AccessToken: + type: apiKey + in: query + name: access_token + description: Personal access token supplied as the `access_token` query parameter. + BasicAuth: + type: http + scheme: basic + description: HTTP Basic authentication, used by token-management endpoints (optionally with an OTP + header for 2FA). + SessionCookie: + type: apiKey + in: cookie + name: i_like_ace + description: Session cookie issued to the web console after sign-in (CSRF-protected). The cookie + name is configurable via the session COOKIE_NAME setting. + SudoParam: + type: apiKey + in: query + name: sudo + description: Site-admin impersonation of the named user. + SudoHeader: + type: apiKey + in: header + name: Sudo + description: Site-admin impersonation of the named user. + parameters: + ownerParam: + name: owner + in: path + required: true + description: Organization slug or username that owns the cluster. + schema: &id003 + type: string + clusterParam: + name: cluster + in: path + required: true + description: Cluster name within the owner scope. + schema: &id002 + type: string + orgnameParam: + name: orgname + in: path + required: true + description: Organization slug. + schema: + type: string + orgnameQuery: + name: org + in: query + required: false + description: Organization slug providing org context, resolved from the `?org=` query parameter + (used by admin/authorization endpoints). + schema: + type: string + OwnerQueryParam: + name: org + in: query + required: false + description: Owner (organization) context supplied as the `?org=` query parameter (used by contract + endpoints). + schema: + type: string + usernameParam: + name: username + in: path + required: true + description: Account username. + schema: &id004 + type: string + pageParam: + name: page + in: query + required: false + description: Page number of results to return (1-based). + schema: + type: integer + limitParam: + name: limit + in: query + required: false + description: Page size of results. + schema: + type: integer + summaryYearParam: + name: year + in: path + required: true + description: Report year (e.g. `2026`). + schema: + type: string + summaryMonthParam: + name: month + in: path + required: true + description: Report month name (case-insensitive, e.g. `january`). + schema: + type: string + cluster: + name: cluster + in: path + required: true + description: Cluster name within the owner scope. + schema: *id002 + clusterPathParam: + name: cluster + in: path + required: true + description: Cluster name within the owner scope. + schema: *id002 + owner: + name: owner + in: path + required: true + description: Organization slug or username that owns the cluster. + schema: *id003 + ownerPathParam: + name: owner + in: path + required: true + description: Organization slug or username that owns the cluster. + schema: *id003 + username: + name: username + in: path + required: true + description: Account username. + schema: *id004 + responses: + NotFound: + description: The target could not be found. + content: &id006 + application/json: + schema: + $ref: '#/components/schemas/APIError' + Unauthorized: + description: Authentication is required or has failed. + content: &id007 + application/json: + schema: + $ref: '#/components/schemas/APIError' + Forbidden: + description: The caller is authenticated but not authorized for this action. + content: &id005 + application/json: + schema: + $ref: '#/components/schemas/APIError' + ValidationError: + description: The request body or parameters failed validation. + content: &id008 + application/json: + schema: + $ref: '#/components/schemas/APIError' + forbidden: + description: The caller is authenticated but not authorized for this action. + content: *id005 + notFound: + description: The target could not be found. + content: *id006 + unauthorized: + description: Authentication is required or has failed. + content: *id007 + validationError: + description: The request body or parameters failed validation. + content: *id008 + schemas: + APIError: + type: object + description: Standard error envelope returned by the API on failure. + properties: + message: + type: string + url: + type: string + K8sObject: + type: object + description: A free-form Kubernetes object (arbitrary group/version/kind). Passed through to/from + the member cluster verbatim. + additionalProperties: true + K8sStatus: + type: object + description: A Kubernetes metav1.Status object. + additionalProperties: true + ObjectReference: + type: object + description: A reference to a Kubernetes object (kmodules ObjectReference). + properties: + namespace: + type: string + name: + type: string + GroupVersionResource: + type: object + properties: + group: + type: string + version: + type: string + resource: + type: string + User: + type: object + description: Represents a user (individual or organization). + properties: + id: + type: integer + format: int64 + login: + type: string + description: The user's username. + username: + type: string + description: Backward-compatibility alias of login (added via custom MarshalJSON). + full_name: + type: string + email: + type: string + format: email + avatar_url: + type: string + language: + type: string + is_admin: + type: boolean + last_login: + type: string + format: date-time + created: + type: string + format: date-time + type: + type: integer + active: + type: boolean + prohibit_login: + type: boolean + location: + type: string + website: + type: string + description: + type: string + orgAdmin: + type: boolean + orgType: + type: integer + clientOrgUser: + type: boolean + Email: + type: object + description: An email address belonging to a user. + properties: + email: + type: string + format: email + verified: + type: boolean + primary: + type: boolean + CreateEmailOption: + type: object + description: Options when creating email addresses. + properties: + emails: + type: array + items: + type: string + DeleteEmailOption: + type: object + description: Options when deleting email addresses. + properties: + emails: + type: array + items: + type: string + AccessToken: + type: object + description: An API access token (structs.AccessToken). + properties: + id: + type: integer + format: int64 + name: + type: string + sha1: + type: string + description: The plaintext token, returned only on creation. + token_last_eight: + type: string + CreateAccessTokenOption: + type: object + description: Options when creating an access token. + required: + - name + properties: + name: + type: string + Organization: + type: object + description: Represents an organization. + properties: + id: + type: integer + format: int64 + username: + type: string + full_name: + type: string + avatar_url: + type: string + description: + type: string + website: + type: string + location: + type: string + rancherManagementClusterEndPoint: + type: string + visibility: + type: string + orgType: + type: integer + Team: + type: object + description: Represents a team in an organization. + properties: + id: + type: integer + format: int64 + name: + type: string + description: + type: string + organization: + $ref: '#/components/schemas/Organization' + permission: + type: string + description: One of none, read, write, admin, owner. + units: + type: array + items: + type: string + type: + type: string + role_ids: + type: array + items: + type: integer + format: int64 + FirebaseToken: + type: object + description: A Firebase custom auth token. + properties: + firebaseToken: + type: string + NatsCredentialsResponse: + type: object + description: NATS endpoints and credential bytes for the authenticated user. + properties: + natsEndpoints: + type: array + items: + type: string + credentials: + type: string + format: byte + SignInParams: + type: object + description: Credentials for signing in with username and password. + properties: + username: + type: string + password: + type: string + remember: + type: boolean + Profile: + type: object + description: Editable user profile fields. + properties: + name: + type: string + full_name: + type: string + email: + type: string + format: email + keep_email_private: + type: boolean + website: + type: string + location: + type: string + language: + type: string + description: + type: string + AvatarParams: + type: object + description: Avatar settings. On update accepts multipart/form-data with an avatar file. + properties: + source: + type: string + avatar: + type: string + format: binary + description: Uploaded avatar file (multipart). + gravatar: + type: string + federavatar: + type: boolean + UpdatePasswordParams: + type: object + description: Fields for updating the user's password. + properties: + old_password: + type: string + password: + type: string + retype: + type: string + AddEmailParams: + type: object + description: Field for adding a new email address. + properties: + email: + type: string + format: email + Pagination: + type: object + description: Per-UI pagination page-size settings (models.Pagination). + properties: + kubeDBUI: + type: integer + format: int64 + consoleUI: + type: integer + format: int64 + platformUI: + type: integer + format: int64 + Validation: + type: object + description: Result of a username/orgname/email validation check. + properties: + Status: + type: string + description: One of VALID, USER_EXISTS, RESERVED, INVALID, NOT_ALLOWED. + TwoFAStatus: + type: object + description: Two-factor enrollment status. + properties: + twoFAEnrolled: + type: boolean + TwoFactorAuthParams: + type: object + description: TOTP passcode used to complete two-factor enrollment. + properties: + passCode: + type: string + Security: + type: object + description: TOTP secret and QR image data URL for two-factor enrollment. + properties: + twoFASecret: + type: string + twoFAImageURL: + type: string + description: data:image/png;base64 encoded QR code. + WebauthnRegistrationOptions: + type: object + description: Options for reserving a WebAuthn credential name. + required: + - name + properties: + name: + type: string + WebAuthnSecurityKeys: + type: object + description: A registered WebAuthn security key. + properties: + ID: + type: integer + format: int64 + Name: + type: string + UID: + type: integer + format: int64 + SessionInfoAPIForm: + type: object + description: 'A user session record. Embeds go-macaron session.SessInfo (opaque, protocol-defined) + plus the fields below. + + ' + properties: + isActiveSession: + type: boolean + lastAccessedZonedTime: + type: string + lastAccessed: + type: integer + format: int64 + AccountLink: + type: object + description: A linked external (OAuth2/login-source) account. + properties: + loginSourceID: + type: integer + format: int64 + externalID: + type: string + type: + type: integer + providerDisplayName: + type: string + isActived: + type: boolean + isSyncEnabled: + type: boolean + AccountLinkParams: + type: object + description: Identifies a linked account to remove. + properties: + loginSourceID: + type: integer + format: int64 + externalID: + type: string + CreateOrgParams: + type: object + description: Multipart form for creating an organization. + properties: + orgName: + type: string + orgFullName: + type: string + description: + type: string + website: + type: string + location: + type: string + orgType: + type: string + rancherManagementClusterEndPoint: + type: string + provideSyncToken: + type: boolean + rancherSyncToken: + $ref: '#/components/schemas/RancherAccessToken' + visibility: + type: string + source: + type: string + avatar: + type: string + format: binary + gravatar: + type: string + federavatar: + type: boolean + RancherAccessToken: + type: object + description: Rancher sync-token access key pair (settings.AccessToken). + properties: + rancherSyncTokenAccessKeyID: + type: string + rancherSyncTokenSecretAccessKey: + type: string + ApiResponseMessage: + type: object + description: Generic message wrapper. + properties: + message: + type: string + NewAccessTokenParam: + type: object + description: Parameters for creating a new access token via settings. + properties: + name: + type: string + expTime: + type: integer + format: int64 + description: Unix timestamp expiry; 0 means no expiry. + AccessTokenIdList: + type: object + description: List of access token IDs to delete. + properties: + tokenIDs: + type: array + items: + type: integer + format: int64 + SettingsAccessToken: + type: object + description: Access token in the settings API format (pkg.AccessToken). + properties: + id: + type: integer + format: int64 + uid: + type: integer + format: int64 + name: + type: string + token: + type: string + description: The plaintext token, returned only on creation. + tokenLastEight: + type: string + createdAt: + type: integer + format: int64 + updatedAt: + type: integer + format: int64 + hasRecentActivity: + type: boolean + hasUsed: + type: boolean + expDate: + type: integer + format: int64 + description: TimeStamp (Unix seconds). + OAuth2ApplicationParams: + type: object + description: Parameters for creating/updating an OAuth2 application. + properties: + name: + type: string + redirectUri: + type: string + logo: + type: string + format: binary + description: Logo file (multipart, on update). + OAuth2Application: + type: object + description: An OAuth2 application (pkg.OAuth2Application). + properties: + id: + type: integer + format: int64 + uid: + type: integer + format: int64 + name: + type: string + clientId: + type: string + clientSecret: + type: string + description: Plaintext client secret, returned only on create/regenerate. + clientSecretHash: + type: string + redirectURIs: + type: array + items: + type: string + logo: + type: string + createdAt: + type: integer + format: int64 + updatedAt: + type: integer + format: int64 + OAuth2Grant: + type: object + description: An OAuth2 grant (pkg.OAuth2Grant). + properties: + id: + type: integer + format: int64 + userId: + type: integer + format: int64 + applicationId: + type: integer + format: int64 + applicationName: + type: string + logo: + type: string + counter: + type: integer + format: int64 + createdAt: + type: integer + format: int64 + updatedAt: + type: integer + format: int64 + ClusterInfo: + type: object + description: Summary information about a cluster (pkg.ClusterInfo). + properties: + id: + type: integer + format: int64 + displayName: + type: string + name: + type: string + uid: + type: string + ownerID: + type: integer + format: int64 + managerID: + type: integer + format: int64 + externalID: + type: string + hubClusterName: + type: string + hubClusterUID: + type: string + hubClusterOwnerName: + type: string + clusterSetName: + type: string + ownerName: + type: string + provider: + type: string + vendor: + type: string + infraNamespace: + type: string + isMonitoringCluster: + type: boolean + endpoint: + type: string + location: + type: string + project: + type: string + kubernetesVersion: + type: string + nodeCount: + type: integer + format: int32 + createdAt: + type: string + format: date-time + age: + type: string + clusterManagers: + type: array + items: + type: string + isCapiClusterUpgradeable: + type: boolean + status: + $ref: '#/components/schemas/K8sObject' + description: rsapi.ClusterStatus (Kubernetes-style object). + CloudCredentialApiForm: + type: object + description: 'A cloud credential in API form. Embeds cloudv1alpha1.CredentialSpec (a Kubernetes-style + object, modeled as an opaque object) plus a creation timestamp. + + ' + properties: + creationTimestamp: + type: string + format: date-time + additionalProperties: true + BucketListOptions: + type: object + description: Options for listing storage buckets. + properties: + credential: + type: string + gce_project: + type: string + cluster_uid: + type: string + secret_namespace: + type: string + secret_name: + type: string + provider: + type: string + BucketListResponse: + type: object + description: List of bucket names. + properties: + names: + type: array + items: + type: string + CreateOrgOption: + type: object + required: + - username + properties: + username: + type: string + full_name: + type: string + description: + type: string + website: + type: string + location: + type: string + orgType: + type: string + description: possible values are `public` (default), `limited` or `private` + rancherManagementClusterEndPoint: + type: string + visibility: + type: string + enum: + - '' + - public + - limited + - private + EditOrgOption: + type: object + properties: + full_name: + type: string + description: + type: string + website: + type: string + location: + type: string + orgType: + type: string + description: possible values are `public`, `limited` or `private` + rancherManagementClusterEndPoint: + type: string + visibility: + type: string + enum: + - '' + - public + - limited + - private + OrgClaimableCheckResp: + type: object + properties: + isClaimable: + type: boolean + claimID: + type: string + CreateTeamOption: + type: object + required: + - name + - type + properties: + name: + type: string + description: + type: string + permission: + type: string + enum: + - read + - write + - admin + assignedRoleIDs: + type: array + items: + type: integer + format: int64 + type: + type: string + EditTeamOption: + type: object + required: + - name + properties: + name: + type: string + description: + type: string + permission: + type: string + enum: + - read + - write + - admin + - custom + assignedRoleIDs: + type: array + items: + type: integer + format: int64 + type: + type: string + RancherAPIToken: + type: object + properties: + userID: + type: integer + format: int64 + orgID: + type: integer + format: int64 + orgName: + type: string + accessKeyID: + type: string + secretAccessKey: + type: string + AccessTokenInfo: + type: object + description: API representation of a personal/system access token (routers/api/v1/settings/pkg.AccessToken). + properties: + id: + type: integer + format: int64 + uid: + type: integer + format: int64 + name: + type: string + token: + type: string + tokenLastEight: + type: string + createdAt: + type: integer + format: int64 + updatedAt: + type: integer + format: int64 + hasRecentActivity: + type: boolean + hasUsed: + type: boolean + expDate: + type: integer + format: int64 + description: Unix timestamp (util.TimeStamp) + NatsAccount: + type: object + description: API representation of a NATS account/token (routers/api/v1/settings/pkg.NatsAccount). + properties: + id: + type: integer + format: int64 + uid: + type: integer + format: int64 + accountType: + type: string + natsPubKey: + type: string + clusterID: + type: string + productName: + type: string + revoked: + type: boolean + CreateUserOption: + type: object + required: + - username + - email + - password + properties: + source_id: + type: integer + format: int64 + login_name: + type: string + username: + type: string + full_name: + type: string + email: + type: string + format: email + password: + type: string + must_change_password: + type: boolean + send_notify: + type: boolean + EditUserOption: + type: object + required: + - email + properties: + source_id: + type: integer + format: int64 + login_name: + type: string + full_name: + type: string + email: + type: string + format: email + password: + type: string + must_change_password: + type: boolean + website: + type: string + location: + type: string + active: + type: boolean + admin: + type: boolean + allow_git_hook: + type: boolean + allow_import_local: + type: boolean + prohibit_login: + type: boolean + allow_create_organization: + type: boolean + AdminCreateUserPayload: + type: object + required: + - loginType + - userName + - email + properties: + loginType: + type: string + loginName: + type: string + userName: + type: string + fullName: + type: string + email: + type: string + format: email + password: + type: string + sendNotify: + type: boolean + mustChangePassword: + type: boolean + AdminEditUserPayload: + type: object + required: + - loginType + - email + properties: + loginType: + type: string + loginName: + type: string + fullName: + type: string + email: + type: string + format: email + password: + type: string + website: + type: string + location: + type: string + active: + type: boolean + admin: + type: boolean + allowGitHook: + type: boolean + allowImportLocal: + type: boolean + allowCreateOrganization: + type: boolean + prohibitLogin: + type: boolean + disableTwoFactor: + type: boolean + AuthenticationPayload: + type: object + required: + - name + properties: + id: + type: integer + format: int64 + type: + type: integer + name: + type: string + host: + type: string + port: + type: integer + bindDN: + type: string + bindPassword: + type: string + userBase: + type: string + userDN: + type: string + attributeUsername: + type: string + attributeName: + type: string + attributeSurname: + type: string + attributeMail: + type: string + attributeSSHPublicKey: + type: string + attributesInBind: + type: boolean + usePagedSearch: + type: boolean + searchPageSize: + type: integer + filter: + type: string + adminFilter: + type: string + isActive: + type: boolean + isSyncEnabled: + type: boolean + smtpAuth: + type: string + smtpHost: + type: string + smtpPort: + type: integer + allowedDomains: + type: string + securityProtocol: + type: integer + tls: + type: boolean + skipVerify: + type: boolean + pamServiceName: + type: string + oauth2Provider: + type: string + oauth2Key: + type: string + oauth2Secret: + type: string + openIDConnectAutoDiscoveryURL: + type: string + oauth2UseCustomURL: + type: boolean + oauth2TokenURL: + type: string + oauth2AuthURL: + type: string + oauth2ProfileURL: + type: string + oauth2EmailURL: + type: string + ExternalOAuth2AppPayload: + type: object + properties: + provider: + type: string + clientID: + type: string + clientSecret: + type: string + callbackURL: + type: string + BrandingResponse: + type: object + properties: + logo: + type: string + description: Base64-encoded image (base64Image.Base64ImageFormat). + favicons: + $ref: '#/components/schemas/K8sObject' + primaryColor: + type: string + runMode: + type: string + deploymentType: + type: string + isOfflineInstaller: + type: boolean + showAppTag: + type: boolean + appName: + type: string + BrandingOptions: + type: object + properties: + logo: + type: string + description: Base64-encoded image (base64Image.Base64ImageFormat). + favicon: + type: string + description: Base64-encoded image (base64Image.Base64ImageFormat). + primaryColor: + type: string + showAppTag: + type: boolean + appName: + type: string + DomainOpts: + type: object + properties: + name: + type: string + RegistrationOpts: + type: object + properties: + disableRegistration: + type: boolean + AuthObjectIdentifier: + type: object + properties: + objectType: + type: string + objectID: + type: integer + format: int64 + AuthObjectAllowedPermissions: + type: object + properties: + objectType: + type: string + objectID: + type: integer + format: int64 + allowedPermissions: + type: array + items: + type: string + PermissionInput: + type: object + properties: + namespace: + type: string + description: PermissionNamespace value. + action: + type: string + RoleResponse: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + owner_id: + type: integer + format: int64 + description: + type: string + permissions: + type: array + items: + $ref: '#/components/schemas/PermissionInput' + team_ids: + type: array + items: + type: integer + format: int64 + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + CreateRoleRequest: + type: object + required: + - name + - permissions + properties: + name: + type: string + description: + type: string + permissions: + type: array + items: + $ref: '#/components/schemas/PermissionInput' + teamIDs: + type: array + items: + type: integer + format: int64 + UpdateRoleRequest: + type: object + properties: + name: + type: string + description: + type: string + permissions: + type: array + items: + $ref: '#/components/schemas/PermissionInput' + teamIDs: + type: array + items: + type: integer + format: int64 + ClusterInfoModel: + type: object + description: Persisted cluster info model returned by UpdateCluster (models.ClusterInfo). Fields + are dynamic/DB-backed; represented as an open object. + additionalProperties: true + ImportClusterOption: + type: object + description: Request body for importing/updating a cluster (structs.ImportClusterOption). + properties: + displayName: + type: string + name: + type: string + provider: + type: string + kubeConfig: + type: string + required: + - provider + - kubeConfig + ExecuteCommandPayload: + type: object + description: Request body for executing a kubectl plugin command. + properties: + command: + type: string + required: + - command + CommandResponse: + type: object + description: Output of an executed command. + properties: + stdout: + type: string + stderr: + type: string + BadgerEntryList: + type: object + description: List of resource-history entries (models.BadgerEntryList). + properties: + items: + type: array + items: + $ref: '#/components/schemas/BadgerEntry' + BadgerEntry: + type: object + description: A single resource-history entry (models.BadgerEntry). + properties: + key: + type: string + values: + type: array + items: + $ref: '#/components/schemas/BadgerValue' + lastSeen: + type: integer + format: int64 + required: + - key + - values + BadgerValue: + type: object + description: A single value within a resource-history entry (models.BadgerValue). + properties: + resource: + $ref: '#/components/schemas/K8sObject' + resourceID: + $ref: '#/components/schemas/K8sObject' + licenseID: + type: string + version: + type: integer + format: int64 + timestamp: + type: integer + format: int64 + required: + - resourceID + - licenseID + - version + - timestamp + TaskResponse: + type: object + description: Async task submission response (natjobs/manager.TaskResponse). + properties: + id: + type: string + subject: + type: string + ConsoleConfig: + type: object + description: Console/tiller config in API format (console_config.ConsoleConfig). + properties: + id: + type: integer + format: int64 + userID: + type: integer + format: int64 + clusterID: + type: string + type: + type: string + description: models.SettingType + data: + type: object + additionalProperties: true + createdUnix: + type: integer + format: int64 + updatedUnix: + type: integer + format: int64 + required: + - id + - userID + - clusterID + - type + - data + - createdUnix + - updatedUnix + TillerOptions: + type: object + description: Helm driver (tiller) options (console_config.TillerOptions). + properties: + driver: + $ref: '#/components/schemas/HelmDriver' + HelmDriver: + type: object + properties: + helm3: + $ref: '#/components/schemas/Helm3Driver' + Helm3Driver: + type: object + properties: + driverName: + type: string + UninstallReleaseRequest: + type: object + description: Request body to uninstall a helm release (helm3.UninstallReleaseRequest). + properties: + namespace: + type: string + disable_hooks: + type: boolean + purge: + type: boolean + timeout: + type: integer + format: int64 + RollbackReleaseRequest: + type: object + description: Request body to rollback a helm release (helm3.RollbackReleaseRequest). + properties: + namespace: + type: string + dry_run: + type: boolean + disable_hooks: + type: boolean + version: + type: integer + format: int32 + recreate: + type: boolean + timeout: + type: integer + format: int64 + wait: + type: boolean + force: + type: boolean + description: + type: string + cleanup_on_fail: + type: boolean + K8sResource: + type: object + description: Identifies a single Kubernetes object by its object reference (namespace/name) and + GroupVersionResource. + properties: + namespace: + type: string + description: Namespace of the object (empty for cluster-scoped resources). + name: + type: string + description: Name of the object. + group: + type: string + description: Kubernetes API group. + version: + type: string + description: Kubernetes API version. + resource: + type: string + description: Kubernetes resource (plural). + BatchDeleteRequest: + type: object + description: Request body for the batch-delete endpoint. + properties: + resources: + type: array + description: The resources to delete. + items: + $ref: '#/components/schemas/K8sResource' + required: + - resources + K8sResourceDeleteStatus: + type: object + description: Deletion outcome for a single resource in a batch-delete request. + properties: + namespace: + type: string + name: + type: string + group: + type: string + version: + type: string + resource: + type: string + status: + allOf: + - $ref: '#/components/schemas/K8sStatus' + description: The metav1.Status describing the deletion result. + BatchDeleteResponse: + type: object + description: Response body for the batch-delete endpoint. + properties: + resourcesStatus: + type: array + description: Per-resource deletion statuses (populated for failures). + items: + $ref: '#/components/schemas/K8sResourceDeleteStatus' + BasicInfo: + type: object + properties: + name: + type: string + displayName: + type: string + ownerID: + type: integer + format: int64 + managerID: + type: integer + format: int64 + userID: + type: integer + format: int64 + clusterUID: + type: string + hubClusterID: + type: string + infraNamespace: + type: string + ProviderOptions: + type: object + properties: + name: + type: string + credential: + type: string + eksAuthMode: + type: string + enum: + - IRSA + - PodIdentity + clusterID: + type: string + project: + type: string + region: + type: string + resourceGroup: + type: string + kubeConfig: + type: string + FeatureSet: + type: object + properties: + name: + type: string + features: + type: array + items: + type: string + ComponentOptions: + type: object + properties: + fluxCD: + type: boolean + featureSets: + type: array + items: + $ref: '#/components/schemas/FeatureSet' + allFeatures: + type: boolean + clusterProfile: + type: string + monitoringClusterName: + type: string + spokeComponent: + type: boolean + CheckOptions: + type: object + properties: + basicInfo: + $ref: '#/components/schemas/BasicInfo' + provider: + $ref: '#/components/schemas/ProviderOptions' + ImportOptions: + type: object + properties: + basicInfo: + $ref: '#/components/schemas/BasicInfo' + provider: + $ref: '#/components/schemas/ProviderOptions' + components: + $ref: '#/components/schemas/ComponentOptions' + ConnectOptions: + type: object + properties: + name: + type: string + credential: + type: string + kubeConfig: + type: string + ReconfigureOptions: + type: object + properties: + basicInfo: + $ref: '#/components/schemas/BasicInfo' + components: + $ref: '#/components/schemas/ComponentOptions' + RemovalOptions: + type: object + properties: + name: + type: string + components: + $ref: '#/components/schemas/ComponentOptions' + ClusterOptions: + type: object + description: Options for creating or importing a virtual cluster. + properties: + clusterName: + type: string + hostClusterName: + type: string + hostClusterUID: + type: string + hostClusterOwnerID: + type: integer + format: int64 + hubClusterName: + type: string + hubClusterUID: + type: string + hubClusterOwnerID: + type: integer + format: int64 + ClusterMetadata: + type: object + properties: + uid: + type: string + name: + type: string + displayName: + type: string + provider: + type: string + ownerID: + type: string + ownerType: + type: string + apiEndpoint: + type: string + caBundle: + type: string + managerID: + type: string + hubClusterID: + type: string + cloudServiceAuthMode: + type: string + mode: + type: string + enum: + - prod + - qa + - staging + - dev + HubCluster: + type: object + properties: + name: + type: string + ownerName: + type: string + displayName: + type: string + hubClusterUID: + type: string + spokeClusters: + type: integer + addOns: + type: integer + clusterNode: + type: integer + provider: + type: string + hubType: + type: string + locations: + type: string + age: + type: string + createdAt: + type: string + format: date-time + SkipCredentialsResponse: + type: object + properties: + skipCredentials: + type: boolean + reason: + type: string + message: + type: string + GatewayConfigInfo: + type: object + properties: + presetName: + type: string + presetNamespace: + type: string + configName: + type: string + configNamespace: + type: string + version: + type: string + host: + type: string + hostType: + type: string + isDefault: + type: boolean + updateAvailable: + type: boolean + ValidationResponse: + type: object + description: Result of validating cluster import options. + properties: + alreadyImported: + type: boolean + displayName: + $ref: '#/components/schemas/FieldValidation' + clusterId: + $ref: '#/components/schemas/FieldValidation' + fluxCD: + $ref: '#/components/schemas/K8sObject' + message: + type: string + availableFeatureSets: + $ref: '#/components/schemas/K8sObject' + clusterAPI: + $ref: '#/components/schemas/K8sObject' + clusterMetadata: + $ref: '#/components/schemas/ClusterMetadata' + monitoringClusterList: + type: array + items: + type: string + FieldValidation: + type: object + properties: + valid: + type: boolean + reason: + type: string + InboxTokenRequestResponse: + type: object + properties: + agentJwtToken: + type: string + caBundle: + type: string + AcceptOptions: + type: object + description: Options for accepting spoke cluster join requests. + properties: + clusters: + type: array + items: + type: string + skipApproveCheck: + type: boolean + requesters: + type: array + items: + type: string + ClusterSetOptions: + type: object + description: Options identifying clusters and a cluster set. + properties: + clusters: + type: array + items: + type: string + clusterSet: + type: string + BindNamespaceOptions: + type: object + description: Options binding a namespace to a cluster set. + properties: + clusterSet: + type: string + namespace: + type: string + EnableFeatureOptions: + type: object + description: Options for enabling/disabling a feature set on a cluster set. + properties: + clusterSet: + type: string + features: + type: array + items: + type: string + featureSet: + type: string + RemoveClusterOptions: + type: object + description: Options identifying a managed cluster to remove. + properties: + clusterName: + type: string + UserOptions: + type: object + description: Options for creating or updating an OCM user's permissions. + properties: + id: + type: integer + format: int64 + userName: + type: string + email: + type: string + permissions: + type: array + items: + $ref: '#/components/schemas/Permission' + importCluster: + type: boolean + clientOrg: + type: boolean + Permission: + type: object + description: A single cluster or cluster-set permission grant. + properties: + name: + type: string + description: Cluster or cluster set name. + isClusterSet: + type: boolean + roleType: + type: string + description: 'Role scope: "ClusterRole" or "Role".' + roleRefName: + type: string + roleRefNamespace: + type: array + items: + type: string + managedClusterRoleBindingName: + type: string + managedClusterSetRoleBindingName: + type: string + RemovePermissionOpts: + type: object + description: Options identifying permissions to remove from an OCM user. + properties: + namespaceScopedResources: + type: array + items: + $ref: '#/components/schemas/NamespacedName' + clusterScopedResources: + type: array + items: + type: string + NamespacedName: + type: object + description: A Kubernetes namespaced-name pair. Marshals with capitalized keys (Namespace, Name) + because the source struct has no json tags. + properties: + Namespace: + type: string + Name: + type: string + UserPermissions: + type: object + description: An OCM user's cluster and cluster-set permissions. The map keys are cluster / cluster-set + names. Marshals with capitalized Go field names. + properties: + ClusterPermissions: + type: object + additionalProperties: + type: array + items: + $ref: '#/components/schemas/Permission' + ClusterSetPermissions: + type: object + additionalProperties: + type: array + items: + $ref: '#/components/schemas/Permission' + ManagedClusterInfo: + type: object + description: Summary of an OCM managed (spoke) cluster. + properties: + name: + type: string + clusterURL: + type: string + clusterUID: + type: string + clusterSet: + type: string + ListClusterSetResp: + type: object + description: Summary of a cluster set with its cluster count. + properties: + clusterSetName: + type: string + clusterSetTitle: + type: string + clusters: + type: integer + ClustersResp: + type: object + description: Summary of a cluster within a cluster set. + properties: + name: + type: string + displayName: + type: string + clusterNode: + type: integer + format: int32 + provider: + type: string + kubernetesVersion: + type: string + imported: + type: boolean + FeatureSetInfo: + type: object + description: Availability and installation info for a feature set. + properties: + name: + type: string + title: + type: string + description: + type: string + recommended: + type: boolean + features: + type: array + items: + $ref: '#/components/schemas/FeatureInfo' + requiredFeatures: + type: array + items: + type: string + installed: + type: boolean + FeatureInfo: + type: object + description: Availability and installation info for a single feature. + properties: + name: + type: string + title: + type: string + description: + type: string + recommended: + type: boolean + installed: + type: boolean + featureBlock: + type: string + versionObj: + type: object + description: A named component and its version. + properties: + name: + type: string + version: + type: string + PermissionScopes: + type: object + description: Namespace scope selector for querying a user's permissions (ocm.PermissionScopes). + properties: + namespaceList: + type: array + items: + type: string + allNamespaces: + type: boolean + ClientOrgUserPermission: + type: object + description: The roles and cluster-roles bound to a client-org user (ocm.ClientOrgUserPermission). + properties: + ClusterRoles: + type: array + items: + $ref: '#/components/schemas/ClientOrgUserPermissionDetails' + Roles: + type: array + items: + $ref: '#/components/schemas/ClientOrgUserPermissionDetails' + ClientOrgUserPermissionDetails: + type: object + description: Details of a single RBAC binding (ocm.ClientOrgUserPermissionDetails). + properties: + ResourceName: + type: string + ResourceNamespace: + type: string + RoleName: + type: string + RoleNamespace: + type: string + ClientOrgStatus: + type: object + description: Status envelope returned for client-org and client-org-cluster status endpoints. One + of Active, Deleting, Partially Deleted, Deleted or NotFound. + properties: + status: + type: string + ClientOrgParams: + type: object + description: Parameters for creating a client organization (settings.ClientOrgParams). + properties: + clientOrg: + $ref: '#/components/schemas/CreateOrgParams' + hubClusterUID: + type: string + description: UID of the hub cluster imported by the site admin. + hubClusterOwnerName: + type: string + userPermission: + $ref: '#/components/schemas/UserOptions' + annotations: + type: object + additionalProperties: + type: string + kubeDBConfig: + $ref: '#/components/schemas/KubeDBConfig' + useGateway: + type: boolean + usableAsShared: + type: boolean + gatewayConfig: + $ref: '#/components/schemas/GatewayConfigOptions' + gatewayConfigRef: + $ref: '#/components/schemas/K8sObject' + telemetryParams: + $ref: '#/components/schemas/TelemetryParams' + KubeDBConfig: + type: object + description: KubeDB scheduling configuration (settings.KubeDBConfig). + properties: + nodeSelector: + type: object + additionalProperties: + type: string + tolerations: + type: array + description: Kubernetes core/v1 Tolerations. + items: + $ref: '#/components/schemas/K8sObject' + GatewayConfigOptions: + type: object + description: Gateway configuration options (settings.GatewayConfigOptions). + properties: + cluster: + $ref: '#/components/schemas/K8sObject' + envoy: + $ref: '#/components/schemas/Envoy' + infra: + $ref: '#/components/schemas/K8sObject' + Envoy: + type: object + description: Envoy gateway provisioning options (settings.Envoy). + properties: + provisionerType: + type: string + service: + $ref: '#/components/schemas/K8sObject' + TelemetryParams: + type: object + description: Telemetry/retention configuration (settings.TelemetryParams). + properties: + monitoringClusterName: + type: string + logsRetentionPeriods: + type: string + tracesRetentionPeriods: + type: string + metricsRetentionPeriods: + $ref: '#/components/schemas/MetricsRetentionConfig' + MetricsRetentionConfig: + type: object + description: Metrics retention periods (settings.MetricsRetentionConfig). + properties: + fiveMinuteRetentionPeriod: + type: string + oneHourRetentionPeriod: + type: string + rawsRetentionPeriod: + type: string + AddClusterParams: + type: object + description: Parameters for adding a cluster to a client organization (settings.AddClusterParams). + Embeds HubSpokeInfo inline. + properties: + hubClusterOwnerName: + type: string + hubClusterName: + type: string + hubClusterUID: + type: string + spokeClusterName: + type: string + annotations: + type: object + additionalProperties: + type: string + kubeDBConfig: + $ref: '#/components/schemas/KubeDBConfig' + useGateway: + type: boolean + gatewayConfig: + $ref: '#/components/schemas/GatewayConfigOptions' + gatewayPresetRef: + $ref: '#/components/schemas/K8sObject' + telemetryParams: + $ref: '#/components/schemas/TelemetryParams' + RemoveClusterParams: + type: object + description: Parameters for removing a cluster from a client organization (settings.RemoveClusterParams). + Embeds HubSpokeInfo inline. + properties: + hubClusterOwnerName: + type: string + hubClusterName: + type: string + hubClusterUID: + type: string + spokeClusterName: + type: string + CloudProviderList: + type: object + description: List of supported cloud providers. + properties: + kind: + type: string + apiVersion: + type: string + metadata: + $ref: '#/components/schemas/K8sObject' + items: + type: array + items: + $ref: '#/components/schemas/CloudProvider' + CloudProvider: + type: object + description: A supported cloud provider (name carried in metadata). + properties: + kind: + type: string + apiVersion: + type: string + metadata: + $ref: '#/components/schemas/K8sObject' + spec: + $ref: '#/components/schemas/CloudProviderSpec' + CloudProviderSpec: + type: object + properties: + regions: + type: array + items: + $ref: '#/components/schemas/Region' + machineTypes: + type: array + items: + $ref: '#/components/schemas/K8sObject' + Region: + type: object + properties: + region: + type: string + zones: + type: array + items: + type: string + location: + type: string + required: + - region + Locations: + type: object + description: A cloud region with its availability zones. + properties: + region: + type: string + description: + type: string + zones: + type: array + items: + type: string + required: + - region + VMInfo: + type: object + description: A cloud provider machine type / server type. + properties: + name: + type: string + description: + type: string + cpu: + type: integer + core: + type: integer + memoryMb: + type: integer + disksSizeGb: + type: integer + iops: + type: integer + shared: + type: boolean + baremetal: + type: boolean + gpus: + type: integer + category: + type: string + family: + type: string + instanceHypervisor: + type: string + architecture: + type: array + items: + type: string + capacityType: + type: array + items: + type: string + networkBW: + type: string + ebsBW: + type: string + monthlyCost: + type: string + required: + - name + - cpu + - memoryMb + - iops + - shared + - baremetal + ClusterProvisionConfig: + type: object + description: Configuration for provisioning a CAPI-based cluster. + properties: + capiClusterConfig: + $ref: '#/components/schemas/CAPIClusterConfig' + importOptions: + $ref: '#/components/schemas/ImportOptions' + CAPIClusterConfig: + type: object + description: Cluster API (CAPI) cluster configuration. + properties: + clusterName: + type: string + region: + type: string + networkCIDR: + type: string + kubernetesVersion: + type: string + googleProjectID: + type: string + controlPlane: + $ref: '#/components/schemas/MachinePool' + workerPools: + type: array + items: + $ref: '#/components/schemas/MachinePool' + MachinePool: + type: object + properties: + machineType: + type: string + machineCount: + type: integer + cpu: + type: integer + memory: + type: integer + required: + - machineType + - machineCount + - cpu + - memory + InstallerMetadata: + type: object + description: Metadata describing a generated or imported ACE installer (selfclient.InstallerMetadata). + properties: + ID: + type: string + installerName: + type: string + deploymentType: + type: string + description: ACE deployment type (api.DeploymentType). + requestedDomain: + type: string + host: + type: string + hostType: + type: string + description: Host type (catgwapi.HostType). + hostedDomain: + type: string + ownerName: + type: string + requesterDisplayName: + type: string + requesterUsername: + type: string + adminDisplayName: + type: string + adminEmail: + type: string + accessTokenID: + type: integer + format: int64 + clusterID: + type: string + version: + type: string + promotedToProduction: + type: boolean + createTimestamp: + type: string + format: date-time + expiryTimestamp: + type: string + format: date-time + lastUpgradeTimestamp: + type: string + format: date-time + lastUpdateTimestamp: + type: string + format: date-time + InstallerDetails: + type: object + description: Details for a generated installer including readme content and archive URLs (installer.Details). + properties: + meta: + $ref: '#/components/schemas/InstallerMetadata' + readme: + type: string + format: byte + archiveZipURL: + type: string + archiveTarURL: + type: string + MarketplaceInstallerStatus: + type: object + description: Marketplace subscription status for a marketplace-type installer (installer.MarketplaceInstallerStatus). + properties: + status: + type: string + description: Either "Pending" or "Bound". + link: + type: string + meta: + $ref: '#/components/schemas/InstallerMetadata' + isExpired: + type: boolean + InstallerVersion: + type: object + description: A single installer version/archive entry (installer.Version). + properties: + version: + type: string + creationTime: + type: string + format: date-time + archiveURL: + type: string + archiveName: + type: string + createdBy: + $ref: '#/components/schemas/User' + lastOperation: + type: string + latestInstaller: + type: boolean + UpgradeOptions: + type: object + description: Multipart form options for triggering an ACE platform upgrade (upgrader.UpgradeOptions). + properties: + version: + type: string + description: Target upgrade version. May be overridden by an `installerVersion` field in the + uploaded values file. + valuesFile: + type: string + format: binary + description: Helm values file (values.yaml) for the upgrade. + useLatestImage: + type: boolean + description: When true, use the latest upgrader image for the target version. + LicenseOpts: + type: object + description: Options for issuing a license for a cluster. + properties: + cluster: + type: string + description: Cluster UUID the license is issued for. + features: + type: array + items: + type: string + AddContractParams: + type: object + description: Parameters for creating a contract. Submitted as multipart/form-data so an optional + contract document file can be attached. One contract is created per entry in `products`. + properties: + id: + type: integer + format: int64 + uid: + type: integer + format: int64 + orgOrUser: + type: string + name: + type: string + products: + type: array + items: + type: string + features: + type: array + items: + type: string + clusters: + type: array + items: + $ref: '#/components/schemas/ContractClusterStatus' + emails: + $ref: '#/components/schemas/ContractEmail' + quota: + $ref: '#/components/schemas/QuotaRule' + start: + type: integer + format: int64 + description: Contract start time (Unix seconds). + end: + type: integer + format: int64 + description: Contract end time (Unix seconds). + document: + type: string + format: binary + description: Optional contract document file (multipart upload). + documentPath: + type: string + allowOffline: + type: boolean + disableAnalytics: + type: boolean + enableClientBilling: + type: boolean + autoAssignCluster: + type: boolean + revoked: + type: boolean + restrictions: + type: string + description: JSON-encoded restrictions data. + Contract: + type: object + description: A licensing contract. Used both as request body (multipart/form-data on update/extend) + and as response. + properties: + id: + type: integer + format: int64 + uid: + type: integer + format: int64 + orgOrUser: + type: string + name: + type: string + product: + type: string + features: + type: array + items: + type: string + clusters: + type: array + items: + $ref: '#/components/schemas/ContractClusterStatus' + associatedCluster: + $ref: '#/components/schemas/ContractClusterStatus' + emails: + $ref: '#/components/schemas/ContractEmail' + quota: + $ref: '#/components/schemas/QuotaRule' + start: + type: integer + format: int64 + description: Contract start time (Unix seconds). + end: + type: integer + format: int64 + description: Contract end time (Unix seconds). + document: + type: string + format: binary + description: Optional contract document file (multipart upload). + documentPath: + type: string + allowOffline: + type: boolean + autoAssignCluster: + type: boolean + disableAnalytics: + type: boolean + enableClientBilling: + type: boolean + revoked: + type: boolean + restrictions: + type: string + description: JSON-encoded restrictions data. + Reminder45DaysSentUnix: + type: integer + format: int64 + nullable: true + Reminder10DaysSentUnix: + type: integer + format: int64 + nullable: true + ContractEmail: + type: object + description: Contract email recipient groups. For subfields, set values against the subfield name + (e.g. contactPerson). The usageAlertAdmin field is stripped from user-facing (non-admin) responses. + properties: + contactPerson: + type: array + items: + type: string + signingAuthority: + type: array + items: + type: string + licenseUsers: + type: array + items: + type: string + financeTeam: + type: array + items: + type: string + usageAlertClient: + type: array + description: Email recipients. Accepts either a JSON array of strings or a single string (which + is normalized to a one-element array). + items: + type: string + usageAlertAdmin: + type: array + description: Email recipients. Accepts either a JSON array of strings or a single string (which + is normalized to a one-element array). + items: + type: string + QuotaRule: + type: object + description: Quota enforcement configuration for one metric. + properties: + enabled: + type: boolean + metric: + type: string + description: Billable usage metric (e.g. memory_gib_month, cpu_core_month). + limit: + type: number + format: double + alertThresholds: + type: array + items: + type: integer + disableLicenseOnLimitReached: + type: boolean + UpdateUserContractPreferences: + type: object + description: Caller-editable contract preferences. + properties: + autoAssignCluster: + type: boolean + nullable: true + usageAlertClient: + type: array + nullable: true + description: Email recipients. Accepts either a JSON array of strings or a single string. + items: + type: string + License: + type: object + description: An issued license and its contract window. + properties: + contract: + $ref: '#/components/schemas/LicenseContract' + license: + type: string + format: byte + description: The license certificate bytes (base64-encoded in JSON). + LicenseContract: + type: object + description: License contract window (from license-verifier v1alpha1.Contract). + properties: + id: + type: string + startTimestamp: + type: string + format: date-time + expiryTimestamp: + type: string + format: date-time + ContractAudit: + type: object + description: A single contract audit-trail event. + properties: + id: + type: integer + format: int64 + contractID: + type: integer + format: int64 + addedBy: + type: string + event: + type: string + createdUnix: + type: integer + format: int64 + InstallerOptions: + type: object + description: Options for generating a license-proxy installer. When clusterID or contractIDs are + set, an offline installer is generated. + properties: + clusterID: + type: string + contractIDs: + type: array + items: + type: integer + format: int64 + BindContractCluster: + type: object + description: Options for binding a cluster to an existing contract. + properties: + displayName: + type: string + cluster: + type: string + description: Cluster UUID (validated as a UUID). + tags: + type: array + items: + type: string + ClusterContractList: + type: object + description: A cluster and the set of contract IDs to assign it to. + properties: + clusterId: + type: string + displayName: + type: string + contractIds: + type: array + items: + type: integer + format: int64 + BatchClusterStatusRequest: + type: object + description: A batch of cluster UUIDs to check status for. + properties: + clusters: + type: array + items: + type: string + ContractClusterStatus: + type: object + description: A cluster associated with a contract along with its status in the console system. + properties: + id: + type: integer + format: int64 + contractId: + type: integer + format: int64 + cluster: + type: string + displayName: + type: string + clusterStatus: + $ref: '#/components/schemas/ClusterStatus' + duplicateContractFeatures: + type: array + items: + $ref: '#/components/schemas/ContractFeatures' + error: + type: string + PatchUserContractClusterName: + type: object + description: New display name for a contract cluster. + properties: + clusterName: + type: string + PatchUserContractClusterTags: + type: object + description: Full replacement tag set for a contract cluster. + properties: + tags: + type: array + items: + type: string + ContractFeatures: + type: object + properties: + contractId: + type: integer + format: int64 + product: + type: string + features: + type: array + items: + type: string + ClusterWithAssociatedContracts: + type: object + properties: + associatedContractIDs: + type: array + items: + type: integer + format: int64 + cluster: + type: string + displayName: + type: string + tags: + type: array + items: + type: string + ClusterStatus: + type: object + description: Whether a bound contract cluster is already imported in the console. + properties: + isImported: + type: boolean + name: + type: string + tags: + type: array + items: + type: string + associatedContractId: + type: integer + format: int64 + PlanInfo: + type: object + description: Metadata about a supported contract product/plan. + properties: + DisplayName: + type: string + ProductLine: + type: string + TierName: + type: string + TwitterHandle: + type: string + QuickstartLink: + type: string + Features: + type: array + items: + type: string + MailingLists: + type: array + items: + type: string + VerifierOptions: + type: object + description: License registration payload (license-verifier Options). The license field carries + the cryptographically-signed license used to authenticate the /register request. + properties: + clusterUID: + type: string + features: + type: string + caCert: + type: string + format: byte + license: + type: string + format: byte + LicensedUserAPIForm: + type: object + description: Summary of a licensed user for the billing dashboard. + properties: + username: + type: string + userType: + type: string + email: + type: string + userID: + type: integer + format: int64 + lastReceivedAt: + type: integer + format: int64 + ActiveClustersAPIForm: + type: object + description: An active cluster reported for a user, with contract count. + properties: + username: + type: string + clusterID: + type: string + firstReceivedAt: + type: integer + format: int64 + lastReceivedAt: + type: integer + format: int64 + noOfAssociatedContracts: + type: integer + format: int64 + ActiveLicenseAPIForm: + type: object + description: An active license reported for a user's cluster. + properties: + username: + type: string + email: + type: string + userId: + type: integer + format: int64 + licenseID: + type: string + firstReceivedAt: + type: integer + format: int64 + lastReceivedAt: + type: integer + format: int64 + SystemOutageRequest: + type: object + description: Request body to create a system outage entry. + properties: + accountName: + type: string + clusterID: + type: string + start: + type: string + format: date-time + end: + type: string + format: date-time + tags: + type: array + items: + type: string + comments: + type: string + SystemOutageApiForm: + type: object + description: A recorded system outage entry. + properties: + id: + type: integer + format: int64 + accountID: + type: integer + format: int64 + accountName: + type: string + clusterID: + type: string + start: + type: string + format: date-time + end: + type: string + format: date-time + tags: + type: array + items: + type: string + comments: + type: string + createdAt: + type: string + format: date-time + SystemOutagesAndReportAPIForm: + type: object + description: System outage entries together with an aggregated report. + properties: + report: + $ref: '#/components/schemas/SystemOutageReport' + entries: + type: array + items: + $ref: '#/components/schemas/SystemOutageApiForm' + SystemOutageReport: + type: object + description: Aggregated report over a set of system outage entries. + properties: + totalOutages: + type: integer + format: int64 + totalDurationHours: + type: number + format: double + topTagsPercentage: + type: array + items: + $ref: '#/components/schemas/TagPercentage' + topAccountsDuration: + type: array + items: + $ref: '#/components/schemas/EntityDurationPercentage' + topClustersDuration: + type: array + items: + $ref: '#/components/schemas/EntityDurationPercentage' + TagPercentage: + type: object + properties: + tag: + type: string + percentage: + type: number + format: double + EntityDurationPercentage: + type: object + properties: + entity: + type: string + entityName: + type: string + durationHours: + type: number + format: double + percentage: + type: number + format: double + LicensedPlan: + type: object + description: A licensed plan associated with one or more clusters. + properties: + uid: + type: integer + format: int64 + nullable: true + email: + type: string + licenseID: + type: string + clusters: + type: array + items: + type: string + planName: + type: string + notBefore: + type: integer + format: int64 + nullable: true + notAfter: + type: integer + format: int64 + nullable: true + reconciledAt: + type: integer + format: int64 + nullable: true + registeredAt: + type: integer + format: int64 + nullable: true + createdAt: + type: integer + format: int64 + updatedAt: + type: integer + format: int64 + LicensePlanApiForm: + type: object + description: API representation of a licensed plan. + properties: + uid: + type: integer + format: int64 + nullable: true + email: + type: string + licenseID: + type: string + clusters: + type: array + items: + type: string + planName: + type: string + notBefore: + type: integer + format: int64 + nullable: true + notAfter: + type: integer + format: int64 + nullable: true + reconciledAt: + type: integer + format: int64 + nullable: true + registeredAt: + type: integer + format: int64 + nullable: true + createdAt: + type: integer + format: int64 + updatedAt: + type: integer + format: int64 + ReceivedLicensedProduct: + type: object + description: A licensed product reported by a cluster. + properties: + userName: + type: string + userType: + type: string + email: + type: string + userID: + type: integer + format: int64 + clusterID: + type: string + licenseID: + type: string + productName: + type: string + firstReceivedAt: + type: integer + format: int64 + lastReceivedAt: + type: integer + format: int64 + EventsReport: + type: object + description: Aggregated events history report for a resource. + properties: + userID: + type: integer + format: int64 + clusterID: + type: string + licenseID: + type: string + group: + type: string + resource: + type: string + resourceID: + type: string + totalEvents: + type: integer + eventsTimeHistories: + type: array + items: + type: string + format: date-time + eventsDurationHours: + type: number + format: double + averageEventsPerHour: + type: number + format: double + ClusterResourceTabularForm: + type: object + description: A tabular event row for a cluster resource. + properties: + key: + type: string + version: + type: integer + format: int64 + timestamp: + type: integer + format: int64 + partialResource: + $ref: '#/components/schemas/PartialResourceAPIForm' + PartialResourceAPIForm: + type: object + properties: + partialObjectMeta: + $ref: '#/components/schemas/K8sObject' + EventsCounterResponse: + type: object + description: Today's event count for a cluster/license/resource. + properties: + clusterID: + type: string + product: + type: string + licenseID: + type: string + group: + type: string + resource: + type: string + RID: + type: string + date: + type: string + noOfEvents: + type: integer + format: int64 + error: + type: string + Marketplace: + type: string + description: Marketplace identifier. + enum: + - Aws + - Azure + - Gcp + SubscriptionState: + type: string + description: Lifecycle state of a marketplace subscription. + enum: + - Pending + - Bounded + - Running + - Failed + - Deleting + - DeletionFailed + - Deleted + - Revoked + Subscription: + type: object + description: A marketplace subscription. + properties: + marketplace: + $ref: '#/components/schemas/Marketplace' + subscriptionId: + type: string + subscriberId: + type: integer + format: int64 + requesterId: + type: integer + format: int64 + boundedInstallerId: + type: string + state: + $ref: '#/components/schemas/SubscriptionState' + azureBillingDetails: + $ref: '#/components/schemas/AzureBillingDetails' + awsBillingDetails: + $ref: '#/components/schemas/AwsBillingDetails' + gcpBillingDetails: + $ref: '#/components/schemas/GcpBillingDetails' + lastBillingEventSentAt: + type: string + format: date-time + nullable: true + noOfBillingEventSent: + type: integer + lastAlertNotificationSentAt: + type: string + format: date-time + nullable: true + noOfAlertNotificationsSent: + type: integer + billingNotBefore: + type: string + format: date-time + nullable: true + isRevocable: + type: boolean + createdAt: + type: string + format: date-time + lastUpdatedAt: + type: string + format: date-time + GcpBillingDetails: + type: object + properties: + hostedB3BaseURL: + type: string + meteringProxyApiToken: + type: string + AwsBillingDetails: + type: object + properties: + hostedB3BaseURL: + type: string + meteringProxyApiToken: + type: string + AzureBillingDetails: + type: object + properties: + resourceUri: + type: string + resourceUsageId: + type: string + managedResourceGroupId: + type: string + planId: + type: string + subscriptionId: + type: string + customerOwnedRG: + type: string + appName: + type: string + SettingWarnings: + type: object + description: Marketplace configuration warnings keyed by marketplace. + properties: + warnings: + type: object + additionalProperties: + type: array + items: + $ref: '#/components/schemas/Warning' + Warning: + type: object + properties: + Level: + type: string + Msg: + type: string + AuditReportsResp: + type: object + description: Marketplace audit event reports grouped by audit period. + properties: + auditReports: + type: object + additionalProperties: + type: array + items: + $ref: '#/components/schemas/MarketplaceAuditEvent' + MarketplaceAuditEvent: + type: object + description: A single marketplace audit event. + properties: + marketplace: + $ref: '#/components/schemas/Marketplace' + subscriptionID: + type: string + status: + type: string + operationType: + type: string + description: + type: string + data: + type: object + additionalProperties: true + timestamp: + type: string + format: date-time + GeneratedDates: + type: object + description: Year/month combinations for which a usage summary has been generated. The map is keyed + by year (string) with month-name lists as values. + properties: + yearMonthList: + type: object + additionalProperties: + type: array + items: + type: string + UsageView: + type: object + description: A billing usage-report view. These views (KubeDB/KubeStash/KubeVault/ Voyager objects/clusters/namespaces/GKs/contracts/quota-history + and the DBaaS namespace reports) are complex, deeply-nested aggregation structures whose shape + varies by `view_type` and product; they are modeled here as a free-form JSON object. + additionalProperties: true + ApiError: + type: object + description: Generic marketplace error response produced by `NewApiErr`; a single `message` field + carrying the joined error messages. + properties: + message: + type: string + InitialInput: + type: object + description: Initial admin/domain inputs used for AWS and GCP marketplace deployments. + properties: + adminUsername: + type: string + adminPassword: + type: string + domainWhiteList: + type: array + items: + type: string + BindingInfo: + type: object + description: Marketplace binding information carried in webhook notification payloads. Embeds InitialInput + fields (adminUsername, adminPassword, domainWhiteList). + properties: + marketplace: + type: string + enum: + - Aws + - Azure + - Gcp + installerId: + type: string + clusterId: + type: string + AWSAccountID: + type: string + adminUsername: + type: string + adminPassword: + type: string + domainWhiteList: + type: array + items: + type: string + options: + type: object + additionalProperties: true + AwsWebhookNotification: + type: object + description: AWS Marketplace webhook notification payload. + properties: + eventType: + type: string + eventTime: + type: string + format: date-time + bindingInfo: + $ref: '#/components/schemas/BindingInfo' + GcpWebhookNotification: + type: object + description: GCP Marketplace webhook notification payload. + properties: + eventType: + type: string + eventTime: + type: string + format: date-time + bindingInfo: + $ref: '#/components/schemas/BindingInfo' + AzureResourceIdParts: + type: object + description: Parsed parts of an Azure application resource ID. Populated server-side and not part + of the incoming JSON payload. + properties: + ClientSubscriptionId: + type: string + ResourceGroup: + type: string + Provider: + type: string + Application: + type: string + AzureWebhookNotification: + type: object + description: Azure Marketplace webhook notification payload. Some fields (managedResourceGroupId, + resourceIdParts) are populated server-side and are not part of the incoming JSON payload. + properties: + eventType: + type: string + applicationId: + type: string + managedResourceGroupId: + type: string + resourceIdParts: + $ref: '#/components/schemas/AzureResourceIdParts' + eventTime: + type: string + format: date-time + provisioningState: + type: string + billingDetails: + type: object + properties: + resourceUsageId: + type: string + plan: + type: object + properties: + publisher: + type: string + product: + type: string + name: + type: string + version: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + details: + type: array + items: + type: object + properties: + code: + type: string + message: + type: string + bindingInfo: + $ref: '#/components/schemas/BindingInfo' + GcpUsageValue: + type: object + properties: + int64Value: + type: integer + format: int64 + doubleValue: + type: number + format: double + GcpUsageReport: + type: object + description: Usage report forwarded to the GCP Service Control reporting API via the metered-billing + proxy. + properties: + name: + type: string + startTime: + type: string + format: date-time + endTime: + type: string + format: date-time + labels: + type: object + additionalProperties: + type: string + value: + $ref: '#/components/schemas/GcpUsageValue' + dimension: + type: string + serviceName: + type: string + Tag: + type: object + description: AWS Marketplace Metering usage-allocation tag (key-value pair). + required: + - Key + - Value + properties: + Key: + type: string + Value: + type: string + UsageAllocation: + type: object + description: AWS Marketplace Metering usage allocation bucket. + required: + - AllocatedUsageQuantity + properties: + AllocatedUsageQuantity: + type: integer + format: int64 + Tags: + type: array + items: + $ref: '#/components/schemas/Tag' + MeterUsageInput: + type: object + description: AWS Marketplace Metering `MeterUsage` request forwarded via the metered-billing proxy. + required: + - ProductCode + - Timestamp + - UsageDimension + properties: + DryRun: + type: boolean + ProductCode: + type: string + Timestamp: + type: string + format: date-time + UsageAllocations: + type: array + items: + $ref: '#/components/schemas/UsageAllocation' + UsageDimension: + type: string + UsageQuantity: + type: integer + format: int64 + MeterUsageOutput: + type: object + description: AWS Marketplace Metering `MeterUsage` response. + properties: + MeteringRecordId: + type: string + AwsMeteringProxyErr: + type: object + description: Error returned when the AWS Marketplace Metering service rejects a usage report. + properties: + code: + type: string + message: + type: string + origErr: + type: object + nullable: true + CreateTelemetryStackRequest: + type: object + description: Request to create a TelemetryStack. The `spec` field is a TelemetryStackSpec (go.open-pulse.dev/tenant-operator) + and is modeled as a free-form Kubernetes object. + properties: + name: + type: string + namespace: + type: string + spec: + $ref: '#/components/schemas/K8sObject' + RegisterRequest: + type: object + description: Trickster backend registration request. Embeds PrometheusContext fields inline alongside + the Prometheus connection config. + properties: + prometheus: + $ref: '#/components/schemas/PrometheusConfig' + hubUID: + type: string + clusterUID: + type: string + projectId: + type: string + default: + type: boolean + issueToken: + type: boolean + clientOrgID: + type: string + PrometheusConfig: + type: object + properties: + url: + type: string + service: + $ref: '#/components/schemas/ServiceSpec' + basicAuth: + $ref: '#/components/schemas/BasicAuth' + bearerToken: + type: string + tls: + $ref: '#/components/schemas/TLSConfig' + PrometheusContext: + type: object + properties: + hubUID: + type: string + clusterUID: + type: string + projectId: + type: string + default: + type: boolean + issueToken: + type: boolean + clientOrgID: + type: string + ServiceSpec: + type: object + properties: + scheme: + type: string + name: + type: string + namespace: + type: string + port: + type: string + path: + type: string + query: + type: string + BasicAuth: + type: object + properties: + username: + type: string + password: + type: string + TLSConfig: + type: object + properties: + ca: + type: string + cert: + type: string + key: + type: string + serverName: + type: string + insecureSkipTLSVerify: + type: boolean + DashboardSpec: + type: object + properties: + datasource: + type: string + folderID: + type: integer + PersesDashboardSpec: + type: object + properties: + projectName: + type: string + folderName: + type: string + datasource: + type: string + GrafanaConfig: + type: object + properties: + url: + type: string + service: + $ref: '#/components/schemas/ServiceSpec' + basicAuth: + $ref: '#/components/schemas/BasicAuth' + bearerToken: + type: string + tls: + $ref: '#/components/schemas/TLSConfig' + dashboard: + $ref: '#/components/schemas/DashboardSpec' + PersesConfig: + type: object + properties: + url: + type: string + service: + $ref: '#/components/schemas/ServiceSpec' + basicAuth: + $ref: '#/components/schemas/BasicAuth' + bearerToken: + type: string + tls: + $ref: '#/components/schemas/TLSConfig' + dashboard: + $ref: '#/components/schemas/PersesDashboardSpec' + GrafanaContext: + type: object + properties: + folderID: + type: integer + format: int64 + datasource: + type: string + PersesContext: + type: object + properties: + projectName: + type: string + folderName: + type: string + datasource: + type: string + GrafanaDatasourceResponse: + type: object + description: Grafana datasource registration response. Embeds GrafanaContext fields inline alongside + the Grafana connection config. + properties: + grafana: + $ref: '#/components/schemas/GrafanaConfig' + folderID: + type: integer + format: int64 + datasource: + type: string + PersesDatasourceResponse: + type: object + description: Perses datasource registration response. Embeds PersesContext fields inline alongside + the Perses connection config. + properties: + perses: + $ref: '#/components/schemas/PersesConfig' + projectName: + type: string + folderName: + type: string + datasource: + type: string + ChartRepositoryEntry: + type: object + description: A Helm Hub chart repository entry (Helm repo.Entry). Fields are those of the Helm repository + configuration. + properties: + name: + type: string + url: + type: string + username: + type: string + password: + type: string + certFile: + type: string + keyFile: + type: string + caFile: + type: string + insecure_skip_tls_verify: + type: boolean + pass_credentials_all: + type: boolean + ChartVersion: + type: object + description: A Helm chart version entry (Helm repo.ChartVersion / chart.Metadata plus distribution + fields). Modeled with the common chart metadata fields. + properties: + name: + type: string + version: + type: string + description: + type: string + apiVersion: + type: string + appVersion: + type: string + type: + type: string + deprecated: + type: boolean + icon: + type: string + home: + type: string + keywords: + type: array + items: + type: string + sources: + type: array + items: + type: string + urls: + type: array + items: + type: string + created: + type: string + format: date-time + digest: + type: string + MarkdownOption: + type: object + description: Markdown rendering options. + properties: + Text: + type: string + description: Markdown to render. + Mode: + type: string + description: Rendering mode (e.g. "gfm"). + Context: + type: string + description: URL context for resolving relative links. + Wiki: + type: boolean + description: Whether the document is a wiki page. + ServerVersion: + type: object + properties: + version: + type: string diff --git a/docs/platform/api/organizations-teams/_index.md b/docs/platform/api/organizations-teams/_index.md new file mode 100644 index 0000000..025bacb --- /dev/null +++ b/docs/platform/api/organizations-teams/_index.md @@ -0,0 +1,34 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-organizations-teams + name: "Identity: Organizations & Teams" + parent: api + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Identity: Organizations & Teams + +APIs for organizations and the teams inside them. Organizations own clusters, +contracts, and billing scope; teams provide per-org grouping with role-based +permissions. All authorization checks are OpenFGA-backed (relationship-based), so +access to each endpoint depends on the caller's role in the organization or team. + +All routes are served under the `/api/v1` prefix. Most endpoints authenticate with a +personal access token sent as `Authorization: token ` (it may also be +supplied as a `token` or `access_token` query parameter). A few read endpoints are +public (no auth) and return only what an anonymous caller may see — this is called +out per endpoint. + +## Pages + +- [Organizations](../organizations.md) — the `/api/v1/orgs/*` + endpoints: create/claim organizations, get/edit/delete an org, ownership and + membership checks, member management, avatars, Rancher sync/user tokens, and org + access/NATS tokens. +- [Teams](../teams.md) — the `/api/v1/orgs/{orgname}/teams` and + `/api/v1/teams/{teamid}/*` endpoints: list/create teams, team actions, and team + member management. diff --git a/docs/platform/api/organizations-teams/organizations.md b/docs/platform/api/organizations-teams/organizations.md new file mode 100644 index 0000000..a2f38ed --- /dev/null +++ b/docs/platform/api/organizations-teams/organizations.md @@ -0,0 +1,708 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-organizations-teams-organizations + name: Organizations + parent: api-organizations-teams + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Organizations + +Endpoints for creating and managing organizations, their members, avatars, Rancher +integration tokens, and organization-scoped access/NATS tokens. + +All paths below are relative to the API root `/api/v1`. For example, `GET /orgs/{orgname}` +is `GET https:///api/v1/orgs/{orgname}`. In these paths `orgname` is the +organization slug (e.g. `appscode`). + +Unless noted, authenticated endpoints accept a personal access token: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/orgs/appscode +``` + +Authorization checks (e.g. `edit:org`, `admin:org`, `view:avatar`) are +relationship-based (OpenFGA) and evaluated against the caller's role in the +organization. + +## Organization lifecycle + +### POST /orgs + +Create a new organization owned by the authenticated user. + +- **Auth:** token. The user must be permitted to create organizations + (`CanCreateOrganization`); otherwise `403` is returned. + +**Request body** (`CreateOrgOption`): + +```json +{ + "username": "acme", + "full_name": "Acme Inc.", + "description": "Acme engineering org", + "website": "https://acme.example.com", + "location": "Remote", + "orgType": "public", + "visibility": "public" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `username` | string | yes | Slug/username of the new organization. | +| `full_name` | string | no | Display name. | +| `description` | string | no | Free-text description. | +| `website` | string | no | Website URL. | +| `location` | string | no | Location text. | +| `orgType` | string | no | One of `public` (default), `limited`, or `private`. | +| `rancherManagementClusterEndPoint` | string | no | Rancher management cluster endpoint (for Rancher-origin orgs). | +| `visibility` | string | no | One of `""`, `public`, `limited`, `private`. | + +**Response:** `201 Created` with the created `Organization`: + +```json +{ + "id": 42, + "username": "acme", + "full_name": "Acme Inc.", + "avatar_url": "https:///accounts/avatars?obj=avatars/42-", + "description": "Acme engineering org", + "website": "https://acme.example.com", + "location": "Remote", + "rancherManagementClusterEndPoint": "", + "visibility": "public", + "orgType": 0 +} +``` + +### PATCH /orgs/claim/{claimID} + +Claim a previously created standalone (marketplace) organization and assign ownership +to the authenticated user. + +- **Auth:** token. Only registered on AppsCode-hosted deployments (`setting.AppsCodeHosted`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `claimID` | string | Claim identifier of the standalone organization. | + +**Response:** `200 OK` returning the claimed organization as a free-form Kubernetes +object (`models.User.APIFormat`, dynamic payload). `409 Conflict` if the organization +was already claimed; `404` if the claim ID is unknown. + +### GET /orgs/claim/ + +Return the claim ID of the oldest claimable standalone organization, by proxying an +eligibility check to the central marketplace server. + +- **Auth:** token + **site admin** (`reqSiteAdmin`). Only registered for marketplace + deployments or in dev run mode. + +**Response:** `200 OK` (`OrgClaimableCheckResp`): + +```json +{ + "isClaimable": true, + "claimID": "a1b2c3d4" +} +``` + +> **Verified:** not called against the live platform (registered only on +> marketplace/dev deployments and requires site admin). + +### GET /orgs/{orgname} + +Get an organization's details (returned if visible to the requesting user). + +- **Auth:** public (no auth required). A non-public org may return `404` to callers + who cannot see it. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` (`Organization`): + +```json +{ + "id": 3, + "username": "appscode", + "full_name": "", + "avatar_url": "https:///accounts/avatars?obj=avatars/3-", + "description": "", + "website": "", + "location": "", + "rancherManagementClusterEndPoint": "", + "visibility": "public", + "orgType": 6 +} +``` + +> **Verified:** `GET` returned `200` for `appscode` on 2026-07-14. + +### PATCH /orgs/{orgname} + +Update an organization's profile fields. + +- **Auth:** token + `authzCheck(edit:org)` (`Organization_CanEditOrg`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Request body** (`EditOrgOption`): + +```json +{ + "full_name": "Acme Inc.", + "description": "Updated description", + "website": "https://acme.example.com", + "location": "Remote", + "orgType": "limited", + "visibility": "limited" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `full_name` | string | no | Display name. | +| `description` | string | no | Free-text description. | +| `website` | string | no | Website URL. | +| `location` | string | no | Location text. | +| `orgType` | string | no | One of `public`, `limited`, or `private`. | +| `rancherManagementClusterEndPoint` | string | no | Rancher management cluster endpoint. | +| `visibility` | string | no | One of `""`, `public`, `limited`, `private`. | + +**Response:** `200 OK` with the updated `Organization` (same shape as `GET /orgs/{orgname}`). + +### DELETE /orgs/{orgname} + +Delete an organization. + +- **Auth:** token + `authzCheck(delete:org)` (`Organization_CanDeleteOrg`). The + requester must be the last admin (per the `orgLastAdmin` condition). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `204 No Content` on success. + +## Membership & ownership checks + +### GET /orgs/{orgname}/user/{username} + +Check whether a user exists (in the org context). Looks up a user by username and +returns their profile if the user exists and is active. + +- **Auth:** token (org context). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | +| `username` | string | Username to look up. | + +**Response:** `200 OK` (`Profile`): + +```json +{ + "name": "someuser", + "full_name": "Some User", + "email": "user@example.com", + "keep_email_private": false, + "website": "", + "location": "", + "language": "en-US", + "description": "" +} +``` + +`400` if the user does not exist or is inactive. + +> **Verified:** `GET` returned `200` for `appscode/appscode` on 2026-07-14. + +### GET /orgs/{orgname}/is-owner + +Return `200` if the authenticated user is an owner of the organization. Ownership is +enforced by upstream middleware. + +- **Auth:** token (org context). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` (empty body) when the caller is an owner; otherwise `403`. + +> **Verified:** `GET` returned `200` for `appscode` on 2026-07-14. + +### GET /orgs/{orgname}/members + +List an organization's members. Non-members (and unauthenticated callers) see only +public members. + +- **Auth:** public (no auth required); the response is scoped to what the caller may + see. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` — an array of `User`: + +```json +[ + { + "id": 2, + "login": "someuser", + "username": "someuser", + "full_name": "Some User", + "email": "user@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/?d=identicon", + "language": "en-US", + "is_admin": true, + "last_login": "2026-07-13T18:23:53Z", + "created": "2026-07-05T06:46:29Z", + "type": 0, + "active": true, + "prohibit_login": false, + "location": "", + "website": "", + "description": "", + "orgAdmin": true, + "clientOrgUser": false + } +] +``` + +`username` is a backward-compatibility alias of `login`. + +> **Verified:** `GET` returned `200` for `appscode` on 2026-07-14. + +### POST /orgs/{orgname}/members/action/{action} + +Perform a membership action for a member identified by the `uid` query parameter. + +- **Auth:** token + org membership. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | +| `action` | string | One of `private`, `public`, `remove`, `leave`. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `uid` | integer (int64) | yes | User ID of the member the action applies to. | + +**Response:** `200 OK` when the action is performed. `400` if `uid` is missing or invalid. + +### GET /orgs/{orgname}/members/{username} + +Check whether a user is a member of an organization. + +- **Auth:** public (no auth required). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | +| `username` | string | Username to check. | + +**Response:** `204 No Content` if the user is a member; `404` if not; may redirect +(`302`) to the public-members check for non-members of the org. + +> **Verified:** `GET` returned `204` for member `appscode/someuser` on 2026-07-14. + +### DELETE /orgs/{orgname}/members/{username} + +Remove a member from the organization. + +- **Auth:** token + org ownership + `authzCheck(admin:org)` + (`Organization_CanRemoveMember`, `orgLastMember` condition). Site admins cannot be + removed from the administrative org. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | +| `username` | string | Username of the member to remove. | + +**Response:** `204 No Content` on success. + +### GET /orgs/{orgname}/public_members + +List an organization's public members. + +- **Auth:** public (no auth required). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` — an array of `User` (same shape as `GET /orgs/{orgname}/members`). + +> **Verified:** `GET` returned `200` for `appscode` on 2026-07-14. + +### GET /orgs/{orgname}/public_members/{username} + +Check whether a user is a public member of an organization. + +- **Auth:** public (no auth required). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | +| `username` | string | Username to check. | + +**Response:** `204 No Content` if the user is a public member; `404` if not. + +> **Verified:** `GET` returned `404` for `appscode/someuser` on 2026-07-14 (member is not public). + +### PUT /orgs/{orgname}/public_members/{username} + +Publicize the caller's own organization membership. + +- **Auth:** token + org membership. A user cannot publicize another member (`403`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | +| `username` | string | The caller's own username. | + +**Response:** `204 No Content` on success. + +### DELETE /orgs/{orgname}/public_members/{username} + +Conceal (make private) the caller's own organization membership. + +- **Auth:** token + org membership. A user cannot conceal another member (`403`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | +| `username` | string | The caller's own username. | + +**Response:** `204 No Content` on success. + +## Organization avatar + +### GET /orgs/{orgname}/avatar/ + +Get the organization's avatar URL. + +- **Auth:** token + `authzCheck(view:avatar)` (`Organization_Viewer`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` — a JSON string containing the avatar URL: + +```json +"https:///accounts/avatars?obj=avatars/3-" +``` + +### POST /orgs/{orgname}/avatar/ + +Upload or set the organization avatar. + +- **Auth:** token + `authzCheck(update:avatar)` (`Organization_Editor`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Request body:** `multipart/form-data` (`AvatarParams`): + +| Field | Type | Required | Description | +|---|---|---|---| +| `avatar` | binary (file) | no | Uploaded avatar image file. | +| `source` | string | no | Avatar source selector. | +| `gravatar` | string | no | Gravatar email/URL. | +| `federavatar` | boolean | no | Whether to use a federated avatar. | + +**Response:** `200 OK`; the exact body depends on the avatar handler (a free-form +Kubernetes object). + +### POST /orgs/{orgname}/avatar/delete + +Remove the organization's avatar. + +- **Auth:** token + `authzCheck(delete:avatar)` (`Organization_Editor`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` on success. + +## Rancher integration tokens + +### GET /orgs/{orgname}/rancher/sync-token + +Get the organization's Rancher synchronization token. + +- **Auth:** token + `authzCheck(view:sync-token)` (`Organization_Viewer`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` (`RancherAPIToken`): + +```json +{ + "userID": 4, + "orgID": 3, + "orgName": "appscode", + "accessKeyID": "", + "secretAccessKey": "" +} +``` + +`404` when no sync token exists (e.g. the org is not of Rancher origin). + +> **Verified:** `GET` returned `404` for `appscode` on 2026-07-14 (org is not of Rancher origin — no sync token). + +### POST /orgs/{orgname}/rancher/sync-token + +Create a Rancher organization synchronization token from the provided access key. The +organization must be of Rancher origin. + +- **Auth:** token + `authzCheck(create:rancher-org-sync-token)` (`Organization_Editor`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Request body** (`AccessToken`): + +```json +{ + "name": "rancher-sync", + "sha1": "" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `id` | integer (int64) | no | Token ID. | +| `name` | string | no | Token name. | +| `sha1` | string | no | The plaintext access key. | +| `token_last_eight` | string | no | Last eight characters of the token. | + +**Response:** `200 OK` (`ApiResponseMessage`): + +```json +{ "message": "token created" } +``` + +`400` if the organization's origin is not Rancher. + +### DELETE /orgs/{orgname}/rancher/sync-token + +Delete the organization's Rancher synchronization token. + +- **Auth:** token + `authzCheck(remove:rancher-sync-token)` (`Organization_Editor`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` on success. + +### GET /orgs/{orgname}/rancher/user-token + +**Deprecated.** Return the caller's Rancher API token for the organization. + +- **Auth:** token + org membership + `authzCheck(view:sync-token)` (`Organization_Viewer`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` (`RancherAPIToken`, same shape as the sync-token response). + +> **Verified:** `GET` returned `404` for `appscode` on 2026-07-14 (deprecated; org is not of Rancher origin). + +### POST /orgs/{orgname}/rancher/user-token + +**Deprecated.** Store a Rancher API token for the caller in the organization. + +- **Auth:** token + org membership + `authzCheck(create:rancher-org-sync-token)` (`Organization_Editor`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Request body** (`AccessToken`): same as `POST /orgs/{orgname}/rancher/sync-token`. + +**Response:** `200 OK` on success. + +### DELETE /orgs/{orgname}/rancher/user-token + +**Deprecated.** Delete the caller's Rancher API token for the organization. + +- **Auth:** token + org membership + `authzCheck(remove:rancher-sync-token)` (`Organization_Editor`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` on success. + +## Organization access & NATS tokens + +These endpoints manage tokens belonging to the organization's system admin. + +### GET /orgs/{orgname}/tokens/access-tokens/ + +List the access tokens of the organization's system admin. + +- **Auth:** token + org membership + `authzCheck(list:access-token)` (`Organization_Viewer`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` — an array of `AccessTokenInfo`: + +```json +[ + { + "id": 12, + "uid": 4, + "name": "kube-ui-server 2026-07-05 7:49AM", + "token": "", + "tokenLastEight": "3d492e7c", + "createdAt": 1783237775, + "updatedAt": 1783785356, + "hasRecentActivity": true, + "hasUsed": true, + "expDate": 2098856975 + } +] +``` + +The `token` value is empty for existing tokens; the full token is only returned at +creation time. `createdAt`, `updatedAt`, and `expDate` are Unix timestamps. `400` +if the organization system admin does not exist. + +> **Verified:** `GET` returned `200` for `appscode` on 2026-07-14. + +### DELETE /orgs/{orgname}/tokens/access-tokens/{id} + +Delete an access token of the organization's system admin. + +- **Auth:** token + org membership + `authzCheck(delete:access-token)` (`Organization_Editor`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | +| `id` | integer (int64) | ID of the access token. | + +**Response:** `200 OK` on success. `400` if the organization system admin does not exist. + +### GET /orgs/{orgname}/tokens/nats-tokens/ + +List the NATS user-type tokens of the organization's system admin. + +- **Auth:** token + org membership + `authzCheck(list:nats-token)` (`Organization_Viewer`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` — an array of `NatsAccount`: + +```json +[ + { + "id": 1, + "uid": 4, + "accountType": "user", + "natsPubKey": "", + "clusterID": "", + "productName": "kubedb", + "revoked": false + } +] +``` + +`400` if the organization system admin does not exist. + +> **Verified:** `GET` returned `200` for `appscode` on 2026-07-14 (empty list `[]`). + +### POST /orgs/{orgname}/tokens/nats-tokens/{id}/revoke + +Revoke a NATS user-type token of the organization's system admin. + +- **Auth:** token + org membership + `authzCheck(revoke:nats-token)` (`Organization_Editor`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | +| `id` | integer (int64) | ID of the NATS token. | + +**Response:** `200 OK` on success. `400` if the organization system admin is missing +or the NATS user is not found. diff --git a/docs/platform/api/organizations-teams/teams.md b/docs/platform/api/organizations-teams/teams.md new file mode 100644 index 0000000..2b95e78 --- /dev/null +++ b/docs/platform/api/organizations-teams/teams.md @@ -0,0 +1,320 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-organizations-teams-teams + name: Teams + parent: api-organizations-teams + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Teams + +Endpoints for managing teams within an organization and their members. Teams are +created under an organization (`/orgs/{orgname}/teams`) and then addressed by their +numeric ID under `/teams/{teamid}`. + +All paths below are relative to the API root `/api/v1`. For example, +`GET /teams/{teamid}` is `GET https:///api/v1/teams/{teamid}`. In these +paths `orgname` is the organization slug (e.g. `appscode`) and `teamid` is the +team's numeric ID. + +All team endpoints authenticate with a personal access token: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/teams/1 +``` + +Authorization checks (e.g. `view:team`, `edit:team`, `add:team-member`) are +relationship-based (OpenFGA) and evaluated against the caller's role in the team or +its organization. + +## Teams under an organization + +### GET /orgs/{orgname}/teams + +List the teams of an organization. + +- **Auth:** token + org membership + `authzCheck(list:team)` (`Organization_Viewer`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Response:** `200 OK` — an array of `Team`: + +```json +[ + { + "id": 1, + "name": "Owners", + "description": "", + "organization": null, + "permission": "owner", + "units": [ + "repo.code", + "repo.issues", + "repo.pulls" + ], + "type": "kubernetes" + }, + { + "id": 2, + "name": "Editors", + "description": "", + "organization": null, + "permission": "write", + "units": null, + "type": "" + }, + { + "id": 3, + "name": "Viewers", + "description": "", + "organization": null, + "permission": "read", + "units": null, + "type": "" + } +] +``` + +Each `Team` has an `id`, `name`, `description`, optional embedded `organization`, +`permission` (one of `none`, `read`, `write`, `admin`, `owner`), a `units` list, a +`type`, and (when set) a `role_ids` array of assigned custom-role IDs. + +> **Verified:** `GET` returned `200` for `appscode` on 2026-07-14 (3 teams: Owners, Editors, Viewers). + +### POST /orgs/{orgname}/teams + +Create a team in the organization. + +- **Auth:** token + org membership + `authzCheck(create:team)` (team editor). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | + +**Request body** (`CreateTeamOption`): + +```json +{ + "name": "Developers", + "description": "Application developers", + "permission": "write", + "assignedRoleIDs": [101, 102], + "type": "kubernetes" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `name` | string | yes | Team name. | +| `type` | string | yes | Team type. | +| `description` | string | no | Free-text description. | +| `permission` | string | no | One of `read`, `write`, `admin`. | +| `assignedRoleIDs` | integer[] (int64) | no | Custom-role IDs assigned to the team. | + +**Response:** `201 Created` with the created `Team`. `400` if the team type is +invalid or too many roles are assigned. + +### POST /orgs/{orgname}/teams/{teamid}/action/{action} + +Perform a team action (join, leave, remove, add) for the user identified by the `uid` +query parameter (or `uname` for the `add` action). + +- **Auth:** token + org membership + `authzCheck(ctx.param.action:team)` (`Team_Member`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. | +| `teamid` | integer (int64) | ID of the team. | +| `action` | string | One of `join`, `leave`, `remove`, `add`. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `uid` | integer (int64) | yes | User ID the action applies to. | +| `uname` | string | no | Username to add (used with the `add` action). | + +**Response:** `200 OK` when the action is performed. `400` if `uid` is missing or the +target user is an organization. `409` if the user is already a member of the team. + +## Managing a team by ID + +### GET /teams/{teamid} + +Get a team by ID. + +- **Auth:** token + `authzCheck(view:team)` (`Team_CanView`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `teamid` | integer (int64) | ID of the team. | + +**Response:** `200 OK` (`Team`): + +```json +{ + "id": 1, + "name": "Owners", + "description": "", + "organization": null, + "permission": "owner", + "units": null, + "type": "kubernetes" +} +``` + +> **Verified:** `GET` returned `200` for team `1` on 2026-07-14. + +### PATCH /teams/{teamid} + +Update a team. The owner-team permission cannot be changed. + +- **Auth:** token + `authzCheck(edit:team)` (`Team_CanEdit`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `teamid` | integer (int64) | ID of the team. | + +**Request body** (`EditTeamOption`): + +```json +{ + "name": "Developers", + "description": "Updated description", + "permission": "custom", + "assignedRoleIDs": [101], + "type": "kubernetes" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `name` | string | yes | Team name. | +| `description` | string | no | Free-text description. | +| `permission` | string | no | One of `read`, `write`, `admin`, `custom`. | +| `assignedRoleIDs` | integer[] (int64) | no | Custom-role IDs assigned to the team. | +| `type` | string | no | Team type. | + +**Response:** `200 OK` with the updated `Team`. `400` if the team type or name is invalid. + +### DELETE /teams/{teamid} + +Delete a team. + +- **Auth:** token + `authzCheck(delete:team)` (`Team_CanDelete`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `teamid` | integer (int64) | ID of the team. | + +**Response:** `204 No Content` on success. + +## Team members + +### GET /teams/{teamid}/members + +List the members of a team. + +- **Auth:** token + org membership + `authzCheck(list:team-members)` (`Team_CanView`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `teamid` | integer (int64) | ID of the team. | + +**Response:** `200 OK` — an array of `User`: + +```json +[ + { + "id": 2, + "login": "someuser", + "username": "someuser", + "full_name": "Some User", + "email": "user@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/?d=identicon", + "is_admin": true, + "active": true, + "orgAdmin": true + } +] +``` + +`username` is a backward-compatibility alias of `login`. + +> **Verified:** `GET` returned `200` for team `1` on 2026-07-14. + +### GET /teams/{teamid}/members/{username} + +Get a specific member of a team. + +- **Auth:** token + `authzCheck(view:team-member)` (`Team_CanView`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `teamid` | integer (int64) | ID of the team. | +| `username` | string | Username of the team member. | + +**Response:** `200 OK` — a single `User` (same shape as the list entries above). + +> **Verified:** `GET` returned `200` for team `1`, member `someuser`, on 2026-07-14. + +### PUT /teams/{teamid}/members/{username} + +Add a user to the team. + +- **Auth:** token + `authzCheck(add:team-member)` (`Team_CanAddMember`). + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `teamid` | integer (int64) | ID of the team. | +| `username` | string | Username of the user to add. | + +**Query parameters:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `autoConnectClusters` | boolean | no | When adding to the owner team, auto-connect the user to the org's clusters. | + +**Response:** `204 No Content` on success. + +### DELETE /teams/{teamid}/members/{username} + +Remove a user from the team. + +- **Auth:** token + `authzCheck(remove:team-member)` (`Team_CanRemoveMember`, + `ownerTeamLastMember` condition). Site admins cannot be removed from the + administrative org. + +**Path parameters:** + +| Name | Type | Description | +|---|---|---| +| `teamid` | integer (int64) | ID of the team. | +| `username` | string | Username of the member to remove. | + +**Response:** `204 No Content` on success. diff --git a/docs/platform/api/rancher/_index.md b/docs/platform/api/rancher/_index.md new file mode 100644 index 0000000..5d6a2f6 --- /dev/null +++ b/docs/platform/api/rancher/_index.md @@ -0,0 +1,35 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-rancher + name: Rancher Integration + parent: api + weight: 160 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Rancher Integration API + +The Rancher Integration API wires ACE together with a Rancher management cluster. +It lets a site administrator sync Rancher users into a Rancher-managed +organization, obtain the `acerproxy` Helm installation command, download the +platform CA certificate, and mint Rancher proxy-server tokens. It also exposes an +endpoint that returns NATS credentials for the authenticated Rancher user. + +All routes live under the `/api/v1/rancher` prefix and require a valid bearer +token. + +> **Auth notes.** The `/rancher/org/{orgname}/...` routes require **site-admin** +> privileges **and** a **Rancher-managed organization** (an org whose origin is +> Rancher). On a platform whose organizations are not Rancher-managed these routes +> return `500` with `org isn't a rancher organization`. `POST /rancher/proxy-token` +> requires site-admin only. `GET /rancher/nats-cred` requires a token in the +> **Rancher-user** context (injected by the server's `injectRancherUserInfo` +> middleware). + +## Pages + +- [Rancher Integration](../rancher.md) — user sync, acerproxy install + command, CA download, proxy-server token, and NATS credentials. diff --git a/docs/platform/api/rancher/rancher.md b/docs/platform/api/rancher/rancher.md new file mode 100644 index 0000000..3350b6c --- /dev/null +++ b/docs/platform/api/rancher/rancher.md @@ -0,0 +1,213 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-rancher-rancher + name: Rancher Integration + parent: api-rancher + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Rancher Integration + +Endpoints for integrating ACE with a Rancher management cluster: syncing Rancher +users, generating the `acerproxy` installation command, downloading the platform +CA certificate, minting Rancher proxy-server tokens, and fetching NATS +credentials for the authenticated Rancher user. + +All paths below are relative to the API base **`/api/v1`** (for example, +`/rancher/nats-cred` is served at `/api/v1/rancher/nats-cred`). + +## Authentication + +Every endpoint requires a bearer token, sent as a header: + +``` +Authorization: token +``` + +The token may also be supplied via a `token` or `access_token` query parameter. + +Authorization requirements differ per route: + +- **`/rancher/org/{orgname}/...`** — the caller must be a **site administrator** + and the named organization must be **Rancher-managed** (its origin is Rancher). + On platforms whose organizations are not Rancher-managed these routes fail with + `500 org isn't a rancher organization`. +- **`POST /rancher/proxy-token`** — the caller must be a **site administrator**. +- **`GET /rancher/nats-cred`** — any valid token; the server resolves the + Rancher-user context from the token. + +--- + +## User sync + +### GET /rancher/org/{orgname}/sync/users + +Imports users from the organization's Rancher management cluster into ACE. For +each Rancher user it creates a matching ACE user (when missing) and adds them to +the organization's viewer team. + +- **Auth:** token — **site-admin** required, and `{orgname}` must be a + Rancher-managed organization. + +**Path parameters** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. Must be a Rancher-managed org. | + +**Response** — `200 OK`. A summary of the sync, listing successfully synced +usernames and any users that failed (each with an error string). + +```json +{ + "synced_users": [ + "alice", + "bob" + ], + "failed_users": [ + { "carol": "could not create user: email already in use" } + ] +} +``` + +| Field | Type | Description | +|---|---|---| +| `synced_users` | array of string | Usernames successfully imported / added to the viewer team. | +| `failed_users` | array of object | Map entries of `username → error message` for users that failed. | + +> **Verified:** returned `500` against `appscode/sync/users` — `org isn't a rancher organization` (this platform's org `appscode` is not Rancher-managed, so the site-admin + Rancher-org precondition fails before any sync). + +--- + +## acerproxy installation + +### GET /rancher/org/{orgname}/acerproxy + +Returns a ready-to-run Helm command that installs the `acerproxy` chart, wired +with a freshly issued Rancher extended server token and the platform base URL. + +- **Auth:** token — **site-admin** required, and `{orgname}` must be a + Rancher-managed organization. + +**Path parameters** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. Must be a Rancher-managed org. | + +**Response** — `200 OK`. + +```json +{ + "helm": "helm upgrade -i acerproxy oci://ghcr.io/appscode-charts/acerproxy --set token= --set baseURL=https:// ..." +} +``` + +| Field | Type | Description | +|---|---|---| +| `helm` | string | The complete `helm upgrade -i` command to install acerproxy. | + +> **Verified:** returned `500` against `appscode/acerproxy` — `org isn't a rancher organization` (org `appscode` is not Rancher-managed). + +--- + +## CA certificate + +### GET /rancher/org/{orgname}/ca/download + +Returns the platform CA certificate as a downloadable text file (`ace-ca.txt`). + +- **Auth:** token — **site-admin** required, and `{orgname}` must be a + Rancher-managed organization. + +**Path parameters** + +| Name | Type | Description | +|---|---|---| +| `orgname` | string | Organization slug. Must be a Rancher-managed org. | + +**Response** — `200 OK`, `Content-Type: text/plain`. The response body is the +PEM-encoded CA certificate, served as an attachment named `ace-ca.txt`. Returns +`400` if no CA certificate is configured. + +``` +-----BEGIN CERTIFICATE----- +MIIC......IDAQAB +-----END CERTIFICATE----- +``` + +> **Verified:** returned `500` against `appscode/ca/download` — `org isn't a rancher organization` (org `appscode` is not Rancher-managed). + +--- + +## Proxy-server token + +### POST /rancher/proxy-token + +Creates a Rancher extended server token for a given Rancher URL and returns it in +the platform's access-token API format. + +- **Auth:** token — **site-admin** required. +- **Not verified live:** this is a `POST`; not called against the platform per + the GET-only verification policy. + +**Request body** — a JSON string map. The `rancherUrl` key specifies the Rancher +management cluster endpoint. + +```json +{ + "rancherUrl": "https://rancher.example.com" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `rancherUrl` | string | yes | Endpoint of the Rancher management cluster to mint the extended server token against. | + +**Response** — `201 Created`. The created access token (`AccessToken` schema). + +```json +{ + "name": "rancher-proxy-server", + "token": "", + "expiresAt": "2026-08-01T00:00:00Z" +} +``` + +The exact field set follows the platform `AccessToken` schema; treat `token` as a +secret and store it securely. + +--- + +## NATS credentials + +### GET /rancher/nats-cred + +Returns the primary NATS user JWT and seed for the authenticated Rancher user. If +the existing credentials are no longer authorized, the server recreates the +primary NATS account before returning fresh credentials. + +- **Auth:** token — any valid token; the Rancher-user context is resolved from + the token by the server. + +**Response** — `200 OK`. + +```json +{ + "user-jwt": "", + "user-seed": "SUAB......XYZ", + "url": "wss:///nats" +} +``` + +| Field | Type | Description | +|---|---|---| +| `user-jwt` | string | The primary NATS user JWT for the Rancher user. | +| `user-seed` | string | The NATS user seed (private nkey). Treat as a secret. | +| `url` | string | NATS connection URL. Present only when two external NATS addresses are configured. | + +> **Verified:** `GET` returned `200` against `/rancher/nats-cred` on 2026-07-14 — the response carried `url`, `user-jwt`, and `user-seed` for the token's Rancher-user context. diff --git a/docs/platform/api/users-settings/_index.md b/docs/platform/api/users-settings/_index.md new file mode 100644 index 0000000..4911361 --- /dev/null +++ b/docs/platform/api/users-settings/_index.md @@ -0,0 +1,36 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-users-settings + name: "Identity: Users & Settings" + parent: api + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Identity: Users & Settings + +APIs for user accounts, profile and security settings, personal access and NATS +tokens, cloud credentials, and social (follow) relationships. These endpoints back +the account and settings screens of the ACE web console and let you script the same +operations against the `b3` backend. + +All routes are served under the `/api/v1` prefix. Most endpoints authenticate with a +personal access token sent as `Authorization: token ` (it may also be +supplied as a `token` or `access_token` query parameter). A handful of routes are +public (no auth) or use HTTP Basic auth — this is called out per endpoint. + +## Pages + +- [Public & Basic-auth User APIs](../public-user-apis.md) — public + user lookup/search, a user's organizations, social follow info, HTTP Basic-auth + token management, and sign-in. +- [Authenticated User](../authenticated-user.md) — the + `/api/v1/user/*` endpoints: the current user, emails, NATS credentials, cloud + credentials, clusters, teams, organizations, and name/email validation. +- [User Settings](../user-settings.md) — the + `/api/v1/user/settings/*` endpoints: profile and avatar, password and account + emails, 2FA and WebAuthn security, sessions, personal access and NATS tokens, and + OAuth2 applications. diff --git a/docs/platform/api/users-settings/authenticated-user.md b/docs/platform/api/users-settings/authenticated-user.md new file mode 100644 index 0000000..f98b2db --- /dev/null +++ b/docs/platform/api/users-settings/authenticated-user.md @@ -0,0 +1,571 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-users-settings-authenticated-user + name: Authenticated User + parent: api-users-settings + weight: 20 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Authenticated User + +The `/api/v1/user/*` endpoints operate on the currently authenticated user +identified by the request token. All paths on this page are relative to the API root +`/api/v1` (for example, `/user/emails` is `https:///api/v1/user/emails`). + +Unless noted otherwise: + +- **Auth:** Token — send `Authorization: token `. + +A few endpoints require additional privileges (site admin) or are only registered on +AppsCode-hosted deployments; this is called out per endpoint. + +--- + +## Current user & session + +### GET /user + +Get the authenticated user. + +- **Auth:** Token. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `check_client_org` | string | no | When `"true"`, populate the `clientOrgUser` field on the response. | + +**Response:** `200 OK` — a `User` object. + +```json +{ + "id": 2, + "login": "someuser", + "username": "someuser", + "full_name": "Some User", + "email": "user@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/?d=identicon", + "language": "en-US", + "is_admin": true, + "last_login": "2026-07-13T18:23:53Z", + "created": "2026-07-05T06:46:29Z", + "type": 0, + "active": true, + "prohibit_login": false, + "orgAdmin": false, + "clientOrgUser": false +} +``` + +The `User` fields are documented in the +[Public & Basic-auth User APIs](../public-user-apis.md#user-object) +page. + +> **Verified:** `GET /user` returned `200` against `appscode` on 2026-07-14. + +Example: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + https:///api/v1/user +``` + +### GET /user/signout + +Sign out the authenticated user (clears session and auth cookies). + +- **Auth:** Token. + +**Response:** `200 OK` with no body. + +### GET /user/firebase-token + +Get a Firebase custom auth token for the authenticated user. Only registered on +AppsCode-hosted deployments. + +- **Auth:** Token. AppsCode-hosted deployments only. + +**Response:** `200 OK` — a `FirebaseToken`. + +```json +{ + "firebaseToken": "" +} +``` + +> **Verified:** `GET /user/firebase-token` returned `404` against `appscode` on 2026-07-14 — the route is not registered on this (self-hosted) deployment. + +--- + +## NATS credentials + +### GET /user/nats/credentials + +Get the authenticated user's NATS credentials (endpoints plus credential bytes for +the primary NATS user). + +- **Auth:** Token. + +**Response:** `200 OK` — a `NatsCredentialsResponse`. + +```json +{ + "natsEndpoints": ["nats://nats.example.com:4222"], + "credentials": "" +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `natsEndpoints` | array of string | NATS server URLs. | +| `credentials` | string (byte) | Base64-encoded NATS credentials file contents. | + +> **Verified:** `GET /user/nats/credentials` returned `200` against `appscode` on 2026-07-14. (Credential bytes redacted above.) + +### GET /user/nats/admin_credentials + +Get NATS admin credentials. The response body is deployment-specific and modeled as +an opaque JSON object. + +- **Auth:** Token + **site admin**. + +**Response:** `200 OK` — an opaque object. + +> **Verified:** `GET /user/nats/admin_credentials` returned `200` against `appscode` on 2026-07-14 (called with a site-admin token). + +### GET /user/nats/user_credentials + +Get NATS user credentials. Deployment-specific opaque object. + +- **Auth:** Token + **site admin**. + +**Response:** `200 OK` — an opaque object. + +> **Verified:** `GET /user/nats/user_credentials` returned `302` against `appscode` on 2026-07-14 — the request was redirected (missing required NATS user context on this deployment). + +### GET /user/nats/cluster-resource-history + +Get cluster resource history from NATS. Deployment-specific opaque object. + +- **Auth:** Token + **site admin**. + +**Response:** `200 OK` — an opaque object. + +> **Verified:** `GET /user/nats/cluster-resource-history` returned `400` against `appscode` on 2026-07-14 — required query parameters (cluster context) were not supplied. + +--- + +## Emails + +### GET /user/emails + +List the authenticated user's email addresses. + +- **Auth:** Token. + +**Response:** `200 OK` — an array of `Email` objects. + +```json +[ + { "email": "user@example.com", "verified": true, "primary": true } +] +``` + +| Field | Type | Description | +|-------|------|-------------| +| `email` | string | The email address. | +| `verified` | boolean | Whether the address is verified. | +| `primary` | boolean | Whether it is the primary address. | + +> **Verified:** `GET /user/emails` returned `200` against `appscode` on 2026-07-14. + +### POST /user/emails + +Add one or more email addresses. + +- **Auth:** Token. + +**Request body:** `CreateEmailOption`. + +```json +{ + "emails": ["user@example.com"] +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `emails` | array of string | yes | Email addresses to add. | + +**Response:** `201 Created` — the updated array of `Email` objects. + +### DELETE /user/emails + +Delete one or more email addresses. + +- **Auth:** Token. + +**Request body:** `DeleteEmailOption`. + +```json +{ + "emails": ["user@example.com"] +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `emails` | array of string | yes | Email addresses to remove. | + +**Response:** `204 No Content`. + +--- + +## Social follow + +### GET /user/followers + +List the authenticated user's followers. + +- **Auth:** Token. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `page` | integer | no | Page number of results (1-based). | + +**Response:** `200 OK` — an array of `User` objects. + +> **Verified:** `GET /user/followers` returned `200` against `appscode` on 2026-07-14. + +### GET /user/following + +List the users the authenticated user is following. + +- **Auth:** Token. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `page` | integer | no | Page number of results (1-based). | + +**Response:** `200 OK` — an array of `User` objects. + +> **Verified:** `GET /user/following` returned `200` against `appscode` on 2026-07-14. + +### GET /user/following/{username} + +Check whether the authenticated user follows the given user. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Username to check. | + +**Response:** `204 No Content` if following; `404` otherwise. + +### PUT /user/following/{username} + +Follow a user. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Username to follow. | + +**Response:** `204 No Content`. + +### DELETE /user/following/{username} + +Unfollow a user. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Username to unfollow. | + +**Response:** `204 No Content`. + +--- + +## Organizations & teams + +### GET /user/teams + +List all teams the authenticated user belongs to. + +- **Auth:** Token. + +**Response:** `200 OK` — an array of `Team` objects. + +```json +[ + { + "id": 5, + "name": "developers", + "description": "Application developers", + "permission": "write", + "type": "", + "units": [], + "role_ids": [] + } +] +``` + +| Field | Type | Description | +|-------|------|-------------| +| `id` | integer (int64) | Team ID. | +| `name` | string | Team name. | +| `description` | string | Free-form description. | +| `organization` | Organization | The owning organization. | +| `permission` | string | One of `none`, `read`, `write`, `admin`, `owner`. | +| `units` | array of string | Enabled feature units. | +| `type` | string | Team type. | +| `role_ids` | array of integer | Assigned custom-role IDs. | + +> **Verified:** `GET /user/teams` returned `200` against `appscode` on 2026-07-14. + +Organization list endpoints for the authenticated user live under settings — see +[GET /user/settings/organizations](../user-settings.md#get-usersettingsorganizations). + +--- + +## Clusters + +### GET /user/clusters + +List clusters the authenticated user owns or can access. + +- **Auth:** Token. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `all` | string | no | When `"true"`, include clusters the user has access to, not just owned clusters. | + +**Response:** `200 OK` — an array of `ClusterInfo` objects. + +```json +[ + { + "id": 1, + "displayName": "ACE Hub", + "name": "ace", + "uid": "", + "ownerName": "appscode", + "provider": "generic", + "kubernetesVersion": "1.29.0", + "nodeCount": 3, + "createdAt": "2026-07-05T06:46:29Z" + } +] +``` + +Key `ClusterInfo` fields: `id`, `displayName`, `name`, `uid`, `ownerID`/`ownerName`, +`provider`, `vendor`, `kubernetesVersion`, `nodeCount`, `endpoint`, `location`, +`hubClusterName`, `clusterSetName`, `isMonitoringCluster`, `createdAt`, `age`, and a +`status` (a Kubernetes-style object). + +> **Verified:** `GET /user/clusters` returned `200` against `appscode` on 2026-07-14. `GET /user/clusters?all=true` returned `302` on 2026-07-14 (redirected — the `all` variant requires session/org context). + +--- + +## Cloud credentials + +### GET /user/credentials + +List the authenticated user's cloud credentials. + +- **Auth:** Token. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `credential_type` | array of string | no | Filter by one or more credential types. | +| `rancher_endpoint` | string | no | For Rancher credentials, only return those matching this endpoint. | + +**Response:** `200 OK` — an array of `CloudCredentialApiForm` objects. Each embeds a +`cloudv1alpha1.CredentialSpec` (a Kubernetes-style object) plus a `creationTimestamp` +field; the credential fields themselves are free-form (provider-specific). + +> **Verified:** `GET /user/credentials` returned `200` against `appscode` on 2026-07-14. + +### GET /user/credentials/{credName} + +Get a single cloud credential by name. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `credName` | string | Name of the cloud credential. | + +**Response:** `200 OK` — a `CloudCredentialApiForm` object; `404` if not found. + +### POST /user/credentials + +Create a cloud credential for the authenticated user. + +- **Auth:** Token. + +**Request body:** a `cloudv1alpha1.CredentialSpec` — a Kubernetes-style object. +The exact fields are provider-specific; the API passes the object through as an +arbitrary Kubernetes object rather than a fixed schema. + +**Response:** `201 Created` with no body. + +### PUT /user/credentials + +Update a cloud credential for the authenticated user. Registered at the path +`/user/credentials/` (with a trailing slash). + +- **Auth:** Token. + +**Request body:** a `cloudv1alpha1.CredentialSpec` — a Kubernetes-style object (see +POST above). + +**Response:** `204 No Content`. + +### DELETE /user/credentials/{credName} + +Delete a cloud credential by name. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `credName` | string | Name of the cloud credential. | + +**Response:** `204 No Content`; `404` if not found. + +### GET /user/clouds/{cloud}/buckets + +List storage buckets for a cloud provider. + +- **Auth:** Token. + +> **Note:** Despite being a `GET`, this endpoint is bound to a JSON request body +> (`BucketListOptions`). Either a cloud credential **or** a secret namespace + name +> must be provided, plus a cluster UID. Because it requires a body it was not +> exercised as part of live GET verification. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `cloud` | string | Cloud provider identifier. | + +**Request body:** `BucketListOptions`. + +```json +{ + "credential": "my-gcs-cred", + "gce_project": "my-project", + "cluster_uid": "", + "secret_namespace": "", + "secret_name": "", + "provider": "gcs" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `credential` | string | one of credential / secret | Cloud credential name. | +| `gce_project` | string | no | GCE project (for GCS). | +| `cluster_uid` | string | yes | Cluster UID for context. | +| `secret_namespace` | string | one of credential / secret | Secret namespace. | +| `secret_name` | string | one of credential / secret | Secret name. | +| `provider` | string | no | Provider identifier. | + +**Response:** `200 OK` — a `BucketListResponse`. + +```json +{ + "names": ["bucket-a", "bucket-b"] +} +``` + +--- + +## Name & email validation + +Each validation endpoint returns a `Validation` object whose `Status` is one of +`VALID`, `USER_EXISTS`, `RESERVED`, `INVALID`, or `NOT_ALLOWED`. + +### POST /user/validate/username + +Validate username availability. + +- **Auth:** Token. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `user_name` | string | no | Username to validate. | + +**Response:** `200 OK` — a `Validation` object. + +```json +{ "Status": "VALID" } +``` + +### POST /user/validate/orgname + +Validate organization-name availability. + +- **Auth:** Token. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `org` | string | no | Existing organization name (when renaming). | +| `user_name` | string | no | Proposed organization name to validate. | + +**Response:** `200 OK` — a `Validation` object. + +### POST /user/validate/email + +Validate email availability. + +- **Auth:** Token. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `email` | string | no | Email address to validate. | + +**Response:** `200 OK` — a `Validation` object. + +--- + +## Deployment orders + +The high-level design also lists deployment-order endpoints under the authenticated +user (`POST /user/deploy/orders` and the `/user/deploy/orders/{id}/render/*` preview +routes). These are not part of the machine-readable OpenAPI specification for this +group and are therefore not documented in detail here; consult the `b3` source +(`routers/api/v1`) for their current request/response shapes. diff --git a/docs/platform/api/users-settings/public-user-apis.md b/docs/platform/api/users-settings/public-user-apis.md new file mode 100644 index 0000000..68beb3e --- /dev/null +++ b/docs/platform/api/users-settings/public-user-apis.md @@ -0,0 +1,376 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-users-settings-public-user-apis + name: Public & Basic-auth User APIs + parent: api-users-settings + weight: 10 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# Public & Basic-auth User APIs + +Endpoints for looking up users, a user's organizations, social follow relationships, +managing a user's access tokens over HTTP Basic auth, and public sign-in. All paths +on this page are relative to the API root `/api/v1` (for example, `/users/search` is +`https:///api/v1/users/search`). + +Authentication varies per endpoint: + +- **Public** — no credentials required. +- **Basic auth** — HTTP Basic authentication (username + password), used by the + token-management endpoints. A 2FA one-time-password header may also be required. +- **Token** — a personal access token (`Authorization: token `), used by + the follow-relationship endpoints. + +--- + +## User lookup + +### GET /users/search + +Search for users by keyword or user ID. + +- **Auth:** Public. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `q` | string | no | Keyword to search for. | +| `uid` | integer (int64) | no | ID of a specific user to search for. | +| `limit` | integer | no | Maximum number of users to return. | + +**Response:** `200 OK` — a wrapper with an `ok` flag and a `data` array of users. + +```json +{ + "ok": true, + "data": [ + { + "id": 4, + "login": "someuser", + "username": "someuser", + "full_name": "Some User", + "email": "user@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/?d=identicon", + "type": 0, + "active": true, + "is_admin": false + } + ] +} +``` + +> **Verified:** `GET /users/search?q=a&limit=2` returned `200` against `appscode` on 2026-07-14. + +Example: + +``` +curl -H "Authorization: token $ACE_TOKEN" \ + "https:///api/v1/users/search?q=alice&limit=10" +``` + +(The token is optional here since the endpoint is public.) + +### GET /users/{username} + +Get the public profile of a single user by username. + +- **Auth:** Public. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Account username. | + +**Response:** `200 OK` — a [`User`](#user-object) object; `404` if no such user. + +```json +{ + "id": 2, + "login": "someuser", + "username": "someuser", + "full_name": "Some User", + "email": "user@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/?d=identicon", + "language": "en-US", + "is_admin": false, + "type": 0, + "active": true +} +``` + +> **Verified:** `GET /users/appscode` returned `200` against `appscode` on 2026-07-14. + +### GET /users/{username}/orgs + +List the organizations a user belongs to. + +- **Auth:** Public. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Account username. | + +**Response:** `200 OK` — an array of [`Organization`](#organization-object) objects. + +```json +[ + { + "id": 1, + "username": "appscode", + "full_name": "AppsCode Inc.", + "avatar_url": "https://secure.gravatar.com/avatar/?d=identicon", + "description": "", + "website": "", + "location": "", + "visibility": "public", + "orgType": 1 + } +] +``` + +> **Verified:** `GET /users/appscode/orgs` returned `200` against `appscode` on 2026-07-14. + +--- + +## Social follow (public/token) + +### GET /users/{username}/followers + +List a user's followers. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Account username. | + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `page` | integer | no | Page number of results (1-based). | + +**Response:** `200 OK` — an array of [`User`](#user-object) objects. + +> **Verified:** `GET /users/appscode/followers` returned `200` against `appscode` on 2026-07-14. + +### GET /users/{username}/following + +List the users a given user follows. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Account username. | + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `page` | integer | no | Page number of results (1-based). | + +**Response:** `200 OK` — an array of [`User`](#user-object) objects. + +> **Verified:** `GET /users/appscode/following` returned `200` against `appscode` on 2026-07-14. + +### GET /users/{username}/following/{target} + +Check whether one user follows another. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | The (possibly) following user. | +| `target` | string | Username of the possibly-followed user. | + +**Response:** `204 No Content` if `username` follows `target`; `404` otherwise. + +--- + +## Access tokens over HTTP Basic auth + +These endpoints manage a user's personal access tokens using HTTP Basic +authentication. Tokens always belong to the authenticated user. + +### GET /users/{username}/tokens + +List a user's access tokens. + +- **Auth:** Basic auth. A 2FA OTP header may also be required if the account has 2FA + enabled. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Account username (must be the authenticated user). | + +**Response:** `200 OK` — an array of [`AccessToken`](#accesstoken-object) objects. +Note that `sha1` (the plaintext token) is only ever populated on creation. + +```json +[ + { + "id": 12, + "name": "ci-token", + "token_last_eight": "1a2b3c4d" + } +] +``` + +### POST /users/{username}/tokens + +Create an access token for the authenticated user. + +- **Auth:** Basic auth. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Account username (must be the authenticated user). | + +**Request body:** `CreateAccessTokenOption`. + +```json +{ + "name": "ci-token" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | yes | Human-readable name for the token. | + +**Response:** `201 Created` — the created [`AccessToken`](#accesstoken-object). The +plaintext token is returned in `sha1` **only on this response** — store it now, it +cannot be retrieved later. + +```json +{ + "id": 13, + "name": "ci-token", + "sha1": "", + "token_last_eight": "9f8e7d6c" +} +``` + +### DELETE /users/{username}/tokens/{id} + +Delete one of the authenticated user's access tokens. + +- **Auth:** Basic auth. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `username` | string | Account username (must be the authenticated user). | +| `id` | integer (int64) | ID of the access token to delete. | + +**Response:** `204 No Content`. + +--- + +## Sign in + +### POST /user/signin + +Public sign-in with username and password. + +- **Auth:** Public. On success, session/CSRF/NATS cookies are set. Accounts enrolled + in 2FA **cannot** sign in through this endpoint (returns `405`). + +**Request body:** `SignInParams`. + +```json +{ + "username": "someuser", + "password": "", + "remember": true +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `username` | string | yes | Account username. | +| `password` | string | yes | Account password. | +| `remember` | boolean | no | Persist the session across browser restarts. | + +**Response:** `200 OK` with no body (session cookies set). Other statuses: `404` user +does not exist, `405` login prohibited / user inactive / 2FA enabled, `409` email +already in use, `422` validation error. + +--- + +## Object reference + + + +### User object + +| Field | Type | Description | +|-------|------|-------------| +| `id` | integer (int64) | User ID. | +| `login` | string | The user's username. | +| `username` | string | Backward-compatibility alias of `login`. | +| `full_name` | string | Display name. | +| `email` | string | Primary email. | +| `avatar_url` | string | Avatar image URL. | +| `language` | string | Preferred UI language. | +| `is_admin` | boolean | Whether the user is a site admin. | +| `last_login` | string (date-time) | Last login time. | +| `created` | string (date-time) | Account creation time. | +| `type` | integer | Account type (0 = individual). | +| `active` | boolean | Whether the account is active. | +| `prohibit_login` | boolean | Whether login is disabled. | +| `location` | string | Free-form location. | +| `website` | string | Website URL. | +| `description` | string | Free-form bio. | +| `orgAdmin` | boolean | Whether the user administers the org context. | +| `orgType` | integer | Organization type (for org accounts). | +| `clientOrgUser` | boolean | Whether the user is a client-org user. | + + + +### Organization object + +| Field | Type | Description | +|-------|------|-------------| +| `id` | integer (int64) | Organization ID. | +| `username` | string | Organization slug. | +| `full_name` | string | Display name. | +| `avatar_url` | string | Avatar image URL. | +| `description` | string | Free-form description. | +| `website` | string | Website URL. | +| `location` | string | Free-form location. | +| `rancherManagementClusterEndPoint` | string | Rancher management endpoint, if any. | +| `visibility` | string | `public`, `limited`, or `private`. | +| `orgType` | integer | Organization type. | + + + +### AccessToken object + +| Field | Type | Description | +|-------|------|-------------| +| `id` | integer (int64) | Token ID. | +| `name` | string | Token name. | +| `sha1` | string | Plaintext token value — **returned only on creation**. | +| `token_last_eight` | string | Last eight characters, for identification. | diff --git a/docs/platform/api/users-settings/user-settings.md b/docs/platform/api/users-settings/user-settings.md new file mode 100644 index 0000000..7ca5642 --- /dev/null +++ b/docs/platform/api/users-settings/user-settings.md @@ -0,0 +1,847 @@ +--- +layout: docs +menu: + docsplatform_{{.version}}: + identifier: api-users-settings-user-settings + name: User Settings + parent: api-users-settings + weight: 30 +menu_name: docsplatform_{{.version}} +section_menu_id: api +--- + +# User Settings + +The `/api/v1/user/settings/*` endpoints back the account-settings screens: profile +and avatar, password and account emails, two-factor and WebAuthn security, active +sessions, personal access and NATS tokens, and OAuth2 applications. All paths on this +page are relative to the API root `/api/v1` (for example, `/user/settings/profile` +is `https:///api/v1/user/settings/profile`). + +Unless noted otherwise: + +- **Auth:** Token — send `Authorization: token `. + +--- + +## Profile & avatar + +### GET /user/settings/profile + +Get the authenticated user's editable profile. + +- **Auth:** Token. + +**Response:** `200 OK` — a `Profile` object. + +```json +{ + "name": "someuser", + "full_name": "Some User", + "email": "user@example.com", + "keep_email_private": false, + "website": "", + "location": "", + "language": "en-US", + "description": "" +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Username. | +| `full_name` | string | Display name. | +| `email` | string | Primary email. | +| `keep_email_private` | boolean | Hide email from public profile. | +| `website` | string | Website URL. | +| `location` | string | Free-form location. | +| `language` | string | Preferred UI language. | +| `description` | string | Free-form bio. | + +> **Verified:** `GET /user/settings/profile` returned `200` against `appscode` on 2026-07-14. + +### POST /user/settings/profile + +Update the authenticated user's profile. + +- **Auth:** Token. + +**Request body:** a `Profile` object (same fields as above). + +**Response:** `200 OK` — the updated `Profile` object. + +### GET /user/settings/avatar + +Get the authenticated user's avatar settings. + +- **Auth:** Token. + +**Response:** `200 OK` — an `AvatarParams` object. + +```json +{ + "source": "gravatar", + "gravatar": "user@example.com", + "federavatar": false +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `source` | string | Avatar source (e.g. `gravatar`, `local`). | +| `gravatar` | string | Gravatar email/hash. | +| `federavatar` | boolean | Whether federated (libravatar) is enabled. | + +> **Verified:** `GET /user/settings/avatar` returned `200` against `appscode` on 2026-07-14. + +### POST /user/settings/avatar + +Update the authenticated user's avatar. + +- **Auth:** Token. +- **Content type:** `multipart/form-data` (`AvatarParams`), with an `avatar` file + field for uploads plus the `source`, `gravatar`, and `federavatar` fields. + +**Response:** `200 OK` with no body. + +### POST /user/settings/avatar/delete + +Delete the authenticated user's avatar. + +- **Auth:** Token. + +**Response:** `200 OK` with no body. + +--- + +## Account: password, email, deletion + +### POST /user/settings/account/password + +Update the authenticated user's password. + +- **Auth:** Token. + +**Request body:** `UpdatePasswordParams`. + +```json +{ + "old_password": "", + "password": "", + "retype": "" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `old_password` | string | yes | Current password. | +| `password` | string | yes | New password. | +| `retype` | string | yes | New password, repeated for confirmation. | + +**Response:** `200 OK` with no body. + +### GET /user/settings/account/email + +Get the authenticated user's email-address records. Returns the raw +`models.EmailAddress` records, modeled as an array of opaque objects. + +- **Auth:** Token. + +**Response:** `200 OK` — an array of opaque email-address records. + +> **Verified:** the sibling [`GET /user/emails`](../authenticated-user.md#get-useremails) returned `200`; this settings variant returns the same underlying records in raw form. + +### POST /user/settings/account/email + +Add an email address, or make an existing one primary. + +- **Auth:** Token. + +With `?_method=PRIMARY&id=`, marks the existing email with that ID as primary. +Otherwise, adds the email supplied in the body. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `_method` | string | no | Set to `PRIMARY` to mark an existing email as primary. | +| `id` | integer (int64) | no | Email address ID (used with `_method=PRIMARY`). | + +**Request body:** `AddEmailParams`. + +```json +{ "email": "user@example.com" } +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `email` | string | yes (when adding) | Email address to add. | + +**Response:** `200 OK` (with or without a string body). + +### POST /user/settings/account/email/delete + +Delete an email address. + +- **Auth:** Token. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `id` | integer (int64) | no | ID of the email address to delete. | + +**Response:** `200 OK` with no body. + +### POST /user/settings/account/delete + +Delete the authenticated user's account. Requires the current password and signs the +user out on success. + +- **Auth:** Token. + +**Query parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| `password` | string | no | Current password, for confirmation. | + +**Response:** `200 OK` — account deleted and user signed out. + +--- + +## Pagination preferences + +### GET /user/settings/pagination + +Get the authenticated user's per-UI pagination page-size settings. + +- **Auth:** Token. + +**Response:** `200 OK` — a `Pagination` object. + +```json +{ + "kubeDBUI": 0, + "consoleUI": 0, + "platformUI": 0 +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `kubeDBUI` | integer (int64) | Page size for the KubeDB UI. | +| `consoleUI` | integer (int64) | Page size for the console UI. | +| `platformUI` | integer (int64) | Page size for the platform UI. | + +> **Verified:** `GET /user/settings/pagination` returned `200` against `appscode` on 2026-07-14. + +### POST /user/settings/pagination + +Update the authenticated user's pagination settings. + +- **Auth:** Token. + +**Request body:** a `Pagination` object (fields as above). + +**Response:** `200 OK` — the updated `Pagination` object. + +--- + +## Security: two-factor authentication + +### GET /user/settings/security/ + +Get the two-factor enrollment status. + +- **Auth:** Token. + +**Response:** `200 OK` — a `TwoFAStatus` object. + +```json +{ "twoFAEnrolled": false } +``` + +> **Verified:** `GET /user/settings/security/` returned `200` against `appscode` on 2026-07-14. + +### GET /user/settings/security/twofa/enroll + +Begin two-factor enrollment: generate a TOTP secret and QR image. + +- **Auth:** Token. + +**Response:** `200 OK` — a `Security` object. + +```json +{ + "twoFASecret": "", + "twoFAImageURL": "data:image/png;base64,<...>" +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `twoFASecret` | string | TOTP secret to add to an authenticator app. | +| `twoFAImageURL` | string | `data:image/png;base64` encoded QR code. | + +> **Verified:** `GET /user/settings/security/twofa/enroll` returned `200` against `appscode` on 2026-07-14. (Secret redacted above.) + +### POST /user/settings/security/twofa/enroll + +Complete two-factor enrollment by submitting a TOTP passcode. + +- **Auth:** Token. + +**Request body:** `TwoFactorAuthParams`. + +```json +{ "passCode": "123456" } +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `passCode` | string | yes | TOTP passcode from the authenticator app. | + +**Response:** `200 OK` — a scratch token string (store it safely for account recovery). + +### POST /user/settings/security/twofa/regenerate_scratch + +Regenerate the two-factor scratch (recovery) token. + +- **Auth:** Token. + +**Response:** `200 OK` — a new scratch token string. + +### POST /user/settings/security/twofa/disable + +Disable two-factor authentication. + +- **Auth:** Token. + +**Response:** `200 OK` with no body. + +--- + +## Security: WebAuthn keys + +### GET /user/settings/security/webauthn/keys + +List the authenticated user's registered WebAuthn security keys. + +- **Auth:** Token. + +**Response:** `200 OK` — an array of `WebAuthnSecurityKeys` objects. + +```json +[ + { "ID": 1, "Name": "yubikey-5", "UID": 2 } +] +``` + +| Field | Type | Description | +|-------|------|-------------| +| `ID` | integer (int64) | Key ID. | +| `Name` | string | User-assigned key name. | +| `UID` | integer (int64) | Owning user ID. | + +> **Verified:** `GET /user/settings/security/webauthn/keys` returned `200` against `appscode` on 2026-07-14. + +### POST /user/settings/security/webauthn/request_register + +Begin WebAuthn registration; reserves a credential name and returns the WebAuthn +credential-creation options. + +- **Auth:** Token. + +**Request body:** `WebauthnRegistrationOptions`. + +```json +{ "name": "yubikey-5" } +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | yes | Name for the new security key. | + +**Response:** `200 OK` — the WebAuthn credential-creation options (an opaque, +protocol-defined object passed to the browser's WebAuthn API). + +### POST /user/settings/security/webauthn/register + +Complete WebAuthn registration. Reads the security-key response (the authenticator's +attestation) from the request body. + +- **Auth:** Token. + +**Response:** `201 Created` — the created credential (an opaque, protocol-defined +object). + +### DELETE /user/settings/security/webauthn/keys/{id} + +Delete a WebAuthn security key. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | ID of the WebAuthn security key. | + +**Response:** `200 OK` with no body; `404` if not found. + +--- + +## Security: sessions + +### GET /user/settings/security/sessions/ + +List the authenticated user's active sessions. + +- **Auth:** Token. + +**Response:** `200 OK` — an array of `SessionInfoAPIForm` objects. Each embeds an +opaque go-macaron session record plus the fields below. + +```json +[ + { + "isActiveSession": true, + "lastAccessedZonedTime": "2026-07-13T18:23:53Z", + "lastAccessed": 1768329833 + } +] +``` + +| Field | Type | Description | +|-------|------|-------------| +| `isActiveSession` | boolean | Whether this is the current session. | +| `lastAccessedZonedTime` | string | Last access time (formatted). | +| `lastAccessed` | integer (int64) | Last access time (Unix). | + +> **Verified:** `GET /user/settings/security/sessions/` returned `302` against `appscode` on 2026-07-14 — this endpoint relies on the web-console session cookie and redirects when called with a bare token. + +### DELETE /user/settings/security/sessions/{sid}/revoke + +Revoke a session. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `sid` | string | Session ID to revoke. | + +**Response:** `200 OK` — the remaining array of `SessionInfoAPIForm` objects; +`404` if the session is not found. + +--- + +## Security: linked accounts + +### GET /user/settings/security/account_link + +List linked external (OAuth2/login-source) accounts. + +- **Auth:** Token. + +**Response:** `200 OK` — an array of `AccountLink` objects. + +```json +[ + { + "loginSourceID": 3, + "externalID": "", + "type": 6, + "providerDisplayName": "GitHub", + "isActived": true, + "isSyncEnabled": false + } +] +``` + +| Field | Type | Description | +|-------|------|-------------| +| `loginSourceID` | integer (int64) | Login-source ID. | +| `externalID` | string | External account identifier. | +| `type` | integer | Login-source type. | +| `providerDisplayName` | string | Human-readable provider name. | +| `isActived` | boolean | Whether the link is active. | +| `isSyncEnabled` | boolean | Whether group/attribute sync is enabled. | + +> **Verified:** `GET /user/settings/security/account_link` returned `200` against `appscode` on 2026-07-14. + +### POST /user/settings/security/account_link + +Remove a linked external account. (Despite the `POST` verb, this deletes the link.) + +- **Auth:** Token. + +**Request body:** `AccountLinkParams`. + +```json +{ + "loginSourceID": 3, + "externalID": "" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `loginSourceID` | integer (int64) | yes | Login-source ID of the link. | +| `externalID` | string | yes | External account identifier. | + +**Response:** `200 OK` with no body. + +--- + +## Organizations + + + +### GET /user/settings/organizations + +List the authenticated user's organizations. + +- **Auth:** Token. + +**Response:** `200 OK` — an array of `Organization` objects (fields documented on the +[Public & Basic-auth User APIs](../public-user-apis.md#organization-object) +page). + +> **Verified:** `GET /user/settings/organizations` returned `200` against `appscode` on 2026-07-14. + +### GET /user/settings/organizations/create + +Check whether the authenticated user is allowed to create organizations. + +- **Auth:** Token. + +**Response:** `200 OK` if allowed; `403` if not. + +> **Verified:** `GET /user/settings/organizations/create` returned `200` against `appscode` on 2026-07-14 (this user may create organizations). + +### POST /user/settings/organizations/create + +Create an organization. + +- **Auth:** Token. +- **Content type:** `multipart/form-data` (`CreateOrgParams`). + +**Request body fields (`CreateOrgParams`):** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `orgName` | string | yes | Organization slug. | +| `orgFullName` | string | no | Display name. | +| `description` | string | no | Free-form description. | +| `website` | string | no | Website URL. | +| `location` | string | no | Free-form location. | +| `orgType` | string | no | Organization type. | +| `rancherManagementClusterEndPoint` | string | no | Rancher management endpoint. | +| `provideSyncToken` | boolean | no | Whether a Rancher sync token is supplied. | +| `rancherSyncToken` | object | no | Rancher access key pair. | +| `visibility` | string | no | `public`, `limited`, or `private`. | +| `source` / `avatar` / `gravatar` / `federavatar` | mixed | no | Avatar settings (with `avatar` as a file upload). | + +**Response:** `200 OK` — an `ApiResponseMessage` (`{ "message": "..." }`), which may +carry a note about Rancher sync. + +--- + +## Personal access tokens (settings) + +### GET /user/settings/tokens/access-tokens/ + +List the authenticated user's personal access tokens. + +- **Auth:** Token. + +**Response:** `200 OK` — an array of `SettingsAccessToken` objects. + +```json +[ + { + "id": 1, + "uid": 2, + "name": "ci-token", + "tokenLastEight": "1a2b3c4d", + "createdAt": 1768329833, + "updatedAt": 1768329833, + "hasRecentActivity": true, + "hasUsed": true, + "expDate": 0 + } +] +``` + +| Field | Type | Description | +|-------|------|-------------| +| `id` | integer (int64) | Token ID. | +| `uid` | integer (int64) | Owning user ID. | +| `name` | string | Token name. | +| `token` | string | Plaintext token — **returned only on creation**. | +| `tokenLastEight` | string | Last eight characters, for identification. | +| `createdAt` / `updatedAt` | integer (int64) | Unix timestamps. | +| `hasRecentActivity` | boolean | Whether the token was used recently. | +| `hasUsed` | boolean | Whether the token has ever been used. | +| `expDate` | integer (int64) | Expiry (Unix seconds); `0` means no expiry. | + +> **Verified:** `GET /user/settings/tokens/access-tokens/` returned `200` against `appscode` on 2026-07-14. + +### POST /user/settings/tokens/access-tokens/ + +Create a new personal access token. + +- **Auth:** Token. + +**Request body:** `NewAccessTokenParam`. + +```json +{ + "name": "ci-token", + "expTime": 0 +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | yes | Token name. | +| `expTime` | integer (int64) | no | Unix expiry timestamp; `0` means no expiry. | + +**Response:** `201 Created` — a `SettingsAccessToken`. The plaintext value is returned +in `token` **only on this response**. + +### POST /user/settings/tokens/access-tokens/delete-records + +Bulk-delete access tokens by ID. + +- **Auth:** Token. + +**Request body:** `AccessTokenIdList`. + +```json +{ "tokenIDs": [1, 2, 3] } +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `tokenIDs` | array of integer (int64) | yes | IDs of tokens to delete. | + +**Response:** `200 OK` — a message describing how many records were deleted +(`{ "message": "..." }`). + +### DELETE /user/settings/tokens/access-tokens/{id} + +Delete a single access token. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | ID of the access token to delete. | + +**Response:** `200 OK` with no body; `404` if not found. + +--- + +## NATS tokens (settings) + +### GET /user/settings/tokens/nats-tokens/ + +List the authenticated user's NATS user-type tokens (returned as an array of opaque +NATS token-account objects). + +- **Auth:** Token. + +**Response:** `200 OK` — an array of opaque objects. + +> **Verified:** `GET /user/settings/tokens/nats-tokens/` returned `200` against `appscode` on 2026-07-14. + +### POST /user/settings/tokens/nats-tokens/{id}/revoke/ + +Revoke a NATS user-type token. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | ID of the NATS token to revoke. | + +**Response:** `200 OK` with no body; `404` if not found. + +--- + +## OAuth2 applications + +### GET /user/settings/applications/oauth2 + +List the authenticated user's OAuth2 applications. + +- **Auth:** Token. + +**Response:** `200 OK` — an array of `OAuth2Application` objects. + +```json +[ + { + "id": 1, + "uid": 2, + "name": "my-app", + "clientId": "", + "redirectURIs": ["https://app.example.com/callback"], + "createdAt": 1768329833, + "updatedAt": 1768329833 + } +] +``` + +| Field | Type | Description | +|-------|------|-------------| +| `id` | integer (int64) | Application ID. | +| `uid` | integer (int64) | Owning user ID. | +| `name` | string | Application name. | +| `clientId` | string | OAuth2 client ID. | +| `clientSecret` | string | Plaintext secret — **returned only on create/regenerate**. | +| `clientSecretHash` | string | Stored secret hash. | +| `redirectURIs` | array of string | Allowed redirect URIs. | +| `logo` | string | Logo URL. | +| `createdAt` / `updatedAt` | integer (int64) | Unix timestamps. | + +> **Verified:** `GET /user/settings/applications/oauth2` returned `200` against `appscode` on 2026-07-14. + +### POST /user/settings/applications/oauth2 + +Create an OAuth2 application. + +- **Auth:** Token. + +**Request body:** `OAuth2ApplicationParams`. + +```json +{ + "name": "my-app", + "redirectUri": "https://app.example.com/callback" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | yes | Application name. | +| `redirectUri` | string | yes | Redirect URI. | +| `logo` | file | no | Logo file (multipart, on update). | + +**Response:** `200 OK` — the created `OAuth2Application`, including the plaintext +`clientSecret` (**shown only on this response**). + +### GET /user/settings/applications/oauth2/{id} + +Get a single OAuth2 application. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | Application ID. | + +**Response:** `200 OK` — an `OAuth2Application`; `404` if not found. + +### PUT /user/settings/applications/oauth2/{id} + +Update an OAuth2 application. + +- **Auth:** Token. +- **Content type:** `multipart/form-data` (`OAuth2ApplicationParams`, which may + include a `logo` file). + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | Application ID. | + +**Response:** `200 OK` — the updated `OAuth2Application`. + +### DELETE /user/settings/applications/oauth2/{id} + +Delete an OAuth2 application. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | Application ID. | + +**Response:** `200 OK` with no body; `404` if not found. + +### POST /user/settings/applications/oauth2/{id}/regenerate_secret + +Regenerate an OAuth2 application's client secret. + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | Application ID. | + +**Response:** `200 OK` — the new client-secret string. + +### POST /user/settings/applications/oauth2/{id}/revoke + +Revoke an OAuth2 grant. Here `{id}` is the **grant** ID (not the application ID). + +- **Auth:** Token. + +**Path parameters:** + +| Name | Type | Description | +|------|------|-------------| +| `id` | integer (int64) | ID of the OAuth2 grant to revoke. | + +**Response:** `200 OK` with no body. + +### GET /user/settings/applications/oauth2/grants + +List the authenticated user's OAuth2 grants (authorizations the user has given to +applications). + +- **Auth:** Token. + +**Response:** `200 OK` — an array of `OAuth2Grant` objects. + +```json +[ + { + "id": 1, + "userId": 2, + "applicationId": 1, + "applicationName": "my-app", + "counter": 4, + "createdAt": 1768329833, + "updatedAt": 1768329833 + } +] +``` + +| Field | Type | Description | +|-------|------|-------------| +| `id` | integer (int64) | Grant ID. | +| `userId` | integer (int64) | Granting user ID. | +| `applicationId` | integer (int64) | Application ID. | +| `applicationName` | string | Application name. | +| `logo` | string | Application logo URL. | +| `counter` | integer (int64) | Usage counter. | +| `createdAt` / `updatedAt` | integer (int64) | Unix timestamps. | + +> **Verified:** `GET /user/settings/applications/oauth2/grants` returned `200` against `appscode` on 2026-07-14.