Skip to content

Commit 84c3cf8

Browse files
committed
add reportAppHealth
1 parent c098980 commit 84c3cf8

File tree

12 files changed

+258
-133
lines changed

12 files changed

+258
-133
lines changed

agent/agent.go

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333

3434
"cdr.dev/slog"
3535
"github.com/coder/coder/agent/usershell"
36+
"github.com/coder/coder/codersdk"
3637
"github.com/coder/coder/pty"
3738
"github.com/coder/coder/tailnet"
3839
"github.com/coder/retry"
@@ -49,39 +50,26 @@ const (
4950
MagicSessionErrorCode = 229
5051
)
5152

52-
var (
53-
// tailnetIP is a static IPv6 address with the Tailscale prefix that is used to route
54-
// connections from clients to this node. A dynamic address is not required because a Tailnet
55-
// client only dials a single agent at a time.
56-
tailnetIP = netip.MustParseAddr("fd7a:115c:a1e0:49d6:b259:b7ac:b1b2:48f4")
57-
tailnetSSHPort = 1
58-
tailnetReconnectingPTYPort = 2
59-
tailnetSpeedtestPort = 3
60-
)
61-
6253
type Options struct {
63-
CoordinatorDialer CoordinatorDialer
64-
FetchMetadata FetchMetadata
65-
54+
CoordinatorDialer CoordinatorDialer
55+
FetchMetadata FetchMetadata
56+
FetchWorkspaceApps FetchWorkspaceApps
57+
PostWorkspaceAppHealth PostWorkspaceAppHealth
6658
StatsReporter StatsReporter
6759
ReconnectingPTYTimeout time.Duration
6860
EnvironmentVariables map[string]string
6961
Logger slog.Logger
7062
}
7163

72-
type Metadata struct {
73-
DERPMap *tailcfg.DERPMap `json:"derpmap"`
74-
EnvironmentVariables map[string]string `json:"environment_variables"`
75-
StartupScript string `json:"startup_script"`
76-
Directory string `json:"directory"`
77-
}
78-
7964
// CoordinatorDialer is a function that constructs a new broker.
8065
// A dialer must be passed in to allow for reconnects.
81-
type CoordinatorDialer func(ctx context.Context) (net.Conn, error)
66+
type CoordinatorDialer func(context.Context) (net.Conn, error)
8267

8368
// FetchMetadata is a function to obtain metadata for the agent.
84-
type FetchMetadata func(ctx context.Context) (Metadata, error)
69+
type FetchMetadata func(context.Context) (codersdk.WorkspaceAgentMetadata, error)
70+
71+
type FetchWorkspaceApps func(context.Context) ([]codersdk.WorkspaceApp, error)
72+
type PostWorkspaceAppHealth func(context.Context, map[string]codersdk.WorkspaceAppHealth) error
8573

8674
func New(options Options) io.Closer {
8775
if options.ReconnectingPTYTimeout == 0 {
@@ -98,6 +86,8 @@ func New(options Options) io.Closer {
9886
fetchMetadata: options.FetchMetadata,
9987
stats: &Stats{},
10088
statsReporter: options.StatsReporter,
89+
fetchWorkspaceApps: options.FetchWorkspaceApps,
90+
postWorkspaceAppHealth: options.PostWorkspaceAppHealth,
10191
}
10292
server.init(ctx)
10393
return server
@@ -120,14 +110,16 @@ type agent struct {
120110
fetchMetadata FetchMetadata
121111
sshServer *ssh.Server
122112

123-
network *tailnet.Conn
124-
coordinatorDialer CoordinatorDialer
125-
stats *Stats
126-
statsReporter StatsReporter
113+
network *tailnet.Conn
114+
coordinatorDialer CoordinatorDialer
115+
stats *Stats
116+
statsReporter StatsReporter
117+
fetchWorkspaceApps FetchWorkspaceApps
118+
postWorkspaceAppHealth PostWorkspaceAppHealth
127119
}
128120

129121
func (a *agent) run(ctx context.Context) {
130-
var metadata Metadata
122+
var metadata codersdk.WorkspaceAgentMetadata
131123
var err error
132124
// An exponential back-off occurs when the connection is failing to dial.
133125
// This is to prevent server spam in case of a coderd outage.
@@ -168,6 +160,8 @@ func (a *agent) run(ctx context.Context) {
168160
if metadata.DERPMap != nil {
169161
go a.runTailnet(ctx, metadata.DERPMap)
170162
}
163+
164+
go reportAppHealth(ctx, a.logger, a.fetchWorkspaceApps, a.postWorkspaceAppHealth)
171165
}
172166

173167
func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
@@ -182,7 +176,7 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
182176
}
183177
var err error
184178
a.network, err = tailnet.NewConn(&tailnet.Options{
185-
Addresses: []netip.Prefix{netip.PrefixFrom(tailnetIP, 128)},
179+
Addresses: []netip.Prefix{netip.PrefixFrom(codersdk.TailnetIP, 128)},
186180
DERPMap: derpMap,
187181
Logger: a.logger.Named("tailnet"),
188182
})
@@ -199,7 +193,7 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
199193
})
200194
go a.runCoordinator(ctx)
201195

