Skip to content

Commit 8ed7cf8

Browse files
committed
Merge remote-tracking branch 'origin/main' into stevenmasley/fix_offset
2 parents 89aa6cc + ab764db commit 8ed7cf8

Some content is hidden

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

63 files changed

+1350
-1533
lines changed

cli/agent_test.go

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,8 @@ func TestWorkspaceAgent(t *testing.T) {
3131
})
3232
user := coderdtest.CreateFirstUser(t, client)
3333
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
34-
Parse: echo.ParseComplete,
35-
ProvisionApply: []*proto.Provision_Response{{
36-
Type: &proto.Provision_Response_Complete{
37-
Complete: &proto.Provision_Complete{
38-
Resources: []*proto.Resource{{
39-
Name: "somename",
40-
Type: "someinstance",
41-
Agents: []*proto.Agent{{
42-
Id: uuid.NewString(),
43-
Name: "someagent",
44-
Auth: &proto.Agent_Token{
45-
Token: authToken,
46-
},
47-
}},
48-
}},
49-
},
50-
},
51-
}},
34+
Parse: echo.ParseComplete,
35+
ProvisionApply: echo.ProvisionApplyWithAgent(authToken),
5236
})
5337
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
5438
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)

cli/configssh_test.go

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -94,23 +94,7 @@ func TestConfigSSH(t *testing.T) {
9494
},
9595
},
9696
}},
97-
ProvisionApply: []*proto.Provision_Response{{
98-
Type: &proto.Provision_Response_Complete{
99-
Complete: &proto.Provision_Complete{
100-
Resources: []*proto.Resource{{
101-
Name: "example",
102-
Type: "aws_instance",
103-
Agents: []*proto.Agent{{
104-
Id: uuid.NewString(),
105-
Name: "example",
106-
Auth: &proto.Agent_Token{
107-
Token: authToken,
108-
},
109-
}},
110-
}},
111-
},
112-
},
113-
}},
97+
ProvisionApply: echo.ProvisionApplyWithAgent(authToken),
11498
})
11599
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
116100
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)

cli/gitssh_test.go

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"github.com/coder/coder/coderd/coderdtest"
2525
"github.com/coder/coder/codersdk"
2626
"github.com/coder/coder/provisioner/echo"
27-
"github.com/coder/coder/provisionersdk/proto"
2827
"github.com/coder/coder/pty/ptytest"
2928
"github.com/coder/coder/testutil"
3029
)
@@ -48,23 +47,9 @@ func prepareTestGitSSH(ctx context.Context, t *testing.T) (*codersdk.Client, str
4847
// setup template
4948
agentToken := uuid.NewString()
5049
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
51-
Parse: echo.ParseComplete,
52-
ProvisionPlan: echo.ProvisionComplete,
53-
ProvisionApply: []*proto.Provision_Response{{
54-
Type: &proto.Provision_Response_Complete{
55-
Complete: &proto.Provision_Complete{
56-
Resources: []*proto.Resource{{
57-
Name: "somename",
58-
Type: "someinstance",
59-
Agents: []*proto.Agent{{
60-
Auth: &proto.Agent_Token{
61-
Token: agentToken,
62-
},
63-
}},
64-
}},
65-
},
66-
},
67-
}},
50+
Parse: echo.ParseComplete,
51+
ProvisionPlan: echo.ProvisionComplete,
52+
ProvisionApply: echo.ProvisionApplyWithAgent(agentToken),
6853
})
6954
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
7055
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)

