From d2e2d968046dcb68e2e67a07f05a5dd61058cf65 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Wed, 3 Jul 2024 16:01:57 +0300 Subject: [PATCH 01/10] docs: improve docs by using code-styled markdown (#253) * docs: improve docs by using code-styled markdown * `make gen` * fixup! * make deprecated bold * fix tests * fix tests * more formatting * fixes * make better * add deprecation warning to `coder_git_auth` --- docs/data-sources/git_auth.md | 5 +++++ docs/data-sources/parameter.md | 8 ++++---- docs/data-sources/workspace.md | 18 ++++++++--------- docs/index.md | 2 +- docs/resources/agent.md | 26 ++++++++++++------------ docs/resources/agent_instance.md | 4 ++-- docs/resources/app.md | 20 +++++++++---------- docs/resources/env.md | 6 +++--- docs/resources/metadata.md | 8 ++++---- docs/resources/script.md | 4 ++-- provider/agent.go | 34 ++++++++++++++++---------------- provider/app.go | 34 ++++++++++++++++---------------- provider/env.go | 4 ++-- provider/gitauth.go | 2 +- provider/metadata.go | 10 +++++----- provider/parameter.go | 10 +++++----- provider/script.go | 10 +++++----- provider/script_test.go | 4 ++-- provider/workspace.go | 4 ++-- scripts/docsgen/main.go | 2 +- 20 files changed, 110 insertions(+), 105 deletions(-) diff --git a/docs/data-sources/git_auth.md b/docs/data-sources/git_auth.md index fe64805e..e665aeb1 100644 --- a/docs/data-sources/git_auth.md +++ b/docs/data-sources/git_auth.md @@ -3,11 +3,16 @@ page_title: "coder_git_auth Data Source - terraform-provider-coder" subcategory: "" description: |- + ~> Deprecated + Use the coder_external_auth data source instead. Use this data source to require users to authenticate with a Git provider prior to workspace creation. This can be used to perform an authenticated git clone in startup scripts. --- # coder_git_auth (Data Source) +~> **Deprecated** +Use the `coder_external_auth` data source instead. + Use this data source to require users to authenticate with a Git provider prior to workspace creation. This can be used to perform an authenticated `git clone` in startup scripts. ## Example Usage diff --git a/docs/data-sources/parameter.md b/docs/data-sources/parameter.md index 178c6d9d..f40a9c83 100644 --- a/docs/data-sources/parameter.md +++ b/docs/data-sources/parameter.md @@ -145,11 +145,11 @@ data "coder_parameter" "home_volume_size" { - `description` (String) Describe what this parameter does. - `display_name` (String) The displayed name of the parameter as it will appear in the interface. - `ephemeral` (Boolean) The value of an ephemeral parameter will not be preserved between consecutive workspace builds. -- `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons [here](https://github.com/coder/coder/tree/main/site/static/icon). Use a built-in icon with `data.coder_workspace.me.access_url + "/icon/"`. +- `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons [here](https://github.com/coder/coder/tree/main/site/static/icon). Use a built-in icon with `"${data.coder_workspace.me.access_url}/icon/"`. - `mutable` (Boolean) Whether this value can be changed after workspace creation. This can be destructive for values like region, so use with caution! -- `option` (Block List, Max: 64) Each "option" block defines a value for a user to select from. (see [below for nested schema](#nestedblock--option)) +- `option` (Block List, Max: 64) Each `option` block defines a value for a user to select from. (see [below for nested schema](#nestedblock--option)) - `order` (Number) The order determines the position of a template parameter in the UI/CLI presentation. The lowest order is shown first and parameters with equal order are sorted by name (ascending order). -- `type` (String) The type of this parameter. Must be one of: "number", "string", "bool", or "list(string)". +- `type` (String) The type of this parameter. Must be one of: `"number"`, `"string"`, `"bool"`, or `"list(string)"`. - `validation` (Block List, Max: 1) Validate the input of a parameter. (see [below for nested schema](#nestedblock--validation)) ### Read-Only @@ -169,7 +169,7 @@ Required: Optional: - `description` (String) Describe what selecting this value does. -- `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons here: https://github.com/coder/coder/tree/main/site/static/icon. Use a built-in icon with `data.coder_workspace.me.access_url + "/icon/"`. +- `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons [here](https://github.com/coder/coder/tree/main/site/static/icon). Use a built-in icon with `"${data.coder_workspace.me.access_url}/icon/"`. diff --git a/docs/data-sources/workspace.md b/docs/data-sources/workspace.md index e9de5889..8b824c37 100644 --- a/docs/data-sources/workspace.md +++ b/docs/data-sources/workspace.md @@ -30,15 +30,15 @@ resource "kubernetes_pod" "dev" { - `access_url` (String) The access URL of the Coder deployment provisioning this workspace. - `id` (String) UUID of the workspace. - `name` (String) Name of the workspace. -- `owner` (String, Deprecated: Use `coder_workspace_owner.name` instead.) Username of the workspace owner. -- `owner_email` (String, Deprecated: Use `coder_workspace_owner.email` instead.) Email address of the workspace owner. -- `owner_groups` (List of String, Deprecated: Use `coder_workspace_owner.groups` instead.) List of groups the workspace owner belongs to. -- `owner_id` (String, Deprecated: Use `coder_workspace_owner.id` instead.) UUID of the workspace owner. -- `owner_name` (String, Deprecated: Use `coder_workspace_owner.full_name` instead.) Name of the workspace owner. -- `owner_oidc_access_token` (String, Deprecated: Use `coder_workspace_owner.oidc_access_token` instead.) A valid OpenID Connect access token of the workspace owner. This is only available if the workspace owner authenticated with OpenID Connect. If a valid token cannot be obtained, this value will be an empty string. -- `owner_session_token` (String, Deprecated: Use `coder_workspace_owner.session_token` instead.) Session token for authenticating with a Coder deployment. It is regenerated everytime a workspace is started. -- `start_count` (Number) A computed count based on "transition" state. If "start", count will equal 1. +- `owner` (String, **Deprecated**: Use `coder_workspace_owner.name` instead.) Username of the workspace owner. +- `owner_email` (String, **Deprecated**: Use `coder_workspace_owner.email` instead.) Email address of the workspace owner. +- `owner_groups` (List of String, **Deprecated**: Use `coder_workspace_owner.groups` instead.) List of groups the workspace owner belongs to. +- `owner_id` (String, **Deprecated**: Use `coder_workspace_owner.id` instead.) UUID of the workspace owner. +- `owner_name` (String, **Deprecated**: Use `coder_workspace_owner.full_name` instead.) Name of the workspace owner. +- `owner_oidc_access_token` (String, **Deprecated**: Use `coder_workspace_owner.oidc_access_token` instead.) A valid OpenID Connect access token of the workspace owner. This is only available if the workspace owner authenticated with OpenID Connect. If a valid token cannot be obtained, this value will be an empty string. +- `owner_session_token` (String, **Deprecated**: Use `coder_workspace_owner.session_token` instead.) Session token for authenticating with a Coder deployment. It is regenerated everytime a workspace is started. +- `start_count` (Number) A computed count based on `transition` state. If `start`, count will equal 1. - `template_id` (String) ID of the workspace's template. - `template_name` (String) Name of the workspace's template. - `template_version` (String) Version of the workspace's template. -- `transition` (String) Either "start" or "stop". Use this to start/stop resources with "count". +- `transition` (String) Either `start` or `stop`. Use this to start/stop resources with `count`. diff --git a/docs/index.md b/docs/index.md index 84843dec..a4dfd70e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -62,5 +62,5 @@ resource "google_compute_instance" "dev" { ### Optional -- `feature_use_managed_variables` (Boolean, Deprecated: Terraform variables are now exclusively utilized for template-wide variables after the removal of support for legacy parameters.) Feature: use managed Terraform variables. The feature flag is not used anymore as Terraform variables are now exclusively utilized for template-wide variables. +- `feature_use_managed_variables` (Boolean, **Deprecated**: Terraform variables are now exclusively utilized for template-wide variables after the removal of support for legacy parameters.) Feature: use managed Terraform variables. The feature flag is not used anymore as Terraform variables are now exclusively utilized for template-wide variables. - `url` (String) The URL to access Coder. \ No newline at end of file diff --git a/docs/resources/agent.md b/docs/resources/agent.md index d20374d0..e444d2d7 100644 --- a/docs/resources/agent.md +++ b/docs/resources/agent.md @@ -66,32 +66,32 @@ resource "kubernetes_pod" "dev" { ### Required -- `arch` (String) The architecture the agent will run on. Must be one of: "amd64", "armv7", "arm64". -- `os` (String) The operating system the agent will run on. Must be one of: "linux", "darwin", or "windows". +- `arch` (String) The architecture the agent will run on. Must be one of: `"amd64"`, `"armv7"`, `"arm64"`. +- `os` (String) The operating system the agent will run on. Must be one of: `"linux"`, `"darwin"`, or `"windows"`. ### Optional -- `auth` (String) The authentication type the agent will use. Must be one of: "token", "google-instance-identity", "aws-instance-identity", "azure-instance-identity". +- `auth` (String) The authentication type the agent will use. Must be one of: `"token"`, `"google-instance-identity"`, `"aws-instance-identity"`, `"azure-instance-identity"`. - `connection_timeout` (Number) Time in seconds until the agent is marked as timed out when a connection with the server cannot be established. A value of zero never marks the agent as timed out. -- `dir` (String) The starting directory when a user creates a shell session. Defaults to $HOME. +- `dir` (String) The starting directory when a user creates a shell session. Defaults to `"$HOME"`. - `display_apps` (Block Set, Max: 1) The list of built-in apps to display in the agent bar. (see [below for nested schema](#nestedblock--display_apps)) - `env` (Map of String) A mapping of environment variables to set inside the workspace. -- `login_before_ready` (Boolean, Deprecated: Configure startup_script_behavior instead. This attribute will be removed in a future version of the provider.) This option defines whether or not the user can (by default) login to the workspace before it is ready. Ready means that e.g. the startup_script is done and has exited. When enabled, users may see an incomplete workspace when logging in. -- `metadata` (Block List) Each "metadata" block defines a single item consisting of a key/value pair. This feature is in alpha and may break in future releases. (see [below for nested schema](#nestedblock--metadata)) -- `motd_file` (String) The path to a file within the workspace containing a message to display to users when they login via SSH. A typical value would be /etc/motd. +- `login_before_ready` (Boolean, **Deprecated**: Configure `startup_script_behavior` instead. This attribute will be removed in a future version of the provider.) This option defines whether or not the user can (by default) login to the workspace before it is ready. Ready means that e.g. the `startup_script` is done and has exited. When enabled, users may see an incomplete workspace when logging in. +- `metadata` (Block List) Each `metadata` block defines a single item consisting of a key/value pair. This feature is in alpha and may break in future releases. (see [below for nested schema](#nestedblock--metadata)) +- `motd_file` (String) The path to a file within the workspace containing a message to display to users when they login via SSH. A typical value would be `"/etc/motd"`. - `order` (Number) The order determines the position of agents in the UI presentation. The lowest order is shown first and agents with equal order are sorted by name (ascending order). -- `shutdown_script` (String) A script to run before the agent is stopped. The script should exit when it is done to signal that the workspace can be stopped. This option is an alias for defining a "coder_script" resource with "run_on_stop" set to true. -- `shutdown_script_timeout` (Number, Deprecated: This feature is deprecated and has no effect. This attribute will be removed in a future version of the provider.) Time in seconds until the agent lifecycle status is marked as timed out during shutdown, this happens when the shutdown script has not completed (exited) in the given time. -- `startup_script` (String) A script to run after the agent starts. The script should exit when it is done to signal that the agent is ready. This option is an alias for defining a "coder_script" resource with "run_on_start" set to true. -- `startup_script_behavior` (String) This option sets the behavior of the "startup_script". When set to "blocking", the startup_script must exit before the workspace is ready. When set to "non-blocking", the startup_script may run in the background and the workspace will be ready immediately. Default is "non-blocking", although "blocking" is recommended. This option is an alias for defining a "coder_script" resource with "start_blocks_login" set to true (blocking). -- `startup_script_timeout` (Number, Deprecated: This feature is deprecated and has no effect. This attribute will be removed in a future version of the provider.) Time in seconds until the agent lifecycle status is marked as timed out during start, this happens when the startup script has not completed (exited) in the given time. +- `shutdown_script` (String) A script to run before the agent is stopped. The script should exit when it is done to signal that the workspace can be stopped. This option is an alias for defining a `coder_script` resource with `run_on_stop` set to `true`. +- `shutdown_script_timeout` (Number, **Deprecated**: This feature is deprecated and has no effect. This attribute will be removed in a future version of the provider.) Time in seconds until the agent lifecycle status is marked as timed out during shutdown, this happens when the shutdown script has not completed (exited) in the given time. +- `startup_script` (String) A script to run after the agent starts. The script should exit when it is done to signal that the agent is ready. This option is an alias for defining a `coder_script` resource with `run_on_start` set to `true`. +- `startup_script_behavior` (String) This option sets the behavior of the `startup_script`. When set to `"blocking"`, the `startup_script` must exit before the workspace is ready. When set to `"non-blocking"`, the `startup_script` may run in the background and the workspace will be ready immediately. Default is `"non-blocking"`, although `"blocking"` is recommended. This option is an alias for defining a `coder_script` resource with `start_blocks_login` set to `true` (blocking). +- `startup_script_timeout` (Number, **Deprecated**: This feature is deprecated and has no effect. This attribute will be removed in a future version of the provider.) Time in seconds until the agent lifecycle status is marked as timed out during start, this happens when the startup script has not completed (exited) in the given time. - `troubleshooting_url` (String) A URL to a document with instructions for troubleshooting problems with the agent. ### Read-Only - `id` (String) The ID of this resource. - `init_script` (String) Run this script on startup of an instance to initialize the agent. -- `token` (String, Sensitive) Set the environment variable "CODER_AGENT_TOKEN" with this token to authenticate an agent. +- `token` (String, Sensitive) Set the environment variable `CODER_AGENT_TOKEN` with this token to authenticate an agent. ### Nested Schema for `display_apps` diff --git a/docs/resources/agent_instance.md b/docs/resources/agent_instance.md index 6af2bb46..ec855b12 100644 --- a/docs/resources/agent_instance.md +++ b/docs/resources/agent_instance.md @@ -8,7 +8,7 @@ description: |- # coder_agent_instance (Resource) -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. ## Example Usage @@ -34,7 +34,7 @@ resource "coder_agent_instance" "dev" { ### Required -- `agent_id` (String) The "id" property of a "coder_agent" resource to associate with. +- `agent_id` (String) The `id` property of a `coder_agent` resource to associate with. - `instance_id` (String) The instance identifier of a provisioned resource. ### Read-Only diff --git a/docs/resources/app.md b/docs/resources/app.md index e9ca7b2f..f61ed799 100644 --- a/docs/resources/app.md +++ b/docs/resources/app.md @@ -54,22 +54,22 @@ resource "coder_app" "vim" { ### Required -- `agent_id` (String) The "id" property of a "coder_agent" resource to associate with. +- `agent_id` (String) The `id` property of a `coder_agent` resource to associate with. - `slug` (String) A hostname-friendly name for the app. This is used in URLs to access the app. May contain alphanumerics and hyphens. Cannot start/end with a hyphen or contain two consecutive hyphens. ### Optional -- `command` (String) A command to run in a terminal opening this app. In the web, this will open in a new tab. In the CLI, this will SSH and execute the command. Either "command" or "url" may be specified, but not both. +- `command` (String) A command to run in a terminal opening this app. In the web, this will open in a new tab. In the CLI, this will SSH and execute the command. Either `command` or `url` may be specified, but not both. - `display_name` (String) A display name to identify the app. Defaults to the slug. -- `external` (Boolean) Specifies whether "url" is opened on the client machine instead of proxied through the workspace. +- `external` (Boolean) Specifies whether `url` is opened on the client machine instead of proxied through the workspace. - `healthcheck` (Block Set, Max: 1) HTTP health checking to determine the application readiness. (see [below for nested schema](#nestedblock--healthcheck)) -- `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons here: https://github.com/coder/coder/tree/main/site/static/icon. Use a built-in icon with `data.coder_workspace.me.access_url + "/icon/"`. -- `name` (String, Deprecated: `name` on apps is deprecated, use `display_name` instead) A display name to identify the app. +- `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons here: https://github.com/coder/coder/tree/main/site/static/icon. Use a built-in icon with `"${data.coder_workspace.me.access_url}/icon/"`. +- `name` (String, **Deprecated**: `name` on apps is deprecated, use `display_name` instead) A display name to identify the app. - `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). -- `relative_path` (Boolean, Deprecated: `relative_path` on apps is deprecated, use `subdomain` instead.) Specifies whether the URL will be accessed via a relative path or wildcard. Use if wildcard routing is unavailable. Defaults to true. -- `share` (String) Determines the "level" which the application is shared at. Valid levels are "owner" (default), "authenticated" and "public". Level "owner" disables sharing on the app, so only the workspace owner can access it. Level "authenticated" shares the app with all authenticated users. Level "public" shares it with any user, including unauthenticated users. Permitted application sharing levels can be configured site-wide via a flag on `coder server` (Enterprise only). -- `subdomain` (Boolean) Determines whether the app will be accessed via it's own subdomain or whether it will be accessed via a path on Coder. If wildcards have not been setup by the administrator then apps with "subdomain" set to true will not be accessible. Defaults to false. -- `url` (String) An external url if "external=true" or a URL to be proxied to from inside the workspace. This should be of the form "http://localhost:PORT[/SUBPATH]". Either "command" or "url" may be specified, but not both. +- `relative_path` (Boolean, **Deprecated**: `relative_path` on apps is deprecated, use `subdomain` instead.) Specifies whether the URL will be accessed via a relative path or wildcard. Use if wildcard routing is unavailable. Defaults to `true`. +- `share` (String) Determines the level which the application is shared at. Valid levels are `"owner"` (default), `"authenticated"` and `"public"`. Level `"owner"` disables sharing on the app, so only the workspace owner can access it. Level `"authenticated"` shares the app with all authenticated users. Level `"public"` shares it with any user, including unauthenticated users. Permitted application sharing levels can be configured site-wide via a flag on `coder server` (Enterprise only). +- `subdomain` (Boolean) Determines whether the app will be accessed via it's own subdomain or whether it will be accessed via a path on Coder. If wildcards have not been setup by the administrator then apps with `subdomain` set to `true` will not be accessible. Defaults to `false`. +- `url` (String) An external url if `external=true` or a URL to be proxied to from inside the workspace. This should be of the form `http://localhost:PORT[/SUBPATH]`. Either `command` or `url` may be specified, but not both. ### Read-Only @@ -82,4 +82,4 @@ Required: - `interval` (Number) Duration in seconds to wait between healthcheck requests. - `threshold` (Number) Number of consecutive heathcheck failures before returning an unhealthy status. -- `url` (String) HTTP address used determine the application readiness. A successful health check is a HTTP response code less than 500 returned before healthcheck.interval seconds. +- `url` (String) HTTP address used determine the application readiness. A successful health check is a HTTP response code less than 500 returned before `healthcheck.interval` seconds. diff --git a/docs/resources/env.md b/docs/resources/env.md index 3531335c..3a5a7f3a 100644 --- a/docs/resources/env.md +++ b/docs/resources/env.md @@ -3,12 +3,12 @@ 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) -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. ## Example Usage @@ -39,7 +39,7 @@ resource "coder_env" "internal_api_url" { ### Required -- `agent_id` (String) The "id" property of a "coder_agent" resource to associate with. +- `agent_id` (String) The `id` property of a `coder_agent` resource to associate with. - `name` (String) The name of the environment variable. ### Optional diff --git a/docs/resources/metadata.md b/docs/resources/metadata.md index 9d6ff92f..f739db14 100644 --- a/docs/resources/metadata.md +++ b/docs/resources/metadata.md @@ -59,14 +59,14 @@ resource "coder_metadata" "pod_info" { ### Required -- `resource_id` (String) The "id" property of another resource that metadata should be attached to. +- `resource_id` (String) The `id` property of another resource that metadata should be attached to. ### Optional - `daily_cost` (Number) (Enterprise) The cost of this resource every 24 hours. Use the smallest denomination of your preferred currency. For example, if you work in USD, use cents. - `hide` (Boolean) Hide the resource from the UI. -- `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons here: https://github.com/coder/coder/tree/main/site/static/icon. Use a built-in icon with `data.coder_workspace.me.access_url + "/icon/"`. -- `item` (Block List) Each "item" block defines a single metadata item consisting of a key/value pair. (see [below for nested schema](#nestedblock--item)) +- `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons [here](https://github.com/coder/coder/tree/main/site/static/icon). Use a built-in icon with `"${data.coder_workspace.me.access_url}/icon/"`. +- `item` (Block List) Each `item` block defines a single metadata item consisting of a key/value pair. (see [below for nested schema](#nestedblock--item)) ### Read-Only @@ -81,7 +81,7 @@ Required: Optional: -- `sensitive` (Boolean) Set to "true" to for items such as API keys whose values should be hidden from view by default. Note that this does not prevent metadata from being retrieved using the API, so it is not suitable for secrets that should not be exposed to workspace users. +- `sensitive` (Boolean) Set to `true` to for items such as API keys whose values should be hidden from view by default. Note that this does not prevent metadata from being retrieved using the API, so it is not suitable for secrets that should not be exposed to workspace users. - `value` (String) The value of this metadata item. Read-Only: diff --git a/docs/resources/script.md b/docs/resources/script.md index d4d5dd9f..22ac1b50 100644 --- a/docs/resources/script.md +++ b/docs/resources/script.md @@ -72,14 +72,14 @@ resource "coder_script" "shutdown" { ### Required -- `agent_id` (String) The "id" property of a "coder_agent" resource to associate with. +- `agent_id` (String) The `id` property of a `coder_agent` resource to associate with. - `display_name` (String) The display name of the script to display logs in the dashboard. - `script` (String) The content of the script that will be run. ### Optional - `cron` (String) The cron schedule to run the script on. This is a cron expression. -- `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons here: https://github.com/coder/coder/tree/main/site/static/icon. Use a built-in icon with `data.coder_workspace.me.access_url + "/icon/"`. +- `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons [here](https://github.com/coder/coder/tree/main/site/static/icon). Use a built-in icon with `"${data.coder_workspace.me.access_url}/icon/"`. - `log_path` (String) The path of a file to write the logs to. If relative, it will be appended to tmp. - `run_on_start` (Boolean) This option defines whether or not the script should run when the agent starts. The script should exit when it is done to signal that the agent is ready. - `run_on_stop` (Boolean) This option defines whether or not the script should run when the agent stops. The script should exit when it is done to signal that the workspace can be stopped. diff --git a/provider/agent.go b/provider/agent.go index 0ff5ca21..352dd5d9 100644 --- a/provider/agent.go +++ b/provider/agent.go @@ -92,7 +92,7 @@ func agentResource() *schema.Resource { Type: schema.TypeString, ForceNew: true, Required: true, - Description: `The architecture the agent will run on. Must be one of: "amd64", "armv7", "arm64".`, + Description: "The architecture the agent will run on. Must be one of: `\"amd64\"`, `\"armv7\"`, `\"arm64\"`.", ValidateFunc: validation.StringInSlice([]string{"amd64", "armv7", "arm64"}, false), }, "auth": { @@ -100,14 +100,14 @@ func agentResource() *schema.Resource { Default: "token", ForceNew: true, Optional: true, - Description: `The authentication type the agent will use. Must be one of: "token", "google-instance-identity", "aws-instance-identity", "azure-instance-identity".`, + Description: "The authentication type the agent will use. Must be one of: `\"token\"`, `\"google-instance-identity\"`, `\"aws-instance-identity\"`, `\"azure-instance-identity\"`.", ValidateFunc: validation.StringInSlice([]string{"token", "google-instance-identity", "aws-instance-identity", "azure-instance-identity"}, false), }, "dir": { Type: schema.TypeString, ForceNew: true, Optional: true, - Description: "The starting directory when a user creates a shell session. Defaults to $HOME.", + Description: "The starting directory when a user creates a shell session. Defaults to `\"$HOME\"`.", }, "env": { ForceNew: true, @@ -119,12 +119,12 @@ func agentResource() *schema.Resource { Type: schema.TypeString, ForceNew: true, Required: true, - Description: `The operating system the agent will run on. Must be one of: "linux", "darwin", or "windows".`, + Description: "The operating system the agent will run on. Must be one of: `\"linux\"`, `\"darwin\"`, or `\"windows\"`.", ValidateFunc: validation.StringInSlice([]string{"linux", "darwin", "windows"}, false), }, "startup_script": { ForceNew: true, - Description: `A script to run after the agent starts. The script should exit when it is done to signal that the agent is ready. This option is an alias for defining a "coder_script" resource with "run_on_start" set to true.`, + Description: "A script to run after the agent starts. The script should exit when it is done to signal that the agent is ready. This option is an alias for defining a `coder_script` resource with `run_on_start` set to `true`.", Type: schema.TypeString, Optional: true, }, @@ -141,7 +141,7 @@ func agentResource() *schema.Resource { Type: schema.TypeString, ForceNew: true, Optional: true, - Description: `A script to run before the agent is stopped. The script should exit when it is done to signal that the workspace can be stopped. This option is an alias for defining a "coder_script" resource with "run_on_stop" set to true.`, + Description: "A script to run before the agent is stopped. The script should exit when it is done to signal that the workspace can be stopped. This option is an alias for defining a `coder_script` resource with `run_on_stop` set to `true`.", }, "shutdown_script_timeout": { Type: schema.TypeInt, @@ -155,7 +155,7 @@ func agentResource() *schema.Resource { "token": { ForceNew: true, Sensitive: true, - Description: `Set the environment variable "CODER_AGENT_TOKEN" with this token to authenticate an agent.`, + Description: "Set the environment variable `CODER_AGENT_TOKEN` with this token to authenticate an agent.", Type: schema.TypeString, Computed: true, }, @@ -177,7 +177,7 @@ func agentResource() *schema.Resource { Type: schema.TypeString, ForceNew: true, Optional: true, - Description: "The path to a file within the workspace containing a message to display to users when they login via SSH. A typical value would be /etc/motd.", + Description: "The path to a file within the workspace containing a message to display to users when they login via SSH. A typical value would be `\"/etc/motd\"`.", }, "login_before_ready": { // Note: When this is removed, "startup_script_behavior" should @@ -186,8 +186,8 @@ func agentResource() *schema.Resource { Default: true, ForceNew: true, Optional: true, - Description: "This option defines whether or not the user can (by default) login to the workspace before it is ready. Ready means that e.g. the startup_script is done and has exited. When enabled, users may see an incomplete workspace when logging in.", - Deprecated: "Configure startup_script_behavior instead. This attribute will be removed in a future version of the provider.", + Description: "This option defines whether or not the user can (by default) login to the workspace before it is ready. Ready means that e.g. the `startup_script` is done and has exited. When enabled, users may see an incomplete workspace when logging in.", + Deprecated: "Configure `startup_script_behavior` instead. This attribute will be removed in a future version of the provider.", ConflictsWith: []string{"startup_script_behavior"}, }, "startup_script_behavior": { @@ -200,13 +200,13 @@ func agentResource() *schema.Resource { Type: schema.TypeString, ForceNew: true, Optional: true, - Description: `This option sets the behavior of the "startup_script". When set to "blocking", the startup_script must exit before the workspace is ready. When set to "non-blocking", the startup_script may run in the background and the workspace will be ready immediately. Default is "non-blocking", although "blocking" is recommended. This option is an alias for defining a "coder_script" resource with "start_blocks_login" set to true (blocking).`, + Description: "This option sets the behavior of the `startup_script`. When set to `\"blocking\"`, the `startup_script` must exit before the workspace is ready. When set to `\"non-blocking\"`, the `startup_script` may run in the background and the workspace will be ready immediately. Default is `\"non-blocking\"`, although `\"blocking\"` is recommended. This option is an alias for defining a `coder_script` resource with `start_blocks_login` set to `true` (blocking).", ValidateFunc: validation.StringInSlice([]string{"blocking", "non-blocking"}, false), ConflictsWith: []string{"login_before_ready"}, }, "metadata": { Type: schema.TypeList, - Description: "Each \"metadata\" block defines a single item consisting of a key/value pair. This feature is in alpha and may break in future releases.", + Description: "Each `metadata` block defines a single item consisting of a key/value pair. This feature is in alpha and may break in future releases.", ForceNew: true, Optional: true, Elem: &schema.Resource{ @@ -313,9 +313,9 @@ func agentResource() *schema.Resource { func agentInstanceResource() *schema.Resource { return &schema.Resource{ 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.", + "authentication. This association is done automatically for `\"google_compute_instance\"`, " + + "`\"aws_instance\"`, `\"azurerm_linux_virtual_machine\"`, and " + + "`\"azurerm_windows_virtual_machine\"` resources.", CreateContext: func(c context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { resourceData.SetId(uuid.NewString()) return nil @@ -329,14 +329,14 @@ func agentInstanceResource() *schema.Resource { Schema: map[string]*schema.Schema{ "agent_id": { Type: schema.TypeString, - Description: `The "id" property of a "coder_agent" resource to associate with.`, + Description: "The `id` property of a `coder_agent` resource to associate with.", ForceNew: true, Required: true, }, "instance_id": { ForceNew: true, Required: true, - Description: `The instance identifier of a provisioned resource.`, + Description: "The instance identifier of a provisioned resource.", Type: schema.TypeString, }, }, diff --git a/provider/app.go b/provider/app.go index c2690311..91c08f0f 100644 --- a/provider/app.go +++ b/provider/app.go @@ -41,7 +41,7 @@ func appResource() *schema.Resource { Schema: map[string]*schema.Schema{ "agent_id": { Type: schema.TypeString, - Description: `The "id" property of a "coder_agent" resource to associate with.`, + Description: "The `id` property of a `coder_agent` resource to associate with.", ForceNew: true, Required: true, }, @@ -49,7 +49,7 @@ func appResource() *schema.Resource { Type: schema.TypeString, Description: "A command to run in a terminal opening this app. In the web, " + "this will open in a new tab. In the CLI, this will SSH and execute the command. " + - "Either \"command\" or \"url\" may be specified, but not both.", + "Either `command` or `url` may be specified, but not both.", ConflictsWith: []string{"url"}, Optional: true, ForceNew: true, @@ -58,7 +58,7 @@ func appResource() *schema.Resource { Type: schema.TypeString, Description: "A URL to an icon that will display in the dashboard. View built-in " + "icons here: https://github.com/coder/coder/tree/main/site/static/icon. Use a " + - "built-in icon with `data.coder_workspace.me.access_url + \"/icon/\"`.", + "built-in icon with `\"${data.coder_workspace.me.access_url}/icon/\"`.", ForceNew: true, Optional: true, ValidateFunc: func(i interface{}, s string) ([]string, []error) { @@ -84,7 +84,7 @@ func appResource() *schema.Resource { } if !appSlugRegex.MatchString(valStr) { - return diag.Errorf("invalid coder_app slug, must be a valid hostname (%q, cannot contain two consecutive hyphens or start/end with a hyphen): %q", appSlugRegex.String(), valStr) + return diag.Errorf(`invalid "coder_app" slug, must be a valid hostname (%q, cannot contain two consecutive hyphens or start/end with a hyphen): %q`, appSlugRegex.String(), valStr) } return nil @@ -109,7 +109,7 @@ func appResource() *schema.Resource { Description: "Determines whether the app will be accessed via it's own " + "subdomain or whether it will be accessed via a path on Coder. If " + "wildcards have not been setup by the administrator then apps with " + - "\"subdomain\" set to true will not be accessible. Defaults to false.", + "`subdomain` set to `true` will not be accessible. Defaults to `false`.", ForceNew: true, Optional: true, }, @@ -117,19 +117,19 @@ func appResource() *schema.Resource { Type: schema.TypeBool, Deprecated: "`relative_path` on apps is deprecated, use `subdomain` instead.", Description: "Specifies whether the URL will be accessed via a relative " + - "path or wildcard. Use if wildcard routing is unavailable. Defaults to true.", + "path or wildcard. Use if wildcard routing is unavailable. Defaults to `true`.", ForceNew: true, Optional: true, ConflictsWith: []string{"subdomain"}, }, "share": { Type: schema.TypeString, - Description: `Determines the "level" which the application ` + - `is shared at. Valid levels are "owner" (default), ` + - `"authenticated" and "public". Level "owner" disables ` + + Description: "Determines the level which the application " + + "is shared at. Valid levels are `\"owner\"` (default), " + + "`\"authenticated\"` and `\"public\"`. Level `\"owner\"` disables " + "sharing on the app, so only the workspace owner can " + - `access it. Level "authenticated" shares the app with ` + - `all authenticated users. Level "public" shares it with ` + + "access it. Level `\"authenticated\"` shares the app with " + + "all authenticated users. Level `\"public\"` shares it with " + "any user, including unauthenticated users. Permitted " + "application sharing levels can be configured site-wide " + "via a flag on `coder server` (Enterprise only).", @@ -147,21 +147,21 @@ func appResource() *schema.Resource { return nil } - return diag.Errorf(`invalid app share %q, must be one of "owner", "authenticated", "public"`, valStr) + return diag.Errorf("invalid app share %q, must be one of \"owner\", \"authenticated\", \"public\"", valStr) }, }, "url": { Type: schema.TypeString, - Description: "An external url if \"external=true\" or a URL to be proxied to from inside the workspace. " + - "This should be of the form \"http://localhost:PORT[/SUBPATH]\". " + - "Either \"command\" or \"url\" may be specified, but not both.", + Description: "An external url if `external=true` or a URL to be proxied to from inside the workspace. " + + "This should be of the form `http://localhost:PORT[/SUBPATH]`. " + + "Either `command` or `url` may be specified, but not both.", ForceNew: true, Optional: true, ConflictsWith: []string{"command"}, }, "external": { Type: schema.TypeBool, - Description: "Specifies whether \"url\" is opened on the client machine " + + Description: "Specifies whether `url` is opened on the client machine " + "instead of proxied through the workspace.", Default: false, ForceNew: true, @@ -179,7 +179,7 @@ func appResource() *schema.Resource { Schema: map[string]*schema.Schema{ "url": { Type: schema.TypeString, - Description: "HTTP address used determine the application readiness. A successful health check is a HTTP response code less than 500 returned before healthcheck.interval seconds.", + Description: "HTTP address used determine the application readiness. A successful health check is a HTTP response code less than 500 returned before `healthcheck.interval` seconds.", ForceNew: true, Required: true, }, diff --git a/provider/env.go b/provider/env.go index 8f55ff8c..d45201ee 100644 --- a/provider/env.go +++ b/provider/env.go @@ -14,7 +14,7 @@ func envResource() *schema.Resource { return &schema.Resource{ SchemaVersion: 1, - 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.`, + 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.", CreateContext: func(_ context.Context, rd *schema.ResourceData, _ interface{}) diag.Diagnostics { rd.SetId(uuid.NewString()) @@ -25,7 +25,7 @@ func envResource() *schema.Resource { Schema: map[string]*schema.Schema{ "agent_id": { Type: schema.TypeString, - Description: `The "id" property of a "coder_agent" resource to associate with.`, + Description: "The `id` property of a `coder_agent` resource to associate with.", ForceNew: true, Required: true, }, diff --git a/provider/gitauth.go b/provider/gitauth.go index 72c05bcd..e8230ade 100644 --- a/provider/gitauth.go +++ b/provider/gitauth.go @@ -16,7 +16,7 @@ func gitAuthDataSource() *schema.Resource { SchemaVersion: 1, DeprecationMessage: "Use the `coder_external_auth` data source instead.", - Description: "Use this data source to require users to authenticate with a Git provider prior to workspace creation. This can be used to perform an authenticated `git clone` in startup scripts.", + Description: "~> **Deprecated**\nUse the `coder_external_auth` data source instead.\n\nUse this data source to require users to authenticate with a Git provider prior to workspace creation. This can be used to perform an authenticated `git clone` in startup scripts.", ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { rawID, ok := rd.GetOk("id") if !ok { diff --git a/provider/metadata.go b/provider/metadata.go index 00b488e4..abfe0a05 100644 --- a/provider/metadata.go +++ b/provider/metadata.go @@ -38,7 +38,7 @@ func metadataResource() *schema.Resource { Schema: map[string]*schema.Schema{ "resource_id": { Type: schema.TypeString, - Description: "The \"id\" property of another resource that metadata should be attached to.", + Description: "The `id` property of another resource that metadata should be attached to.", ForceNew: true, Required: true, }, @@ -51,8 +51,8 @@ func metadataResource() *schema.Resource { "icon": { Type: schema.TypeString, Description: "A URL to an icon that will display in the dashboard. View built-in " + - "icons here: https://github.com/coder/coder/tree/main/site/static/icon. Use a " + - "built-in icon with `data.coder_workspace.me.access_url + \"/icon/\"`.", + "icons [here](https://github.com/coder/coder/tree/main/site/static/icon). Use a " + + "built-in icon with `\"${data.coder_workspace.me.access_url}/icon/\"`.", ForceNew: true, Optional: true, ValidateFunc: func(i interface{}, s string) ([]string, []error) { @@ -73,7 +73,7 @@ func metadataResource() *schema.Resource { }, "item": { Type: schema.TypeList, - Description: "Each \"item\" block defines a single metadata item consisting of a key/value pair.", + Description: "Each `item` block defines a single metadata item consisting of a key/value pair.", ForceNew: true, Optional: true, Elem: &schema.Resource{ @@ -92,7 +92,7 @@ func metadataResource() *schema.Resource { }, "sensitive": { Type: schema.TypeBool, - Description: "Set to \"true\" to for items such as API keys whose values should be " + + Description: "Set to `true` to for items such as API keys whose values should be " + "hidden from view by default. Note that this does not prevent metadata from " + "being retrieved using the API, so it is not suitable for secrets that should " + "not be exposed to workspace users.", diff --git a/provider/parameter.go b/provider/parameter.go index 281537f6..00dd5f34 100644 --- a/provider/parameter.go +++ b/provider/parameter.go @@ -204,7 +204,7 @@ func parameterDataSource() *schema.Resource { Default: "string", Optional: true, ValidateFunc: validation.StringInSlice([]string{"number", "string", "bool", "list(string)"}, false), - Description: `The type of this parameter. Must be one of: "number", "string", "bool", or "list(string)".`, + Description: "The type of this parameter. Must be one of: `\"number\"`, `\"string\"`, `\"bool\"`, or `\"list(string)\"`.", }, "mutable": { Type: schema.TypeBool, @@ -221,7 +221,7 @@ func parameterDataSource() *schema.Resource { Type: schema.TypeString, Description: "A URL to an icon that will display in the dashboard. View built-in " + "icons [here](https://github.com/coder/coder/tree/main/site/static/icon). Use a " + - "built-in icon with `data.coder_workspace.me.access_url + \"/icon/\"`.", + "built-in icon with `\"${data.coder_workspace.me.access_url}/icon/\"`.", ForceNew: true, Optional: true, ValidateFunc: func(i interface{}, s string) ([]string, []error) { @@ -234,7 +234,7 @@ func parameterDataSource() *schema.Resource { }, "option": { Type: schema.TypeList, - Description: "Each \"option\" block defines a value for a user to select from.", + Description: "Each `option` block defines a value for a user to select from.", ForceNew: true, Optional: true, MaxItems: 64, @@ -261,8 +261,8 @@ func parameterDataSource() *schema.Resource { "icon": { Type: schema.TypeString, Description: "A URL to an icon that will display in the dashboard. View built-in " + - "icons here: https://github.com/coder/coder/tree/main/site/static/icon. Use a " + - "built-in icon with `data.coder_workspace.me.access_url + \"/icon/\"`.", + "icons [here](https://github.com/coder/coder/tree/main/site/static/icon). Use a " + + "built-in icon with `\"${data.coder_workspace.me.access_url}/icon/\"`.", ForceNew: true, Optional: true, ValidateFunc: func(i interface{}, s string) ([]string, []error) { diff --git a/provider/script.go b/provider/script.go index 536a5732..df436ead 100644 --- a/provider/script.go +++ b/provider/script.go @@ -26,10 +26,10 @@ func scriptResource() *schema.Resource { cron, _ := rd.Get("cron").(string) if !runOnStart && !runOnStop && cron == "" { - return diag.Errorf("at least one of run_on_start, run_on_stop, or cron must be set") + return diag.Errorf(`at least one of "run_on_start", "run_on_stop", or "cron" must be set`) } if !runOnStart && startBlocksLogin { - return diag.Errorf("start_blocks_login can only be set if run_on_start is true") + return diag.Errorf(`"start_blocks_login" can only be set if "run_on_start" is "true"`) } return nil }, @@ -38,7 +38,7 @@ func scriptResource() *schema.Resource { Schema: map[string]*schema.Schema{ "agent_id": { Type: schema.TypeString, - Description: `The "id" property of a "coder_agent" resource to associate with.`, + Description: "The `id` property of a `coder_agent` resource to associate with.", ForceNew: true, Required: true, }, @@ -59,8 +59,8 @@ func scriptResource() *schema.Resource { ForceNew: true, Optional: true, Description: "A URL to an icon that will display in the dashboard. View built-in " + - "icons here: https://github.com/coder/coder/tree/main/site/static/icon. Use a " + - "built-in icon with `data.coder_workspace.me.access_url + \"/icon/\"`.", + "icons [here](https://github.com/coder/coder/tree/main/site/static/icon). Use a " + + "built-in icon with `\"${data.coder_workspace.me.access_url}/icon/\"`.", }, "script": { ForceNew: true, diff --git a/provider/script_test.go b/provider/script_test.go index 937c6008..9b6bd570 100644 --- a/provider/script_test.go +++ b/provider/script_test.go @@ -69,7 +69,7 @@ func TestScriptNeverRuns(t *testing.T) { script = "Wow" } `, - ExpectError: regexp.MustCompile(`at least one of run_on_start, run_on_stop, or cron must be set`), + ExpectError: regexp.MustCompile(`at least one of "run_on_start", "run_on_stop", or "cron" must be set`), }}, }) } @@ -94,7 +94,7 @@ func TestScriptStartBlocksLoginRequiresRunOnStart(t *testing.T) { start_blocks_login = true } `, - ExpectError: regexp.MustCompile(`start_blocks_login can only be set if run_on_start is true`), + ExpectError: regexp.MustCompile(`"start_blocks_login" can only be set if "run_on_start" is "true"`), }}, }) resource.Test(t, resource.TestCase{ diff --git a/provider/workspace.go b/provider/workspace.go index d8bfd3a5..3f667e8f 100644 --- a/provider/workspace.go +++ b/provider/workspace.go @@ -115,12 +115,12 @@ func workspaceDataSource() *schema.Resource { "start_count": { Type: schema.TypeInt, Computed: true, - Description: `A computed count based on "transition" state. If "start", count will equal 1.`, + Description: "A computed count based on `transition` state. If `start`, count will equal 1.", }, "transition": { Type: schema.TypeString, Computed: true, - Description: `Either "start" or "stop". Use this to start/stop resources with "count".`, + Description: "Either `start` or `stop`. Use this to start/stop resources with `count`.", }, "owner": { Type: schema.TypeString, diff --git a/scripts/docsgen/main.go b/scripts/docsgen/main.go index 90244ccd..d83cf123 100644 --- a/scripts/docsgen/main.go +++ b/scripts/docsgen/main.go @@ -84,6 +84,6 @@ func writeDeprecationMessage(doc []byte, schemas map[string]*schema.Schema) []by log.Printf("warn: same property name `%s` but description does not match, most likely a different property", propertyName) return m } - return bytes.Replace(m, []byte("Deprecated"), []byte(fmt.Sprintf("Deprecated: %s", sch.Deprecated)), 1) + return bytes.Replace(m, []byte("Deprecated"), []byte(fmt.Sprintf("**Deprecated**: %s", sch.Deprecated)), 1) }) } From 3022367b60b7d7c535101798ce17270832552fd6 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 5 Jul 2024 11:40:20 +0300 Subject: [PATCH 02/10] ci: drop terraform versions < 1.5.x, add 1.9.x for tests (#258) --- .github/workflows/test.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f17d1c10..57faf626 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -64,15 +64,11 @@ jobs: fail-fast: false matrix: terraform: - - "1.0.*" - - "1.1.*" - - "1.2.*" - - "1.3.*" - - "1.4.*" - "1.5.*" - "1.6.*" - "1.7.*" - "1.8.*" + - "1.9.*" steps: - name: Set up Go uses: actions/setup-go@v5 @@ -112,7 +108,7 @@ jobs: - uses: hashicorp/setup-terraform@v3 with: - terraform_version: "1.3.*" + terraform_version: "latest" terraform_wrapper: false - name: Check out code into the Go module directory From 7ed088d0942fc4b24cf26c3e031a15618667f3c0 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 5 Jul 2024 11:40:47 +0300 Subject: [PATCH 03/10] chore!: remove deprecated items from `coder_workspace` data source (#255) --- docs/data-sources/workspace.md | 53 ++++++++++--- docs/data-sources/workspace_owner.md | 6 +- .../coder_workspace/data-source.tf | 46 ++++++++++- .../coder_workspace_owner/data-source.tf | 6 +- integration/integration_test.go | 38 +++------- integration/test-data-source/main.tf | 10 +-- integration/workspace-owner/main.tf | 10 +-- provider/workspace.go | 76 ------------------- provider/workspace_test.go | 29 +------ 9 files changed, 107 insertions(+), 167 deletions(-) diff --git a/docs/data-sources/workspace.md b/docs/data-sources/workspace.md index 8b824c37..26396ba1 100644 --- a/docs/data-sources/workspace.md +++ b/docs/data-sources/workspace.md @@ -13,11 +13,51 @@ Use this data source to get information for the active workspace build. ## Example Usage ```terraform -data "coder_workspace" "dev" { +provider "coder" {} + +provider "docker" {} + +data "coder_workspace" "me" {} + +data "coder_workspace_owner" "me" {} + +resource "coder_agent" "dev" { + arch = "amd64" + os = "linux" + dir = "/workspace" } -resource "kubernetes_pod" "dev" { - count = data.coder_workspace.dev.transition == "start" ? 1 : 0 +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 + } } ``` @@ -30,13 +70,6 @@ resource "kubernetes_pod" "dev" { - `access_url` (String) The access URL of the Coder deployment provisioning this workspace. - `id` (String) UUID of the workspace. - `name` (String) Name of the workspace. -- `owner` (String, **Deprecated**: Use `coder_workspace_owner.name` instead.) Username of the workspace owner. -- `owner_email` (String, **Deprecated**: Use `coder_workspace_owner.email` instead.) Email address of the workspace owner. -- `owner_groups` (List of String, **Deprecated**: Use `coder_workspace_owner.groups` instead.) List of groups the workspace owner belongs to. -- `owner_id` (String, **Deprecated**: Use `coder_workspace_owner.id` instead.) UUID of the workspace owner. -- `owner_name` (String, **Deprecated**: Use `coder_workspace_owner.full_name` instead.) Name of the workspace owner. -- `owner_oidc_access_token` (String, **Deprecated**: Use `coder_workspace_owner.oidc_access_token` instead.) A valid OpenID Connect access token of the workspace owner. This is only available if the workspace owner authenticated with OpenID Connect. If a valid token cannot be obtained, this value will be an empty string. -- `owner_session_token` (String, **Deprecated**: Use `coder_workspace_owner.session_token` instead.) Session token for authenticating with a Coder deployment. It is regenerated everytime a workspace is started. - `start_count` (Number) A computed count based on `transition` state. If `start`, count will equal 1. - `template_id` (String) ID of the workspace's template. - `template_name` (String) Name of the workspace's template. diff --git a/docs/data-sources/workspace_owner.md b/docs/data-sources/workspace_owner.md index 0deff622..1c64ea50 100644 --- a/docs/data-sources/workspace_owner.md +++ b/docs/data-sources/workspace_owner.md @@ -15,14 +15,12 @@ Use this data source to fetch information about the workspace owner. ```terraform provider "coder" {} -data "coder_workspace" "me" {} - data "coder_workspace_owner" "me" {} resource "coder_agent" "dev" { arch = "amd64" os = "linux" - dir = local.repo_dir + dir = "/workspace" env = { OIDC_TOKEN : data.coder_workspace_owner.me.oidc_access_token, } @@ -36,7 +34,7 @@ resource "coder_env" "git_author_name" { } resource "coder_env" "git_author_email" { - agent_id = var.agent_id + 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/examples/data-sources/coder_workspace/data-source.tf b/examples/data-sources/coder_workspace/data-source.tf index 4898439b..8eb4a8f8 100644 --- a/examples/data-sources/coder_workspace/data-source.tf +++ b/examples/data-sources/coder_workspace/data-source.tf @@ -1,6 +1,46 @@ -data "coder_workspace" "dev" { +provider "coder" {} + +provider "docker" {} + +data "coder_workspace" "me" {} + +data "coder_workspace_owner" "me" {} + +resource "coder_agent" "dev" { + arch = "amd64" + os = "linux" + dir = "/workspace" } -resource "kubernetes_pod" "dev" { - count = data.coder_workspace.dev.transition == "start" ? 1 : 0 +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 + } } diff --git a/examples/data-sources/coder_workspace_owner/data-source.tf b/examples/data-sources/coder_workspace_owner/data-source.tf index fc27db6c..cad73e1e 100644 --- a/examples/data-sources/coder_workspace_owner/data-source.tf +++ b/examples/data-sources/coder_workspace_owner/data-source.tf @@ -1,13 +1,11 @@ provider "coder" {} -data "coder_workspace" "me" {} - data "coder_workspace_owner" "me" {} resource "coder_agent" "dev" { arch = "amd64" os = "linux" - dir = local.repo_dir + dir = "/workspace" env = { OIDC_TOKEN : data.coder_workspace_owner.me.oidc_access_token, } @@ -21,7 +19,7 @@ resource "coder_env" "git_author_name" { } resource "coder_env" "git_author_email" { - agent_id = var.agent_id + 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/integration/integration_test.go b/integration/integration_test.go index 75b35d20..8208d20a 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -71,25 +71,18 @@ func TestIntegration(t *testing.T) { name: "test-data-source", minVersion: "v0.0.0", expectedOutput: map[string]string{ - "provisioner.arch": runtime.GOARCH, - "provisioner.id": `[a-zA-Z0-9-]+`, - "provisioner.os": runtime.GOOS, - "workspace.access_port": `\d+`, - "workspace.access_url": `https?://\D+:\d+`, - "workspace.id": `[a-zA-z0-9-]+`, - "workspace.name": `test-data-source`, - "workspace.owner": `testing`, - "workspace.owner_email": `testing@coder\.com`, - "workspace.owner_groups": `\[\]`, - "workspace.owner_id": `[a-zA-Z0-9]+`, - "workspace.owner_name": `default`, - "workspace.owner_oidc_access_token": `^$`, // TODO: need a test OIDC integration - "workspace.owner_session_token": `[a-zA-Z0-9-]+`, - "workspace.start_count": `1`, - "workspace.template_id": `[a-zA-Z0-9-]+`, - "workspace.template_name": `test-data-source`, - "workspace.template_version": `.+`, - "workspace.transition": `start`, + "provisioner.arch": runtime.GOARCH, + "provisioner.id": `[a-zA-Z0-9-]+`, + "provisioner.os": runtime.GOOS, + "workspace.access_port": `\d+`, + "workspace.access_url": `https?://\D+:\d+`, + "workspace.id": `[a-zA-z0-9-]+`, + "workspace.name": `test-data-source`, + "workspace.start_count": `1`, + "workspace.template_id": `[a-zA-Z0-9-]+`, + "workspace.template_name": `test-data-source`, + "workspace.template_version": `.+`, + "workspace.transition": `start`, }, }, { @@ -103,13 +96,6 @@ func TestIntegration(t *testing.T) { "workspace.access_url": `https?://\D+:\d+`, "workspace.id": `[a-zA-z0-9-]+`, "workspace.name": ``, - "workspace.owner": `testing`, - "workspace.owner_email": `testing@coder\.com`, - "workspace.owner_groups": `\[\]`, - "workspace.owner_id": `[a-zA-Z0-9]+`, - "workspace.owner_name": `default`, - "workspace.owner_oidc_access_token": `^$`, // TODO: need a test OIDC integration - "workspace.owner_session_token": `[a-zA-Z0-9-]+`, "workspace.start_count": `1`, "workspace.template_id": `[a-zA-Z0-9-]+`, "workspace.template_name": `workspace-owner`, diff --git a/integration/test-data-source/main.tf b/integration/test-data-source/main.tf index 838125a0..6d4b85cd 100644 --- a/integration/test-data-source/main.tf +++ b/integration/test-data-source/main.tf @@ -9,9 +9,8 @@ terraform { } } -// TODO: test coder_external_auth and coder_git_auth +// TODO: test coder_external_auth // data coder_external_auth "me" {} -// data coder_git_auth "me" {} data "coder_provisioner" "me" {} data "coder_workspace" "me" {} data "coder_workspace_owner" "me" {} @@ -26,13 +25,6 @@ locals { "workspace.access_url" : data.coder_workspace.me.access_url, "workspace.id" : data.coder_workspace.me.id, "workspace.name" : data.coder_workspace.me.name, - "workspace.owner" : data.coder_workspace.me.owner, - "workspace.owner_email" : data.coder_workspace.me.owner_email, - "workspace.owner_groups" : jsonencode(data.coder_workspace.me.owner_groups), - "workspace.owner_id" : data.coder_workspace.me.owner_id, - "workspace.owner_name" : data.coder_workspace.me.owner_name, - "workspace.owner_oidc_access_token" : data.coder_workspace.me.owner_oidc_access_token, - "workspace.owner_session_token" : data.coder_workspace.me.owner_session_token, "workspace.start_count" : tostring(data.coder_workspace.me.start_count), "workspace.template_id" : data.coder_workspace.me.template_id, "workspace.template_name" : data.coder_workspace.me.template_name, diff --git a/integration/workspace-owner/main.tf b/integration/workspace-owner/main.tf index 580592cb..2be11d8e 100644 --- a/integration/workspace-owner/main.tf +++ b/integration/workspace-owner/main.tf @@ -9,9 +9,8 @@ terraform { } } -// TODO: test coder_external_auth and coder_git_auth +// TODO: test coder_external_auth // data coder_external_auth "me" {} -// data coder_git_auth "me" {} data "coder_provisioner" "me" {} data "coder_workspace" "me" {} data "coder_workspace_owner" "me" {} @@ -26,13 +25,6 @@ locals { "workspace.access_url" : data.coder_workspace.me.access_url, "workspace.id" : data.coder_workspace.me.id, "workspace.name" : data.coder_workspace.me.name, - "workspace.owner" : data.coder_workspace.me.owner, - "workspace.owner_email" : data.coder_workspace.me.owner_email, - "workspace.owner_groups" : jsonencode(data.coder_workspace.me.owner_groups), - "workspace.owner_id" : data.coder_workspace.me.owner_id, - "workspace.owner_name" : data.coder_workspace.me.owner_name, - "workspace.owner_oidc_access_token" : data.coder_workspace.me.owner_oidc_access_token, - "workspace.owner_session_token" : data.coder_workspace.me.owner_session_token, "workspace.start_count" : tostring(data.coder_workspace.me.start_count), "workspace.template_id" : data.coder_workspace.me.template_id, "workspace.template_name" : data.coder_workspace.me.template_name, diff --git a/provider/workspace.go b/provider/workspace.go index 3f667e8f..575fd60f 100644 --- a/provider/workspace.go +++ b/provider/workspace.go @@ -2,7 +2,6 @@ package provider import ( "context" - "encoding/json" "reflect" "strconv" @@ -28,37 +27,9 @@ func workspaceDataSource() *schema.Resource { } _ = rd.Set("start_count", count) - owner := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_OWNER", "default") - _ = rd.Set("owner", owner) - - ownerEmail := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_OWNER_EMAIL", "default@example.com") - _ = rd.Set("owner_email", ownerEmail) - - ownerGroupsText := helpers.OptionalEnv("CODER_WORKSPACE_OWNER_GROUPS") - var ownerGroups []string - if ownerGroupsText != "" { - err := json.Unmarshal([]byte(ownerGroupsText), &ownerGroups) - if err != nil { - return diag.Errorf("couldn't parse owner groups %q", ownerGroupsText) - } - } - _ = rd.Set("owner_groups", ownerGroups) - - ownerName := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_OWNER_NAME", "default") - _ = rd.Set("owner_name", ownerName) - - ownerID := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_OWNER_ID", uuid.Nil.String()) - _ = rd.Set("owner_id", ownerID) - - ownerOIDCAccessToken := helpers.OptionalEnv("CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN") - _ = rd.Set("owner_oidc_access_token", ownerOIDCAccessToken) - name := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_NAME", "default") rd.Set("name", name) - sessionToken := helpers.OptionalEnv("CODER_WORKSPACE_OWNER_SESSION_TOKEN") - _ = rd.Set("owner_session_token", sessionToken) - id := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_ID", uuid.NewString()) rd.SetId(id) @@ -122,47 +93,6 @@ func workspaceDataSource() *schema.Resource { Computed: true, Description: "Either `start` or `stop`. Use this to start/stop resources with `count`.", }, - "owner": { - Type: schema.TypeString, - Computed: true, - Description: "Username of the workspace owner.", - Deprecated: "Use `coder_workspace_owner.name` instead.", - }, - "owner_email": { - Type: schema.TypeString, - Computed: true, - Description: "Email address of the workspace owner.", - Deprecated: "Use `coder_workspace_owner.email` instead.", - }, - "owner_id": { - Type: schema.TypeString, - Computed: true, - Description: "UUID of the workspace owner.", - Deprecated: "Use `coder_workspace_owner.id` instead.", - }, - "owner_name": { - Type: schema.TypeString, - Computed: true, - Description: "Name of the workspace owner.", - Deprecated: "Use `coder_workspace_owner.full_name` instead.", - }, - "owner_oidc_access_token": { - Type: schema.TypeString, - Computed: true, - Description: "A valid OpenID Connect access token of the workspace owner. " + - "This is only available if the workspace owner authenticated with OpenID Connect. " + - "If a valid token cannot be obtained, this value will be an empty string.", - Deprecated: "Use `coder_workspace_owner.oidc_access_token` instead.", - }, - "owner_groups": { - Type: schema.TypeList, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - Computed: true, - Description: "List of groups the workspace owner belongs to.", - Deprecated: "Use `coder_workspace_owner.groups` instead.", - }, "id": { Type: schema.TypeString, Computed: true, @@ -173,12 +103,6 @@ func workspaceDataSource() *schema.Resource { Computed: true, Description: "Name of the workspace.", }, - "owner_session_token": { - Type: schema.TypeString, - Computed: true, - Description: "Session token for authenticating with a Coder deployment. It is regenerated everytime a workspace is started.", - Deprecated: "Use `coder_workspace_owner.session_token` instead.", - }, "template_id": { Type: schema.TypeString, Computed: true, diff --git a/provider/workspace_test.go b/provider/workspace_test.go index e53f30d4..12d5210b 100644 --- a/provider/workspace_test.go +++ b/provider/workspace_test.go @@ -14,13 +14,6 @@ import ( ) func TestWorkspace(t *testing.T) { - t.Setenv("CODER_WORKSPACE_OWNER", "owner123") - t.Setenv("CODER_WORKSPACE_OWNER_ID", "11111111-1111-1111-1111-111111111111") - t.Setenv("CODER_WORKSPACE_OWNER_NAME", "Mr Owner") - t.Setenv("CODER_WORKSPACE_OWNER_EMAIL", "owner123@example.com") - t.Setenv("CODER_WORKSPACE_OWNER_SESSION_TOKEN", "abc123") - t.Setenv("CODER_WORKSPACE_OWNER_GROUPS", `["group1", "group2"]`) - t.Setenv("CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN", "supersecret") t.Setenv("CODER_WORKSPACE_TEMPLATE_ID", "templateID") t.Setenv("CODER_WORKSPACE_TEMPLATE_NAME", "template123") t.Setenv("CODER_WORKSPACE_TEMPLATE_VERSION", "v1.2.3") @@ -49,16 +42,9 @@ func TestWorkspace(t *testing.T) { t.Log(value) assert.Equal(t, "https://example.com:8080", attribs["access_url"]) assert.Equal(t, "8080", attribs["access_port"]) - assert.Equal(t, "owner123", attribs["owner"]) - assert.Equal(t, "11111111-1111-1111-1111-111111111111", attribs["owner_id"]) - assert.Equal(t, "Mr Owner", attribs["owner_name"]) - assert.Equal(t, "owner123@example.com", attribs["owner_email"]) - assert.Equal(t, "group1", attribs["owner_groups.0"]) - assert.Equal(t, "group2", attribs["owner_groups.1"]) assert.Equal(t, "templateID", attribs["template_id"]) assert.Equal(t, "template123", attribs["template_name"]) assert.Equal(t, "v1.2.3", attribs["template_version"]) - assert.Equal(t, "supersecret", attribs["owner_oidc_access_token"]) return nil }, }}, @@ -66,9 +52,6 @@ func TestWorkspace(t *testing.T) { } func TestWorkspace_UndefinedOwner(t *testing.T) { - t.Setenv("CODER_WORKSPACE_OWNER", "owner123") - t.Setenv("CODER_WORKSPACE_OWNER_SESSION_TOKEN", "abc123") - t.Setenv("CODER_WORKSPACE_OWNER_GROUPS", `["group1", "group2"]`) t.Setenv("CODER_WORKSPACE_TEMPLATE_ID", "templateID") t.Setenv("CODER_WORKSPACE_TEMPLATE_NAME", "template123") t.Setenv("CODER_WORKSPACE_TEMPLATE_VERSION", "v1.2.3") @@ -95,8 +78,9 @@ func TestWorkspace_UndefinedOwner(t *testing.T) { value := attribs["transition"] require.NotNil(t, value) t.Log(value) - assert.Equal(t, "owner123", attribs["owner"]) - assert.Equal(t, "default@example.com", attribs["owner_email"]) + assert.Equal(t, "templateID", attribs["template_id"]) + assert.Equal(t, "template123", attribs["template_name"]) + assert.Equal(t, "v1.2.3", attribs["template_version"]) // Skip other asserts return nil }, @@ -107,13 +91,6 @@ func TestWorkspace_UndefinedOwner(t *testing.T) { func TestWorkspace_MissingTemplateName(t *testing.T) { t.Setenv("CODER_WORKSPACE_BUILD_ID", "1") // Let's pretend this is a workspace build - t.Setenv("CODER_WORKSPACE_OWNER", "owner123") - t.Setenv("CODER_WORKSPACE_OWNER_ID", "11111111-1111-1111-1111-111111111111") - t.Setenv("CODER_WORKSPACE_OWNER_NAME", "Mr Owner") - t.Setenv("CODER_WORKSPACE_OWNER_EMAIL", "owner123@example.com") - t.Setenv("CODER_WORKSPACE_OWNER_SESSION_TOKEN", "abc123") - t.Setenv("CODER_WORKSPACE_OWNER_GROUPS", `["group1", "group2"]`) - t.Setenv("CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN", "supersecret") t.Setenv("CODER_WORKSPACE_TEMPLATE_ID", "templateID") // CODER_WORKSPACE_TEMPLATE_NAME is missing t.Setenv("CODER_WORKSPACE_TEMPLATE_VERSION", "v1.2.3") From 5ca08cbcbeef38fa215823ab90d4c50eb5159ed7 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 5 Jul 2024 11:41:01 +0300 Subject: [PATCH 04/10] chore!: remove deprecated `coder_git_auth` data source (#254) --- docs/data-sources/git_auth.md | 52 ------------------ .../coder_git_auth/data-source.tf | 20 ------- provider/gitauth.go | 53 ------------------- provider/gitauth_test.go | 44 --------------- provider/provider.go | 1 - provider/provider_test.go | 3 -- 6 files changed, 173 deletions(-) delete mode 100644 docs/data-sources/git_auth.md delete mode 100644 examples/data-sources/coder_git_auth/data-source.tf delete mode 100644 provider/gitauth.go delete mode 100644 provider/gitauth_test.go diff --git a/docs/data-sources/git_auth.md b/docs/data-sources/git_auth.md deleted file mode 100644 index e665aeb1..00000000 --- a/docs/data-sources/git_auth.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "coder_git_auth Data Source - terraform-provider-coder" -subcategory: "" -description: |- - ~> Deprecated - Use the coder_external_auth data source instead. - Use this data source to require users to authenticate with a Git provider prior to workspace creation. This can be used to perform an authenticated git clone in startup scripts. ---- - -# coder_git_auth (Data Source) - -~> **Deprecated** -Use the `coder_external_auth` data source instead. - -Use this data source to require users to authenticate with a Git provider prior to workspace creation. This can be used to perform an authenticated `git clone` in startup scripts. - -## Example Usage - -```terraform -provider "coder" {} - -data "coder_git_auth" "github" { - # Matches the ID of the git auth provider in Coder. - id = "github" -} - -resource "coder_agent" "dev" { - os = "linux" - arch = "amd64" - dir = "~/coder" - env = { - GITHUB_TOKEN : data.coder_git_auth.github.access_token - } - startup_script = < -## Schema - -### Required - -- `id` (String) The identifier of a configured git auth provider set up in your Coder deployment. - -### Read-Only - -- `access_token` (String) The access token returned by the git authentication provider. This can be used to pre-authenticate command-line tools. diff --git a/examples/data-sources/coder_git_auth/data-source.tf b/examples/data-sources/coder_git_auth/data-source.tf deleted file mode 100644 index 488554f2..00000000 --- a/examples/data-sources/coder_git_auth/data-source.tf +++ /dev/null @@ -1,20 +0,0 @@ -provider "coder" {} - -data "coder_git_auth" "github" { - # Matches the ID of the git auth provider in Coder. - id = "github" -} - -resource "coder_agent" "dev" { - os = "linux" - arch = "amd64" - dir = "~/coder" - env = { - GITHUB_TOKEN : data.coder_git_auth.github.access_token - } - startup_script = < **Deprecated**\nUse the `coder_external_auth` data source instead.\n\nUse this data source to require users to authenticate with a Git provider prior to workspace creation. This can be used to perform an authenticated `git clone` in startup scripts.", - ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { - rawID, ok := rd.GetOk("id") - if !ok { - return diag.Errorf("id is required") - } - id, ok := rawID.(string) - if !ok { - return diag.Errorf("unexpected type %q for id", rawID) - } - rd.SetId(id) - - accessToken := helpers.OptionalEnv(GitAuthAccessTokenEnvironmentVariable(id)) - rd.Set("access_token", accessToken) - - return nil - }, - Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Required: true, - Description: "The identifier of a configured git auth provider set up in your Coder deployment.", - }, - "access_token": { - Type: schema.TypeString, - Computed: true, - Description: "The access token returned by the git authentication provider. This can be used to pre-authenticate command-line tools.", - }, - }, - } -} - -func GitAuthAccessTokenEnvironmentVariable(id string) string { - return fmt.Sprintf("CODER_GIT_AUTH_ACCESS_TOKEN_%s", id) -} diff --git a/provider/gitauth_test.go b/provider/gitauth_test.go deleted file mode 100644 index 481d79f5..00000000 --- a/provider/gitauth_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package provider_test - -import ( - "testing" - - "github.com/coder/terraform-provider-coder/provider" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" - - "github.com/stretchr/testify/require" -) - -func TestGitAuth(t *testing.T) { - t.Parallel() - - resource.Test(t, resource.TestCase{ - Providers: map[string]*schema.Provider{ - "coder": provider.New(), - }, - IsUnitTest: true, - Steps: []resource.TestStep{{ - Config: ` - provider "coder" { - } - data "coder_git_auth" "github" { - id = "github" - } - `, - Check: func(state *terraform.State) error { - require.Len(t, state.Modules, 1) - require.Len(t, state.Modules[0].Resources, 1) - resource := state.Modules[0].Resources["data.coder_git_auth.github"] - require.NotNil(t, resource) - - attribs := resource.Primary.Attributes - require.Equal(t, "github", attribs["id"]) - - return nil - }, - }}, - }) -} diff --git a/provider/provider.go b/provider/provider.go index c1991a26..4d513139 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -72,7 +72,6 @@ func New() *schema.Provider { "coder_workspace_tags": workspaceTagDataSource(), "coder_provisioner": provisionerDataSource(), "coder_parameter": parameterDataSource(), - "coder_git_auth": gitAuthDataSource(), "coder_external_auth": externalAuthDataSource(), "coder_workspace_owner": workspaceOwnerDataSource(), }, diff --git a/provider/provider_test.go b/provider/provider_test.go index 7069db09..742eb30b 100644 --- a/provider/provider_test.go +++ b/provider/provider_test.go @@ -37,9 +37,6 @@ func TestProviderEmpty(t *testing.T) { data "coder_external_auth" "git" { id = "git" } - data "coder_git_auth" "git" { - id = "git" - } data "coder_parameter" "param" { name = "hey" }`, From f46148f247afcb5fa8b1127cf27ebab77d9120f0 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 5 Jul 2024 11:41:12 +0300 Subject: [PATCH 05/10] chore!: remove deprecated feature_use_managed_variables (#256) --- docs/index.md | 1 - provider/provider.go | 7 ------- 2 files changed, 8 deletions(-) diff --git a/docs/index.md b/docs/index.md index a4dfd70e..859964d4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -62,5 +62,4 @@ resource "google_compute_instance" "dev" { ### Optional -- `feature_use_managed_variables` (Boolean, **Deprecated**: Terraform variables are now exclusively utilized for template-wide variables after the removal of support for legacy parameters.) Feature: use managed Terraform variables. The feature flag is not used anymore as Terraform variables are now exclusively utilized for template-wide variables. - `url` (String) The URL to access Coder. \ No newline at end of file diff --git a/provider/provider.go b/provider/provider.go index 4d513139..1a37b706 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -35,13 +35,6 @@ func New() *schema.Provider { return nil, nil }, }, - "feature_use_managed_variables": { - Type: schema.TypeBool, - Description: "Feature: use managed Terraform variables. The feature flag is not used anymore as Terraform variables are now exclusively utilized for template-wide variables.", - Default: true, - Optional: true, - Deprecated: "Terraform variables are now exclusively utilized for template-wide variables after the removal of support for legacy parameters.", - }, }, ConfigureContextFunc: func(c context.Context, resourceData *schema.ResourceData) (interface{}, diag.Diagnostics) { rawURL, ok := resourceData.Get("url").(string) From dea044287505e28e99bac4b232c9a9e07f7eb8e3 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 5 Jul 2024 11:44:06 +0300 Subject: [PATCH 06/10] chore!: remove deprecated fields from `coder_app` and `coder_agent` resources (#257) --- docs/resources/agent.md | 3 --- docs/resources/app.md | 2 -- provider/agent.go | 47 ++++++----------------------------------- provider/agent_test.go | 32 ---------------------------- provider/app.go | 17 --------------- 5 files changed, 6 insertions(+), 95 deletions(-) diff --git a/docs/resources/agent.md b/docs/resources/agent.md index e444d2d7..8c786d6e 100644 --- a/docs/resources/agent.md +++ b/docs/resources/agent.md @@ -76,15 +76,12 @@ resource "kubernetes_pod" "dev" { - `dir` (String) The starting directory when a user creates a shell session. Defaults to `"$HOME"`. - `display_apps` (Block Set, Max: 1) The list of built-in apps to display in the agent bar. (see [below for nested schema](#nestedblock--display_apps)) - `env` (Map of String) A mapping of environment variables to set inside the workspace. -- `login_before_ready` (Boolean, **Deprecated**: Configure `startup_script_behavior` instead. This attribute will be removed in a future version of the provider.) This option defines whether or not the user can (by default) login to the workspace before it is ready. Ready means that e.g. the `startup_script` is done and has exited. When enabled, users may see an incomplete workspace when logging in. - `metadata` (Block List) Each `metadata` block defines a single item consisting of a key/value pair. This feature is in alpha and may break in future releases. (see [below for nested schema](#nestedblock--metadata)) - `motd_file` (String) The path to a file within the workspace containing a message to display to users when they login via SSH. A typical value would be `"/etc/motd"`. - `order` (Number) The order determines the position of agents in the UI presentation. The lowest order is shown first and agents with equal order are sorted by name (ascending order). - `shutdown_script` (String) A script to run before the agent is stopped. The script should exit when it is done to signal that the workspace can be stopped. This option is an alias for defining a `coder_script` resource with `run_on_stop` set to `true`. -- `shutdown_script_timeout` (Number, **Deprecated**: This feature is deprecated and has no effect. This attribute will be removed in a future version of the provider.) Time in seconds until the agent lifecycle status is marked as timed out during shutdown, this happens when the shutdown script has not completed (exited) in the given time. - `startup_script` (String) A script to run after the agent starts. The script should exit when it is done to signal that the agent is ready. This option is an alias for defining a `coder_script` resource with `run_on_start` set to `true`. - `startup_script_behavior` (String) This option sets the behavior of the `startup_script`. When set to `"blocking"`, the `startup_script` must exit before the workspace is ready. When set to `"non-blocking"`, the `startup_script` may run in the background and the workspace will be ready immediately. Default is `"non-blocking"`, although `"blocking"` is recommended. This option is an alias for defining a `coder_script` resource with `start_blocks_login` set to `true` (blocking). -- `startup_script_timeout` (Number, **Deprecated**: This feature is deprecated and has no effect. This attribute will be removed in a future version of the provider.) Time in seconds until the agent lifecycle status is marked as timed out during start, this happens when the startup script has not completed (exited) in the given time. - `troubleshooting_url` (String) A URL to a document with instructions for troubleshooting problems with the agent. ### Read-Only diff --git a/docs/resources/app.md b/docs/resources/app.md index f61ed799..1cb5d08b 100644 --- a/docs/resources/app.md +++ b/docs/resources/app.md @@ -64,9 +64,7 @@ resource "coder_app" "vim" { - `external` (Boolean) Specifies whether `url` is opened on the client machine instead of proxied through the workspace. - `healthcheck` (Block Set, Max: 1) HTTP health checking to determine the application readiness. (see [below for nested schema](#nestedblock--healthcheck)) - `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons here: https://github.com/coder/coder/tree/main/site/static/icon. Use a built-in icon with `"${data.coder_workspace.me.access_url}/icon/"`. -- `name` (String, **Deprecated**: `name` on apps is deprecated, use `display_name` instead) A display name to identify the app. - `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). -- `relative_path` (Boolean, **Deprecated**: `relative_path` on apps is deprecated, use `subdomain` instead.) Specifies whether the URL will be accessed via a relative path or wildcard. Use if wildcard routing is unavailable. Defaults to `true`. - `share` (String) Determines the level which the application is shared at. Valid levels are `"owner"` (default), `"authenticated"` and `"public"`. Level `"owner"` disables sharing on the app, so only the workspace owner can access it. Level `"authenticated"` shares the app with all authenticated users. Level `"public"` shares it with any user, including unauthenticated users. Permitted application sharing levels can be configured site-wide via a flag on `coder server` (Enterprise only). - `subdomain` (Boolean) Determines whether the app will be accessed via it's own subdomain or whether it will be accessed via a path on Coder. If wildcards have not been setup by the administrator then apps with `subdomain` set to `true` will not be accessible. Defaults to `false`. - `url` (String) An external url if `external=true` or a URL to be proxied to from inside the workspace. This should be of the form `http://localhost:PORT[/SUBPATH]`. Either `command` or `url` may be specified, but not both. diff --git a/provider/agent.go b/provider/agent.go index 352dd5d9..d0ce4070 100644 --- a/provider/agent.go +++ b/provider/agent.go @@ -128,30 +128,12 @@ func agentResource() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "startup_script_timeout": { - Type: schema.TypeInt, - Default: 300, - ForceNew: true, - Optional: true, - Description: "Time in seconds until the agent lifecycle status is marked as timed out during start, this happens when the startup script has not completed (exited) in the given time.", - Deprecated: "This feature is deprecated and has no effect. This attribute will be removed in a future version of the provider.", - ValidateFunc: validation.IntAtLeast(1), - }, "shutdown_script": { Type: schema.TypeString, ForceNew: true, Optional: true, Description: "A script to run before the agent is stopped. The script should exit when it is done to signal that the workspace can be stopped. This option is an alias for defining a `coder_script` resource with `run_on_stop` set to `true`.", }, - "shutdown_script_timeout": { - Type: schema.TypeInt, - Default: 300, - ForceNew: true, - Optional: true, - Description: "Time in seconds until the agent lifecycle status is marked as timed out during shutdown, this happens when the shutdown script has not completed (exited) in the given time.", - Deprecated: "This feature is deprecated and has no effect. This attribute will be removed in a future version of the provider.", - ValidateFunc: validation.IntAtLeast(1), - }, "token": { ForceNew: true, Sensitive: true, @@ -179,30 +161,13 @@ func agentResource() *schema.Resource { Optional: true, Description: "The path to a file within the workspace containing a message to display to users when they login via SSH. A typical value would be `\"/etc/motd\"`.", }, - "login_before_ready": { - // Note: When this is removed, "startup_script_behavior" should - // be set to "non-blocking" by default (instead of empty string). - Type: schema.TypeBool, - Default: true, - ForceNew: true, - Optional: true, - Description: "This option defines whether or not the user can (by default) login to the workspace before it is ready. Ready means that e.g. the `startup_script` is done and has exited. When enabled, users may see an incomplete workspace when logging in.", - Deprecated: "Configure `startup_script_behavior` instead. This attribute will be removed in a future version of the provider.", - ConflictsWith: []string{"startup_script_behavior"}, - }, "startup_script_behavior": { - // Note: Our default value is "non-blocking" but we do not set - // it here because we want to be able to differentiate between - // the user setting this or "login_before_ready". For all - // intents and purposes, until deprecation, setting - // "login_before_ready = false" is equivalent to setting - // "startup_script_behavior = blocking". - Type: schema.TypeString, - ForceNew: true, - Optional: true, - Description: "This option sets the behavior of the `startup_script`. When set to `\"blocking\"`, the `startup_script` must exit before the workspace is ready. When set to `\"non-blocking\"`, the `startup_script` may run in the background and the workspace will be ready immediately. Default is `\"non-blocking\"`, although `\"blocking\"` is recommended. This option is an alias for defining a `coder_script` resource with `start_blocks_login` set to `true` (blocking).", - ValidateFunc: validation.StringInSlice([]string{"blocking", "non-blocking"}, false), - ConflictsWith: []string{"login_before_ready"}, + Type: schema.TypeString, + Default: "non-blocking", + ForceNew: true, + Optional: true, + Description: "This option sets the behavior of the `startup_script`. When set to `\"blocking\"`, the `startup_script` must exit before the workspace is ready. When set to `\"non-blocking\"`, the `startup_script` may run in the background and the workspace will be ready immediately. Default is `\"non-blocking\"`, although `\"blocking\"` is recommended. This option is an alias for defining a `coder_script` resource with `start_blocks_login` set to `true` (blocking).", + ValidateFunc: validation.StringInSlice([]string{"blocking", "non-blocking"}, false), }, "metadata": { Type: schema.TypeList, diff --git a/provider/agent_test.go b/provider/agent_test.go index 491e59f9..0df2cf2d 100644 --- a/provider/agent_test.go +++ b/provider/agent_test.go @@ -34,11 +34,9 @@ func TestAgent(t *testing.T) { hi = "test" } startup_script = "echo test" - startup_script_timeout = 120 troubleshooting_url = "https://example.com/troubleshoot" motd_file = "/etc/motd" shutdown_script = "echo bye bye" - shutdown_script_timeout = 120 order = 4 } `, @@ -55,12 +53,10 @@ func TestAgent(t *testing.T) { "dir", "env.hi", "startup_script", - "startup_script_timeout", "connection_timeout", "troubleshooting_url", "motd_file", "shutdown_script", - "shutdown_script_timeout", "order", } { value := resource.Primary.Attributes[key] @@ -109,34 +105,6 @@ func TestAgent_StartupScriptBehavior(t *testing.T) { require.Equal(t, "non-blocking", state.Primary.Attributes["startup_script_behavior"]) }, }, - { - Name: "login_before_ready (deprecated)", - Config: ` - resource "coder_agent" "new" { - os = "linux" - arch = "amd64" - login_before_ready = false - } - `, - Check: func(state *terraform.ResourceState) { - require.Equal(t, "false", state.Primary.Attributes["login_before_ready"]) - // startup_script_behavior must be empty, this indicates that - // login_before_ready should be used instead. - require.Equal(t, "", state.Primary.Attributes["startup_script_behavior"]) - }, - }, - { - Name: "no login_before_ready with startup_script_behavior", - Config: ` - resource "coder_agent" "new" { - os = "linux" - arch = "amd64" - login_before_ready = false - startup_script_behavior = "blocking" - } - `, - ExpectError: regexp.MustCompile("conflicts with"), - }, } { tc := tc t.Run(tc.Name, func(t *testing.T) { diff --git a/provider/app.go b/provider/app.go index 91c08f0f..754b0e2a 100644 --- a/provider/app.go +++ b/provider/app.go @@ -96,14 +96,6 @@ func appResource() *schema.Resource { ForceNew: true, Optional: true, }, - "name": { - Type: schema.TypeString, - Description: "A display name to identify the app.", - Deprecated: "`name` on apps is deprecated, use `display_name` instead", - ForceNew: true, - Optional: true, - ConflictsWith: []string{"display_name"}, - }, "subdomain": { Type: schema.TypeBool, Description: "Determines whether the app will be accessed via it's own " + @@ -113,15 +105,6 @@ func appResource() *schema.Resource { ForceNew: true, Optional: true, }, - "relative_path": { - Type: schema.TypeBool, - Deprecated: "`relative_path` on apps is deprecated, use `subdomain` instead.", - Description: "Specifies whether the URL will be accessed via a relative " + - "path or wildcard. Use if wildcard routing is unavailable. Defaults to `true`.", - ForceNew: true, - Optional: true, - ConflictsWith: []string{"subdomain"}, - }, "share": { Type: schema.TypeString, Description: "Determines the level which the application " + From f478379740aab9e2b3887cd04cbc740c97e5cfaa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jul 2024 13:08:06 +0300 Subject: [PATCH 07/10] build(deps): Bump goreleaser/goreleaser-action from 5.1.0 to 6.0.0 (#238) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Muhammad Atif Ali --- .github/workflows/release.yml | 4 ++-- .goreleaser.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ad8d96c9..6bf1284c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,10 +38,10 @@ jobs: passphrase: ${{ secrets.PASSPHRASE }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v5.1.0 + uses: goreleaser/goreleaser-action@v6.0.0 with: version: latest - args: release --rm-dist + args: release --clean env: GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} # GitHub sets this automatically diff --git a/.goreleaser.yml b/.goreleaser.yml index 0e43eeec..3866324a 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -57,4 +57,4 @@ release: # If you want to manually examine the release before its live, uncomment this line: # draft: true changelog: - skip: true \ No newline at end of file + disable: true From 1d525fa819e14edf745e6acc5e110a8d14f470e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:34:54 +0100 Subject: [PATCH 08/10] build(deps): Bump github.com/docker/docker (#263) Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.1.4+incompatible to 26.1.5+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v26.1.4...v26.1.5) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7e8aebe9..d83e1250 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22 toolchain go1.22.3 require ( - github.com/docker/docker v26.1.4+incompatible + github.com/docker/docker v26.1.5+incompatible github.com/google/uuid v1.6.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0 diff --git a/go.sum b/go.sum index 79ed9f85..866fe7b5 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= -github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.1.5+incompatible h1:NEAxTwEjxV6VbBMBoGG3zPqbiJosIApZjxlbrG9q3/g= +github.com/docker/docker v26.1.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= From a90433161c47200097d0769b5ac6e8f8c2572662 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Wed, 21 Aug 2024 11:38:37 +0300 Subject: [PATCH 09/10] docs: add description to provider index page --- docs/index.md | 4 +++- templates/index.md.tmpl | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 859964d4..735e3ccd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,11 +3,13 @@ page_title: "Coder Provider" subcategory: "Infrastructure" description: |- - + Terraform provider for managing Coder templates, which are the underlying infrastructure for Coder workspaces. --- # Coder Provider +CTerraform provider for managing Coder [templates](https://coder.com/docs/templates), which are the underlying infrastructure for Coder [workspaces](https://coder.com/docs/workspaces). + ## Example ```terraform diff --git a/templates/index.md.tmpl b/templates/index.md.tmpl index 5ca983fd..de4ec73e 100644 --- a/templates/index.md.tmpl +++ b/templates/index.md.tmpl @@ -3,11 +3,13 @@ page_title: "Coder Provider" subcategory: "Infrastructure" description: |- - + Terraform provider for managing Coder templates, which are the underlying infrastructure for Coder workspaces. --- # Coder Provider +Terraform provider for managing Coder [templates](https://coder.com/docs/templates), which are the underlying infrastructure for Coder [workspaces](https://coder.com/docs/workspaces). + ## Example {{tffile "examples/provider/provider.tf"}} From 12132aa6dbafbb8b764d36cbc73dc92b3984919b Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Wed, 21 Aug 2024 11:51:56 +0300 Subject: [PATCH 10/10] fix typo --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 735e3ccd..7ce115a7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -8,7 +8,7 @@ description: |- # Coder Provider -CTerraform provider for managing Coder [templates](https://coder.com/docs/templates), which are the underlying infrastructure for Coder [workspaces](https://coder.com/docs/workspaces). +Terraform provider for managing Coder [templates](https://coder.com/docs/templates), which are the underlying infrastructure for Coder [workspaces](https://coder.com/docs/workspaces). ## Example