From 85760c6f3a7525dee52c521a61fdcc37aa149afc Mon Sep 17 00:00:00 2001 From: Marcin Tojek <marcin@coder.com> Date: Fri, 10 May 2024 16:05:47 +0200 Subject: [PATCH 01/10] feat: support workspace tags --- .../coder_workspace_tags/resource.tf | 48 +++++++++++++++++++ provider/examples_test.go | 28 ++++++----- 2 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 examples/resources/coder_workspace_tags/resource.tf diff --git a/examples/resources/coder_workspace_tags/resource.tf b/examples/resources/coder_workspace_tags/resource.tf new file mode 100644 index 00000000..5988bac4 --- /dev/null +++ b/examples/resources/coder_workspace_tags/resource.tf @@ -0,0 +1,48 @@ +provider "coder" {} + +data "coder_parameter" "os_selector" { + name = "os_selector" + display_name = "Operating System" + mutable = false + + default = "osx" + + option { + icon = "/icons/linux.png" + name = "Linux" + value = "linux" + } + option { + icon = "/icons/osx.png" + name = "OSX" + value = "osx" + } + option { + icon = "/icons/windows.png" + name = "Windows" + value = "windows" + } +} + +data "coder_parameter" "feature_cache_enabled" { + name = "feature_cache_enabled" + display_name = "Enable cache?" + type = "bool" + + default = false +} + +data "coder_workspace_tags" "custom_workspace_tags" { + tag { + name = "cluster" + value = "developers" + } + tag { + name = "os" + value = "${data.coder_parameter.os_selector}" + } + tag { + name = "cache" + value = data.coder_parameter.feature_cache_enabled == "true" ? "nix-with-cache": "no-cache" + } +} \ No newline at end of file diff --git a/provider/examples_test.go b/provider/examples_test.go index 9be7ce02..6fa73d21 100644 --- a/provider/examples_test.go +++ b/provider/examples_test.go @@ -14,19 +14,25 @@ import ( func TestExamples(t *testing.T) { t.Parallel() - t.Run("coder_parameter", func(t *testing.T) { - t.Parallel() + for _, testDir := range []string{ + "coder_parameter", + "coder_workspace_tags", + } { + t.Run(testDir, func(t *testing.T) { + testDir := testDir + t.Parallel() - resource.Test(t, resource.TestCase{ - Providers: map[string]*schema.Provider{ - "coder": provider.New(), - }, - IsUnitTest: true, - Steps: []resource.TestStep{{ - Config: mustReadFile(t, "../examples/resources/coder_parameter/resource.tf"), - }}, + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), + }, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: mustReadFile(t, "../examples/resources/"+testDir+"/resource.tf"), + }}, + }) }) - }) + } } func mustReadFile(t *testing.T, path string) string { From 2601c439e678a05af315c7a03eeb6c49e39c3622 Mon Sep 17 00:00:00 2001 From: Marcin Tojek <marcin@coder.com> Date: Fri, 10 May 2024 16:07:33 +0200 Subject: [PATCH 02/10] fmt --- .../resources/coder_workspace_tags/resource.tf | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/resources/coder_workspace_tags/resource.tf b/examples/resources/coder_workspace_tags/resource.tf index 5988bac4..ed3e65e8 100644 --- a/examples/resources/coder_workspace_tags/resource.tf +++ b/examples/resources/coder_workspace_tags/resource.tf @@ -1,9 +1,9 @@ provider "coder" {} data "coder_parameter" "os_selector" { - name = "os_selector" + name = "os_selector" display_name = "Operating System" - mutable = false + mutable = false default = "osx" @@ -27,22 +27,22 @@ data "coder_parameter" "os_selector" { data "coder_parameter" "feature_cache_enabled" { name = "feature_cache_enabled" display_name = "Enable cache?" - type = "bool" + type = "bool" default = false } data "coder_workspace_tags" "custom_workspace_tags" { tag { - name = "cluster" + name = "cluster" value = "developers" } tag { - name = "os" - value = "${data.coder_parameter.os_selector}" + name = "os" + value = data.coder_parameter.os_selector } tag { - name = "cache" - value = data.coder_parameter.feature_cache_enabled == "true" ? "nix-with-cache": "no-cache" + name = "cache" + value = data.coder_parameter.feature_cache_enabled == "true" ? "nix-with-cache" : "no-cache" } } \ No newline at end of file From 434b170000d24fcc046fb21b5d2c3ad967163401 Mon Sep 17 00:00:00 2001 From: Marcin Tojek <marcin@coder.com> Date: Tue, 14 May 2024 14:17:52 +0200 Subject: [PATCH 03/10] WIP --- .../coder_workspace_tags/resource.tf | 16 ++++- provider/provider.go | 11 ++-- provider/workspace_tags.go | 60 +++++++++++++++++++ 3 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 provider/workspace_tags.go diff --git a/examples/resources/coder_workspace_tags/resource.tf b/examples/resources/coder_workspace_tags/resource.tf index ed3e65e8..ffa7efe4 100644 --- a/examples/resources/coder_workspace_tags/resource.tf +++ b/examples/resources/coder_workspace_tags/resource.tf @@ -32,6 +32,14 @@ data "coder_parameter" "feature_cache_enabled" { default = false } +data "coder_parameter" "feature_debug_enabled" { + name = "feature_debug_enabled" + display_name = "Enable debug?" + type = "bool" + + default = true +} + data "coder_workspace_tags" "custom_workspace_tags" { tag { name = "cluster" @@ -39,10 +47,14 @@ data "coder_workspace_tags" "custom_workspace_tags" { } tag { name = "os" - value = data.coder_parameter.os_selector + value = data.coder_parameter.os_selector.value + } + tag { + name = "debug" + value = data.coder_parameter.feature_debug_enabled.value } tag { name = "cache" - value = data.coder_parameter.feature_cache_enabled == "true" ? "nix-with-cache" : "no-cache" + value = data.coder_parameter.feature_cache_enabled.value == "true" ? "nix-with-cache" : "no-cache" } } \ No newline at end of file diff --git a/provider/provider.go b/provider/provider.go index fb262c8c..4ea75ba8 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -68,11 +68,12 @@ func New() *schema.Provider { }, nil }, DataSourcesMap: map[string]*schema.Resource{ - "coder_workspace": workspaceDataSource(), - "coder_provisioner": provisionerDataSource(), - "coder_parameter": parameterDataSource(), - "coder_git_auth": gitAuthDataSource(), - "coder_external_auth": externalAuthDataSource(), + "coder_workspace": workspaceDataSource(), + "coder_workspace_tags": workspaceTagDataSource(), + "coder_provisioner": provisionerDataSource(), + "coder_parameter": parameterDataSource(), + "coder_git_auth": gitAuthDataSource(), + "coder_external_auth": externalAuthDataSource(), }, ResourcesMap: map[string]*schema.Resource{ "coder_agent": agentResource(), diff --git a/provider/workspace_tags.go b/provider/workspace_tags.go new file mode 100644 index 00000000..2f2be6d5 --- /dev/null +++ b/provider/workspace_tags.go @@ -0,0 +1,60 @@ +package provider + +import ( + "context" + "log" + + "github.com/google/uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +type WorkspaceTags struct { + Tag []Tag +} + +type Tag struct { + Name string + Value string +} + +func workspaceTagDataSource() *schema.Resource { + return &schema.Resource{ + Description: "Use this data source to configure workspace tags to select provisioners.", + ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { + rd.SetId(uuid.NewString()) + rawConfig := rd.GetRawConfig() + rawTags, ok := rawConfig.AsValueMap()["tag"] + if !ok { + return diag.Errorf("boom") + } + log.Println(rawTags) + return nil + }, + Schema: map[string]*schema.Schema{ + "tag": { + Type: schema.TypeList, + Description: `Each "tag" block defines a workspace tag.`, + ForceNew: true, + Optional: true, + MaxItems: 64, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Description: "The name of the tag.", + ForceNew: true, + Required: true, + }, + "value": { + Type: schema.TypeString, + Description: "The value of the tag.", + ForceNew: true, + Required: true, + }, + }, + }, + }, + }, + } +} From 2b879566874f476e9f4ff84077eee841228e8cd1 Mon Sep 17 00:00:00 2001 From: Marcin Tojek <marcin@coder.com> Date: Tue, 14 May 2024 14:57:00 +0200 Subject: [PATCH 04/10] WIP --- examples/resources/coder_workspace_tags/resource.tf | 2 +- provider/workspace_tags.go | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/examples/resources/coder_workspace_tags/resource.tf b/examples/resources/coder_workspace_tags/resource.tf index ffa7efe4..392d328c 100644 --- a/examples/resources/coder_workspace_tags/resource.tf +++ b/examples/resources/coder_workspace_tags/resource.tf @@ -51,7 +51,7 @@ data "coder_workspace_tags" "custom_workspace_tags" { } tag { name = "debug" - value = data.coder_parameter.feature_debug_enabled.value + value = "${data.coder_parameter.feature_debug_enabled.value}" } tag { name = "cache" diff --git a/provider/workspace_tags.go b/provider/workspace_tags.go index 2f2be6d5..f1430f49 100644 --- a/provider/workspace_tags.go +++ b/provider/workspace_tags.go @@ -2,7 +2,6 @@ package provider import ( "context" - "log" "github.com/google/uuid" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -23,12 +22,6 @@ func workspaceTagDataSource() *schema.Resource { Description: "Use this data source to configure workspace tags to select provisioners.", ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { rd.SetId(uuid.NewString()) - rawConfig := rd.GetRawConfig() - rawTags, ok := rawConfig.AsValueMap()["tag"] - if !ok { - return diag.Errorf("boom") - } - log.Println(rawTags) return nil }, Schema: map[string]*schema.Schema{ From 537e372f28580b2cc61c76c7ac74977823dd79a0 Mon Sep 17 00:00:00 2001 From: Marcin Tojek <marcin@coder.com> Date: Tue, 14 May 2024 15:04:20 +0200 Subject: [PATCH 05/10] unit test --- provider/workspace_tags_test.go | 54 +++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 provider/workspace_tags_test.go diff --git a/provider/workspace_tags_test.go b/provider/workspace_tags_test.go new file mode 100644 index 00000000..bda2c780 --- /dev/null +++ b/provider/workspace_tags_test.go @@ -0,0 +1,54 @@ +package provider_test + +import ( + "testing" + + "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" + + "github.com/coder/terraform-provider-coder/provider" +) + +func TestWorkspaceTags(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), + }, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: ` + provider "coder" { + } + data "coder_parameter" "animal" { + name = "animal" + type = "string" + default = "chris" + } + data "coder_workspace_tags" "wt" { + tag { + name = "cat" + value = "james" + } + tag { + name = "dog" + value = data.coder_parameter.animal.value + } + }`, + Check: func(state *terraform.State) error { + require.Len(t, state.Modules, 1) + require.Len(t, state.Modules[0].Resources, 2) + resource := state.Modules[0].Resources["data.coder_workspace_tags.wt"] + require.NotNil(t, resource) + + attribs := resource.Primary.Attributes + require.Equal(t, "cat", attribs["tag.0.name"]) + require.Equal(t, "james", attribs["tag.0.value"]) + require.Equal(t, "dog", attribs["tag.1.name"]) + require.Equal(t, "chris", attribs["tag.1.value"]) + return nil + }, + }}, + }) +} From 1d66a392116cac8438d1fdc3760643502e470637 Mon Sep 17 00:00:00 2001 From: Marcin Tojek <marcin@coder.com> Date: Wed, 15 May 2024 11:15:56 +0200 Subject: [PATCH 06/10] Env --- provider/examples_test.go | 47 ++++++++++++++++++++++---------------- provider/workspace_tags.go | 2 ++ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/provider/examples_test.go b/provider/examples_test.go index 6fa73d21..e612a1db 100644 --- a/provider/examples_test.go +++ b/provider/examples_test.go @@ -2,6 +2,7 @@ package provider_test import ( "os" + "path/filepath" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -11,28 +12,34 @@ import ( "github.com/coder/terraform-provider-coder/provider" ) -func TestExamples(t *testing.T) { +func TestExamples_CoderParameter(t *testing.T) { t.Parallel() - for _, testDir := range []string{ - "coder_parameter", - "coder_workspace_tags", - } { - t.Run(testDir, func(t *testing.T) { - testDir := testDir - t.Parallel() - - resource.Test(t, resource.TestCase{ - Providers: map[string]*schema.Provider{ - "coder": provider.New(), - }, - IsUnitTest: true, - Steps: []resource.TestStep{{ - Config: mustReadFile(t, "../examples/resources/"+testDir+"/resource.tf"), - }}, - }) - }) - } + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), + }, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: mustReadFile(t, "../examples/resources/coder_workspace_tags/resource.tf"), + }}, + }) +} + +func TestExamples_CoderWorkspaceTags(t *testing.T) { + // no parallel as the test calls t.Setenv() + workDir := "../examples/resources/coder_workspace_tags" + t.Setenv(provider.TerraformWorkDirEnv, workDir) + + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), + }, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: mustReadFile(t, filepath.Join(workDir, "/resource.tf")), + }}, + }) } func mustReadFile(t *testing.T, path string) string { diff --git a/provider/workspace_tags.go b/provider/workspace_tags.go index f1430f49..1d754ab7 100644 --- a/provider/workspace_tags.go +++ b/provider/workspace_tags.go @@ -8,6 +8,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +const TerraformWorkDirEnv = "CODER_TF_WORK_DIR" + type WorkspaceTags struct { Tag []Tag } From f0f2f342b37178c793f3d5521042c9f632cd9de5 Mon Sep 17 00:00:00 2001 From: Marcin Tojek <marcin@coder.com> Date: Wed, 15 May 2024 12:29:50 +0200 Subject: [PATCH 07/10] just basic data resource --- provider/examples_test.go | 47 ++++++++++++++++---------------------- provider/workspace_tags.go | 2 -- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/provider/examples_test.go b/provider/examples_test.go index e612a1db..6fa73d21 100644 --- a/provider/examples_test.go +++ b/provider/examples_test.go @@ -2,7 +2,6 @@ package provider_test import ( "os" - "path/filepath" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -12,34 +11,28 @@ import ( "github.com/coder/terraform-provider-coder/provider" ) -func TestExamples_CoderParameter(t *testing.T) { +func TestExamples(t *testing.T) { t.Parallel() - resource.Test(t, resource.TestCase{ - Providers: map[string]*schema.Provider{ - "coder": provider.New(), - }, - IsUnitTest: true, - Steps: []resource.TestStep{{ - Config: mustReadFile(t, "../examples/resources/coder_workspace_tags/resource.tf"), - }}, - }) -} - -func TestExamples_CoderWorkspaceTags(t *testing.T) { - // no parallel as the test calls t.Setenv() - workDir := "../examples/resources/coder_workspace_tags" - t.Setenv(provider.TerraformWorkDirEnv, workDir) - - resource.Test(t, resource.TestCase{ - Providers: map[string]*schema.Provider{ - "coder": provider.New(), - }, - IsUnitTest: true, - Steps: []resource.TestStep{{ - Config: mustReadFile(t, filepath.Join(workDir, "/resource.tf")), - }}, - }) + for _, testDir := range []string{ + "coder_parameter", + "coder_workspace_tags", + } { + t.Run(testDir, func(t *testing.T) { + testDir := testDir + t.Parallel() + + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), + }, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: mustReadFile(t, "../examples/resources/"+testDir+"/resource.tf"), + }}, + }) + }) + } } func mustReadFile(t *testing.T, path string) string { diff --git a/provider/workspace_tags.go b/provider/workspace_tags.go index 1d754ab7..f1430f49 100644 --- a/provider/workspace_tags.go +++ b/provider/workspace_tags.go @@ -8,8 +8,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -const TerraformWorkDirEnv = "CODER_TF_WORK_DIR" - type WorkspaceTags struct { Tag []Tag } From 98d4df8c73aaeffa9930d4d7e92b033de140ce9a Mon Sep 17 00:00:00 2001 From: Marcin Tojek <marcin@coder.com> Date: Wed, 15 May 2024 12:46:10 +0200 Subject: [PATCH 08/10] fmt --- examples/resources/coder_workspace_tags/resource.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/resources/coder_workspace_tags/resource.tf b/examples/resources/coder_workspace_tags/resource.tf index 392d328c..00ad198d 100644 --- a/examples/resources/coder_workspace_tags/resource.tf +++ b/examples/resources/coder_workspace_tags/resource.tf @@ -51,7 +51,7 @@ data "coder_workspace_tags" "custom_workspace_tags" { } tag { name = "debug" - value = "${data.coder_parameter.feature_debug_enabled.value}" + value = "${data.coder_parameter.feature_debug_enabled.value}+12345" } tag { name = "cache" From 9a46f65b745161878254207eb7783b3e8ccac052 Mon Sep 17 00:00:00 2001 From: Marcin Tojek <marcin@coder.com> Date: Wed, 15 May 2024 17:23:15 +0200 Subject: [PATCH 09/10] Tags as map --- .../coder_workspace_tags/resource.tf | 20 +++--------- provider/workspace_tags.go | 31 +++---------------- 2 files changed, 10 insertions(+), 41 deletions(-) diff --git a/examples/resources/coder_workspace_tags/resource.tf b/examples/resources/coder_workspace_tags/resource.tf index 00ad198d..6c26b061 100644 --- a/examples/resources/coder_workspace_tags/resource.tf +++ b/examples/resources/coder_workspace_tags/resource.tf @@ -41,20 +41,10 @@ data "coder_parameter" "feature_debug_enabled" { } data "coder_workspace_tags" "custom_workspace_tags" { - tag { - name = "cluster" - value = "developers" - } - tag { - name = "os" - value = data.coder_parameter.os_selector.value - } - tag { - name = "debug" - value = "${data.coder_parameter.feature_debug_enabled.value}+12345" - } - tag { - name = "cache" - value = data.coder_parameter.feature_cache_enabled.value == "true" ? "nix-with-cache" : "no-cache" + tags = { + "cluster" = "developers" + "os" = data.coder_parameter.os_selector.value + "debug" = "${data.coder_parameter.feature_debug_enabled.value}+12345" + "cache" = data.coder_parameter.feature_cache_enabled.value == "true" ? "nix-with-cache" : "no-cache" } } \ No newline at end of file diff --git a/provider/workspace_tags.go b/provider/workspace_tags.go index f1430f49..088ff546 100644 --- a/provider/workspace_tags.go +++ b/provider/workspace_tags.go @@ -9,12 +9,7 @@ import ( ) type WorkspaceTags struct { - Tag []Tag -} - -type Tag struct { - Name string - Value string + Tags map[string]string } func workspaceTagDataSource() *schema.Resource { @@ -25,28 +20,12 @@ func workspaceTagDataSource() *schema.Resource { return nil }, Schema: map[string]*schema.Schema{ - "tag": { - Type: schema.TypeList, - Description: `Each "tag" block defines a workspace tag.`, + "tags": { + Type: schema.TypeMap, + Description: `Key-value map with workspace tags`, ForceNew: true, Optional: true, - MaxItems: 64, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "The name of the tag.", - ForceNew: true, - Required: true, - }, - "value": { - Type: schema.TypeString, - Description: "The value of the tag.", - ForceNew: true, - Required: true, - }, - }, - }, + Elem: &schema.Schema{Type: schema.TypeString}, }, }, } From 4aa79df87e1ae247f71888d3713090b3c3738ac0 Mon Sep 17 00:00:00 2001 From: Marcin Tojek <marcin@coder.com> Date: Wed, 15 May 2024 17:27:41 +0200 Subject: [PATCH 10/10] james and chris --- provider/workspace_tags_test.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/provider/workspace_tags_test.go b/provider/workspace_tags_test.go index bda2c780..2d0f1c49 100644 --- a/provider/workspace_tags_test.go +++ b/provider/workspace_tags_test.go @@ -27,13 +27,9 @@ func TestWorkspaceTags(t *testing.T) { default = "chris" } data "coder_workspace_tags" "wt" { - tag { - name = "cat" - value = "james" - } - tag { - name = "dog" - value = data.coder_parameter.animal.value + tags = { + "cat" = "james" + "dog" = data.coder_parameter.animal.value } }`, Check: func(state *terraform.State) error { @@ -43,10 +39,8 @@ func TestWorkspaceTags(t *testing.T) { require.NotNil(t, resource) attribs := resource.Primary.Attributes - require.Equal(t, "cat", attribs["tag.0.name"]) - require.Equal(t, "james", attribs["tag.0.value"]) - require.Equal(t, "dog", attribs["tag.1.name"]) - require.Equal(t, "chris", attribs["tag.1.value"]) + require.Equal(t, "james", attribs["tags.cat"]) + require.Equal(t, "chris", attribs["tags.dog"]) return nil }, }},