mirror of https://github.com/coder/coder.git
Compare commits
12 Commits
50be22f76c
...
859a4b66cd
Author | SHA1 | Date |
---|---|---|
Kayla Washburn-Love | 859a4b66cd | |
McKayla Washburn | ff1a914af8 | |
McKayla Washburn | 95c6f2cd1d | |
McKayla Washburn | 7080879935 | |
McKayla Washburn | 9bc61254d2 | |
McKayla Washburn | d6b5326397 | |
Colin Adler | 13dd526f11 | |
McKayla Washburn | aefa8012e4 | |
recanman | b20c63c185 | |
Michael Brewer | 060f023174 | |
McKayla Washburn | a6236f4777 | |
Colin Adler | 205c43da99 |
110
agent/agent.go
110
agent/agent.go
|
@ -155,35 +155,35 @@ func New(options Options) Agent {
|
|||
hardCtx, hardCancel := context.WithCancel(context.Background())
|
||||
gracefulCtx, gracefulCancel := context.WithCancel(hardCtx)
|
||||
a := &agent{
|
||||
tailnetListenPort: options.TailnetListenPort,
|
||||
reconnectingPTYTimeout: options.ReconnectingPTYTimeout,
|
||||
logger: options.Logger,
|
||||
gracefulCtx: gracefulCtx,
|
||||
gracefulCancel: gracefulCancel,
|
||||
hardCtx: hardCtx,
|
||||
hardCancel: hardCancel,
|
||||
coordDisconnected: make(chan struct{}),
|
||||
environmentVariables: options.EnvironmentVariables,
|
||||
client: options.Client,
|
||||
exchangeToken: options.ExchangeToken,
|
||||
filesystem: options.Filesystem,
|
||||
logDir: options.LogDir,
|
||||
tempDir: options.TempDir,
|
||||
scriptDataDir: options.ScriptDataDir,
|
||||
lifecycleUpdate: make(chan struct{}, 1),
|
||||
lifecycleReported: make(chan codersdk.WorkspaceAgentLifecycle, 1),
|
||||
lifecycleStates: []agentsdk.PostLifecycleRequest{{State: codersdk.WorkspaceAgentLifecycleCreated}},
|
||||
ignorePorts: options.IgnorePorts,
|
||||
portCacheDuration: options.PortCacheDuration,
|
||||
reportMetadataInterval: options.ReportMetadataInterval,
|
||||
serviceBannerRefreshInterval: options.ServiceBannerRefreshInterval,
|
||||
sshMaxTimeout: options.SSHMaxTimeout,
|
||||
subsystems: options.Subsystems,
|
||||
addresses: options.Addresses,
|
||||
syscaller: options.Syscaller,
|
||||
modifiedProcs: options.ModifiedProcesses,
|
||||
processManagementTick: options.ProcessManagementTick,
|
||||
logSender: agentsdk.NewLogSender(options.Logger),
|
||||
tailnetListenPort: options.TailnetListenPort,
|
||||
reconnectingPTYTimeout: options.ReconnectingPTYTimeout,
|
||||
logger: options.Logger,
|
||||
gracefulCtx: gracefulCtx,
|
||||
gracefulCancel: gracefulCancel,
|
||||
hardCtx: hardCtx,
|
||||
hardCancel: hardCancel,
|
||||
coordDisconnected: make(chan struct{}),
|
||||
environmentVariables: options.EnvironmentVariables,
|
||||
client: options.Client,
|
||||
exchangeToken: options.ExchangeToken,
|
||||
filesystem: options.Filesystem,
|
||||
logDir: options.LogDir,
|
||||
tempDir: options.TempDir,
|
||||
scriptDataDir: options.ScriptDataDir,
|
||||
lifecycleUpdate: make(chan struct{}, 1),
|
||||
lifecycleReported: make(chan codersdk.WorkspaceAgentLifecycle, 1),
|
||||
lifecycleStates: []agentsdk.PostLifecycleRequest{{State: codersdk.WorkspaceAgentLifecycleCreated}},
|
||||
ignorePorts: options.IgnorePorts,
|
||||
portCacheDuration: options.PortCacheDuration,
|
||||
reportMetadataInterval: options.ReportMetadataInterval,
|
||||
notificationBannersRefreshInterval: options.ServiceBannerRefreshInterval,
|
||||
sshMaxTimeout: options.SSHMaxTimeout,
|
||||
subsystems: options.Subsystems,
|
||||
addresses: options.Addresses,
|
||||
syscaller: options.Syscaller,
|
||||
modifiedProcs: options.ModifiedProcesses,
|
||||
processManagementTick: options.ProcessManagementTick,
|
||||
logSender: agentsdk.NewLogSender(options.Logger),
|
||||
|
||||
prometheusRegistry: prometheusRegistry,
|
||||
metrics: newAgentMetrics(prometheusRegistry),
|
||||
|
@ -193,7 +193,7 @@ func New(options Options) Agent {
|
|||
// that gets closed on disconnection. This is used to wait for graceful disconnection from the
|
||||
// coordinator during shut down.
|
||||
close(a.coordDisconnected)
|
||||
a.serviceBanner.Store(new(codersdk.ServiceBannerConfig))
|
||||
a.notificationBanners.Store(new([]codersdk.BannerConfig))
|
||||
a.sessionToken.Store(new(string))
|
||||
a.init()
|
||||
return a
|
||||
|
@ -231,14 +231,14 @@ type agent struct {
|
|||
|
||||
environmentVariables map[string]string
|
||||
|
||||
manifest atomic.Pointer[agentsdk.Manifest] // manifest is atomic because values can change after reconnection.
|
||||
reportMetadataInterval time.Duration
|
||||
scriptRunner *agentscripts.Runner
|
||||
serviceBanner atomic.Pointer[codersdk.ServiceBannerConfig] // serviceBanner is atomic because it is periodically updated.
|
||||
serviceBannerRefreshInterval time.Duration
|
||||
sessionToken atomic.Pointer[string]
|
||||
sshServer *agentssh.Server
|
||||
sshMaxTimeout time.Duration
|
||||
manifest atomic.Pointer[agentsdk.Manifest] // manifest is atomic because values can change after reconnection.
|
||||
reportMetadataInterval time.Duration
|
||||
scriptRunner *agentscripts.Runner
|
||||
notificationBanners atomic.Pointer[[]codersdk.BannerConfig] // notificationBanners is atomic because it is periodically updated.
|
||||
notificationBannersRefreshInterval time.Duration
|
||||
sessionToken atomic.Pointer[string]
|
||||
sshServer *agentssh.Server
|
||||
sshMaxTimeout time.Duration
|
||||
|
||||
lifecycleUpdate chan struct{}
|
||||
lifecycleReported chan codersdk.WorkspaceAgentLifecycle
|
||||
|
@ -272,11 +272,11 @@ func (a *agent) TailnetConn() *tailnet.Conn {
|
|||
func (a *agent) init() {
|
||||
// pass the "hard" context because we explicitly close the SSH server as part of graceful shutdown.
|
||||
sshSrv, err := agentssh.NewServer(a.hardCtx, a.logger.Named("ssh-server"), a.prometheusRegistry, a.filesystem, &agentssh.Config{
|
||||
MaxTimeout: a.sshMaxTimeout,
|
||||
MOTDFile: func() string { return a.manifest.Load().MOTDFile },
|
||||
ServiceBanner: func() *codersdk.ServiceBannerConfig { return a.serviceBanner.Load() },
|
||||
UpdateEnv: a.updateCommandEnv,
|
||||
WorkingDirectory: func() string { return a.manifest.Load().Directory },
|
||||
MaxTimeout: a.sshMaxTimeout,
|
||||
MOTDFile: func() string { return a.manifest.Load().MOTDFile },
|
||||
NotificationBanners: func() *[]codersdk.BannerConfig { return a.notificationBanners.Load() },
|
||||
UpdateEnv: a.updateCommandEnv,
|
||||
WorkingDirectory: func() string { return a.manifest.Load().Directory },
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -709,23 +709,26 @@ func (a *agent) setLifecycle(state codersdk.WorkspaceAgentLifecycle) {
|
|||
// (and must be done before the session actually starts).
|
||||
func (a *agent) fetchServiceBannerLoop(ctx context.Context, conn drpc.Conn) error {
|
||||
aAPI := proto.NewDRPCAgentClient(conn)
|
||||
ticker := time.NewTicker(a.serviceBannerRefreshInterval)
|
||||
ticker := time.NewTicker(a.notificationBannersRefreshInterval)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-ticker.C:
|
||||
sbp, err := aAPI.GetServiceBanner(ctx, &proto.GetServiceBannerRequest{})
|
||||
bannersProto, err := aAPI.GetNotificationBanners(ctx, &proto.GetNotificationBannersRequest{})
|
||||
if err != nil {
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
a.logger.Error(ctx, "failed to update service banner", slog.Error(err))
|
||||
a.logger.Error(ctx, "failed to update notification banners", slog.Error(err))
|
||||
return err
|
||||
}
|
||||
serviceBanner := agentsdk.ServiceBannerFromProto(sbp)
|
||||
a.serviceBanner.Store(&serviceBanner)
|
||||
banners := make([]codersdk.BannerConfig, 0, len(bannersProto.NotificationBanners))
|
||||
for _, bannerProto := range bannersProto.NotificationBanners {
|
||||
banners = append(banners, agentsdk.BannerConfigFromProto(bannerProto))
|
||||
}
|
||||
a.notificationBanners.Store(&banners)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -757,15 +760,18 @@ func (a *agent) run() (retErr error) {
|
|||
// redial the coder server and retry.
|
||||
connMan := newAPIConnRoutineManager(a.gracefulCtx, a.hardCtx, a.logger, conn)
|
||||
|
||||
connMan.start("init service banner", gracefulShutdownBehaviorStop,
|
||||
connMan.start("init notification banners", gracefulShutdownBehaviorStop,
|
||||
func(ctx context.Context, conn drpc.Conn) error {
|
||||
aAPI := proto.NewDRPCAgentClient(conn)
|
||||
sbp, err := aAPI.GetServiceBanner(ctx, &proto.GetServiceBannerRequest{})
|
||||
bannersProto, err := aAPI.GetNotificationBanners(ctx, &proto.GetNotificationBannersRequest{})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("fetch service banner: %w", err)
|
||||
}
|
||||
serviceBanner := agentsdk.ServiceBannerFromProto(sbp)
|
||||
a.serviceBanner.Store(&serviceBanner)
|
||||
banners := make([]codersdk.BannerConfig, 0, len(bannersProto.NotificationBanners))
|
||||
for _, bannerProto := range bannersProto.NotificationBanners {
|
||||
banners = append(banners, agentsdk.BannerConfigFromProto(bannerProto))
|
||||
}
|
||||
a.notificationBanners.Store(&banners)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
|
|
@ -614,12 +614,12 @@ func TestAgent_Session_TTY_MOTD_Update(t *testing.T) {
|
|||
// Set new banner func and wait for the agent to call it to update the
|
||||
// banner.
|
||||
ready := make(chan struct{}, 2)
|
||||
client.SetServiceBannerFunc(func() (codersdk.ServiceBannerConfig, error) {
|
||||
client.SetNotificationBannersFunc(func() ([]codersdk.BannerConfig, error) {
|
||||
select {
|
||||
case ready <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
return test.banner, nil
|
||||
return []codersdk.BannerConfig{test.banner}, nil
|
||||
})
|
||||
<-ready
|
||||
<-ready // Wait for two updates to ensure the value has propagated.
|
||||
|
@ -2193,15 +2193,15 @@ func setupAgentSSHClient(ctx context.Context, t *testing.T) *ssh.Client {
|
|||
func setupSSHSession(
|
||||
t *testing.T,
|
||||
manifest agentsdk.Manifest,
|
||||
serviceBanner codersdk.ServiceBannerConfig,
|
||||
banner codersdk.BannerConfig,
|
||||
prepareFS func(fs afero.Fs),
|
||||
opts ...func(*agenttest.Client, *agent.Options),
|
||||
) *ssh.Session {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
opts = append(opts, func(c *agenttest.Client, o *agent.Options) {
|
||||
c.SetServiceBannerFunc(func() (codersdk.ServiceBannerConfig, error) {
|
||||
return serviceBanner, nil
|
||||
c.SetNotificationBannersFunc(func() ([]codersdk.BannerConfig, error) {
|
||||
return []codersdk.BannerConfig{banner}, nil
|
||||
})
|
||||
})
|
||||
//nolint:dogsled
|
||||
|
|
|
@ -63,7 +63,7 @@ type Config struct {
|
|||
// file will be displayed to the user upon login.
|
||||
MOTDFile func() string
|
||||
// ServiceBanner returns the configuration for the Coder service banner.
|
||||
ServiceBanner func() *codersdk.BannerConfig
|
||||
NotificationBanners func() *[]codersdk.BannerConfig
|
||||
// UpdateEnv updates the environment variables for the command to be
|
||||
// executed. It can be used to add, modify or replace environment variables.
|
||||
UpdateEnv func(current []string) (updated []string, err error)
|
||||
|
@ -123,8 +123,8 @@ func NewServer(ctx context.Context, logger slog.Logger, prometheusRegistry *prom
|
|||
if config.MOTDFile == nil {
|
||||
config.MOTDFile = func() string { return "" }
|
||||
}
|
||||
if config.ServiceBanner == nil {
|
||||
config.ServiceBanner = func() *codersdk.BannerConfig { return &codersdk.BannerConfig{} }
|
||||
if config.NotificationBanners == nil {
|
||||
config.NotificationBanners = func() *[]codersdk.BannerConfig { return &[]codersdk.BannerConfig{} }
|
||||
}
|
||||
if config.WorkingDirectory == nil {
|
||||
config.WorkingDirectory = func() string {
|
||||
|
@ -441,12 +441,15 @@ func (s *Server) startPTYSession(logger slog.Logger, session ptySession, magicTy
|
|||
session.DisablePTYEmulation()
|
||||
|
||||
if isLoginShell(session.RawCommand()) {
|
||||
serviceBanner := s.config.ServiceBanner()
|
||||
if serviceBanner != nil {
|
||||
err := showServiceBanner(session, serviceBanner)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "agent failed to show service banner", slog.Error(err))
|
||||
s.metrics.sessionErrors.WithLabelValues(magicTypeLabel, "yes", "service_banner").Add(1)
|
||||
banners := s.config.NotificationBanners()
|
||||
if banners != nil {
|
||||
for _, banner := range *banners {
|
||||
err := showNotificationBanner(session, banner)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "agent failed to show service banner", slog.Error(err))
|
||||
s.metrics.sessionErrors.WithLabelValues(magicTypeLabel, "yes", "notification_banner").Add(1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -891,9 +894,9 @@ func isQuietLogin(fs afero.Fs, rawCommand string) bool {
|
|||
return err == nil
|
||||
}
|
||||
|
||||
// showServiceBanner will write the service banner if enabled and not blank
|
||||
// showNotificationBanner will write the service banner if enabled and not blank
|
||||
// along with a blank line for spacing.
|
||||
func showServiceBanner(session io.Writer, banner *codersdk.ServiceBannerConfig) error {
|
||||
func showNotificationBanner(session io.Writer, banner codersdk.BannerConfig) error {
|
||||
if banner.Enabled && banner.Message != "" {
|
||||
// The banner supports Markdown so we might want to parse it but Markdown is
|
||||
// still fairly readable in its raw form.
|
||||
|
|
|
@ -138,8 +138,8 @@ func (c *Client) GetStartupLogs() []agentsdk.Log {
|
|||
return c.logs
|
||||
}
|
||||
|
||||
func (c *Client) SetServiceBannerFunc(f func() (codersdk.ServiceBannerConfig, error)) {
|
||||
c.fakeAgentAPI.SetServiceBannerFunc(f)
|
||||
func (c *Client) SetNotificationBannersFunc(f func() ([]codersdk.ServiceBannerConfig, error)) {
|
||||
c.fakeAgentAPI.SetNotificationBannersFunc(f)
|
||||
}
|
||||
|
||||
func (c *Client) PushDERPMapUpdate(update *tailcfg.DERPMap) error {
|
||||
|
@ -171,31 +171,39 @@ type FakeAgentAPI struct {
|
|||
lifecycleStates []codersdk.WorkspaceAgentLifecycle
|
||||
metadata map[string]agentsdk.Metadata
|
||||
|
||||
getServiceBannerFunc func() (codersdk.ServiceBannerConfig, error)
|
||||
getNotificationBannersFunc func() ([]codersdk.BannerConfig, error)
|
||||
}
|
||||
|
||||
func (f *FakeAgentAPI) GetManifest(context.Context, *agentproto.GetManifestRequest) (*agentproto.Manifest, error) {
|
||||
return f.manifest, nil
|
||||
}
|
||||
|
||||
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 (*FakeAgentAPI) GetServiceBanner(context.Context, *agentproto.GetServiceBannerRequest) (*agentproto.ServiceBanner, error) {
|
||||
return &agentproto.ServiceBanner{}, nil
|
||||
}
|
||||
|
||||
func (f *FakeAgentAPI) GetServiceBanner(context.Context, *agentproto.GetServiceBannerRequest) (*agentproto.ServiceBanner, error) {
|
||||
func (f *FakeAgentAPI) SetNotificationBannersFunc(fn func() ([]codersdk.BannerConfig, error)) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
if f.getServiceBannerFunc == nil {
|
||||
return &agentproto.ServiceBanner{}, nil
|
||||
f.getNotificationBannersFunc = fn
|
||||
f.logger.Info(context.Background(), "updated notification banners")
|
||||
}
|
||||
|
||||
func (f *FakeAgentAPI) GetNotificationBanners(context.Context, *agentproto.GetNotificationBannersRequest) (*agentproto.GetNotificationBannersResponse, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
if f.getNotificationBannersFunc == nil {
|
||||
return &agentproto.GetNotificationBannersResponse{NotificationBanners: []*agentproto.BannerConfig{}}, nil
|
||||
}
|
||||
sb, err := f.getServiceBannerFunc()
|
||||
banners, err := f.getNotificationBannersFunc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return agentsdk.ProtoFromServiceBanner(sb), nil
|
||||
bannersProto := make([]*agentproto.BannerConfig, 0, len(banners))
|
||||
for _, banner := range banners {
|
||||
bannersProto = append(bannersProto, agentsdk.ProtoFromBannerConfig(banner))
|
||||
}
|
||||
return &agentproto.GetNotificationBannersResponse{NotificationBanners: bannersProto}, nil
|
||||
}
|
||||
|
||||
func (f *FakeAgentAPI) UpdateStats(ctx context.Context, req *agentproto.UpdateStatsRequest) (*agentproto.UpdateStatsResponse, error) {
|
||||
|
|
|
@ -1859,6 +1859,154 @@ func (x *BatchCreateLogsResponse) GetLogLimitExceeded() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
type GetNotificationBannersRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *GetNotificationBannersRequest) Reset() {
|
||||
*x = GetNotificationBannersRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[22]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *GetNotificationBannersRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetNotificationBannersRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetNotificationBannersRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[22]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetNotificationBannersRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetNotificationBannersRequest) Descriptor() ([]byte, []int) {
|
||||
return file_agent_proto_agent_proto_rawDescGZIP(), []int{22}
|
||||
}
|
||||
|
||||
type GetNotificationBannersResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
NotificationBanners []*BannerConfig `protobuf:"bytes,1,rep,name=notification_banners,json=notificationBanners,proto3" json:"notification_banners,omitempty"`
|
||||
}
|
||||
|
||||
func (x *GetNotificationBannersResponse) Reset() {
|
||||
*x = GetNotificationBannersResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[23]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *GetNotificationBannersResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetNotificationBannersResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetNotificationBannersResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[23]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetNotificationBannersResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetNotificationBannersResponse) Descriptor() ([]byte, []int) {
|
||||
return file_agent_proto_agent_proto_rawDescGZIP(), []int{23}
|
||||
}
|
||||
|
||||
func (x *GetNotificationBannersResponse) GetNotificationBanners() []*BannerConfig {
|
||||
if x != nil {
|
||||
return x.NotificationBanners
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type BannerConfig struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
||||
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
|
||||
BackgroundColor string `protobuf:"bytes,3,opt,name=background_color,json=backgroundColor,proto3" json:"background_color,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BannerConfig) Reset() {
|
||||
*x = BannerConfig{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[24]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *BannerConfig) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BannerConfig) ProtoMessage() {}
|
||||
|
||||
func (x *BannerConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[24]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BannerConfig.ProtoReflect.Descriptor instead.
|
||||
func (*BannerConfig) Descriptor() ([]byte, []int) {
|
||||
return file_agent_proto_agent_proto_rawDescGZIP(), []int{24}
|
||||
}
|
||||
|
||||
func (x *BannerConfig) GetEnabled() bool {
|
||||
if x != nil {
|
||||
return x.Enabled
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *BannerConfig) GetMessage() string {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *BannerConfig) GetBackgroundColor() string {
|
||||
if x != nil {
|
||||
return x.BackgroundColor
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type WorkspaceApp_Healthcheck struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
@ -1872,7 +2020,7 @@ type WorkspaceApp_Healthcheck struct {
|
|||
func (x *WorkspaceApp_Healthcheck) Reset() {
|
||||
*x = WorkspaceApp_Healthcheck{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[22]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[25]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
@ -1885,7 +2033,7 @@ func (x *WorkspaceApp_Healthcheck) String() string {
|
|||
func (*WorkspaceApp_Healthcheck) ProtoMessage() {}
|
||||
|
||||
func (x *WorkspaceApp_Healthcheck) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[22]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[25]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -1936,7 +2084,7 @@ type WorkspaceAgentMetadata_Result struct {
|
|||
func (x *WorkspaceAgentMetadata_Result) Reset() {
|
||||
*x = WorkspaceAgentMetadata_Result{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[23]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[26]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
@ -1949,7 +2097,7 @@ func (x *WorkspaceAgentMetadata_Result) String() string {
|
|||
func (*WorkspaceAgentMetadata_Result) ProtoMessage() {}
|
||||
|
||||
func (x *WorkspaceAgentMetadata_Result) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[23]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[26]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -2008,7 +2156,7 @@ type WorkspaceAgentMetadata_Description struct {
|
|||
func (x *WorkspaceAgentMetadata_Description) Reset() {
|
||||
*x = WorkspaceAgentMetadata_Description{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[24]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[27]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
@ -2021,7 +2169,7 @@ func (x *WorkspaceAgentMetadata_Description) String() string {
|
|||
func (*WorkspaceAgentMetadata_Description) ProtoMessage() {}
|
||||
|
||||
func (x *WorkspaceAgentMetadata_Description) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[24]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[27]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -2086,7 +2234,7 @@ type Stats_Metric struct {
|
|||
func (x *Stats_Metric) Reset() {
|
||||
*x = Stats_Metric{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[27]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[30]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
@ -2099,7 +2247,7 @@ func (x *Stats_Metric) String() string {
|
|||
func (*Stats_Metric) ProtoMessage() {}
|
||||
|
||||
func (x *Stats_Metric) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[27]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[30]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -2155,7 +2303,7 @@ type Stats_Metric_Label struct {
|
|||
func (x *Stats_Metric_Label) Reset() {
|
||||
*x = Stats_Metric_Label{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[28]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[31]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
@ -2168,7 +2316,7 @@ func (x *Stats_Metric_Label) String() string {
|
|||
func (*Stats_Metric_Label) ProtoMessage() {}
|
||||
|
||||
func (x *Stats_Metric_Label) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[28]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[31]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -2210,7 +2358,7 @@ type BatchUpdateAppHealthRequest_HealthUpdate struct {
|
|||
func (x *BatchUpdateAppHealthRequest_HealthUpdate) Reset() {
|
||||
*x = BatchUpdateAppHealthRequest_HealthUpdate{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[29]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[32]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
@ -2223,7 +2371,7 @@ func (x *BatchUpdateAppHealthRequest_HealthUpdate) String() string {
|
|||
func (*BatchUpdateAppHealthRequest_HealthUpdate) ProtoMessage() {}
|
||||
|
||||
func (x *BatchUpdateAppHealthRequest_HealthUpdate) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[29]
|
||||
mi := &file_agent_proto_agent_proto_msgTypes[32]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -2594,64 +2742,87 @@ var file_agent_proto_agent_proto_rawDesc = []byte{
|
|||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x69,
|
||||
0x6d, 0x69, 0x74, 0x5f, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x10, 0x6c, 0x6f, 0x67, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x45, 0x78, 0x63, 0x65,
|
||||
0x65, 0x64, 0x65, 0x64, 0x2a, 0x63, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74,
|
||||
0x68, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x50, 0x50, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f,
|
||||
0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a,
|
||||
0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49,
|
||||
0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0b, 0x0a,
|
||||
0x07, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e,
|
||||
0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x04, 0x32, 0xf6, 0x05, 0x0a, 0x05, 0x41, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65,
|
||||
0x73, 0x74, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61,
|
||||
0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74,
|
||||
0x12, 0x5a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61,
|
||||
0x6e, 0x6e, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e,
|
||||
0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x56, 0x0a, 0x0b,
|
||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x22, 0x2e, 0x63, 0x6f,
|
||||
0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x23, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32,
|
||||
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69,
|
||||
0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e,
|
||||
0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c,
|
||||
0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x19, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32,
|
||||
0x2e, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x42, 0x61,
|
||||
0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c,
|
||||
0x74, 0x68, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e,
|
||||
0x65, 0x64, 0x65, 0x64, 0x22, 0x1f, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66,
|
||||
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x71, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69,
|
||||
0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x14, 0x6e, 0x6f, 0x74, 0x69, 0x66,
|
||||
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x18,
|
||||
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x52, 0x13, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x6d, 0x0a, 0x0c, 0x42, 0x61, 0x6e, 0x6e,
|
||||
0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62,
|
||||
0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
||||
0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x10,
|
||||
0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2a, 0x63, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x48, 0x65,
|
||||
0x61, 0x6c, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x50, 0x50, 0x5f, 0x48, 0x45, 0x41, 0x4c,
|
||||
0x54, 0x48, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
|
||||
0x12, 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x10,
|
||||
0x0a, 0x0c, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x02,
|
||||
0x12, 0x0b, 0x0a, 0x07, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x03, 0x12, 0x0d, 0x0a,
|
||||
0x09, 0x55, 0x4e, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x04, 0x32, 0xef, 0x06, 0x0a,
|
||||
0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e,
|
||||
0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65,
|
||||
0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x6f, 0x64, 0x65,
|
||||
0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66,
|
||||
0x65, 0x73, 0x74, 0x12, 0x5a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e,
|
||||
0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76,
|
||||
0x32, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12,
|
||||
0x56, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x22,
|
||||
0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e,
|
||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x23, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64,
|
||||
0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x72, 0x0a,
|
||||
0x15, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48,
|
||||
0x65, 0x61, 0x6c, 0x74, 0x68, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61,
|
||||
0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e,
|
||||
0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||
0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76,
|
||||
0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70,
|
||||
0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e,
|
||||
0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12,
|
||||
0x24, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32,
|
||||
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x6e,
|
||||
0x0a, 0x13, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74,
|
||||
0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65,
|
||||
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62,
|
||||
0x0a, 0x0f, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67,
|
||||
0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f,
|
||||
0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65,
|
||||
0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68,
|
||||
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f,
|
||||
0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74,
|
||||
0x75, 0x70, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75,
|
||||
0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72,
|
||||
0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75,
|
||||
0x70, 0x12, 0x6e, 0x0a, 0x13, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||
0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72,
|
||||
0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55,
|
||||
0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x62, 0x0a, 0x0f, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||
0x4c, 0x6f, 0x67, 0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||
0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x63,
|
||||
0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61,
|
||||
0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69,
|
||||
0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x12,
|
||||
0x2d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32,
|
||||
0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e,
|
||||
0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e,
|
||||
0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42,
|
||||
0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27,
|
||||
0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64,
|
||||
0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x67, 0x65, 0x6e,
|
||||
0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -2667,7 +2838,7 @@ func file_agent_proto_agent_proto_rawDescGZIP() []byte {
|
|||
}
|
||||
|
||||
var file_agent_proto_agent_proto_enumTypes = make([]protoimpl.EnumInfo, 7)
|
||||
var file_agent_proto_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 30)
|
||||
var file_agent_proto_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 33)
|
||||
var file_agent_proto_agent_proto_goTypes = []interface{}{
|
||||
(AppHealth)(0), // 0: coder.agent.v2.AppHealth
|
||||
(WorkspaceApp_SharingLevel)(0), // 1: coder.agent.v2.WorkspaceApp.SharingLevel
|
||||
|
@ -2698,73 +2869,79 @@ var file_agent_proto_agent_proto_goTypes = []interface{}{
|
|||
(*Log)(nil), // 26: coder.agent.v2.Log
|
||||
(*BatchCreateLogsRequest)(nil), // 27: coder.agent.v2.BatchCreateLogsRequest
|
||||
(*BatchCreateLogsResponse)(nil), // 28: coder.agent.v2.BatchCreateLogsResponse
|
||||
(*WorkspaceApp_Healthcheck)(nil), // 29: coder.agent.v2.WorkspaceApp.Healthcheck
|
||||
(*WorkspaceAgentMetadata_Result)(nil), // 30: coder.agent.v2.WorkspaceAgentMetadata.Result
|
||||
(*WorkspaceAgentMetadata_Description)(nil), // 31: coder.agent.v2.WorkspaceAgentMetadata.Description
|
||||
nil, // 32: coder.agent.v2.Manifest.EnvironmentVariablesEntry
|
||||
nil, // 33: coder.agent.v2.Stats.ConnectionsByProtoEntry
|
||||
(*Stats_Metric)(nil), // 34: coder.agent.v2.Stats.Metric
|
||||
(*Stats_Metric_Label)(nil), // 35: coder.agent.v2.Stats.Metric.Label
|
||||
(*BatchUpdateAppHealthRequest_HealthUpdate)(nil), // 36: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate
|
||||
(*durationpb.Duration)(nil), // 37: google.protobuf.Duration
|
||||
(*proto.DERPMap)(nil), // 38: coder.tailnet.v2.DERPMap
|
||||
(*timestamppb.Timestamp)(nil), // 39: google.protobuf.Timestamp
|
||||
(*GetNotificationBannersRequest)(nil), // 29: coder.agent.v2.GetNotificationBannersRequest
|
||||
(*GetNotificationBannersResponse)(nil), // 30: coder.agent.v2.GetNotificationBannersResponse
|
||||
(*BannerConfig)(nil), // 31: coder.agent.v2.BannerConfig
|
||||
(*WorkspaceApp_Healthcheck)(nil), // 32: coder.agent.v2.WorkspaceApp.Healthcheck
|
||||
(*WorkspaceAgentMetadata_Result)(nil), // 33: coder.agent.v2.WorkspaceAgentMetadata.Result
|
||||
(*WorkspaceAgentMetadata_Description)(nil), // 34: coder.agent.v2.WorkspaceAgentMetadata.Description
|
||||
nil, // 35: coder.agent.v2.Manifest.EnvironmentVariablesEntry
|
||||
nil, // 36: coder.agent.v2.Stats.ConnectionsByProtoEntry
|
||||
(*Stats_Metric)(nil), // 37: coder.agent.v2.Stats.Metric
|
||||
(*Stats_Metric_Label)(nil), // 38: coder.agent.v2.Stats.Metric.Label
|
||||
(*BatchUpdateAppHealthRequest_HealthUpdate)(nil), // 39: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate
|
||||
(*durationpb.Duration)(nil), // 40: google.protobuf.Duration
|
||||
(*proto.DERPMap)(nil), // 41: coder.tailnet.v2.DERPMap
|
||||
(*timestamppb.Timestamp)(nil), // 42: google.protobuf.Timestamp
|
||||
}
|
||||
var file_agent_proto_agent_proto_depIdxs = []int32{
|
||||
1, // 0: coder.agent.v2.WorkspaceApp.sharing_level:type_name -> coder.agent.v2.WorkspaceApp.SharingLevel
|
||||
29, // 1: coder.agent.v2.WorkspaceApp.healthcheck:type_name -> coder.agent.v2.WorkspaceApp.Healthcheck
|
||||
32, // 1: coder.agent.v2.WorkspaceApp.healthcheck:type_name -> coder.agent.v2.WorkspaceApp.Healthcheck
|
||||
2, // 2: coder.agent.v2.WorkspaceApp.health:type_name -> coder.agent.v2.WorkspaceApp.Health
|
||||
37, // 3: coder.agent.v2.WorkspaceAgentScript.timeout:type_name -> google.protobuf.Duration
|
||||
30, // 4: coder.agent.v2.WorkspaceAgentMetadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result
|
||||
31, // 5: coder.agent.v2.WorkspaceAgentMetadata.description:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description
|
||||
32, // 6: coder.agent.v2.Manifest.environment_variables:type_name -> coder.agent.v2.Manifest.EnvironmentVariablesEntry
|
||||
38, // 7: coder.agent.v2.Manifest.derp_map:type_name -> coder.tailnet.v2.DERPMap
|
||||
40, // 3: coder.agent.v2.WorkspaceAgentScript.timeout:type_name -> google.protobuf.Duration
|
||||
33, // 4: coder.agent.v2.WorkspaceAgentMetadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result
|
||||
34, // 5: coder.agent.v2.WorkspaceAgentMetadata.description:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description
|
||||
35, // 6: coder.agent.v2.Manifest.environment_variables:type_name -> coder.agent.v2.Manifest.EnvironmentVariablesEntry
|
||||
41, // 7: coder.agent.v2.Manifest.derp_map:type_name -> coder.tailnet.v2.DERPMap
|
||||
8, // 8: coder.agent.v2.Manifest.scripts:type_name -> coder.agent.v2.WorkspaceAgentScript
|
||||
7, // 9: coder.agent.v2.Manifest.apps:type_name -> coder.agent.v2.WorkspaceApp
|
||||
31, // 10: coder.agent.v2.Manifest.metadata:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description
|
||||
33, // 11: coder.agent.v2.Stats.connections_by_proto:type_name -> coder.agent.v2.Stats.ConnectionsByProtoEntry
|
||||
34, // 12: coder.agent.v2.Stats.metrics:type_name -> coder.agent.v2.Stats.Metric
|
||||
34, // 10: coder.agent.v2.Manifest.metadata:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description
|
||||
36, // 11: coder.agent.v2.Stats.connections_by_proto:type_name -> coder.agent.v2.Stats.ConnectionsByProtoEntry
|
||||
37, // 12: coder.agent.v2.Stats.metrics:type_name -> coder.agent.v2.Stats.Metric
|
||||
14, // 13: coder.agent.v2.UpdateStatsRequest.stats:type_name -> coder.agent.v2.Stats
|
||||
37, // 14: coder.agent.v2.UpdateStatsResponse.report_interval:type_name -> google.protobuf.Duration
|
||||
40, // 14: coder.agent.v2.UpdateStatsResponse.report_interval:type_name -> google.protobuf.Duration
|
||||
4, // 15: coder.agent.v2.Lifecycle.state:type_name -> coder.agent.v2.Lifecycle.State
|
||||
39, // 16: coder.agent.v2.Lifecycle.changed_at:type_name -> google.protobuf.Timestamp
|
||||
42, // 16: coder.agent.v2.Lifecycle.changed_at:type_name -> google.protobuf.Timestamp
|
||||
17, // 17: coder.agent.v2.UpdateLifecycleRequest.lifecycle:type_name -> coder.agent.v2.Lifecycle
|
||||
36, // 18: coder.agent.v2.BatchUpdateAppHealthRequest.updates:type_name -> coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate
|
||||
39, // 18: coder.agent.v2.BatchUpdateAppHealthRequest.updates:type_name -> coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate
|
||||
5, // 19: coder.agent.v2.Startup.subsystems:type_name -> coder.agent.v2.Startup.Subsystem
|
||||
21, // 20: coder.agent.v2.UpdateStartupRequest.startup:type_name -> coder.agent.v2.Startup
|
||||
30, // 21: coder.agent.v2.Metadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result
|
||||
33, // 21: coder.agent.v2.Metadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result
|
||||
23, // 22: coder.agent.v2.BatchUpdateMetadataRequest.metadata:type_name -> coder.agent.v2.Metadata
|
||||
39, // 23: coder.agent.v2.Log.created_at:type_name -> google.protobuf.Timestamp
|
||||
42, // 23: coder.agent.v2.Log.created_at:type_name -> google.protobuf.Timestamp
|
||||
6, // 24: coder.agent.v2.Log.level:type_name -> coder.agent.v2.Log.Level
|
||||
26, // 25: coder.agent.v2.BatchCreateLogsRequest.logs:type_name -> coder.agent.v2.Log
|
||||
37, // 26: coder.agent.v2.WorkspaceApp.Healthcheck.interval:type_name -> google.protobuf.Duration
|
||||
39, // 27: coder.agent.v2.WorkspaceAgentMetadata.Result.collected_at:type_name -> google.protobuf.Timestamp
|
||||
37, // 28: coder.agent.v2.WorkspaceAgentMetadata.Description.interval:type_name -> google.protobuf.Duration
|
||||
37, // 29: coder.agent.v2.WorkspaceAgentMetadata.Description.timeout:type_name -> google.protobuf.Duration
|
||||
3, // 30: coder.agent.v2.Stats.Metric.type:type_name -> coder.agent.v2.Stats.Metric.Type
|
||||
35, // 31: coder.agent.v2.Stats.Metric.labels:type_name -> coder.agent.v2.Stats.Metric.Label
|
||||
0, // 32: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate.health:type_name -> coder.agent.v2.AppHealth
|
||||
11, // 33: coder.agent.v2.Agent.GetManifest:input_type -> coder.agent.v2.GetManifestRequest
|
||||
13, // 34: coder.agent.v2.Agent.GetServiceBanner:input_type -> coder.agent.v2.GetServiceBannerRequest
|
||||
15, // 35: coder.agent.v2.Agent.UpdateStats:input_type -> coder.agent.v2.UpdateStatsRequest
|
||||
18, // 36: coder.agent.v2.Agent.UpdateLifecycle:input_type -> coder.agent.v2.UpdateLifecycleRequest
|
||||
19, // 37: coder.agent.v2.Agent.BatchUpdateAppHealths:input_type -> coder.agent.v2.BatchUpdateAppHealthRequest
|
||||
22, // 38: coder.agent.v2.Agent.UpdateStartup:input_type -> coder.agent.v2.UpdateStartupRequest
|
||||
24, // 39: coder.agent.v2.Agent.BatchUpdateMetadata:input_type -> coder.agent.v2.BatchUpdateMetadataRequest
|
||||
27, // 40: coder.agent.v2.Agent.BatchCreateLogs:input_type -> coder.agent.v2.BatchCreateLogsRequest
|
||||
10, // 41: coder.agent.v2.Agent.GetManifest:output_type -> coder.agent.v2.Manifest
|
||||
12, // 42: coder.agent.v2.Agent.GetServiceBanner:output_type -> coder.agent.v2.ServiceBanner
|
||||
16, // 43: coder.agent.v2.Agent.UpdateStats:output_type -> coder.agent.v2.UpdateStatsResponse
|
||||
17, // 44: coder.agent.v2.Agent.UpdateLifecycle:output_type -> coder.agent.v2.Lifecycle
|
||||
20, // 45: coder.agent.v2.Agent.BatchUpdateAppHealths:output_type -> coder.agent.v2.BatchUpdateAppHealthResponse
|
||||
21, // 46: coder.agent.v2.Agent.UpdateStartup:output_type -> coder.agent.v2.Startup
|
||||
25, // 47: coder.agent.v2.Agent.BatchUpdateMetadata:output_type -> coder.agent.v2.BatchUpdateMetadataResponse
|
||||
28, // 48: coder.agent.v2.Agent.BatchCreateLogs:output_type -> coder.agent.v2.BatchCreateLogsResponse
|
||||
41, // [41:49] is the sub-list for method output_type
|
||||
33, // [33:41] is the sub-list for method input_type
|
||||
33, // [33:33] is the sub-list for extension type_name
|
||||
33, // [33:33] is the sub-list for extension extendee
|
||||
0, // [0:33] is the sub-list for field type_name
|
||||
31, // 26: coder.agent.v2.GetNotificationBannersResponse.notification_banners:type_name -> coder.agent.v2.BannerConfig
|
||||
40, // 27: coder.agent.v2.WorkspaceApp.Healthcheck.interval:type_name -> google.protobuf.Duration
|
||||
42, // 28: coder.agent.v2.WorkspaceAgentMetadata.Result.collected_at:type_name -> google.protobuf.Timestamp
|
||||
40, // 29: coder.agent.v2.WorkspaceAgentMetadata.Description.interval:type_name -> google.protobuf.Duration
|
||||
40, // 30: coder.agent.v2.WorkspaceAgentMetadata.Description.timeout:type_name -> google.protobuf.Duration
|
||||
3, // 31: coder.agent.v2.Stats.Metric.type:type_name -> coder.agent.v2.Stats.Metric.Type
|
||||
38, // 32: coder.agent.v2.Stats.Metric.labels:type_name -> coder.agent.v2.Stats.Metric.Label
|
||||
0, // 33: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate.health:type_name -> coder.agent.v2.AppHealth
|
||||
11, // 34: coder.agent.v2.Agent.GetManifest:input_type -> coder.agent.v2.GetManifestRequest
|
||||
13, // 35: coder.agent.v2.Agent.GetServiceBanner:input_type -> coder.agent.v2.GetServiceBannerRequest
|
||||
15, // 36: coder.agent.v2.Agent.UpdateStats:input_type -> coder.agent.v2.UpdateStatsRequest
|
||||
18, // 37: coder.agent.v2.Agent.UpdateLifecycle:input_type -> coder.agent.v2.UpdateLifecycleRequest
|
||||
19, // 38: coder.agent.v2.Agent.BatchUpdateAppHealths:input_type -> coder.agent.v2.BatchUpdateAppHealthRequest
|
||||
22, // 39: coder.agent.v2.Agent.UpdateStartup:input_type -> coder.agent.v2.UpdateStartupRequest
|
||||
24, // 40: coder.agent.v2.Agent.BatchUpdateMetadata:input_type -> coder.agent.v2.BatchUpdateMetadataRequest
|
||||
27, // 41: coder.agent.v2.Agent.BatchCreateLogs:input_type -> coder.agent.v2.BatchCreateLogsRequest
|
||||
29, // 42: coder.agent.v2.Agent.GetNotificationBanners:input_type -> coder.agent.v2.GetNotificationBannersRequest
|
||||
10, // 43: coder.agent.v2.Agent.GetManifest:output_type -> coder.agent.v2.Manifest
|
||||
12, // 44: coder.agent.v2.Agent.GetServiceBanner:output_type -> coder.agent.v2.ServiceBanner
|
||||
16, // 45: coder.agent.v2.Agent.UpdateStats:output_type -> coder.agent.v2.UpdateStatsResponse
|
||||
17, // 46: coder.agent.v2.Agent.UpdateLifecycle:output_type -> coder.agent.v2.Lifecycle
|
||||
20, // 47: coder.agent.v2.Agent.BatchUpdateAppHealths:output_type -> coder.agent.v2.BatchUpdateAppHealthResponse
|
||||
21, // 48: coder.agent.v2.Agent.UpdateStartup:output_type -> coder.agent.v2.Startup
|
||||
25, // 49: coder.agent.v2.Agent.BatchUpdateMetadata:output_type -> coder.agent.v2.BatchUpdateMetadataResponse
|
||||
28, // 50: coder.agent.v2.Agent.BatchCreateLogs:output_type -> coder.agent.v2.BatchCreateLogsResponse
|
||||
30, // 51: coder.agent.v2.Agent.GetNotificationBanners:output_type -> coder.agent.v2.GetNotificationBannersResponse
|
||||
43, // [43:52] is the sub-list for method output_type
|
||||
34, // [34:43] is the sub-list for method input_type
|
||||
34, // [34:34] is the sub-list for extension type_name
|
||||
34, // [34:34] is the sub-list for extension extendee
|
||||
0, // [0:34] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_agent_proto_agent_proto_init() }
|
||||
|
@ -3038,7 +3215,7 @@ func file_agent_proto_agent_proto_init() {
|
|||
}
|
||||
}
|
||||
file_agent_proto_agent_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WorkspaceApp_Healthcheck); i {
|
||||
switch v := v.(*GetNotificationBannersRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
|
@ -3050,7 +3227,7 @@ func file_agent_proto_agent_proto_init() {
|
|||
}
|
||||
}
|
||||
file_agent_proto_agent_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WorkspaceAgentMetadata_Result); i {
|
||||
switch v := v.(*GetNotificationBannersResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
|
@ -3062,7 +3239,31 @@ func file_agent_proto_agent_proto_init() {
|
|||
}
|
||||
}
|
||||
file_agent_proto_agent_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WorkspaceAgentMetadata_Description); i {
|
||||
switch v := v.(*BannerConfig); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_agent_proto_agent_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WorkspaceApp_Healthcheck); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_agent_proto_agent_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WorkspaceAgentMetadata_Result); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
|
@ -3074,6 +3275,18 @@ func file_agent_proto_agent_proto_init() {
|
|||
}
|
||||
}
|
||||
file_agent_proto_agent_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WorkspaceAgentMetadata_Description); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_agent_proto_agent_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Stats_Metric); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -3085,7 +3298,7 @@ func file_agent_proto_agent_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_agent_proto_agent_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
|
||||
file_agent_proto_agent_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Stats_Metric_Label); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -3097,7 +3310,7 @@ func file_agent_proto_agent_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_agent_proto_agent_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} {
|
||||
file_agent_proto_agent_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*BatchUpdateAppHealthRequest_HealthUpdate); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -3116,7 +3329,7 @@ func file_agent_proto_agent_proto_init() {
|
|||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_agent_proto_agent_proto_rawDesc,
|
||||
NumEnums: 7,
|
||||
NumMessages: 30,
|
||||
NumMessages: 33,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
|
|
@ -251,6 +251,18 @@ message BatchCreateLogsResponse {
|
|||
bool log_limit_exceeded = 1;
|
||||
}
|
||||
|
||||
message GetNotificationBannersRequest {}
|
||||
|
||||
message GetNotificationBannersResponse {
|
||||
repeated BannerConfig notification_banners = 1;
|
||||
}
|
||||
|
||||
message BannerConfig {
|
||||
bool enabled = 1;
|
||||
string message = 2;
|
||||
string background_color = 3;
|
||||
}
|
||||
|
||||
service Agent {
|
||||
rpc GetManifest(GetManifestRequest) returns (Manifest);
|
||||
rpc GetServiceBanner(GetServiceBannerRequest) returns (ServiceBanner);
|
||||
|
@ -260,4 +272,5 @@ service Agent {
|
|||
rpc UpdateStartup(UpdateStartupRequest) returns (Startup);
|
||||
rpc BatchUpdateMetadata(BatchUpdateMetadataRequest) returns (BatchUpdateMetadataResponse);
|
||||
rpc BatchCreateLogs(BatchCreateLogsRequest) returns (BatchCreateLogsResponse);
|
||||
rpc GetNotificationBanners(GetNotificationBannersRequest) returns (GetNotificationBannersResponse);
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ type DRPCAgentClient interface {
|
|||
UpdateStartup(ctx context.Context, in *UpdateStartupRequest) (*Startup, error)
|
||||
BatchUpdateMetadata(ctx context.Context, in *BatchUpdateMetadataRequest) (*BatchUpdateMetadataResponse, error)
|
||||
BatchCreateLogs(ctx context.Context, in *BatchCreateLogsRequest) (*BatchCreateLogsResponse, error)
|
||||
GetNotificationBanners(ctx context.Context, in *GetNotificationBannersRequest) (*GetNotificationBannersResponse, error)
|
||||
}
|
||||
|
||||
type drpcAgentClient struct {
|
||||
|
@ -130,6 +131,15 @@ func (c *drpcAgentClient) BatchCreateLogs(ctx context.Context, in *BatchCreateLo
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *drpcAgentClient) GetNotificationBanners(ctx context.Context, in *GetNotificationBannersRequest) (*GetNotificationBannersResponse, error) {
|
||||
out := new(GetNotificationBannersResponse)
|
||||
err := c.cc.Invoke(ctx, "/coder.agent.v2.Agent/GetNotificationBanners", drpcEncoding_File_agent_proto_agent_proto{}, in, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type DRPCAgentServer interface {
|
||||
GetManifest(context.Context, *GetManifestRequest) (*Manifest, error)
|
||||
GetServiceBanner(context.Context, *GetServiceBannerRequest) (*ServiceBanner, error)
|
||||
|
@ -139,6 +149,7 @@ type DRPCAgentServer interface {
|
|||
UpdateStartup(context.Context, *UpdateStartupRequest) (*Startup, error)
|
||||
BatchUpdateMetadata(context.Context, *BatchUpdateMetadataRequest) (*BatchUpdateMetadataResponse, error)
|
||||
BatchCreateLogs(context.Context, *BatchCreateLogsRequest) (*BatchCreateLogsResponse, error)
|
||||
GetNotificationBanners(context.Context, *GetNotificationBannersRequest) (*GetNotificationBannersResponse, error)
|
||||
}
|
||||
|
||||
type DRPCAgentUnimplementedServer struct{}
|
||||
|
@ -175,9 +186,13 @@ func (s *DRPCAgentUnimplementedServer) BatchCreateLogs(context.Context, *BatchCr
|
|||
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
func (s *DRPCAgentUnimplementedServer) GetNotificationBanners(context.Context, *GetNotificationBannersRequest) (*GetNotificationBannersResponse, error) {
|
||||
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
type DRPCAgentDescription struct{}
|
||||
|
||||
func (DRPCAgentDescription) NumMethods() int { return 8 }
|
||||
func (DRPCAgentDescription) NumMethods() int { return 9 }
|
||||
|
||||
func (DRPCAgentDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
|
||||
switch n {
|
||||
|
@ -253,6 +268,15 @@ func (DRPCAgentDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver,
|
|||
in1.(*BatchCreateLogsRequest),
|
||||
)
|
||||
}, DRPCAgentServer.BatchCreateLogs, true
|
||||
case 8:
|
||||
return "/coder.agent.v2.Agent/GetNotificationBanners", drpcEncoding_File_agent_proto_agent_proto{},
|
||||
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
|
||||
return srv.(DRPCAgentServer).
|
||||
GetNotificationBanners(
|
||||
ctx,
|
||||
in1.(*GetNotificationBannersRequest),
|
||||
)
|
||||
}, DRPCAgentServer.GetNotificationBanners, true
|
||||
default:
|
||||
return "", nil, nil, nil, false
|
||||
}
|
||||
|
@ -389,3 +413,19 @@ func (x *drpcAgent_BatchCreateLogsStream) SendAndClose(m *BatchCreateLogsRespons
|
|||
}
|
||||
return x.CloseSend()
|
||||
}
|
||||
|
||||
type DRPCAgent_GetNotificationBannersStream interface {
|
||||
drpc.Stream
|
||||
SendAndClose(*GetNotificationBannersResponse) error
|
||||
}
|
||||
|
||||
type drpcAgent_GetNotificationBannersStream struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcAgent_GetNotificationBannersStream) SendAndClose(m *GetNotificationBannersResponse) error {
|
||||
if err := x.MsgSend(m, drpcEncoding_File_agent_proto_agent_proto{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return x.CloseSend()
|
||||
}
|
||||
|
|
|
@ -287,7 +287,8 @@ func (r *RootCmd) login() *serpent.Command {
|
|||
}
|
||||
|
||||
sessionToken, err = cliui.Prompt(inv, cliui.PromptOptions{
|
||||
Text: "Paste your token here:",
|
||||
Text: "Paste your token here:",
|
||||
Secret: true,
|
||||
Validate: func(token string) error {
|
||||
client.SetSessionToken(token)
|
||||
_, err := client.User(ctx, codersdk.Me)
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
@ -79,6 +80,10 @@ func (r *RootCmd) ssh() *serpent.Command {
|
|||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
// Prevent unnecessary logs from the stdlib from messing up the TTY.
|
||||
// See: https://github.com/coder/coder/issues/13144
|
||||
log.SetOutput(io.Discard)
|
||||
|
||||
logger := inv.Logger
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
|
|
|
@ -35,7 +35,7 @@ import (
|
|||
type API struct {
|
||||
opts Options
|
||||
*ManifestAPI
|
||||
*ServiceBannerAPI
|
||||
*NotificationBannerAPI
|
||||
*StatsAPI
|
||||
*LifecycleAPI
|
||||
*AppsAPI
|
||||
|
@ -107,7 +107,7 @@ func New(opts Options) *API {
|
|||
},
|
||||
}
|
||||
|
||||
api.ServiceBannerAPI = &ServiceBannerAPI{
|
||||
api.NotificationBannerAPI = &NotificationBannerAPI{
|
||||
appearanceFetcher: opts.AppearanceFetcher,
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package agentapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/v2/agent/proto"
|
||||
"github.com/coder/coder/v2/coderd/appearance"
|
||||
"github.com/coder/coder/v2/codersdk/agentsdk"
|
||||
)
|
||||
|
||||
type NotificationBannerAPI struct {
|
||||
appearanceFetcher *atomic.Pointer[appearance.Fetcher]
|
||||
}
|
||||
|
||||
// Deprecated: GetServiceBanner has been deprecated in favor of GetNotificationBanners.
|
||||
func (a *NotificationBannerAPI) GetServiceBanner(ctx context.Context, _ *proto.GetServiceBannerRequest) (*proto.ServiceBanner, error) {
|
||||
cfg, err := (*a.appearanceFetcher.Load()).Fetch(ctx)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("fetch appearance: %w", err)
|
||||
}
|
||||
if cfg.NotificationBanners == nil || len(cfg.NotificationBanners) == 0 {
|
||||
return &proto.ServiceBanner{}, nil
|
||||
}
|
||||
return agentsdk.ProtoFromServiceBanner(cfg.NotificationBanners[0]), nil
|
||||
}
|
||||
|
||||
func (a *NotificationBannerAPI) GetNotificationBanners(ctx context.Context, _ *proto.GetNotificationBannersRequest) (*proto.GetNotificationBannersResponse, error) {
|
||||
cfg, err := (*a.appearanceFetcher.Load()).Fetch(ctx)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("fetch appearance: %w", err)
|
||||
}
|
||||
banners := make([]*proto.BannerConfig, 0, len(cfg.NotificationBanners))
|
||||
for _, banner := range cfg.NotificationBanners {
|
||||
banners = append(banners, agentsdk.ProtoFromBannerConfig(banner))
|
||||
}
|
||||
return &proto.GetNotificationBannersResponse{
|
||||
NotificationBanners: banners,
|
||||
}, nil
|
||||
}
|
|
@ -11,36 +11,30 @@ import (
|
|||
agentproto "github.com/coder/coder/v2/agent/proto"
|
||||
"github.com/coder/coder/v2/coderd/appearance"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/codersdk/agentsdk"
|
||||
)
|
||||
|
||||
func TestGetServiceBanner(t *testing.T) {
|
||||
func TestGetNotificationBanners(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := codersdk.ServiceBannerConfig{
|
||||
cfg := []codersdk.BannerConfig{{
|
||||
Enabled: true,
|
||||
Message: "hello world",
|
||||
BackgroundColor: "#000000",
|
||||
}
|
||||
Message: "The beep-bop will be boop-beeped on Saturday at 12AM PST.",
|
||||
BackgroundColor: "#00FF00",
|
||||
}}
|
||||
|
||||
var ff appearance.Fetcher = fakeFetcher{cfg: codersdk.AppearanceConfig{ServiceBanner: cfg}}
|
||||
var ff appearance.Fetcher = fakeFetcher{cfg: codersdk.AppearanceConfig{NotificationBanners: cfg}}
|
||||
ptr := atomic.Pointer[appearance.Fetcher]{}
|
||||
ptr.Store(&ff)
|
||||
|
||||
api := &ServiceBannerAPI{
|
||||
appearanceFetcher: &ptr,
|
||||
}
|
||||
|
||||
resp, err := api.GetServiceBanner(context.Background(), &agentproto.GetServiceBannerRequest{})
|
||||
api := &NotificationBannerAPI{appearanceFetcher: &ptr}
|
||||
resp, err := api.GetNotificationBanners(context.Background(), &agentproto.GetNotificationBannersRequest{})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, &agentproto.ServiceBanner{
|
||||
Enabled: cfg.Enabled,
|
||||
Message: cfg.Message,
|
||||
BackgroundColor: cfg.BackgroundColor,
|
||||
}, resp)
|
||||
require.Len(t, resp.NotificationBanners, 1)
|
||||
require.Equal(t, cfg[0], agentsdk.BannerConfigFromProto(resp.NotificationBanners[0]))
|
||||
})
|
||||
|
||||
t.Run("FetchError", func(t *testing.T) {
|
||||
|
@ -51,11 +45,8 @@ func TestGetServiceBanner(t *testing.T) {
|
|||
ptr := atomic.Pointer[appearance.Fetcher]{}
|
||||
ptr.Store(&ff)
|
||||
|
||||
api := &ServiceBannerAPI{
|
||||
appearanceFetcher: &ptr,
|
||||
}
|
||||
|
||||
resp, err := api.GetServiceBanner(context.Background(), &agentproto.GetServiceBannerRequest{})
|
||||
api := &NotificationBannerAPI{appearanceFetcher: &ptr}
|
||||
resp, err := api.GetNotificationBanners(context.Background(), &agentproto.GetNotificationBannersRequest{})
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, expectedErr)
|
||||
require.Nil(t, resp)
|
|
@ -1,24 +0,0 @@
|
|||
package agentapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/v2/agent/proto"
|
||||
"github.com/coder/coder/v2/coderd/appearance"
|
||||
"github.com/coder/coder/v2/codersdk/agentsdk"
|
||||
)
|
||||
|
||||
type ServiceBannerAPI struct {
|
||||
appearanceFetcher *atomic.Pointer[appearance.Fetcher]
|
||||
}
|
||||
|
||||
func (a *ServiceBannerAPI) GetServiceBanner(ctx context.Context, _ *proto.GetServiceBannerRequest) (*proto.ServiceBanner, error) {
|
||||
cfg, err := (*a.appearanceFetcher.Load()).Fetch(ctx)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("fetch appearance: %w", err)
|
||||
}
|
||||
return agentsdk.ProtoFromServiceBanner(cfg.XServiceBanner), nil
|
||||
}
|
|
@ -525,9 +525,6 @@ func (s *MethodTestSuite) TestLicense() {
|
|||
s.Run("UpsertLogoURL", s.Subtest(func(db database.Store, check *expects) {
|
||||
check.Args("value").Asserts(rbac.ResourceDeploymentValues, rbac.ActionCreate)
|
||||
}))
|
||||
s.Run("UpsertServiceBanner", s.Subtest(func(db database.Store, check *expects) {
|
||||
check.Args("value").Asserts(rbac.ResourceDeploymentValues, rbac.ActionCreate)
|
||||
}))
|
||||
s.Run("UpsertNotificationBanners", s.Subtest(func(db database.Store, check *expects) {
|
||||
check.Args("value").Asserts(rbac.ResourceDeploymentValues, rbac.ActionCreate)
|
||||
}))
|
||||
|
@ -559,11 +556,6 @@ func (s *MethodTestSuite) TestLicense() {
|
|||
require.NoError(s.T(), err)
|
||||
check.Args().Asserts().Returns("value")
|
||||
}))
|
||||
s.Run("GetServiceBanner", s.Subtest(func(db database.Store, check *expects) {
|
||||
err := db.UpsertServiceBanner(context.Background(), "value")
|
||||
require.NoError(s.T(), err)
|
||||
check.Args().Asserts().Returns("value")
|
||||
}))
|
||||
s.Run("GetNotificationBanners", s.Subtest(func(db database.Store, check *expects) {
|
||||
err := db.UpsertNotificationBanners(context.Background(), "value")
|
||||
require.NoError(s.T(), err)
|
||||
|
|
|
@ -36,6 +36,10 @@ var skipMethods = map[string]string{
|
|||
"Wrappers": "Not relevant",
|
||||
"AcquireLock": "Not relevant",
|
||||
"TryAcquireLock": "Not relevant",
|
||||
|
||||
// These queries can probably be removed.
|
||||
"GetServiceBanner": "Deprecated, not implemented in dbmem",
|
||||
"UpsertServiceBanner": "Deprecated, not implemented in dbmem",
|
||||
}
|
||||
|
||||
// TestMethodTestSuite runs MethodTestSuite.
|
||||
|
|
|
@ -185,7 +185,6 @@ type data struct {
|
|||
deploymentID string
|
||||
derpMeshKey string
|
||||
lastUpdateCheck []byte
|
||||
serviceBanner []byte
|
||||
notificationBanners []byte
|
||||
healthSettings []byte
|
||||
applicationName string
|
||||
|
@ -3043,11 +3042,7 @@ func (q *FakeQuerier) GetServiceBanner(_ context.Context) (string, error) {
|
|||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
if q.serviceBanner == nil {
|
||||
return "", sql.ErrNoRows
|
||||
}
|
||||
|
||||
return string(q.serviceBanner), nil
|
||||
return "", sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (*FakeQuerier) GetTailnetAgents(context.Context, uuid.UUID) ([]database.TailnetAgent, error) {
|
||||
|
@ -8318,12 +8313,8 @@ func (q *FakeQuerier) UpsertProvisionerDaemon(_ context.Context, arg database.Up
|
|||
return d, nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) UpsertServiceBanner(_ context.Context, data string) error {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
q.serviceBanner = []byte(data)
|
||||
return nil
|
||||
func (*FakeQuerier) UpsertServiceBanner(_ context.Context, _ string) error {
|
||||
return ErrUnimplemented
|
||||
}
|
||||
|
||||
func (*FakeQuerier) UpsertTailnetAgent(context.Context, database.UpsertTailnetAgentParams) (database.TailnetAgent, error) {
|
||||
|
|
|
@ -293,6 +293,22 @@ func ProtoFromServiceBanner(sb codersdk.BannerConfig) *proto.ServiceBanner {
|
|||
}
|
||||
}
|
||||
|
||||
func BannerConfigFromProto(sbp *proto.BannerConfig) codersdk.BannerConfig {
|
||||
return codersdk.BannerConfig{
|
||||
Enabled: sbp.GetEnabled(),
|
||||
Message: sbp.GetMessage(),
|
||||
BackgroundColor: sbp.GetBackgroundColor(),
|
||||
}
|
||||
}
|
||||
|
||||
func ProtoFromBannerConfig(sb codersdk.BannerConfig) *proto.BannerConfig {
|
||||
return &proto.BannerConfig{
|
||||
Enabled: sb.Enabled,
|
||||
Message: sb.Message,
|
||||
BackgroundColor: sb.BackgroundColor,
|
||||
}
|
||||
}
|
||||
|
||||
func ProtoFromSubsystems(ss []codersdk.AgentSubsystem) ([]proto.Startup_Subsystem, error) {
|
||||
ret := make([]proto.Startup_Subsystem, len(ss))
|
||||
for i, s := range ss {
|
||||
|
|
|
@ -2103,7 +2103,7 @@ type AppearanceConfig struct {
|
|||
ApplicationName string `json:"application_name"`
|
||||
LogoURL string `json:"logo_url"`
|
||||
// Deprecated: ServiceBanner is for a single banner, and has been replaced by NotificationBanners.
|
||||
XServiceBanner BannerConfig `json:"service_banner"`
|
||||
ServiceBanner BannerConfig `json:"service_banner"`
|
||||
NotificationBanners []BannerConfig `json:"notification_banners"`
|
||||
SupportLinks []LinkConfig `json:"support_links,omitempty"`
|
||||
}
|
||||
|
@ -2112,7 +2112,7 @@ type UpdateAppearanceConfig struct {
|
|||
ApplicationName string `json:"application_name"`
|
||||
LogoURL string `json:"logo_url"`
|
||||
// Deprecated: ServiceBanner is for a single banner, and has been replaced by NotificationBanners.
|
||||
XServiceBanner BannerConfig `json:"service_banner"`
|
||||
ServiceBanner BannerConfig `json:"service_banner"`
|
||||
NotificationBanners []BannerConfig `json:"notification_banners"`
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/v2/agent/proto"
|
||||
|
@ -56,7 +55,7 @@ func TestCustomLogoAndCompanyName(t *testing.T) {
|
|||
require.Equal(t, uac.LogoURL, got.LogoURL)
|
||||
}
|
||||
|
||||
func TestServiceBanners(t *testing.T) {
|
||||
func TestNotificationBanners(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("User", func(t *testing.T) {
|
||||
|
@ -68,10 +67,10 @@ func TestServiceBanners(t *testing.T) {
|
|||
adminClient, adminUser := coderdenttest.New(t, &coderdenttest.Options{DontAddLicense: true})
|
||||
basicUserClient, _ := coderdtest.CreateAnotherUser(t, adminClient, adminUser.OrganizationID)
|
||||
|
||||
// Even without a license, the banner should return as disabled.
|
||||
// Without a license, there should be no banners.
|
||||
sb, err := basicUserClient.Appearance(ctx)
|
||||
require.NoError(t, err)
|
||||
require.False(t, sb.ServiceBanner.Enabled)
|
||||
require.Empty(t, sb.NotificationBanners)
|
||||
|
||||
coderdenttest.AddLicense(t, adminClient, coderdenttest.LicenseOptions{
|
||||
Features: license.Features{
|
||||
|
@ -82,43 +81,42 @@ func TestServiceBanners(t *testing.T) {
|
|||
// Default state
|
||||
sb, err = basicUserClient.Appearance(ctx)
|
||||
require.NoError(t, err)
|
||||
require.False(t, sb.ServiceBanner.Enabled)
|
||||
require.Empty(t, sb.NotificationBanners)
|
||||
|
||||
uac := codersdk.UpdateAppearanceConfig{
|
||||
ServiceBanner: sb.ServiceBanner,
|
||||
}
|
||||
// Regular user should be unable to set the banner
|
||||
uac.ServiceBanner.Enabled = true
|
||||
|
||||
uac := codersdk.UpdateAppearanceConfig{
|
||||
NotificationBanners: []codersdk.BannerConfig{{Enabled: true}},
|
||||
}
|
||||
err = basicUserClient.UpdateAppearance(ctx, uac)
|
||||
require.Error(t, err)
|
||||
var sdkError *codersdk.Error
|
||||
require.True(t, errors.As(err, &sdkError))
|
||||
require.ErrorAs(t, err, &sdkError)
|
||||
require.Equal(t, http.StatusForbidden, sdkError.StatusCode())
|
||||
|
||||
// But an admin can
|
||||
wantBanner := uac
|
||||
wantBanner.ServiceBanner.Enabled = true
|
||||
wantBanner.ServiceBanner.Message = "Hey"
|
||||
wantBanner.ServiceBanner.BackgroundColor = "#00FF00"
|
||||
wantBanner := codersdk.UpdateAppearanceConfig{
|
||||
NotificationBanners: []codersdk.BannerConfig{{
|
||||
Enabled: true,
|
||||
Message: "The beep-bop will be boop-beeped on Saturday at 12AM PST.",
|
||||
BackgroundColor: "#00FF00",
|
||||
}},
|
||||
}
|
||||
err = adminClient.UpdateAppearance(ctx, wantBanner)
|
||||
require.NoError(t, err)
|
||||
gotBanner, err := adminClient.Appearance(ctx) //nolint:gocritic // we should assert at least once that the owner can get the banner
|
||||
require.NoError(t, err)
|
||||
gotBanner.SupportLinks = nil // clean "support links" before comparison
|
||||
require.Equal(t, wantBanner.ServiceBanner, gotBanner.ServiceBanner)
|
||||
require.Equal(t, wantBanner.NotificationBanners, gotBanner.NotificationBanners)
|
||||
|
||||
// But even an admin can't give a bad color
|
||||
wantBanner.ServiceBanner.BackgroundColor = "#bad color"
|
||||
wantBanner.NotificationBanners[0].BackgroundColor = "#bad color"
|
||||
err = adminClient.UpdateAppearance(ctx, wantBanner)
|
||||
require.Error(t, err)
|
||||
|
||||
var sdkErr *codersdk.Error
|
||||
if assert.ErrorAs(t, err, &sdkErr) {
|
||||
assert.Equal(t, http.StatusBadRequest, sdkErr.StatusCode())
|
||||
assert.Contains(t, sdkErr.Message, "Invalid color format")
|
||||
assert.Contains(t, sdkErr.Detail, "expected # prefix and 6 characters")
|
||||
}
|
||||
require.ErrorAs(t, err, &sdkErr)
|
||||
require.Equal(t, http.StatusBadRequest, sdkErr.StatusCode())
|
||||
require.Contains(t, sdkErr.Message, "Invalid color format")
|
||||
require.Contains(t, sdkErr.Detail, "expected # prefix and 6 characters")
|
||||
})
|
||||
|
||||
t.Run("Agent", func(t *testing.T) {
|
||||
|
@ -141,11 +139,11 @@ func TestServiceBanners(t *testing.T) {
|
|||
},
|
||||
})
|
||||
cfg := codersdk.UpdateAppearanceConfig{
|
||||
ServiceBanner: codersdk.BannerConfig{
|
||||
NotificationBanners: []codersdk.BannerConfig{{
|
||||
Enabled: true,
|
||||
Message: "Hey",
|
||||
Message: "The beep-bop will be boop-beeped on Saturday at 12AM PST.",
|
||||
BackgroundColor: "#00FF00",
|
||||
},
|
||||
}},
|
||||
}
|
||||
err := client.UpdateAppearance(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
@ -157,34 +155,38 @@ func TestServiceBanners(t *testing.T) {
|
|||
|
||||
agentClient := agentsdk.New(client.URL)
|
||||
agentClient.SetSessionToken(r.AgentToken)
|
||||
banner := requireGetServiceBanner(ctx, t, agentClient)
|
||||
require.Equal(t, cfg.ServiceBanner, banner)
|
||||
banners := requireGetNotificationBanners(ctx, t, agentClient)
|
||||
require.Equal(t, cfg.NotificationBanners, banners)
|
||||
|
||||
// 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 = requireGetServiceBanner(ctx, t, agplAgentClient)
|
||||
require.Equal(t, codersdk.BannerConfig{}, banner)
|
||||
banners = requireGetNotificationBanners(ctx, t, agplAgentClient)
|
||||
require.Equal(t, []codersdk.BannerConfig{}, banners)
|
||||
|
||||
// No license means no banner.
|
||||
err = client.DeleteLicense(ctx, lic.ID)
|
||||
require.NoError(t, err)
|
||||
banner = requireGetServiceBanner(ctx, t, agentClient)
|
||||
require.Equal(t, codersdk.BannerConfig{}, banner)
|
||||
banners = requireGetNotificationBanners(ctx, t, agentClient)
|
||||
require.Equal(t, []codersdk.BannerConfig{}, banners)
|
||||
})
|
||||
}
|
||||
|
||||
func requireGetServiceBanner(ctx context.Context, t *testing.T, client *agentsdk.Client) codersdk.BannerConfig {
|
||||
func requireGetNotificationBanners(ctx context.Context, t *testing.T, client *agentsdk.Client) []codersdk.BannerConfig {
|
||||
cc, err := client.ConnectRPC(ctx)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
_ = cc.Close()
|
||||
}()
|
||||
aAPI := proto.NewDRPCAgentClient(cc)
|
||||
sbp, err := aAPI.GetServiceBanner(ctx, &proto.GetServiceBannerRequest{})
|
||||
bannersProto, err := aAPI.GetNotificationBanners(ctx, &proto.GetNotificationBannersRequest{})
|
||||
require.NoError(t, err)
|
||||
return agentsdk.ServiceBannerFromProto(sbp)
|
||||
banners := make([]codersdk.BannerConfig, 0, len(bannersProto.NotificationBanners))
|
||||
for _, bannerProto := range bannersProto.NotificationBanners {
|
||||
banners = append(banners, agentsdk.BannerConfigFromProto(bannerProto))
|
||||
}
|
||||
return banners
|
||||
}
|
||||
|
||||
func TestCustomSupportLinks(t *testing.T) {
|
||||
|
|
|
@ -1485,10 +1485,17 @@ func (h *heartbeats) filter(mappings []mapping) []mapping {
|
|||
ok := m.coordinator == h.self
|
||||
if !ok {
|
||||
_, ok = h.coordinators[m.coordinator]
|
||||
if !ok {
|
||||
// If a mapping exists to a coordinator lost to heartbeats,
|
||||
// still add the mapping as LOST. If a coordinator misses
|
||||
// heartbeats but a client is still connected to it, this may be
|
||||
// the only mapping available for it. Newer mappings will take
|
||||
// precedence.
|
||||
m.kind = proto.CoordinateResponse_PeerUpdate_LOST
|
||||
}
|
||||
}
|
||||
if ok {
|
||||
out = append(out, m)
|
||||
}
|
||||
|
||||
out = append(out, m)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
"golang.org/x/xerrors"
|
||||
|
@ -33,9 +34,9 @@ import (
|
|||
// make update-golden-files
|
||||
var UpdateGoldenFiles = flag.Bool("update", false, "update .golden files")
|
||||
|
||||
// TestHeartbeat_Cleanup is internal so that we can overwrite the cleanup period and not wait an hour for the timed
|
||||
// TestHeartbeats_Cleanup is internal so that we can overwrite the cleanup period and not wait an hour for the timed
|
||||
// cleanup.
|
||||
func TestHeartbeat_Cleanup(t *testing.T) {
|
||||
func TestHeartbeats_Cleanup(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
|
@ -78,6 +79,41 @@ func TestHeartbeat_Cleanup(t *testing.T) {
|
|||
close(waitForCleanup)
|
||||
}
|
||||
|
||||
func TestHeartbeats_LostCoordinator_MarkLost(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
mStore := dbmock.NewMockStore(ctrl)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
||||
defer cancel()
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
uut := &heartbeats{
|
||||
ctx: ctx,
|
||||
logger: logger,
|
||||
store: mStore,
|
||||
cleanupPeriod: time.Millisecond,
|
||||
coordinators: map[uuid.UUID]time.Time{
|
||||
uuid.New(): time.Now(),
|
||||
},
|
||||
}
|
||||
|
||||
mpngs := []mapping{{
|
||||
peer: uuid.New(),
|
||||
coordinator: uuid.New(),
|
||||
updatedAt: time.Now(),
|
||||
node: &proto.Node{},
|
||||
kind: proto.CoordinateResponse_PeerUpdate_NODE,
|
||||
}}
|
||||
|
||||
// Filter should still return the mapping without a coordinator, but marked
|
||||
// as LOST.
|
||||
got := uut.filter(mpngs)
|
||||
require.Len(t, got, 1)
|
||||
assert.Equal(t, proto.CoordinateResponse_PeerUpdate_LOST, got[0].kind)
|
||||
}
|
||||
|
||||
// TestLostPeerCleanupQueries tests that our SQL queries to clean up lost peers do what we expect,
|
||||
// that is, clean up peers and associated tunnels that have been lost for over 24 hours.
|
||||
func TestLostPeerCleanupQueries(t *testing.T) {
|
||||
|
|
|
@ -415,6 +415,52 @@ func TestPGCoordinatorSingle_MissedHeartbeats(t *testing.T) {
|
|||
assertEventuallyLost(ctx, t, store, client.id)
|
||||
}
|
||||
|
||||
func TestPGCoordinatorSingle_MissedHeartbeats_NoDrop(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !dbtestutil.WillUsePostgres() {
|
||||
t.Skip("test only with postgres")
|
||||
}
|
||||
store, ps := dbtestutil.NewDB(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitSuperLong)
|
||||
defer cancel()
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
coordinator, err := tailnet.NewPGCoord(ctx, logger, ps, store)
|
||||
require.NoError(t, err)
|
||||
defer coordinator.Close()
|
||||
|
||||
agentID := uuid.New()
|
||||
|
||||
client := agpltest.NewPeer(ctx, t, coordinator, "client")
|
||||
defer client.Close(ctx)
|
||||
client.AddTunnel(agentID)
|
||||
|
||||
client.UpdateDERP(11)
|
||||
|
||||
// simulate a second coordinator via DB calls only --- our goal is to test
|
||||
// broken heart-beating, so we can't use a real coordinator
|
||||
fCoord2 := &fakeCoordinator{
|
||||
ctx: ctx,
|
||||
t: t,
|
||||
store: store,
|
||||
id: uuid.New(),
|
||||
}
|
||||
// simulate a single heartbeat, the coordinator is healthy
|
||||
fCoord2.heartbeat()
|
||||
|
||||
fCoord2.agentNode(agentID, &agpl.Node{PreferredDERP: 12})
|
||||
// since it's healthy the client should get the new node.
|
||||
client.AssertEventuallyHasDERP(agentID, 12)
|
||||
|
||||
// the heartbeat should then timeout and we'll get sent a LOST update, NOT a
|
||||
// disconnect.
|
||||
client.AssertEventuallyLost(agentID)
|
||||
|
||||
client.Close(ctx)
|
||||
|
||||
assertEventuallyLost(ctx, t, store, client.ID)
|
||||
}
|
||||
|
||||
func TestPGCoordinatorSingle_SendsHeartbeats(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !dbtestutil.WillUsePostgres() {
|
||||
|
@ -857,6 +903,16 @@ func newTestAgent(t *testing.T, coord agpl.CoordinatorV1, name string, id ...uui
|
|||
return a
|
||||
}
|
||||
|
||||
func newTestClient(t *testing.T, coord agpl.CoordinatorV1, agentID uuid.UUID, id ...uuid.UUID) *testConn {
|
||||
c := newTestConn(id)
|
||||
go func() {
|
||||
err := coord.ServeClient(c.serverWS, c.id, agentID)
|
||||
assert.NoError(t, err)
|
||||
close(c.closeChan)
|
||||
}()
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *testConn) close() error {
|
||||
return c.ws.Close()
|
||||
}
|
||||
|
@ -902,16 +958,6 @@ func (c *testConn) waitForClose(ctx context.Context, t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func newTestClient(t *testing.T, coord agpl.CoordinatorV1, agentID uuid.UUID, id ...uuid.UUID) *testConn {
|
||||
c := newTestConn(id)
|
||||
go func() {
|
||||
err := coord.ServeClient(c.serverWS, c.id, agentID)
|
||||
assert.NoError(t, err)
|
||||
close(c.closeChan)
|
||||
}()
|
||||
return c
|
||||
}
|
||||
|
||||
func assertEventuallyHasDERPs(ctx context.Context, t *testing.T, c *testConn, expected ...int) {
|
||||
t.Helper()
|
||||
for {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#!/sbin/openrc-run
|
||||
name=coder
|
||||
description="Coder - Self-hosted developer workspaces on your infra"
|
||||
document="https://coder.com/docs/coder-oss"
|
||||
|
||||
depend() {
|
||||
need net
|
||||
after net-online
|
||||
use dns logger
|
||||
}
|
||||
|
||||
checkpath --directory --owner coder:coder --mode 0700 /var/cache/coder
|
||||
|
||||
start_pre() {
|
||||
if [ ! -f /etc/coder.d/coder.env ]; then
|
||||
eerror "/etc/coder.d/coder.env file does not exist"
|
||||
return 1
|
||||
fi
|
||||
# Read and export environment variables ignoring comment lines and blank lines
|
||||
while IFS= read -r line; do
|
||||
# Skip blank or comment lines
|
||||
if [ -z "$line" ] || [[ "$line" =~ ^# ]]; then
|
||||
continue
|
||||
fi
|
||||
export "$line"
|
||||
done < /etc/coder.d/coder.env
|
||||
}
|
||||
|
||||
command="/usr/bin/coder"
|
||||
command_args="server"
|
||||
command_user="coder:coder"
|
||||
command_background="yes"
|
||||
pidfile="/run/coder.pid"
|
||||
|
||||
restart="always"
|
||||
restart_delay="5"
|
||||
|
||||
stop_timeout="90"
|
|
@ -0,0 +1,39 @@
|
|||
#!/sbin/openrc-run
|
||||
name=coder-workspace-proxy
|
||||
description="Coder - external workspace proxy server"
|
||||
document="https://coder.com/docs/coder-oss"
|
||||
|
||||
depend() {
|
||||
need net
|
||||
after net-online
|
||||
use dns logger
|
||||
}
|
||||
|
||||
checkpath --directory --owner coder:coder --mode 0700 /var/cache/coder
|
||||
|
||||
start_pre() {
|
||||
if [ ! -f /etc/coder.d/coder-workspace-proxy.env ]; then
|
||||
eerror "/etc/coder.d/coder-workspace-proxy.env file does not exist"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Read and export environment variables ignoring comment lines and blank lines
|
||||
while IFS= read -r line; do
|
||||
# Skip blank or comment lines
|
||||
if [ -z "$line" ] || [[ "$line" =~ ^# ]]; then
|
||||
continue
|
||||
fi
|
||||
export "$line"
|
||||
done < /etc/coder.d/coder-workspace-proxy.env
|
||||
}
|
||||
|
||||
command="/usr/bin/coder"
|
||||
command_args="workspace-proxy server"
|
||||
command_user="coder:coder"
|
||||
command_background="yes"
|
||||
pidfile="/run/coder-workspace-proxy.pid"
|
||||
|
||||
restart="always"
|
||||
restart_delay="5"
|
||||
|
||||
stop_timeout="90"
|
|
@ -0,0 +1,29 @@
|
|||
name: coder
|
||||
platform: linux
|
||||
arch: "${GOARCH}"
|
||||
version: "${CODER_VERSION}"
|
||||
version_schema: semver
|
||||
release: 1
|
||||
|
||||
vendor: Coder
|
||||
homepage: https://coder.com
|
||||
maintainer: Coder <support@coder.com>
|
||||
description: |
|
||||
Provision development environments with infrastructure with code
|
||||
license: AGPL-3.0
|
||||
suggests:
|
||||
- postgresql
|
||||
|
||||
scripts:
|
||||
preinstall: preinstall.sh
|
||||
|
||||
contents:
|
||||
- src: coder
|
||||
dst: /usr/bin/coder
|
||||
- src: coder.env
|
||||
dst: /etc/coder.d/coder.env
|
||||
type: "config|noreplace"
|
||||
- src: coder-workspace-proxy-openrc
|
||||
dst: /etc/init.d/coder-workspace-proxy
|
||||
- src: coder-openrc
|
||||
dst: /etc/init.d/coder
|
|
@ -89,9 +89,16 @@ ln "$(realpath scripts/linux-pkg/coder.service)" "$temp_dir/"
|
|||
ln "$(realpath scripts/linux-pkg/nfpm.yaml)" "$temp_dir/"
|
||||
ln "$(realpath scripts/linux-pkg/preinstall.sh)" "$temp_dir/"
|
||||
|
||||
nfpm_config_file="nfpm.yaml"
|
||||
|
||||
# Use nfpm-alpine.yaml when building for Alpine (OpenRC).
|
||||
if [[ "$format" == "apk" ]]; then
|
||||
nfpm_config_file="nfpm-alpine.yaml"
|
||||
fi
|
||||
|
||||
pushd "$temp_dir"
|
||||
GOARCH="$arch" CODER_VERSION="$version" nfpm package \
|
||||
-f nfpm.yaml \
|
||||
-f "$nfpm_config_file" \
|
||||
-p "$format" \
|
||||
-t "$output_path" \
|
||||
1>&2
|
||||
|
|
|
@ -9,15 +9,15 @@ const meta: Meta<typeof AppearanceSettingsPageView> = {
|
|||
application_name: "Foobar",
|
||||
logo_url: "https://github.com/coder.png",
|
||||
service_banner: {
|
||||
enabled: true,
|
||||
message: "hello world",
|
||||
background_color: "white",
|
||||
enabled: false,
|
||||
message: "",
|
||||
background_color: "#00ff00",
|
||||
},
|
||||
notification_banners: [
|
||||
{
|
||||
enabled: true,
|
||||
message: "hello world",
|
||||
background_color: "white",
|
||||
message: "The beep-bop will be boop-beeped on Saturday at 12AM PST.",
|
||||
background_color: "#ffaff3",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -20,7 +20,6 @@ export type AppearanceSettingsPageViewProps = {
|
|||
isEntitled: boolean;
|
||||
onSaveAppearance: (
|
||||
newConfig: Partial<UpdateAppearanceConfig>,
|
||||
preview?: boolean,
|
||||
) => Promise<void>;
|
||||
};
|
||||
|
||||
|
@ -33,7 +32,7 @@ export const AppearanceSettingsPageView: FC<
|
|||
initialValues: {
|
||||
application_name: appearance.application_name,
|
||||
},
|
||||
onSubmit: (values) => onSaveAppearance(values, false),
|
||||
onSubmit: (values) => onSaveAppearance(values),
|
||||
});
|
||||
const applicationNameFieldHelpers = getFormHelpers(applicationNameForm);
|
||||
|
||||
|
@ -43,7 +42,7 @@ export const AppearanceSettingsPageView: FC<
|
|||
initialValues: {
|
||||
logo_url: appearance.logo_url,
|
||||
},
|
||||
onSubmit: (values) => onSaveAppearance(values, false),
|
||||
onSubmit: (values) => onSaveAppearance(values),
|
||||
});
|
||||
const logoFieldHelpers = getFormHelpers(logoForm);
|
||||
|
||||
|
|
|
@ -129,7 +129,6 @@ func handleTestSubprocess(t *testing.T) {
|
|||
testName += *clientName
|
||||
}
|
||||
|
||||
//nolint:parralleltest
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
log := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
switch *role {
|
||||
|
|
Loading…
Reference in New Issue