diff --git a/agent/agent.go b/agent/agent.go index 92ab84a2d0..377dec7492 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -41,6 +41,7 @@ import ( "github.com/coder/coder/v2/agent/agentproc" "github.com/coder/coder/v2/agent/agentscripts" "github.com/coder/coder/v2/agent/agentssh" + "github.com/coder/coder/v2/agent/proto" "github.com/coder/coder/v2/agent/reconnectingpty" "github.com/coder/coder/v2/buildinfo" "github.com/coder/coder/v2/cli/gitauth" @@ -95,7 +96,6 @@ type Client interface { PostStartup(ctx context.Context, req agentsdk.PostStartupRequest) error PostMetadata(ctx context.Context, req agentsdk.PostMetadataRequest) error PatchLogs(ctx context.Context, req agentsdk.PatchLogs) error - GetServiceBanner(ctx context.Context) (codersdk.ServiceBannerConfig, error) } type Agent interface { @@ -269,7 +269,6 @@ func (a *agent) init(ctx context.Context) { func (a *agent) runLoop(ctx context.Context) { go a.reportLifecycleLoop(ctx) go a.reportMetadataLoop(ctx) - go a.fetchServiceBannerLoop(ctx) go a.manageProcessPriorityLoop(ctx) for retrier := retry.New(100*time.Millisecond, 10*time.Second); retrier.Wait(ctx); { @@ -662,22 +661,23 @@ func (a *agent) setLifecycle(ctx context.Context, state codersdk.WorkspaceAgentL // fetchServiceBannerLoop fetches the service banner on an interval. It will // not be fetched immediately; the expectation is that it is primed elsewhere // (and must be done before the session actually starts). -func (a *agent) fetchServiceBannerLoop(ctx context.Context) { +func (a *agent) fetchServiceBannerLoop(ctx context.Context, aAPI proto.DRPCAgentClient) error { ticker := time.NewTicker(a.serviceBannerRefreshInterval) defer ticker.Stop() for { select { case <-ctx.Done(): - return + return ctx.Err() case <-ticker.C: - serviceBanner, err := a.client.GetServiceBanner(ctx) + sbp, err := aAPI.GetServiceBanner(ctx, &proto.GetServiceBannerRequest{}) if err != nil { if ctx.Err() != nil { - return + return ctx.Err() } a.logger.Error(ctx, "failed to update service banner", slog.Error(err)) - continue + return err } + serviceBanner := proto.SDKServiceBannerFromProto(sbp) a.serviceBanner.Store(&serviceBanner) } } @@ -693,10 +693,24 @@ func (a *agent) run(ctx context.Context) error { } a.sessionToken.Store(&sessionToken) - serviceBanner, err := a.client.GetServiceBanner(ctx) + // Listen returns the dRPC connection we use for the Agent v2+ API + conn, err := a.client.Listen(ctx) + if err != nil { + return err + } + defer func() { + cErr := conn.Close() + if cErr != nil { + a.logger.Debug(ctx, "error closing drpc connection", slog.Error(err)) + } + }() + + aAPI := proto.NewDRPCAgentClient(conn) + sbp, err := aAPI.GetServiceBanner(ctx, &proto.GetServiceBannerRequest{}) if err != nil { return xerrors.Errorf("fetch service banner: %w", err) } + serviceBanner := proto.SDKServiceBannerFromProto(sbp) a.serviceBanner.Store(&serviceBanner) manifest, err := a.client.Manifest(ctx) @@ -821,18 +835,6 @@ func (a *agent) run(ctx context.Context) error { network.SetBlockEndpoints(manifest.DisableDirectConnections) } - // Listen returns the dRPC connection we use for both Coordinator and DERPMap updates - conn, err := a.client.Listen(ctx) - if err != nil { - return err - } - defer func() { - cErr := conn.Close() - if cErr != nil { - a.logger.Debug(ctx, "error closing drpc connection", slog.Error(err)) - } - }() - eg, egCtx := errgroup.WithContext(ctx) eg.Go(func() error { a.logger.Debug(egCtx, "running tailnet connection coordinator") @@ -852,6 +854,15 @@ func (a *agent) run(ctx context.Context) error { return nil }) + eg.Go(func() error { + a.logger.Debug(egCtx, "running fetch server banner loop") + err := a.fetchServiceBannerLoop(egCtx, aAPI) + if err != nil { + return xerrors.Errorf("fetch server banner loop: %w", err) + } + return nil + }) + return eg.Wait() } diff --git a/agent/agent_test.go b/agent/agent_test.go index 6f3ab55ffd..ca30bf3b98 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -35,6 +35,7 @@ import ( "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/valyala/fasthttp/fasthttputil" "go.uber.org/goleak" "go.uber.org/mock/gomock" "golang.org/x/crypto/ssh" @@ -2026,7 +2027,10 @@ func setupAgent(t *testing.T, metadata agentsdk.Manifest, ptyTimeout time.Durati afero.Fs, agent.Agent, ) { - logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) + logger := slogtest.Make(t, &slogtest.Options{ + // we get this error when closing the Agent API + IgnoredErrorIs: append(slogtest.DefaultIgnoredErrorIs, fasthttputil.ErrInmemoryListenerClosed), + }).Leveled(slog.LevelDebug) if metadata.DERPMap == nil { metadata.DERPMap, _ = tailnettest.RunDERPAndSTUN(t) } diff --git a/agent/agenttest/client.go b/agent/agenttest/client.go index d7c632e7d4..2eaa11156c 100644 --- a/agent/agenttest/client.go +++ b/agent/agenttest/client.go @@ -18,6 +18,7 @@ import ( "tailscale.com/tailcfg" "cdr.dev/slog" + agentproto "github.com/coder/coder/v2/agent/proto" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" drpcsdk "github.com/coder/coder/v2/codersdk/drpc" @@ -48,6 +49,9 @@ func NewClient(t testing.TB, } err := proto.DRPCRegisterTailnet(mux, drpcService) require.NoError(t, err) + fakeAAPI := NewFakeAgentAPI(t, logger) + err = agentproto.DRPCRegisterAgent(mux, fakeAAPI) + require.NoError(t, err) server := drpcserver.NewWithOptions(mux, drpcserver.Options{ Log: func(err error) { if xerrors.Is(err, io.EOF) { @@ -64,22 +68,23 @@ func NewClient(t testing.TB, statsChan: statsChan, coordinator: coordinator, server: server, + fakeAgentAPI: fakeAAPI, derpMapUpdates: derpMapUpdates, } } type Client struct { - t testing.TB - logger slog.Logger - agentID uuid.UUID - manifest agentsdk.Manifest - metadata map[string]agentsdk.Metadata - statsChan chan *agentsdk.Stats - coordinator tailnet.Coordinator - server *drpcserver.Server - LastWorkspaceAgent func() - PatchWorkspaceLogs func() error - GetServiceBannerFunc func() (codersdk.ServiceBannerConfig, error) + t testing.TB + logger slog.Logger + agentID uuid.UUID + manifest agentsdk.Manifest + metadata map[string]agentsdk.Metadata + statsChan chan *agentsdk.Stats + coordinator tailnet.Coordinator + server *drpcserver.Server + fakeAgentAPI *FakeAgentAPI + LastWorkspaceAgent func() + PatchWorkspaceLogs func() error mu sync.Mutex // Protects following. lifecycleStates []codersdk.WorkspaceAgentLifecycle @@ -221,20 +226,7 @@ func (c *Client) PatchLogs(ctx context.Context, logs agentsdk.PatchLogs) error { } func (c *Client) SetServiceBannerFunc(f func() (codersdk.ServiceBannerConfig, error)) { - c.mu.Lock() - defer c.mu.Unlock() - - c.GetServiceBannerFunc = f -} - -func (c *Client) GetServiceBanner(ctx context.Context) (codersdk.ServiceBannerConfig, error) { - c.mu.Lock() - defer c.mu.Unlock() - c.logger.Debug(ctx, "get service banner") - if c.GetServiceBannerFunc != nil { - return c.GetServiceBannerFunc() - } - return codersdk.ServiceBannerConfig{}, nil + c.fakeAgentAPI.SetServiceBannerFunc(f) } func (c *Client) PushDERPMapUpdate(update *tailcfg.DERPMap) error { @@ -254,3 +246,73 @@ type closeFunc func() error func (c closeFunc) Close() error { return c() } + +type FakeAgentAPI struct { + sync.Mutex + t testing.TB + logger slog.Logger + + getServiceBannerFunc func() (codersdk.ServiceBannerConfig, error) +} + +func (*FakeAgentAPI) GetManifest(context.Context, *agentproto.GetManifestRequest) (*agentproto.Manifest, error) { + // TODO implement me + panic("implement me") +} + +func (f *FakeAgentAPI) SetServiceBannerFunc(fn func() (codersdk.ServiceBannerConfig, error)) { + f.Lock() + defer f.Unlock() + f.getServiceBannerFunc = fn + f.logger.Info(context.Background(), "updated ServiceBannerFunc") +} + +func (f *FakeAgentAPI) GetServiceBanner(context.Context, *agentproto.GetServiceBannerRequest) (*agentproto.ServiceBanner, error) { + f.Lock() + defer f.Unlock() + if f.getServiceBannerFunc == nil { + return &agentproto.ServiceBanner{}, nil + } + sb, err := f.getServiceBannerFunc() + if err != nil { + return nil, err + } + return agentproto.ServiceBannerFromSDK(sb), nil +} + +func (*FakeAgentAPI) UpdateStats(context.Context, *agentproto.UpdateStatsRequest) (*agentproto.UpdateStatsResponse, error) { + // TODO implement me + panic("implement me") +} + +func (*FakeAgentAPI) UpdateLifecycle(context.Context, *agentproto.UpdateLifecycleRequest) (*agentproto.Lifecycle, error) { + // TODO implement me + panic("implement me") +} + +func (*FakeAgentAPI) BatchUpdateAppHealths(context.Context, *agentproto.BatchUpdateAppHealthRequest) (*agentproto.BatchUpdateAppHealthResponse, error) { + // TODO implement me + panic("implement me") +} + +func (*FakeAgentAPI) UpdateStartup(context.Context, *agentproto.UpdateStartupRequest) (*agentproto.Startup, error) { + // TODO implement me + panic("implement me") +} + +func (*FakeAgentAPI) BatchUpdateMetadata(context.Context, *agentproto.BatchUpdateMetadataRequest) (*agentproto.BatchUpdateMetadataResponse, error) { + // TODO implement me + panic("implement me") +} + +func (*FakeAgentAPI) BatchCreateLogs(context.Context, *agentproto.BatchCreateLogsRequest) (*agentproto.BatchCreateLogsResponse, error) { + // TODO implement me + panic("implement me") +} + +func NewFakeAgentAPI(t testing.TB, logger slog.Logger) *FakeAgentAPI { + return &FakeAgentAPI{ + t: t, + logger: logger.Named("FakeAgentAPI"), + } +} diff --git a/cli/agent_test.go b/cli/agent_test.go index eb0140c446..fd71b962b9 100644 --- a/cli/agent_test.go +++ b/cli/agent_test.go @@ -83,7 +83,8 @@ func TestWorkspaceAgent(t *testing.T) { ctx := inv.Context() clitest.Start(t, inv) - coderdtest.AwaitWorkspaceAgents(t, client, r.Workspace.ID) + coderdtest.NewWorkspaceAgentWaiter(t, client, r.Workspace.ID). + MatchResources(matchAgentWithVersion).Wait() workspace, err := client.Workspace(ctx, r.Workspace.ID) require.NoError(t, err) resources := workspace.LatestBuild.Resources @@ -120,7 +121,9 @@ func TestWorkspaceAgent(t *testing.T) { clitest.Start(t, inv) ctx := inv.Context() - coderdtest.AwaitWorkspaceAgents(t, client, r.Workspace.ID) + coderdtest.NewWorkspaceAgentWaiter(t, client, r.Workspace.ID). + MatchResources(matchAgentWithVersion). + Wait() workspace, err := client.Workspace(ctx, r.Workspace.ID) require.NoError(t, err) resources := workspace.LatestBuild.Resources @@ -161,7 +164,9 @@ func TestWorkspaceAgent(t *testing.T) { ) ctx := inv.Context() - coderdtest.AwaitWorkspaceAgents(t, client, r.Workspace.ID) + coderdtest.NewWorkspaceAgentWaiter(t, client, r.Workspace.ID). + MatchResources(matchAgentWithVersion). + Wait() workspace, err := client.Workspace(ctx, r.Workspace.ID) require.NoError(t, err) resources := workspace.LatestBuild.Resources @@ -212,7 +217,8 @@ func TestWorkspaceAgent(t *testing.T) { clitest.Start(t, inv) - resources := coderdtest.AwaitWorkspaceAgents(t, client, r.Workspace.ID) + resources := coderdtest.NewWorkspaceAgentWaiter(t, client, r.Workspace.ID). + MatchResources(matchAgentWithSubsystems).Wait() require.Len(t, resources, 1) require.Len(t, resources[0].Agents, 1) require.Len(t, resources[0].Agents[0].Subsystems, 2) @@ -221,3 +227,29 @@ func TestWorkspaceAgent(t *testing.T) { require.Equal(t, codersdk.AgentSubsystemExectrace, resources[0].Agents[0].Subsystems[1]) }) } + +func matchAgentWithVersion(rs []codersdk.WorkspaceResource) bool { + if len(rs) < 1 { + return false + } + if len(rs[0].Agents) < 1 { + return false + } + if rs[0].Agents[0].Version == "" { + return false + } + return true +} + +func matchAgentWithSubsystems(rs []codersdk.WorkspaceResource) bool { + if len(rs) < 1 { + return false + } + if len(rs[0].Agents) < 1 { + return false + } + if len(rs[0].Agents[0].Subsystems) < 1 { + return false + } + return true +} diff --git a/coderd/agentapi/servicebanner_internal_test.go b/coderd/agentapi/servicebanner_internal_test.go index d559bf0860..6098d7df5f 100644 --- a/coderd/agentapi/servicebanner_internal_test.go +++ b/coderd/agentapi/servicebanner_internal_test.go @@ -5,12 +5,12 @@ import ( "sync/atomic" "testing" + "github.com/stretchr/testify/require" "golang.org/x/xerrors" agentproto "github.com/coder/coder/v2/agent/proto" "github.com/coder/coder/v2/coderd/appearance" "github.com/coder/coder/v2/codersdk" - "github.com/stretchr/testify/require" ) func TestGetServiceBanner(t *testing.T) { diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index 91ff7e1753..b1c496e4ba 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -915,23 +915,67 @@ func AwaitWorkspaceBuildJobCompleted(t testing.TB, client *codersdk.Client, buil // AwaitWorkspaceAgents waits for all resources with agents to be connected. If // specific agents are provided, it will wait for those agents to be connected // but will not fail if other agents are not connected. +// +// Deprecated: Use NewWorkspaceAgentWaiter func AwaitWorkspaceAgents(t testing.TB, client *codersdk.Client, workspaceID uuid.UUID, agentNames ...string) []codersdk.WorkspaceResource { - t.Helper() + return NewWorkspaceAgentWaiter(t, client, workspaceID).AgentNames(agentNames).Wait() +} - agentNamesMap := make(map[string]struct{}, len(agentNames)) - for _, name := range agentNames { +// WorkspaceAgentWaiter waits for all resources with agents to be connected. If +// specific agents are provided using AgentNames(), it will wait for those agents +// to be connected but will not fail if other agents are not connected. +type WorkspaceAgentWaiter struct { + t testing.TB + client *codersdk.Client + workspaceID uuid.UUID + agentNames []string + resourcesMatcher func([]codersdk.WorkspaceResource) bool +} + +// NewWorkspaceAgentWaiter returns an object that waits for agents to connect when +// you call Wait() on it. +func NewWorkspaceAgentWaiter(t testing.TB, client *codersdk.Client, workspaceID uuid.UUID) WorkspaceAgentWaiter { + return WorkspaceAgentWaiter{ + t: t, + client: client, + workspaceID: workspaceID, + } +} + +// AgentNames instructs the waiter to wait for the given, named agents to be connected and will +// return even if other agents are not connected. +func (w WorkspaceAgentWaiter) AgentNames(names []string) WorkspaceAgentWaiter { + //nolint: revive // returns modified struct + w.agentNames = names + return w +} + +// MatchResources instructs the waiter to wait until the workspace has resources that cause the +// provided matcher function to return true. +func (w WorkspaceAgentWaiter) MatchResources(m func([]codersdk.WorkspaceResource) bool) WorkspaceAgentWaiter { + //nolint: revive // returns modified struct + w.resourcesMatcher = m + return w +} + +// Wait waits for the agent(s) to connect and fails the test if they do not within testutil.WaitLong +func (w WorkspaceAgentWaiter) Wait() []codersdk.WorkspaceResource { + w.t.Helper() + + agentNamesMap := make(map[string]struct{}, len(w.agentNames)) + for _, name := range w.agentNames { agentNamesMap[name] = struct{}{} } ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() - t.Logf("waiting for workspace agents (workspace %s)", workspaceID) + w.t.Logf("waiting for workspace agents (workspace %s)", w.workspaceID) var resources []codersdk.WorkspaceResource - require.Eventually(t, func() bool { + require.Eventually(w.t, func() bool { var err error - workspace, err := client.Workspace(ctx, workspaceID) - if !assert.NoError(t, err) { + workspace, err := w.client.Workspace(ctx, w.workspaceID) + if !assert.NoError(w.t, err) { return false } if workspace.LatestBuild.Job.CompletedAt == nil { @@ -943,23 +987,25 @@ func AwaitWorkspaceAgents(t testing.TB, client *codersdk.Client, workspaceID uui for _, resource := range workspace.LatestBuild.Resources { for _, agent := range resource.Agents { - if len(agentNames) > 0 { + if len(w.agentNames) > 0 { if _, ok := agentNamesMap[agent.Name]; !ok { continue } } if agent.Status != codersdk.WorkspaceAgentConnected { - t.Logf("agent %s not connected yet", agent.Name) + w.t.Logf("agent %s not connected yet", agent.Name) return false } } } resources = workspace.LatestBuild.Resources - - return true + if w.resourcesMatcher == nil { + return true + } + return w.resourcesMatcher(resources) }, testutil.WaitLong, testutil.IntervalMedium) - t.Logf("got workspace agents (workspace %s)", workspaceID) + w.t.Logf("got workspace agents (workspace %s)", w.workspaceID) return resources } diff --git a/coderd/wsconncache/wsconncache_test.go b/coderd/wsconncache/wsconncache_test.go index ae01bf5785..ac69702faf 100644 --- a/coderd/wsconncache/wsconncache_test.go +++ b/coderd/wsconncache/wsconncache_test.go @@ -29,6 +29,8 @@ import ( "cdr.dev/slog" "cdr.dev/slog/sloggers/slogtest" "github.com/coder/coder/v2/agent" + "github.com/coder/coder/v2/agent/agenttest" + agentproto "github.com/coder/coder/v2/agent/proto" "github.com/coder/coder/v2/coderd/wsconncache" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" @@ -171,13 +173,12 @@ func setupAgent(t *testing.T, manifest agentsdk.Manifest, ptyTimeout time.Durati _ = coordinator.Close() }) manifest.AgentID = uuid.New() - aC := &client{ - t: t, - agentID: manifest.AgentID, - manifest: manifest, - coordinator: coordinator, - derpMapUpdates: make(chan *tailcfg.DERPMap), - } + aC := newClient( + t, + slogtest.Make(t, nil).Leveled(slog.LevelDebug), + manifest, + coordinator, + ) t.Cleanup(aC.close) closer := agent.New(agent.Options{ Client: aC, @@ -239,6 +240,45 @@ type client struct { coordinator tailnet.Coordinator closeOnce sync.Once derpMapUpdates chan *tailcfg.DERPMap + server *drpcserver.Server + fakeAgentAPI *agenttest.FakeAgentAPI +} + +func newClient(t *testing.T, logger slog.Logger, manifest agentsdk.Manifest, coordinator tailnet.Coordinator) *client { + logger = logger.Named("drpc") + coordPtr := atomic.Pointer[tailnet.Coordinator]{} + coordPtr.Store(&coordinator) + mux := drpcmux.New() + derpMapUpdates := make(chan *tailcfg.DERPMap) + drpcService := &tailnet.DRPCService{ + CoordPtr: &coordPtr, + Logger: logger, + DerpMapUpdateFrequency: time.Microsecond, + DerpMapFn: func() *tailcfg.DERPMap { return <-derpMapUpdates }, + } + err := proto.DRPCRegisterTailnet(mux, drpcService) + require.NoError(t, err) + fakeAAPI := agenttest.NewFakeAgentAPI(t, logger) + err = agentproto.DRPCRegisterAgent(mux, fakeAAPI) + require.NoError(t, err) + server := drpcserver.NewWithOptions(mux, drpcserver.Options{ + Log: func(err error) { + if xerrors.Is(err, io.EOF) { + return + } + logger.Debug(context.Background(), "drpc server error", slog.Error(err)) + }, + }) + + return &client{ + t: t, + agentID: manifest.AgentID, + manifest: manifest, + coordinator: coordinator, + derpMapUpdates: derpMapUpdates, + server: server, + fakeAgentAPI: fakeAAPI, + } } func (c *client) close() { @@ -250,35 +290,12 @@ func (c *client) Manifest(_ context.Context) (agentsdk.Manifest, error) { } func (c *client) Listen(_ context.Context) (drpc.Conn, error) { - logger := slogtest.Make(c.t, nil).Leveled(slog.LevelDebug).Named("drpc") conn, lis := drpcsdk.MemTransportPipe() c.t.Cleanup(func() { _ = conn.Close() _ = lis.Close() }) - coordPtr := atomic.Pointer[tailnet.Coordinator]{} - coordPtr.Store(&c.coordinator) - mux := drpcmux.New() - drpcService := &tailnet.DRPCService{ - CoordPtr: &coordPtr, - Logger: logger, - DerpMapUpdateFrequency: time.Microsecond, - DerpMapFn: func() *tailcfg.DERPMap { return <-c.derpMapUpdates }, - } - err := proto.DRPCRegisterTailnet(mux, drpcService) - if err != nil { - return nil, xerrors.Errorf("register DRPC service: %w", err) - } - server := drpcserver.NewWithOptions(mux, drpcserver.Options{ - Log: func(err error) { - if xerrors.Is(err, io.EOF) || - xerrors.Is(err, context.Canceled) || - xerrors.Is(err, context.DeadlineExceeded) { - return - } - logger.Debug(context.Background(), "drpc server error", slog.Error(err)) - }, - }) + serveCtx, cancel := context.WithCancel(context.Background()) c.t.Cleanup(cancel) auth := tailnet.AgentTunnelAuth{} @@ -289,7 +306,7 @@ func (c *client) Listen(_ context.Context) (drpc.Conn, error) { } serveCtx = tailnet.WithStreamID(serveCtx, streamID) go func() { - server.Serve(serveCtx, lis) + c.server.Serve(serveCtx, lis) }() return conn, nil } @@ -317,7 +334,3 @@ func (*client) PostStartup(_ context.Context, _ agentsdk.PostStartupRequest) err func (*client) PatchLogs(_ context.Context, _ agentsdk.PatchLogs) error { return nil } - -func (*client) GetServiceBanner(_ context.Context) (codersdk.ServiceBannerConfig, error) { - return codersdk.ServiceBannerConfig{}, nil -} diff --git a/codersdk/agentsdk/agentsdk.go b/codersdk/agentsdk/agentsdk.go index 2e94b6cd42..cddb03aae1 100644 --- a/codersdk/agentsdk/agentsdk.go +++ b/codersdk/agentsdk/agentsdk.go @@ -637,24 +637,6 @@ func (c *Client) PostLogSource(ctx context.Context, req PostLogSource) (codersdk return logSource, json.NewDecoder(res.Body).Decode(&logSource) } -// GetServiceBanner relays the service banner config. -func (c *Client) GetServiceBanner(ctx context.Context) (codersdk.ServiceBannerConfig, error) { - res, err := c.SDK.Request(ctx, http.MethodGet, "/api/v2/appearance", nil) - if err != nil { - return codersdk.ServiceBannerConfig{}, err - } - defer res.Body.Close() - // If the route does not exist then Enterprise code is not enabled. - if res.StatusCode == http.StatusNotFound { - return codersdk.ServiceBannerConfig{}, nil - } - if res.StatusCode != http.StatusOK { - return codersdk.ServiceBannerConfig{}, codersdk.ReadBodyAsError(res) - } - var cfg codersdk.AppearanceConfig - return cfg.ServiceBanner, json.NewDecoder(res.Body).Decode(&cfg) -} - type ExternalAuthResponse struct { AccessToken string `json:"access_token"` TokenExtra map[string]interface{} `json:"token_extra"` diff --git a/enterprise/coderd/appearance_test.go b/enterprise/coderd/appearance_test.go index 41e2e8c6f0..9abdee599d 100644 --- a/enterprise/coderd/appearance_test.go +++ b/enterprise/coderd/appearance_test.go @@ -157,34 +157,25 @@ func TestServiceBanners(t *testing.T) { agentClient := agentsdk.New(client.URL) agentClient.SetSessionToken(r.AgentToken) - banner, err := agentClient.GetServiceBanner(ctx) - require.NoError(t, err) - require.Equal(t, cfg.ServiceBanner, banner) - banner = requireGetServiceBannerV2(ctx, t, agentClient) + banner := requireGetServiceBanner(ctx, t, agentClient) require.Equal(t, cfg.ServiceBanner, banner) // Create an AGPL Coderd against the same database agplClient := coderdtest.New(t, &coderdtest.Options{Database: store, Pubsub: ps}) agplAgentClient := agentsdk.New(agplClient.URL) agplAgentClient.SetSessionToken(r.AgentToken) - banner, err = agplAgentClient.GetServiceBanner(ctx) - require.NoError(t, err) - require.Equal(t, codersdk.ServiceBannerConfig{}, banner) - banner = requireGetServiceBannerV2(ctx, t, agplAgentClient) + banner = requireGetServiceBanner(ctx, t, agplAgentClient) require.Equal(t, codersdk.ServiceBannerConfig{}, banner) // No license means no banner. err = client.DeleteLicense(ctx, lic.ID) require.NoError(t, err) - banner, err = agentClient.GetServiceBanner(ctx) - require.NoError(t, err) - require.Equal(t, codersdk.ServiceBannerConfig{}, banner) - banner = requireGetServiceBannerV2(ctx, t, agentClient) + banner = requireGetServiceBanner(ctx, t, agentClient) require.Equal(t, codersdk.ServiceBannerConfig{}, banner) }) } -func requireGetServiceBannerV2(ctx context.Context, t *testing.T, client *agentsdk.Client) codersdk.ServiceBannerConfig { +func requireGetServiceBanner(ctx context.Context, t *testing.T, client *agentsdk.Client) codersdk.ServiceBannerConfig { cc, err := client.Listen(ctx) require.NoError(t, err) defer func() { diff --git a/go.mod b/go.mod index 27cef3718d..bbdc6462f4 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ replace github.com/imulab/go-scim/pkg/v2 => github.com/coder/go-scim/pkg/v2 v2.0 replace github.com/pkg/sftp => github.com/mafredri/sftp v1.13.6-0.20231212144145-8218e927edb0 require ( - cdr.dev/slog v1.6.2-0.20230929193652-f0c466fabe10 + cdr.dev/slog v1.6.2-0.20240126064726-20367d4aede6 cloud.google.com/go/compute/metadata v0.2.3 github.com/AlecAivazis/survey/v2 v2.3.5 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d diff --git a/go.sum b/go.sum index 39af1d5a16..c74f064e40 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -cdr.dev/slog v1.6.2-0.20230929193652-f0c466fabe10 h1:gnB1By6Hzs2PVQXyi/cvo6L3kHPb8utLuzycWHfCztQ= -cdr.dev/slog v1.6.2-0.20230929193652-f0c466fabe10/go.mod h1:NaoTA7KwopCrnaSb0JXTC0PTp/O/Y83Lndnq0OEV3ZQ= +cdr.dev/slog v1.6.2-0.20240126064726-20367d4aede6 h1:KHblWIE/KHOwQ6lEbMZt6YpcGve2FEZ1sDtrW1Am5UI= +cdr.dev/slog v1.6.2-0.20240126064726-20367d4aede6/go.mod h1:NaoTA7KwopCrnaSb0JXTC0PTp/O/Y83Lndnq0OEV3ZQ= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=