mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: implement runtime configuration package with multi-org support (#14624)
runtime configuration package --------- Signed-off-by: Danny Kopping <danny@coder.com> Co-authored-by: Danny Kopping <danny@coder.com>
This commit is contained in:
co-authored by
Danny Kopping
parent
9da646704b
commit
cb9d40fb8a
@@ -1183,6 +1183,13 @@ func (q *querier) DeleteReplicasUpdatedBefore(ctx context.Context, updatedAt tim
|
||||
return q.db.DeleteReplicasUpdatedBefore(ctx, updatedAt)
|
||||
}
|
||||
|
||||
func (q *querier) DeleteRuntimeConfig(ctx context.Context, key string) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceSystem); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.DeleteRuntimeConfig(ctx, key)
|
||||
}
|
||||
|
||||
func (q *querier) DeleteTailnetAgent(ctx context.Context, arg database.DeleteTailnetAgentParams) (database.DeleteTailnetAgentRow, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil {
|
||||
return database.DeleteTailnetAgentRow{}, err
|
||||
@@ -1856,6 +1863,13 @@ func (q *querier) GetReplicasUpdatedAfter(ctx context.Context, updatedAt time.Ti
|
||||
return q.db.GetReplicasUpdatedAfter(ctx, updatedAt)
|
||||
}
|
||||
|
||||
func (q *querier) GetRuntimeConfig(ctx context.Context, key string) (string, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return q.db.GetRuntimeConfig(ctx, key)
|
||||
}
|
||||
|
||||
func (q *querier) GetTailnetAgents(ctx context.Context, id uuid.UUID) ([]database.TailnetAgent, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTailnetCoordinator); err != nil {
|
||||
return nil, err
|
||||
@@ -3906,6 +3920,13 @@ func (q *querier) UpsertProvisionerDaemon(ctx context.Context, arg database.Upse
|
||||
return q.db.UpsertProvisionerDaemon(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertRuntimeConfig(ctx context.Context, arg database.UpsertRuntimeConfigParams) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.UpsertRuntimeConfig(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertTailnetAgent(ctx context.Context, arg database.UpsertTailnetAgentParams) (database.TailnetAgent, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil {
|
||||
return database.TailnetAgent{}, err
|
||||
|
||||
@@ -2696,6 +2696,22 @@ func (s *MethodTestSuite) TestSystemFunctions() {
|
||||
AgentID: uuid.New(),
|
||||
}).Asserts(tpl, policy.ActionCreate)
|
||||
}))
|
||||
s.Run("DeleteRuntimeConfig", s.Subtest(func(db database.Store, check *expects) {
|
||||
check.Args("test").Asserts(rbac.ResourceSystem, policy.ActionDelete)
|
||||
}))
|
||||
s.Run("GetRuntimeConfig", s.Subtest(func(db database.Store, check *expects) {
|
||||
_ = db.UpsertRuntimeConfig(context.Background(), database.UpsertRuntimeConfigParams{
|
||||
Key: "test",
|
||||
Value: "value",
|
||||
})
|
||||
check.Args("test").Asserts(rbac.ResourceSystem, policy.ActionRead)
|
||||
}))
|
||||
s.Run("UpsertRuntimeConfig", s.Subtest(func(db database.Store, check *expects) {
|
||||
check.Args(database.UpsertRuntimeConfigParams{
|
||||
Key: "test",
|
||||
Value: "value",
|
||||
}).Asserts(rbac.ResourceSystem, policy.ActionCreate)
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *MethodTestSuite) TestNotifications() {
|
||||
|
||||
@@ -84,6 +84,7 @@ func New() database.Store {
|
||||
workspaceProxies: make([]database.WorkspaceProxy, 0),
|
||||
customRoles: make([]database.CustomRole, 0),
|
||||
locks: map[int64]struct{}{},
|
||||
runtimeConfig: map[string]string{},
|
||||
},
|
||||
}
|
||||
// Always start with a default org. Matching migration 198.
|
||||
@@ -194,6 +195,7 @@ type data struct {
|
||||
workspaces []database.Workspace
|
||||
workspaceProxies []database.WorkspaceProxy
|
||||
customRoles []database.CustomRole
|
||||
runtimeConfig map[string]string
|
||||
// Locks is a map of lock names. Any keys within the map are currently
|
||||
// locked.
|
||||
locks map[int64]struct{}
|
||||
@@ -1928,6 +1930,14 @@ func (q *FakeQuerier) DeleteReplicasUpdatedBefore(_ context.Context, before time
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) DeleteRuntimeConfig(_ context.Context, key string) error {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
delete(q.runtimeConfig, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*FakeQuerier) DeleteTailnetAgent(context.Context, database.DeleteTailnetAgentParams) (database.DeleteTailnetAgentRow, error) {
|
||||
return database.DeleteTailnetAgentRow{}, ErrUnimplemented
|
||||
}
|
||||
@@ -3505,6 +3515,18 @@ func (q *FakeQuerier) GetReplicasUpdatedAfter(_ context.Context, updatedAt time.
|
||||
return replicas, nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) GetRuntimeConfig(_ context.Context, key string) (string, error) {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
val, ok := q.runtimeConfig[key]
|
||||
if !ok {
|
||||
return "", sql.ErrNoRows
|
||||
}
|
||||
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func (*FakeQuerier) GetTailnetAgents(context.Context, uuid.UUID) ([]database.TailnetAgent, error) {
|
||||
return nil, ErrUnimplemented
|
||||
}
|
||||
@@ -9187,6 +9209,19 @@ func (q *FakeQuerier) UpsertProvisionerDaemon(_ context.Context, arg database.Up
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) UpsertRuntimeConfig(_ context.Context, arg database.UpsertRuntimeConfigParams) error {
|
||||
err := validateDatabaseType(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
q.runtimeConfig[arg.Key] = arg.Value
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*FakeQuerier) UpsertTailnetAgent(context.Context, database.UpsertTailnetAgentParams) (database.TailnetAgent, error) {
|
||||
return database.TailnetAgent{}, ErrUnimplemented
|
||||
}
|
||||
|
||||
@@ -347,6 +347,13 @@ func (m metricsStore) DeleteReplicasUpdatedBefore(ctx context.Context, updatedAt
|
||||
return err
|
||||
}
|
||||
|
||||
func (m metricsStore) DeleteRuntimeConfig(ctx context.Context, key string) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.DeleteRuntimeConfig(ctx, key)
|
||||
m.queryLatencies.WithLabelValues("DeleteRuntimeConfig").Observe(time.Since(start).Seconds())
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m metricsStore) DeleteTailnetAgent(ctx context.Context, arg database.DeleteTailnetAgentParams) (database.DeleteTailnetAgentRow, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.DeleteTailnetAgent(ctx, arg)
|
||||
@@ -991,6 +998,13 @@ func (m metricsStore) GetReplicasUpdatedAfter(ctx context.Context, updatedAt tim
|
||||
return replicas, err
|
||||
}
|
||||
|
||||
func (m metricsStore) GetRuntimeConfig(ctx context.Context, key string) (string, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetRuntimeConfig(ctx, key)
|
||||
m.queryLatencies.WithLabelValues("GetRuntimeConfig").Observe(time.Since(start).Seconds())
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m metricsStore) GetTailnetAgents(ctx context.Context, id uuid.UUID) ([]database.TailnetAgent, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetTailnetAgents(ctx, id)
|
||||
@@ -2454,6 +2468,13 @@ func (m metricsStore) UpsertProvisionerDaemon(ctx context.Context, arg database.
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m metricsStore) UpsertRuntimeConfig(ctx context.Context, arg database.UpsertRuntimeConfigParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertRuntimeConfig(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("UpsertRuntimeConfig").Observe(time.Since(start).Seconds())
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m metricsStore) UpsertTailnetAgent(ctx context.Context, arg database.UpsertTailnetAgentParams) (database.TailnetAgent, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.UpsertTailnetAgent(ctx, arg)
|
||||
|
||||
@@ -584,6 +584,20 @@ func (mr *MockStoreMockRecorder) DeleteReplicasUpdatedBefore(arg0, arg1 any) *go
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteReplicasUpdatedBefore", reflect.TypeOf((*MockStore)(nil).DeleteReplicasUpdatedBefore), arg0, arg1)
|
||||
}
|
||||
|
||||
// DeleteRuntimeConfig mocks base method.
|
||||
func (m *MockStore) DeleteRuntimeConfig(arg0 context.Context, arg1 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DeleteRuntimeConfig", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DeleteRuntimeConfig indicates an expected call of DeleteRuntimeConfig.
|
||||
func (mr *MockStoreMockRecorder) DeleteRuntimeConfig(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRuntimeConfig", reflect.TypeOf((*MockStore)(nil).DeleteRuntimeConfig), arg0, arg1)
|
||||
}
|
||||
|
||||
// DeleteTailnetAgent mocks base method.
|
||||
func (m *MockStore) DeleteTailnetAgent(arg0 context.Context, arg1 database.DeleteTailnetAgentParams) (database.DeleteTailnetAgentRow, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -2019,6 +2033,21 @@ func (mr *MockStoreMockRecorder) GetReplicasUpdatedAfter(arg0, arg1 any) *gomock
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReplicasUpdatedAfter", reflect.TypeOf((*MockStore)(nil).GetReplicasUpdatedAfter), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetRuntimeConfig mocks base method.
|
||||
func (m *MockStore) GetRuntimeConfig(arg0 context.Context, arg1 string) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetRuntimeConfig", arg0, arg1)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetRuntimeConfig indicates an expected call of GetRuntimeConfig.
|
||||
func (mr *MockStoreMockRecorder) GetRuntimeConfig(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRuntimeConfig", reflect.TypeOf((*MockStore)(nil).GetRuntimeConfig), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetTailnetAgents mocks base method.
|
||||
func (m *MockStore) GetTailnetAgents(arg0 context.Context, arg1 uuid.UUID) ([]database.TailnetAgent, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -5151,6 +5180,20 @@ func (mr *MockStoreMockRecorder) UpsertProvisionerDaemon(arg0, arg1 any) *gomock
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertProvisionerDaemon", reflect.TypeOf((*MockStore)(nil).UpsertProvisionerDaemon), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpsertRuntimeConfig mocks base method.
|
||||
func (m *MockStore) UpsertRuntimeConfig(arg0 context.Context, arg1 database.UpsertRuntimeConfigParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpsertRuntimeConfig", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpsertRuntimeConfig indicates an expected call of UpsertRuntimeConfig.
|
||||
func (mr *MockStoreMockRecorder) UpsertRuntimeConfig(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertRuntimeConfig", reflect.TypeOf((*MockStore)(nil).UpsertRuntimeConfig), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpsertTailnetAgent mocks base method.
|
||||
func (m *MockStore) UpsertTailnetAgent(arg0 context.Context, arg1 database.UpsertTailnetAgentParams) (database.TailnetAgent, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
@@ -96,6 +96,7 @@ type sqlcQuerier interface {
|
||||
DeleteOrganizationMember(ctx context.Context, arg DeleteOrganizationMemberParams) error
|
||||
DeleteProvisionerKey(ctx context.Context, id uuid.UUID) error
|
||||
DeleteReplicasUpdatedBefore(ctx context.Context, updatedAt time.Time) error
|
||||
DeleteRuntimeConfig(ctx context.Context, key string) error
|
||||
DeleteTailnetAgent(ctx context.Context, arg DeleteTailnetAgentParams) (DeleteTailnetAgentRow, error)
|
||||
DeleteTailnetClient(ctx context.Context, arg DeleteTailnetClientParams) (DeleteTailnetClientRow, error)
|
||||
DeleteTailnetClientSubscription(ctx context.Context, arg DeleteTailnetClientSubscriptionParams) error
|
||||
@@ -199,6 +200,7 @@ type sqlcQuerier interface {
|
||||
GetQuotaConsumedForUser(ctx context.Context, arg GetQuotaConsumedForUserParams) (int64, error)
|
||||
GetReplicaByID(ctx context.Context, id uuid.UUID) (Replica, error)
|
||||
GetReplicasUpdatedAfter(ctx context.Context, updatedAt time.Time) ([]Replica, error)
|
||||
GetRuntimeConfig(ctx context.Context, key string) (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)
|
||||
@@ -478,6 +480,7 @@ type sqlcQuerier interface {
|
||||
UpsertNotificationsSettings(ctx context.Context, value string) error
|
||||
UpsertOAuthSigningKey(ctx context.Context, value string) error
|
||||
UpsertProvisionerDaemon(ctx context.Context, arg UpsertProvisionerDaemonParams) (ProvisionerDaemon, error)
|
||||
UpsertRuntimeConfig(ctx context.Context, arg UpsertRuntimeConfigParams) error
|
||||
UpsertTailnetAgent(ctx context.Context, arg UpsertTailnetAgentParams) (TailnetAgent, error)
|
||||
UpsertTailnetClient(ctx context.Context, arg UpsertTailnetClientParams) (TailnetClient, error)
|
||||
UpsertTailnetClientSubscription(ctx context.Context, arg UpsertTailnetClientSubscriptionParams) error
|
||||
|
||||
@@ -6703,6 +6703,16 @@ func (q *sqlQuerier) UpdateCustomRole(ctx context.Context, arg UpdateCustomRoleP
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteRuntimeConfig = `-- name: DeleteRuntimeConfig :exec
|
||||
DELETE FROM site_configs
|
||||
WHERE site_configs.key = $1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) DeleteRuntimeConfig(ctx context.Context, key string) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteRuntimeConfig, key)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAnnouncementBanners = `-- name: GetAnnouncementBanners :one
|
||||
SELECT value FROM site_configs WHERE key = 'announcement_banners'
|
||||
`
|
||||
@@ -6844,6 +6854,17 @@ func (q *sqlQuerier) GetOAuthSigningKey(ctx context.Context) (string, error) {
|
||||
return value, err
|
||||
}
|
||||
|
||||
const getRuntimeConfig = `-- name: GetRuntimeConfig :one
|
||||
SELECT value FROM site_configs WHERE site_configs.key = $1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetRuntimeConfig(ctx context.Context, key string) (string, error) {
|
||||
row := q.db.QueryRowContext(ctx, getRuntimeConfig, key)
|
||||
var value string
|
||||
err := row.Scan(&value)
|
||||
return value, err
|
||||
}
|
||||
|
||||
const insertDERPMeshKey = `-- name: InsertDERPMeshKey :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('derp_mesh_key', $1)
|
||||
`
|
||||
@@ -6975,6 +6996,21 @@ func (q *sqlQuerier) UpsertOAuthSigningKey(ctx context.Context, value string) er
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertRuntimeConfig = `-- name: UpsertRuntimeConfig :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ($1, $2)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $2 WHERE site_configs.key = $1
|
||||
`
|
||||
|
||||
type UpsertRuntimeConfigParams struct {
|
||||
Key string `db:"key" json:"key"`
|
||||
Value string `db:"value" json:"value"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpsertRuntimeConfig(ctx context.Context, arg UpsertRuntimeConfigParams) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertRuntimeConfig, arg.Key, arg.Value)
|
||||
return err
|
||||
}
|
||||
|
||||
const cleanTailnetCoordinators = `-- name: CleanTailnetCoordinators :exec
|
||||
DELETE
|
||||
FROM tailnet_coordinators
|
||||
|
||||
@@ -96,3 +96,14 @@ SELECT
|
||||
INSERT INTO site_configs (key, value) VALUES ('notifications_settings', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'notifications_settings';
|
||||
|
||||
-- name: GetRuntimeConfig :one
|
||||
SELECT value FROM site_configs WHERE site_configs.key = $1;
|
||||
|
||||
-- name: UpsertRuntimeConfig :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ($1, $2)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $2 WHERE site_configs.key = $1;
|
||||
|
||||
-- name: DeleteRuntimeConfig :exec
|
||||
DELETE FROM site_configs
|
||||
WHERE site_configs.key = $1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user