diff --git a/docs/admin/templates/extending-templates/dynamic-parameters.md b/docs/admin/templates/extending-templates/dynamic-parameters.md new file mode 100644 index 0000000000..d676c3bcf3 --- /dev/null +++ b/docs/admin/templates/extending-templates/dynamic-parameters.md @@ -0,0 +1,833 @@ +# Dynamic Parameters + +Coder v2.24.0 introduces Dynamic Parameters to extend Coder [parameters](./parameters.md) with conditional form controls, +enriched input types, and user identity awareness. +This allows template authors to create interactive workspace creation forms with more environment customization, +and that means fewer templates to maintain. + +![Dynamic Parameters in Action](https://i.imgur.com/uR8mpRJ.gif) + +All parameters are parsed from Terraform, so your workspace creation forms live in the same location as your provisioning code. +You can use all the native Terraform functions and conditionality to create a self-service tooling catalog for every template. + +Administrators can use Dynamic Parameters to: + +- Create parameters which respond to the inputs of others. +- Only show parameters when other input criteria are met. +- Only show select parameters to target Coder roles or groups. + +You can try the Dynamic Parameter syntax and any of the code examples below in the +[Parameters Playground](https://playground.coder.app/parameters). +You should experiment with parameters in the playground before you upgrade live templates. + +## When You Should Upgrade to Dynamic Parameters + +While Dynamic parameters introduce a variety of new powerful tools, all functionality is backwards compatible with +existing coder templates. +When you opt-in to the new experience, no functional changes will be applied to your production parameters. + +Some reasons Coder template admins should try Dynamic Parameters: + +- You maintain or support many templates for teams with unique expectations or use cases. +- You want to selectively expose privileged workspace options to admins, power users, or personas. +- You want to make the workspace creation flow more ergonomic for developers. + +Dynamic Parameters help you reduce template duplication by setting the conditions for which users should see specific parameters. +They reduce the potential complexity of user-facing configuration by allowing administrators to organize a long list of options into interactive, branching paths for workspace customization. +They allow you to set resource guardrails by referencing Coder identity in the `coder_workspace_owner` data source. + +## How to enable Dynamic Parameters + +In Coder v2.24.0, you can opt-in to Dynamic Parameters on a per-template basis. + +1. Go to your template's settings and enable the **Enable dynamic parameters for workspace creation** option. + + ![Enable dynamic parameters for workspace creation](../../../images/admin/templates/extend-templates/dyn-params/enable-dynamic-parameters.png) + +1. Update your template to use version >=2.4.0 of the Coder provider with the following Terraform block. + + ```terraform + terraform { + required_providers { + coder = { + source = "coder/coder" + version = ">=2.4.0" + } + } + } + ``` + +1. This enables Dynamic Parameters in the template. + Add some [conditional parameters](#available-form-input-types). + + Note that these new features must be declared in your Terraform to start leveraging Dynamic Parameters. + +1. Save and publish the template. + +1. Users should see the updated workspace creation form. + +Dynamic Parameters features are backwards compatible, so all existing templates may be upgraded in-place. +If you decide to revert to the legacy flow later, disable Dynamic Parameters in the template's settings. + +## Features and Capabilities + +Dynamic Parameters introduces three primary enhancements to the standard parameter system: + +- **Conditional Parameters** + + - Parameters can respond to changes in other parameters + - Show or hide parameters based on other selections + - Modify validation rules conditionally + - Create branching paths in workspace creation forms + +- **Reference User Properties** + + - Read user data at build time from [`coder_workspace_owner`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace_owner) + - Conditionally hide parameters based on user's role + - Change parameter options based on user groups + - Reference user name, groups, and roles in parameter text + +- **Additional Form Inputs** + + - Searchable dropdown lists for easier selection + - Multi-select options for choosing multiple items + - Secret text inputs for sensitive information + - Slider input for disk size, model temperature + - Disabled parameters to display immutable data + +> [!IMPORTANT] +> Dynamic Parameters does not support external data fetching via HTTP endpoints at workspace build time. +> +> External fetching would introduce unpredictability in workspace builds after publishing a template. +> Instead, we recommend that template administrators pull in any required data for a workspace build as a +> [locals](https://developer.hashicorp.com/terraform/tutorials/configuration-language/locals) or JSON file, +> then reference that data in Terraform. +> +> If you have a use case for external data fetching, please file an issue or create a discussion in the +> [Coder GitHub repository](https://github.com/coder/coder). + +## Available Form Input Types + +Dynamic Parameters supports a variety of form types to create rich, interactive user experiences. + +![Old vs New Parameters](../../../images/admin/templates/extend-templates/dyn-params/dynamic-params-compare.png) + +Different parameter types support different form types. +You can specify the form type using the +[`form_type`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/parameter#form_type-1) attribute. + +The **Options** column in the table below indicates whether the form type supports options (**Yes**) or doesn't support them (**No**). +When supported, you can specify options using one or more `option` blocks in your parameter definition, +where each option has a `name` (displayed to the user) and a `value` (used in your template logic). + +| Form Type | Parameter Types | Options | Notes | +|----------------|--------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------| +| `radio` | `string`, `number`, `bool`, `list(string)` | Yes | Radio buttons for selecting a single option with all choices visible at once.
The classic parameter option. | +| `dropdown` | `string`, `number` | Yes | Choose a single option from a searchable dropdown list.
Default for `string` or `number` parameters with options. | +| `multi-select` | `list(string)` | Yes | Select multiple items from a list with checkboxes. | +| `tag-select` | `list(string)` | No | Default for `list(string)` parameters without options. | +| `input` | `string`, `number` | No | Standard single-line text input field.
Default for `string/number` parameters without options. | +| `textarea` | `string` | No | Multi-line text input field for longer content. | +| `slider` | `number` | No | Slider selection with min/max validation for numeric values. | +| `checkbox` | `bool` | No | A single checkbox for boolean parameters.
Default for boolean parameters. | + +### Available Styling Options + +The `coder_parameter` resource supports an additional `styling` attribute for special cosmetic changes that can be used +to further customize the workspace creation form. + +This can be used for: + +- Masking private inputs +- Marking inputs as read-only +- Setting placeholder text + +Note that the `styling` attribute should not be used as a governance tool, since it only changes how the interactive +form is displayed. +Users can avoid restrictions like `disabled` if they create a workspace via the CLI. + +This attribute accepts JSON like so: + +```terraform +data "coder_parameter" "styled_parameter" { + ... + styling = jsonencode({ + disabled = true + }) +} +``` + +Not all styling attributes are supported by all form types, use the reference below for syntax: + +| Styling Option | Compatible parameter types | Compatible form types | Notes | +|----------------|----------------------------|-----------------------|-------------------------------------------------------------------------------------| +| `disabled` | All parameter types | All form types | Disables the form control when `true`. | +| `placeholder` | `string` | `input`, `textarea` | Sets placeholder text.
This is overwritten by user entry. | +| `mask_input` | `string`, `number` | `input`, `textarea` | Masks inputs as asterisks (`*`). Used to cosmetically hide token or password entry. | + +## Use Case Examples + +### New Form Types + +The following examples show some basic usage of the +[`form_type`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/parameter#form_type-1) +attribute [explained above](#available-form-input-types). +These are used to change the input style of form controls in the create workspace form. + +
+ +### Dropdowns + +Single-select parameters with options can use the `form_type="dropdown"` attribute for better organization. + +[Try dropdown lists on the Parameter Playground](https://playground.coder.app/parameters/kgNBpjnz7x) + +```terraform +locals { + ides = [ + "VS Code", + "JetBrains IntelliJ", + "PyCharm", + "GoLand", + "WebStorm", + "Vim", + "Emacs", + "Neovim" + ] +} + +data "coder_parameter" "ides_dropdown" { + name = "ides_dropdown" + display_name = "Select your IDEs" + type = "string" + + form_type = "dropdown" + + dynamic "option" { + for_each = local.ides + content { + name = option.value + value = option.value + } + } +} +``` + +### Text Area + +The large text entry option can be used to enter long strings like AI prompts, scripts, or natural language. + +[Try textarea parameters on the Parameter Playground](https://playground.coder.app/parameters/RCAHA1Oi1_) + +```terraform + +data "coder_parameter" "text_area" { + name = "text_area" + description = "Enter multi-line text." + mutable = true + display_name = "Textarea" + + form_type = "textarea" + type = "string" + + default = <<-EOT + This is an example of multi-line text entry. + + The 'textarea' form_type is useful for + - AI prompts + - Scripts + - Read-only info (try the 'disabled' styling option) + EOT +} + +``` + +### Multi-select + +Multi-select parameters allow users to select one or many options from a single list of options. +For example, adding multiple IDEs with a single parameter. + +[Try multi-select parameters on the Parameter Playground](https://playground.coder.app/parameters/XogX54JV_f) + +```terraform +locals { + ides = [ + "VS Code", "JetBrains IntelliJ", + "GoLand", "WebStorm", + "Vim", "Emacs", + "Neovim", "PyCharm", + "Databricks", "Jupyter Notebook", + ] +} + +data "coder_parameter" "ide_selector" { + name = "ide_selector" + description = "Choose any IDEs for your workspace." + mutable = true + display_name = "Select multiple IDEs" + + + # Allows users to select multiple IDEs from the list. + form_type = "multi-select" + type = "list(string)" + + + dynamic "option" { + for_each = local.ides + content { + name = option.value + value = option.value + } + } +} +``` + +### Radio + +Radio buttons are used to select a single option with high visibility. +This is the original styling for list parameters. + +[Try radio parameters on the Parameter Playground](https://playground.coder.app/parameters/3OMDp5ANZI). + +```terraform +data "coder_parameter" "environment" { + name = "environment" + display_name = "Environment" + description = "An example of environment listing with the radio form type." + type = "string" + default = "dev" + + form_type = "radio" + + option { + name = "Development" + value = "dev" + } + option { + name = "Experimental" + value = "exp" + } + option { + name = "Staging" + value = "staging" + } + option { + name = "Production" + value = "prod" + } +} +``` + +### Checkboxes + +A single checkbox for boolean values. +This can be used for a TOS confirmation or to expose advanced options. + +[Try checkbox parameters on the Parameters Playground](https://playground.coder.app/parameters/ycWuQJk2Py). + +```terraform +data "coder_parameter" "enable_gpu" { + name = "enable_gpu" + display_name = "Enable GPU" + type = "bool" + form_type = "checkbox" # This is the default for boolean parameters + default = false +} +``` + +### Slider + +Sliders can be used for configuration on a linear scale, like resource allocation. +The `validation` block is used to constrain (or clamp) the minimum and maximum values for the parameter. + +[Try slider parameters on the Parameters Playground](https://playground.coder.app/parameters/RsBNcWVvfm). + +```terraform +data "coder_parameter" "cpu_cores" { + name = "cpu_cores" + display_name = "CPU Cores" + type = "number" + form_type = "slider" + default = 2 + validation { + min = 1 + max = 8 + } +} +``` + +### Masked Input + +Masked input parameters can be used to visually hide secret values in the workspace creation form. +Note that this does not secure information on the backend and is purely cosmetic. + +[Try private parameters on the Parameters Playground](https://playground.coder.app/parameters/wmiP7FM3Za). + +Note: This text may not be properly hidden in the Playground. +The `mask_input` styling attribute is supported in v2.24.0 and later. + +```terraform +data "coder_parameter" "private_api_key" { + name = "private_api_key" + display_name = "Your super secret API key" + type = "string" + + form_type = "input" # | "textarea" + + # Will render as "**********" + default = "privatekey" + + styling = jsonencode({ + mask_input = true + }) +} +``` + +
+ +### Conditional Parameters + +Using native Terraform syntax and parameter attributes like `count`, we can allow some parameters to react to user inputs. + +This means: + +- Hiding parameters unless activated +- Conditionally setting default values +- Changing available options based on other parameter inputs + +Use these in conjunction to build intuitive, reactive forms for workspace creation. + +
+ +### Hide/Show Options + +Use Terraform conditionals and the `count` block to allow a checkbox to expose or hide a subsequent parameter. + +[Try conditional parameters on the Parameter Playground](https://playground.coder.app/parameters/xmG5MKEGNM). + +```terraform +data "coder_parameter" "show_cpu_cores" { + name = "show_cpu_cores" + display_name = "Toggles next parameter" + description = "Select this checkbox to show the CPU cores parameter." + type = "bool" + form_type = "checkbox" + default = false + order = 1 +} + +data "coder_parameter" "cpu_cores" { + # Only show this parameter if the previous box is selected. + count = data.coder_parameter.show_cpu_cores.value ? 1 : 0 + + name = "cpu_cores" + display_name = "CPU Cores" + type = "number" + form_type = "slider" + default = 2 + order = 2 + validation { + min = 1 + max = 8 + } +} +``` + +### Dynamic Defaults + +Influence which option is selected by default for one parameter based on the selection of another. +This allows you to suggest an option dynamically without strict enforcement. + +[Try dynamic defaults in the Parameter Playground](https://playground.coder.app/parameters/DEi-Bi6DVe). + +```terraform +locals { + ides = [ + "VS Code", + "IntelliJ", "GoLand", + "WebStorm", "PyCharm", + "Databricks", "Jupyter Notebook", + ] + mlkit_ides = jsonencode(["Databricks", "PyCharm"]) + core_ides = jsonencode(["VS Code", "GoLand"]) +} + +data "coder_parameter" "git_repo" { + name = "git_repo" + display_name = "Git repo" + description = "Select a git repo to work on." + order = 1 + mutable = true + type = "string" + form_type = "dropdown" + + option { + # A Go-heavy repository + name = "coder/coder" + value = "coder/coder" + } + + option { + # A python-heavy repository + name = "coder/mlkit" + value = "coder/mlkit" + } +} + +data "coder_parameter" "ide_selector" { + # Conditionally expose this parameter + count = try(data.coder_parameter.git_repo.value, "") != "" ? 1 : 0 + + name = "ide_selector" + description = "Choose any IDEs for your workspace." + order = 2 + mutable = true + + display_name = "Select IDEs" + form_type = "multi-select" + type = "list(string)" + default = try(data.coder_parameter.git_repo.value, "") == "coder/mlkit" ? local.mlkit_ides : local.core_ides + + + dynamic "option" { + for_each = local.ides + content { + name = option.value + value = option.value + } + } +} +``` + +## Dynamic Validation + +A parameter's validation block can leverage inputs from other parameters. + +[Try dynamic validation in the Parameter Playground](https://playground.coder.app/parameters/sdbzXxagJ4). + +```terraform +data "coder_parameter" "git_repo" { + name = "git_repo" + display_name = "Git repo" + description = "Select a git repo to work on." + order = 1 + mutable = true + type = "string" + form_type = "dropdown" + + option { + # A Go-heavy repository + name = "coder/coder" + value = "coder/coder" + } + + option { + # A python-heavy repository + name = "coder/mlkit" + value = "coder/mlkit" + } +} + +data "coder_parameter" "cpu_cores" { + # Only show this parameter if the previous box is selected. + count = data.coder_parameter.show_cpu_cores.value ? 1 : 0 + + name = "cpu_cores" + display_name = "CPU Cores" + type = "number" + form_type = "slider" + order = 2 + + # Dynamically set default + default = try(data.coder_parameter.git_repo.value, "") == "coder/mlkit" ? 12 : 6 + + validation { + min = 1 + + # Dynamically set max validation + max = try(data.coder_parameter.git_repo.value, "") == "coder/mlkit" ? 16 : 8 + } +} +``` + + + +
+ +## Identity-Aware Parameters (Premium) + +Premium users can leverage our roles and groups to conditionally expose or change parameters based on user identity. +This is helpful for establishing governance policy directly in the workspace creation form, +rather than creating multiple templates to manage RBAC. + +User identity is referenced in Terraform by reading the +[`coder_workspace_owner`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace_owner) data source. + +
+ +### Role-aware Options + +Template administrators often want to expose certain experimental or unstable options only to those with elevated roles. +You can now do this by setting `count` based on a user's group or role, referencing the +[`coder_workspace_owner`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace_owner) +data source. + +[Try out admin-only options in the Playground](https://playground.coder.app/parameters/5Gn9W3hYs7). + +```terraform + +locals { + roles = [for r in data.coder_workspace_owner.me.rbac_roles: r.name] + is_admin = contains(data.coder_workspace_owner.me.groups, "admin") + has_admin_role = contains(local.roles, "owner") +} + +data "coder_workspace_owner" "me" {} + +data "coder_parameter" "advanced_settings" { + # This parameter is only visible when the user is an administrator + count = local.is_admin ? 1 : 0 + + name = "advanced_settings" + display_name = "Add an arbitrary script" + description = "An advanced configuration option only available to admins." + type = "string" + form_type = "textarea" + mutable = true + order = 5 + + styling = jsonencode({ + placeholder = <<-EOT + #!/usr/bin/env bash + while true; do + echo "hello world" + sleep 1 + done + EOT + }) +} + +``` + +### Group-aware Regions + +You can expose regions depending on which group a user belongs to. +This way developers can't accidentally induce low-latency with world-spanning connections. + +[Try user-aware regions in the parameter playground](https://playground.coder.app/parameters/tBD-mbZRGm) + +```terraform + +locals { + eu_regions = [ + "eu-west-1 (Ireland)", + "eu-central-1 (Frankfurt)", + "eu-north-1 (Stockholm)", + "eu-west-3 (Paris)", + "eu-south-1 (Milan)" + ] + + us_regions = [ + "us-east-1 (N. Virginia)", + "us-west-1 (California)", + "us-west-2 (Oregon)", + "us-east-2 (Ohio)", + "us-central-1 (Iowa)" + ] + + eu_group_name = "eu-helsinki" + is_eu_dev = contains(data.coder_workspace_owner.me.groups, local.eu_group_name) + region_desc_tag = local.is_eu_dev ? "european" : "american" +} + +data "coder_parameter" "region" { + name = "region" + display_name = "Select a Region" + description = "Select from ${local.region_desc_tag} region options." + type = "string" + form_type = "dropdown" + order = 5 + default = local.is_eu_dev ? local.eu_regions[0] : local.us_regions[0] + + dynamic "option" { + for_each = local.is_eu_dev ? local.eu_regions : local.us_regions + content { + name = option.value + value = option.value + description = "Use ${option.value}" + } + } +} +``` + +### Groups As Namespaces + +A slightly unorthodox way to leverage this is by filling the selections of a parameter from the user's groups. +Some users associate groups with namespaces, such as Kubernetes, then allow users to target that namespace with a parameter. + +[Try groups as options in the Parameter Playground](https://playground.coder.app/parameters/lKbU53nYjl). + +```terraform +locals { + groups = data.coder_workspace_owner.me.groups +} + +data "coder_workspace_owner" "me" {} + +data "coder_parameter" "your_groups" { + type = "string" + name = "your_groups" + display_name = "Your Coder Groups" + description = "Select your namespace..." + default = "target-${local.groups[0]}" + mutable = true + form_type = "dropdown" + + dynamic "option" { + # options populated directly from groups + for_each = local.groups + content { + name = option.value + # Native terraform be used to decorate output + value = "target-${option.value}" + } + } +} +``` + +
+ +## Troubleshooting + +Dynamic Parameters is still in Beta as we continue to polish and improve the workflow. +If you have any issues during upgrade, please file an issue in our +[GitHub repository](https://github.com/coder/coder/issues/new?labels=parameters) and include a +[Playground link](https://playground.coder.app/parameters) where applicable. +We appreciate the feedback and look forward to what the community creates with this system! + +You can also [search or track the list of known issues](https://github.com/coder/coder/issues?q=is%3Aissue%20state%3Aopen%20label%3Aparameters). + +You can share anything you build with Dynamic Parameters in our [Discord](https://coder.com/chat). + +### Enabled Dynamic Parameters, but my template looks the same + +Ensure that the following version requirements are met: + +- `coder/coder`: >= [v2.24.0](https://github.com/coder/coder/releases/tag/v2.24.0) +- `coder/terraform-provider-coder`: >= [v2.5.3](https://github.com/coder/terraform-provider-coder/releases/tag/v2.5.3) + +Enabling Dynamic Parameters on an existing template requires administrators to publish a new template version. +This will resolve the necessary template metadata to render the form. + +### Reverting to classic parameters + +To revert Dynamic Parameters on a template: + +1. Prepare your template by removing any conditional logic or user data references in parameters. +1. As a template administrator or owner, go to your template's settings: + + **Templates** > **Your template** > **Settings** + +1. Uncheck the **Enable dynamic parameters for workspace creation** option. +1. Create a new template version and publish to the active version. + +### Template variables not showing up + +In beta, template variables are not supported in Dynamic Parameters. + +This issue will be resolved by the next minor release of `coder/coder`. +If this is issue is blocking your usage of Dynamic Parameters, please let us know in [this thread](https://github.com/coder/coder/issues/18671). + +### Can I use registry modules with Dynamic Parameters? + +Yes, registry modules are supported with Dynamic Parameters. + +Unless explicitly mentioned, no registry modules require Dynamic Parameters. +Later in 2025, more registry modules will be converted to Dynamic Parameters to improve their UX. + +In the meantime, you can safely convert existing templates and build new parameters on top of the functionality provided in the registry. diff --git a/docs/admin/templates/extending-templates/parameters.md b/docs/admin/templates/extending-templates/parameters.md index 6977d4d3b4..d29cf8c29c 100644 --- a/docs/admin/templates/extending-templates/parameters.md +++ b/docs/admin/templates/extending-templates/parameters.md @@ -394,544 +394,10 @@ parameters in one of two ways: ## Dynamic Parameters (beta) -Dynamic Parameters enhances Coder's existing parameter system with real-time validation, -conditional parameter behavior, and richer input types. -This feature allows template authors to create more interactive and responsive workspace creation experiences. +Coder v2.24.0 introduces [Dynamic Parameters](./dynamic-parameters.md) to extend the existing parameter system with +conditional form controls, enriched input types, and user identity awareness. +This feature allows template authors to create interactive workspace creation forms, meaning more environment +customization and fewer templates to maintain. -### Enable Dynamic Parameters - -To use Dynamic Parameters, enable the experiment flag or set the environment variable. - -Note that as of v2.22.0, Dynamic parameters are an unsafe experiment and will not be enabled with the experiment wildcard. - -
- -#### Flag - -```shell -coder server --experiments=dynamic-parameters -``` - -#### Env Variable - -```shell -CODER_EXPERIMENTS=dynamic-parameters -``` - -
- -Dynamic Parameters also require version >=2.4.0 of the Coder provider. - -Enable the experiment, then include the following at the top of your template: - -```terraform -terraform { - required_providers { - coder = { - source = "coder/coder" - version = ">=2.4.0" - } - } -} -``` - -Once enabled, users can toggle between the experimental and classic interfaces during -workspace creation using an escape hatch in the workspace creation form. - -## Features and Capabilities - -Dynamic Parameters introduces three primary enhancements to the standard parameter system: - -- **Conditional Parameters** - - - Parameters can respond to changes in other parameters - - Show or hide parameters based on other selections - - Modify validation rules conditionally - - Create branching paths in workspace creation forms - -- **Reference User Properties** - - - Read user data at build time from [`coder_workspace_owner`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace_owner) - - Conditionally hide parameters based on user's role - - Change parameter options based on user groups - - Reference user name in parameters - -- **Additional Form Inputs** - - - Searchable dropdown lists for easier selection - - Multi-select options for choosing multiple items - - Secret text inputs for sensitive information - - Key-value pair inputs for complex data - - Button parameters for toggling sections - -## Available Form Input Types - -Dynamic Parameters supports a variety of form types to create rich, interactive user experiences. - -You can specify the form type using the `form_type` property. -Different parameter types support different form types. - -The "Options" column in the table below indicates whether the form type requires options to be defined (Yes) or doesn't support/require them (No). When required, options are specified using one or more `option` blocks in your parameter definition, where each option has a `name` (displayed to the user) and a `value` (used in your template logic). - -| Form Type | Parameter Types | Options | Notes | -|----------------|--------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------| -| `checkbox` | `bool` | No | A single checkbox for boolean parameters. Default for boolean parameters. | -| `dropdown` | `string`, `number` | Yes | Searchable dropdown list for choosing a single option from a list. Default for `string` or `number` parameters with options. | -| `input` | `string`, `number` | No | Standard single-line text input field. Default for string/number parameters without options. | -| `multi-select` | `list(string)` | Yes | Select multiple items from a list with checkboxes. | -| `radio` | `string`, `number`, `bool`, `list(string)` | Yes | Radio buttons for selecting a single option with all choices visible at once. | -| `slider` | `number` | No | Slider selection with min/max validation for numeric values. | -| `switch` | `bool` | No | Toggle switch alternative for boolean parameters. | -| `tag-select` | `list(string)` | No | Default for list(string) parameters without options. | -| `textarea` | `string` | No | Multi-line text input field for longer content. | -| `error` | | No | Used to display an error message when a parameter form_type is unknown | - -### Form Type Examples - -
checkbox: A single checkbox for boolean values - -```tf -data "coder_parameter" "enable_gpu" { - name = "enable_gpu" - display_name = "Enable GPU" - type = "bool" - form_type = "checkbox" # This is the default for boolean parameters - default = false -} -``` - -
- -
dropdown: A searchable select menu for choosing a single option from a list - -```tf -data "coder_parameter" "region" { - name = "region" - display_name = "Region" - description = "Select a region" - type = "string" - form_type = "dropdown" # This is the default for string parameters with options - - option { - name = "US East" - value = "us-east-1" - } - option { - name = "US West" - value = "us-west-2" - } -} -``` - -
- -
input: A standard text input field - -```tf -data "coder_parameter" "custom_domain" { - name = "custom_domain" - display_name = "Custom Domain" - type = "string" - form_type = "input" # This is the default for string parameters without options - default = "" -} -``` - -
- -
key-value: Input for entering key-value pairs - -```tf -data "coder_parameter" "environment_vars" { - name = "environment_vars" - display_name = "Environment Variables" - type = "string" - form_type = "key-value" - default = jsonencode({"NODE_ENV": "development"}) -} -``` - -
- -
multi-select: Checkboxes for selecting multiple options from a list - -```tf -data "coder_parameter" "tools" { - name = "tools" - display_name = "Developer Tools" - type = "list(string)" - form_type = "multi-select" - default = jsonencode(["git", "docker"]) - - option { - name = "Git" - value = "git" - } - option { - name = "Docker" - value = "docker" - } - option { - name = "Kubernetes CLI" - value = "kubectl" - } -} -``` - -
- -
password: A text input that masks sensitive information - -```tf -data "coder_parameter" "api_key" { - name = "api_key" - display_name = "API Key" - type = "string" - form_type = "password" - secret = true -} -``` - -
- -
radio: Radio buttons for selecting a single option with high visibility - -```tf -data "coder_parameter" "environment" { - name = "environment" - display_name = "Environment" - type = "string" - form_type = "radio" - default = "dev" - - option { - name = "Development" - value = "dev" - } - option { - name = "Staging" - value = "staging" - } -} -``` - -
- -
slider: A slider for selecting numeric values within a range - -```tf -data "coder_parameter" "cpu_cores" { - name = "cpu_cores" - display_name = "CPU Cores" - type = "number" - form_type = "slider" - default = 2 - validation { - min = 1 - max = 8 - } -} -``` - -
- -
switch: A toggle switch for boolean values - -```tf -data "coder_parameter" "advanced_mode" { - name = "advanced_mode" - display_name = "Advanced Mode" - type = "bool" - form_type = "switch" - default = false -} -``` - -
- -
textarea: A multi-line text input field for longer content - -```tf -data "coder_parameter" "init_script" { - name = "init_script" - display_name = "Initialization Script" - type = "string" - form_type = "textarea" - default = "#!/bin/bash\necho 'Hello World'" -} -``` - -
- -## Dynamic Parameter Use Case Examples - -
Conditional Parameters: Region and Instance Types - -This example shows instance types based on the selected region: - -```tf -data "coder_parameter" "region" { - name = "region" - display_name = "Region" - description = "Select a region for your workspace" - type = "string" - default = "us-east-1" - - option { - name = "US East (N. Virginia)" - value = "us-east-1" - } - - option { - name = "US West (Oregon)" - value = "us-west-2" - } -} - -data "coder_parameter" "instance_type" { - name = "instance_type" - display_name = "Instance Type" - description = "Select an instance type available in the selected region" - type = "string" - - # This option will only appear when us-east-1 is selected - dynamic "option" { - for_each = data.coder_parameter.region.value == "us-east-1" ? [1] : [] - content { - name = "t3.large (US East)" - value = "t3.large" - } - } - - # This option will only appear when us-west-2 is selected - dynamic "option" { - for_each = data.coder_parameter.region.value == "us-west-2" ? [1] : [] - content { - name = "t3.medium (US West)" - value = "t3.medium" - } - } -} -``` - -
- -
Advanced Options Toggle - -This example shows how to create an advanced options section: - -```tf -data "coder_parameter" "show_advanced" { - name = "show_advanced" - display_name = "Show Advanced Options" - description = "Enable to show advanced configuration options" - type = "bool" - default = false - order = 0 -} - -data "coder_parameter" "advanced_setting" { - # This parameter is only visible when show_advanced is true - count = data.coder_parameter.show_advanced.value ? 1 : 0 - name = "advanced_setting" - display_name = "Advanced Setting" - description = "An advanced configuration option" - type = "string" - default = "default_value" - mutable = true - order = 1 -} - -
- -
Multi-select IDE Options - -This example allows selecting multiple IDEs to install: - -```tf -data "coder_parameter" "ides" { - name = "ides" - display_name = "IDEs to Install" - description = "Select which IDEs to install in your workspace" - type = "list(string)" - default = jsonencode(["vscode"]) - mutable = true - form_type = "multi-select" - - option { - name = "VS Code" - value = "vscode" - icon = "/icon/vscode.png" - } - - option { - name = "JetBrains IntelliJ" - value = "intellij" - icon = "/icon/intellij.png" - } - - option { - name = "JupyterLab" - value = "jupyter" - icon = "/icon/jupyter.png" - } -} -``` - -
- -
Team-specific Resources - -This example filters resources based on user group membership: - -```tf -data "coder_parameter" "instance_type" { - name = "instance_type" - display_name = "Instance Type" - description = "Select an instance type for your workspace" - type = "string" - - # Show GPU options only if user belongs to the "data-science" group - dynamic "option" { - for_each = contains(data.coder_workspace_owner.me.groups, "data-science") ? [1] : [] - content { - name = "p3.2xlarge (GPU)" - value = "p3.2xlarge" - } - } - - # Standard options for all users - option { - name = "t3.medium (Standard)" - value = "t3.medium" - } -} -``` - -### Advanced Usage Patterns - -
Creating Branching Paths - -For templates serving multiple teams or use cases, you can create comprehensive branching paths: - -```tf -data "coder_parameter" "environment_type" { - name = "environment_type" - display_name = "Environment Type" - description = "Select your preferred development environment" - type = "string" - default = "container" - - option { - name = "Container" - value = "container" - } - - option { - name = "Virtual Machine" - value = "vm" - } -} - -# Container-specific parameters -data "coder_parameter" "container_image" { - name = "container_image" - display_name = "Container Image" - description = "Select a container image for your environment" - type = "string" - default = "ubuntu:latest" - - # Only show when container environment is selected - condition { - field = data.coder_parameter.environment_type.name - value = "container" - } - - option { - name = "Ubuntu" - value = "ubuntu:latest" - } - - option { - name = "Python" - value = "python:3.9" - } -} - -# VM-specific parameters -data "coder_parameter" "vm_image" { - name = "vm_image" - display_name = "VM Image" - description = "Select a VM image for your environment" - type = "string" - default = "ubuntu-20.04" - - # Only show when VM environment is selected - condition { - field = data.coder_parameter.environment_type.name - value = "vm" - } - - option { - name = "Ubuntu 20.04" - value = "ubuntu-20.04" - } - - option { - name = "Debian 11" - value = "debian-11" - } -} -``` - -
- -
Conditional Validation - -Adjust validation rules dynamically based on parameter values: - -```tf -data "coder_parameter" "team" { - name = "team" - display_name = "Team" - type = "string" - default = "engineering" - - option { - name = "Engineering" - value = "engineering" - } - - option { - name = "Data Science" - value = "data-science" - } -} - -data "coder_parameter" "cpu_count" { - name = "cpu_count" - display_name = "CPU Count" - type = "number" - default = 2 - - # Engineering team has lower limits - dynamic "validation" { - for_each = data.coder_parameter.team.value == "engineering" ? [1] : [] - content { - min = 1 - max = 4 - } - } - - # Data Science team has higher limits - dynamic "validation" { - for_each = data.coder_parameter.team.value == "data-science" ? [1] : [] - content { - min = 2 - max = 8 - } - } -} -``` - -
+You can read more in the [Dynamic Parameters documentation](./dynamic-parameters.md) and try it out in the +[Parameters Playground](https://playground.coder.app/parameters). diff --git a/docs/images/admin/templates/extend-templates/dyn-params/dynamic-params-compare.png b/docs/images/admin/templates/extend-templates/dyn-params/dynamic-params-compare.png new file mode 100644 index 0000000000..31f02506bf Binary files /dev/null and b/docs/images/admin/templates/extend-templates/dyn-params/dynamic-params-compare.png differ diff --git a/docs/images/admin/templates/extend-templates/dyn-params/enable-dynamic-parameters.png b/docs/images/admin/templates/extend-templates/dyn-params/enable-dynamic-parameters.png new file mode 100644 index 0000000000..13732661e7 Binary files /dev/null and b/docs/images/admin/templates/extend-templates/dyn-params/enable-dynamic-parameters.png differ diff --git a/docs/manifest.json b/docs/manifest.json index 9b85e634dc..65555caa0d 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -527,6 +527,12 @@ "description": "Use parameters to customize workspaces at build", "path": "./admin/templates/extending-templates/parameters.md" }, + { + "title": "Dynamic Parameters", + "description": "Conditional, identity-aware parameter syntax for advanced users.", + "path": "./admin/templates/extending-templates/dynamic-parameters.md", + "state": ["beta"] + }, { "title": "Prebuilt workspaces", "description": "Pre-provision a ready-to-deploy workspace with a defined set of parameters",