202-
sshListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(tailnetSSHPort))
196+
sshListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(codersdk.TailnetSSHPort))
203197
if err != nil {
204198
a.logger.Critical(ctx, "listen for ssh", slog.Error(err))
205199
return
@@ -213,7 +207,7 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
213207
go a.sshServer.HandleConn(a.stats.wrapConn(conn))
214208
}
215209
}()
216-
reconnectingPTYListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(tailnetReconnectingPTYPort))
210+
reconnectingPTYListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(codersdk.TailnetReconnectingPTYPort))
217211
if err != nil {
218212
a.logger.Critical(ctx, "listen for reconnecting pty", slog.Error(err))
219213
return
@@ -239,15 +233,15 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
239233
if err != nil {
240234
continue
241235
}
242-
var msg reconnectingPTYInit
236+
var msg codersdk.ReconnectingPTYInit
243237
err = json.Unmarshal(data, &msg)
244238
if err != nil {
245239
continue
246240
}
247241
go a.handleReconnectingPTY(ctx, msg, conn)
248242
}
249243
}()
250-
speedtestListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(tailnetSpeedtestPort))
244+
speedtestListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(codersdk.TailnetSpeedtestPort))
251245
if err != nil {
252246
a.logger.Critical(ctx, "listen for speedtest", slog.Error(err))
253247
return
@@ -434,7 +428,7 @@ func (a *agent) init(ctx context.Context) {
434428

435429
go a.run(ctx)
436430
if a.statsReporter != nil {
437-
cl, err := a.statsReporter(ctx, a.logger, func() *Stats {
431+
cl, err := a.statsReporter(ctx, a.logger, func() *codersdk.AgentStats {
438432
return a.stats.Copy()
439433
})
440434
if err != nil {
@@ -469,7 +463,7 @@ func (a *agent) createCommand(ctx context.Context, rawCommand string, env []stri
469463
if rawMetadata == nil {
470464
return nil, xerrors.Errorf("no metadata was provided: %w", err)
471465
}
472-
metadata, valid := rawMetadata.(Metadata)
466+
metadata, valid := rawMetadata.(codersdk.WorkspaceAgentMetadata)
473467
if !valid {
474468
return nil, xerrors.Errorf("metadata is the wrong type: %T", metadata)
475469
}
@@ -625,7 +619,7 @@ func (a *agent) handleSSHSession(session ssh.Session) (retErr error) {
625619
return cmd.Wait()
626620
}
627621

628-
func (a *agent) handleReconnectingPTY(ctx context.Context, msg reconnectingPTYInit, conn net.Conn) {
622+
func (a *agent) handleReconnectingPTY(ctx context.Context, msg codersdk.ReconnectingPTYInit, conn net.Conn) {
629623
defer conn.Close()
630624

631625
var rpty *reconnectingPTY
@@ -766,7 +760,7 @@ func (a *agent) handleReconnectingPTY(ctx context.Context, msg reconnectingPTYIn
766760
rpty.activeConnsMutex.Unlock()
767761
}()
768762
decoder := json.NewDecoder(conn)
769-
var req ReconnectingPTYRequest
763+
var req codersdk.ReconnectingPTYRequest
770764
for {
771765
err = decoder.Decode(&req)
772766
if xerrors.Is(err, io.EOF) {

0 commit comments

Comments
 (0)