Skip to content

Commit 991db6d

Browse files
Merge remote-tracking branch 'origin/main' into yevhenii/secrets-prototype
2 parents 887f914 + dad033e commit 991db6d

File tree

121 files changed

+6943
-868
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+6943
-868
lines changed

.github/workflows/release.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,29 @@ jobs:
634634
- name: ls build
635635
run: ls -lh build
636636

637+
- name: Publish Coder CLI binaries and detached signatures to GCS
638+
if: ${{ !inputs.dry_run && github.ref == 'refs/heads/main' && github.repository_owner == 'coder'}}
639+
run: |
640+
set -euxo pipefail
641+
642+
version="$(./scripts/version.sh)"
643+
644+
binaries=(
645+
"coder-darwin-amd64"
646+
"coder-darwin-arm64"
647+
"coder-linux-amd64"
648+
"coder-linux-arm64"
649+
"coder-linux-armv7"
650+
"coder-windows-amd64.exe"
651+
"coder-windows-arm64.exe"
652+
)
653+
654+
for binary in "${binaries[@]}"; do
655+
detached_signature="${binary}.asc"
656+
gcloud storage cp "./site/out/bin/${binary}" "gs://releases.coder.com/coder-cli/${version}/${binary}"
657+
gcloud storage cp "./site/out/bin/${detached_signature}" "gs://releases.coder.com/coder-cli/${version}/${detached_signature}"
658+
done
659+
637660
- name: Publish release
638661
run: |
639662
set -euo pipefail

agent/agentcontainers/api_test.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,8 +2883,12 @@ func TestAPI(t *testing.T) {
28832883
Op: fsnotify.Write,
28842884
})
28852885

2886-
err = api.RefreshContainers(ctx)
2887-
require.NoError(t, err)
2886+
require.Eventuallyf(t, func() bool {
2887+
err = api.RefreshContainers(ctx)
2888+
require.NoError(t, err)
2889+
2890+
return len(fakeSAC.agents) == 1
2891+
}, testutil.WaitShort, testutil.IntervalFast, "subagent should be created after config change")
28882892

