diff --git a/docs/manifest.json b/docs/manifest.json index 13b1b72cceb0f..85f5c250066ff 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -200,6 +200,11 @@ "description": "Prompt the template administrator for additional information about a template", "path": "./templates/variables.md" }, + { + "title": "Workspace Tags", + "description": "Control provisioning using Workspace Tags and Parameters", + "path": "./templates/workspace-tags.md" + }, { "title": "Administering templates", "description": "Configuration settings for template admins", diff --git a/docs/templates/workspace-tags.md b/docs/templates/workspace-tags.md new file mode 100644 index 0000000000000..ce886629abfe3 --- /dev/null +++ b/docs/templates/workspace-tags.md @@ -0,0 +1,87 @@ +# Workspace Tags + +Template administrators can leverage static template tags to limit workspace +provisioning to designated provisioner groups that have locally deployed +credentials for creating workspace resources. While this method ensures +controlled access, it offers limited flexibility and does not permit users to +select the nodes for their workspace creation. + +By using `coder_workspace_tags` and `coder_parameter`s, template administrators +can enable dynamic tag selection and modify static template tags. + +## Dynamic tag selection + +Here is a sample `coder_workspace_tags` data resource with a few workspace tags +specified: + +```hcl +data "coder_workspace_tags" "custom_workspace_tags" { + tags = { + "zone" = "developers" + "runtime" = data.coder_parameter.runtime_selector.value + "project_id" = "PROJECT_${data.coder_parameter.project_name.value}" + "cache" = data.coder_parameter.feature_cache_enabled.value == "true" ? "with-cache" : "no-cache" + } +} +``` + +**Legend** + +- `zone` - static tag value set to `developers` +- `runtime` - supported by the string-type `coder_parameter` to select + provisioner runtime, `runtime_selector` +- `project_id` - a formatted string supported by the string-type + `coder_parameter`, `project_name` +- `cache` - an HCL condition involving boolean-type `coder_parameter`, + `feature_cache_enabled` + +Review the +[full template example](https://github.com/coder/coder/tree/main/examples/workspace-tags) +using `coder_workspace_tags` and `coder_parameter`s. + +## Constraints + +### Tagged provisioners + +It is possible to choose tag combinations that no provisioner can handle. This +will cause the provisioner job to get stuck in the queue until a provisioner is +added that can handle its combination of tags. + +Before releasing the template version with configurable workspace tags, ensure +that every tag set is associated with at least one healthy provisioner. + +### Parameters types + +Provisioners require job tags to be defined in plain string format. When a +workspace tag refers to a `coder_parameter` without involving the string +formatter, for example, +(`"runtime" = data.coder_parameter.runtime_selector.value`), the Coder +provisioner server can transform only the following parameter types to strings: +_string_, _number_, and _bool_. + +### Mutability + +A mutable `coder_parameter` can be dangerous for a workspace tag as it allows +the workspace owner to change a provisioner group (due to different tags). In +most cases, `coder_parameter`s backing `coder_workspace_tags` should be marked +as immutable and set only once, during workspace creation. + +### HCL syntax + +When importing the template version with `coder_workspace_tags`, the Coder +provisioner server extracts raw partial queries for each workspace tag and +stores them in the database. During workspace build time, the Coder server uses +the [Hashicorp HCL library](https://github.com/hashicorp/hcl) to evaluate these +raw queries on-the-fly without processing the entire Terraform template. This +evaluation is simpler but also limited in terms of available functions, +variables, and references to other resources. + +**Supported syntax** + +- Static string: `foobar_tag = "foobaz"` +- Formatted string: `foobar_tag = "foobaz ${data.coder_parameter.foobaz.value}"` +- Reference to `coder_parameter`: + `foobar_tag = data.coder_parameter.foobar.value` +- Boolean logic: `production_tag = !data.coder_parameter.staging_env.value` +- Condition: + `cache = data.coder_parameter.feature_cache_enabled.value == "true" ? "with-cache" : "no-cache"` diff --git a/examples/parameters-dynamic-options/README.md b/examples/parameters-dynamic-options/README.md index 2c6c00d6acc83..b1c3f2dd3c5e0 100644 --- a/examples/parameters-dynamic-options/README.md +++ b/examples/parameters-dynamic-options/README.md @@ -35,6 +35,5 @@ Update the template and push it using the following command: ./scripts/coder-dev.sh templates push examples-parameters-dynamic-options \ -d examples/parameters-dynamic-options \ --variables-file examples/parameters-dynamic-options/variables.yml \ - --create \ -y ``` diff --git a/examples/workspace-tags/README.md b/examples/workspace-tags/README.md new file mode 100644 index 0000000000000..f3fbc86ae8fc1 --- /dev/null +++ b/examples/workspace-tags/README.md @@ -0,0 +1,26 @@ +--- +name: Sample Template with Workspace Tags +description: Review the sample template and introduce dynamic workspace tags to your template +tags: [local, docker, workspace-tags] +icon: /icon/docker.png +--- + +# Overview + +This Coder template presents use of [Workspace Tags](https://coder.com/docs/v2/latest/templates/workspace-tags) [Coder Parameters](https://coder.com/docs/v2/latest/templates/parameters). + +# Use case + +Template administrators can use static tags to control workspace provisioning, limiting it to specific provisioner groups. However, this restricts workspace users from choosing their preferred workspace nodes. + +By using `coder_workspace_tags` and `coder_parameter`s, template administrators can allow dynamic tag selection, avoiding the need to push the same template multiple times with different tags. + +## Development + +Update the template and push it using the following command: + +``` +./scripts/coder-dev.sh templates push examples-workspace-tags \ + -d examples/workspace-tags \ + -y +``` diff --git a/examples/workspace-tags/main.tf b/examples/workspace-tags/main.tf new file mode 100644 index 0000000000000..f74286741cbb0 --- /dev/null +++ b/examples/workspace-tags/main.tf @@ -0,0 +1,170 @@ +terraform { + required_providers { + coder = { + source = "coder/coder" + } + docker = { + source = "kreuzwerker/docker" + } + } +} + +locals { + username = data.coder_workspace.me.owner +} + +data "coder_provisioner" "me" { +} + +data "coder_workspace" "me" { +} + +data "coder_workspace_tags" "custom_workspace_tags" { + tags = { + "zone" = "developers" + "runtime" = data.coder_parameter.runtime_selector.value + "project_id" = "PROJECT_${data.coder_parameter.project_name.value}" + "cache" = data.coder_parameter.feature_cache_enabled.value == "true" ? "with-cache" : "no-cache" + } +} + +data "coder_parameter" "runtime_selector" { + name = "runtime_selector" + display_name = "Provisioner Runtime" + default = "development" + + option { + name = "Development (free zone)" + value = "development" + } + option { + name = "Staging (internal access)" + value = "staging" + } + option { + name = "Production (air-gapped)" + value = "production" + } + + mutable = false +} + +data "coder_parameter" "project_name" { + name = "project_name" + display_name = "Project name" + description = "Specify the project name." + + mutable = false +} + +data "coder_parameter" "feature_cache_enabled" { + name = "feature_cache_enabled" + display_name = "Enable cache?" + type = "bool" + default = false + + mutable = false +} + +resource "coder_agent" "main" { + arch = data.coder_provisioner.me.arch + os = "linux" + startup_script = <