@@ -33,6 +33,7 @@ import (
33
33
34
34
"cdr.dev/slog"
35
35
"github.com/coder/coder/agent/usershell"
36
+ "github.com/coder/coder/codersdk"
36
37
"github.com/coder/coder/pty"
37
38
"github.com/coder/coder/tailnet"
38
39
"github.com/coder/retry"
@@ -49,39 +50,26 @@ const (
49
50
MagicSessionErrorCode = 229
50
51
)
51
52
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
-
62
53
type Options struct {
63
- CoordinatorDialer CoordinatorDialer
64
- FetchMetadata FetchMetadata
65
-
54
+ CoordinatorDialer CoordinatorDialer
55
+ FetchMetadata FetchMetadata
56
+ FetchWorkspaceApps FetchWorkspaceApps
57
+ PostWorkspaceAppHealth PostWorkspaceAppHealth
66
58
StatsReporter StatsReporter
67
59
ReconnectingPTYTimeout time.Duration
68
60
EnvironmentVariables map [string ]string
69
61
Logger slog.Logger
70
62
}
71
63
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
-
79
64
// CoordinatorDialer is a function that constructs a new broker.
80
65
// 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 )
82
67
83
68
// 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
85
73
86
74
func New (options Options ) io.Closer {
87
75
if options .ReconnectingPTYTimeout == 0 {
@@ -98,6 +86,8 @@ func New(options Options) io.Closer {
98
86
fetchMetadata : options .FetchMetadata ,
99
87
stats : & Stats {},
100
88
statsReporter : options .StatsReporter ,
89
+ fetchWorkspaceApps : options .FetchWorkspaceApps ,
90
+ postWorkspaceAppHealth : options .PostWorkspaceAppHealth ,
101
91
}
102
92
server .init (ctx )
103
93
return server
@@ -120,14 +110,16 @@ type agent struct {
120
110
fetchMetadata FetchMetadata
121
111
sshServer * ssh.Server
122
112
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
127
119
}
128
120
129
121
func (a * agent ) run (ctx context.Context ) {
130
- var metadata Metadata
122
+ var metadata codersdk. WorkspaceAgentMetadata
131
123
var err error
132
124
// An exponential back-off occurs when the connection is failing to dial.
133
125
// This is to prevent server spam in case of a coderd outage.
@@ -168,6 +160,8 @@ func (a *agent) run(ctx context.Context) {
168
160
if metadata .DERPMap != nil {
169
161
go a .runTailnet (ctx , metadata .DERPMap )
170
162
}
163
+
164
+ go reportAppHealth (ctx , a .logger , a .fetchWorkspaceApps , a .postWorkspaceAppHealth )
171
165
}
172
166
173
167
func (a * agent ) runTailnet (ctx context.Context , derpMap * tailcfg.DERPMap ) {
@@ -182,7 +176,7 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
182
176
}
183
177
var err error
184
178
a .network , err = tailnet .NewConn (& tailnet.Options {
185
- Addresses : []netip.Prefix {netip .PrefixFrom (tailnetIP , 128 )},
179
+ Addresses : []netip.Prefix {netip .PrefixFrom (codersdk . TailnetIP , 128 )},
186
180
DERPMap : derpMap ,
187
181
Logger : a .logger .Named ("tailnet" ),
188
182
})
@@ -199,7 +193,7 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
199
193
})
200
194
go a .runCoordinator (ctx )
201
195
202
- sshListener , err := a .network .Listen ("tcp" , ":" + strconv .Itoa (tailnetSSHPort ))
196
+ sshListener , err := a .network .Listen ("tcp" , ":" + strconv .Itoa (codersdk . TailnetSSHPort ))
203
197
if err != nil {
204
198
a .logger .Critical (ctx , "listen for ssh" , slog .Error (err ))
205
199
return
@@ -213,7 +207,7 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
213
207
go a .sshServer .HandleConn (a .stats .wrapConn (conn ))
214
208
}
215
209
}()
216
- reconnectingPTYListener , err := a .network .Listen ("tcp" , ":" + strconv .Itoa (tailnetReconnectingPTYPort ))
210
+ reconnectingPTYListener , err := a .network .Listen ("tcp" , ":" + strconv .Itoa (codersdk . TailnetReconnectingPTYPort ))
217
211
if err != nil {
218
212
a .logger .Critical (ctx , "listen for reconnecting pty" , slog .Error (err ))
219
213
return
@@ -239,15 +233,15 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
239
233
if err != nil {
240
234
continue
241
235
}
242
- var msg reconnectingPTYInit
236
+ var msg codersdk. ReconnectingPTYInit
243
237
err = json .Unmarshal (data , & msg )
244
238
if err != nil {
245
239
continue
246
240
}
247
241
go a .handleReconnectingPTY (ctx , msg , conn )
248
242
}
249
243
}()
250
- speedtestListener , err := a .network .Listen ("tcp" , ":" + strconv .Itoa (tailnetSpeedtestPort ))
244
+ speedtestListener , err := a .network .Listen ("tcp" , ":" + strconv .Itoa (codersdk . TailnetSpeedtestPort ))
251
245
if err != nil {
252
246
a .logger .Critical (ctx , "listen for speedtest" , slog .Error (err ))
253
247
return
@@ -434,7 +428,7 @@ func (a *agent) init(ctx context.Context) {
434
428
435
429
go a .run (ctx )
436
430
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 {
438
432
return a .stats .Copy ()
439
433
})
440
434
if err != nil {
@@ -469,7 +463,7 @@ func (a *agent) createCommand(ctx context.Context, rawCommand string, env []stri
469
463
if rawMetadata == nil {
470
464
return nil , xerrors .Errorf ("no metadata was provided: %w" , err )
471
465
}
472
- metadata , valid := rawMetadata .(Metadata )
466
+ metadata , valid := rawMetadata .(codersdk. WorkspaceAgentMetadata )
473
467
if ! valid {
474
468
return nil , xerrors .Errorf ("metadata is the wrong type: %T" , metadata )
475
469
}
@@ -625,7 +619,7 @@ func (a *agent) handleSSHSession(session ssh.Session) (retErr error) {
625
619
return cmd .Wait ()
626
620
}
627
621
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 ) {
629
623
defer conn .Close ()
630
624
631
625
var rpty * reconnectingPTY
@@ -766,7 +760,7 @@ func (a *agent) handleReconnectingPTY(ctx context.Context, msg reconnectingPTYIn
766
760
rpty .activeConnsMutex .Unlock ()
767
761
}()
768
762
decoder := json .NewDecoder (conn )
769
- var req ReconnectingPTYRequest
763
+ var req codersdk. ReconnectingPTYRequest
770
764
for {
771
765
err = decoder .Decode (& req )
772
766
if xerrors .Is (err , io .EOF ) {
0 commit comments