Skip to content

Commit a588ec5

Browse files
authored
chore: assign user to multiple orgs in coderdtest user create (coder#13867)
* chore: coderdtest assign user to multiple orgs on create
1 parent 7bb3e0d commit a588ec5

File tree

4 files changed

+62
-15
lines changed

4 files changed

+62
-15
lines changed

cli/templatelist_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ func TestTemplateList(t *testing.T) {
122122
_ = coderdtest.CreateTemplate(t, client, owner.OrganizationID, firstVersion.ID)
123123

124124
secondOrg := coderdtest.CreateOrganization(t, client, coderdtest.CreateOrganizationOptions{
125-
IncludeProvisionerDaemon: true,
125+
// Listing templates does not require the template actually completes.
126+
// We cannot provision an external provisioner in AGPL tests.
127+
IncludeProvisionerDaemon: false,
126128
})
127129
secondVersion := coderdtest.CreateTemplateVersion(t, client, secondOrg.ID, nil)
128130
_ = coderdtest.CreateTemplate(t, client, secondOrg.ID, secondVersion.ID)

coderd/coderdtest/coderdtest.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -605,12 +605,18 @@ func NewExternalProvisionerDaemon(t testing.TB, client *codersdk.Client, org uui
605605

606606
// Without this check, the provisioner will silently fail.
607607
entitlements, err := client.Entitlements(context.Background())
608-
if err == nil {
609-
feature := entitlements.Features[codersdk.FeatureExternalProvisionerDaemons]
610-
if !feature.Enabled || feature.Entitlement != codersdk.EntitlementEntitled {
611-
require.NoError(t, xerrors.Errorf("external provisioner daemons require an entitled license"))
612-
return nil
613-
}
608+
if err != nil {
609+
// AGPL instances will throw this error. They cannot use external
610+
// provisioners.
611+
t.Errorf("external provisioners requires a license with entitlements. The client failed to fetch the entitlements, is this an enterprise instance of coderd?")
612+
t.FailNow()
613+
return nil
614+
}
615+
616+
feature := entitlements.Features[codersdk.FeatureExternalProvisionerDaemons]
617+
if !feature.Enabled || feature.Entitlement != codersdk.EntitlementEntitled {
618+
require.NoError(t, xerrors.Errorf("external provisioner daemons require an entitled license"))
619+
return nil
614620
}
615621

616622
echoClient, echoServer := drpc.MemTransportPipe()
@@ -796,13 +802,30 @@ func createAnotherUserRetry(t testing.TB, client *codersdk.Client, organizationI
796802
user, err = client.UpdateUserRoles(context.Background(), user.ID.String(), codersdk.UpdateRoles{Roles: db2sdk.List(siteRoles, onlyName)})
797803
require.NoError(t, err, "update site roles")
798804

805+
// isMember keeps track of which orgs the user was added to as a member
806+
isMember := map[uuid.UUID]bool{
807+
organizationID: true,
808+
}
809+
799810
// Update org roles
800811
for orgID, roles := range orgRoles {
812+
// The user must be an organization of any orgRoles, so insert
813+
// the organization member, then assign the roles.
814+
if !isMember[orgID] {
815+
_, err = client.PostOrganizationMember(context.Background(), orgID, user.ID.String())
816+
require.NoError(t, err, "add user to organization as member")
817+
}
818+
801819
_, err = client.UpdateOrganizationMemberRoles(context.Background(), orgID, user.ID.String(),
802820
codersdk.UpdateRoles{Roles: db2sdk.List(roles, onlyName)})
803821
require.NoError(t, err, "update org membership roles")
822+
isMember[orgID] = true
804823
}
805824
}
825+
826+
user, err = client.User(context.Background(), user.Username)
827+
require.NoError(t, err, "update final user")
828+
806829
return other, user
807830
}
808831

coderd/coderdtest/coderdtest_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ package coderdtest_test
33
import (
44
"testing"
55

6+
"github.com/google/uuid"
7+
"github.com/stretchr/testify/require"
68
"go.uber.org/goleak"
79

810
"github.com/coder/coder/v2/coderd/coderdtest"
11+
"github.com/coder/coder/v2/coderd/rbac"
912
)
1013

1114
func TestMain(m *testing.M) {
@@ -27,3 +30,20 @@ func TestNew(t *testing.T) {
2730
_, _ = coderdtest.NewGoogleInstanceIdentity(t, "example", false)
2831
_, _ = coderdtest.NewAWSInstanceIdentity(t, "an-instance")
2932
}
33+
34+
// TestOrganizationMember checks the coderdtest helper can add organization members
35+
// to multiple orgs.
36+
func TestOrganizationMember(t *testing.T) {
37+
t.Parallel()
38+
39+
client := coderdtest.New(t, &coderdtest.Options{})
40+
owner := coderdtest.CreateFirstUser(t, client)
41+
42+
second := coderdtest.CreateOrganization(t, client, coderdtest.CreateOrganizationOptions{})
43+
third := coderdtest.CreateOrganization(t, client, coderdtest.CreateOrganizationOptions{})
44+
45+
// Assign the user to 3 orgs in this 1 statement
46+
_, user := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.ScopedRoleOrgMember(second.ID), rbac.ScopedRoleOrgMember(third.ID))
47+
require.Len(t, user.OrganizationIDs, 3)
48+
require.ElementsMatch(t, user.OrganizationIDs, []uuid.UUID{owner.OrganizationID, second.ID, third.ID})
49+
}

coderd/members.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ func (api *API) postOrganizationMember(rw http.ResponseWriter, r *http.Request)
3333
user = httpmw.UserParam(r)
3434
auditor = api.Auditor.Load()
3535
aReq, commitAudit = audit.InitRequest[database.AuditableOrganizationMember](rw, &audit.RequestParams{
36-
Audit: *auditor,
37-
Log: api.Logger,
38-
Request: r,
39-
Action: database.AuditActionCreate,
36+
OrganizationID: organization.ID,
37+
Audit: *auditor,
38+
Log: api.Logger,
39+
Request: r,
40+
Action: database.AuditActionCreate,
4041
})
4142
)
4243
aReq.Old = database.AuditableOrganizationMember{}
@@ -95,10 +96,11 @@ func (api *API) deleteOrganizationMember(rw http.ResponseWriter, r *http.Request
9596
member = httpmw.OrganizationMemberParam(r)
9697
auditor = api.Auditor.Load()
9798
aReq, commitAudit = audit.InitRequest[database.AuditableOrganizationMember](rw, &audit.RequestParams{
98-
Audit: *auditor,
99-
Log: api.Logger,
100-
Request: r,
101-
Action: database.AuditActionDelete,
99+
OrganizationID: organization.ID,
100+
Audit: *auditor,
101+
Log: api.Logger,
102+
Request: r,
103+
Action: database.AuditActionDelete,
102104
})
103105
)
104106
aReq.Old = member.OrganizationMember.Auditable(member.Username)

0 commit comments

Comments
 (0)