chore: Add watch workspace endpoint (#1493)

This commit is contained in:
Garrett Delfosse
2022-05-18 16:16:26 -05:00
committed by GitHub
parent b8ee939e52
commit 0706c60445
21 changed files with 259 additions and 37 deletions

View File

@ -12,6 +12,7 @@ import (
"strings"
"golang.org/x/xerrors"
"nhooyr.io/websocket"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw"
@ -63,7 +64,7 @@ func (c *Client) Request(ctx context.Context, method, path string, body interfac
return nil, xerrors.Errorf("create request: %w", err)
}
req.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: c.SessionToken,
})
if body != nil {
@ -80,6 +81,38 @@ func (c *Client) Request(ctx context.Context, method, path string, body interfac
return resp, err
}
// dialWebsocket opens a dialWebsocket connection on that path provided.
// The caller is responsible for closing the dialWebsocket.Conn.
func (c *Client) dialWebsocket(ctx context.Context, path string) (*websocket.Conn, error) {
serverURL, err := c.URL.Parse(path)
if err != nil {
return nil, xerrors.Errorf("parse path: %w", err)
}
apiURL, err := url.Parse(serverURL.String())
if err != nil {
return nil, xerrors.Errorf("parse server url: %w", err)
}
apiURL.Scheme = "ws"
if serverURL.Scheme == "https" {
apiURL.Scheme = "wss"
}
apiURL.Path = path
q := apiURL.Query()
q.Add(httpmw.SessionTokenKey, c.SessionToken)
apiURL.RawQuery = q.Encode()
//nolint:bodyclose
conn, _, err := websocket.Dial(ctx, apiURL.String(), &websocket.DialOptions{
HTTPClient: c.HTTPClient,
})
if err != nil {
return nil, xerrors.Errorf("dial websocket: %w", err)
}
return conn, nil
}
// readBodyAsError reads the response as an httpapi.Message, and
// wraps it in a codersdk.Error type for easy marshaling.
func readBodyAsError(res *http.Response) error {

View File

@ -188,7 +188,7 @@ func (c *Client) ListenWorkspaceAgent(ctx context.Context, logger slog.Logger) (
return agent.Metadata{}, nil, xerrors.Errorf("create cookie jar: %w", err)
}
jar.SetCookies(serverURL, []*http.Cookie{{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: c.SessionToken,
}})
httpClient := &http.Client{
@ -263,7 +263,7 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti
return nil, xerrors.Errorf("create cookie jar: %w", err)
}
jar.SetCookies(serverURL, []*http.Cookie{{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: c.SessionToken,
}})
httpClient := &http.Client{
@ -351,7 +351,7 @@ func (c *Client) WorkspaceAgentReconnectingPTY(ctx context.Context, agentID, rec
return nil, xerrors.Errorf("create cookie jar: %w", err)
}
jar.SetCookies(serverURL, []*http.Cookie{{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: c.SessionToken,
}})
httpClient := &http.Client{

View File

@ -9,6 +9,8 @@ import (
"github.com/google/uuid"
"golang.org/x/xerrors"
"nhooyr.io/websocket"
"nhooyr.io/websocket/wsjson"
"github.com/coder/coder/coderd/database"
)
@ -98,6 +100,36 @@ func (c *Client) WorkspaceBuildByName(ctx context.Context, workspace uuid.UUID,
return workspaceBuild, json.NewDecoder(res.Body).Decode(&workspaceBuild)
}
func (c *Client) WatchWorkspace(ctx context.Context, id uuid.UUID) (<-chan Workspace, error) {
conn, err := c.dialWebsocket(ctx, fmt.Sprintf("/api/v2/workspaces/%s/watch", id))
if err != nil {
return nil, err
}
wc := make(chan Workspace, 256)
go func() {
defer close(wc)
defer conn.Close(websocket.StatusNormalClosure, "")
for {
select {
case <-ctx.Done():
return
default:
var ws Workspace
err := wsjson.Read(ctx, conn, &ws)
if err != nil {
conn.Close(websocket.StatusInternalError, "failed to read workspace")
return
}
wc <- ws
}
}
}()
return wc, nil
}
// UpdateWorkspaceAutostartRequest is a request to update a workspace's autostart schedule.
type UpdateWorkspaceAutostartRequest struct {
Schedule string `json:"schedule"`