diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index d26302c54d091..c8419b5b00bb8 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -715,6 +715,13 @@ func (q *querier) DeleteAllTailnetClientSubscriptions(ctx context.Context, arg d return q.db.DeleteAllTailnetClientSubscriptions(ctx, arg) } +func (q *querier) DeleteAllTailnetTunnels(ctx context.Context, arg database.DeleteAllTailnetTunnelsParams) error { + if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + return err + } + return q.db.DeleteAllTailnetTunnels(ctx, arg) +} + func (q *querier) DeleteApplicationConnectAPIKeysByUserID(ctx context.Context, userID uuid.UUID) error { // TODO: This is not 100% correct because it omits apikey IDs. err := q.authorizeContext(ctx, rbac.ActionDelete, @@ -811,6 +818,20 @@ func (q *querier) DeleteTailnetClientSubscription(ctx context.Context, arg datab return q.db.DeleteTailnetClientSubscription(ctx, arg) } +func (q *querier) DeleteTailnetPeer(ctx context.Context, arg database.DeleteTailnetPeerParams) (database.DeleteTailnetPeerRow, error) { + if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + return database.DeleteTailnetPeerRow{}, err + } + return q.db.DeleteTailnetPeer(ctx, arg) +} + +func (q *querier) DeleteTailnetTunnel(ctx context.Context, arg database.DeleteTailnetTunnelParams) (database.DeleteTailnetTunnelRow, error) { + if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + return database.DeleteTailnetTunnelRow{}, err + } + return q.db.DeleteTailnetTunnel(ctx, arg) +} + func (q *querier) GetAPIKeyByID(ctx context.Context, id string) (database.APIKey, error) { return fetch(q.log, q.auth, q.db.GetAPIKeyByID)(ctx, id) } @@ -1246,6 +1267,27 @@ func (q *querier) GetTailnetClientsForAgent(ctx context.Context, agentID uuid.UU return q.db.GetTailnetClientsForAgent(ctx, agentID) } +func (q *querier) GetTailnetPeers(ctx context.Context, id uuid.UUID) ([]database.TailnetPeer, error) { + if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + return nil, err + } + return q.db.GetTailnetPeers(ctx, id) +} + +func (q *querier) GetTailnetTunnelPeerBindings(ctx context.Context, srcID uuid.UUID) ([]database.GetTailnetTunnelPeerBindingsRow, error) { + if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + return nil, err + } + return q.db.GetTailnetTunnelPeerBindings(ctx, srcID) +} + +func (q *querier) GetTailnetTunnelPeerIDs(ctx context.Context, srcID uuid.UUID) ([]database.GetTailnetTunnelPeerIDsRow, error) { + if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + return nil, err + } + return q.db.GetTailnetTunnelPeerIDs(ctx, srcID) +} + func (q *querier) GetTemplateAppInsights(ctx context.Context, arg database.GetTemplateAppInsightsParams) ([]database.GetTemplateAppInsightsRow, error) { for _, templateID := range arg.TemplateIDs { template, err := q.db.GetTemplateByID(ctx, templateID) @@ -2972,6 +3014,20 @@ func (q *querier) UpsertTailnetCoordinator(ctx context.Context, id uuid.UUID) (d return q.db.UpsertTailnetCoordinator(ctx, id) } +func (q *querier) UpsertTailnetPeer(ctx context.Context, arg database.UpsertTailnetPeerParams) (database.TailnetPeer, error) { + if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceTailnetCoordinator); err != nil { + return database.TailnetPeer{}, err + } + return q.db.UpsertTailnetPeer(ctx, arg) +} + +func (q *querier) UpsertTailnetTunnel(ctx context.Context, arg database.UpsertTailnetTunnelParams) (database.TailnetTunnel, error) { + if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceTailnetCoordinator); err != nil { + return database.TailnetTunnel{}, err + } + return q.db.UpsertTailnetTunnel(ctx, arg) +} + func (q *querier) GetAuthorizedTemplates(ctx context.Context, arg database.GetTemplatesWithFilterParams, _ rbac.PreparedAuthorized) ([]database.Template, error) { // TODO Delete this function, all GetTemplates should be authorized. For now just call getTemplates on the authz querier. return q.GetTemplatesWithFilter(ctx, arg) diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index 985b2d4b422ee..436f25984d95f 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -981,6 +981,15 @@ func (*FakeQuerier) DeleteAllTailnetClientSubscriptions(_ context.Context, arg d return ErrUnimplemented } +func (*FakeQuerier) DeleteAllTailnetTunnels(_ context.Context, arg database.DeleteAllTailnetTunnelsParams) error { + err := validateDatabaseType(arg) + if err != nil { + return err + } + + return ErrUnimplemented +} + func (q *FakeQuerier) DeleteApplicationConnectAPIKeysByUserID(_ context.Context, userID uuid.UUID) error { q.mutex.Lock() defer q.mutex.Unlock() @@ -1118,6 +1127,24 @@ func (*FakeQuerier) DeleteTailnetClientSubscription(context.Context, database.De return ErrUnimplemented } +func (*FakeQuerier) DeleteTailnetPeer(_ context.Context, arg database.DeleteTailnetPeerParams) (database.DeleteTailnetPeerRow, error) { + err := validateDatabaseType(arg) + if err != nil { + return database.DeleteTailnetPeerRow{}, err + } + + return database.DeleteTailnetPeerRow{}, ErrUnimplemented +} + +func (*FakeQuerier) DeleteTailnetTunnel(_ context.Context, arg database.DeleteTailnetTunnelParams) (database.DeleteTailnetTunnelRow, error) { + err := validateDatabaseType(arg) + if err != nil { + return database.DeleteTailnetTunnelRow{}, err + } + + return database.DeleteTailnetTunnelRow{}, ErrUnimplemented +} + func (q *FakeQuerier) GetAPIKeyByID(_ context.Context, id string) (database.APIKey, error) { q.mutex.RLock() defer q.mutex.RUnlock() @@ -2240,6 +2267,18 @@ func (*FakeQuerier) GetTailnetClientsForAgent(context.Context, uuid.UUID) ([]dat return nil, ErrUnimplemented } +func (*FakeQuerier) GetTailnetPeers(context.Context, uuid.UUID) ([]database.TailnetPeer, error) { + return nil, ErrUnimplemented +} + +func (*FakeQuerier) GetTailnetTunnelPeerBindings(context.Context, uuid.UUID) ([]database.GetTailnetTunnelPeerBindingsRow, error) { + return nil, ErrUnimplemented +} + +func (*FakeQuerier) GetTailnetTunnelPeerIDs(context.Context, uuid.UUID) ([]database.GetTailnetTunnelPeerIDsRow, error) { + return nil, ErrUnimplemented +} + func (q *FakeQuerier) GetTemplateAppInsights(ctx context.Context, arg database.GetTemplateAppInsightsParams) ([]database.GetTemplateAppInsightsRow, error) { err := validateDatabaseType(arg) if err != nil { @@ -6786,6 +6825,24 @@ func (*FakeQuerier) UpsertTailnetCoordinator(context.Context, uuid.UUID) (databa return database.TailnetCoordinator{}, ErrUnimplemented } +func (*FakeQuerier) UpsertTailnetPeer(_ context.Context, arg database.UpsertTailnetPeerParams) (database.TailnetPeer, error) { + err := validateDatabaseType(arg) + if err != nil { + return database.TailnetPeer{}, err + } + + return database.TailnetPeer{}, ErrUnimplemented +} + +func (*FakeQuerier) UpsertTailnetTunnel(_ context.Context, arg database.UpsertTailnetTunnelParams) (database.TailnetTunnel, error) { + err := validateDatabaseType(arg) + if err != nil { + return database.TailnetTunnel{}, err + } + + return database.TailnetTunnel{}, ErrUnimplemented +} + func (q *FakeQuerier) GetAuthorizedTemplates(ctx context.Context, arg database.GetTemplatesWithFilterParams, prepared rbac.PreparedAuthorized) ([]database.Template, error) { if err := validateDatabaseType(arg); err != nil { return nil, err diff --git a/coderd/database/dbmetrics/dbmetrics.go b/coderd/database/dbmetrics/dbmetrics.go index 3d04591938b0d..ac1666db041e5 100644 --- a/coderd/database/dbmetrics/dbmetrics.go +++ b/coderd/database/dbmetrics/dbmetrics.go @@ -142,6 +142,13 @@ func (m metricsStore) DeleteAllTailnetClientSubscriptions(ctx context.Context, a return r0 } +func (m metricsStore) DeleteAllTailnetTunnels(ctx context.Context, arg database.DeleteAllTailnetTunnelsParams) error { + start := time.Now() + r0 := m.s.DeleteAllTailnetTunnels(ctx, arg) + m.queryLatencies.WithLabelValues("DeleteAllTailnetTunnels").Observe(time.Since(start).Seconds()) + return r0 +} + func (m metricsStore) DeleteApplicationConnectAPIKeysByUserID(ctx context.Context, userID uuid.UUID) error { start := time.Now() err := m.s.DeleteApplicationConnectAPIKeysByUserID(ctx, userID) @@ -230,6 +237,20 @@ func (m metricsStore) DeleteTailnetClientSubscription(ctx context.Context, arg d return r0 } +func (m metricsStore) DeleteTailnetPeer(ctx context.Context, arg database.DeleteTailnetPeerParams) (database.DeleteTailnetPeerRow, error) { + start := time.Now() + r0, r1 := m.s.DeleteTailnetPeer(ctx, arg) + m.queryLatencies.WithLabelValues("DeleteTailnetPeer").Observe(time.Since(start).Seconds()) + return r0, r1 +} + +func (m metricsStore) DeleteTailnetTunnel(ctx context.Context, arg database.DeleteTailnetTunnelParams) (database.DeleteTailnetTunnelRow, error) { + start := time.Now() + r0, r1 := m.s.DeleteTailnetTunnel(ctx, arg) + m.queryLatencies.WithLabelValues("DeleteTailnetTunnel").Observe(time.Since(start).Seconds()) + return r0, r1 +} + func (m metricsStore) GetAPIKeyByID(ctx context.Context, id string) (database.APIKey, error) { start := time.Now() apiKey, err := m.s.GetAPIKeyByID(ctx, id) @@ -655,6 +676,27 @@ func (m metricsStore) GetTailnetClientsForAgent(ctx context.Context, agentID uui return m.s.GetTailnetClientsForAgent(ctx, agentID) } +func (m metricsStore) GetTailnetPeers(ctx context.Context, id uuid.UUID) ([]database.TailnetPeer, error) { + start := time.Now() + r0, r1 := m.s.GetTailnetPeers(ctx, id) + m.queryLatencies.WithLabelValues("GetTailnetPeers").Observe(time.Since(start).Seconds()) + return r0, r1 +} + +func (m metricsStore) GetTailnetTunnelPeerBindings(ctx context.Context, srcID uuid.UUID) ([]database.GetTailnetTunnelPeerBindingsRow, error) { + start := time.Now() + r0, r1 := m.s.GetTailnetTunnelPeerBindings(ctx, srcID) + m.queryLatencies.WithLabelValues("GetTailnetTunnelPeerBindings").Observe(time.Since(start).Seconds()) + return r0, r1 +} + +func (m metricsStore) GetTailnetTunnelPeerIDs(ctx context.Context, srcID uuid.UUID) ([]database.GetTailnetTunnelPeerIDsRow, error) { + start := time.Now() + r0, r1 := m.s.GetTailnetTunnelPeerIDs(ctx, srcID) + m.queryLatencies.WithLabelValues("GetTailnetTunnelPeerIDs").Observe(time.Since(start).Seconds()) + return r0, r1 +} + func (m metricsStore) GetTemplateAppInsights(ctx context.Context, arg database.GetTemplateAppInsightsParams) ([]database.GetTemplateAppInsightsRow, error) { start := time.Now() r0, r1 := m.s.GetTemplateAppInsights(ctx, arg) @@ -1877,6 +1919,20 @@ func (m metricsStore) UpsertTailnetCoordinator(ctx context.Context, id uuid.UUID return m.s.UpsertTailnetCoordinator(ctx, id) } +func (m metricsStore) UpsertTailnetPeer(ctx context.Context, arg database.UpsertTailnetPeerParams) (database.TailnetPeer, error) { + start := time.Now() + r0, r1 := m.s.UpsertTailnetPeer(ctx, arg) + m.queryLatencies.WithLabelValues("UpsertTailnetPeer").Observe(time.Since(start).Seconds()) + return r0, r1 +} + +func (m metricsStore) UpsertTailnetTunnel(ctx context.Context, arg database.UpsertTailnetTunnelParams) (database.TailnetTunnel, error) { + start := time.Now() + r0, r1 := m.s.UpsertTailnetTunnel(ctx, arg) + m.queryLatencies.WithLabelValues("UpsertTailnetTunnel").Observe(time.Since(start).Seconds()) + return r0, r1 +} + func (m metricsStore) GetAuthorizedTemplates(ctx context.Context, arg database.GetTemplatesWithFilterParams, prepared rbac.PreparedAuthorized) ([]database.Template, error) { start := time.Now() templates, err := m.s.GetAuthorizedTemplates(ctx, arg, prepared) diff --git a/coderd/database/dbmock/dbmock.go b/coderd/database/dbmock/dbmock.go index bfa9cebc01a13..9af07691e3e30 100644 --- a/coderd/database/dbmock/dbmock.go +++ b/coderd/database/dbmock/dbmock.go @@ -168,6 +168,20 @@ func (mr *MockStoreMockRecorder) DeleteAllTailnetClientSubscriptions(arg0, arg1 return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAllTailnetClientSubscriptions", reflect.TypeOf((*MockStore)(nil).DeleteAllTailnetClientSubscriptions), arg0, arg1) } +// DeleteAllTailnetTunnels mocks base method. +func (m *MockStore) DeleteAllTailnetTunnels(arg0 context.Context, arg1 database.DeleteAllTailnetTunnelsParams) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteAllTailnetTunnels", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteAllTailnetTunnels indicates an expected call of DeleteAllTailnetTunnels. +func (mr *MockStoreMockRecorder) DeleteAllTailnetTunnels(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAllTailnetTunnels", reflect.TypeOf((*MockStore)(nil).DeleteAllTailnetTunnels), arg0, arg1) +} + // DeleteApplicationConnectAPIKeysByUserID mocks base method. func (m *MockStore) DeleteApplicationConnectAPIKeysByUserID(arg0 context.Context, arg1 uuid.UUID) error { m.ctrl.T.Helper() @@ -353,6 +367,36 @@ func (mr *MockStoreMockRecorder) DeleteTailnetClientSubscription(arg0, arg1 inte return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTailnetClientSubscription", reflect.TypeOf((*MockStore)(nil).DeleteTailnetClientSubscription), arg0, arg1) } +// DeleteTailnetPeer mocks base method. +func (m *MockStore) DeleteTailnetPeer(arg0 context.Context, arg1 database.DeleteTailnetPeerParams) (database.DeleteTailnetPeerRow, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteTailnetPeer", arg0, arg1) + ret0, _ := ret[0].(database.DeleteTailnetPeerRow) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteTailnetPeer indicates an expected call of DeleteTailnetPeer. +func (mr *MockStoreMockRecorder) DeleteTailnetPeer(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTailnetPeer", reflect.TypeOf((*MockStore)(nil).DeleteTailnetPeer), arg0, arg1) +} + +// DeleteTailnetTunnel mocks base method. +func (m *MockStore) DeleteTailnetTunnel(arg0 context.Context, arg1 database.DeleteTailnetTunnelParams) (database.DeleteTailnetTunnelRow, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteTailnetTunnel", arg0, arg1) + ret0, _ := ret[0].(database.DeleteTailnetTunnelRow) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteTailnetTunnel indicates an expected call of DeleteTailnetTunnel. +func (mr *MockStoreMockRecorder) DeleteTailnetTunnel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTailnetTunnel", reflect.TypeOf((*MockStore)(nil).DeleteTailnetTunnel), arg0, arg1) +} + // GetAPIKeyByID mocks base method. func (m *MockStore) GetAPIKeyByID(arg0 context.Context, arg1 string) (database.APIKey, error) { m.ctrl.T.Helper() @@ -1313,6 +1357,51 @@ func (mr *MockStoreMockRecorder) GetTailnetClientsForAgent(arg0, arg1 interface{ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTailnetClientsForAgent", reflect.TypeOf((*MockStore)(nil).GetTailnetClientsForAgent), arg0, arg1) } +// GetTailnetPeers mocks base method. +func (m *MockStore) GetTailnetPeers(arg0 context.Context, arg1 uuid.UUID) ([]database.TailnetPeer, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTailnetPeers", arg0, arg1) + ret0, _ := ret[0].([]database.TailnetPeer) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTailnetPeers indicates an expected call of GetTailnetPeers. +func (mr *MockStoreMockRecorder) GetTailnetPeers(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTailnetPeers", reflect.TypeOf((*MockStore)(nil).GetTailnetPeers), arg0, arg1) +} + +// GetTailnetTunnelPeerBindings mocks base method. +func (m *MockStore) GetTailnetTunnelPeerBindings(arg0 context.Context, arg1 uuid.UUID) ([]database.GetTailnetTunnelPeerBindingsRow, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTailnetTunnelPeerBindings", arg0, arg1) + ret0, _ := ret[0].([]database.GetTailnetTunnelPeerBindingsRow) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTailnetTunnelPeerBindings indicates an expected call of GetTailnetTunnelPeerBindings. +func (mr *MockStoreMockRecorder) GetTailnetTunnelPeerBindings(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTailnetTunnelPeerBindings", reflect.TypeOf((*MockStore)(nil).GetTailnetTunnelPeerBindings), arg0, arg1) +} + +// GetTailnetTunnelPeerIDs mocks base method. +func (m *MockStore) GetTailnetTunnelPeerIDs(arg0 context.Context, arg1 uuid.UUID) ([]database.GetTailnetTunnelPeerIDsRow, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTailnetTunnelPeerIDs", arg0, arg1) + ret0, _ := ret[0].([]database.GetTailnetTunnelPeerIDsRow) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTailnetTunnelPeerIDs indicates an expected call of GetTailnetTunnelPeerIDs. +func (mr *MockStoreMockRecorder) GetTailnetTunnelPeerIDs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTailnetTunnelPeerIDs", reflect.TypeOf((*MockStore)(nil).GetTailnetTunnelPeerIDs), arg0, arg1) +} + // GetTemplateAppInsights mocks base method. func (m *MockStore) GetTemplateAppInsights(arg0 context.Context, arg1 database.GetTemplateAppInsightsParams) ([]database.GetTemplateAppInsightsRow, error) { m.ctrl.T.Helper() @@ -3943,6 +4032,36 @@ func (mr *MockStoreMockRecorder) UpsertTailnetCoordinator(arg0, arg1 interface{} return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertTailnetCoordinator", reflect.TypeOf((*MockStore)(nil).UpsertTailnetCoordinator), arg0, arg1) } +// UpsertTailnetPeer mocks base method. +func (m *MockStore) UpsertTailnetPeer(arg0 context.Context, arg1 database.UpsertTailnetPeerParams) (database.TailnetPeer, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpsertTailnetPeer", arg0, arg1) + ret0, _ := ret[0].(database.TailnetPeer) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpsertTailnetPeer indicates an expected call of UpsertTailnetPeer. +func (mr *MockStoreMockRecorder) UpsertTailnetPeer(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertTailnetPeer", reflect.TypeOf((*MockStore)(nil).UpsertTailnetPeer), arg0, arg1) +} + +// UpsertTailnetTunnel mocks base method. +func (m *MockStore) UpsertTailnetTunnel(arg0 context.Context, arg1 database.UpsertTailnetTunnelParams) (database.TailnetTunnel, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpsertTailnetTunnel", arg0, arg1) + ret0, _ := ret[0].(database.TailnetTunnel) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpsertTailnetTunnel indicates an expected call of UpsertTailnetTunnel. +func (mr *MockStoreMockRecorder) UpsertTailnetTunnel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertTailnetTunnel", reflect.TypeOf((*MockStore)(nil).UpsertTailnetTunnel), arg0, arg1) +} + // Wrappers mocks base method. func (m *MockStore) Wrappers() []string { m.ctrl.T.Helper() diff --git a/coderd/database/querier.go b/coderd/database/querier.go index 1332644ac4a06..2fcf6d638642e 100644 --- a/coderd/database/querier.go +++ b/coderd/database/querier.go @@ -44,6 +44,7 @@ type sqlcQuerier interface { DeleteAPIKeyByID(ctx context.Context, id string) error DeleteAPIKeysByUserID(ctx context.Context, userID uuid.UUID) error DeleteAllTailnetClientSubscriptions(ctx context.Context, arg DeleteAllTailnetClientSubscriptionsParams) error + DeleteAllTailnetTunnels(ctx context.Context, arg DeleteAllTailnetTunnelsParams) error DeleteApplicationConnectAPIKeysByUserID(ctx context.Context, userID uuid.UUID) error DeleteCoordinator(ctx context.Context, id uuid.UUID) error DeleteGitSSHKey(ctx context.Context, userID uuid.UUID) error @@ -59,6 +60,8 @@ type sqlcQuerier interface { DeleteTailnetAgent(ctx context.Context, arg DeleteTailnetAgentParams) (DeleteTailnetAgentRow, error) DeleteTailnetClient(ctx context.Context, arg DeleteTailnetClientParams) (DeleteTailnetClientRow, error) DeleteTailnetClientSubscription(ctx context.Context, arg DeleteTailnetClientSubscriptionParams) error + DeleteTailnetPeer(ctx context.Context, arg DeleteTailnetPeerParams) (DeleteTailnetPeerRow, error) + DeleteTailnetTunnel(ctx context.Context, arg DeleteTailnetTunnelParams) (DeleteTailnetTunnelRow, error) GetAPIKeyByID(ctx context.Context, id string) (APIKey, error) // there is no unique constraint on empty token names GetAPIKeyByName(ctx context.Context, arg GetAPIKeyByNameParams) (APIKey, error) @@ -128,6 +131,9 @@ type sqlcQuerier interface { GetServiceBanner(ctx context.Context) (string, error) GetTailnetAgents(ctx context.Context, id uuid.UUID) ([]TailnetAgent, error) GetTailnetClientsForAgent(ctx context.Context, agentID uuid.UUID) ([]TailnetClient, error) + GetTailnetPeers(ctx context.Context, id uuid.UUID) ([]TailnetPeer, error) + GetTailnetTunnelPeerBindings(ctx context.Context, srcID uuid.UUID) ([]GetTailnetTunnelPeerBindingsRow, error) + GetTailnetTunnelPeerIDs(ctx context.Context, srcID uuid.UUID) ([]GetTailnetTunnelPeerIDsRow, error) // GetTemplateAppInsights returns the aggregate usage of each app in a given // timeframe. The result can be filtered on template_ids, meaning only user data // from workspaces based on those templates will be included. @@ -356,6 +362,8 @@ type sqlcQuerier interface { UpsertTailnetClient(ctx context.Context, arg UpsertTailnetClientParams) (TailnetClient, error) UpsertTailnetClientSubscription(ctx context.Context, arg UpsertTailnetClientSubscriptionParams) error UpsertTailnetCoordinator(ctx context.Context, id uuid.UUID) (TailnetCoordinator, error) + UpsertTailnetPeer(ctx context.Context, arg UpsertTailnetPeerParams) (TailnetPeer, error) + UpsertTailnetTunnel(ctx context.Context, arg UpsertTailnetTunnelParams) (TailnetTunnel, error) } var _ sqlcQuerier = (*sqlQuerier)(nil) diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 03aff0ea801b2..b45507f1261bc 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -4478,6 +4478,22 @@ func (q *sqlQuerier) DeleteAllTailnetClientSubscriptions(ctx context.Context, ar return err } +const deleteAllTailnetTunnels = `-- name: DeleteAllTailnetTunnels :exec +DELETE +FROM tailnet_tunnels +WHERE coordinator_id = $1 and src_id = $2 +` + +type DeleteAllTailnetTunnelsParams struct { + CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"` + SrcID uuid.UUID `db:"src_id" json:"src_id"` +} + +func (q *sqlQuerier) DeleteAllTailnetTunnels(ctx context.Context, arg DeleteAllTailnetTunnelsParams) error { + _, err := q.db.ExecContext(ctx, deleteAllTailnetTunnels, arg.CoordinatorID, arg.SrcID) + return err +} + const deleteCoordinator = `-- name: DeleteCoordinator :exec DELETE FROM tailnet_coordinators @@ -4554,6 +4570,56 @@ func (q *sqlQuerier) DeleteTailnetClientSubscription(ctx context.Context, arg De return err } +const deleteTailnetPeer = `-- name: DeleteTailnetPeer :one +DELETE +FROM tailnet_peers +WHERE id = $1 and coordinator_id = $2 +RETURNING id, coordinator_id +` + +type DeleteTailnetPeerParams struct { + ID uuid.UUID `db:"id" json:"id"` + CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"` +} + +type DeleteTailnetPeerRow struct { + ID uuid.UUID `db:"id" json:"id"` + CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"` +} + +func (q *sqlQuerier) DeleteTailnetPeer(ctx context.Context, arg DeleteTailnetPeerParams) (DeleteTailnetPeerRow, error) { + row := q.db.QueryRowContext(ctx, deleteTailnetPeer, arg.ID, arg.CoordinatorID) + var i DeleteTailnetPeerRow + err := row.Scan(&i.ID, &i.CoordinatorID) + return i, err +} + +const deleteTailnetTunnel = `-- name: DeleteTailnetTunnel :one +DELETE +FROM tailnet_tunnels +WHERE coordinator_id = $1 and src_id = $2 and dst_id = $3 +RETURNING coordinator_id, src_id, dst_id +` + +type DeleteTailnetTunnelParams struct { + CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"` + SrcID uuid.UUID `db:"src_id" json:"src_id"` + DstID uuid.UUID `db:"dst_id" json:"dst_id"` +} + +type DeleteTailnetTunnelRow struct { + CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"` + SrcID uuid.UUID `db:"src_id" json:"src_id"` + DstID uuid.UUID `db:"dst_id" json:"dst_id"` +} + +func (q *sqlQuerier) DeleteTailnetTunnel(ctx context.Context, arg DeleteTailnetTunnelParams) (DeleteTailnetTunnelRow, error) { + row := q.db.QueryRowContext(ctx, deleteTailnetTunnel, arg.CoordinatorID, arg.SrcID, arg.DstID) + var i DeleteTailnetTunnelRow + err := row.Scan(&i.CoordinatorID, &i.SrcID, &i.DstID) + return i, err +} + const getAllTailnetAgents = `-- name: GetAllTailnetAgents :many SELECT id, coordinator_id, updated_at, node FROM tailnet_agents @@ -4700,6 +4766,125 @@ func (q *sqlQuerier) GetTailnetClientsForAgent(ctx context.Context, agentID uuid return items, nil } +const getTailnetPeers = `-- name: GetTailnetPeers :many +SELECT id, coordinator_id, updated_at, node, status FROM tailnet_peers WHERE id = $1 +` + +func (q *sqlQuerier) GetTailnetPeers(ctx context.Context, id uuid.UUID) ([]TailnetPeer, error) { + rows, err := q.db.QueryContext(ctx, getTailnetPeers, id) + if err != nil { + return nil, err + } + defer rows.Close() + var items []TailnetPeer + for rows.Next() { + var i TailnetPeer + if err := rows.Scan( + &i.ID, + &i.CoordinatorID, + &i.UpdatedAt, + &i.Node, + &i.Status, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getTailnetTunnelPeerBindings = `-- name: GetTailnetTunnelPeerBindings :many +SELECT tailnet_tunnels.dst_id as peer_id, tailnet_peers.coordinator_id, tailnet_peers.updated_at, tailnet_peers.node +FROM tailnet_tunnels +INNER JOIN tailnet_peers ON tailnet_tunnels.dst_id = tailnet_peers.id +WHERE tailnet_tunnels.src_id = $1 +UNION +SELECT tailnet_tunnels.src_id as peer_id, tailnet_peers.coordinator_id, tailnet_peers.updated_at, tailnet_peers.node +FROM tailnet_tunnels +INNER JOIN tailnet_peers ON tailnet_tunnels.src_id = tailnet_peers.id +WHERE tailnet_tunnels.dst_id = $1 +` + +type GetTailnetTunnelPeerBindingsRow struct { + PeerID uuid.UUID `db:"peer_id" json:"peer_id"` + CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"` + UpdatedAt time.Time `db:"updated_at" json:"updated_at"` + Node []byte `db:"node" json:"node"` +} + +func (q *sqlQuerier) GetTailnetTunnelPeerBindings(ctx context.Context, srcID uuid.UUID) ([]GetTailnetTunnelPeerBindingsRow, error) { + rows, err := q.db.QueryContext(ctx, getTailnetTunnelPeerBindings, srcID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetTailnetTunnelPeerBindingsRow + for rows.Next() { + var i GetTailnetTunnelPeerBindingsRow + if err := rows.Scan( + &i.PeerID, + &i.CoordinatorID, + &i.UpdatedAt, + &i.Node, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getTailnetTunnelPeerIDs = `-- name: GetTailnetTunnelPeerIDs :many +SELECT dst_id as peer_id, coordinator_id, updated_at +FROM tailnet_tunnels +WHERE tailnet_tunnels.src_id = $1 +UNION +SELECT src_id as peer_id, coordinator_id, updated_at +FROM tailnet_tunnels +WHERE tailnet_tunnels.dst_id = $1 +` + +type GetTailnetTunnelPeerIDsRow struct { + PeerID uuid.UUID `db:"peer_id" json:"peer_id"` + CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"` + UpdatedAt time.Time `db:"updated_at" json:"updated_at"` +} + +func (q *sqlQuerier) GetTailnetTunnelPeerIDs(ctx context.Context, srcID uuid.UUID) ([]GetTailnetTunnelPeerIDsRow, error) { + rows, err := q.db.QueryContext(ctx, getTailnetTunnelPeerIDs, srcID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetTailnetTunnelPeerIDsRow + for rows.Next() { + var i GetTailnetTunnelPeerIDsRow + if err := rows.Scan(&i.PeerID, &i.CoordinatorID, &i.UpdatedAt); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const upsertTailnetAgent = `-- name: UpsertTailnetAgent :one INSERT INTO tailnet_agents ( @@ -4825,6 +5010,89 @@ func (q *sqlQuerier) UpsertTailnetCoordinator(ctx context.Context, id uuid.UUID) return i, err } +const upsertTailnetPeer = `-- name: UpsertTailnetPeer :one +INSERT INTO + tailnet_peers ( + id, + coordinator_id, + node, + status, + updated_at +) +VALUES + ($1, $2, $3, $4, now() at time zone 'utc') +ON CONFLICT (id, coordinator_id) +DO UPDATE SET + id = $1, + coordinator_id = $2, + node = $3, + status = $4, + updated_at = now() at time zone 'utc' +RETURNING id, coordinator_id, updated_at, node, status +` + +type UpsertTailnetPeerParams struct { + ID uuid.UUID `db:"id" json:"id"` + CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"` + Node []byte `db:"node" json:"node"` + Status TailnetStatus `db:"status" json:"status"` +} + +func (q *sqlQuerier) UpsertTailnetPeer(ctx context.Context, arg UpsertTailnetPeerParams) (TailnetPeer, error) { + row := q.db.QueryRowContext(ctx, upsertTailnetPeer, + arg.ID, + arg.CoordinatorID, + arg.Node, + arg.Status, + ) + var i TailnetPeer + err := row.Scan( + &i.ID, + &i.CoordinatorID, + &i.UpdatedAt, + &i.Node, + &i.Status, + ) + return i, err +} + +const upsertTailnetTunnel = `-- name: UpsertTailnetTunnel :one +INSERT INTO + tailnet_tunnels ( + coordinator_id, + src_id, + dst_id, + updated_at +) +VALUES + ($1, $2, $3, now() at time zone 'utc') +ON CONFLICT (coordinator_id, src_id, dst_id) +DO UPDATE SET + coordinator_id = $1, + src_id = $2, + dst_id = $3, + updated_at = now() at time zone 'utc' +RETURNING coordinator_id, src_id, dst_id, updated_at +` + +type UpsertTailnetTunnelParams struct { + CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"` + SrcID uuid.UUID `db:"src_id" json:"src_id"` + DstID uuid.UUID `db:"dst_id" json:"dst_id"` +} + +func (q *sqlQuerier) UpsertTailnetTunnel(ctx context.Context, arg UpsertTailnetTunnelParams) (TailnetTunnel, error) { + row := q.db.QueryRowContext(ctx, upsertTailnetTunnel, arg.CoordinatorID, arg.SrcID, arg.DstID) + var i TailnetTunnel + err := row.Scan( + &i.CoordinatorID, + &i.SrcID, + &i.DstID, + &i.UpdatedAt, + ) + return i, err +} + const getTemplateAverageBuildTime = `-- name: GetTemplateAverageBuildTime :one WITH build_times AS ( SELECT @@ -10387,7 +10655,7 @@ WHERE -- workspaces since they are considered soft-deleted. AND CASE WHEN $10 :: text != '' THEN - dormant_at IS NOT NULL + dormant_at IS NOT NULL ELSE dormant_at IS NULL END diff --git a/coderd/database/queries/tailnet.sql b/coderd/database/queries/tailnet.sql index 16f8708f3210a..011bc6900f2e7 100644 --- a/coderd/database/queries/tailnet.sql +++ b/coderd/database/queries/tailnet.sql @@ -121,3 +121,81 @@ RETURNING *; DELETE FROM tailnet_coordinators WHERE heartbeat_at < now() - INTERVAL '24 HOURS'; + +-- name: UpsertTailnetPeer :one +INSERT INTO + tailnet_peers ( + id, + coordinator_id, + node, + status, + updated_at +) +VALUES + ($1, $2, $3, $4, now() at time zone 'utc') +ON CONFLICT (id, coordinator_id) +DO UPDATE SET + id = $1, + coordinator_id = $2, + node = $3, + status = $4, + updated_at = now() at time zone 'utc' +RETURNING *; + +-- name: DeleteTailnetPeer :one +DELETE +FROM tailnet_peers +WHERE id = $1 and coordinator_id = $2 +RETURNING id, coordinator_id; + +-- name: GetTailnetPeers :many +SELECT * FROM tailnet_peers WHERE id = $1; + +-- name: UpsertTailnetTunnel :one +INSERT INTO + tailnet_tunnels ( + coordinator_id, + src_id, + dst_id, + updated_at +) +VALUES + ($1, $2, $3, now() at time zone 'utc') +ON CONFLICT (coordinator_id, src_id, dst_id) +DO UPDATE SET + coordinator_id = $1, + src_id = $2, + dst_id = $3, + updated_at = now() at time zone 'utc' +RETURNING *; + +-- name: DeleteTailnetTunnel :one +DELETE +FROM tailnet_tunnels +WHERE coordinator_id = $1 and src_id = $2 and dst_id = $3 +RETURNING coordinator_id, src_id, dst_id; + +-- name: DeleteAllTailnetTunnels :exec +DELETE +FROM tailnet_tunnels +WHERE coordinator_id = $1 and src_id = $2; + +-- name: GetTailnetTunnelPeerIDs :many +SELECT dst_id as peer_id, coordinator_id, updated_at +FROM tailnet_tunnels +WHERE tailnet_tunnels.src_id = $1 +UNION +SELECT src_id as peer_id, coordinator_id, updated_at +FROM tailnet_tunnels +WHERE tailnet_tunnels.dst_id = $1; + +-- name: GetTailnetTunnelPeerBindings :many +SELECT tailnet_tunnels.dst_id as peer_id, tailnet_peers.coordinator_id, tailnet_peers.updated_at, tailnet_peers.node +FROM tailnet_tunnels +INNER JOIN tailnet_peers ON tailnet_tunnels.dst_id = tailnet_peers.id +WHERE tailnet_tunnels.src_id = $1 +UNION +SELECT tailnet_tunnels.src_id as peer_id, tailnet_peers.coordinator_id, tailnet_peers.updated_at, tailnet_peers.node +FROM tailnet_tunnels +INNER JOIN tailnet_peers ON tailnet_tunnels.src_id = tailnet_peers.id +WHERE tailnet_tunnels.dst_id = $1; diff --git a/coderd/database/queries/workspaces.sql b/coderd/database/queries/workspaces.sql index f20c9edb88b28..01a283d1bc71c 100644 --- a/coderd/database/queries/workspaces.sql +++ b/coderd/database/queries/workspaces.sql @@ -243,7 +243,7 @@ WHERE -- workspaces since they are considered soft-deleted. AND CASE WHEN @is_dormant :: text != '' THEN - dormant_at IS NOT NULL + dormant_at IS NOT NULL ELSE dormant_at IS NULL END