28892893
t.Log("Phase 2: Cont, waiting for sub agent to exit")
28902894
exitSubAgentOnce.Do(func() {
@@ -2919,8 +2923,12 @@ func TestAPI(t *testing.T) {
29192923
Op: fsnotify.Write,
29202924
})
29212925

2922-
err = api.RefreshContainers(ctx)
2923-
require.NoError(t, err)
2926+
require.Eventuallyf(t, func() bool {
2927+
err = api.RefreshContainers(ctx)
2928+
require.NoError(t, err)
2929+
2930+
return len(fakeSAC.agents) == 0
2931+
}, testutil.WaitShort, testutil.IntervalFast, "subagent should be deleted after config change")
29242932

29252933
req = httptest.NewRequest(http.MethodGet, "/", nil).WithContext(ctx)
29262934
rec = httptest.NewRecorder()

cli/delete_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,6 @@ func TestDelete(t *testing.T) {
233233
t.Skip("this test requires postgres")
234234
}
235235

236-
clock := quartz.NewMock(t)
237-
ctx := testutil.Context(t, testutil.WaitSuperLong)
238-
239236
// Setup
240237
db, pb := dbtestutil.NewDB(t, dbtestutil.WithDumpOnFailure())
241238
client, _ := coderdtest.NewWithProvisionerCloser(t, &coderdtest.Options{
@@ -301,6 +298,9 @@ func TestDelete(t *testing.T) {
301298
t.Run(tc.name, func(t *testing.T) {
302299
t.Parallel()
303300

301+
clock := quartz.NewMock(t)
302+
ctx := testutil.Context(t, testutil.WaitSuperLong)
303+
304304
// Create one prebuilt workspace (owned by system user) and one normal workspace (owned by a user)
305305
// Each workspace is persisted in the DB along with associated workspace jobs and builds.
306306
dbPrebuiltWorkspace := setupTestDBWorkspace(t, clock, db, pb, orgID, database.PrebuildsSystemUserID, template.ID, version.ID, preset.ID)

cli/testdata/coder_list_--output_json.golden

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
"automatic_updates": "never",
8787
"allow_renames": false,
8888
"favorite": false,
89-
"next_start_at": "====[timestamp]====="
89+
"next_start_at": "====[timestamp]=====",
90+
"is_prebuild": false
9091
}
9192
]

coderd/agentapi/api.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
agentproto "github.com/coder/coder/v2/agent/proto"
2020
"github.com/coder/coder/v2/coderd/agentapi/resourcesmonitor"
2121
"github.com/coder/coder/v2/coderd/appearance"
22-
"github.com/coder/coder/v2/coderd/audit"
22+
"github.com/coder/coder/v2/coderd/connectionlog"
2323
"github.com/coder/coder/v2/coderd/database"
2424
"github.com/coder/coder/v2/coderd/database/pubsub"
2525
"github.com/coder/coder/v2/coderd/externalauth"
@@ -50,7 +50,7 @@ type API struct {
5050
*ResourcesMonitoringAPI
5151
*LogsAPI
5252
*ScriptsAPI
53-
*AuditAPI
53+
*ConnLogAPI
5454
*SubAgentAPI
5555
*tailnet.DRPCService
5656

@@ -71,7 +71,7 @@ type Options struct {
7171
Database database.Store
7272
NotificationsEnqueuer notifications.Enqueuer
7373
Pubsub pubsub.Pubsub
74-
Auditor *atomic.Pointer[audit.Auditor]
74+
ConnectionLogger *atomic.Pointer[connectionlog.ConnectionLogger]
7575
DerpMapFn func() *tailcfg.DERPMap
7676
TailnetCoordinator *atomic.Pointer[tailnet.Coordinator]
7777
StatsReporter *workspacestats.Reporter
@@ -180,11 +180,11 @@ func New(opts Options) *API {
180180
Database: opts.Database,
181181
}
182182

183-
api.AuditAPI = &AuditAPI{
184-
AgentFn: api.agent,
185-
Auditor: opts.Auditor,
186-
Database: opts.Database,
187-
Log: opts.Log,
183+
api.ConnLogAPI = &ConnLogAPI{
184+
AgentFn: api.agent,
185+
ConnectionLogger: opts.ConnectionLogger,
186+
Database: opts.Database,
187+
Log: opts.Log,
188188
}
189189

190190
api.DRPCService = &tailnet.DRPCService{

coderd/agentapi/audit.go

Lines changed: 0 additions & 105 deletions
This file was deleted.

coderd/agentapi/connectionlog.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package agentapi
2+
3+
import (
4+
"context"
5+
"database/sql"
6+
"sync/atomic"
7+
8+
"github.com/google/uuid"
9+
"golang.org/x/xerrors"
10+
"google.golang.org/protobuf/types/known/emptypb"
11+
12+
"cdr.dev/slog"
13+
agentproto "github.com/coder/coder/v2/agent/proto"
14+
"github.com/coder/coder/v2/coderd/connectionlog"
15+
"github.com/coder/coder/v2/coderd/database"
16+
"github.com/coder/coder/v2/coderd/database/db2sdk"
17+
)
18+
19+
type ConnLogAPI struct {
20+
AgentFn func(context.Context) (database.WorkspaceAgent, error)
21+
ConnectionLogger *atomic.Pointer[connectionlog.ConnectionLogger]
22+
Database database.Store
23+
Log slog.Logger
24+
}
25+
26+
func (a *ConnLogAPI) ReportConnection(ctx context.Context, req *agentproto.ReportConnectionRequest) (*emptypb.Empty, error) {
27+
// We use the connection ID to identify which connection log event to mark
28+
// as closed, when we receive a close action for that ID.
29+
connectionID, err := uuid.FromBytes(req.GetConnection().GetId())
30+
if err != nil {
31+
return nil, xerrors.Errorf("connection id from bytes: %w", err)
32+
}
33+
34+
if connectionID == uuid.Nil {
35+
return nil, xerrors.New("connection ID cannot be nil")
36+
}
37+
action, err := db2sdk.ConnectionLogStatusFromAgentProtoConnectionAction(req.GetConnection().GetAction())
38+
if err != nil {
39+
return nil, err
40+
}
41+
connectionType, err := db2sdk.ConnectionLogConnectionTypeFromAgentProtoConnectionType(req.GetConnection().GetType())
42+
if err != nil {
43+
return nil, err
44+
}
45+
46+
var code sql.NullInt32
47+
if action == database.ConnectionStatusDisconnected {
48+
code = sql.NullInt32{
49+
Int32: req.GetConnection().GetStatusCode(),
50+
Valid: true,
51+
}
52+
}
53+
54+
// Fetch contextual data for this connection log event.
55+
workspaceAgent, err := a.AgentFn(ctx)
56+
if err != nil {
57+
return nil, xerrors.Errorf("get agent: %w", err)
58+
}
59+
workspace, err := a.Database.GetWorkspaceByAgentID(ctx, workspaceAgent.ID)
60+
if err != nil {
61+
return nil, xerrors.Errorf("get workspace by agent id: %w", err)
62+
}
63+
64+
reason := req.GetConnection().GetReason()
65+
connLogger := *a.ConnectionLogger.Load()
66+
err = connLogger.Upsert(ctx, database.UpsertConnectionLogParams{
67+
ID: uuid.New(),
68+
Time: req.GetConnection().GetTimestamp().AsTime(),
69+
OrganizationID: workspace.OrganizationID,
70+
WorkspaceOwnerID: workspace.OwnerID,
71+
WorkspaceID: workspace.ID,
72+
WorkspaceName: workspace.Name,
73+
AgentName: workspaceAgent.Name,
74+
Type: connectionType,
75+
Code: code,
76+
Ip: database.ParseIP(req.GetConnection().GetIp()),
77+
ConnectionID: uuid.NullUUID{
78+
UUID: connectionID,
79+
Valid: true,
80+
},
81+
DisconnectReason: sql.NullString{
82+
String: reason,
83+
Valid: reason != "",
84+
},
85+
// We supply the action:
86+
// - So the DB can handle duplicate connections or disconnections properly.
87+
// - To make it clear whether this is a connection or disconnection
88+
// prior to it's insertion into the DB (logs)
89+
ConnectionStatus: action,
90+
91+
// It's not possible to tell which user connected. Once we have
92+
// the capability, this may be reported by the agent.
93+
UserID: uuid.NullUUID{
94+
Valid: false,
95+
},
96+
// N/A
97+
UserAgent: sql.NullString{},
98+
// N/A
99+
SlugOrPort: sql.NullString{},
100+
})
101+
if err != nil {
102+
return nil, xerrors.Errorf("export connection log: %w", err)
103+
}
104+
105+
return &emptypb.Empty{}, nil
106+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy