Skip to content

Commit cb9d40f

Browse files
Emyrkdannykopping
andauthored
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>
1 parent 9da6467 commit cb9d40f

File tree

18 files changed

+546
-0
lines changed

18 files changed

+546
-0
lines changed

cli/server.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import (
5656
"cdr.dev/slog"
5757
"cdr.dev/slog/sloggers/sloghuman"
5858
"github.com/coder/coder/v2/coderd/entitlements"
59+
"github.com/coder/coder/v2/coderd/runtimeconfig"
5960
"github.com/coder/pretty"
6061
"github.com/coder/quartz"
6162
"github.com/coder/retry"
@@ -820,6 +821,8 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
820821
return err
821822
}
822823

824+
options.RuntimeConfig = runtimeconfig.NewManager()
825+
823826
// This should be output before the logs start streaming.
824827
cliui.Infof(inv.Stdout, "\n==> Logs will stream in below (press ctrl+c to gracefully exit):")
825828

coderd/coderd.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"cdr.dev/slog"
4040
"github.com/coder/coder/v2/coderd/entitlements"
4141
"github.com/coder/coder/v2/coderd/idpsync"
42+
"github.com/coder/coder/v2/coderd/runtimeconfig"
4243
"github.com/coder/quartz"
4344
"github.com/coder/serpent"
4445

@@ -135,6 +136,7 @@ type Options struct {
135136
Logger slog.Logger
136137
Database database.Store
137138
Pubsub pubsub.Pubsub
139+
RuntimeConfig *runtimeconfig.Manager
138140

139141
// CacheDir is used for caching files served by the API.
140142
CacheDir string

coderd/coderdtest/coderdtest.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ import (
6767
"github.com/coder/coder/v2/coderd/notifications"
6868
"github.com/coder/coder/v2/coderd/rbac"
6969
"github.com/coder/coder/v2/coderd/rbac/policy"
70+
"github.com/coder/coder/v2/coderd/runtimeconfig"
7071
"github.com/coder/coder/v2/coderd/schedule"
7172
"github.com/coder/coder/v2/coderd/telemetry"
7273
"github.com/coder/coder/v2/coderd/unhanger"
@@ -254,6 +255,7 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
254255
var acs dbauthz.AccessControlStore = dbauthz.AGPLTemplateAccessControlStore{}
255256
accessControlStore.Store(&acs)
256257

258+
runtimeManager := runtimeconfig.NewManager()
257259
options.Database = dbauthz.New(options.Database, options.Authorizer, *options.Logger, accessControlStore)
258260

259261
// Some routes expect a deployment ID, so just make sure one exists.
@@ -482,6 +484,7 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
482484
AppHostnameRegex: appHostnameRegex,
483485
Logger: *options.Logger,
484486
CacheDir: t.TempDir(),
487+
RuntimeConfig: runtimeManager,
485488
Database: options.Database,
486489
Pubsub: options.Pubsub,
487490
ExternalAuthConfigs: options.ExternalAuthConfigs,

coderd/database/dbauthz/dbauthz.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,13 @@ func (q *querier) DeleteReplicasUpdatedBefore(ctx context.Context, updatedAt tim
11831183
return q.db.DeleteReplicasUpdatedBefore(ctx, updatedAt)
11841184
}
11851185

1186+
func (q *querier) DeleteRuntimeConfig(ctx context.Context, key string) error {
1187+
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceSystem); err != nil {
1188+
return err
1189+
}
1190+
return q.db.DeleteRuntimeConfig(ctx, key)
1191+
}
1192+
11861193
func (q *querier) DeleteTailnetAgent(ctx context.Context, arg database.DeleteTailnetAgentParams) (database.DeleteTailnetAgentRow, error) {
11871194
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil {
11881195
return database.DeleteTailnetAgentRow{}, err
@@ -1856,6 +1863,13 @@ func (q *querier) GetReplicasUpdatedAfter(ctx context.Context, updatedAt time.Ti
18561863
return q.db.GetReplicasUpdatedAfter(ctx, updatedAt)
18571864
}
18581865

1866+
func (q *querier) GetRuntimeConfig(ctx context.Context, key string) (string, error) {
1867+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
1868+
return "", err
1869+
}
1870+
return q.db.GetRuntimeConfig(ctx, key)
1871+
}
1872+
18591873
func (q *querier) GetTailnetAgents(ctx context.Context, id uuid.UUID) ([]database.TailnetAgent, error) {
18601874
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTailnetCoordinator); err != nil {
18611875
return nil, err
@@ -3906,6 +3920,13 @@ func (q *querier) UpsertProvisionerDaemon(ctx context.Context, arg database.Upse
39063920
return q.db.UpsertProvisionerDaemon(ctx, arg)
39073921
}
39083922

3923+
func (q *querier) UpsertRuntimeConfig(ctx context.Context, arg database.UpsertRuntimeConfigParams) error {
3924+
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil {
3925+
return err
3926+
}
3927+
return q.db.UpsertRuntimeConfig(ctx, arg)
3928+
}
3929+
39093930
func (q *querier) UpsertTailnetAgent(ctx context.Context, arg database.UpsertTailnetAgentParams) (database.TailnetAgent, error) {
39103931
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil {
39113932
return database.TailnetAgent{}, err

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2696,6 +2696,22 @@ func (s *MethodTestSuite) TestSystemFunctions() {
26962696
AgentID: uuid.New(),
26972697
}).Asserts(tpl, policy.ActionCreate)
26982698
}))
2699+
s.Run("DeleteRuntimeConfig", s.Subtest(func(db database.Store, check *expects) {
2700+
check.Args("test").Asserts(rbac.ResourceSystem, policy.ActionDelete)
2701+
}))
2702+
s.Run("GetRuntimeConfig", s.Subtest(func(db database.Store, check *expects) {
2703+
_ = db.UpsertRuntimeConfig(context.Background(), database.UpsertRuntimeConfigParams{
2704+
Key: "test",
2705+
Value: "value",
2706+
})
2707+
check.Args("test").Asserts(rbac.ResourceSystem, policy.ActionRead)
2708+
}))
2709+
s.Run("UpsertRuntimeConfig", s.Subtest(func(db database.Store, check *expects) {
2710+
check.Args(database.UpsertRuntimeConfigParams{
2711+
Key: "test",
2712+
Value: "value",
2713+
}).Asserts(rbac.ResourceSystem, policy.ActionCreate)
2714+
}))
26992715
}
27002716

