mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add TemplateBuilderCreateTemplate SDK types and client method (#26360)
Adds `POST /api/v2/templatebuilder/compose/template`, a synchronous endpoint that composes a template from a base and modules, validates it via a provisioner import job, and creates the template in a single request. The handler composes terraform files, bundles them as a tar, inserts the file with hash-based dedup, creates a template version with an import job, waits up to 2 minutes for the job to complete, classifies errors for known failure modes (network-unreachable registry, DNS failures), then creates the template on success. Canceled and failed jobs return appropriate error responses. Also adds `hclwrite.Format` to composed terraform output for canonical HCL formatting. Closes https://linear.app/codercom/issue/DEVEX-279 <details> <summary>Implementation notes</summary> - SDK types and client method in `codersdk/templatebuilder.go` with validation tags matching the standard template creation path (`template_display_name`, `lt=128`) - `ClassifyProvisionerError` in `coderd/templatebuilder/errors.go` detects DNS, connection refused, i/o timeout, and TLS handshake failures and returns actionable messages - `waitForProvisionerJob` polls with a ramp-up interval schedule (100ms, 200ms, 500ms, then 1s steady) and accepts an `onUpdate` callback for future SSE streaming - Audit logging for both template and template version creation - TOCTOU name uniqueness: early check for fast feedback, DB unique constraint catch for the race window (returns 409, not 500) - Swagger annotations for all error responses (400, 404, 409, 504) </details> > 🤖 Generated by Coder Agents
This commit is contained in:
Generated
+122
@@ -83,6 +83,128 @@ curl -X POST http://coder-server:8080/api/v2/templatebuilder/compose \
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
## Compose and create a template
|
||||
|
||||
### Code samples
|
||||
|
||||
```shell
|
||||
# Example request using curl
|
||||
curl -X POST http://coder-server:8080/api/v2/templatebuilder/compose/template \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Coder-Session-Token: API_KEY'
|
||||
```
|
||||
|
||||
`POST /api/v2/templatebuilder/compose/template`
|
||||
|
||||
> Body parameter
|
||||
|
||||
```json
|
||||
{
|
||||
"base_template_id": "string",
|
||||
"description": "string",
|
||||
"display_name": "string",
|
||||
"icon": "string",
|
||||
"modules": [
|
||||
{
|
||||
"id": "string",
|
||||
"variables": {
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"name": "string",
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"provisioner_tags": {
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
| Name | In | Type | Required | Description |
|
||||
|--------|------|----------------------------------------------------------------------------------------------------------|----------|-------------------------|
|
||||
| `body` | body | [codersdk.TemplateBuilderCreateTemplateRequest](schemas.md#codersdktemplatebuildercreatetemplaterequest) | true | Create template request |
|
||||
|
||||
### Example responses
|
||||
|
||||
> 201 Response
|
||||
|
||||
```json
|
||||
{
|
||||
"template": {
|
||||
"active_user_count": 0,
|
||||
"active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc",
|
||||
"activity_bump_ms": 0,
|
||||
"allow_user_autostart": true,
|
||||
"allow_user_autostop": true,
|
||||
"allow_user_cancel_workspace_jobs": true,
|
||||
"autostart_requirement": {
|
||||
"days_of_week": [
|
||||
"monday"
|
||||
]
|
||||
},
|
||||
"autostop_requirement": {
|
||||
"days_of_week": [
|
||||
"monday"
|
||||
],
|
||||
"weeks": 0
|
||||
},
|
||||
"build_time_stats": {
|
||||
"property1": {
|
||||
"p50": 123,
|
||||
"p95": 146
|
||||
},
|
||||
"property2": {
|
||||
"p50": 123,
|
||||
"p95": 146
|
||||
}
|
||||
},
|
||||
"cors_behavior": "simple",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
"created_by_id": "9377d689-01fb-4abf-8450-3368d2c1924f",
|
||||
"created_by_name": "string",
|
||||
"default_ttl_ms": 0,
|
||||
"deleted": true,
|
||||
"deprecated": true,
|
||||
"deprecation_message": "string",
|
||||
"description": "string",
|
||||
"disable_module_cache": true,
|
||||
"display_name": "string",
|
||||
"failure_ttl_ms": 0,
|
||||
"icon": "string",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"max_port_share_level": "owner",
|
||||
"name": "string",
|
||||
"organization_display_name": "string",
|
||||
"organization_icon": "string",
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"organization_name": "string",
|
||||
"provisioner": "terraform",
|
||||
"require_active_version": true,
|
||||
"time_til_dormant_autodelete_ms": 0,
|
||||
"time_til_dormant_ms": 0,
|
||||
"updated_at": "2019-08-24T14:15:22Z",
|
||||
"use_classic_parameter_flow": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
||||
| Status | Meaning | Description | Schema |
|
||||
|--------|-----------------------------------------------------------------------|-----------------|------------------------------------------------------------------------------------------------------------|
|
||||
| 201 | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created | [codersdk.TemplateBuilderCreateTemplateResponse](schemas.md#codersdktemplatebuildercreatetemplateresponse) |
|
||||
| 400 | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1) | Bad Request | [codersdk.Response](schemas.md#codersdkresponse) |
|
||||
| 404 | [Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4) | Not Found | [codersdk.Response](schemas.md#codersdkresponse) |
|
||||
| 409 | [Conflict](https://tools.ietf.org/html/rfc7231#section-6.5.8) | Conflict | [codersdk.Response](schemas.md#codersdkresponse) |
|
||||
| 504 | [Gateway Time-out](https://tools.ietf.org/html/rfc7231#section-6.6.5) | Gateway Timeout | [codersdk.Response](schemas.md#codersdkresponse) |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
## List template builder modules
|
||||
|
||||
### Code samples
|
||||
|
||||
Reference in New Issue
Block a user