From 21040529a5d8f500c811af073ff2f555b6b6556d Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Sat, 22 Oct 2022 20:30:09 +0000 Subject: [PATCH 1/3] docs: better explain persistent resources --- docs/images/icons/infinity.svg | 1 + docs/manifest.json | 6 ++ docs/templates.md | 9 +-- docs/templates/resource-persistence.md | 90 ++++++++++++++++++++++++++ docs/workspaces.md | 5 +- dogfood/main.tf | 3 + 6 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 docs/images/icons/infinity.svg create mode 100644 docs/templates/resource-persistence.md diff --git a/docs/images/icons/infinity.svg b/docs/images/icons/infinity.svg new file mode 100644 index 0000000000000..f1d11dccfaa1c --- /dev/null +++ b/docs/images/icons/infinity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/manifest.json b/docs/manifest.json index b10d2de0f9824..ec9660ed80e19 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -100,6 +100,12 @@ "path": "./templates.md", "icon_path": "./images/icons/picture.svg", "children": [ + { + "title": "Resource Persistence", + "description": "Learn how to resource persistence works in Coder", + "path": "./templates/resource-persistence.md", + "icon_path": "./images/icons/infinity.svg" + }, { "title": "Provider Authentication", "description": "Learn how to authenticate the provisioner", diff --git a/docs/templates.md b/docs/templates.md index 5d09b56e0217b..6e8c98a0f5c31 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -164,13 +164,10 @@ resource "docker_image" "workspace" { } ``` -### Persistent vs. ephemeral resources - -You can use the workspace state to ensure some resources in Coder are -persistent, while others are ephemeral. - #### Start/stop +[Learn about resource persistence in Coder](./templates/resource-persistence.md) + Coder workspaces can be started/stopped. This is often used to save on cloud costs or enforce ephemeral workflows. When a workspace is started or stopped, the Coder server runs an additional @@ -180,7 +177,7 @@ Coder provider that the workspace has a new transition state. This template sample has one persistent resource (docker volume) and one ephemeral resource (docker image). -```sh +```hcl data "coder_workspace" "me" { } diff --git a/docs/templates/resource-persistence.md b/docs/templates/resource-persistence.md new file mode 100644 index 0000000000000..d2acfa67bf078 --- /dev/null +++ b/docs/templates/resource-persistence.md @@ -0,0 +1,90 @@ +# Resource Persistence + +Coder doesn't prescribe your workspace's level of ephemerality. In a +completely ephemeral workspace, there are zero resources in the On state. In +a completely persistent workspace, there is no difference between the Off and +On states. + +Most workspaces fall somewhere in the middle, persisting user data +such as filesystem volumes, but deleting expensive, reproducible resources +such as compute instances. + +By default, all Coder resources are persistent, but there are practices all +production templates **must** employ to prevent accidental deletion. + +## Disabling Persistence + +The [`coder_workspace` data source](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace) exposes the `start_count = [0 | 1]` attribute that other +resources use to become ephemeral. + +For example: + +```hcl +data "coder_workspace" "me" { +} + +resource "docker_container" "workspace" { + # ephemeral resource (deleted when workspace is stopped, created when started) + count = data.coder_workspace.me.start_count # 0 (stopped), 1 (started) + # ... other config +} +``` + +## ⚠️ Persistence Pitfalls + +Take this example resource: + +```hcl +data "coder_workspace" "me" { +} + +resource "docker_volume" "home_volume" { + # Coder will recreate and wipe this volume if the owner changes their username. + name = "coder-${data.coder_workspace.me.owner}-home" +} +``` + +Because we depend on `coder_workspace.me.owner`, if the owner changed their +username, Terraform would recreate the volume (wiping the data) the next +time the workspace restarted. + +Thus, persistent resource names must depend on immutable IDs such as: +* `coder_workspace.me.owner_id` +* `coder_workspace.me.id` + +```hcl +data "coder_workspace" "me" { +} + +resource "docker_volume" "home_volume" { + # This volume will survive until the Workspace is deleted or the template + # admin changes this resource block. + name = "coder-${data.coder_workspace.id}-home" +} +``` + +## Bulletproofing +Even if we depend exclusively static IDs, a change to the `name` format or other +attributes would cause Terraform to rebuild the resource. + +Bulletproof persistent resources by setting the [`ignore_changes = all` directive in the `lifecycle` block](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#ignore_changes). This +setting prevents Terraform from recreating the resource under any circumstance. + + +```hcl +data "coder_workspace" "me" { +} + +resource "docker_volume" "home_volume" { + # This resource will survive until either the entire block is deleted + # or the workspace is. + name = "coder-${data.coder_workspace.me.id}-home" + lifecycle { + ignore_changes = all + } +} +``` + +## Up next + +- [Templates](../templates.md) diff --git a/docs/workspaces.md b/docs/workspaces.md index 5839a7e056ceb..3537356692872 100644 --- a/docs/workspaces.md +++ b/docs/workspaces.md @@ -27,9 +27,8 @@ any activity or if there was a [template update](./templates.md#manage-templates) available. Resources are often destroyed and re-created when a workspace is restarted, -though the exact behavior depends on the template's definitions. For more -information, see [persistent vs. ephemeral -resources](./templates.md#persistent-vs-ephemeral-resources). +though the exact behavior depends on the template. For more +information, see [Resource Persistence](./templates/resource-persistence.md). > ⚠️ To avoid data loss, refer to your template documentation for information on > where to store files, install software, etc., so that they persist. Default diff --git a/dogfood/main.tf b/dogfood/main.tf index 0b757336b812c..7e473a5a6491c 100644 --- a/dogfood/main.tf +++ b/dogfood/main.tf @@ -54,6 +54,9 @@ resource "coder_app" "code-server" { resource "docker_volume" "home_volume" { name = "coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}-home" + lifecycle { + ignore_changes = all + } } resource "coder_metadata" "home_info" { From ea58254d1055c25dbc29fd098364e6ca902928b1 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Sat, 22 Oct 2022 22:39:32 +0000 Subject: [PATCH 2/3] fixup! docs: better explain persistent resources --- docs/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/manifest.json b/docs/manifest.json index ec9660ed80e19..63959d9079faa 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -102,7 +102,7 @@ "children": [ { "title": "Resource Persistence", - "description": "Learn how to resource persistence works in Coder", + "description": "Learn how resource persistence works in Coder", "path": "./templates/resource-persistence.md", "icon_path": "./images/icons/infinity.svg" }, From 0ba49bef521e68261bdb6e1eddd6737d6c4bbfa9 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Sun, 23 Oct 2022 18:43:42 +0000 Subject: [PATCH 3/3] fixup! docs: better explain persistent resources --- docs/manifest.json | 3 ++- docs/templates/resource-persistence.md | 30 ++++++++++++-------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/docs/manifest.json b/docs/manifest.json index 63959d9079faa..361e39cacdf68 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -104,7 +104,8 @@ "title": "Resource Persistence", "description": "Learn how resource persistence works in Coder", "path": "./templates/resource-persistence.md", - "icon_path": "./images/icons/infinity.svg" + "icon_path": "./images/icons/infinity.svg", + "last_updated": "2022-10-23" }, { "title": "Provider Authentication", diff --git a/docs/templates/resource-persistence.md b/docs/templates/resource-persistence.md index d2acfa67bf078..44ab17977ea22 100644 --- a/docs/templates/resource-persistence.md +++ b/docs/templates/resource-persistence.md @@ -1,6 +1,6 @@ # Resource Persistence -Coder doesn't prescribe your workspace's level of ephemerality. In a +Coder templates have full control over workspace ephemerality. In a completely ephemeral workspace, there are zero resources in the On state. In a completely persistent workspace, there is no difference between the Off and On states. @@ -9,13 +9,14 @@ Most workspaces fall somewhere in the middle, persisting user data such as filesystem volumes, but deleting expensive, reproducible resources such as compute instances. -By default, all Coder resources are persistent, but there are practices all -production templates **must** employ to prevent accidental deletion. +By default, all Coder resources are persistent, but +production templates **must** employ the practices laid out in this document +to prevent accidental deletion. ## Disabling Persistence The [`coder_workspace` data source](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace) exposes the `start_count = [0 | 1]` attribute that other -resources use to become ephemeral. +resources reference to become ephemeral. For example: @@ -24,7 +25,7 @@ data "coder_workspace" "me" { } resource "docker_container" "workspace" { - # ephemeral resource (deleted when workspace is stopped, created when started) + # When `start_count` is 0, `count` is 0, so no `docker_container` is created. count = data.coder_workspace.me.start_count # 0 (stopped), 1 (started) # ... other config } @@ -39,16 +40,15 @@ data "coder_workspace" "me" { } resource "docker_volume" "home_volume" { - # Coder will recreate and wipe this volume if the owner changes their username. name = "coder-${data.coder_workspace.me.owner}-home" } ``` -Because we depend on `coder_workspace.me.owner`, if the owner changed their -username, Terraform would recreate the volume (wiping the data) the next -time the workspace restarted. +Because we depend on `coder_workspace.me.owner`, if the owner changes their +username, Terraform would recreate the volume (wiping its data!) the next +time the workspace restarts. -Thus, persistent resource names must depend on immutable IDs such as: +Therefore, persistent resource names must only depend on immutable IDs such as: * `coder_workspace.me.owner_id` * `coder_workspace.me.id` @@ -63,13 +63,11 @@ resource "docker_volume" "home_volume" { } ``` -## Bulletproofing -Even if we depend exclusively static IDs, a change to the `name` format or other -attributes would cause Terraform to rebuild the resource. - -Bulletproof persistent resources by setting the [`ignore_changes = all` directive in the `lifecycle` block](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#ignore_changes). This -setting prevents Terraform from recreating the resource under any circumstance. +## 🛡 Bulletproofing +Even if our persistent resource depends exclusively on static IDs, a change to +the `name` format or other attributes would cause Terraform to rebuild the resource. +Prevent Terraform from recreating the resource under any circumstance by setting the [`ignore_changes = all` directive in the `lifecycle` block](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#ignore_changes). ```hcl data "coder_workspace" "me" {