Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 174664c

Browse files
committed
feat: agentapi uses appearance.Fetcher
1 parent 810bb6e commit 174664c

File tree

7 files changed

+120
-109
lines changed

7 files changed

+120
-109
lines changed

agent/proto/convert.go

+16
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

+3-1
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

+9-24
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
}
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

-84
This file was deleted.

coderd/workspaceagentsrpc.go

+1
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

+19
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)