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

Skip to content

Commit 9c50c40

Browse files
committed
Merge branch 'main' of https://github.com/coder/coder into bq/go-to-task-page
2 parents fa138ef + 1c87796 commit 9c50c40

File tree

25 files changed

+1415
-468
lines changed

25 files changed

+1415
-468
lines changed

agent/agent.go

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,21 +1158,13 @@ func (a *agent) handleManifest(manifestOK *checkpoint) func(ctx context.Context,
11581158
}
11591159
}
11601160

1161-
var (
1162-
scripts = manifest.Scripts
1163-
scriptRunnerOpts []agentscripts.InitOption
1164-
devcontainerScripts map[uuid.UUID]codersdk.WorkspaceAgentScript
1165-
)
1166-
if a.devcontainers {
1167-
a.containerAPI.Init(
1168-
agentcontainers.WithManifestInfo(manifest.OwnerName, manifest.WorkspaceName, manifest.AgentName),
1169-
agentcontainers.WithDevcontainers(manifest.Devcontainers, scripts),
1170-
agentcontainers.WithSubAgentClient(agentcontainers.NewSubAgentClientFromAPI(a.logger, aAPI)),
1171-
)
1172-
1173-
scripts, devcontainerScripts = agentcontainers.ExtractDevcontainerScripts(manifest.Devcontainers, scripts)
1161+
scripts := manifest.Scripts
1162+
if a.containerAPI != nil {
1163+
// Since devcontainer are enabled, remove devcontainer scripts
1164+
// from the main scripts list to avoid showing an error.
1165+
scripts, _ = agentcontainers.ExtractDevcontainerScripts(manifest.Devcontainers, manifest.Scripts)
11741166
}
1175-
err = a.scriptRunner.Init(scripts, aAPI.ScriptCompleted, scriptRunnerOpts...)
1167+
err = a.scriptRunner.Init(scripts, aAPI.ScriptCompleted)
11761168
if err != nil {
11771169
return xerrors.Errorf("init script runner: %w", err)
11781170
}
@@ -1190,9 +1182,18 @@ func (a *agent) handleManifest(manifestOK *checkpoint) func(ctx context.Context,
11901182
// autostarted devcontainer will be included in this time.
11911183
err := a.scriptRunner.Execute(a.gracefulCtx, agentscripts.ExecuteStartScripts)
11921184

1193-
for _, dc := range manifest.Devcontainers {
1194-
cErr := a.createDevcontainer(ctx, aAPI, dc, devcontainerScripts[dc.ID])
1195-
err = errors.Join(err, cErr)
1185+
if a.containerAPI != nil {
1186+
a.containerAPI.Init(
1187+
agentcontainers.WithManifestInfo(manifest.OwnerName, manifest.WorkspaceName, manifest.AgentName),
1188+
agentcontainers.WithDevcontainers(manifest.Devcontainers, manifest.Scripts),
1189+
agentcontainers.WithSubAgentClient(agentcontainers.NewSubAgentClientFromAPI(a.logger, aAPI)),
1190+
)
1191+
1192+
_, devcontainerScripts := agentcontainers.ExtractDevcontainerScripts(manifest.Devcontainers, manifest.Scripts)
1193+
for _, dc := range manifest.Devcontainers {
1194+
cErr := a.createDevcontainer(ctx, aAPI, dc, devcontainerScripts[dc.ID])
1195+
err = errors.Join(err, cErr)
1196+
}
11961197
}
11971198

11981199
dur := time.Since(start).Seconds()

agent/agentcontainers/api.go

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,14 @@ type API struct {
7979
containersErr error // Error from the last list operation.
8080
devcontainerNames map[string]bool // By devcontainer name.
8181
knownDevcontainers map[string]codersdk.WorkspaceAgentDevcontainer // By workspace folder.
82+
devcontainerLogSourceIDs map[string]uuid.UUID // By workspace folder.
8283
configFileModifiedTimes map[string]time.Time // By config file path.
8384
recreateSuccessTimes map[string]time.Time // By workspace folder.
8485
recreateErrorTimes map[string]time.Time // By workspace folder.
8586
injectedSubAgentProcs map[string]subAgentProcess // By workspace folder.
8687
usingWorkspaceFolderName map[string]bool // By workspace folder.
8788
ignoredDevcontainers map[string]bool // By workspace folder. Tracks three states (true, false and not checked).
8889
asyncWg sync.WaitGroup
89-
90-
devcontainerLogSourceIDs map[string]uuid.UUID // By workspace folder.
9190
}
9291

9392
type subAgentProcess struct {
@@ -530,7 +529,6 @@ func (api *API) updateContainers(ctx context.Context) error {
530529
// will clear up on the next update.
531530
if !errors.Is(err, context.Canceled) {
532531
api.mu.Lock()
533-
api.containers = codersdk.WorkspaceAgentListContainersResponse{}
534532
api.containersErr = err
535533
api.mu.Unlock()
536534
}
@@ -936,34 +934,33 @@ func (api *API) CreateDevcontainer(workspaceFolder, configPath string, opts ...D
936934
return xerrors.Errorf("devcontainer not found")
937935
}
938936

939-
api.asyncWg.Add(1)
940-
defer api.asyncWg.Done()
941-
api.mu.Unlock()
942-
943937
var (
944-
err error
945938
ctx = api.ctx
946939
logger = api.logger.With(
947940
slog.F("devcontainer_id", dc.ID),
948941
slog.F("devcontainer_name", dc.Name),
949942
slog.F("workspace_folder", dc.WorkspaceFolder),
950-
slog.F("config_path", configPath),
943+
slog.F("config_path", dc.ConfigPath),
951944
)
952945
)
953946

954-
if dc.ConfigPath != configPath {
955-
logger.Warn(ctx, "devcontainer config path mismatch",
956-
slog.F("config_path_param", configPath),
957-
)
958-
}
959-
960947
// Send logs via agent logging facilities.
961948
logSourceID := api.devcontainerLogSourceIDs[dc.WorkspaceFolder]
962949
if logSourceID == uuid.Nil {
963-
// Fallback to the external log source ID if not found.
950+
api.logger.Debug(api.ctx, "devcontainer log source ID not found, falling back to external log source ID")
964951
logSourceID = agentsdk.ExternalLogSourceID
965952
}
966953

954+
api.asyncWg.Add(1)
955+
defer api.asyncWg.Done()
956+
api.mu.Unlock()
957+
958+
if dc.ConfigPath != configPath {
959+
logger.Warn(ctx, "devcontainer config path mismatch",
960+
slog.F("config_path_param", configPath),
961+
)
962+
}
963+
967964
scriptLogger := api.scriptLogger(logSourceID)
968965
defer func() {
969966
flushCtx, cancel := context.WithTimeout(api.ctx, 5*time.Second)
@@ -982,7 +979,7 @@ func (api *API) CreateDevcontainer(workspaceFolder, configPath string, opts ...D
982979
upOptions := []DevcontainerCLIUpOptions{WithUpOutput(infoW, errW)}
983980
upOptions = append(upOptions, opts...)
984981

985-
_, err = api.dccli.Up(ctx, dc.WorkspaceFolder, configPath, upOptions...)
982+
_, err := api.dccli.Up(ctx, dc.WorkspaceFolder, configPath, upOptions...)
986983
if err != nil {
987984
// No need to log if the API is closing (context canceled), as this
988985
// is expected behavior when the API is shutting down.
@@ -1002,15 +999,6 @@ func (api *API) CreateDevcontainer(workspaceFolder, configPath string, opts ...D
1002999

10031000
logger.Info(ctx, "devcontainer created successfully")
10041001

1005-
// Ensure the container list is updated immediately after creation.
1006-
// This makes sure that dc.Container is populated before we acquire
1007-
// the lock avoiding a temporary inconsistency in the API state
1008-
// where status is running, but the container is nil.
1009-
if err := api.RefreshContainers(ctx); err != nil {
1010-
logger.Error(ctx, "failed to trigger immediate refresh after devcontainer creation", slog.Error(err))
1011-
return xerrors.Errorf("refresh containers: %w", err)
1012-
}
1013-
10141002
api.mu.Lock()
10151003
dc = api.knownDevcontainers[dc.WorkspaceFolder]
10161004
// Update the devcontainer status to Running or Stopped based on the
@@ -1029,6 +1017,13 @@ func (api *API) CreateDevcontainer(workspaceFolder, configPath string, opts ...D
10291017
api.knownDevcontainers[dc.WorkspaceFolder] = dc
10301018
api.mu.Unlock()
10311019

1020+
// Ensure an immediate refresh to accurately reflect the
1021+
// devcontainer state after recreation.
1022+
if err := api.RefreshContainers(ctx); err != nil {
1023+
logger.Error(ctx, "failed to trigger immediate refresh after devcontainer creation", slog.Error(err))
1024+
return xerrors.Errorf("refresh containers: %w", err)
1025+
}
1026+
10321027
return nil
10331028
}
10341029

agent/agentssh/agentssh.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ type Config struct {
117117
// Note that this is different from the devcontainers feature, which uses
118118
// subagents.
119119
ExperimentalContainers bool
120+
// X11Net allows overriding the networking implementation used for X11
121+
// forwarding listeners. When nil, a default implementation backed by the
122+
// standard library networking package is used.
123+
X11Net X11Network
120124
}
121125

122126
type Server struct {
@@ -130,9 +134,10 @@ type Server struct {
130134
// a lock on mu but protected by closing.
131135
wg sync.WaitGroup
132136

133-
Execer agentexec.Execer
134-
logger slog.Logger
135-
srv *ssh.Server
137+
Execer agentexec.Execer
138+
logger slog.Logger
139+
srv *ssh.Server
140+
x11Forwarder *x11Forwarder
136141

137142
config *Config
138143

@@ -188,6 +193,20 @@ func NewServer(ctx context.Context, logger slog.Logger, prometheusRegistry *prom
188193
config: config,
189194

190195
metrics: metrics,
196+
x11Forwarder: &x11Forwarder{
197+
logger: logger,
198+
x11HandlerErrors: metrics.x11HandlerErrors,
199+
fs: fs,
200+
displayOffset: *config.X11DisplayOffset,
201+
sessions: make(map[*x11Session]struct{}),
202+
connections: make(map[net.Conn]struct{}),
203+
network: func() X11Network {
204+
if config.X11Net != nil {
205+
return config.X11Net
206+
}
207+
return osNet{}
208+
}(),
209+
},
191210
}
192211

193212
srv := &ssh.Server{
@@ -455,7 +474,7 @@ func (s *Server) sessionHandler(session ssh.Session) {
455474

456475
x11, hasX11 := session.X11()
457476
if hasX11 {
458-
display, handled := s.x11Handler(ctx, x11)
477+
display, handled := s.x11Forwarder.x11Handler(ctx, session)
459478
if !handled {
460479
logger.Error(ctx, "x11 handler failed")
461480
closeCause("x11 handler failed")
@@ -1114,6 +1133,9 @@ func (s *Server) Close() error {
11141133

11151134
s.mu.Unlock()
11161135

1136+
s.logger.Debug(ctx, "closing X11 forwarding")
1137+
_ = s.x11Forwarder.Close()
1138+
11171139
s.logger.Debug(ctx, "waiting for all goroutines to exit")
11181140
s.wg.Wait() // Wait for all goroutines to exit.
11191141

0 commit comments

Comments
 (0)