fix: add missing route for codersdk.PostLogSource (#13421)

This commit is contained in:
Colin Adler
2024-06-03 12:29:50 -05:00
committed by GitHub
parent 8cdd468107
commit 9d00a26a90
10 changed files with 269 additions and 4 deletions
+54
View File
@@ -5871,6 +5871,45 @@ const docTemplate = `{
}
}
},
"/workspaceagents/me/log-source": {
"post": {
"security": [
{
"CoderSessionToken": []
}
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Agents"
],
"summary": "Post workspace agent log source",
"operationId": "post-workspace-agent-log-source",
"parameters": [
{
"description": "Log source request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/agentsdk.PostLogSourceRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.WorkspaceAgentLogSource"
}
}
}
}
},
"/workspaceagents/me/logs": {
"patch": {
"security": [
@@ -8112,6 +8151,21 @@ const docTemplate = `{
}
}
},
"agentsdk.PostLogSourceRequest": {
"type": "object",
"properties": {
"display_name": {
"type": "string"
},
"icon": {
"type": "string"
},
"id": {
"description": "ID is a unique identifier for the log source.\nIt is scoped to a workspace agent, and can be statically\ndefined inside code to prevent duplicate sources from being\ncreated for the same agent.",
"type": "string"
}
}
},
"agentsdk.PostMetadataRequest": {
"type": "object",
"properties": {
+48
View File
@@ -5179,6 +5179,39 @@
}
}
},
"/workspaceagents/me/log-source": {
"post": {
"security": [
{
"CoderSessionToken": []
}
],
"consumes": ["application/json"],
"produces": ["application/json"],
"tags": ["Agents"],
"summary": "Post workspace agent log source",
"operationId": "post-workspace-agent-log-source",
"parameters": [
{
"description": "Log source request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/agentsdk.PostLogSourceRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.WorkspaceAgentLogSource"
}
}
}
}
},
"/workspaceagents/me/logs": {
"patch": {
"security": [
@@ -7184,6 +7217,21 @@
}
}
},
"agentsdk.PostLogSourceRequest": {
"type": "object",
"properties": {
"display_name": {
"type": "string"
},
"icon": {
"type": "string"
},
"id": {
"description": "ID is a unique identifier for the log source.\nIt is scoped to a workspace agent, and can be statically\ndefined inside code to prevent duplicate sources from being\ncreated for the same agent.",
"type": "string"
}
}
},
"agentsdk.PostMetadataRequest": {
"type": "object",
"properties": {
+1 -1
View File
@@ -128,7 +128,7 @@ func TestGenerate(t *testing.T) {
// Assert that the hashed secret is correct.
hashed := sha256.Sum256([]byte(keytokens[1]))
assert.ElementsMatch(t, hashed, key.HashedSecret[:])
assert.ElementsMatch(t, hashed, key.HashedSecret)
assert.Equal(t, tc.params.UserID, key.UserID)
assert.WithinDuration(t, dbtime.Now(), key.CreatedAt, time.Second*5)
+1
View File
@@ -1021,6 +1021,7 @@ func New(options *Options) *API {
r.Post("/report-lifecycle", api.workspaceAgentReportLifecycle)
r.Post("/metadata", api.workspaceAgentPostMetadata)
r.Post("/metadata/{key}", api.workspaceAgentPostMetadataDeprecated)
r.Post("/log-source", api.workspaceAgentPostLogSource)
})
r.Route("/{workspaceagent}", func(r chi.Router) {
r.Use(
+50
View File
@@ -1084,6 +1084,56 @@ func (api *API) workspaceAgentClientCoordinate(rw http.ResponseWriter, r *http.R
}
}
// @Summary Post workspace agent log source
// @ID post-workspace-agent-log-source
// @Security CoderSessionToken
// @Accept json
// @Produce json
// @Tags Agents
// @Param request body agentsdk.PostLogSourceRequest true "Log source request"
// @Success 200 {object} codersdk.WorkspaceAgentLogSource
// @Router /workspaceagents/me/log-source [post]
func (api *API) workspaceAgentPostLogSource(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var req agentsdk.PostLogSourceRequest
if !httpapi.Read(ctx, rw, r, &req) {
return
}
workspaceAgent := httpmw.WorkspaceAgent(r)
sources, err := api.Database.InsertWorkspaceAgentLogSources(ctx, database.InsertWorkspaceAgentLogSourcesParams{
WorkspaceAgentID: workspaceAgent.ID,
CreatedAt: dbtime.Now(),
ID: []uuid.UUID{req.ID},
DisplayName: []string{req.DisplayName},
Icon: []string{req.Icon},
})
if err != nil {
if database.IsUniqueViolation(err, "workspace_agent_log_sources_pkey") {
httpapi.Write(ctx, rw, http.StatusCreated, codersdk.WorkspaceAgentLogSource{
WorkspaceAgentID: workspaceAgent.ID,
CreatedAt: dbtime.Now(),
ID: req.ID,
DisplayName: req.DisplayName,
Icon: req.Icon,
})
return
}
httpapi.InternalServerError(rw, err)
return
}
if len(sources) != 1 {
httpapi.InternalServerError(rw, xerrors.Errorf("database should've returned 1 row, got %d", len(sources)))
return
}
apiSource := convertLogSources(sources)[0]
httpapi.Write(ctx, rw, http.StatusCreated, apiSource)
}
// convertProvisionedApps converts applications that are in the middle of provisioning process.
// It means that they may not have an agent or workspace assigned (dry-run job).
func convertProvisionedApps(dbApps []database.WorkspaceApp) []codersdk.WorkspaceApp {
+42
View File
@@ -921,6 +921,48 @@ func TestWorkspaceAgentAppHealth(t *testing.T) {
require.EqualValues(t, codersdk.WorkspaceAppHealthUnhealthy, manifest.Apps[1].Health)
}
func TestWorkspaceAgentPostLogSource(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitShort)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
agentClient := agentsdk.New(client.URL)
agentClient.SetSessionToken(r.AgentToken)
req := agentsdk.PostLogSourceRequest{
ID: uuid.New(),
DisplayName: "colin logs",
Icon: "/emojis/1f42e.png",
}
res, err := agentClient.PostLogSource(ctx, req)
require.NoError(t, err)
assert.Equal(t, req.ID, res.ID)
assert.Equal(t, req.DisplayName, res.DisplayName)
assert.Equal(t, req.Icon, res.Icon)
assert.NotZero(t, res.WorkspaceAgentID)
assert.NotZero(t, res.CreatedAt)
// should be idempotent
res, err = agentClient.PostLogSource(ctx, req)
require.NoError(t, err)
assert.Equal(t, req.ID, res.ID)
assert.Equal(t, req.DisplayName, res.DisplayName)
assert.Equal(t, req.Icon, res.Icon)
assert.NotZero(t, res.WorkspaceAgentID)
assert.NotZero(t, res.CreatedAt)
})
}
// TestWorkspaceAgentReportStats tests the legacy (agent API v1) report stats endpoint.
func TestWorkspaceAgentReportStats(t *testing.T) {
t.Parallel()
+1 -1
View File
@@ -573,7 +573,7 @@ func (s *Server) proxyWorkspaceApp(rw http.ResponseWriter, r *http.Request, appT
}
// This strips the session token from a workspace app request.
cookieHeaders := r.Header.Values("Cookie")[:]
cookieHeaders := r.Header.Values("Cookie")
r.Header.Del("Cookie")
for _, cookieHeader := range cookieHeaders {
r.Header.Add("Cookie", httpapi.StripCoderCookies(cookieHeader))
+2 -2
View File
@@ -533,7 +533,7 @@ func (c *Client) PatchLogs(ctx context.Context, req PatchLogs) error {
return nil
}
type PostLogSource struct {
type PostLogSourceRequest struct {
// ID is a unique identifier for the log source.
// It is scoped to a workspace agent, and can be statically
// defined inside code to prevent duplicate sources from being
@@ -543,7 +543,7 @@ type PostLogSource struct {
Icon string `json:"icon"`
}
func (c *Client) PostLogSource(ctx context.Context, req PostLogSource) (codersdk.WorkspaceAgentLogSource, error) {
func (c *Client) PostLogSource(ctx context.Context, req PostLogSourceRequest) (codersdk.WorkspaceAgentLogSource, error) {
res, err := c.SDK.Request(ctx, http.MethodPost, "/api/v2/workspaceagents/me/log-source", req)
if err != nil {
return codersdk.WorkspaceAgentLogSource{}, err
+52
View File
@@ -341,6 +341,58 @@ curl -X GET http://coder-server:8080/api/v2/workspaceagents/me/gitsshkey \
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Post workspace agent log source
### Code samples
```shell
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/workspaceagents/me/log-source \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`POST /workspaceagents/me/log-source`
> Body parameter
```json
{
"display_name": "string",
"icon": "string",
"id": "string"
}
```
### Parameters
| Name | In | Type | Required | Description |
| ------ | ---- | ------------------------------------------------------------------------ | -------- | ------------------ |
| `body` | body | [agentsdk.PostLogSourceRequest](schemas.md#agentsdkpostlogsourcerequest) | true | Log source request |
### Example responses
> 200 Response
```json
{
"created_at": "2019-08-24T14:15:22Z",
"display_name": "string",
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
}
```
### Responses
| Status | Meaning | Description | Schema |
| ------ | ------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------ |
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.WorkspaceAgentLogSource](schemas.md#codersdkworkspaceagentlogsource) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Patch workspace agent logs
### Code samples
+18
View File
@@ -403,6 +403,24 @@
| `changed_at` | string | false | | |
| `state` | [codersdk.WorkspaceAgentLifecycle](#codersdkworkspaceagentlifecycle) | false | | |
## agentsdk.PostLogSourceRequest
```json
{
"display_name": "string",
"icon": "string",
"id": "string"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
| -------------- | ------ | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `display_name` | string | false | | |
| `icon` | string | false | | |
| `id` | string | false | | ID is a unique identifier for the log source. It is scoped to a workspace agent, and can be statically defined inside code to prevent duplicate sources from being created for the same agent. |
## agentsdk.PostMetadataRequest
```json