cli/portforward_test.go

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"github.com/coder/coder/coderd/coderdtest"
1818
"github.com/coder/coder/codersdk"
1919
"github.com/coder/coder/provisioner/echo"
20-
"github.com/coder/coder/provisionersdk/proto"
2120
"github.com/coder/coder/pty/ptytest"
2221
"github.com/coder/coder/testutil"
2322
)
@@ -293,23 +292,9 @@ func runAgent(t *testing.T, client *codersdk.Client, userID uuid.UUID) codersdk.
293292
// Setup template
294293
agentToken := uuid.NewString()
295294
version := coderdtest.CreateTemplateVersion(t, client, orgID, &echo.Responses{
296-
Parse: echo.ParseComplete,
297-
ProvisionPlan: echo.ProvisionComplete,
298-
ProvisionApply: []*proto.Provision_Response{{
299-
Type: &proto.Provision_Response_Complete{
300-
Complete: &proto.Provision_Complete{
301-
Resources: []*proto.Resource{{
302-
Name: "somename",
303-
Type: "someinstance",
304-
Agents: []*proto.Agent{{
305-
Auth: &proto.Agent_Token{
306-
Token: agentToken,
307-
},
308-
}},
309-
}},
310-
},
311-
},
312-
}},
295+
Parse: echo.ParseComplete,
296+
ProvisionPlan: echo.ProvisionComplete,
297+
ProvisionApply: echo.ProvisionApplyWithAgent(agentToken),
313298
})
314299

315300
// Create template and workspace

