mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
feat: Improve resource preview and first-time experience (#946)
* Improve CLI documentation * feat: Allow workspace resources to attach multiple agents This enables a "kubernetes_pod" to attach multiple agents that could be for multiple services. Each agent is required to have a unique name, so SSH syntax is: `coder ssh <workspace>.<agent>` A resource can have zero agents too, they aren't required. * Add tree view * Improve table UI * feat: Allow workspace resources to attach multiple agents This enables a "kubernetes_pod" to attach multiple agents that could be for multiple services. Each agent is required to have a unique name, so SSH syntax is: `coder ssh <workspace>.<agent>` A resource can have zero agents too, they aren't required. * Rename `tunnel` to `skip-tunnel` This command was `true` by default, which causes a confusing user experience. * Add disclaimer about editing templates * Add help to template create * Improve workspace create flow * Add end-to-end test for config-ssh * Improve testing of config-ssh * Fix workspace list * Fix config ssh tests * Update cli/configssh.go Co-authored-by: Cian Johnston <public@cianjohnston.ie> * Fix requested changes * Remove socat requirement * Fix resources not reading in TTY Co-authored-by: Cian Johnston <public@cianjohnston.ie>
This commit is contained in:
@ -108,7 +108,7 @@ func New(t *testing.T, options *Options) *codersdk.Client {
|
||||
|
||||
// We set the handler after server creation for the access URL.
|
||||
srv.Config.Handler, closeWait = coderd.New(&coderd.Options{
|
||||
AgentConnectionUpdateFrequency: 25 * time.Millisecond,
|
||||
AgentConnectionUpdateFrequency: 150 * time.Millisecond,
|
||||
AccessURL: serverURL,
|
||||
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
|
||||
Database: db,
|
||||
@ -264,7 +264,7 @@ func AwaitWorkspaceAgents(t *testing.T, client *codersdk.Client, build uuid.UUID
|
||||
require.NoError(t, err)
|
||||
for _, resource := range resources {
|
||||
for _, agent := range resource.Agents {
|
||||
if agent.FirstConnectedAt == nil {
|
||||
if agent.Status != codersdk.WorkspaceAgentConnected {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,20 @@ func (api *api) workspaceAgentDial(rw http.ResponseWriter, r *http.Request) {
|
||||
defer api.websocketWaitGroup.Done()
|
||||
|
||||
agent := httpmw.WorkspaceAgentParam(r)
|
||||
apiAgent, err := convertWorkspaceAgent(agent, api.AgentConnectionUpdateFrequency)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("convert workspace agent: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
if apiAgent.Status != codersdk.WorkspaceAgentConnected {
|
||||
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{
|
||||
Message: fmt.Sprintf("Agent isn't connected! Status: %s", apiAgent.Status),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
conn, err := websocket.Accept(rw, r, &websocket.AcceptOptions{
|
||||
CompressionMode: websocket.CompressionDisabled,
|
||||
})
|
||||
@ -167,16 +181,16 @@ func (api *api) workspaceAgentListen(rw http.ResponseWriter, r *http.Request) {
|
||||
_ = updateConnectionTimes()
|
||||
}()
|
||||
|
||||
err = updateConnectionTimes()
|
||||
if err != nil {
|
||||
_ = conn.Close(websocket.StatusAbnormalClosure, err.Error())
|
||||
return
|
||||
}
|
||||
err = ensureLatestBuild()
|
||||
if err != nil {
|
||||
_ = conn.Close(websocket.StatusGoingAway, "")
|
||||
return
|
||||
}
|
||||
err = updateConnectionTimes()
|
||||
if err != nil {
|
||||
_ = conn.Close(websocket.StatusAbnormalClosure, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
api.Logger.Info(r.Context(), "accepting agent", slog.F("resource", resource), slog.F("agent", agent))
|
||||
|
||||
@ -239,7 +253,7 @@ func convertWorkspaceAgent(dbAgent database.WorkspaceAgent, agentUpdateFrequency
|
||||
case !dbAgent.FirstConnectedAt.Valid:
|
||||
// If the agent never connected, it's waiting for the compute
|
||||
// to start up.
|
||||
agent.Status = codersdk.WorkspaceAgentWaiting
|
||||
agent.Status = codersdk.WorkspaceAgentConnecting
|
||||
case dbAgent.DisconnectedAt.Time.After(dbAgent.LastConnectedAt.Time):
|
||||
// If we've disconnected after our last connection, we know the
|
||||
// agent is no longer connected.
|
||||
|
Reference in New Issue
Block a user