Skip to content

Commit 385e74a

Browse files
committed
feat: agentapi uses appearance.Fetcher
1 parent bc4ae53 commit 385e74a

File tree

7 files changed

+120
-109
lines changed

7 files changed

+120
-109
lines changed

agent/proto/convert.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,19 @@ func SDKAppFromProto(protoApp *WorkspaceApp) (codersdk.WorkspaceApp, error) {
104104
Health: health,
105105
}, nil
106106
}
107+
108+
func SDKServiceBannerFromProto(sbp *ServiceBanner) codersdk.ServiceBannerConfig {
109+
return codersdk.ServiceBannerConfig{
110+
Enabled: sbp.GetEnabled(),
111+
Message: sbp.GetMessage(),
112+
BackgroundColor: sbp.GetBackgroundColor(),
113+
}
114+
}
115+
116+
func ServiceBannerFromSDK(sb codersdk.ServiceBannerConfig) *ServiceBanner {
117+
return &ServiceBanner{
118+
Enabled: sb.Enabled,
119+
Message: sb.Message,
120+
BackgroundColor: sb.BackgroundColor,
121+
}
122+
}

coderd/agentapi/api.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717

1818
"cdr.dev/slog"
1919
agentproto "github.com/coder/coder/v2/agent/proto"
20+
"github.com/coder/coder/v2/coderd/appearance"
2021
"github.com/coder/coder/v2/coderd/database"
2122
"github.com/coder/coder/v2/coderd/database/pubsub"
2223
"github.com/coder/coder/v2/coderd/externalauth"
@@ -61,6 +62,7 @@ type Options struct {
6162
TailnetCoordinator *atomic.Pointer[tailnet.Coordinator]
6263
TemplateScheduleStore *atomic.Pointer[schedule.TemplateScheduleStore]
6364
StatsBatcher StatsBatcher
65+
AppearanceFetcher *atomic.Pointer[appearance.Fetcher]
6466
PublishWorkspaceUpdateFn func(ctx context.Context, workspaceID uuid.UUID)
6567
PublishWorkspaceAgentLogsUpdateFn func(ctx context.Context, workspaceAgentID uuid.UUID, msg agentsdk.LogsNotifyMessage)
6668

@@ -98,7 +100,7 @@ func New(opts Options) *API {
98100
}
99101

100102
api.ServiceBannerAPI = &ServiceBannerAPI{
101-
Database: opts.Database,
103+
appearanceFetcher: opts.AppearanceFetcher,
102104
}
103105

104106
api.StatsAPI = &StatsAPI{

coderd/agentapi/servicebanner.go

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,22 @@ package agentapi
22

33
import (
44
"context"
5-
"database/sql"
6-
"encoding/json"
5+
"sync/atomic"
76

87
"golang.org/x/xerrors"
98

10-
agentproto "github.com/coder/coder/v2/agent/proto"
11-
"github.com/coder/coder/v2/coderd/database"
12-
"github.com/coder/coder/v2/codersdk"
9+
"github.com/coder/coder/v2/agent/proto"
10+
"github.com/coder/coder/v2/coderd/appearance"
1311
)
1412

1513
type ServiceBannerAPI struct {
16-
Database database.Store
14+
appearanceFetcher *atomic.Pointer[appearance.Fetcher]
1715
}
1816

19-
func (a *ServiceBannerAPI) GetServiceBanner(ctx context.Context, _ *agentproto.GetServiceBannerRequest) (*agentproto.ServiceBanner, error) {
20-
serviceBannerJSON, err := a.Database.GetServiceBanner(ctx)
21-
if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
22-
return nil, xerrors.Errorf("get service banner: %w", err)
17+
func (a *ServiceBannerAPI) GetServiceBanner(ctx context.Context, _ *proto.GetServiceBannerRequest) (*proto.ServiceBanner, error) {
18+
cfg, err := (*a.appearanceFetcher.Load()).Fetch(ctx)
19+
if err != nil {
20+
return nil, xerrors.Errorf("fetch appearance: %w", err)
2321
}
24-
25-
var cfg codersdk.ServiceBannerConfig
26-
if serviceBannerJSON != "" {
27-
err = json.Unmarshal([]byte(serviceBannerJSON), &cfg)
28-
if err != nil {
29-
return nil, xerrors.Errorf("unmarshal json: %w, raw: %s", err, serviceBannerJSON)
30-
}
31-
}
32-
33-
return &agentproto.ServiceBanner{
34-
Enabled: cfg.Enabled,
35-
Message: cfg.Message,
36-
BackgroundColor: cfg.BackgroundColor,
37-
}, nil
22+
return proto.ServiceBannerFromSDK(cfg.ServiceBanner), nil
3823
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package agentapi
2+
3+
import (
4+
"context"
5+
"sync/atomic"
6+
"testing"
7+
8+
"golang.org/x/xerrors"
9+
10+
agentproto "github.com/coder/coder/v2/agent/proto"
11+
"github.com/coder/coder/v2/coderd/appearance"
12+
"github.com/coder/coder/v2/codersdk"
13+
"github.com/stretchr/testify/require"
14+
)
15+
16+
func TestGetServiceBanner(t *testing.T) {
17+
t.Parallel()
18+
19+
t.Run("OK", func(t *testing.T) {
20+
t.Parallel()
21+
22+
cfg := codersdk.ServiceBannerConfig{
23+
Enabled: true,
24+
Message: "hello world",
25+
BackgroundColor: "#000000",
26+
}
27+
28+
var ff appearance.Fetcher = fakeFetcher{cfg: codersdk.AppearanceConfig{ServiceBanner: cfg}}
29+
ptr := atomic.Pointer[appearance.Fetcher]{}
30+
ptr.Store(&ff)
31+
32+
api := &ServiceBannerAPI{
33+
appearanceFetcher: &ptr,
34+
}
35+
36+
resp, err := api.GetServiceBanner(context.Background(), &agentproto.GetServiceBannerRequest{})
37+
require.NoError(t, err)
38+
39+
require.Equal(t, &agentproto.ServiceBanner{
40+
Enabled: cfg.Enabled,
41+
Message: cfg.Message,
42+
BackgroundColor: cfg.BackgroundColor,
43+
}, resp)
44+
})
45+
46+
t.Run("FetchError", func(t *testing.T) {
47+
t.Parallel()
48+
49+
expectedErr := xerrors.New("badness")
50+
var ff appearance.Fetcher = fakeFetcher{err: expectedErr}
51+
ptr := atomic.Pointer[appearance.Fetcher]{}
52+
ptr.Store(&ff)
53+
54+
api := &ServiceBannerAPI{
55+
appearanceFetcher: &ptr,
56+
}
57+
58+
resp, err := api.GetServiceBanner(context.Background(), &agentproto.GetServiceBannerRequest{})
59+
require.Error(t, err)
60+
require.ErrorIs(t, err, expectedErr)
61+
require.Nil(t, resp)
62+
})
63+
}
64+
65+
type fakeFetcher struct {
66+
cfg codersdk.AppearanceConfig
67+
err error
68+
}
69+
70+
func (f fakeFetcher) Fetch(context.Context) (codersdk.AppearanceConfig, error) {
71+
return f.cfg, f.err
72+
}

coderd/agentapi/servicebanner_test.go

Lines changed: 0 additions & 84 deletions
This file was deleted.

coderd/workspaceagentsrpc.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ func (api *API) workspaceAgentRPC(rw http.ResponseWriter, r *http.Request) {
130130
DerpMapFn: api.DERPMap,
131131
TailnetCoordinator: &api.TailnetCoordinator,
132132
TemplateScheduleStore: api.TemplateScheduleStore,
133+
AppearanceFetcher: &api.AppearanceFetcher,
133134
StatsBatcher: api.statsBatcher,
134135
PublishWorkspaceUpdateFn: api.publishWorkspaceUpdate,
135136
PublishWorkspaceAgentLogsUpdateFn: api.publishWorkspaceAgentLogsUpdate,

enterprise/coderd/appearance_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/stretchr/testify/assert"
1010
"github.com/stretchr/testify/require"
1111

12+
"github.com/coder/coder/v2/agent/proto"
1213
"github.com/coder/coder/v2/cli/clibase"
1314
"github.com/coder/coder/v2/coderd/appearance"
1415
"github.com/coder/coder/v2/coderd/coderdtest"
@@ -159,6 +160,8 @@ func TestServiceBanners(t *testing.T) {
159160
banner, err := agentClient.GetServiceBanner(ctx)
160161
require.NoError(t, err)
161162
require.Equal(t, cfg.ServiceBanner, banner)
163+
banner = requireGetServiceBannerV2(ctx, t, agentClient)
164+
require.Equal(t, cfg.ServiceBanner, banner)
162165

163166
// Create an AGPL Coderd against the same database
164167
agplClient := coderdtest.New(t, &coderdtest.Options{Database: store, Pubsub: ps})
@@ -167,16 +170,32 @@ func TestServiceBanners(t *testing.T) {
167170
banner, err = agplAgentClient.GetServiceBanner(ctx)
168171
require.NoError(t, err)
169172
require.Equal(t, codersdk.ServiceBannerConfig{}, banner)
173+
banner = requireGetServiceBannerV2(ctx, t, agplAgentClient)
174+
require.Equal(t, codersdk.ServiceBannerConfig{}, banner)
170175

171176
// No license means no banner.
172177
err = client.DeleteLicense(ctx, lic.ID)
173178
require.NoError(t, err)
174179
banner, err = agentClient.GetServiceBanner(ctx)
175180
require.NoError(t, err)
176181
require.Equal(t, codersdk.ServiceBannerConfig{}, banner)
182+
banner = requireGetServiceBannerV2(ctx, t, agentClient)
183+
require.Equal(t, codersdk.ServiceBannerConfig{}, banner)
177184
})
178185
}
179186

187+
func requireGetServiceBannerV2(ctx context.Context, t *testing.T, client *agentsdk.Client) codersdk.ServiceBannerConfig {
188+
cc, err := client.Listen(ctx)
189+
require.NoError(t, err)
190+
defer func() {
191+
_ = cc.Close()
192+
}()
193+
aAPI := proto.NewDRPCAgentClient(cc)
194+
sbp, err := aAPI.GetServiceBanner(ctx, &proto.GetServiceBannerRequest{})
195+
require.NoError(t, err)
196+
return proto.SDKServiceBannerFromProto(sbp)
197+
}
198+
180199
func TestCustomSupportLinks(t *testing.T) {
181200
t.Parallel()
182201

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