cli/root.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -334,14 +334,14 @@ func createUnauthenticatedClient(cmd *cobra.Command, serverURL *url.URL) (*coder
334334
}
335335
transport := &headerTransport{
336336
transport: http.DefaultTransport,
337-
headers: map[string]string{},
337+
header: http.Header{},
338338
}
339339
for _, header := range headers {
340340
parts := strings.SplitN(header, "=", 2)
341341
if len(parts) < 2 {
342342
return nil, xerrors.Errorf("split header %q had less than two parts", header)
343343
}
344-
transport.headers[parts[0]] = parts[1]
344+
transport.header.Add(parts[0], parts[1])
345345
}
346346
client.HTTPClient.Transport = transport
347347
return client, nil
@@ -655,12 +655,18 @@ func checkWarnings(cmd *cobra.Command, client *codersdk.Client) error {
655655

656656
type headerTransport struct {
657657
transport http.RoundTripper
658-
headers map[string]string
658+
header http.Header
659+
}
660+
661+
func (h *headerTransport) Header() http.Header {
662+
return h.header.Clone()
659663
}
660664

661665
func (h *headerTransport) RoundTrip(req *http.Request) (*http.Response, error) {
662-
for k, v := range h.headers {
663-
req.Header.Add(k, v)
666+
for k, v := range h.header {
667+
for _, vv := range v {
668+
req.Header.Add(k, vv)
669+
}
664670
}
665671
return h.transport.RoundTrip(req)
666672
}

cli/scaletest.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,8 @@ func scaletestCleanup() *cobra.Command {
330330
client.HTTPClient = &http.Client{
331331
Transport: &headerTransport{
332332
transport: http.DefaultTransport,
333-
headers: map[string]string{
334-
codersdk.BypassRatelimitHeader: "true",
333+
header: map[string][]string{
334+
codersdk.BypassRatelimitHeader: {"true"},
335335
},
336336
},
337337
}
@@ -515,8 +515,8 @@ It is recommended that all rate limits are disabled on the server before running
515515
client.HTTPClient = &http.Client{
516516
Transport: &headerTransport{
517517
transport: http.DefaultTransport,
518-
headers: map[string]string{
519-
codersdk.BypassRatelimitHeader: "true",
518+
header: map[string][]string{
519+
codersdk.BypassRatelimitHeader: {"true"},
520520
},
521521
},
522522
}

cli/server.go

Lines changed: 15 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ import (
8585
"github.com/coder/coder/provisionersdk"
8686
sdkproto "github.com/coder/coder/provisionersdk/proto"
8787
"github.com/coder/coder/tailnet"
88+
"github.com/coder/wgtunnel/tunnelsdk"
8889
)
8990

9091
// ReadGitAuthProvidersFromEnv is provided for compatibility purposes with the
@@ -538,34 +539,25 @@ flags, and YAML configuration. The precedence is as follows:
538539
return xerrors.Errorf("configure http client: %w", err)
539540
}
540541

541-
var (
542-
ctxTunnel, closeTunnel = context.WithCancel(ctx)
543-
tunnel *devtunnel.Tunnel
544-
tunnelErr <-chan error
545-
)
546-
defer closeTunnel()
547-
548542
// If the access URL is empty, we attempt to run a reverse-proxy
549543
// tunnel to make the initial setup really simple.
544+
var (
545+
tunnel *tunnelsdk.Tunnel
546+
tunnelDone <-chan struct{} = make(chan struct{}, 1)
547+
)
550548
if cfg.AccessURL.String() == "" {
551549
cmd.Printf("Opening tunnel so workspaces can connect to your deployment. For production scenarios, specify an external access URL\n")
552-
tunnel, tunnelErr, err = devtunnel.New(ctxTunnel, logger.Named("devtunnel"))
550+
tunnel, err = devtunnel.New(ctx, logger.Named("devtunnel"), cfg.WgtunnelHost.String())
553551
if err != nil {
554552
return xerrors.Errorf("create tunnel: %w", err)
555553
}
556-
err = cfg.AccessURL.Set(tunnel.URL)
557-
if err != nil {
558-
return xerrors.Errorf("set access url: %w", err)
559-
}
554+
defer tunnel.Close()
555+
tunnelDone = tunnel.Wait()
556+
cfg.AccessURL = clibase.URL(*tunnel.URL)
560557

561558
if cfg.WildcardAccessURL.String() == "" {
562-
u, err := parseURL(tunnel.URL)
563-
if err != nil {
564-
return xerrors.Errorf("parse tunnel url: %w", err)
565-
}
566-
567559
// Suffixed wildcard access URL.
568-
u, err = url.Parse(fmt.Sprintf("*--%s", u.Hostname()))
560+
u, err := url.Parse(fmt.Sprintf("*--%s", tunnel.URL.Hostname()))
569561
if err != nil {
570562
return xerrors.Errorf("parse wildcard url: %w", err)
571563
}
@@ -796,6 +788,7 @@ flags, and YAML configuration. The precedence is as follows:
796788
AllowSignups: cfg.OIDC.AllowSignups.Value(),
797789
UsernameField: cfg.OIDC.UsernameField.String(),
798790
GroupField: cfg.OIDC.GroupField.String(),
791+
GroupMapping: cfg.OIDC.GroupMapping.Value,
799792
SignInText: cfg.OIDC.SignInText.String(),
800793
IconURL: cfg.OIDC.IconURL.String(),
801794
IgnoreEmailVerified: cfg.OIDC.IgnoreEmailVerified.Value(),
@@ -1089,10 +1082,8 @@ flags, and YAML configuration. The precedence is as follows:
10891082
_, _ = fmt.Fprintln(cmd.OutOrStdout(), cliui.Styles.Bold.Render(
10901083
"Interrupt caught, gracefully exiting. Use ctrl+\\ to force quit",
10911084
))
1092-
case exitErr = <-tunnelErr:
1093-
if exitErr == nil {
1094-
exitErr = xerrors.New("dev tunnel closed unexpectedly")
1095-
}
1085+
case <-tunnelDone:
1086+
exitErr = xerrors.New("dev tunnel closed unexpectedly")
10961087
case exitErr = <-errCh:
10971088
}
10981089
if exitErr != nil && !xerrors.Is(exitErr, context.Canceled) {
@@ -1161,8 +1152,8 @@ flags, and YAML configuration. The precedence is as follows:
11611152
// Close tunnel after we no longer have in-flight connections.
11621153
if tunnel != nil {
11631154
cmd.Println("Waiting for tunnel to close...")
1164-
closeTunnel()
1165-
<-tunnelErr
1155+
_ = tunnel.Close()
1156+
<-tunnel.Wait()
11661157
cmd.Println("Done waiting for tunnel")
11671158
}
11681159

@@ -1240,22 +1231,6 @@ flags, and YAML configuration. The precedence is as follows:
12401231
return root
12411232
}
12421233

1243-
// parseURL parses a string into a URL.
1244-
func parseURL(u string) (*url.URL, error) {
1245-
hasScheme := strings.HasPrefix(u, "http:") || strings.HasPrefix(u, "https:")
1246-
1247-
if !hasScheme {
1248-
return nil, xerrors.Errorf("URL %q must have a scheme of either http or https", u)
1249-
}
1250-
1251-
parsed, err := url.Parse(u)
1252-
if err != nil {
1253-
return nil, err
1254-
}
1255-
1256-
return parsed, nil
1257-
}
1258-
12591234
// isLocalURL returns true if the hostname of the provided URL appears to
12601235
// resolve to a loopback address.
12611236
func isLocalURL(ctx context.Context, u *url.URL) (bool, error) {

coderd/apidoc/docs.go

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/coderd.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,12 @@ func New(options *Options) *API {
223223
options.SSHConfig.HostnamePrefix = "coder."
224224
}
225225
if options.SetUserGroups == nil {
226-
options.SetUserGroups = func(context.Context, database.Store, uuid.UUID, []string) error { return nil }
226+
options.SetUserGroups = func(ctx context.Context, _ database.Store, id uuid.UUID, groups []string) error {
227+
options.Logger.Warn(ctx, "attempted to assign OIDC groups without enterprise license",
228+
slog.F("id", id), slog.F("groups", groups),
229+
)
230+
return nil
231+
}
227232
}
228233
if options.TemplateScheduleStore == nil {
229234
options.TemplateScheduleStore = schedule.NewAGPLTemplateScheduleStore()

coderd/database/db.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,42 @@ func (q *sqlQuerier) Ping(ctx context.Context) (time.Duration, error) {
6767
return time.Since(start), err
6868
}
6969

70-
// InTx performs database operations inside a transaction.
7170
func (q *sqlQuerier) InTx(function func(Store) error, txOpts *sql.TxOptions) error {
71+
_, inTx := q.db.(*sqlx.Tx)
72+
isolation := sql.LevelDefault
73+
if txOpts != nil {
74+
isolation = txOpts.Isolation
75+
}
76+
77+
// If we are not already in a transaction, and we are running in serializable
78+
// mode, we need to run the transaction in a retry loop. The caller should be
79+
// prepared to allow retries if using serializable mode.
80+
// If we are in a transaction already, the parent InTx call will handle the retry.
81+
// We do not want to duplicate those retries.
82+
if !inTx && isolation == sql.LevelSerializable {
83+
// This is an arbitrarily chosen number.
84+
const retryAmount = 3
85+
var err error
86+
attempts := 0
87+
for attempts = 0; attempts < retryAmount; attempts++ {
88+
err = q.runTx(function, txOpts)
89+
if err == nil {
90+
// Transaction succeeded.
91+
return nil
92+
}
93+
if err != nil && !IsSerializedError(err) {
94+
// We should only retry if the error is a serialization error.
95+
return err
96+
}
97+
}
98+
// Transaction kept failing in serializable mode.
99+
return xerrors.Errorf("transaction failed after %d attempts: %w", attempts, err)
100+
}
101+
return q.runTx(function, txOpts)
102+
}
103+
104+
// InTx performs database operations inside a transaction.
105+
func (q *sqlQuerier) runTx(function func(Store) error, txOpts *sql.TxOptions) error {
72106
if _, ok := q.db.(*sqlx.Tx); ok {
73107
// If the current inner "db" is already a transaction, we just reuse it.
74108
// We do not need to handle commit/rollback as the outer tx will handle

0 commit comments

Comments
 (0)