Skip to content

Commit cc17d2f

Browse files
authored
refactor: add postgres tailnet coordinator (#8044)
* postgres tailnet coordinator Signed-off-by: Spike Curtis <spike@coder.com> * Fix db migration; tests Signed-off-by: Spike Curtis <spike@coder.com> * Add fixture, regenerate Signed-off-by: Spike Curtis <spike@coder.com> * Fix fixtures Signed-off-by: Spike Curtis <spike@coder.com> * review comments, run clean gen Signed-off-by: Spike Curtis <spike@coder.com> * Rename waitForConn -> cleanupConn Signed-off-by: Spike Curtis <spike@coder.com> * code review updates Signed-off-by: Spike Curtis <spike@coder.com> * db migration order Signed-off-by: Spike Curtis <spike@coder.com> * fix log field name last_heartbeat Signed-off-by: Spike Curtis <spike@coder.com> * fix heartbeat_from log field Signed-off-by: Spike Curtis <spike@coder.com> * fix slog fields for linting Signed-off-by: Spike Curtis <spike@coder.com> --------- Signed-off-by: Spike Curtis <spike@coder.com>
1 parent 4fb4c9b commit cc17d2f

File tree

20 files changed

+2739
-18
lines changed

20 files changed

+2739
-18
lines changed

coderd/database/dbauthz/dbauthz.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,13 @@ func (q *querier) DeleteApplicationConnectAPIKeysByUserID(ctx context.Context, u
707707
return q.db.DeleteApplicationConnectAPIKeysByUserID(ctx, userID)
708708
}
709709

710+
func (q *querier) DeleteCoordinator(ctx context.Context, id uuid.UUID) error {
711+
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil {
712+
return err
713+
}
714+
return q.db.DeleteCoordinator(ctx, id)
715+
}
716+
710717
func (q *querier) DeleteGitSSHKey(ctx context.Context, userID uuid.UUID) error {
711718
return deleteQ(q.log, q.auth, q.db.GetGitSSHKey, q.db.DeleteGitSSHKey)(ctx, userID)
712719
}
@@ -765,6 +772,20 @@ func (q *querier) DeleteReplicasUpdatedBefore(ctx context.Context, updatedAt tim
765772
return q.db.DeleteReplicasUpdatedBefore(ctx, updatedAt)
766773
}
767774

775+
func (q *querier) DeleteTailnetAgent(ctx context.Context, arg database.DeleteTailnetAgentParams) (database.DeleteTailnetAgentRow, error) {
776+
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil {
777+
return database.DeleteTailnetAgentRow{}, err
778+
}
779+
return q.db.DeleteTailnetAgent(ctx, arg)
780+
}
781+
782+
func (q *querier) DeleteTailnetClient(ctx context.Context, arg database.DeleteTailnetClientParams) (database.DeleteTailnetClientRow, error) {
783+
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil {
784+
return database.DeleteTailnetClientRow{}, err
785+
}
786+
return q.db.DeleteTailnetClient(ctx, arg)
787+
}
788+
768789
func (q *querier) GetAPIKeyByID(ctx context.Context, id string) (database.APIKey, error) {
769790
return fetch(q.log, q.auth, q.db.GetAPIKeyByID)(ctx, id)
770791
}
@@ -1137,6 +1158,20 @@ func (q *querier) GetServiceBanner(ctx context.Context) (string, error) {
11371158
return q.db.GetServiceBanner(ctx)
11381159
}
11391160

1161+
func (q *querier) GetTailnetAgents(ctx context.Context, id uuid.UUID) ([]database.TailnetAgent, error) {
1162+
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil {
1163+
return nil, err
1164+
}
1165+
return q.db.GetTailnetAgents(ctx, id)
1166+
}
1167+
1168+
func (q *querier) GetTailnetClientsForAgent(ctx context.Context, agentID uuid.UUID) ([]database.TailnetClient, error) {
1169+
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil {
1170+
return nil, err
1171+
}
1172+
return q.db.GetTailnetClientsForAgent(ctx, agentID)
1173+
}
1174+
11401175
// Only used by metrics cache.
11411176
func (q *querier) GetTemplateAverageBuildTime(ctx context.Context, arg database.GetTemplateAverageBuildTimeParams) (database.GetTemplateAverageBuildTimeRow, error) {
11421177
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
@@ -2515,3 +2550,24 @@ func (q *querier) UpsertServiceBanner(ctx context.Context, value string) error {
25152550
}
25162551
return q.db.UpsertServiceBanner(ctx, value)
25172552
}
2553+
2554+
func (q *querier) UpsertTailnetAgent(ctx context.Context, arg database.UpsertTailnetAgentParams) (database.TailnetAgent, error) {
2555+
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil {
2556+
return database.TailnetAgent{}, err
2557+
}
2558+
return q.db.UpsertTailnetAgent(ctx, arg)
2559+
}
2560+
2561+
func (q *querier) UpsertTailnetClient(ctx context.Context, arg database.UpsertTailnetClientParams) (database.TailnetClient, error) {
2562+
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil {
2563+
return database.TailnetClient{}, err
2564+
}
2565+
return q.db.UpsertTailnetClient(ctx, arg)
2566+
}
2567+
2568+
func (q *querier) UpsertTailnetCoordinator(ctx context.Context, id uuid.UUID) (database.TailnetCoordinator, error) {
2569+
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil {
2570+
return database.TailnetCoordinator{}, err
2571+
}
2572+
return q.db.UpsertTailnetCoordinator(ctx, id)
2573+
}

coderd/database/dbfake/dbfake.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,14 @@ func isNotNull(v interface{}) bool {
966966
return reflect.ValueOf(v).FieldByName("Valid").Bool()
967967
}
968968

969+
// ErrUnimplemented is returned by methods only used by the enterprise/tailnet.pgCoord. This coordinator explicitly
970+
// depends on postgres triggers that announce changes on the pubsub. Implementing support for this in the fake
971+
// database would strongly couple the fakeQuerier to the pubsub, which is undesirable. Furthermore, it makes little
972+
// sense to directly test the pgCoord against anything other than postgres. The fakeQuerier is designed to allow us to
973+
// test the Coderd API, and for that kind of test, the in-memory, AGPL tailnet coordinator is sufficient. Therefore,
974+
// these methods remain unimplemented in the fakeQuerier.
975+
var ErrUnimplemented = xerrors.New("unimplemented")
976+
969977
func (*fakeQuerier) AcquireLock(_ context.Context, _ int64) error {
970978
return xerrors.New("AcquireLock must only be called within a transaction")
971979
}
@@ -1066,6 +1074,10 @@ func (q *fakeQuerier) DeleteApplicationConnectAPIKeysByUserID(_ context.Context,
10661074
return nil
10671075
}
10681076

1077+
func (*fakeQuerier) DeleteCoordinator(context.Context, uuid.UUID) error {
1078+
return ErrUnimplemented
1079+
}
1080+
10691081
func (q *fakeQuerier) DeleteGitSSHKey(_ context.Context, userID uuid.UUID) error {
10701082
q.mutex.Lock()
10711083
defer q.mutex.Unlock()
@@ -1174,6 +1186,14 @@ func (q *fakeQuerier) DeleteReplicasUpdatedBefore(_ context.Context, before time
11741186
return nil
11751187
}
11761188

1189+
func (*fakeQuerier) DeleteTailnetAgent(context.Context, database.DeleteTailnetAgentParams) (database.DeleteTailnetAgentRow, error) {
1190+
return database.DeleteTailnetAgentRow{}, ErrUnimplemented
1191+
}
1192+
1193+
func (*fakeQuerier) DeleteTailnetClient(context.Context, database.DeleteTailnetClientParams) (database.DeleteTailnetClientRow, error) {
1194+
return database.DeleteTailnetClientRow{}, ErrUnimplemented
1195+
}
1196+
11771197
func (q *fakeQuerier) GetAPIKeyByID(_ context.Context, id string) (database.APIKey, error) {
11781198
q.mutex.RLock()
11791199
defer q.mutex.RUnlock()
@@ -2185,6 +2205,14 @@ func (q *fakeQuerier) GetServiceBanner(_ context.Context) (string, error) {
21852205
return string(q.serviceBanner), nil
21862206
}
21872207

2208+
func (*fakeQuerier) GetTailnetAgents(context.Context, uuid.UUID) ([]database.TailnetAgent, error) {
2209+
return nil, ErrUnimplemented
2210+
}
2211+
2212+
func (*fakeQuerier) GetTailnetClientsForAgent(context.Context, uuid.UUID) ([]database.TailnetClient, error) {
2213+
return nil, ErrUnimplemented
2214+
}
2215+
21882216
func (q *fakeQuerier) GetTemplateAverageBuildTime(ctx context.Context, arg database.GetTemplateAverageBuildTimeParams) (database.GetTemplateAverageBuildTimeRow, error) {
21892217
if err := validateDatabaseType(arg); err != nil {
21902218
return database.GetTemplateAverageBuildTimeRow{}, err
@@ -5238,3 +5266,15 @@ func (q *fakeQuerier) UpsertServiceBanner(_ context.Context, data string) error
52385266
q.serviceBanner = []byte(data)
52395267
return nil
52405268
}
5269+
5270+
func (*fakeQuerier) UpsertTailnetAgent(context.Context, database.UpsertTailnetAgentParams) (database.TailnetAgent, error) {
5271+
return database.TailnetAgent{}, ErrUnimplemented
5272+
}
5273+
5274+
func (*fakeQuerier) UpsertTailnetClient(context.Context, database.UpsertTailnetClientParams) (database.TailnetClient, error) {
5275+
return database.TailnetClient{}, ErrUnimplemented
5276+
}
5277+
5278+
func (*fakeQuerier) UpsertTailnetCoordinator(context.Context, uuid.UUID) (database.TailnetCoordinator, error) {
5279+
return database.TailnetCoordinator{}, ErrUnimplemented
5280+
}

coderd/database/dbmetrics/dbmetrics.go

Lines changed: 48 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmock/dbmock.go

Lines changed: 119 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbtestutil/db.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@ import (
1414
"github.com/coder/coder/coderd/database/pubsub"
1515
)
1616

17+
// WillUsePostgres returns true if a call to NewDB() will return a real, postgres-backed Store and Pubsub.
18+
func WillUsePostgres() bool {
19+
return os.Getenv("DB") != ""
20+
}
21+
1722
func NewDB(t testing.TB) (database.Store, pubsub.Pubsub) {
1823
t.Helper()
1924

2025
db := dbfake.New()
2126
ps := pubsub.NewInMemory()
22-
if os.Getenv("DB") != "" {
27+
if WillUsePostgres() {
2328
connectionURL := os.Getenv("CODER_PG_CONNECTION_URL")
2429
if connectionURL == "" {
2530
var (

0 commit comments

Comments
 (0)