Skip to content

Commit a815a0f

Browse files
authored
Merge branch 'main' into joshvee-websocket-headers
2 parents 27f2fa6 + 3cf235c commit a815a0f

Some content is hidden

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

47 files changed

+1349
-621
lines changed

coderd/apidoc/docs.go

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/coderd.go

+4
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ func New(options *Options) *API {
175175
if options.AgentInactiveDisconnectTimeout == 0 {
176176
// Multiply the update by two to allow for some lag-time.
177177
options.AgentInactiveDisconnectTimeout = options.AgentConnectionUpdateFrequency * 2
178+
// Set a minimum timeout to avoid disconnecting too soon.
179+
if options.AgentInactiveDisconnectTimeout < 2*time.Second {
180+
options.AgentInactiveDisconnectTimeout = 2 * time.Second
181+
}
178182
}
179183
if options.AgentStatsRefreshInterval == 0 {
180184
options.AgentStatsRefreshInterval = 5 * time.Minute

coderd/coderdtest/coderdtest.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ func NewOptions(t *testing.T, options *Options) (func(http.Handler), context.Can
258258
stunAddr, stunCleanup := stuntest.ServeWithPacketListener(t, nettype.Std{})
259259
t.Cleanup(stunCleanup)
260260

261-
derpServer := derp.NewServer(key.NewNode(), tailnet.Logger(slogtest.Make(t, nil).Named("derp")))
261+
derpServer := derp.NewServer(key.NewNode(), tailnet.Logger(slogtest.Make(t, nil).Named("derp").Leveled(slog.LevelDebug)))
262262
derpServer.SetMeshKey("test-key")
263263

264264
// match default with cli default

coderd/database/dbfake/databasefake.go

+1
Original file line numberDiff line numberDiff line change
@@ -2826,6 +2826,7 @@ func (q *fakeQuerier) InsertTemplateVersionParameter(_ context.Context, arg data
28262826
ValidationMax: arg.ValidationMax,
28272827
ValidationMonotonic: arg.ValidationMonotonic,
28282828
Required: arg.Required,
2829+
LegacyVariableName: arg.LegacyVariableName,
28292830
}
28302831
q.templateVersionParameters = append(q.templateVersionParameters, param)
28312832
return param, nil

coderd/database/dump.sql

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE template_version_parameters DROP COLUMN legacy_variable_name;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ALTER TABLE template_version_parameters ADD COLUMN legacy_variable_name text NOT NULL DEFAULT '';
2+
3+
COMMENT ON COLUMN template_version_parameters.legacy_variable_name IS 'Name of the legacy variable for migration purposes';

coderd/database/models.go

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

+14-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/templateversionparameters.sql

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ INSERT INTO
1414
validation_max,
1515
validation_error,
1616
validation_monotonic,
17-
required
17+
required,
18+
legacy_variable_name
1819
)
1920
VALUES
2021
(
@@ -31,7 +32,8 @@ VALUES
3132
$11,
3233
$12,
3334
$13,
34-
$14
35+
$14,
36+
$15
3537
) RETURNING *;
3638

3739
-- name: GetTemplateVersionParameters :many

coderd/database/queries/workspaceagentstats.sql

+2-1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ WITH agent_stats AS (
9292
WHERE workspace_agent_stats.created_at > $1 AND connection_median_latency_ms > 0 GROUP BY user_id, agent_id, workspace_id, template_id
9393
), latest_agent_stats AS (
9494
SELECT
95+
a.agent_id,
9596
coalesce(SUM(session_count_vscode), 0)::bigint AS session_count_vscode,
9697
coalesce(SUM(session_count_ssh), 0)::bigint AS session_count_ssh,
9798
coalesce(SUM(session_count_jetbrains), 0)::bigint AS session_count_jetbrains,
@@ -101,4 +102,4 @@ WITH agent_stats AS (
101102
FROM workspace_agent_stats WHERE created_at > $1
102103
) AS a WHERE a.rn = 1 GROUP BY a.user_id, a.agent_id, a.workspace_id, a.template_id
103104
)
104-
SELECT * FROM agent_stats, latest_agent_stats;
105+
SELECT * FROM agent_stats JOIN latest_agent_stats ON agent_stats.agent_id = latest_agent_stats.agent_id;

coderd/provisionerdserver/provisionerdserver.go

+1
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete
835835
ValidationMax: richParameter.ValidationMax,
836836
ValidationMonotonic: richParameter.ValidationMonotonic,
837837
Required: richParameter.Required,
838+
LegacyVariableName: richParameter.LegacyVariableName,
838839
})
839840
if err != nil {
840841
return nil, xerrors.Errorf("insert parameter: %w", err)

coderd/templateversions.go

+1
Original file line numberDiff line numberDiff line change
@@ -1622,6 +1622,7 @@ func convertTemplateVersionParameter(param database.TemplateVersionParameter) (c
16221622
ValidationError: param.ValidationError,
16231623
ValidationMonotonic: codersdk.ValidationMonotonicOrder(param.ValidationMonotonic),
16241624
Required: param.Required,
1625+
LegacyVariableName: param.LegacyVariableName,
16251626
}, nil
16261627
}
16271628

coderd/workspaceagents.go

+16-37
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package coderd
22

