From e6eb012632948b4959f4705d5fece00a38dd1914 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Mon, 15 Jul 2024 05:51:05 +0000 Subject: [PATCH 1/9] chore: add acceptance tests to user data source --- internal/provider/user_data_source_test.go | 78 ++++++++++++++-------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/internal/provider/user_data_source_test.go b/internal/provider/user_data_source_test.go index 6c5c0df..fea867c 100644 --- a/internal/provider/user_data_source_test.go +++ b/internal/provider/user_data_source_test.go @@ -1,57 +1,80 @@ package provider -/* import ( + "context" "html/template" "strings" "testing" + "github.com/coder/coder/v2/codersdk" + "github.com/coder/terraform-provider-coderd/integration" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/stretchr/testify/require" ) func TestAccUserDataSource(t *testing.T) { + ctx := context.Background() + client := integration.StartCoder(ctx, t, "user_acc") + firstUser, err := client.User(ctx, codersdk.Me) + require.NoError(t, err) + user, err := client.CreateUser(ctx, codersdk.CreateUserRequest{ + Email: "example@coder.com", + Username: "example", + Password: "SomeSecurePassword!", + UserLoginType: "password", + OrganizationID: firstUser.OrganizationIDs[0], + }) + require.NoError(t, err) + _, err = client.UpdateUserRoles(ctx, user.Username, codersdk.UpdateRoles{ + Roles: []string{"auditor"}, + }) + require.NoError(t, err) + _, err = client.UpdateUserProfile(ctx, user.Username, codersdk.UpdateUserProfileRequest{ + Username: user.Username, + Name: "Example User", + }) + require.NoError(t, err) + cfg := testAccUserDataSourceConfig{ + URL: client.URL.String(), + Token: client.SessionToken(), + } // User by Username + cfg.Username = user.Username resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccUserDataSourceConfig{ - Username: "example", - }.String(t), + Config: cfg.String(t), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("coderd_user.test", "username", "example"), - resource.TestCheckResourceAttr("coderd_user.test", "name", "Example User"), - resource.TestCheckResourceAttr("coderd_user.test", "email", "example@coder.com"), - resource.TestCheckResourceAttr("coderd_user.test", "roles.#", "2"), - resource.TestCheckResourceAttr("coderd_user.test", "roles.0", "auditor"), - resource.TestCheckResourceAttr("coderd_user.test", "roles.1", "owner"), - resource.TestCheckResourceAttr("coderd_user.test", "login_type", "password"), - resource.TestCheckResourceAttr("coderd_user.test", "password", "SomeSecurePassword!"), - resource.TestCheckResourceAttr("coderd_user.test", "suspended", "false"), + resource.TestCheckResourceAttr("data.coderd_user.test", "username", "example"), + resource.TestCheckResourceAttr("data.coderd_user.test", "name", "Example User"), + resource.TestCheckResourceAttr("data.coderd_user.test", "email", "example@coder.com"), + resource.TestCheckResourceAttr("data.coderd_user.test", "roles.#", "1"), + resource.TestCheckResourceAttr("data.coderd_user.test", "roles.0", "auditor"), + resource.TestCheckResourceAttr("data.coderd_user.test", "login_type", "password"), + resource.TestCheckResourceAttr("data.coderd_user.test", "suspended", "false"), ), }, }, }) + cfg.Username = "" + cfg.ID = user.ID.String() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, // User by ID Steps: []resource.TestStep{ { - Config: testAccUserDataSourceConfig{ - ID: "example", - }.String(t), + Config: cfg.String(t), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("coderd_user.test", "username", "example"), - resource.TestCheckResourceAttr("coderd_user.test", "name", "Example User"), - resource.TestCheckResourceAttr("coderd_user.test", "email", "example@coder.com"), - resource.TestCheckResourceAttr("coderd_user.test", "roles.#", "2"), - resource.TestCheckResourceAttr("coderd_user.test", "roles.0", "auditor"), - resource.TestCheckResourceAttr("coderd_user.test", "roles.1", "owner"), - resource.TestCheckResourceAttr("coderd_user.test", "login_type", "password"), - resource.TestCheckResourceAttr("coderd_user.test", "password", "SomeSecurePassword!"), - resource.TestCheckResourceAttr("coderd_user.test", "suspended", "false"), + resource.TestCheckResourceAttr("data.coderd_user.test", "username", "example"), + resource.TestCheckResourceAttr("data.coderd_user.test", "name", "Example User"), + resource.TestCheckResourceAttr("data.coderd_user.test", "email", "example@coder.com"), + resource.TestCheckResourceAttr("data.coderd_user.test", "roles.#", "1"), + resource.TestCheckResourceAttr("data.coderd_user.test", "roles.0", "auditor"), + resource.TestCheckResourceAttr("data.coderd_user.test", "login_type", "password"), + resource.TestCheckResourceAttr("data.coderd_user.test", "suspended", "false"), ), }, }, @@ -59,8 +82,8 @@ func TestAccUserDataSource(t *testing.T) { } type testAccUserDataSourceConfig struct { - URL string - Token string + URL string + Token string ID string Username string @@ -92,4 +115,3 @@ data "coderd_user" "test" { return buf.String() } -*/ From 34851702a65db48542fa84572194fecceed6b23a Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Mon, 15 Jul 2024 06:38:30 +0000 Subject: [PATCH 2/9] error test --- internal/provider/user_data_source_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/internal/provider/user_data_source_test.go b/internal/provider/user_data_source_test.go index fea867c..9b71e2a 100644 --- a/internal/provider/user_data_source_test.go +++ b/internal/provider/user_data_source_test.go @@ -3,6 +3,7 @@ package provider import ( "context" "html/template" + "regexp" "strings" "testing" @@ -79,6 +80,20 @@ func TestAccUserDataSource(t *testing.T) { }, }, }) + cfg.ID = "" + resource.Test(t, resource.TestCase{ + IsUnitTest: true, + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + // Neither ID nor Username + Steps: []resource.TestStep{ + { + Config: cfg.String(t), + ExpectError: regexp.MustCompile(`At least one of these attributes must be configured: \[id,username\]`), + }, + }, + }) + } type testAccUserDataSourceConfig struct { From bd799f3118152db62b745788f54aad235b5ab485 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Mon, 15 Jul 2024 06:57:31 +0000 Subject: [PATCH 3/9] review --- internal/provider/user_data_source_test.go | 115 +++++++++++---------- 1 file changed, 63 insertions(+), 52 deletions(-) diff --git a/internal/provider/user_data_source_test.go b/internal/provider/user_data_source_test.go index 9b71e2a..7d8c8a7 100644 --- a/internal/provider/user_data_source_test.go +++ b/internal/provider/user_data_source_test.go @@ -35,63 +35,74 @@ func TestAccUserDataSource(t *testing.T) { Name: "Example User", }) require.NoError(t, err) - cfg := testAccUserDataSourceConfig{ - URL: client.URL.String(), - Token: client.SessionToken(), - } - // User by Username - cfg.Username = user.Username - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, - Steps: []resource.TestStep{ - { - Config: cfg.String(t), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("data.coderd_user.test", "username", "example"), - resource.TestCheckResourceAttr("data.coderd_user.test", "name", "Example User"), - resource.TestCheckResourceAttr("data.coderd_user.test", "email", "example@coder.com"), - resource.TestCheckResourceAttr("data.coderd_user.test", "roles.#", "1"), - resource.TestCheckResourceAttr("data.coderd_user.test", "roles.0", "auditor"), - resource.TestCheckResourceAttr("data.coderd_user.test", "login_type", "password"), - resource.TestCheckResourceAttr("data.coderd_user.test", "suspended", "false"), - ), + t.Run("UserByUsername", func(t *testing.T) { + cfg := testAccUserDataSourceConfig{ + URL: client.URL.String(), + Token: client.SessionToken(), + Username: user.Username, + } + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: cfg.String(t), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.coderd_user.test", "username", "example"), + resource.TestCheckResourceAttr("data.coderd_user.test", "name", "Example User"), + resource.TestCheckResourceAttr("data.coderd_user.test", "email", "example@coder.com"), + resource.TestCheckResourceAttr("data.coderd_user.test", "roles.#", "1"), + resource.TestCheckResourceAttr("data.coderd_user.test", "roles.0", "auditor"), + resource.TestCheckResourceAttr("data.coderd_user.test", "login_type", "password"), + resource.TestCheckResourceAttr("data.coderd_user.test", "suspended", "false"), + ), + }, }, - }, + }) }) - cfg.Username = "" - cfg.ID = user.ID.String() - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, - // User by ID - Steps: []resource.TestStep{ - { - Config: cfg.String(t), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("data.coderd_user.test", "username", "example"), - resource.TestCheckResourceAttr("data.coderd_user.test", "name", "Example User"), - resource.TestCheckResourceAttr("data.coderd_user.test", "email", "example@coder.com"), - resource.TestCheckResourceAttr("data.coderd_user.test", "roles.#", "1"), - resource.TestCheckResourceAttr("data.coderd_user.test", "roles.0", "auditor"), - resource.TestCheckResourceAttr("data.coderd_user.test", "login_type", "password"), - resource.TestCheckResourceAttr("data.coderd_user.test", "suspended", "false"), - ), + + t.Run("UserByID", func(t *testing.T) { + cfg := testAccUserDataSourceConfig{ + URL: client.URL.String(), + Token: client.SessionToken(), + Username: user.ID.String(), + } + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + // User by ID + Steps: []resource.TestStep{ + { + Config: cfg.String(t), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.coderd_user.test", "username", "example"), + resource.TestCheckResourceAttr("data.coderd_user.test", "name", "Example User"), + resource.TestCheckResourceAttr("data.coderd_user.test", "email", "example@coder.com"), + resource.TestCheckResourceAttr("data.coderd_user.test", "roles.#", "1"), + resource.TestCheckResourceAttr("data.coderd_user.test", "roles.0", "auditor"), + resource.TestCheckResourceAttr("data.coderd_user.test", "login_type", "password"), + resource.TestCheckResourceAttr("data.coderd_user.test", "suspended", "false"), + ), + }, }, - }, + }) }) - cfg.ID = "" - resource.Test(t, resource.TestCase{ - IsUnitTest: true, - PreCheck: func() { testAccPreCheck(t) }, - ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, - // Neither ID nor Username - Steps: []resource.TestStep{ - { - Config: cfg.String(t), - ExpectError: regexp.MustCompile(`At least one of these attributes must be configured: \[id,username\]`), + t.Run("NeitherIDNorUsername", func(t *testing.T) { + cfg := testAccUserDataSourceConfig{ + URL: client.URL.String(), + Token: client.SessionToken(), + } + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + // Neither ID nor Username + Steps: []resource.TestStep{ + { + Config: cfg.String(t), + ExpectError: regexp.MustCompile(`At least one of these attributes must be configured: \[id,username\]`), + }, }, - }, + }) }) } From 0f716edd7bca0229fb78239a0280051e12adbf24 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Mon, 15 Jul 2024 06:58:03 +0000 Subject: [PATCH 4/9] fixup --- internal/provider/user_data_source_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/provider/user_data_source_test.go b/internal/provider/user_data_source_test.go index 7d8c8a7..9bfc607 100644 --- a/internal/provider/user_data_source_test.go +++ b/internal/provider/user_data_source_test.go @@ -15,7 +15,7 @@ import ( func TestAccUserDataSource(t *testing.T) { ctx := context.Background() - client := integration.StartCoder(ctx, t, "user_acc") + client := integration.StartCoder(ctx, t, "user_data_acc") firstUser, err := client.User(ctx, codersdk.Me) require.NoError(t, err) user, err := client.CreateUser(ctx, codersdk.CreateUserRequest{ From eece858606a7dbe25d70e1fa625bfa5920e53c54 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Mon, 15 Jul 2024 06:58:33 +0000 Subject: [PATCH 5/9] gen + fmt --- docs/data-sources/user.md | 3 ++- integration/user-test/main.tf | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/data-sources/user.md b/docs/data-sources/user.md index 88c9a1f..2b12670 100644 --- a/docs/data-sources/user.md +++ b/docs/data-sources/user.md @@ -22,11 +22,12 @@ An existing user on the coder deployment ### Read-Only +- `avatar_url` (String) URL of the user's avatar. - `created_at` (Number) Unix timestamp of when the user was created. - `email` (String) Email of the user. - `last_seen_at` (Number) Unix timestamp of when the user was last seen. - `login_type` (String) Type of login for the user. Valid types are 'none', 'password', 'github', and 'oidc'. -- `name` (String) Display name of the user. Defaults to username. +- `name` (String) Display name of the user. - `organization_ids` (Set of String) IDs of organizations the user is associated with. - `roles` (Set of String) Roles assigned to the user. Valid roles are 'owner', 'template-admin', 'user-admin', and 'auditor'. - `suspended` (Boolean) Whether the user is suspended. diff --git a/integration/user-test/main.tf b/integration/user-test/main.tf index 3b05004..922cabb 100644 --- a/integration/user-test/main.tf +++ b/integration/user-test/main.tf @@ -22,11 +22,11 @@ data "coderd_user" "ethan" { } resource "coderd_user" "ethan2" { - username = "${data.coderd_user.ethan.username}2" - name = "${data.coderd_user.ethan.name}2" - email = "${data.coderd_user.ethan.email}.au" - login_type = "${data.coderd_user.ethan.login_type}" - roles = data.coderd_user.ethan.roles - suspended = data.coderd_user.ethan.suspended + username = "${data.coderd_user.ethan.username}2" + name = "${data.coderd_user.ethan.name}2" + email = "${data.coderd_user.ethan.email}.au" + login_type = data.coderd_user.ethan.login_type + roles = data.coderd_user.ethan.roles + suspended = data.coderd_user.ethan.suspended } From f149934467e8e5b821254055ec6961512e21405e Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Mon, 15 Jul 2024 07:20:23 +0000 Subject: [PATCH 6/9] add skip --- internal/provider/user_data_source_test.go | 4 ++++ internal/provider/user_resource_test.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/internal/provider/user_data_source_test.go b/internal/provider/user_data_source_test.go index 9bfc607..bf6bdcb 100644 --- a/internal/provider/user_data_source_test.go +++ b/internal/provider/user_data_source_test.go @@ -3,6 +3,7 @@ package provider import ( "context" "html/template" + "os" "regexp" "strings" "testing" @@ -14,6 +15,9 @@ import ( ) func TestAccUserDataSource(t *testing.T) { + if os.Getenv("TF_ACC") == "" { + t.Skip("Acceptance tests are disabled.") + } ctx := context.Background() client := integration.StartCoder(ctx, t, "user_data_acc") firstUser, err := client.User(ctx, codersdk.Me) diff --git a/internal/provider/user_resource_test.go b/internal/provider/user_resource_test.go index c95ace0..f955310 100644 --- a/internal/provider/user_resource_test.go +++ b/internal/provider/user_resource_test.go @@ -3,6 +3,7 @@ package provider import ( "context" "fmt" + "os" "strings" "testing" "text/template" @@ -13,6 +14,9 @@ import ( ) func TestAccUserResource(t *testing.T) { + if os.Getenv("TF_ACC") == "" { + t.Skip("Acceptance tests are disabled.") + } ctx := context.Background() client := integration.StartCoder(ctx, t, "user_acc") From c524e5434025201905d311e1059f04f07711ec4f Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Tue, 16 Jul 2024 03:02:50 +0000 Subject: [PATCH 7/9] validate retrieved id/username against provided --- internal/provider/user_data_source.go | 7 +++++++ internal/provider/user_data_source_test.go | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/internal/provider/user_data_source.go b/internal/provider/user_data_source.go index 8254fe1..a8654ce 100644 --- a/internal/provider/user_data_source.go +++ b/internal/provider/user_data_source.go @@ -155,6 +155,13 @@ func (d *UserDataSource) Read(ctx context.Context, req datasource.ReadRequest, r resp.Diagnostics.AddError("Client Error", "User is not associated with any organizations") return } + if !data.ID.IsNull() && user.ID.String() != data.ID.ValueString() { + resp.Diagnostics.AddError("Client Error", "Retrieved User's ID does not match the provided ID") + return + } else if !data.Username.IsNull() && user.Username != data.Username.ValueString() { + resp.Diagnostics.AddError("Client Error", "Retrieved User's username does not match the provided username") + return + } data.ID = types.StringValue(user.ID.String()) data.Username = types.StringValue(user.Username) diff --git a/internal/provider/user_data_source_test.go b/internal/provider/user_data_source_test.go index bf6bdcb..b3e3987 100644 --- a/internal/provider/user_data_source_test.go +++ b/internal/provider/user_data_source_test.go @@ -67,9 +67,9 @@ func TestAccUserDataSource(t *testing.T) { t.Run("UserByID", func(t *testing.T) { cfg := testAccUserDataSourceConfig{ - URL: client.URL.String(), - Token: client.SessionToken(), - Username: user.ID.String(), + URL: client.URL.String(), + Token: client.SessionToken(), + ID: user.ID.String(), } resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, From 034e1c23accf96cf01b58b3c5c11348febd791b4 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Tue, 16 Jul 2024 03:04:32 +0000 Subject: [PATCH 8/9] fixup --- integration/user-test/main.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/integration/user-test/main.tf b/integration/user-test/main.tf index 922cabb..aa2e225 100644 --- a/integration/user-test/main.tf +++ b/integration/user-test/main.tf @@ -25,7 +25,6 @@ resource "coderd_user" "ethan2" { username = "${data.coderd_user.ethan.username}2" name = "${data.coderd_user.ethan.name}2" email = "${data.coderd_user.ethan.email}.au" - login_type = data.coderd_user.ethan.login_type roles = data.coderd_user.ethan.roles suspended = data.coderd_user.ethan.suspended } From b697236a50f00cc1fc6e47ede65c4af575674809 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Tue, 16 Jul 2024 03:05:03 +0000 Subject: [PATCH 9/9] fixup2 --- integration/user-test/main.tf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/integration/user-test/main.tf b/integration/user-test/main.tf index aa2e225..a0cebbe 100644 --- a/integration/user-test/main.tf +++ b/integration/user-test/main.tf @@ -22,10 +22,10 @@ data "coderd_user" "ethan" { } resource "coderd_user" "ethan2" { - username = "${data.coderd_user.ethan.username}2" - name = "${data.coderd_user.ethan.name}2" - email = "${data.coderd_user.ethan.email}.au" - roles = data.coderd_user.ethan.roles - suspended = data.coderd_user.ethan.suspended + username = "${data.coderd_user.ethan.username}2" + name = "${data.coderd_user.ethan.name}2" + email = "${data.coderd_user.ethan.email}.au" + roles = data.coderd_user.ethan.roles + suspended = data.coderd_user.ethan.suspended } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy