From 4f9201481404d78754711bc5fb1982d56a869e4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 16:05:51 +0300 Subject: [PATCH 1/7] build(deps): Bump contributor-assistant/github-action from 2.3.2 to 2.4.0 (#221) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/cla.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml index db910ed8..412cac6b 100644 --- a/.github/workflows/cla.yaml +++ b/.github/workflows/cla.yaml @@ -11,7 +11,7 @@ jobs: steps: - name: "CLA Assistant" if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' - uses: contributor-assistant/github-action@v2.3.2 + uses: contributor-assistant/github-action@v2.4.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # the below token should have repo scope and must be manually added by you in the repository's secret From d921c8319d4d9108489bde8703d3fc5425923052 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 May 2024 12:20:00 +0300 Subject: [PATCH 2/7] build(deps): Bump goreleaser/goreleaser-action from 5.0.0 to 5.1.0 (#225) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0c21c4ac..00fd83ec 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,7 +38,7 @@ jobs: passphrase: ${{ secrets.PASSPHRASE }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v5.0.0 + uses: goreleaser/goreleaser-action@v5.1.0 with: version: latest args: release --rm-dist From 2642fa5e14d1a0bf87b9ce4abc4a4db5f209d307 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Thu, 23 May 2024 12:45:44 +0100 Subject: [PATCH 3/7] chore: add devcontainer config (#228) --- .devcontainer/devcontainer.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..fa152f4d --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,9 @@ +{ + "name": "terraform-provider-coder", + "image": "mcr.microsoft.com/devcontainers/go:1.20", + "features": { + "ghcr.io/devcontainers/features/terraform:1": { + "installTerraformDocs": true + } + } +} From c683ad5b3888469cc26d625b6c890f70a022a024 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Thu, 23 May 2024 12:45:53 +0100 Subject: [PATCH 4/7] chore: add terraform 1.8.x to test matrix (#229) --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5830a500..fefaf2f5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,6 +54,7 @@ jobs: - "1.5.*" - "1.6.*" - "1.7.*" + - "1.8.*" steps: - name: Set up Go uses: actions/setup-go@v5 From 7e5a28b99dfea0f40526b0bedd61aac39c1b3d9e Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 24 May 2024 14:45:08 +0100 Subject: [PATCH 5/7] chore: make gen to add missing docs (#231) --- docs/data-sources/workspace_tags.md | 24 +++++++++++++++++++ docs/resources/metadata.md | 7 ++++++ examples/resources/coder_metadata/resource.tf | 7 ++++++ 3 files changed, 38 insertions(+) create mode 100644 docs/data-sources/workspace_tags.md diff --git a/docs/data-sources/workspace_tags.md b/docs/data-sources/workspace_tags.md new file mode 100644 index 00000000..62f72b0f --- /dev/null +++ b/docs/data-sources/workspace_tags.md @@ -0,0 +1,24 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "coder_workspace_tags Data Source - terraform-provider-coder" +subcategory: "" +description: |- + Use this data source to configure workspace tags to select provisioners. +--- + +# coder_workspace_tags (Data Source) + +Use this data source to configure workspace tags to select provisioners. + + + + +## Schema + +### Optional + +- `tags` (Map of String) Key-value map with workspace tags + +### Read-Only + +- `id` (String) The ID of this resource. diff --git a/docs/resources/metadata.md b/docs/resources/metadata.md index 2d67e526..9d6ff92f 100644 --- a/docs/resources/metadata.md +++ b/docs/resources/metadata.md @@ -18,6 +18,13 @@ data "coder_workspace" "me" { resource "kubernetes_pod" "dev" { count = data.coder_workspace.me.start_count + metadata { + name = "k8s_example" + namespace = "example" + } + spec { + # Draw the rest of the pod! + } } resource "tls_private_key" "example_key_pair" { diff --git a/examples/resources/coder_metadata/resource.tf b/examples/resources/coder_metadata/resource.tf index c4facfbb..0491ce57 100644 --- a/examples/resources/coder_metadata/resource.tf +++ b/examples/resources/coder_metadata/resource.tf @@ -3,6 +3,13 @@ data "coder_workspace" "me" { resource "kubernetes_pod" "dev" { count = data.coder_workspace.me.start_count + metadata { + name = "k8s_example" + namespace = "example" + } + spec { + # Draw the rest of the pod! + } } resource "tls_private_key" "example_key_pair" { From eb43b9f95bbbb54af72496b3a72f05c6dfffacbf Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 24 May 2024 14:48:20 +0100 Subject: [PATCH 6/7] feat: add coder_workspace_owner datasource (#230) - Adds a coder_workspace_owner data source populated from fields of coder_workspace prefix with `owner_`. - Adds `coder_workspace_owner.ssh_{public,private}_key`. - Deprecates same fields of coder_workspace. --- docs/data-sources/workspace.md | 14 +-- docs/data-sources/workspace_owner.md | 28 ++++++ provider/provider.go | 13 +-- provider/workspace.go | 7 ++ provider/workspace_owner.go | 127 +++++++++++++++++++++++++++ provider/workspace_owner_test.go | 119 +++++++++++++++++++++++++ provider/workspace_test.go | 4 + 7 files changed, 299 insertions(+), 13 deletions(-) create mode 100644 docs/data-sources/workspace_owner.md create mode 100644 provider/workspace_owner.go create mode 100644 provider/workspace_owner_test.go diff --git a/docs/data-sources/workspace.md b/docs/data-sources/workspace.md index 2ed7c63d..2a813722 100644 --- a/docs/data-sources/workspace.md +++ b/docs/data-sources/workspace.md @@ -30,13 +30,13 @@ 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) Username of the workspace owner. -- `owner_email` (String) Email address of the workspace owner. -- `owner_groups` (List of String) List of groups the workspace owner belongs to. -- `owner_id` (String) UUID of the workspace owner. -- `owner_name` (String) Name of the workspace owner. -- `owner_oidc_access_token` (String) 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) Session token for authenticating with a Coder deployment. It is regenerated everytime a workspace is started. +- `owner` (String, Deprecated) Username of the workspace owner. +- `owner_email` (String, Deprecated) Email address of the workspace owner. +- `owner_groups` (List of String, Deprecated) List of groups the workspace owner belongs to. +- `owner_id` (String, Deprecated) UUID of the workspace owner. +- `owner_name` (String, Deprecated) Name of the workspace owner. +- `owner_oidc_access_token` (String, Deprecated) 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) 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 new file mode 100644 index 00000000..646b1340 --- /dev/null +++ b/docs/data-sources/workspace_owner.md @@ -0,0 +1,28 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "coder_workspace_owner Data Source - terraform-provider-coder" +subcategory: "" +description: |- + Use this data source to fetch information about the workspace owner. +--- + +# coder_workspace_owner (Data Source) + +Use this data source to fetch information about the workspace owner. + + + + +## Schema + +### Read-Only + +- `email` (String) The email address of the user. +- `full_name` (String) The full name of the user. +- `groups` (List of String) The groups of which the user is a member. +- `id` (String) The UUID of the workspace owner. +- `name` (String) The username of the user. +- `oidc_access_token` (String) 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. +- `session_token` (String) Session token for authenticating with a Coder deployment. It is regenerated every time a workspace is started. +- `ssh_private_key` (String, Sensitive) The user's generated SSH private key. +- `ssh_public_key` (String) The user's generated SSH public key. diff --git a/provider/provider.go b/provider/provider.go index 4ea75ba8..c1991a26 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -68,12 +68,13 @@ func New() *schema.Provider { }, nil }, DataSourcesMap: map[string]*schema.Resource{ - "coder_workspace": workspaceDataSource(), - "coder_workspace_tags": workspaceTagDataSource(), - "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(), + "coder_workspace_owner": workspaceOwnerDataSource(), }, ResourcesMap: map[string]*schema.Resource{ "coder_agent": agentResource(), diff --git a/provider/workspace.go b/provider/workspace.go index b8ff1684..098d64cc 100644 --- a/provider/workspace.go +++ b/provider/workspace.go @@ -135,21 +135,25 @@ func workspaceDataSource() *schema.Resource { 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, @@ -157,6 +161,7 @@ func workspaceDataSource() *schema.Resource { 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, @@ -165,6 +170,7 @@ func workspaceDataSource() *schema.Resource { }, Computed: true, Description: "List of groups the workspace owner belongs to.", + Deprecated: "Use `coder_workspace_owner.groups` instead.", }, "id": { Type: schema.TypeString, @@ -180,6 +186,7 @@ func workspaceDataSource() *schema.Resource { 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, diff --git a/provider/workspace_owner.go b/provider/workspace_owner.go new file mode 100644 index 00000000..5721b5c5 --- /dev/null +++ b/provider/workspace_owner.go @@ -0,0 +1,127 @@ +package provider + +import ( + "context" + "encoding/json" + "os" + "strings" + + "github.com/google/uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +type Role struct { + Name string `json:"name"` + DisplayName string `json:"display-name"` +} + +func workspaceOwnerDataSource() *schema.Resource { + return &schema.Resource{ + Description: "Use this data source to fetch information about the workspace owner.", + ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { + if idStr, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_ID"); ok { + rd.SetId(idStr) + } else { + rd.SetId(uuid.NewString()) + } + + if username, ok := os.LookupEnv("CODER_WORKSPACE_OWNER"); ok { + _ = rd.Set("name", username) + } else { + _ = rd.Set("name", "default") + } + + if fullname, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_NAME"); ok { + _ = rd.Set("full_name", fullname) + } else { // compat: field can be blank, fill in default + _ = rd.Set("full_name", "default") + } + + if email, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_EMAIL"); ok { + _ = rd.Set("email", email) + } else { + _ = rd.Set("email", "default@example.com") + } + + if sshPubKey, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_SSH_PUBLIC_KEY"); ok { + _ = rd.Set("ssh_public_key", sshPubKey) + } + + if sshPrivKey, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_SSH_PRIVATE_KEY"); ok { + _ = rd.Set("ssh_private_key", sshPrivKey) + } + + var groups []string + if groupsRaw, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_GROUPS"); ok { + if err := json.NewDecoder(strings.NewReader(groupsRaw)).Decode(&groups); err != nil { + return diag.Errorf("invalid user groups: %s", err.Error()) + } + _ = rd.Set("groups", groups) + } + + if tok, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_SESSION_TOKEN"); ok { + _ = rd.Set("session_token", tok) + } + + if tok, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN"); ok { + _ = rd.Set("oidc_access_token", tok) + } + + return nil + }, + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The UUID of the workspace owner.", + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: "The username of the user.", + }, + "full_name": { + Type: schema.TypeString, + Computed: true, + Description: "The full name of the user.", + }, + "email": { + Type: schema.TypeString, + Computed: true, + Description: "The email address of the user.", + }, + "ssh_public_key": { + Type: schema.TypeString, + Computed: true, + Description: "The user's generated SSH public key.", + }, + "ssh_private_key": { + Type: schema.TypeString, + Computed: true, + Description: "The user's generated SSH private key.", + Sensitive: true, + }, + "groups": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Computed: true, + Description: "The groups of which the user is a member.", + }, + "session_token": { + Type: schema.TypeString, + Computed: true, + Description: "Session token for authenticating with a Coder deployment. It is regenerated every time a workspace is started.", + }, + "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.", + }, + }, + } +} diff --git a/provider/workspace_owner_test.go b/provider/workspace_owner_test.go new file mode 100644 index 00000000..90839cfc --- /dev/null +++ b/provider/workspace_owner_test.go @@ -0,0 +1,119 @@ +package provider_test + +import ( + "os" + "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/assert" + "github.com/stretchr/testify/require" +) + +const ( + testSSHEd25519PublicKey = `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJeNcdBMtd4Jo9f2W8RZef0ld7Ypye5zTQEf0vUXa/Eq owner123@host456` + // nolint:gosec // This key was generated specifically for this purpose. + testSSHEd25519PrivateKey = `-----BEGIN OPENSSH PRIVATE KEY----- + b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW + QyNTUxOQAAACCXjXHQTLXeCaPX9lvEWXn9JXe2Kcnuc00BH9L1F2vxKgAAAJgp3mfQKd5n + 0AAAAAtzc2gtZWQyNTUxOQAAACCXjXHQTLXeCaPX9lvEWXn9JXe2Kcnuc00BH9L1F2vxKg + AAAEBia7mAQFoLBILlvTJroTkOUomzfcPY9ckpViQOjYFkAZeNcdBMtd4Jo9f2W8RZef0l + d7Ypye5zTQEf0vUXa/EqAAAAE3ZzY29kZUAzY2Y4MWY5YmM3MmQBAg== + -----END OPENSSH PRIVATE KEY-----` +) + +func TestWorkspaceOwnerDatasource(t *testing.T) { + t.Run("OK", func(t *testing.T) { + t.Setenv("CODER_WORKSPACE_OWNER_ID", "11111111-1111-1111-1111-111111111111") + t.Setenv("CODER_WORKSPACE_OWNER", "owner123") + t.Setenv("CODER_WORKSPACE_OWNER_NAME", "Mr Owner") + t.Setenv("CODER_WORKSPACE_OWNER_EMAIL", "owner123@example.com") + t.Setenv("CODER_WORKSPACE_OWNER_SSH_PUBLIC_KEY", testSSHEd25519PublicKey) + t.Setenv("CODER_WORKSPACE_OWNER_SSH_PRIVATE_KEY", testSSHEd25519PrivateKey) + t.Setenv("CODER_WORKSPACE_OWNER_GROUPS", `["group1", "group2"]`) + t.Setenv("CODER_WORKSPACE_OWNER_SESSION_TOKEN", `supersecret`) + t.Setenv("CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN", `alsosupersecret`) + + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), + }, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: ` + provider "coder" {} + data "coder_workspace_owner" "me" {} + `, + Check: func(s *terraform.State) error { + require.Len(t, s.Modules, 1) + require.Len(t, s.Modules[0].Resources, 1) + resource := s.Modules[0].Resources["data.coder_workspace_owner.me"] + require.NotNil(t, resource) + + attrs := resource.Primary.Attributes + assert.Equal(t, "11111111-1111-1111-1111-111111111111", attrs["id"]) + assert.Equal(t, "owner123", attrs["name"]) + assert.Equal(t, "Mr Owner", attrs["full_name"]) + assert.Equal(t, "owner123@example.com", attrs["email"]) + assert.Equal(t, testSSHEd25519PublicKey, attrs["ssh_public_key"]) + assert.Equal(t, testSSHEd25519PrivateKey, attrs["ssh_private_key"]) + assert.Equal(t, `group1`, attrs["groups.0"]) + assert.Equal(t, `group2`, attrs["groups.1"]) + assert.Equal(t, `supersecret`, attrs["session_token"]) + assert.Equal(t, `alsosupersecret`, attrs["oidc_access_token"]) + return nil + }, + }}, + }) + }) + + t.Run("Defaults", func(t *testing.T) { + for _, v := range []string{ + "CODER_WORKSPACE_OWNER", + "CODER_WORKSPACE_OWNER_ID", + "CODER_WORKSPACE_OWNER_EMAIL", + "CODER_WORKSPACE_OWNER_NAME", + "CODER_WORKSPACE_OWNER_SESSION_TOKEN", + "CODER_WORKSPACE_OWNER_GROUPS", + "CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN", + "CODER_WORKSPACE_OWNER_SSH_PUBLIC_KEY", + "CODER_WORKSPACE_OWNER_SSH_PRIVATE_KEY", + } { // https://github.com/golang/go/issues/52817 + t.Setenv(v, "") + os.Unsetenv(v) + } + + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), + }, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: ` + provider "coder" {} + data "coder_workspace_owner" "me" {} + `, + Check: func(s *terraform.State) error { + require.Len(t, s.Modules, 1) + require.Len(t, s.Modules[0].Resources, 1) + resource := s.Modules[0].Resources["data.coder_workspace_owner.me"] + require.NotNil(t, resource) + + attrs := resource.Primary.Attributes + assert.NotEmpty(t, attrs["id"]) + assert.Equal(t, "default", attrs["name"]) + assert.Equal(t, "default", attrs["full_name"]) + assert.Equal(t, "default@example.com", attrs["email"]) + assert.Empty(t, attrs["ssh_public_key"]) + assert.Empty(t, attrs["ssh_private_key"]) + assert.Empty(t, attrs["groups.0"]) + assert.Empty(t, attrs["session_token"]) + assert.Empty(t, attrs["oidc_access_token"]) + return nil + }, + }}, + }) + }) +} diff --git a/provider/workspace_test.go b/provider/workspace_test.go index d5866af5..d285b30c 100644 --- a/provider/workspace_test.go +++ b/provider/workspace_test.go @@ -14,10 +14,12 @@ 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") @@ -47,6 +49,7 @@ func TestWorkspace(t *testing.T) { 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"]) @@ -54,6 +57,7 @@ func TestWorkspace(t *testing.T) { 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 }, }}, From 96993eb480472411a8bfb198893d4a8752a38a94 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Mon, 27 May 2024 09:30:48 +0100 Subject: [PATCH 7/7] fix: provider: coder_workspace_owner: avoid setting null values (#232) * chore: add coder_workspace_owner to TestProviderEmpty, rm unused struct * fix: do not set null values --- provider/provider_test.go | 1 + provider/workspace_owner.go | 33 +++++++++------------------------ 2 files changed, 10 insertions(+), 24 deletions(-) diff --git a/provider/provider_test.go b/provider/provider_test.go index c1e3c686..7069db09 100644 --- a/provider/provider_test.go +++ b/provider/provider_test.go @@ -33,6 +33,7 @@ func TestProviderEmpty(t *testing.T) { provider "coder" {} data "coder_provisioner" "me" {} data "coder_workspace" "me" {} + data "coder_workspace_owner" "me" {} data "coder_external_auth" "git" { id = "git" } diff --git a/provider/workspace_owner.go b/provider/workspace_owner.go index 5721b5c5..13e36187 100644 --- a/provider/workspace_owner.go +++ b/provider/workspace_owner.go @@ -11,62 +11,47 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -type Role struct { - Name string `json:"name"` - DisplayName string `json:"display-name"` -} - func workspaceOwnerDataSource() *schema.Resource { return &schema.Resource{ Description: "Use this data source to fetch information about the workspace owner.", ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { - if idStr, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_ID"); ok { + if idStr := os.Getenv("CODER_WORKSPACE_OWNER_ID"); idStr != "" { rd.SetId(idStr) } else { rd.SetId(uuid.NewString()) } - if username, ok := os.LookupEnv("CODER_WORKSPACE_OWNER"); ok { + if username := os.Getenv("CODER_WORKSPACE_OWNER"); username != "" { _ = rd.Set("name", username) } else { _ = rd.Set("name", "default") } - if fullname, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_NAME"); ok { + if fullname := os.Getenv("CODER_WORKSPACE_OWNER_NAME"); fullname != "" { _ = rd.Set("full_name", fullname) } else { // compat: field can be blank, fill in default _ = rd.Set("full_name", "default") } - if email, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_EMAIL"); ok { + if email := os.Getenv("CODER_WORKSPACE_OWNER_EMAIL"); email != "" { _ = rd.Set("email", email) } else { _ = rd.Set("email", "default@example.com") } - if sshPubKey, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_SSH_PUBLIC_KEY"); ok { - _ = rd.Set("ssh_public_key", sshPubKey) - } - - if sshPrivKey, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_SSH_PRIVATE_KEY"); ok { - _ = rd.Set("ssh_private_key", sshPrivKey) - } + _ = rd.Set("ssh_public_key", os.Getenv("CODER_WORKSPACE_OWNER_SSH_PUBLIC_KEY")) + _ = rd.Set("ssh_private_key", os.Getenv("CODER_WORKSPACE_OWNER_SSH_PRIVATE_KEY")) var groups []string if groupsRaw, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_GROUPS"); ok { if err := json.NewDecoder(strings.NewReader(groupsRaw)).Decode(&groups); err != nil { return diag.Errorf("invalid user groups: %s", err.Error()) } - _ = rd.Set("groups", groups) - } - - if tok, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_SESSION_TOKEN"); ok { - _ = rd.Set("session_token", tok) } + _ = rd.Set("groups", groups) - if tok, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN"); ok { - _ = rd.Set("oidc_access_token", tok) - } + _ = rd.Set("session_token", os.Getenv("CODER_WORKSPACE_OWNER_SESSION_TOKEN")) + _ = rd.Set("oidc_access_token", os.Getenv("CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN")) return nil },