feat(coderd): add support for external agents to API's and provisioner (#19286)

This pull request introduces support for external workspace management, allowing users to register and manage workspaces that are provisioned and managed outside of the Coder.

Depends on: https://github.com/coder/terraform-provider-coder/pull/424

* GET /api/v2/init-script - Gets the agent initialization script
  * By default, it returns a script for Linux (amd64), but with query parameters (os and arch) you can get the init script for different platforms
* GET /api/v2/workspaces/{workspace}/external-agent/{agent}/credentials - Gets credentials for an external agent **(enterprise)**
* Updated queries to filter workspaces/templates by the has_external_agent field
This commit is contained in:
Kacper Sawicki
2025-08-19 10:41:33 +02:00
committed by GitHub
parent f085c37af3
commit 9edceef0bf
53 changed files with 1616 additions and 98 deletions
+2 -14
View File
@@ -47,18 +47,6 @@
"path": "./about/contributing/documentation.md",
"icon_path": "./images/icons/document.svg"
},
{
"title": "Modules",
"description": "Learn how to contribute modules to Coder",
"path": "./about/contributing/modules.md",
"icon_path": "./images/icons/gear.svg"
},
{
"title": "Templates",
"description": "Learn how to contribute templates to Coder",
"path": "./about/contributing/templates.md",
"icon_path": "./images/icons/picture.svg"
},
{
"title": "Backend",
"description": "Our guide for backend development",
@@ -714,8 +702,8 @@
"path": "./admin/integrations/platformx.md"
},
{
"title": "DX",
"description": "Tag Coder Users with DX",
"title": "DX Data Cloud",
"description": "Tag Coder Users with DX Data Cloud",
"path": "./admin/integrations/dx-data-cloud.md"
},
{
+6
View File
@@ -33,6 +33,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
@@ -271,6 +272,7 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild} \
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
@@ -998,6 +1000,7 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/sta
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
@@ -1309,6 +1312,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
@@ -1528,6 +1532,7 @@ Status Code **200**
| `» daily_cost` | integer | false | | |
| `» deadline` | string(date-time) | false | | |
| `» has_ai_task` | boolean | false | | |
| `» has_external_agent` | boolean | false | | |
| `» id` | string(uuid) | false | | |
| `» initiator_id` | string(uuid) | false | | |
| `» initiator_name` | string | false | | |
@@ -1802,6 +1807,7 @@ curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
+39
View File
@@ -4254,3 +4254,42 @@ curl -X PATCH http://coder-server:8080/api/v2/workspaceproxies/{workspaceproxy}
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.WorkspaceProxy](schemas.md#codersdkworkspaceproxy) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Get workspace external agent credentials
### Code samples
```shell
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/external-agent/{agent}/credentials \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`GET /workspaces/{workspace}/external-agent/{agent}/credentials`
### Parameters
| Name | In | Type | Required | Description |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true | Workspace ID |
| `agent` | path | string | true | Agent name |
### Example responses
> 200 Response
```json
{
"agent_token": "string",
"command": "string"
}
```
### Responses
| Status | Meaning | Description | Schema |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.ExternalAgentCredentials](schemas.md#codersdkexternalagentcredentials) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
+26
View File
@@ -0,0 +1,26 @@
# InitScript
## Get agent init script
### Code samples
```shell
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/init-script/{os}/{arch}
```
`GET /init-script/{os}/{arch}`
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------|----------|------------------|
| `os` | path | string | true | Operating system |
| `arch` | path | string | true | Architecture |
### Responses
| Status | Meaning | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | Success | |
+22
View File
@@ -3322,6 +3322,22 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
| `mcp-server-http` |
| `workspace-sharing` |
## codersdk.ExternalAgentCredentials
```json
{
"agent_token": "string",
"command": "string"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `agent_token` | string | false | | |
| `command` | string | false | | |
## codersdk.ExternalAuth
```json
@@ -7614,6 +7630,7 @@ Restarts will only happen on weekdays in this list on weeks which line up with W
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"username": "string"
},
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job": {
"available_workers": [
@@ -7678,6 +7695,7 @@ Restarts will only happen on weekdays in this list on weeks which line up with W
| `archived` | boolean | false | | |
| `created_at` | string | false | | |
| `created_by` | [codersdk.MinimalUser](#codersdkminimaluser) | false | | |
| `has_external_agent` | boolean | false | | |
| `id` | string | false | | |
| `job` | [codersdk.ProvisionerJob](#codersdkprovisionerjob) | false | | |
| `matched_provisioners` | [codersdk.MatchedProvisioners](#codersdkmatchedprovisioners) | false | | |
@@ -8813,6 +8831,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
@@ -9923,6 +9942,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
@@ -10132,6 +10152,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
| `daily_cost` | integer | false | | |
| `deadline` | string | false | | |
| `has_ai_task` | boolean | false | | |
| `has_external_agent` | boolean | false | | |
| `id` | string | false | | |
| `initiator_id` | string | false | | |
| `initiator_name` | string | false | | |
@@ -10671,6 +10692,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
+9
View File
@@ -462,6 +462,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"username": "string"
},
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job": {
"available_workers": [
@@ -561,6 +562,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"username": "string"
},
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job": {
"available_workers": [
@@ -684,6 +686,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templa
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"username": "string"
},
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job": {
"available_workers": [
@@ -1250,6 +1253,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions \
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"username": "string"
},
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job": {
"available_workers": [
@@ -1327,6 +1331,7 @@ Status Code **200**
| `»» avatar_url` | string(uri) | false | | |
| `»» id` | string(uuid) | true | | |
| `»» username` | string | true | | |
| `» has_external_agent` | boolean | false | | |
| `» id` | string(uuid) | false | | |
| `» job` | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) | false | | |
| `»» available_workers` | array | false | | |
@@ -1531,6 +1536,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions/{templ
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"username": "string"
},
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job": {
"available_workers": [
@@ -1608,6 +1614,7 @@ Status Code **200**
| `»» avatar_url` | string(uri) | false | | |
| `»» id` | string(uuid) | true | | |
| `»» username` | string | true | | |
| `» has_external_agent` | boolean | false | | |
| `» id` | string(uuid) | false | | |
| `» job` | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) | false | | |
| `»» available_workers` | array | false | | |
@@ -1702,6 +1709,7 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion} \
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"username": "string"
},
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job": {
"available_workers": [
@@ -1810,6 +1818,7 @@ curl -X PATCH http://coder-server:8080/api/v2/templateversions/{templateversion}
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"username": "string"
},
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job": {
"available_workers": [
+11 -5
View File
@@ -88,6 +88,7 @@ of the template will be used.
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
@@ -376,6 +377,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
@@ -689,6 +691,7 @@ of the template will be used.
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
@@ -930,11 +933,11 @@ curl -X GET http://coder-server:8080/api/v2/workspaces \
### Parameters
| Name | In | Type | Required | Description |
|----------|-------|---------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `q` | query | string | false | Search query in the format `key:value`. Available keys are: owner, template, name, status, has-agent, dormant, last_used_after, last_used_before, has-ai-task. |
| `limit` | query | integer | false | Page limit |
| `offset` | query | integer | false | Page offset |
| Name | In | Type | Required | Description |
|----------|-------|---------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `q` | query | string | false | Search query in the format `key:value`. Available keys are: owner, template, name, status, has-agent, dormant, last_used_after, last_used_before, has-ai-task, has_external_agent. |
| `limit` | query | integer | false | Page limit |
| `offset` | query | integer | false | Page offset |
### Example responses
@@ -980,6 +983,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces \
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
@@ -1252,6 +1256,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace} \
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
@@ -1699,6 +1704,7 @@ curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/dormant \
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",