27012717
func (s *MethodTestSuite) TestNotifications() {

coderd/database/dbmem/dbmem.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ func New() database.Store {
8484
workspaceProxies: make([]database.WorkspaceProxy, 0),
8585
customRoles: make([]database.CustomRole, 0),
8686
locks: map[int64]struct{}{},
87+
runtimeConfig: map[string]string{},
8788
},
8889
}
8990
// Always start with a default org. Matching migration 198.
@@ -194,6 +195,7 @@ type data struct {
194195
workspaces []database.Workspace
195196
workspaceProxies []database.WorkspaceProxy
196197
customRoles []database.CustomRole
198+
runtimeConfig map[string]string
197199
// Locks is a map of lock names. Any keys within the map are currently
198200
// locked.
199201
locks map[int64]struct{}
@@ -1928,6 +1930,14 @@ func (q *FakeQuerier) DeleteReplicasUpdatedBefore(_ context.Context, before time
19281930
return nil
19291931
}
19301932

1933+
func (q *FakeQuerier) DeleteRuntimeConfig(_ context.Context, key string) error {
1934+
q.mutex.Lock()
1935+
defer q.mutex.Unlock()
1936+
1937+
delete(q.runtimeConfig, key)
1938+
return nil
1939+
}
1940+
19311941
func (*FakeQuerier) DeleteTailnetAgent(context.Context, database.DeleteTailnetAgentParams) (database.DeleteTailnetAgentRow, error) {
19321942
return database.DeleteTailnetAgentRow{}, ErrUnimplemented
19331943
}
@@ -3505,6 +3515,18 @@ func (q *FakeQuerier) GetReplicasUpdatedAfter(_ context.Context, updatedAt time.
35053515
return replicas, nil
35063516
}
35073517

3518+
func (q *FakeQuerier) GetRuntimeConfig(_ context.Context, key string) (string, error) {
3519+
q.mutex.Lock()
3520+
defer q.mutex.Unlock()
3521+
3522+
val, ok := q.runtimeConfig[key]
3523+
if !ok {
3524+
return "", sql.ErrNoRows
3525+
}
3526+
3527+
return val, nil
3528+
}
3529+
35083530
func (*FakeQuerier) GetTailnetAgents(context.Context, uuid.UUID) ([]database.TailnetAgent, error) {
35093531
return nil, ErrUnimplemented
35103532
}
@@ -9187,6 +9209,19 @@ func (q *FakeQuerier) UpsertProvisionerDaemon(_ context.Context, arg database.Up
91879209
return d, nil
91889210
}
91899211

9212+
func (q *FakeQuerier) UpsertRuntimeConfig(_ context.Context, arg database.UpsertRuntimeConfigParams) error {
9213+
err := validateDatabaseType(arg)
9214+
if err != nil {
9215+
return err
9216+
}
9217+
9218+
q.mutex.Lock()
9219+
defer q.mutex.Unlock()
9220+
9221+
q.runtimeConfig[arg.Key] = arg.Value
9222+
return nil
9223+
}
9224+
91909225
func (*FakeQuerier) UpsertTailnetAgent(context.Context, database.UpsertTailnetAgentParams) (database.TailnetAgent, error) {
91919226
return database.TailnetAgent{}, ErrUnimplemented
91929227
}

coderd/database/dbmetrics/dbmetrics.go

Lines changed: 21 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: 43 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/querier.go

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

coderd/database/queries.sql.go

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

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy