diff --git a/docs/data-sources/external_auth.md b/docs/data-sources/external_auth.md index e4089f24..83ed9ef2 100644 --- a/docs/data-sources/external_auth.md +++ b/docs/data-sources/external_auth.md @@ -3,7 +3,7 @@ page_title: "coder_external_auth Data Source - terraform-provider-coder" subcategory: "" description: |- - Use this data source to require users to authenticate with an external service prior to workspace creation. This can be used to pre-authenticate external services https://coder.com/docs/admin/external-auth in a workspace. (e.g. Google Cloud, Github, Docker, etc.) + Use this data source to require users to authenticate with an external service prior to workspace creation. This can be used to pre-authenticate external services https://coder.com/docs/admin/external-auth in a workspace. (e.g. Google Cloud, Github, Docker, etc.) --- # coder_external_auth (Data Source) @@ -17,12 +17,12 @@ provider "coder" {} data "coder_external_auth" "github" { - id = "github" + id = "github" } data "coder_external_auth" "azure-identity" { - id = "azure-identiy" - optional = true + id = "azure-identiy" + optional = true } ``` diff --git a/docs/data-sources/parameter.md b/docs/data-sources/parameter.md index ecba3929..656f674f 100644 --- a/docs/data-sources/parameter.md +++ b/docs/data-sources/parameter.md @@ -3,7 +3,7 @@ page_title: "coder_parameter Data Source - terraform-provider-coder" subcategory: "" description: |- - Use this data source to configure editable options for workspaces. + Use this data source to configure editable options for workspaces. --- # coder_parameter (Data Source) @@ -16,119 +16,119 @@ Use this data source to configure editable options for workspaces. provider "coder" {} data "coder_parameter" "example" { - name = "Region" - description = "Specify a region to place your workspace." - mutable = false - type = "string" - default = "us-central1-a" - option { - value = "us-central1-a" - name = "US Central" - icon = "/icons/1f1fa-1f1f8.png" - } - option { - value = "asia-southeast1-a" - name = "Singapore" - icon = "/icons/1f1f8-1f1ec.png" - } + name = "Region" + description = "Specify a region to place your workspace." + mutable = false + type = "string" + default = "us-central1-a" + option { + value = "us-central1-a" + name = "US Central" + icon = "/icons/1f1fa-1f1f8.png" + } + option { + value = "asia-southeast1-a" + name = "Singapore" + icon = "/icons/1f1f8-1f1ec.png" + } } data "coder_parameter" "ami" { - name = "Machine Image" - description = <<-EOT - # Provide the machine image - See the [registry](https://container.registry.blah/namespace) for options. - EOT - option { - value = "ami-xxxxxxxx" - name = "Ubuntu" - icon = "/icon/ubuntu.svg" - } + name = "Machine Image" + description = <<-EOT + # Provide the machine image + See the [registry](https://container.registry.blah/namespace) for options. + EOT + option { + value = "ami-xxxxxxxx" + name = "Ubuntu" + icon = "/icon/ubuntu.svg" + } } data "coder_parameter" "is_public_instance" { - name = "Is public instance?" - type = "bool" - icon = "/icon/docker.svg" - default = false + name = "Is public instance?" + type = "bool" + icon = "/icon/docker.svg" + default = false } data "coder_parameter" "cores" { - name = "CPU Cores" - type = "number" - icon = "/icon/cpu.svg" - default = 3 - order = 10 + name = "CPU Cores" + type = "number" + icon = "/icon/cpu.svg" + default = 3 + order = 10 } data "coder_parameter" "disk_size" { - name = "Disk Size" - type = "number" - default = "5" - order = 8 - validation { - # This can apply to number. - min = 0 - max = 10 - monotonic = "increasing" - } + name = "Disk Size" + type = "number" + default = "5" + order = 8 + validation { + # This can apply to number. + min = 0 + max = 10 + monotonic = "increasing" + } } data "coder_parameter" "cat_lives" { - name = "Cat Lives" - type = "number" - default = "9" - validation { - # This can apply to number. - min = 0 - max = 10 - monotonic = "decreasing" - } + name = "Cat Lives" + type = "number" + default = "9" + validation { + # This can apply to number. + min = 0 + max = 10 + monotonic = "decreasing" + } } data "coder_parameter" "fairy_tale" { - name = "Fairy Tale" - type = "string" - mutable = true - default = "Hansel and Gretel" - ephemeral = true + name = "Fairy Tale" + type = "string" + mutable = true + default = "Hansel and Gretel" + ephemeral = true } data "coder_parameter" "users" { - name = "system_users" - display_name = "System users" - type = "list(string)" - default = jsonencode(["root", "user1", "user2"]) + name = "system_users" + display_name = "System users" + type = "list(string)" + default = jsonencode(["root", "user1", "user2"]) } data "coder_parameter" "home_volume_size" { - name = "Home Volume Size" - description = <<-EOF - How large should your home volume be? - EOF - type = "number" - default = 30 - mutable = true - order = 3 - - option { - name = "30GB" - value = 30 - } - - option { - name = "60GB" - value = 60 - } - - option { - name = "100GB" - value = 100 - } - - validation { - monotonic = "increasing" - } + name = "Home Volume Size" + description = <<-EOF + How large should your home volume be? + EOF + type = "number" + default = 30 + mutable = true + order = 3 + + option { + name = "30GB" + value = 30 + } + + option { + name = "60GB" + value = 60 + } + + option { + name = "100GB" + value = 100 + } + + validation { + monotonic = "increasing" + } } ``` diff --git a/docs/data-sources/provisioner.md b/docs/data-sources/provisioner.md index ba930a2a..a1ddbe79 100644 --- a/docs/data-sources/provisioner.md +++ b/docs/data-sources/provisioner.md @@ -3,7 +3,7 @@ page_title: "coder_provisioner Data Source - terraform-provider-coder" subcategory: "" description: |- - Use this data source to get information about the Coder provisioner. + Use this data source to get information about the Coder provisioner. --- # coder_provisioner (Data Source) @@ -20,15 +20,15 @@ data "coder_provisioner" "dev" {} data "coder_workspace" "dev" {} resource "coder_agent" "main" { - arch = data.coder_provisioner.dev.arch - os = data.coder_provisioner.dev.os - dir = "/workspace" - display_apps { - vscode = true - vscode_insiders = false - web_terminal = true - ssh_helper = false - } + arch = data.coder_provisioner.dev.arch + os = data.coder_provisioner.dev.os + dir = "/workspace" + display_apps { + vscode = true + vscode_insiders = false + web_terminal = true + ssh_helper = false + } } ``` diff --git a/docs/data-sources/workspace.md b/docs/data-sources/workspace.md index 4dacdfc3..9b3266a9 100644 --- a/docs/data-sources/workspace.md +++ b/docs/data-sources/workspace.md @@ -3,7 +3,7 @@ page_title: "coder_workspace Data Source - terraform-provider-coder" subcategory: "" description: |- - Use this data source to get information for the active workspace build. + Use this data source to get information for the active workspace build. --- # coder_workspace (Data Source) @@ -22,42 +22,42 @@ data "coder_workspace" "me" {} data "coder_workspace_owner" "me" {} resource "coder_agent" "dev" { - arch = "amd64" - os = "linux" - dir = "/workspace" + arch = "amd64" + os = "linux" + dir = "/workspace" } resource "docker_container" "workspace" { - count = data.coder_workspace.me.start_count - image = docker_image.main.name - # Uses lower() to avoid Docker restriction on container names. - name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" - # Hostname makes the shell more user friendly: coder@my-workspace:~$ - hostname = data.coder_workspace.me.name - # Use the docker gateway if the access URL is 127.0.0.1 - entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")] - env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"] - host { - host = "host.docker.internal" - ip = "host-gateway" - } - # Add labels in Docker to keep track of orphan resources. - labels { - label = "coder.owner" - value = data.coder_workspace_owner.me.name - } - labels { - label = "coder.owner_id" - value = data.coder_workspace_owner.me.id - } - labels { - label = "coder.workspace_id" - value = data.coder_workspace.me.id - } - labels { - label = "coder.workspace_name" - value = data.coder_workspace.me.name - } + count = data.coder_workspace.me.start_count + image = docker_image.main.name + # Uses lower() to avoid Docker restriction on container names. + name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" + # Hostname makes the shell more user friendly: coder@my-workspace:~$ + hostname = data.coder_workspace.me.name + # Use the docker gateway if the access URL is 127.0.0.1 + entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")] + env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"] + host { + host = "host.docker.internal" + ip = "host-gateway" + } + # Add labels in Docker to keep track of orphan resources. + labels { + label = "coder.owner" + value = data.coder_workspace_owner.me.name + } + labels { + label = "coder.owner_id" + value = data.coder_workspace_owner.me.id + } + labels { + label = "coder.workspace_id" + value = data.coder_workspace.me.id + } + labels { + label = "coder.workspace_name" + value = data.coder_workspace.me.name + } } ``` diff --git a/docs/data-sources/workspace_owner.md b/docs/data-sources/workspace_owner.md index 2a912e1f..b3f5779a 100644 --- a/docs/data-sources/workspace_owner.md +++ b/docs/data-sources/workspace_owner.md @@ -3,7 +3,7 @@ page_title: "coder_workspace_owner Data Source - terraform-provider-coder" subcategory: "" description: |- - Use this data source to fetch information about the workspace owner. + Use this data source to fetch information about the workspace owner. --- # coder_workspace_owner (Data Source) @@ -18,26 +18,26 @@ provider "coder" {} data "coder_workspace_owner" "me" {} resource "coder_agent" "dev" { - arch = "amd64" - os = "linux" - dir = "/workspace" - env = { - OIDC_TOKEN : data.coder_workspace_owner.me.oidc_access_token, - } + arch = "amd64" + os = "linux" + dir = "/workspace" + env = { + OIDC_TOKEN : data.coder_workspace_owner.me.oidc_access_token, + } } # Add git credentials from coder_workspace_owner resource "coder_env" "git_author_name" { - agent_id = coder_agent.agent_id - name = "GIT_AUTHOR_NAME" - value = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + agent_id = coder_agent.agent_id + name = "GIT_AUTHOR_NAME" + value = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) } resource "coder_env" "git_author_email" { - agent_id = coder_agent.dev.id - name = "GIT_AUTHOR_EMAIL" - value = data.coder_workspace_owner.me.email - count = data.coder_workspace_owner.me.email != "" ? 1 : 0 + agent_id = coder_agent.dev.id + name = "GIT_AUTHOR_EMAIL" + value = data.coder_workspace_owner.me.email + count = data.coder_workspace_owner.me.email != "" ? 1 : 0 } ``` diff --git a/docs/data-sources/workspace_preset.md b/docs/data-sources/workspace_preset.md index 69057403..383e753d 100644 --- a/docs/data-sources/workspace_preset.md +++ b/docs/data-sources/workspace_preset.md @@ -3,7 +3,7 @@ page_title: "coder_workspace_preset Data Source - terraform-provider-coder" subcategory: "" description: |- - Use this data source to predefine common configurations for coder workspaces. Users will have the option to select a defined preset, which will automatically apply the selected configuration. Any parameters defined in the preset will be applied to the workspace. Parameters that are defined by the template but not defined by the preset will still be configurable when creating a workspace. + Use this data source to predefine common configurations for coder workspaces. Users will have the option to select a defined preset, which will automatically apply the selected configuration. Any parameters defined in the preset will be applied to the workspace. Parameters that are defined by the template but not defined by the preset will still be configurable when creating a workspace. --- # coder_workspace_preset (Data Source) @@ -21,21 +21,21 @@ provider "coder" {} # See the coder_parameter data source's documentation for examples of how to define # parameters like the ones used below. data "coder_workspace_preset" "example" { - name = "example" - parameters = { - (data.coder_parameter.example.name) = "us-central1-a" - (data.coder_parameter.ami.name) = "ami-xxxxxxxx" - } + name = "example" + parameters = { + (data.coder_parameter.example.name) = "us-central1-a" + (data.coder_parameter.ami.name) = "ami-xxxxxxxx" + } } # Example of a default preset that will be pre-selected for users data "coder_workspace_preset" "standard" { - name = "Standard" - default = true - parameters = { - (data.coder_parameter.instance_type.name) = "t3.medium" - (data.coder_parameter.region.name) = "us-west-2" - } + name = "Standard" + default = true + parameters = { + (data.coder_parameter.instance_type.name) = "t3.medium" + (data.coder_parameter.region.name) = "us-west-2" + } } ``` diff --git a/docs/data-sources/workspace_tags.md b/docs/data-sources/workspace_tags.md index 010adfe3..ef7835a1 100644 --- a/docs/data-sources/workspace_tags.md +++ b/docs/data-sources/workspace_tags.md @@ -3,7 +3,7 @@ page_title: "coder_workspace_tags Data Source - terraform-provider-coder" subcategory: "" description: |- - Use this data source to configure workspace tags to select provisioners. + Use this data source to configure workspace tags to select provisioners. --- # coder_workspace_tags (Data Source) @@ -16,52 +16,52 @@ Use this data source to configure workspace tags to select provisioners. provider "coder" {} data "coder_parameter" "os_selector" { - name = "os_selector" - display_name = "Operating System" - mutable = false - - default = "osx" - - option { - icon = "/icons/linux.png" - name = "Linux" - value = "linux" - } - option { - icon = "/icons/osx.png" - name = "OSX" - value = "osx" - } - option { - icon = "/icons/windows.png" - name = "Windows" - value = "windows" - } + name = "os_selector" + display_name = "Operating System" + mutable = false + + default = "osx" + + option { + icon = "/icons/linux.png" + name = "Linux" + value = "linux" + } + option { + icon = "/icons/osx.png" + name = "OSX" + value = "osx" + } + option { + icon = "/icons/windows.png" + name = "Windows" + value = "windows" + } } data "coder_parameter" "feature_cache_enabled" { - name = "feature_cache_enabled" - display_name = "Enable cache?" - type = "bool" + name = "feature_cache_enabled" + display_name = "Enable cache?" + type = "bool" - default = false + default = false } data "coder_parameter" "feature_debug_enabled" { - name = "feature_debug_enabled" - display_name = "Enable debug?" - type = "bool" + name = "feature_debug_enabled" + display_name = "Enable debug?" + type = "bool" - default = true + default = true } data "coder_workspace_tags" "custom_workspace_tags" { - tags = { - "cluster" = "developers" - "os" = data.coder_parameter.os_selector.value - "debug" = "${data.coder_parameter.feature_debug_enabled.value}+12345" - "cache" = data.coder_parameter.feature_cache_enabled.value == "true" ? "nix-with-cache" : "no-cache" - } + tags = { + "cluster" = "developers" + "os" = data.coder_parameter.os_selector.value + "debug" = "${data.coder_parameter.feature_debug_enabled.value}+12345" + "cache" = data.coder_parameter.feature_cache_enabled.value == "true" ? "nix-with-cache" : "no-cache" + } } ``` diff --git a/docs/index.md b/docs/index.md index c30f1477..bb97ff16 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,7 +3,7 @@ page_title: "Coder Provider" subcategory: "Infrastructure" description: |- - Terraform provider for managing Coder templates, which are the underlying infrastructure for Coder workspaces. + Terraform provider for managing Coder templates, which are the underlying infrastructure for Coder workspaces. --- # Coder Provider @@ -14,52 +14,58 @@ Terraform provider for managing Coder [templates](https://coder.com/docs/admin/t !> [`coder_git_auth`](https://registry.terraform.io/providers/coder/coder/1.0.4/docs/data-sources/git_auth) and owner related fields of [`coder_workspace`](https://registry.terraform.io/providers/coder/coder/1.0.4/docs/data-sources/workspace) data source have been removed. Follow the [Version 2 Upgrade Guide](https://registry.terraform.io/providers/coder/coder/latest/docs/guides/version-2-upgrade) to update your code. +## Version Compatibility + +This provider automatically documents version requirements for individual resources and features. + +~> **Note:** Individual resources may have higher version requirements. Check the documentation for each resource to see its specific minimum Coder version. + ## Example ```terraform terraform { - required_providers { - coder = { - source = "coder/coder" - } - } + required_providers { + coder = { + source = "coder/coder" + } + } } provider "google" { - region = "us-central1" + region = "us-central1" } data "coder_workspace" "me" {} resource "coder_agent" "dev" { - arch = "amd64" - os = "linux" - auth = "google-instance-identity" + arch = "amd64" + os = "linux" + auth = "google-instance-identity" } data "google_compute_default_service_account" "default" {} resource "google_compute_instance" "dev" { - zone = "us-central1-a" - count = data.coder_workspace.me.start_count - name = "coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}" - machine_type = "e2-medium" - network_interface { - network = "default" - access_config { - // Ephemeral public IP - } - } - boot_disk { - initialize_params { - image = "debian-cloud/debian-9" - } - } - service_account { - email = data.google_compute_default_service_account.default.email - scopes = ["cloud-platform"] - } - metadata_startup_script = coder_agent.dev.init_script + zone = "us-central1-a" + count = data.coder_workspace.me.start_count + name = "coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}" + machine_type = "e2-medium" + network_interface { + network = "default" + access_config { + // Ephemeral public IP + } + } + boot_disk { + initialize_params { + image = "debian-cloud/debian-9" + } + } + service_account { + email = data.google_compute_default_service_account.default.email + scopes = ["cloud-platform"] + } + metadata_startup_script = coder_agent.dev.init_script } ``` diff --git a/docs/resources/agent.md b/docs/resources/agent.md index 87ab4239..64b7d841 100644 --- a/docs/resources/agent.md +++ b/docs/resources/agent.md @@ -3,7 +3,7 @@ page_title: "coder_agent Resource - terraform-provider-coder" subcategory: "" description: |- - Use this resource to associate an agent. + Use this resource to associate an agent. --- # coder_agent (Resource) @@ -17,48 +17,48 @@ data "coder_workspace" "me" { } resource "coder_agent" "dev" { - os = "linux" - arch = "amd64" - dir = "/workspace" - api_key_scope = "all" - display_apps { - vscode = true - vscode_insiders = false - web_terminal = true - ssh_helper = false - } - - metadata { - display_name = "CPU Usage" - key = "cpu_usage" - script = "coder stat cpu" - interval = 10 - timeout = 1 - order = 2 - } - metadata { - display_name = "RAM Usage" - key = "ram_usage" - script = "coder stat mem" - interval = 10 - timeout = 1 - order = 1 - } - - order = 1 + os = "linux" + arch = "amd64" + dir = "/workspace" + api_key_scope = "all" + display_apps { + vscode = true + vscode_insiders = false + web_terminal = true + ssh_helper = false + } + + metadata { + display_name = "CPU Usage" + key = "cpu_usage" + script = "coder stat cpu" + interval = 10 + timeout = 1 + order = 2 + } + metadata { + display_name = "RAM Usage" + key = "ram_usage" + script = "coder stat mem" + interval = 10 + timeout = 1 + order = 1 + } + + order = 1 } resource "kubernetes_pod" "dev" { - count = data.coder_workspace.me.start_count - spec { - container { - command = ["sh", "-c", coder_agent.dev.init_script] - env { - name = "CODER_AGENT_TOKEN" - value = coder_agent.dev.token - } - } - } + count = data.coder_workspace.me.start_count + spec { + container { + command = ["sh", "-c", coder_agent.dev.init_script] + env { + name = "CODER_AGENT_TOKEN" + value = coder_agent.dev.token + } + } + } } ``` diff --git a/docs/resources/agent_instance.md b/docs/resources/agent_instance.md index ec855b12..063f6911 100644 --- a/docs/resources/agent_instance.md +++ b/docs/resources/agent_instance.md @@ -3,7 +3,7 @@ page_title: "coder_agent_instance Resource - terraform-provider-coder" subcategory: "" description: |- - Use this resource to associate an instance ID with an agent for zero-trust authentication. This association is done automatically for "google_compute_instance", "aws_instance", "azurerm_linux_virtual_machine", and "azurerm_windows_virtual_machine" resources. + Use this resource to associate an instance ID with an agent for zero-trust authentication. This association is done automatically for "google_compute_instance", "aws_instance", "azurerm_linux_virtual_machine", and "azurerm_windows_virtual_machine" resources. --- # coder_agent_instance (Resource) @@ -14,18 +14,18 @@ Use this resource to associate an instance ID with an agent for zero-trust authe ```terraform resource "coder_agent" "dev" { - os = "linux" - arch = "amd64" - auth = "google-instance-identity" + os = "linux" + arch = "amd64" + auth = "google-instance-identity" } resource "google_compute_instance" "dev" { - zone = "us-central1-a" + zone = "us-central1-a" } resource "coder_agent_instance" "dev" { - agent_id = coder_agent.dev.id - instance_id = google_compute_instance.dev.instance_id + agent_id = coder_agent.dev.id + instance_id = google_compute_instance.dev.instance_id } ``` diff --git a/docs/resources/ai_task.md b/docs/resources/ai_task.md index 1922ef59..3002e96b 100644 --- a/docs/resources/ai_task.md +++ b/docs/resources/ai_task.md @@ -3,7 +3,7 @@ page_title: "coder_ai_task Resource - terraform-provider-coder" subcategory: "" description: |- - Use this resource to define Coder tasks. + Use this resource to define Coder tasks. --- # coder_ai_task (Resource) diff --git a/docs/resources/app.md b/docs/resources/app.md index 6be99cf3..242d1661 100644 --- a/docs/resources/app.md +++ b/docs/resources/app.md @@ -3,7 +3,7 @@ page_title: "coder_app Resource - terraform-provider-coder" subcategory: "" description: |- - Use this resource to define shortcuts to access applications in a workspace. + Use this resource to define shortcuts to access applications in a workspace. --- # coder_app (Resource) @@ -16,37 +16,37 @@ Use this resource to define shortcuts to access applications in a workspace. data "coder_workspace" "me" {} resource "coder_agent" "dev" { - os = "linux" - arch = "amd64" - dir = "/workspace" - startup_script = <"`. - `open_in` (String) Determines where the app will be opened. Valid values are `"tab"` and `"slim-window" (default)`. `"tab"` opens in a new tab in the same browser window. `"slim-window"` opens a new browser window without navigation controls. - `order` (Number) The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order). diff --git a/docs/resources/devcontainer.md b/docs/resources/devcontainer.md index 06d7f6f3..4e28221e 100644 --- a/docs/resources/devcontainer.md +++ b/docs/resources/devcontainer.md @@ -3,15 +3,14 @@ page_title: "coder_devcontainer Resource - terraform-provider-coder" subcategory: "" description: |- - Define a Dev Container the agent should know of and attempt to autostart. - -> This resource is only available in Coder v2.21 and later. + Define a Dev Container the agent should know of and attempt to autostart. --- # coder_devcontainer (Resource) -Define a Dev Container the agent should know of and attempt to autostart. +Define a Dev Container the agent should know of and attempt to autostart. --> This resource is only available in Coder v2.21 and later. +~> **Note:** This resource requires [Coder v2.21.0](https://github.com/coder/coder/releases/tag/v2.21.0) or later. diff --git a/docs/resources/env.md b/docs/resources/env.md index 3a5a7f3a..667234b7 100644 --- a/docs/resources/env.md +++ b/docs/resources/env.md @@ -3,7 +3,7 @@ page_title: "coder_env Resource - terraform-provider-coder" subcategory: "" description: |- - Use this resource to set an environment variable in a workspace. Note that this resource cannot be used to overwrite existing environment variables set on the coder_agent resource. + Use this resource to set an environment variable in a workspace. Note that this resource cannot be used to overwrite existing environment variables set on the coder_agent resource. --- # coder_env (Resource) @@ -16,21 +16,21 @@ Use this resource to set an environment variable in a workspace. Note that this data "coder_workspace" "me" {} resource "coder_agent" "dev" { - os = "linux" - arch = "amd64" - dir = "/workspace" + os = "linux" + arch = "amd64" + dir = "/workspace" } resource "coder_env" "welcome_message" { - agent_id = coder_agent.dev.id - name = "WELCOME_MESSAGE" - value = "Welcome to your Coder workspace!" + agent_id = coder_agent.dev.id + name = "WELCOME_MESSAGE" + value = "Welcome to your Coder workspace!" } resource "coder_env" "internal_api_url" { - agent_id = coder_agent.dev.id - name = "INTERNAL_API_URL" - value = "https://api.internal.company.com/v1" + agent_id = coder_agent.dev.id + name = "INTERNAL_API_URL" + value = "https://api.internal.company.com/v1" } ``` diff --git a/docs/resources/metadata.md b/docs/resources/metadata.md index d8329ea9..037f9766 100644 --- a/docs/resources/metadata.md +++ b/docs/resources/metadata.md @@ -3,8 +3,8 @@ page_title: "coder_metadata Resource - terraform-provider-coder" subcategory: "" description: |- - Use this resource to attach metadata to a resource. They will be displayed in the Coder dashboard alongside the resource. The resource containing the agent, and it's metadata, will be shown by default. - Alternatively, to attach metadata to the agent, use a metadata block within a coder_agent resource. + Use this resource to attach metadata to a resource. They will be displayed in the Coder dashboard alongside the resource. The resource containing the agent, and it's metadata, will be shown by default. + Alternatively, to attach metadata to the agent, use a metadata block within a coder_agent resource. --- # coder_metadata (Resource) @@ -20,40 +20,40 @@ data "coder_workspace" "me" { } resource "kubernetes_pod" "dev" { - count = data.coder_workspace.me.start_count - metadata { - name = "k8s_example" - namespace = "example" - } - spec { - # Draw the rest of the pod! - } + count = data.coder_workspace.me.start_count + metadata { + name = "k8s_example" + namespace = "example" + } + spec { + # Draw the rest of the pod! + } } resource "tls_private_key" "example_key_pair" { - algorithm = "ECDSA" - ecdsa_curve = "P256" + algorithm = "ECDSA" + ecdsa_curve = "P256" } resource "coder_metadata" "pod_info" { - count = data.coder_workspace.me.start_count - resource_id = kubernetes_pod.dev[0].id - # (Enterprise-only) this resource consumes 200 quota units - daily_cost = 200 - item { - key = "description" - value = "This description will show up in the Coder dashboard." - } - item { - key = "pod_uid" - value = kubernetes_pod.dev[0].uid - } - item { - key = "public_key" - value = tls_private_key.example_key_pair.public_key_openssh - # The value of this item will be hidden from view by default - sensitive = true - } + count = data.coder_workspace.me.start_count + resource_id = kubernetes_pod.dev[0].id + # (Enterprise-only) this resource consumes 200 quota units + daily_cost = 200 + item { + key = "description" + value = "This description will show up in the Coder dashboard." + } + item { + key = "pod_uid" + value = kubernetes_pod.dev[0].uid + } + item { + key = "public_key" + value = tls_private_key.example_key_pair.public_key_openssh + # The value of this item will be hidden from view by default + sensitive = true + } } ``` diff --git a/docs/resources/script.md b/docs/resources/script.md index 21bfaec9..a7236ea7 100644 --- a/docs/resources/script.md +++ b/docs/resources/script.md @@ -3,7 +3,7 @@ page_title: "coder_script Resource - terraform-provider-coder" subcategory: "" description: |- - Use this resource to run a script from an agent. When multiple scripts are assigned to the same agent, they are executed in parallel. + Use this resource to run a script from an agent. When multiple scripts are assigned to the same agent, they are executed in parallel. --- # coder_script (Resource) @@ -16,65 +16,65 @@ Use this resource to run a script from an agent. When multiple scripts are assig data "coder_workspace" "me" {} resource "coder_agent" "dev" { - os = "linux" - arch = "amd64" - dir = "/workspace" + os = "linux" + arch = "amd64" + dir = "/workspace" } resource "coder_script" "dotfiles" { - agent_id = coder_agent.dev.id - display_name = "Dotfiles" - icon = "/icon/dotfiles.svg" - run_on_start = true - script = templatefile("~/get_dotfiles.sh", { - DOTFILES_URI : var.dotfiles_uri, - DOTFILES_USER : var.dotfiles_user - }) + agent_id = coder_agent.dev.id + display_name = "Dotfiles" + icon = "/icon/dotfiles.svg" + run_on_start = true + script = templatefile("~/get_dotfiles.sh", { + DOTFILES_URI : var.dotfiles_uri, + DOTFILES_USER : var.dotfiles_user + }) } resource "coder_script" "code-server" { - agent_id = coder_agent.dev.id - display_name = "code-server" - icon = "/icon/code.svg" - run_on_start = true - start_blocks_login = true - script = templatefile("./install-code-server.sh", { - LOG_PATH : "/tmp/code-server.log" - }) + agent_id = coder_agent.dev.id + display_name = "code-server" + icon = "/icon/code.svg" + run_on_start = true + start_blocks_login = true + script = templatefile("./install-code-server.sh", { + LOG_PATH : "/tmp/code-server.log" + }) } resource "coder_script" "nightly_update" { - agent_id = coder_agent.dev.id - display_name = "Nightly update" - icon = "/icon/database.svg" - cron = "0 0 22 * * *" # Run at 22:00 (10 PM) every day - script = </tmp/pid.log 2>&1 & - EOF + agent_id = coder_agent.dev.id + display_name = "Stop daemon server" + run_on_stop = true + icon = "/icons/memory.svg" + script = </tmp/pid.log 2>&1 & + EOF } ``` diff --git a/provider/VERSION_METADATA.md b/provider/VERSION_METADATA.md new file mode 100644 index 00000000..f8de5a63 --- /dev/null +++ b/provider/VERSION_METADATA.md @@ -0,0 +1,102 @@ +# Version Metadata Documentation + +This document explains how to add version requirements to resources and attributes in the terraform-provider-coder. + +## Overview + +Version information is embedded directly in resource and attribute descriptions using the `@since:` marker. The documentation generation process automatically extracts this information and formats it appropriately. + +## Adding Version Requirements + +### For Resources + +Add a `@since:` marker to the resource's `Description` field: + +```go +Description: "Your resource description. @since:v2.21.0", +``` + +The marker will be automatically removed from the generated docs and replaced with a formatted note. + +### For Attributes + +Add a `@since:` marker to the attribute's `Description` field: + +```go +"my_attribute": { + Type: schema.TypeString, + Description: "Attribute description. @since:v2.16.0", + Optional: true, +}, +``` + +This will result in the documentation showing: `- my_attribute (String) Attribute description. *(since v2.16.0)*` + +## Version Marker Format + +Use the format: `@since:vX.Y.Z` + +This single format is used for both resources and attributes to maintain consistency. + +## How It Works + +1. **During Development**: Add `@since:` markers to descriptions +2. **During Doc Generation**: + - `terraform-plugin-docs` generates initial documentation + - Our custom `docsgen` script: + - Extracts version information from descriptions + - Adds formatted version notes to resources + - Adds inline version markers to attributes + - Cleans up the version patterns from descriptions + +## Examples + +### Resource Example + +```go +func myNewResource() *schema.Resource { + return &schema.Resource{ + Description: "Manages a new Coder feature. @since:v2.25.0", + // ... rest of resource definition + } +} +``` + +Results in documentation with: +```markdown +# coder_my_new (Resource) + +Manages a new Coder feature. + +~> **Note:** This resource requires [Coder v2.25.0](https://github.com/coder/coder/releases/tag/v2.25.0) or later. +``` + +### Attribute Example + +```go +"advanced_option": { + Type: schema.TypeBool, + Description: "Enable advanced features. @since:v2.22.0", + Optional: true, +}, +``` + +Results in documentation with: +```markdown +- `advanced_option` (Boolean) Enable advanced features. *(since v2.22.0)* +``` + +## When to Add Version Information + +- **Add @since: markers** for newly introduced resources and data sources +- **Add @since: markers** for attributes added to existing resources and data sources +- **Don't add markers** for resources that existed before terraform-provider-coder v2.0 +- Resources and attributes without `@since:` markers won't show version information + +## Best Practices + +1. **Always add @since: markers** when creating new resources or attributes +2. **Use semantic versioning** (vX.Y.Z format) +3. **Test documentation generation** with `make gen` after adding markers +4. **Keep descriptions concise** - the version marker is removed from the final docs + diff --git a/provider/ai_task.go b/provider/ai_task.go index 76b19f3c..281b047e 100644 --- a/provider/ai_task.go +++ b/provider/ai_task.go @@ -25,7 +25,7 @@ func aiTask() *schema.Resource { return &schema.Resource{ SchemaVersion: 1, - Description: "Use this resource to define Coder tasks.", + Description: "Use this resource to define Coder tasks.", CreateContext: func(c context.Context, resourceData *schema.ResourceData, i any) diag.Diagnostics { resourceData.SetId(uuid.NewString()) return nil diff --git a/provider/app.go b/provider/app.go index adbbf0e7..e59e4c24 100644 --- a/provider/app.go +++ b/provider/app.go @@ -251,7 +251,7 @@ func appResource() *schema.Resource { }, "hidden": { Type: schema.TypeBool, - Description: "Determines if the app is visible in the UI (minimum Coder version: v2.16).", + Description: "Determines if the app is visible in the UI.", Default: false, ForceNew: true, Optional: true, diff --git a/provider/devcontainer.go b/provider/devcontainer.go index 81a31194..d3b81017 100644 --- a/provider/devcontainer.go +++ b/provider/devcontainer.go @@ -13,7 +13,7 @@ func devcontainerResource() *schema.Resource { return &schema.Resource{ SchemaVersion: 1, - Description: "Define a Dev Container the agent should know of and attempt to autostart.\n\n-> This resource is only available in Coder v2.21 and later.", + Description: "Define a Dev Container the agent should know of and attempt to autostart. @since:v2.21.0", CreateContext: func(_ context.Context, rd *schema.ResourceData, _ interface{}) diag.Diagnostics { rd.SetId(uuid.NewString()) diff --git a/scripts/docsgen/main.go b/scripts/docsgen/main.go index 53b43ca4..425ed028 100644 --- a/scripts/docsgen/main.go +++ b/scripts/docsgen/main.go @@ -14,11 +14,20 @@ import ( "golang.org/x/xerrors" ) -// This script patches Markdown docs generated by `terraform-plugin-docs` to expose the original deprecation message. +// This script patches Markdown docs generated by `terraform-plugin-docs` to: +// 1. Expose the original deprecation message +// 2. Extract and format version information from resource/attribute descriptions +// 3. Add inline version markers for attributes with version requirements const docsDir = "docs" // FIXME expose as flag? -var reDeprecatedProperty = regexp.MustCompile("`([^`]+)` \\(([^,\\)]+), Deprecated\\) ([^\n]+)") +var ( + reDeprecatedProperty = regexp.MustCompile("`([^`]+)` \\(([^,\\)]+), Deprecated\\) ([^\n]+)") + // Pattern to extract version info from descriptions: @since:v2.16.0 + reVersionPattern = regexp.MustCompile(`@since:(v\d+\.\d+\.\d+)`) + // Pattern to find existing version info in descriptions (to clean up) + reExistingVersionInfo = regexp.MustCompile(`\s*\(@since:[^)]+\)|\s*\(minimum Coder version:[^)]+\)`) +) func main() { p := provider.New() @@ -26,6 +35,12 @@ func main() { if err != nil { log.Fatal(err) } + + // Process version information for all resources and data sources + err = processVersionInformation(p) + if err != nil { + log.Fatal(err) + } } func exposeDeprecationMessage(p *schema.Provider) error { @@ -65,6 +80,9 @@ func adjustDocFile(docPath string, schemas map[string]*schema.Schema) error { } result := writeDeprecationMessage(doc, schemas) + + // Clean @since markers from the final documentation + result = cleanVersionMarkers(result) err = os.WriteFile(docPath, result, 0644) if err != nil { @@ -87,3 +105,198 @@ func writeDeprecationMessage(doc []byte, schemas map[string]*schema.Schema) []by return bytes.Replace(m, []byte("Deprecated"), []byte(fmt.Sprintf("**Deprecated**: %s", sch.Deprecated)), 1) }) } + +// cleanVersionMarkers removes @since markers from the documentation +func cleanVersionMarkers(doc []byte) []byte { + // Remove @since:vX.Y.Z patterns from the documentation + result := reVersionPattern.ReplaceAll(doc, []byte("")) + // Clean up any double spaces that might be left after removing @since markers + result = regexp.MustCompile(` +`).ReplaceAll(result, []byte(" ")) + // Clean up trailing spaces at end of lines + result = regexp.MustCompile(` +$`).ReplaceAllFunc(result, func(m []byte) []byte { + return []byte{} + }) + return result +} + +func processVersionInformation(p *schema.Provider) error { + // Process data sources + for dataSourceName, dataSource := range p.DataSourcesMap { + docFile := filepath.Join(docsDir, "data-sources", strings.Replace(dataSourceName, "coder_", "", 1)+".md") + + // Extract version from description + version := extractVersionFromDescription(dataSource.Description) + if version != "" { + // Only add version note if explicitly specified + if err := addVersionToResourceDoc(docFile, dataSourceName, version, "data source"); err != nil { + return xerrors.Errorf("unable to add version to data-source doc file (data-source: %s): %w", dataSourceName, err) + } + } + + // Process attributes for version info + if err := processAttributeVersions(docFile, dataSource.Schema); err != nil { + return xerrors.Errorf("unable to process attribute versions for data-source (data-source: %s): %w", dataSourceName, err) + } + } + + // Process resources + for resourceName, resource := range p.ResourcesMap { + docFile := filepath.Join(docsDir, "resources", strings.Replace(resourceName, "coder_", "", 1)+".md") + + // Extract version from description + version := extractVersionFromDescription(resource.Description) + if version != "" { + // Only add version note if explicitly specified + if err := addVersionToResourceDoc(docFile, resourceName, version, "resource"); err != nil { + return xerrors.Errorf("unable to add version to resource doc file (resource: %s): %w", resourceName, err) + } + } + + // Process attributes for version info + if err := processAttributeVersions(docFile, resource.Schema); err != nil { + return xerrors.Errorf("unable to process attribute versions for resource (resource: %s): %w", resourceName, err) + } + } + + return nil +} + +func extractVersionFromDescription(description string) string { + matches := reVersionPattern.FindStringSubmatch(description) + if len(matches) > 1 { + return matches[1] + } + return "" +} + +func addVersionToResourceDoc(docPath string, resourceName string, version string, resourceType string) error { + doc, err := os.ReadFile(docPath) + if err != nil { + return xerrors.Errorf("can't read the doc file: %w", err) + } + + docStr := string(doc) + + // Check if version note already exists + if strings.Contains(docStr, "~> **Note:** This") && strings.Contains(docStr, "requires") && strings.Contains(docStr, "Coder") { + // Version note already exists, skip + return nil + } + + // Add version note after the description + versionNote := fmt.Sprintf("\n\n~> **Note:** This %s requires [Coder %s](https://github.com/coder/coder/releases/tag/%s) or later.", + resourceType, version, version) + + // Find the end of frontmatter + frontmatterEnd := -1 + lines := strings.Split(docStr, "\n") + + if len(lines) > 0 && lines[0] == "---" { + for i := 1; i < len(lines); i++ { + if lines[i] == "---" { + frontmatterEnd = i + break + } + } + } + + // Find where to insert the version note + inserted := false + for i := frontmatterEnd + 1; i < len(lines); i++ { + // Skip empty lines and headings + if lines[i] == "" || strings.HasPrefix(lines[i], "#") { + continue + } + + // Insert after the first paragraph (non-empty, non-heading line) + lines[i] = lines[i] + versionNote + inserted = true + break + } + + if !inserted { + // If we couldn't find a good place, add it at the end + lines = append(lines, versionNote) + } + + docStr = strings.Join(lines, "\n") + + err = os.WriteFile(docPath, []byte(docStr), 0644) + if err != nil { + return xerrors.Errorf("can't write modified doc file: %w", err) + } + return nil +} + +func processAttributeVersions(docPath string, schemas map[string]*schema.Schema) error { + doc, err := os.ReadFile(docPath) + if err != nil { + return xerrors.Errorf("can't read the doc file: %w", err) + } + + docStr := string(doc) + modified := false + + // Process each attribute that has version information + for attrName, attrSchema := range schemas { + version := extractVersionFromDescription(attrSchema.Description) + if version != "" && version != "v2.18.0" { // Only add version markers for non-default versions + // Clean the version pattern from the description in the docs + cleanDesc := reExistingVersionInfo.ReplaceAllString(attrSchema.Description, "") + cleanDesc = reVersionPattern.ReplaceAllString(cleanDesc, "") + + // Find the attribute in the documentation and add version marker + // Look for patterns like "- `attrName` (Type) Description" + attrPattern := regexp.MustCompile(fmt.Sprintf(`- \x60%s\x60 \([^)]+\) ([^\n]+)`, regexp.QuoteMeta(attrName))) + + newDocStr := attrPattern.ReplaceAllStringFunc(docStr, func(match string) string { + // Check if version marker already exists + if strings.Contains(match, "*(since") { + return match + } + // Clean version patterns from the description + cleanMatch := reVersionPattern.ReplaceAllString(match, "") + cleanMatch = reExistingVersionInfo.ReplaceAllString(cleanMatch, "") + // Add version marker at the end + return strings.TrimRight(cleanMatch, " ") + fmt.Sprintf(" *(since %s)*", version) + }) + + if newDocStr != docStr { + docStr = newDocStr + modified = true + } + + // Also handle nested attributes (e.g., in blocks) + // Look for patterns like " - `attrName` (Type) Description" (with more spaces) + nestedAttrPattern := regexp.MustCompile(fmt.Sprintf(`( +)- \x60%s\x60 \([^)]+\) ([^\n]+)`, regexp.QuoteMeta(attrName))) + + newDocStr = nestedAttrPattern.ReplaceAllStringFunc(docStr, func(match string) string { + // Check if version marker already exists + if strings.Contains(match, "*(since") { + return match + } + // Clean version patterns from the description + cleanMatch := reVersionPattern.ReplaceAllString(match, "") + cleanMatch = reExistingVersionInfo.ReplaceAllString(cleanMatch, "") + // Add version marker at the end + return strings.TrimRight(cleanMatch, " ") + fmt.Sprintf(" *(since %s)*", version) + }) + + if newDocStr != docStr { + docStr = newDocStr + modified = true + } + } + } + + if modified { + // Clean any remaining @since markers from the final document + cleanedDoc := cleanVersionMarkers([]byte(docStr)) + err = os.WriteFile(docPath, cleanedDoc, 0644) + if err != nil { + return xerrors.Errorf("can't write modified doc file: %w", err) + } + } + + return nil +} diff --git a/templates/index.md.tmpl b/templates/index.md.tmpl index efdaae96..d34dc250 100644 --- a/templates/index.md.tmpl +++ b/templates/index.md.tmpl @@ -14,6 +14,12 @@ Terraform provider for managing Coder [templates](https://coder.com/docs/admin/t !> [`coder_git_auth`](https://registry.terraform.io/providers/coder/coder/1.0.4/docs/data-sources/git_auth) and owner related fields of [`coder_workspace`](https://registry.terraform.io/providers/coder/coder/1.0.4/docs/data-sources/workspace) data source have been removed. Follow the [Version 2 Upgrade Guide](https://registry.terraform.io/providers/coder/coder/latest/docs/guides/version-2-upgrade) to update your code. +## Version Compatibility + +This provider automatically documents version requirements for individual resources and features. + +~> **Note:** Individual resources may have higher version requirements. Check the documentation for each resource to see its specific minimum Coder version. + ## Example {{tffile "examples/provider/provider.tf"}}