Skip to content

Commit 1cd68e3

Browse files
committed
create a prebuilds group in every org that needs it
1 parent af7c7cd commit 1cd68e3

File tree

4 files changed

+233
-96
lines changed

4 files changed

+233
-96
lines changed

coderd/database/dbauthz/dbauthz.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,14 @@ var (
467467
rbac.ResourceFile.Type: {
468468
policy.ActionRead,
469469
},
470+
rbac.ResourceGroup.Type: {
471+
policy.ActionRead,
472+
policy.ActionCreate,
473+
policy.ActionUpdate,
474+
},
475+
rbac.ResourceGroupMember.Type: {
476+
policy.ActionRead,
477+
},
470478
}),
471479
},
472480
}),

docs/admin/templates/extending-templates/prebuilt-workspaces.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,12 +235,18 @@ The system always maintains the desired number of prebuilt workspaces for the ac
235235

236236
### Managing resource quotas
237237

238-
Prebuilt workspaces can be used in conjunction with [resource quotas](../../users/quotas.md).
238+
To help prevent unexpected infrastructure costs, prebuilt workspaces can be used in conjunction with [resource quotas](../../users/quotas.md).
239239
Because unclaimed prebuilt workspaces are owned by the `prebuilds` user, you can:
240240

241241
1. Configure quotas for any group that includes this user.
242242
1. Set appropriate limits to balance prebuilt workspace availability with resource constraints.
243243

244+
When prebuilt workspaces are configured for an organization, Coder creates a "prebuilds" group in that organization and adds the prebuilds user to it. This group has a default quota allowance of 0, which you should adjust based on your needs:
245+
246+
- **Set a quota allowance** on the "prebuilds" group to control how many prebuilt workspaces can be provisioned
247+
- **Monitor usage** to ensure the quota is appropriate for your desired number of prebuilt instances
248+
- **Adjust as needed** based on your template costs and desired prebuilt workspace pool size
249+
244250
If a quota is exceeded, the prebuilt workspace will fail provisioning the same way other workspaces do.
245251

246252
### Template configuration best practices

enterprise/coderd/prebuilds/membership.go

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,37 +44,74 @@ func (s StoreMembershipReconciler) ReconcileAll(ctx context.Context, userID uuid
4444
return xerrors.Errorf("determine prebuild organization membership: %w", err)
4545
}
4646

47-
systemUserMemberships := make(map[uuid.UUID]struct{}, 0)
47+
orgMemberShips := make(map[uuid.UUID]struct{}, 0)
4848
defaultOrg, err := s.store.GetDefaultOrganization(ctx)
4949
if err != nil {
5050
return xerrors.Errorf("get default organization: %w", err)
5151
}
52-
systemUserMemberships[defaultOrg.ID] = struct{}{}
52+
orgMemberShips[defaultOrg.ID] = struct{}{}
5353
for _, o := range organizationMemberships {
54-
systemUserMemberships[o.ID] = struct{}{}
54+
orgMemberShips[o.ID] = struct{}{}
5555
}
5656

5757
var membershipInsertionErrors error
5858
for _, preset := range presets {
59-
_, alreadyMember := systemUserMemberships[preset.OrganizationID]
60-
if alreadyMember {
61-
continue
59+
_, alreadyOrgMember := orgMemberShips[preset.OrganizationID]
60+
if !alreadyOrgMember {
61+
// Add the organization to our list of memberships regardless of potential failure below
62+
// to avoid a retry that will probably be doomed anyway.
63+
orgMemberShips[preset.OrganizationID] = struct{}{}
64+
65+
// Insert the missing membership
66+
_, err = s.store.InsertOrganizationMember(ctx, database.InsertOrganizationMemberParams{
67+
OrganizationID: preset.OrganizationID,
68+
UserID: userID,
69+
CreatedAt: s.clock.Now(),
70+
UpdatedAt: s.clock.Now(),
71+
Roles: []string{},
72+
})
73+
if err != nil {
74+
membershipInsertionErrors = errors.Join(membershipInsertionErrors, xerrors.Errorf("insert membership for prebuilt workspaces: %w", err))
75+
continue
76+
}
6277
}
63-
// Add the organization to our list of memberships regardless of potential failure below
64-
// to avoid a retry that will probably be doomed anyway.
65-
systemUserMemberships[preset.OrganizationID] = struct{}{}
6678

67-
// Insert the missing membership
68-
_, err = s.store.InsertOrganizationMember(ctx, database.InsertOrganizationMemberParams{
79+
// Create a "prebuilds" group in the organization and add the system user to it
80+
// This group will have a quota of 0 by default, which users can adjust based on their needs
81+
prebuildsGroup, err := s.store.InsertGroup(ctx, database.InsertGroupParams{
82+
ID: uuid.New(),
83+
Name: "prebuilds",
84+
DisplayName: "Prebuilds",
6985
OrganizationID: preset.OrganizationID,
70-
UserID: userID,
71-
CreatedAt: s.clock.Now(),
72-
UpdatedAt: s.clock.Now(),
73-
Roles: []string{},
86+
AvatarURL: "",
87+
QuotaAllowance: 0, // Default quota of 0, users should set this based on their needs
88+
})
89+
if err != nil {
90+
// If the group already exists, try to get it
91+
if !database.IsUniqueViolation(err) {
92+
membershipInsertionErrors = errors.Join(membershipInsertionErrors, xerrors.Errorf("create prebuilds group: %w", err))
93+
continue
94+
}
95+
prebuildsGroup, err = s.store.GetGroupByOrgAndName(ctx, database.GetGroupByOrgAndNameParams{
96+
OrganizationID: preset.OrganizationID,
97+
Name: "prebuilds",
98+
})
99+
if err != nil {
100+
membershipInsertionErrors = errors.Join(membershipInsertionErrors, xerrors.Errorf("get existing prebuilds group: %w", err))
101+
continue
102+
}
103+
}
104+
105+
// Add the system user to the prebuilds group
106+
err = s.store.InsertGroupMember(ctx, database.InsertGroupMemberParams{
107+
GroupID: prebuildsGroup.ID,
108+
UserID: userID,
74109
})
75110
if err != nil {
76-
membershipInsertionErrors = errors.Join(membershipInsertionErrors, xerrors.Errorf("insert membership for prebuilt workspaces: %w", err))
77-
continue
111+
// Ignore unique violation errors as the user might already be in the group
112+
if !database.IsUniqueViolation(err) {
113+
membershipInsertionErrors = errors.Join(membershipInsertionErrors, xerrors.Errorf("add system user to prebuilds group: %w", err))
114+
}
78115
}
79116
}
80117
return membershipInsertionErrors

0 commit comments

Comments
 (0)
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