8000 feat: add prebuilt workspaces to non-default organizations by SasSwart · Pull Request #18010 · coder/coder · GitHub
[go: up one dir, main page]

Skip to content

feat: add prebuilt workspaces to non-default organizations #18010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 4, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
WIP: initial view of membership recinciliation approach
  • Loading branch information
SasSwart committed May 22, 2025
commit b886b0386c3e99958db808ea10f64a221c94b9af
63 changes: 63 additions & 0 deletions enterprise/coderd/prebuilds/membership.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package prebuilds

import (
"context"
"errors"

"github.com/google/uuid"
"golang.org/x/xerrors"

"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/prebuilds"
"github.com/coder/quartz"
)

// StoreMembershipReconciler encapsulates the responsibility of ensuring that the prebuilds system user is a member of all
// organizations for which prebuilt workspaces are requested. This is necessary because our data model requires that such
// prebuilt workspaces belong to a member of the organization of their eventual claimant.
type StoreMembershipReconciler struct {
store database.Store
clock quartz.Clock
snapshot *prebuilds.GlobalSnapshot
userID uuid.UUID
}

// ReconcileAll compares the current membership of a user to the membership required in order to create prebuilt workspaces.
// If the user in question is not yet a member of an organization that needs prebuilt workspaces, ReconcileAll will create
// the membership required.
//
// This method does not have an opinion on transaction or lock management. These responsibilities are left to the caller.
func (s StoreMembershipReconciler) ReconcileAll(ctx context.Context) error {
systemUserMemberships, err := s.store.GetOrganizationsByUserID(ctx, database.GetOrganizationsByUserIDParams{
UserID: s.userID,
})
if err != nil {
return xerrors.Errorf("determine prebuild organization membership: %w", err)
}

var membershipInsertionErrors error
for _, preset := range s.snapshot.Presets {
systemUserNeedsMembership := true
for _, systemUserMembership := range systemUserMemberships {
if systemUserMembership.ID == preset.OrganizationID {
systemUserNeedsMembership = false
break
}
}
if systemUserNeedsMembership {
_, err = s.store.InsertOrganizationMember(ctx, database.InsertOrganizationMemberParams{
OrganizationID: preset.OrganizationID,
UserID: prebuilds.SystemUserID,
CreatedAt: s.clock.Now(),
UpdatedAt: s.clock.Now(),
Roles: []string{
// TODO: what roles do we need
},
})
if err != nil {
membershipInsertionErrors = errors.Join(membershipInsertionErrors, xerrors.Errorf("insert membership for prebuilt workspaces: %w", err))
}
}
}
return membershipInsertionErrors
}
12 changes: 12 additions & 0 deletions enterprise/coderd/prebuilds/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,18 @@ func (c *StoreReconciler) ReconcileAll(ctx context.Context) error {
return nil
}

membershipReconciler := StoreMembershipReconciler{
store: db,
clock: c.clock,
snapshot: snapshot,
userID: prebuilds.SystemUserID,
}
err = membershipReconciler.ReconcileAll(ctx)
if err != nil {
logger.Warn(ctx, "reconciling prebuild membership", slog.Error(err))
return nil
}

var eg errgroup.Group
// Reconcile presets in parallel. Each preset in its own goroutine.
for _, preset := range snapshot.Presets {
Expand Down
0