mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
fix: avoid deleting peers on graceful close (#14165)
* fix: avoid deleting peers on graceful close - Fixes an issue where a coordinator deletes all its peers on shutdown. This can cause disconnects whenever a coderd is redeployed.
This commit is contained in:
@ -3324,6 +3324,13 @@ func (q *querier) UpdateReplica(ctx context.Context, arg database.UpdateReplicaP
|
||||
return q.db.UpdateReplica(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpdateTailnetPeerStatusByCoordinator(ctx context.Context, arg database.UpdateTailnetPeerStatusByCoordinatorParams) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.UpdateTailnetPeerStatusByCoordinator(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpdateTemplateACLByID(ctx context.Context, arg database.UpdateTemplateACLByIDParams) error {
|
||||
fetch := func(ctx context.Context, arg database.UpdateTemplateACLByIDParams) (database.Template, error) {
|
||||
return q.db.GetTemplateByID(ctx, arg.ID)
|
||||
|
@ -2152,6 +2152,11 @@ func (s *MethodTestSuite) TestTailnetFunctions() {
|
||||
Asserts(rbac.ResourceTailnetCoordinator, policy.ActionCreate).
|
||||
Errors(dbmem.ErrUnimplemented)
|
||||
}))
|
||||
s.Run("UpdateTailnetPeerStatusByCoordinator", s.Subtest(func(_ database.Store, check *expects) {
|
||||
check.Args(database.UpdateTailnetPeerStatusByCoordinatorParams{}).
|
||||
Asserts(rbac.ResourceTailnetCoordinator, policy.ActionUpdate).
|
||||
Errors(dbmem.ErrUnimplemented)
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *MethodTestSuite) TestDBCrypt() {
|
||||
|
@ -7917,6 +7917,10 @@ func (q *FakeQuerier) UpdateReplica(_ context.Context, arg database.UpdateReplic
|
||||
return database.Replica{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (*FakeQuerier) UpdateTailnetPeerStatusByCoordinator(context.Context, database.UpdateTailnetPeerStatusByCoordinatorParams) error {
|
||||
return ErrUnimplemented
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) UpdateTemplateACLByID(_ context.Context, arg database.UpdateTemplateACLByIDParams) error {
|
||||
if err := validateDatabaseType(arg); err != nil {
|
||||
return err
|
||||
|
@ -2069,6 +2069,13 @@ func (m metricsStore) UpdateReplica(ctx context.Context, arg database.UpdateRepl
|
||||
return replica, err
|
||||
}
|
||||
|
||||
func (m metricsStore) UpdateTailnetPeerStatusByCoordinator(ctx context.Context, arg database.UpdateTailnetPeerStatusByCoordinatorParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpdateTailnetPeerStatusByCoordinator(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("UpdateTailnetPeerStatusByCoordinator").Observe(time.Since(start).Seconds())
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m metricsStore) UpdateTemplateACLByID(ctx context.Context, arg database.UpdateTemplateACLByIDParams) error {
|
||||
start := time.Now()
|
||||
err := m.s.UpdateTemplateACLByID(ctx, arg)
|
||||
|
@ -4366,6 +4366,20 @@ func (mr *MockStoreMockRecorder) UpdateReplica(arg0, arg1 any) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateReplica", reflect.TypeOf((*MockStore)(nil).UpdateReplica), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpdateTailnetPeerStatusByCoordinator mocks base method.
|
||||
func (m *MockStore) UpdateTailnetPeerStatusByCoordinator(arg0 context.Context, arg1 database.UpdateTailnetPeerStatusByCoordinatorParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateTailnetPeerStatusByCoordinator", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpdateTailnetPeerStatusByCoordinator indicates an expected call of UpdateTailnetPeerStatusByCoordinator.
|
||||
func (mr *MockStoreMockRecorder) UpdateTailnetPeerStatusByCoordinator(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTailnetPeerStatusByCoordinator", reflect.TypeOf((*MockStore)(nil).UpdateTailnetPeerStatusByCoordinator), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpdateTemplateACLByID mocks base method.
|
||||
func (m *MockStore) UpdateTemplateACLByID(arg0 context.Context, arg1 database.UpdateTemplateACLByIDParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -35,6 +35,7 @@ type options struct {
|
||||
dumpOnFailure bool
|
||||
returnSQLDB func(*sql.DB)
|
||||
logger slog.Logger
|
||||
url string
|
||||
}
|
||||
|
||||
type Option func(*options)
|
||||
@ -59,6 +60,12 @@ func WithLogger(logger slog.Logger) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func WithURL(u string) Option {
|
||||
return func(o *options) {
|
||||
o.url = u
|
||||
}
|
||||
}
|
||||
|
||||
func withReturnSQLDB(f func(*sql.DB)) Option {
|
||||
return func(o *options) {
|
||||
o.returnSQLDB = f
|
||||
@ -92,6 +99,9 @@ func NewDB(t testing.TB, opts ...Option) (database.Store, pubsub.Pubsub) {
|
||||
ps := pubsub.NewInMemory()
|
||||
if WillUsePostgres() {
|
||||
connectionURL := os.Getenv("CODER_PG_CONNECTION_URL")
|
||||
if connectionURL == "" && o.url != "" {
|
||||
connectionURL = o.url
|
||||
}
|
||||
if connectionURL == "" {
|
||||
var (
|
||||
err error
|
||||
|
@ -418,6 +418,7 @@ type sqlcQuerier interface {
|
||||
UpdateProvisionerJobWithCancelByID(ctx context.Context, arg UpdateProvisionerJobWithCancelByIDParams) error
|
||||
UpdateProvisionerJobWithCompleteByID(ctx context.Context, arg UpdateProvisionerJobWithCompleteByIDParams) error
|
||||
UpdateReplica(ctx context.Context, arg UpdateReplicaParams) (Replica, error)
|
||||
UpdateTailnetPeerStatusByCoordinator(ctx context.Context, arg UpdateTailnetPeerStatusByCoordinatorParams) error
|
||||
UpdateTemplateACLByID(ctx context.Context, arg UpdateTemplateACLByIDParams) error
|
||||
UpdateTemplateAccessControlByID(ctx context.Context, arg UpdateTemplateAccessControlByIDParams) error
|
||||
UpdateTemplateActiveVersionByID(ctx context.Context, arg UpdateTemplateActiveVersionByIDParams) error
|
||||
|
@ -7419,6 +7419,25 @@ func (q *sqlQuerier) GetTailnetTunnelPeerIDs(ctx context.Context, srcID uuid.UUI
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateTailnetPeerStatusByCoordinator = `-- name: UpdateTailnetPeerStatusByCoordinator :exec
|
||||
UPDATE
|
||||
tailnet_peers
|
||||
SET
|
||||
status = $2
|
||||
WHERE
|
||||
coordinator_id = $1
|
||||
`
|
||||
|
||||
type UpdateTailnetPeerStatusByCoordinatorParams struct {
|
||||
CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"`
|
||||
Status TailnetStatus `db:"status" json:"status"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateTailnetPeerStatusByCoordinator(ctx context.Context, arg UpdateTailnetPeerStatusByCoordinatorParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateTailnetPeerStatusByCoordinator, arg.CoordinatorID, arg.Status)
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertTailnetAgent = `-- name: UpsertTailnetAgent :one
|
||||
INSERT INTO
|
||||
tailnet_agents (
|
||||
|
@ -149,6 +149,14 @@ DO UPDATE SET
|
||||
updated_at = now() at time zone 'utc'
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateTailnetPeerStatusByCoordinator :exec
|
||||
UPDATE
|
||||
tailnet_peers
|
||||
SET
|
||||
status = $2
|
||||
WHERE
|
||||
coordinator_id = $1;
|
||||
|
||||
-- name: DeleteTailnetPeer :one
|
||||
DELETE
|
||||
FROM tailnet_peers
|
||||
|
Reference in New Issue
Block a user