From 375a205ee910539256152ea3902f84e323dde534 Mon Sep 17 00:00:00 2001 From: Ethan <39577870+ethanndickson@users.noreply.github.com> Date: Tue, 16 Jul 2024 13:07:58 +1000 Subject: [PATCH] chore: add acceptance tests to user data source (#23) --- docs/data-sources/user.md | 3 +- integration/user-test/main.tf | 9 +- internal/provider/user_data_source.go | 7 + internal/provider/user_data_source_test.go | 144 ++++++++++++++------- internal/provider/user_resource_test.go | 4 + 5 files changed, 115 insertions(+), 52 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 46cb6f6..83bd655 100644 --- a/integration/user-test/main.tf +++ b/integration/user-test/main.tf @@ -22,10 +22,9 @@ 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 + 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 } - 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 6c5c0df..b3e3987 100644 --- a/internal/provider/user_data_source_test.go +++ b/internal/provider/user_data_source_test.go @@ -1,66 +1,119 @@ package provider -/* import ( + "context" "html/template" + "os" + "regexp" "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) { - // User by Username - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, - Steps: []resource.TestStep{ - { - Config: testAccUserDataSourceConfig{ - Username: "example", - }.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"), - ), + 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) + 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) + 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"), + ), + }, }, - }, + }) }) - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, - // User by ID - Steps: []resource.TestStep{ - { - Config: testAccUserDataSourceConfig{ - ID: "example", - }.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"), - ), + + t.Run("UserByID", func(t *testing.T) { + cfg := testAccUserDataSourceConfig{ + URL: client.URL.String(), + Token: client.SessionToken(), + 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("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\]`), + }, }, - }, + }) }) + } type testAccUserDataSourceConfig struct { - URL string - Token string + URL string + Token string ID string Username string @@ -92,4 +145,3 @@ data "coderd_user" "test" { return buf.String() } -*/ 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")