33
import (
4+
"bufio"
45
"context"
56
"database/sql"
67
"encoding/json"
@@ -428,51 +429,29 @@ func (api *API) dialWorkspaceAgentTailnet(r *http.Request, agentID uuid.UUID) (*
428429
ctx := r.Context()
429430
clientConn, serverConn := net.Pipe()
430431

431-
derpMap := api.DERPMap.Clone()
432-
for _, region := range derpMap.Regions {
433-
if !region.EmbeddedRelay {
434-
continue
435-
}
436-
var node *tailcfg.DERPNode
437-
for _, n := range region.Nodes {
438-
if n.STUNOnly {
439-
continue
440-
}
441-
node = n
442-
break
443-
}
444-
if node == nil {
445-
continue
446-
}
447-
// TODO: This should dial directly to execute the
448-
// DERP server instead of contacting localhost.
449-
//
450-
// This requires modification of Tailscale internals
451-
// to pipe through a proxy function per-region, so
452-
// this is an easy and mostly reliable hack for now.
453-
cloned := node.Clone()
454-
// Add p for proxy.
455-
// This first node supports TLS.
456-
cloned.Name += "p"
457-
cloned.IPv4 = "127.0.0.1"
458-
cloned.InsecureForTests = true
459-
region.Nodes = append(region.Nodes, cloned.Clone())
460-
// This second node forces HTTP.
461-
cloned.Name += "-http"
462-
cloned.ForceHTTP = true
463-
region.Nodes = append(region.Nodes, cloned)
464-
}
465-
466432
conn, err := tailnet.NewConn(&tailnet.Options{
467433
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)},
468-
DERPMap: derpMap,
434+
DERPMap: api.DERPMap,
469435
Logger: api.Logger.Named("tailnet"),
470436
})
471437
if err != nil {
472438
_ = clientConn.Close()
473439
_ = serverConn.Close()
474440
return nil, xerrors.Errorf("create tailnet conn: %w", err)
475441
}
442+
conn.SetDERPRegionDialer(func(_ context.Context, region *tailcfg.DERPRegion) net.Conn {
443+
if !region.EmbeddedRelay {
444+
return nil
445+
}
446+
left, right := net.Pipe()
447+
go func() {
448+
defer left.Close()
449+
defer right.Close()
450+
brw := bufio.NewReadWriter(bufio.NewReader(right), bufio.NewWriter(right))
451+
api.DERPServer.Accept(ctx, right, brw, r.RemoteAddr)
452+
}()
453+
return left
454+
})
476455

477456
sendNodes, _ := tailnet.ServeCoordinator(clientConn, func(node []*tailnet.Node) error {
478457
err = conn.UpdateNodes(node, true)
@@ -615,7 +594,7 @@ func (api *API) workspaceAgentCoordinate(rw http.ResponseWriter, r *http.Request
615594

616595
// We use a custom heartbeat routine here instead of `httpapi.Heartbeat`
617596
// because we want to log the agent's last ping time.
618-
var lastPing time.Time
597+
lastPing := time.Now() // Since the agent initiated the request, assume it's alive.
619598
var pingMu sync.Mutex
620599
go pprof.Do(ctx, pprof.Labels("agent", workspaceAgent.ID.String()), func(ctx context.Context) {
621600
// TODO(mafredri): Is this too frequent? Use separate ping disconnect timeout?

coderd/workspacebuilds.go

+33-20
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,39 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
496496
}
497497
apiLastBuildParameters := convertWorkspaceBuildParameters(lastBuildParameters)
498498

499+
legacyParameters, err := api.Database.ParameterValues(ctx, database.ParameterValuesParams{
500+
Scopes: []database.ParameterScope{database.ParameterScopeWorkspace},
501+
ScopeIds: []uuid.UUID{workspace.ID},
502+
})
503+
if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
504+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
505+
Message: "Error fetching previous legacy parameters.",
506+
Detail: err.Error(),
507+
})
508+
return
509+
}
510+
511+
// Rich parameters migration: include legacy variables to the last build parameters
512+
for _, templateVersionParameter := range templateVersionParameters {
513+
// Check if parameter is defined in previous build
514+
if _, found := findWorkspaceBuildParameter(apiLastBuildParameters, templateVersionParameter.Name); found {
515+
continue
516+
}
517+
518+
// Check if legacy variable is defined
519+
for _, legacyParameter := range legacyParameters {
520+
if legacyParameter.Name != templateVersionParameter.LegacyVariableName {
521+
continue
522+
}
523+
524+
apiLastBuildParameters = append(apiLastBuildParameters, codersdk.WorkspaceBuildParameter{
525+
Name: templateVersionParameter.Name,
526+
Value: legacyParameter.SourceValue,
527+
})
528+
break
529+
}
530+
}
531+
499532
err = codersdk.ValidateWorkspaceBuildParameters(templateVersionParameters, createBuild.RichParameterValues, apiLastBuildParameters)
500533
if err != nil {
501534
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
@@ -525,26 +558,6 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
525558
}
526559
}
527560

528-
legacyParameters, err := api.Database.ParameterValues(ctx, database.ParameterValuesParams{
529-
Scopes: []database.ParameterScope{database.ParameterScopeWorkspace},
530-
ScopeIds: []uuid.UUID{workspace.ID},
531-
})
532-
if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
533-
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
534-
Message: "Error fetching previous legacy parameters.",
535-
Detail: err.Error(),
536-
})
537-
return
538-
}
539-
540-
if createBuild.Transition == codersdk.WorkspaceTransitionStart &&
541-
len(legacyParameters) > 0 && len(parameters) > 0 {
542-
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
543-
Message: "Rich parameters can't be used together with legacy parameters.",
544-
})
545-
return
546-
}
547-
548561
var workspaceBuild database.WorkspaceBuild
549562
var provisionerJob database.ProvisionerJob
550563
// This must happen in a transaction to ensure history can be inserted, and

0 commit comments

Comments
 (0)