diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2314763cae0e2..83f99c766caac 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -183,6 +183,9 @@ jobs: - name: Setup sqlc uses: ./.github/actions/setup-sqlc + - name: Setup Terraform + uses: ./.github/actions/setup-tf + - name: go install tools run: | go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30 diff --git a/Makefile b/Makefile index dd31c10fff810..71409d4d8d49b 100644 --- a/Makefile +++ b/Makefile @@ -489,6 +489,7 @@ gen: \ coderd/apidoc/swagger.json \ .prettierignore.include \ .prettierignore \ + provisioner/terraform/testdata/version \ site/.prettierrc.yaml \ site/.prettierignore \ site/.eslintignore \ @@ -674,6 +675,12 @@ provisioner/terraform/testdata/.gen-golden: $(wildcard provisioner/terraform/tes go test ./provisioner/terraform -run="Test.*Golden$$" -update touch "$@" +provisioner/terraform/testdata/version: + if [[ "$(shell cat provisioner/terraform/testdata/version.txt)" != "$(shell terraform version -json | jq -r '.terraform_version')" ]]; then + ./provisioner/terraform/testdata/generate.sh + fi +.PHONY: provisioner/terraform/testdata/version + scripts/ci-report/testdata/.gen-golden: $(wildcard scripts/ci-report/testdata/*) $(wildcard scripts/ci-report/*.go) go test ./scripts/ci-report -run=TestOutputMatchesGoldenFile -update touch "$@" diff --git a/cli/login.go b/cli/login.go index dfba4f3b4cfb0..20b550838dd86 100644 --- a/cli/login.go +++ b/cli/login.go @@ -239,7 +239,7 @@ func (r *RootCmd) login() *serpent.Command { if !inv.ParsedFlags().Changed("first-user-trial") && os.Getenv(firstUserTrialEnv) == "" { v, _ := cliui.Prompt(inv, cliui.PromptOptions{ - Text: "Start a 30-day trial of Enterprise?", + Text: "Start a trial of Enterprise?", IsConfirm: true, Default: "yes", }) diff --git a/cli/server.go b/cli/server.go index e96c8cacdc744..612972014fbb7 100644 --- a/cli/server.go +++ b/cli/server.go @@ -796,31 +796,18 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd. cliui.Infof(inv.Stdout, "\n==> Logs will stream in below (press ctrl+c to gracefully exit):") if vals.Telemetry.Enable { - gitAuth := make([]telemetry.GitAuth, 0) - // TODO: - var gitAuthConfigs []codersdk.ExternalAuthConfig - for _, cfg := range gitAuthConfigs { - gitAuth = append(gitAuth, telemetry.GitAuth{ - Type: cfg.Type, - }) + vals, err := vals.WithoutSecrets() + if err != nil { + return xerrors.Errorf("remove secrets from deployment values: %w", err) } - options.Telemetry, err = telemetry.New(telemetry.Options{ - BuiltinPostgres: builtinPostgres, - DeploymentID: deploymentID, - Database: options.Database, - Logger: logger.Named("telemetry"), - URL: vals.Telemetry.URL.Value(), - Wildcard: vals.WildcardAccessURL.String() != "", - DERPServerRelayURL: vals.DERP.Server.RelayURL.String(), - GitAuth: gitAuth, - GitHubOAuth: vals.OAuth2.Github.ClientID != "", - OIDCAuth: vals.OIDC.ClientID != "", - OIDCIssuerURL: vals.OIDC.IssuerURL.String(), - Prometheus: vals.Prometheus.Enable.Value(), - STUN: len(vals.DERP.Server.STUNAddresses) != 0, - Tunnel: tunnel != nil, - Experiments: vals.Experiments.Value(), + BuiltinPostgres: builtinPostgres, + DeploymentID: deploymentID, + Database: options.Database, + Logger: logger.Named("telemetry"), + URL: vals.Telemetry.URL.Value(), + Tunnel: tunnel != nil, + DeploymentConfig: vals, ParseLicenseJWT: func(lic *telemetry.License) error { // This will be nil when running in AGPL-only mode. if options.ParseLicenseClaims == nil { @@ -1441,7 +1428,7 @@ func newProvisionerDaemon( connector[string(database.ProvisionerTypeTerraform)] = sdkproto.NewDRPCProvisionerClient(terraformClient) default: - return nil, fmt.Errorf("unknown provisioner type %q", provisionerType) + return nil, xerrors.Errorf("unknown provisioner type %q", provisionerType) } } diff --git a/cli/ssh.go b/cli/ssh.go index 1aa832fcda27e..aa8bdadb9d0dd 100644 --- a/cli/ssh.go +++ b/cli/ssh.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "log" "net/http" "net/url" "os" @@ -79,6 +80,10 @@ func (r *RootCmd) ssh() *serpent.Command { ctx, cancel := context.WithCancel(ctx) defer cancel() + // Prevent unnecessary logs from the stdlib from messing up the TTY. + // See: https://github.com/coder/coder/issues/13144 + log.SetOutput(io.Discard) + logger := inv.Logger defer func() { if retErr != nil { diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 9e746d2df6abf..8bee9fc67b24b 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -8549,6 +8549,10 @@ const docTemplate = `{ "description": "ExternalURL references the current Coder version.\nFor production builds, this will link directly to a release. For development builds, this will link to a commit.", "type": "string" }, + "telemetry": { + "description": "Telemetry is a boolean that indicates whether telemetry is enabled.", + "type": "boolean" + }, "upgrade_message": { "description": "UpgradeMessage is the message displayed to users when an outdated client\nis detected.", "type": "string" @@ -9608,12 +9612,6 @@ const docTemplate = `{ "description": "DisplayName is shown in the UI to identify the auth config.", "type": "string" }, - "extra_token_keys": { - "type": "array", - "items": { - "type": "string" - } - }, "id": { "description": "ID is a unique identifier for the auth config.\nIt defaults to ` + "`" + `type` + "`" + ` when not provided.", "type": "string" diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index d0e60d65aabfe..5eadc31d90bf4 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -7607,6 +7607,10 @@ "description": "ExternalURL references the current Coder version.\nFor production builds, this will link directly to a release. For development builds, this will link to a commit.", "type": "string" }, + "telemetry": { + "description": "Telemetry is a boolean that indicates whether telemetry is enabled.", + "type": "boolean" + }, "upgrade_message": { "description": "UpgradeMessage is the message displayed to users when an outdated client\nis detected.", "type": "string" @@ -8603,12 +8607,6 @@ "description": "DisplayName is shown in the UI to identify the auth config.", "type": "string" }, - "extra_token_keys": { - "type": "array", - "items": { - "type": "string" - } - }, "id": { "description": "ID is a unique identifier for the auth config.\nIt defaults to `type` when not provided.", "type": "string" diff --git a/coderd/coderd.go b/coderd/coderd.go index 9dcda1a71536e..ee3ff1e8e7141 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -444,6 +444,7 @@ func New(options *Options) *API { WorkspaceProxy: false, UpgradeMessage: api.DeploymentValues.CLIUpgradeMessage.String(), DeploymentID: api.DeploymentID, + Telemetry: api.Telemetry.Enabled(), } api.SiteHandler = site.New(&site.Options{ BinFS: binFS, diff --git a/coderd/coderdtest/oidctest/idp.go b/coderd/coderdtest/oidctest/idp.go index c0b95619d46b7..844c4df1d2664 100644 --- a/coderd/coderdtest/oidctest/idp.go +++ b/coderd/coderdtest/oidctest/idp.go @@ -1255,7 +1255,9 @@ type ExternalAuthConfigOptions struct { // ValidatePayload is the payload that is used when the user calls the // equivalent of "userinfo" for oauth2. This is not standardized, so is // different for each provider type. - ValidatePayload func(email string) interface{} + // + // The int,error payload can control the response if set. + ValidatePayload func(email string) (interface{}, int, error) // routes is more advanced usage. This allows the caller to // completely customize the response. It captures all routes under the /external-auth-validate/* @@ -1292,7 +1294,20 @@ func (f *FakeIDP) ExternalAuthConfig(t testing.TB, id string, custom *ExternalAu case "/user", "/", "": var payload interface{} = "OK" if custom.ValidatePayload != nil { - payload = custom.ValidatePayload(email) + var err error + var code int + payload, code, err = custom.ValidatePayload(email) + if code == 0 && err == nil { + code = http.StatusOK + } + if code == 0 && err != nil { + code = http.StatusUnauthorized + } + if err != nil { + http.Error(rw, fmt.Sprintf("failed validation via custom method: %s", err.Error()), code) + return + } + rw.WriteHeader(code) } _ = json.NewEncoder(rw).Encode(payload) default: diff --git a/coderd/externalauth/externalauth.go b/coderd/externalauth/externalauth.go index 85e53f2e91f33..f5447ebeecd25 100644 --- a/coderd/externalauth/externalauth.go +++ b/coderd/externalauth/externalauth.go @@ -202,7 +202,7 @@ func (c *Config) ValidateToken(ctx context.Context, link *oauth2.Token) (bool, * return false, nil, err } defer res.Body.Close() - if res.StatusCode == http.StatusUnauthorized { + if res.StatusCode == http.StatusUnauthorized || res.StatusCode == http.StatusForbidden { // The token is no longer valid! return false, nil, nil } diff --git a/coderd/externalauth_test.go b/coderd/externalauth_test.go index db40ccf38a554..916a88460d53c 100644 --- a/coderd/externalauth_test.go +++ b/coderd/externalauth_test.go @@ -79,11 +79,11 @@ func TestExternalAuthByID(t *testing.T) { client := coderdtest.New(t, &coderdtest.Options{ ExternalAuthConfigs: []*externalauth.Config{ fake.ExternalAuthConfig(t, providerID, &oidctest.ExternalAuthConfigOptions{ - ValidatePayload: func(_ string) interface{} { + ValidatePayload: func(_ string) (interface{}, int, error) { return github.User{ Login: github.String("kyle"), AvatarURL: github.String("https://avatars.githubusercontent.com/u/12345678?v=4"), - } + }, 0, nil }, }, func(cfg *externalauth.Config) { cfg.Type = codersdk.EnhancedExternalAuthProviderGitHub.String() @@ -108,11 +108,11 @@ func TestExternalAuthByID(t *testing.T) { // routes includes a route for /install that returns a list of installations routes := (&oidctest.ExternalAuthConfigOptions{ - ValidatePayload: func(_ string) interface{} { + ValidatePayload: func(_ string) (interface{}, int, error) { return github.User{ Login: github.String("kyle"), AvatarURL: github.String("https://avatars.githubusercontent.com/u/12345678?v=4"), - } + }, 0, nil }, }).AddRoute("/installs", func(_ string, rw http.ResponseWriter, r *http.Request) { httpapi.Write(r.Context(), rw, http.StatusOK, struct { @@ -556,7 +556,7 @@ func TestExternalAuthCallback(t *testing.T) { // If the validation URL gives a non-OK status code, this // should be treated as an internal server error. srv.Config.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusForbidden) + w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Something went wrong!")) }) _, err = agentClient.ExternalAuth(ctx, agentsdk.ExternalAuthRequest{ @@ -565,7 +565,7 @@ func TestExternalAuthCallback(t *testing.T) { var apiError *codersdk.Error require.ErrorAs(t, err, &apiError) require.Equal(t, http.StatusInternalServerError, apiError.StatusCode()) - require.Equal(t, "validate external auth token: status 403: body: Something went wrong!", apiError.Detail) + require.Equal(t, "validate external auth token: status 400: body: Something went wrong!", apiError.Detail) }) t.Run("ExpiredNoRefresh", func(t *testing.T) { diff --git a/coderd/telemetry/telemetry.go b/coderd/telemetry/telemetry.go index 36292179da478..9d16ba7922098 100644 --- a/coderd/telemetry/telemetry.go +++ b/coderd/telemetry/telemetry.go @@ -41,20 +41,13 @@ type Options struct { // URL is an endpoint to direct telemetry towards! URL *url.URL - BuiltinPostgres bool - DeploymentID string - GitHubOAuth bool - OIDCAuth bool - OIDCIssuerURL string - Wildcard bool - DERPServerRelayURL string - GitAuth []GitAuth - Prometheus bool - STUN bool - SnapshotFrequency time.Duration - Tunnel bool - ParseLicenseJWT func(lic *License) error - Experiments []string + DeploymentID string + DeploymentConfig *codersdk.DeploymentValues + BuiltinPostgres bool + Tunnel bool + + SnapshotFrequency time.Duration + ParseLicenseJWT func(lic *License) error } // New constructs a reporter for telemetry data. @@ -100,6 +93,7 @@ type Reporter interface { // database. For example, if a new user is added, a snapshot can // contain just that user entry. Report(snapshot *Snapshot) + Enabled() bool Close() } @@ -116,6 +110,10 @@ type remoteReporter struct { shutdownAt *time.Time } +func (*remoteReporter) Enabled() bool { + return true +} + func (r *remoteReporter) Report(snapshot *Snapshot) { go r.reportSync(snapshot) } @@ -242,31 +240,24 @@ func (r *remoteReporter) deployment() error { } data, err := json.Marshal(&Deployment{ - ID: r.options.DeploymentID, - Architecture: sysInfo.Architecture, - BuiltinPostgres: r.options.BuiltinPostgres, - Containerized: containerized, - Wildcard: r.options.Wildcard, - DERPServerRelayURL: r.options.DERPServerRelayURL, - GitAuth: r.options.GitAuth, - Kubernetes: os.Getenv("KUBERNETES_SERVICE_HOST") != "", - GitHubOAuth: r.options.GitHubOAuth, - OIDCAuth: r.options.OIDCAuth, - OIDCIssuerURL: r.options.OIDCIssuerURL, - Prometheus: r.options.Prometheus, - InstallSource: installSource, - STUN: r.options.STUN, - Tunnel: r.options.Tunnel, - OSType: sysInfo.OS.Type, - OSFamily: sysInfo.OS.Family, - OSPlatform: sysInfo.OS.Platform, - OSName: sysInfo.OS.Name, - OSVersion: sysInfo.OS.Version, - CPUCores: runtime.NumCPU(), - MemoryTotal: mem.Total, - MachineID: sysInfo.UniqueID, - StartedAt: r.startedAt, - ShutdownAt: r.shutdownAt, + ID: r.options.DeploymentID, + Architecture: sysInfo.Architecture, + BuiltinPostgres: r.options.BuiltinPostgres, + Containerized: containerized, + Config: r.options.DeploymentConfig, + Kubernetes: os.Getenv("KUBERNETES_SERVICE_HOST") != "", + InstallSource: installSource, + Tunnel: r.options.Tunnel, + OSType: sysInfo.OS.Type, + OSFamily: sysInfo.OS.Family, + OSPlatform: sysInfo.OS.Platform, + OSName: sysInfo.OS.Name, + OSVersion: sysInfo.OS.Version, + CPUCores: runtime.NumCPU(), + MemoryTotal: mem.Total, + MachineID: sysInfo.UniqueID, + StartedAt: r.startedAt, + ShutdownAt: r.shutdownAt, }) if err != nil { return xerrors.Errorf("marshal deployment: %w", err) @@ -481,10 +472,6 @@ func (r *remoteReporter) createSnapshot() (*Snapshot, error) { } return nil }) - eg.Go(func() error { - snapshot.Experiments = ConvertExperiments(r.options.Experiments) - return nil - }) err := eg.Wait() if err != nil { @@ -745,16 +732,6 @@ func ConvertExternalProvisioner(id uuid.UUID, tags map[string]string, provisione } } -func ConvertExperiments(experiments []string) []Experiment { - var out []Experiment - - for _, exp := range experiments { - out = append(out, Experiment{Name: exp}) - } - - return out -} - // Snapshot represents a point-in-time anonymized database dump. // Data is aggregated by latest on the server-side, so partial data // can be sent without issue. @@ -777,40 +754,28 @@ type Snapshot struct { WorkspaceResourceMetadata []WorkspaceResourceMetadata `json:"workspace_resource_metadata"` WorkspaceResources []WorkspaceResource `json:"workspace_resources"` Workspaces []Workspace `json:"workspaces"` - Experiments []Experiment `json:"experiments"` } // Deployment contains information about the host running Coder. type Deployment struct { - ID string `json:"id"` - Architecture string `json:"architecture"` - BuiltinPostgres bool `json:"builtin_postgres"` - Containerized bool `json:"containerized"` - Kubernetes bool `json:"kubernetes"` - Tunnel bool `json:"tunnel"` - Wildcard bool `json:"wildcard"` - DERPServerRelayURL string `json:"derp_server_relay_url"` - GitAuth []GitAuth `json:"git_auth"` - GitHubOAuth bool `json:"github_oauth"` - OIDCAuth bool `json:"oidc_auth"` - OIDCIssuerURL string `json:"oidc_issuer_url"` - Prometheus bool `json:"prometheus"` - InstallSource string `json:"install_source"` - STUN bool `json:"stun"` - OSType string `json:"os_type"` - OSFamily string `json:"os_family"` - OSPlatform string `json:"os_platform"` - OSName string `json:"os_name"` - OSVersion string `json:"os_version"` - CPUCores int `json:"cpu_cores"` - MemoryTotal uint64 `json:"memory_total"` - MachineID string `json:"machine_id"` - StartedAt time.Time `json:"started_at"` - ShutdownAt *time.Time `json:"shutdown_at"` -} - -type GitAuth struct { - Type string `json:"type"` + ID string `json:"id"` + Architecture string `json:"architecture"` + BuiltinPostgres bool `json:"builtin_postgres"` + Containerized bool `json:"containerized"` + Kubernetes bool `json:"kubernetes"` + Config *codersdk.DeploymentValues `json:"config"` + Tunnel bool `json:"tunnel"` + InstallSource string `json:"install_source"` + OSType string `json:"os_type"` + OSFamily string `json:"os_family"` + OSPlatform string `json:"os_platform"` + OSName string `json:"os_name"` + OSVersion string `json:"os_version"` + CPUCores int `json:"cpu_cores"` + MemoryTotal uint64 `json:"memory_total"` + MachineID string `json:"machine_id"` + StartedAt time.Time `json:"started_at"` + ShutdownAt *time.Time `json:"shutdown_at"` } type APIKey struct { @@ -985,11 +950,8 @@ type ExternalProvisioner struct { ShutdownAt *time.Time `json:"shutdown_at"` } -type Experiment struct { - Name string `json:"name"` -} - type noopReporter struct{} func (*noopReporter) Report(_ *Snapshot) {} +func (*noopReporter) Enabled() bool { return false } func (*noopReporter) Close() {} diff --git a/coderd/telemetry/telemetry_test.go b/coderd/telemetry/telemetry_test.go index 4661a4f8f21bf..fa8650de3f3d5 100644 --- a/coderd/telemetry/telemetry_test.go +++ b/coderd/telemetry/telemetry_test.go @@ -114,17 +114,6 @@ func TestTelemetry(t *testing.T) { require.Len(t, snapshot.Users, 1) require.Equal(t, snapshot.Users[0].EmailHashed, "bb44bf07cf9a2db0554bba63a03d822c927deae77df101874496df5a6a3e896d@coder.com") }) - t.Run("Experiments", func(t *testing.T) { - t.Parallel() - - const expName = "my-experiment" - exps := []string{expName} - _, snapshot := collectSnapshot(t, dbmem.New(), func(opts telemetry.Options) telemetry.Options { - opts.Experiments = exps - return opts - }) - require.Equal(t, []telemetry.Experiment{{Name: expName}}, snapshot.Experiments) - }) } // nolint:paralleltest diff --git a/coderd/workspacebuilds_test.go b/coderd/workspacebuilds_test.go index f8560ff911925..eb76239b84658 100644 --- a/coderd/workspacebuilds_test.go +++ b/coderd/workspacebuilds_test.go @@ -20,9 +20,11 @@ import ( "cdr.dev/slog/sloggers/slogtest" "github.com/coder/coder/v2/coderd/audit" "github.com/coder/coder/v2/coderd/coderdtest" + "github.com/coder/coder/v2/coderd/coderdtest/oidctest" "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database/dbauthz" "github.com/coder/coder/v2/coderd/database/dbtime" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/rbac" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/provisioner/echo" @@ -711,6 +713,78 @@ func TestWorkspaceBuildStatus(t *testing.T) { require.EqualValues(t, codersdk.WorkspaceStatusDeleted, workspace.LatestBuild.Status) } +func TestWorkspaceDeleteSuspendedUser(t *testing.T) { + t.Parallel() + const providerID = "fake-github" + fake := oidctest.NewFakeIDP(t, oidctest.WithServing()) + + validateCalls := 0 + userSuspended := false + owner := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerDaemon: true, + ExternalAuthConfigs: []*externalauth.Config{ + fake.ExternalAuthConfig(t, providerID, &oidctest.ExternalAuthConfigOptions{ + ValidatePayload: func(email string) (interface{}, int, error) { + validateCalls++ + if userSuspended { + // Simulate the user being suspended from the IDP too. + return "", http.StatusForbidden, fmt.Errorf("user is suspended") + } + return "OK", 0, nil + }, + }), + }, + }) + + first := coderdtest.CreateFirstUser(t, owner) + + // New user that we will suspend when we try to delete the workspace. + client, user := coderdtest.CreateAnotherUser(t, owner, first.OrganizationID, rbac.RoleTemplateAdmin()) + fake.ExternalLogin(t, client) + + version := coderdtest.CreateTemplateVersion(t, client, first.OrganizationID, &echo.Responses{ + Parse: echo.ParseComplete, + ProvisionApply: echo.ApplyComplete, + ProvisionPlan: []*proto.Response{{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ + Error: "", + Resources: nil, + Parameters: nil, + ExternalAuthProviders: []*proto.ExternalAuthProviderResource{ + { + Id: providerID, + Optional: false, + }, + }, + }, + }, + }}, + }) + + validateCalls = 0 // Reset + coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) + template := coderdtest.CreateTemplate(t, client, first.OrganizationID, version.ID) + workspace := coderdtest.CreateWorkspace(t, client, first.OrganizationID, template.ID) + coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) + require.Equal(t, 1, validateCalls) // Ensure the external link is working + + // Suspend the user + ctx := testutil.Context(t, testutil.WaitLong) + _, err := owner.UpdateUserStatus(ctx, user.ID.String(), codersdk.UserStatusSuspended) + require.NoError(t, err, "suspend user") + + // Now delete the workspace build + userSuspended = true + build, err := owner.CreateWorkspaceBuild(ctx, workspace.ID, codersdk.CreateWorkspaceBuildRequest{ + Transition: codersdk.WorkspaceTransitionDelete, + }) + require.NoError(t, err) + build = coderdtest.AwaitWorkspaceBuildJobCompleted(t, owner, build.ID) + require.Equal(t, 2, validateCalls) + require.Equal(t, codersdk.WorkspaceStatusDeleted, build.Status) +} + func TestWorkspaceBuildDebugMode(t *testing.T) { t.Parallel() diff --git a/codersdk/deployment.go b/codersdk/deployment.go index 2aa675727b72b..a61bad83eaa47 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -389,7 +389,7 @@ type ExternalAuthConfig struct { AppInstallationsURL string `json:"app_installations_url" yaml:"app_installations_url"` NoRefresh bool `json:"no_refresh" yaml:"no_refresh"` Scopes []string `json:"scopes" yaml:"scopes"` - ExtraTokenKeys []string `json:"extra_token_keys" yaml:"extra_token_keys"` + ExtraTokenKeys []string `json:"-" yaml:"extra_token_keys"` DeviceFlow bool `json:"device_flow" yaml:"device_flow"` DeviceCodeURL string `json:"device_code_url" yaml:"device_code_url"` // Regex allows API requesters to match an auth config by @@ -2152,11 +2152,12 @@ type BuildInfoResponse struct { ExternalURL string `json:"external_url"` // Version returns the semantic version of the build. Version string `json:"version"` - // DashboardURL is the URL to hit the deployment's dashboard. // For external workspace proxies, this is the coderd they are connected // to. DashboardURL string `json:"dashboard_url"` + // Telemetry is a boolean that indicates whether telemetry is enabled. + Telemetry bool `json:"telemetry"` WorkspaceProxy bool `json:"workspace_proxy"` diff --git a/docs/api/general.md b/docs/api/general.md index 52313409cb02c..aa77d9d272c94 100644 --- a/docs/api/general.md +++ b/docs/api/general.md @@ -57,6 +57,7 @@ curl -X GET http://coder-server:8080/api/v2/buildinfo \ "dashboard_url": "string", "deployment_id": "string", "external_url": "string", + "telemetry": true, "upgrade_message": "string", "version": "string", "workspace_proxy": true @@ -227,7 +228,6 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \ "device_flow": true, "display_icon": "string", "display_name": "string", - "extra_token_keys": ["string"], "id": "string", "no_refresh": true, "regex": "string", diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 26b38a7c1ec78..f19f2ea0cf53b 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -1180,6 +1180,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "dashboard_url": "string", "deployment_id": "string", "external_url": "string", + "telemetry": true, "upgrade_message": "string", "version": "string", "workspace_proxy": true @@ -1194,6 +1195,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `dashboard_url` | string | false | | Dashboard URL is the URL to hit the deployment's dashboard. For external workspace proxies, this is the coderd they are connected to. | | `deployment_id` | string | false | | Deployment ID is the unique identifier for this deployment. | | `external_url` | string | false | | External URL references the current Coder version. For production builds, this will link directly to a release. For development builds, this will link to a commit. | +| `telemetry` | boolean | false | | Telemetry is a boolean that indicates whether telemetry is enabled. | | `upgrade_message` | string | false | | Upgrade message is the message displayed to users when an outdated client is detected. | | `version` | string | false | | Version returns the semantic version of the build. | | `workspace_proxy` | boolean | false | | | @@ -1955,7 +1957,6 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o "device_flow": true, "display_icon": "string", "display_name": "string", - "extra_token_keys": ["string"], "id": "string", "no_refresh": true, "regex": "string", @@ -2328,7 +2329,6 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o "device_flow": true, "display_icon": "string", "display_name": "string", - "extra_token_keys": ["string"], "id": "string", "no_refresh": true, "regex": "string", @@ -2745,7 +2745,6 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o "device_flow": true, "display_icon": "string", "display_name": "string", - "extra_token_keys": ["string"], "id": "string", "no_refresh": true, "regex": "string", @@ -2768,7 +2767,6 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o | `device_flow` | boolean | false | | | | `display_icon` | string | false | | Display icon is a URL to an icon to display in the UI. | | `display_name` | string | false | | Display name is shown in the UI to identify the auth config. | -| `extra_token_keys` | array of string | false | | | | `id` | string | false | | ID is a unique identifier for the auth config. It defaults to `type` when not provided. | | `no_refresh` | boolean | false | | | | `regex` | string | false | | Regex allows API requesters to match an auth config by a string (e.g. coder.com) instead of by it's type. | @@ -8693,7 +8691,6 @@ _None_ "device_flow": true, "display_icon": "string", "display_name": "string", - "extra_token_keys": ["string"], "id": "string", "no_refresh": true, "regex": "string", diff --git a/enterprise/trialer/trialer.go b/enterprise/trialer/trialer.go index fd846df58db61..fa5d15a65b25a 100644 --- a/enterprise/trialer/trialer.go +++ b/enterprise/trialer/trialer.go @@ -39,6 +39,22 @@ func New(db database.Store, url string, keys map[string]ed25519.PublicKey) func( return xerrors.Errorf("perform license request: %w", err) } defer res.Body.Close() + if res.StatusCode > 300 { + body, err := io.ReadAll(res.Body) + if err != nil { + return xerrors.Errorf("read license response: %w", err) + } + // This is the format of the error response from + // the license server. + var msg struct { + Error string `json:"error"` + } + err = json.Unmarshal(body, &msg) + if err != nil { + return xerrors.Errorf("unmarshal error: %w", err) + } + return xerrors.New(msg.Error) + } raw, err := io.ReadAll(res.Body) if err != nil { return xerrors.Errorf("read license: %w", err) diff --git a/enterprise/wsproxy/wsproxysdk/wsproxysdk_test.go b/enterprise/wsproxy/wsproxysdk/wsproxysdk_test.go index 870d06b71da6d..c94b712cc9872 100644 --- a/enterprise/wsproxy/wsproxysdk/wsproxysdk_test.go +++ b/enterprise/wsproxy/wsproxysdk/wsproxysdk_test.go @@ -216,7 +216,7 @@ func TestDialCoordinator(t *testing.T) { Node: &proto.Node{ Id: 55, AsOf: timestamppb.New(time.Unix(1689653252, 0)), - Key: peerNodeKey[:], + Key: peerNodeKey, Disco: string(peerDiscoKey), PreferredDerp: 0, DerpLatency: map[string]float64{ diff --git a/provisioner/terraform/executor.go b/provisioner/terraform/executor.go index 0a6c1df943595..b1a3ecadb5203 100644 --- a/provisioner/terraform/executor.go +++ b/provisioner/terraform/executor.go @@ -24,6 +24,8 @@ import ( "github.com/coder/coder/v2/provisionersdk/proto" ) +var version170 = version.Must(version.NewVersion("1.7.0")) + type executor struct { logger slog.Logger server *server @@ -346,8 +348,16 @@ func (e *executor) graph(ctx, killCtx context.Context) (string, error) { return "", ctx.Err() } + ver, err := e.version(ctx) + if err != nil { + return "", err + } + args := []string{"graph"} + if ver.GreaterThanOrEqual(version170) { + args = append(args, "-type=plan") + } var out strings.Builder - cmd := exec.CommandContext(killCtx, e.binaryPath, "graph") // #nosec + cmd := exec.CommandContext(killCtx, e.binaryPath, args...) // #nosec cmd.Stdout = &out cmd.Dir = e.workdir cmd.Env = e.basicEnv() @@ -356,7 +366,7 @@ func (e *executor) graph(ctx, killCtx context.Context) (string, error) { slog.F("binary_path", e.binaryPath), slog.F("args", "graph"), ) - err := cmd.Start() + err = cmd.Start() if err != nil { return "", err } diff --git a/provisioner/terraform/testdata/calling-module/calling-module.tf b/provisioner/terraform/testdata/calling-module/calling-module.tf index c83c7dd2245b0..14777169d9994 100644 --- a/provisioner/terraform/testdata/calling-module/calling-module.tf +++ b/provisioner/terraform/testdata/calling-module/calling-module.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.6.1" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/calling-module/calling-module.tfplan.dot b/provisioner/terraform/testdata/calling-module/calling-module.tfplan.dot index f3a28a65c5ecc..47f46d7ce79ba 100644 --- a/provisioner/terraform/testdata/calling-module/calling-module.tfplan.dot +++ b/provisioner/terraform/testdata/calling-module/calling-module.tfplan.dot @@ -21,4 +21,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json b/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json index e71a071e4fd9d..28a2b055ecf10 100644 --- a/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json +++ b/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -17,11 +17,22 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, - "sensitive_values": {} + "sensitive_values": { + "display_apps": [], + "metadata": [] + } } ], "child_modules": [ @@ -78,17 +89,29 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, + "metadata": [], "token": true }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], + "metadata": [], "token": true } } @@ -153,7 +176,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.6.1" + "version_constraint": "0.22.0" }, "module.module:null": { "name": "null", @@ -236,5 +259,6 @@ ] } ], - "timestamp": "2023-08-30T19:24:59Z" + "timestamp": "2024-05-22T17:02:40Z", + "errored": false } diff --git a/provisioner/terraform/testdata/calling-module/calling-module.tfstate.dot b/provisioner/terraform/testdata/calling-module/calling-module.tfstate.dot index f3a28a65c5ecc..47f46d7ce79ba 100644 --- a/provisioner/terraform/testdata/calling-module/calling-module.tfstate.dot +++ b/provisioner/terraform/testdata/calling-module/calling-module.tfstate.dot @@ -21,4 +21,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json b/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json index dc3627f793ffc..5f8a795e2a894 100644 --- a/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json +++ b/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -16,15 +16,36 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "c6fd4a45-dc64-4830-8ff1-9a6c8074fca8", + "id": "f26b1d53-799e-4fbb-9fd3-71e60b37eacd", "init_script": "", + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, - "token": "2559767b-afc6-4293-92cf-d57d98bda13a", + "startup_script_behavior": null, + "startup_script_timeout": 300, + "token": "ce663074-ebea-44cb-b6d1-321f590f7982", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], + "metadata": [], "token": true } } @@ -48,7 +69,7 @@ "outputs": { "script": "" }, - "random": "5659889568915200015" + "random": "8031375470547649400" }, "sensitive_values": { "inputs": {}, @@ -63,7 +84,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "4052095409343470524", + "id": "3370916843136140681", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tf b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tf index 302a34fb17c03..3f210452dfee0 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tf +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.6.1" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.dot b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.dot index 5ebd454aba477..47a4798719ca0 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.dot +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.dot @@ -17,4 +17,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json index c34eba1bf5e2c..9717ddd34b128 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -17,11 +17,22 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, - "sensitive_values": {} + "sensitive_values": { + "display_apps": [], + "metadata": [] + } }, { "address": "null_resource.a", @@ -68,17 +79,29 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, + "metadata": [], "token": true }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], + "metadata": [], "token": true } } @@ -131,7 +154,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.6.1" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -181,5 +204,6 @@ ] } }, - "timestamp": "2023-08-30T19:25:02Z" + "timestamp": "2024-05-22T17:02:43Z", + "errored": false } diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.dot b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.dot index 5ebd454aba477..47a4798719ca0 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.dot +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.dot @@ -17,4 +17,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json index 60821742c70b5..304e9703b9073 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -16,15 +16,36 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "9fb263ae-2d96-414f-abfa-7874e73695d2", + "id": "9d869fc3-c185-4278-a5d2-873f809a4449", "init_script": "", + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, - "token": "4f391c60-20f9-4d57-906e-92e2f3e1e3c1", + "startup_script_behavior": null, + "startup_script_timeout": 300, + "token": "418bb1d6-49d8-4340-ac84-ed6991457ff9", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], + "metadata": [], "token": true } }, @@ -36,7 +57,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "2616597461049838347", + "id": "3681188688307687011", "triggers": null }, "sensitive_values": {}, @@ -53,7 +74,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "6759504907417146954", + "id": "6055360096088266226", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tf b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tf index e51020602ba31..8c7b200fca7b0 100644 --- a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tf +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.6.1" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.dot b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.dot index b1478de04e121..c887bda7e2672 100644 --- a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.dot +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.dot @@ -19,4 +19,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json index ec759bd57e6e6..a62fa814bea53 100644 --- a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -17,11 +17,22 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, - "sensitive_values": {} + "sensitive_values": { + "display_apps": [], + "metadata": [] + } }, { "address": "null_resource.first", @@ -68,17 +79,29 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, + "metadata": [], "token": true }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], + "metadata": [], "token": true } } @@ -131,7 +154,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.6.1" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -181,5 +204,6 @@ ] } }, - "timestamp": "2023-08-30T19:25:04Z" + "timestamp": "2024-05-22T17:02:45Z", + "errored": false } diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.dot b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.dot index b1478de04e121..c887bda7e2672 100644 --- a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.dot +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.dot @@ -19,4 +19,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json index cc9d6c4d07bed..4aa66de56d2c9 100644 --- a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -16,15 +16,36 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "56d6f6e2-a7f8-4594-9bc3-044a4fd3b021", + "id": "d9c497fe-1dc4-4551-b46d-282f775e9509", "init_script": "", + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, - "token": "715216d1-fca1-4652-9032-d5367072706f", + "startup_script_behavior": null, + "startup_script_timeout": 300, + "token": "6fa01f69-de93-4610-b942-b787118146f8", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], + "metadata": [], "token": true } }, @@ -36,7 +57,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "7470209964325643389", + "id": "2012753940926517215", "triggers": null }, "sensitive_values": {}, @@ -52,7 +73,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "251158623761758523", + "id": "2163283012438694669", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tf b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tf index ab6c4cd551802..494e0acafb48f 100644 --- a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tf +++ b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.11.2" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.dot b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.dot index a1dd4289708f0..0b8e5a1594998 100644 --- a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.dot +++ b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.dot @@ -15,4 +15,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.json b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.json index 07d7647d1ec07..de8d982bef577 100644 --- a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.json +++ b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -29,6 +29,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -89,6 +90,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -143,7 +145,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.11.2" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -201,5 +203,6 @@ ] } }, - "timestamp": "2023-08-30T19:25:10Z" + "timestamp": "2024-05-22T17:02:50Z", + "errored": false } diff --git a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.dot b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.dot index a1dd4289708f0..0b8e5a1594998 100644 --- a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.dot +++ b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.dot @@ -15,4 +15,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.json b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.json index dd0f7eed39ed9..3567c75133732 100644 --- a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.json +++ b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -26,18 +26,19 @@ } ], "env": null, - "id": "ba0faeb0-5a14-4908-946e-360329a8c852", + "id": "c55cfcad-5422-46e5-a144-e933660bacd3", "init_script": "", "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "010c13b9-95aa-4b66-a2ad-5937e467134a", + "token": "e170615d-a3a2-4dc4-a65e-4990ceeb79e5", "troubleshooting_url": null }, "sensitive_values": { @@ -56,7 +57,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "7220106781059326067", + "id": "3512108359019802900", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/display-apps/display-apps.tf b/provisioner/terraform/testdata/display-apps/display-apps.tf index f4398bcdf34c2..a36b68cd3b1cc 100644 --- a/provisioner/terraform/testdata/display-apps/display-apps.tf +++ b/provisioner/terraform/testdata/display-apps/display-apps.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.11.2" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/display-apps/display-apps.tfplan.dot b/provisioner/terraform/testdata/display-apps/display-apps.tfplan.dot index a1dd4289708f0..0b8e5a1594998 100644 --- a/provisioner/terraform/testdata/display-apps/display-apps.tfplan.dot +++ b/provisioner/terraform/testdata/display-apps/display-apps.tfplan.dot @@ -15,4 +15,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/display-apps/display-apps.tfplan.json b/provisioner/terraform/testdata/display-apps/display-apps.tfplan.json index 135f576b99422..d41c6e03541d0 100644 --- a/provisioner/terraform/testdata/display-apps/display-apps.tfplan.json +++ b/provisioner/terraform/testdata/display-apps/display-apps.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -29,6 +29,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -89,6 +90,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -143,7 +145,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.11.2" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -201,5 +203,6 @@ ] } }, - "timestamp": "2023-08-30T19:25:07Z" + "timestamp": "2024-05-22T17:02:48Z", + "errored": false } diff --git a/provisioner/terraform/testdata/display-apps/display-apps.tfstate.dot b/provisioner/terraform/testdata/display-apps/display-apps.tfstate.dot index a1dd4289708f0..0b8e5a1594998 100644 --- a/provisioner/terraform/testdata/display-apps/display-apps.tfstate.dot +++ b/provisioner/terraform/testdata/display-apps/display-apps.tfstate.dot @@ -15,4 +15,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/display-apps/display-apps.tfstate.json b/provisioner/terraform/testdata/display-apps/display-apps.tfstate.json index 6742240dd2800..79b2e6dd6490f 100644 --- a/provisioner/terraform/testdata/display-apps/display-apps.tfstate.json +++ b/provisioner/terraform/testdata/display-apps/display-apps.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -26,18 +26,19 @@ } ], "env": null, - "id": "a7b8ff17-66ba-47b4-a4b4-51da1ad835fc", + "id": "3fb63a4e-bb0e-4380-9ed9-8b1581943b1f", "init_script": "", "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "75fc044a-b120-4e86-be94-056cec981bd9", + "token": "eb5720a7-91fd-4e37-8085-af3c8205702c", "troubleshooting_url": null }, "sensitive_values": { @@ -56,7 +57,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "4184951391452107661", + "id": "2929624824161973000", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tf b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tf index 7afa655792cea..0b68bbe5710fe 100644 --- a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tf +++ b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.16.0" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.dot b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.dot index a011d7c85e40e..06ec61c86c754 100644 --- a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.dot +++ b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.dot @@ -21,4 +21,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.json b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.json index afd5d60812138..837d50255a3a1 100644 --- a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.json +++ b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.6.6", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -20,6 +20,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -69,6 +70,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -116,7 +118,7 @@ ], "prior_state": { "format_version": "1.0", - "terraform_version": "1.6.6", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -157,7 +159,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.16.0" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -225,6 +227,6 @@ ] } }, - "timestamp": "2024-02-12T23:11:52Z", + "timestamp": "2024-05-22T17:02:52Z", "errored": false } diff --git a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.dot b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.dot index a011d7c85e40e..06ec61c86c754 100644 --- a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.dot +++ b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.dot @@ -21,4 +21,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.json b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.json index 21f66e44b607b..125cea74bcc3c 100644 --- a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.json +++ b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.6.6", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -54,18 +54,19 @@ } ], "env": null, - "id": "d1f23602-ef8e-4ecf-aa5a-df8aa476344e", + "id": "923df4d0-cf96-4cf8-aaff-426e58927a81", "init_script": "", "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "90440015-11c8-442b-adba-9f2bd279b5c7", + "token": "f5328221-90c7-4056-83b4-7b76d6f46580", "troubleshooting_url": null }, "sensitive_values": { @@ -84,7 +85,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "8183284779544326910", + "id": "4621387386750422041", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/generate.sh b/provisioner/terraform/testdata/generate.sh index 4ae1a87fb2504..04ac7bdef3c64 100755 --- a/provisioner/terraform/testdata/generate.sh +++ b/provisioner/terraform/testdata/generate.sh @@ -22,11 +22,13 @@ for d in */; do terraform init -upgrade terraform plan -out terraform.tfplan terraform show -json ./terraform.tfplan | jq >"$name".tfplan.json - terraform graph >"$name".tfplan.dot + terraform graph -type=plan >"$name".tfplan.dot rm terraform.tfplan terraform apply -auto-approve terraform show -json ./terraform.tfstate | jq >"$name".tfstate.json rm terraform.tfstate - terraform graph >"$name".tfstate.dot + terraform graph -type=plan >"$name".tfstate.dot popd done + +terraform version -json | jq -r '.terraform_version' >version.txt diff --git a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tf b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tf index e76479c459043..337699a36cccd 100644 --- a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tf +++ b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.6.13" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.dot b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.dot index 3d0775104e9c8..119f00d4b3840 100644 --- a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.dot +++ b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.dot @@ -21,4 +21,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.json b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.json index e5976f1d4341d..bd9286692d328 100644 --- a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.json +++ b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -18,15 +18,21 @@ "dir": null, "env": null, "login_before_ready": true, + "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, "startup_script_timeout": 300, "troubleshooting_url": null }, - "sensitive_values": {} + "sensitive_values": { + "display_apps": [], + "metadata": [] + } }, { "address": "null_resource.dev", @@ -62,21 +68,28 @@ "dir": null, "env": null, "login_before_ready": true, + "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, "startup_script_timeout": 300, "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, + "metadata": [], "token": true }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], + "metadata": [], "token": true } } @@ -105,7 +118,7 @@ ], "prior_state": { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -144,7 +157,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.6.13" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -209,5 +222,6 @@ ] } }, - "timestamp": "2023-08-30T19:25:13Z" + "timestamp": "2024-05-22T17:02:55Z", + "errored": false } diff --git a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.dot b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.dot index 3d0775104e9c8..119f00d4b3840 100644 --- a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.dot +++ b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.dot @@ -21,4 +21,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.json b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.json index 0abc4e8a4cf32..509c6d5a9d7fc 100644 --- a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.json +++ b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -42,20 +42,36 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "a8139f31-219b-4ee5-9e64-60d8dd94be27", + "id": "48a24332-1a90-48d9-9e03-b4e9f09c6eab", "init_script": "", "login_before_ready": true, + "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "20cdf0ee-2da9-432e-a3ad-674b900ed3c1", + "token": "6a2ae93f-3f25-423d-aa97-b2f1c5d9c20b", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], + "metadata": [], "token": true } }, @@ -67,7 +83,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "8246789295692160686", + "id": "8095584601893320918", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/instance-id/instance-id.tf b/provisioner/terraform/testdata/instance-id/instance-id.tf index 328ac453c490f..1cd4ab828b4f0 100644 --- a/provisioner/terraform/testdata/instance-id/instance-id.tf +++ b/provisioner/terraform/testdata/instance-id/instance-id.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.6.1" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/instance-id/instance-id.tfplan.dot b/provisioner/terraform/testdata/instance-id/instance-id.tfplan.dot index eff161be511b3..543bd3679ea9c 100644 --- a/provisioner/terraform/testdata/instance-id/instance-id.tfplan.dot +++ b/provisioner/terraform/testdata/instance-id/instance-id.tfplan.dot @@ -17,4 +17,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/instance-id/instance-id.tfplan.json b/provisioner/terraform/testdata/instance-id/instance-id.tfplan.json index cd94915162d1c..fe875367359c0 100644 --- a/provisioner/terraform/testdata/instance-id/instance-id.tfplan.json +++ b/provisioner/terraform/testdata/instance-id/instance-id.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -17,11 +17,22 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, - "sensitive_values": {} + "sensitive_values": { + "display_apps": [], + "metadata": [] + } }, { "address": "coder_agent_instance.main", @@ -68,17 +79,29 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, + "metadata": [], "token": true }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], + "metadata": [], "token": true } } @@ -132,7 +155,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.6.1" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -201,5 +224,6 @@ ] } ], - "timestamp": "2023-08-30T19:25:15Z" + "timestamp": "2024-05-22T17:02:57Z", + "errored": false } diff --git a/provisioner/terraform/testdata/instance-id/instance-id.tfstate.dot b/provisioner/terraform/testdata/instance-id/instance-id.tfstate.dot index eff161be511b3..543bd3679ea9c 100644 --- a/provisioner/terraform/testdata/instance-id/instance-id.tfstate.dot +++ b/provisioner/terraform/testdata/instance-id/instance-id.tfstate.dot @@ -17,4 +17,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json b/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json index 6b91850750048..ef5346a2ac822 100644 --- a/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json +++ b/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -16,15 +16,36 @@ "auth": "google-instance-identity", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "07c39e97-3461-4912-87c6-aab06714fb79", + "id": "3bc8e20f-2024-4014-ac11-806e7e1a1e24", "init_script": "", + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, - "token": "4d389c4e-479b-4004-8ad1-b10da989bbdb", + "startup_script_behavior": null, + "startup_script_timeout": 300, + "token": "6ef0492b-8dbe-4c61-8eb8-a37acb671278", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], + "metadata": [], "token": true } }, @@ -36,8 +57,8 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { - "agent_id": "07c39e97-3461-4912-87c6-aab06714fb79", - "id": "13ac93bd-54bf-4e93-b2a1-35534139e255", + "agent_id": "3bc8e20f-2024-4014-ac11-806e7e1a1e24", + "id": "7ba714fa-f2b8-4d33-8987-f67466505033", "instance_id": "example" }, "sensitive_values": {}, @@ -53,7 +74,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "8984327635720248545", + "id": "4065206823139127011", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tf b/provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tf index e8d6b1d08b3dc..2ae1298904fbb 100644 --- a/provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tf +++ b/provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.6.5" + version = "0.22.0" } kubernetes = { source = "hashicorp/kubernetes" diff --git a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tf b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tf index 6ed5f0d18276b..1e13495d6ebc7 100644 --- a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tf +++ b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.6.1" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.dot b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.dot index a54bed2003cc0..963c7c228deda 100644 --- a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.dot +++ b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.dot @@ -18,4 +18,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.json b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.json index 600373f73aeb0..9fad4b322a02d 100644 --- a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.json +++ b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -17,11 +17,22 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, - "sensitive_values": {} + "sensitive_values": { + "display_apps": [], + "metadata": [] + } }, { "address": "coder_app.apps[\"app1\"]", @@ -34,9 +45,11 @@ "values": { "command": null, "display_name": "app1", + "external": false, "healthcheck": [], "icon": null, "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app1", @@ -58,9 +71,11 @@ "values": { "command": null, "display_name": "app2", + "external": false, "healthcheck": [], "icon": null, "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app2", @@ -104,17 +119,29 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, + "metadata": [], "token": true }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], + "metadata": [], "token": true } } @@ -134,9 +161,11 @@ "after": { "command": null, "display_name": "app1", + "external": false, "healthcheck": [], "icon": null, "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app1", @@ -169,9 +198,11 @@ "after": { "command": null, "display_name": "app2", + "external": false, "healthcheck": [], "icon": null, "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app2", @@ -216,7 +247,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.6.1" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -295,5 +326,6 @@ ] } ], - "timestamp": "2023-08-30T19:25:17Z" + "timestamp": "2024-05-22T17:02:59Z", + "errored": false } diff --git a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.dot b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.dot index a54bed2003cc0..963c7c228deda 100644 --- a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.dot +++ b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.dot @@ -18,4 +18,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.json b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.json index 99ab3f5adad8a..e19a8b484bf6a 100644 --- a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.json +++ b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -16,15 +16,36 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "9a8356cf-b5ef-4da0-9b4e-cfeaca1fbfcf", + "id": "d8d2ed23-193d-4784-9ce5-7bc0d879bb14", "init_script": "", + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, - "token": "7116ebd2-5205-4427-8cdb-5f86ec819911", + "startup_script_behavior": null, + "startup_script_timeout": 300, + "token": "0555adfc-e969-4fd2-8cfd-47560bd1b5a3", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], + "metadata": [], "token": true } }, @@ -37,13 +58,15 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { - "agent_id": "9a8356cf-b5ef-4da0-9b4e-cfeaca1fbfcf", + "agent_id": "d8d2ed23-193d-4784-9ce5-7bc0d879bb14", "command": null, "display_name": "app1", + "external": false, "healthcheck": [], "icon": null, - "id": "8ad9b3c3-0951-4612-adea-5c89ac12642a", + "id": "11fa3ff2-d6ba-41ca-b1df-6c98d395c0b8", "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app1", @@ -66,13 +89,15 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { - "agent_id": "9a8356cf-b5ef-4da0-9b4e-cfeaca1fbfcf", + "agent_id": "d8d2ed23-193d-4784-9ce5-7bc0d879bb14", "command": null, "display_name": "app2", + "external": false, "healthcheck": [], "icon": null, - "id": "b3cbb3eb-62d8-485f-8378-2d2ed751aa38", + "id": "cd1a2e37-adbc-49f0-bd99-033c62a1533e", "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app2", @@ -94,7 +119,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "5757307222275435634", + "id": "4490911212417021152", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tf b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tf index 978bbb164d604..d44a981d168bb 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tf +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.8.3" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.dot b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.dot index 02839b24d696d..b988d02d15ef8 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.dot +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.dot @@ -27,4 +27,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json index 4cdf0a05ee33b..7f44aa45ca7d9 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -20,6 +20,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -29,6 +30,7 @@ "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [], "metadata": [] } }, @@ -48,6 +50,7 @@ "login_before_ready": true, "metadata": [], "motd_file": "/etc/motd", + "order": null, "os": "darwin", "shutdown_script": "echo bye bye", "shutdown_script_timeout": 30, @@ -57,6 +60,7 @@ "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [], "metadata": [] } }, @@ -76,6 +80,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -85,6 +90,7 @@ "troubleshooting_url": "https://coder.com/troubleshoot" }, "sensitive_values": { + "display_apps": [], "metadata": [] } }, @@ -104,6 +110,7 @@ "login_before_ready": false, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -113,6 +120,7 @@ "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [], "metadata": [] } }, @@ -152,6 +160,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -161,6 +170,7 @@ "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, "metadata": [], @@ -168,6 +178,7 @@ }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], "metadata": [], "token": true } @@ -193,6 +204,7 @@ "login_before_ready": true, "metadata": [], "motd_file": "/etc/motd", + "order": null, "os": "darwin", "shutdown_script": "echo bye bye", "shutdown_script_timeout": 30, @@ -202,6 +214,7 @@ "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, "metadata": [], @@ -209,6 +222,7 @@ }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], "metadata": [], "token": true } @@ -234,6 +248,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -243,6 +258,7 @@ "troubleshooting_url": "https://coder.com/troubleshoot" }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, "metadata": [], @@ -250,6 +266,7 @@ }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], "metadata": [], "token": true } @@ -275,6 +292,7 @@ "login_before_ready": false, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -284,6 +302,7 @@ "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, "metadata": [], @@ -291,6 +310,7 @@ }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], "metadata": [], "token": true } @@ -323,7 +343,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.8.3" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -440,5 +460,6 @@ ] } }, - "timestamp": "2023-08-30T19:25:20Z" + "timestamp": "2024-05-22T17:03:01Z", + "errored": false } diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.dot b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.dot index 02839b24d696d..b988d02d15ef8 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.dot +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.dot @@ -27,4 +27,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json index d9bfc636cd442..0bbd45fa5a3df 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -16,22 +16,35 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "094d300c-f07a-4357-870f-6ca1fc9154a2", + "id": "0ffc6582-b017-404e-b83f-48e4a5ab38bc", "init_script": "", "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "27bd44bc-0126-4c8d-9b98-8f27619e3656", + "token": "b7f0a913-ecb1-4c80-8559-fbcb435d53d0", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], "metadata": [], "token": true } @@ -48,22 +61,35 @@ "auth": "token", "connection_timeout": 1, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "bb844516-2cdd-419c-87e1-d0d3ea69fe78", + "id": "1780ae95-844c-4d5c-94fb-6ccfe4a7656d", "init_script": "", "login_before_ready": true, "metadata": [], "motd_file": "/etc/motd", + "order": null, "os": "darwin", "shutdown_script": "echo bye bye", "shutdown_script_timeout": 30, "startup_script": null, "startup_script_behavior": "non-blocking", "startup_script_timeout": 30, - "token": "8a31b688-d3d2-4c22-b37e-c9810b9b329a", + "token": "695f8765-3d3d-4da0-9a5a-bb7b1f568bde", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], "metadata": [], "token": true } @@ -80,22 +106,35 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "c6123c01-0543-4102-bdcf-f0ee2a9c1269", + "id": "333b7856-24ac-46be-9ae3-e4981b25481d", "init_script": "", "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, "startup_script_behavior": "blocking", "startup_script_timeout": 300, - "token": "64185462-292f-4b75-b350-625326ba596e", + "token": "50ddfb93-264f-4f64-8c8d-db7d8d37c0a1", "troubleshooting_url": "https://coder.com/troubleshoot" }, "sensitive_values": { + "display_apps": [ + {} + ], "metadata": [], "token": true } @@ -112,22 +151,35 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "85d0614c-3e44-4f20-b4bf-a015c8dfcaac", + "id": "90736626-71c9-4b76-bdfc-f6ce9b3dda05", "init_script": "", "login_before_ready": false, "metadata": [], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "021b1139-fa63-42ba-be1a-85f8456f3c28", + "token": "8c4ae7b9-12b7-4a9c-a55a-a98cfb049103", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], "metadata": [], "token": true } @@ -140,7 +192,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "6753149467284740901", + "id": "6980014108785645805", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tf b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tf index 3a713df629218..c7c4f9968b5c3 100644 --- a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tf +++ b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.6.1" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.dot b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.dot index b072ccafce750..d844163e70c1e 100644 --- a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.dot +++ b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.dot @@ -23,4 +23,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.json b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.json index 27958fe02d975..eee1d09317ba1 100644 --- a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.json +++ b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -17,11 +17,22 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, - "sensitive_values": {} + "sensitive_values": { + "display_apps": [], + "metadata": [] + } }, { "address": "coder_app.app1", @@ -33,9 +44,11 @@ "values": { "command": null, "display_name": null, + "external": false, "healthcheck": [], "icon": null, "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app1", @@ -56,6 +69,7 @@ "values": { "command": null, "display_name": null, + "external": false, "healthcheck": [ { "interval": 5, @@ -65,6 +79,7 @@ ], "icon": null, "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app2", @@ -87,9 +102,11 @@ "values": { "command": null, "display_name": null, + "external": false, "healthcheck": [], "icon": null, "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app3", @@ -133,17 +150,29 @@ "connection_timeout": 120, "dir": null, "env": null, + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, + "metadata": [], "token": true }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], + "metadata": [], "token": true } } @@ -162,9 +191,11 @@ "after": { "command": null, "display_name": null, + "external": false, "healthcheck": [], "icon": null, "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app1", @@ -196,6 +227,7 @@ "after": { "command": null, "display_name": null, + "external": false, "healthcheck": [ { "interval": 5, @@ -205,6 +237,7 @@ ], "icon": null, "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app2", @@ -240,9 +273,11 @@ "after": { "command": null, "display_name": null, + "external": false, "healthcheck": [], "icon": null, "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app3", @@ -287,7 +322,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.6.1" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -410,5 +445,6 @@ ] } ], - "timestamp": "2023-08-30T19:25:22Z" + "timestamp": "2024-05-22T17:03:03Z", + "errored": false } diff --git a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.dot b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.dot index b072ccafce750..d844163e70c1e 100644 --- a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.dot +++ b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.dot @@ -23,4 +23,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json index 92ede7e786e85..3ed04ae6ecab0 100644 --- a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json +++ b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -16,15 +16,36 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "c8dab94d-651c-4d9b-a19a-1c067a2976ea", + "id": "c950352c-7c4a-41cc-9049-ad07ded85c47", "init_script": "", + "login_before_ready": true, + "metadata": [], + "motd_file": null, + "order": null, "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, "startup_script": null, - "token": "96745539-f607-45f5-aa71-4f70f593ca6a", + "startup_script_behavior": null, + "startup_script_timeout": 300, + "token": "143c3974-49f5-4898-815b-c4044283ebc8", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], + "metadata": [], "token": true } }, @@ -36,13 +57,15 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { - "agent_id": "c8dab94d-651c-4d9b-a19a-1c067a2976ea", + "agent_id": "c950352c-7c4a-41cc-9049-ad07ded85c47", "command": null, "display_name": null, + "external": false, "healthcheck": [], "icon": null, - "id": "de5959cb-248c-44a0-bd04-9d5f28dfb415", + "id": "23135384-0e9f-4efc-b74c-d3e5e878ed67", "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app1", @@ -64,9 +87,10 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { - "agent_id": "c8dab94d-651c-4d9b-a19a-1c067a2976ea", + "agent_id": "c950352c-7c4a-41cc-9049-ad07ded85c47", "command": null, "display_name": null, + "external": false, "healthcheck": [ { "interval": 5, @@ -75,8 +99,9 @@ } ], "icon": null, - "id": "60aaa860-01d1-4d42-804b-2dc689676307", + "id": "01e73639-0fd1-4bcb-bd88-d22eb8244627", "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app2", @@ -100,13 +125,15 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { - "agent_id": "c8dab94d-651c-4d9b-a19a-1c067a2976ea", + "agent_id": "c950352c-7c4a-41cc-9049-ad07ded85c47", "command": null, "display_name": null, + "external": false, "healthcheck": [], "icon": null, - "id": "3455e899-9bf9-4c0e-ac5b-6f861d5541a0", + "id": "058c9054-9714-4a5f-9fde-8a451ab58620", "name": null, + "order": null, "relative_path": null, "share": "owner", "slug": "app3", @@ -128,7 +155,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "7562947701260361048", + "id": "9051436019409847411", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tf b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tf index 21e6f4206499c..b316db7c3cdf1 100644 --- a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tf +++ b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.9.0" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.dot b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.dot index 34f1ea8f3cb29..cbeae141ae3d0 100644 --- a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.dot +++ b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.dot @@ -20,4 +20,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.json b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.json index 54a7edb51063b..6084ae4435990 100644 --- a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.json +++ b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -23,11 +23,13 @@ "display_name": "Process Count", "interval": 5, "key": "process_count", + "order": null, "script": "ps -ef | wc -l", "timeout": 1 } ], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -37,6 +39,7 @@ "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [], "metadata": [ {} ] @@ -137,11 +140,13 @@ "display_name": "Process Count", "interval": 5, "key": "process_count", + "order": null, "script": "ps -ef | wc -l", "timeout": 1 } ], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -151,6 +156,7 @@ "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, "metadata": [ @@ -160,6 +166,7 @@ }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], "metadata": [ {} ], @@ -283,7 +290,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.9.0" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -424,5 +431,6 @@ ] } ], - "timestamp": "2023-08-30T19:25:27Z" + "timestamp": "2024-05-22T17:03:06Z", + "errored": false } diff --git a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.dot b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.dot index 34f1ea8f3cb29..cbeae141ae3d0 100644 --- a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.dot +++ b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.dot @@ -20,4 +20,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.json b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.json index f09fea579e70f..e617f565156ab 100644 --- a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.json +++ b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -16,8 +16,17 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "4d2791c5-e623-4c79-9c3a-81d70fde0f1d", + "id": "8352a117-1250-44ef-bba2-0abdb2a77665", "init_script": "", "login_before_ready": true, "metadata": [ @@ -25,21 +34,26 @@ "display_name": "Process Count", "interval": 5, "key": "process_count", + "order": 0, "script": "ps -ef | wc -l", "timeout": 1 } ], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "b068b430-4ecb-4116-a103-de3aaa1abd3e", + "token": "b46fd197-3be4-42f8-9c47-5a9e71a76ef6", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], "metadata": [ {} ], @@ -57,7 +71,7 @@ "daily_cost": 29, "hide": true, "icon": "/icon/server.svg", - "id": "0a46d060-c676-4324-a016-8dcdc7581d36", + "id": "1f7911d4-5b64-4e20-af9b-b6ee2aff602b", "item": [ { "is_null": false, @@ -72,7 +86,7 @@ "value": "" } ], - "resource_id": "6477445272839759515" + "resource_id": "7229373774865666851" }, "sensitive_values": { "item": [ @@ -96,7 +110,7 @@ "daily_cost": 20, "hide": true, "icon": "/icon/server.svg", - "id": "77a107bc-073e-4180-9f7f-0e60fc42b6c2", + "id": "34fe7a46-2a2f-4628-8946-ef80a7ffdb5e", "item": [ { "is_null": false, @@ -105,7 +119,7 @@ "value": "world" } ], - "resource_id": "6477445272839759515" + "resource_id": "7229373774865666851" }, "sensitive_values": { "item": [ @@ -125,7 +139,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "6477445272839759515", + "id": "7229373774865666851", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tf b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tf index c8ae6ca470cbf..cd46057ce8526 100644 --- a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tf +++ b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.14.1" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.dot b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.dot index ffe2fdf71254d..f3de2ca20df25 100644 --- a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.dot +++ b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.dot @@ -1,9 +1,19 @@ -digraph G { - rankdir = "RL"; - node [shape = rect, fontname = "sans-serif"]; - "coder_agent.main" [label="coder_agent.main"]; - "coder_metadata.about_info" [label="coder_metadata.about_info"]; - "null_resource.about" [label="null_resource.about"]; - "coder_metadata.about_info" -> "null_resource.about"; - "null_resource.about" -> "coder_agent.main"; +digraph { + compound = "true" + newrank = "true" + subgraph "root" { + "[root] coder_agent.main (expand)" [label = "coder_agent.main", shape = "box"] + "[root] coder_metadata.about_info (expand)" [label = "coder_metadata.about_info", shape = "box"] + "[root] null_resource.about (expand)" [label = "null_resource.about", shape = "box"] + "[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"] + "[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"] + "[root] coder_agent.main (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" + "[root] coder_metadata.about_info (expand)" -> "[root] null_resource.about (expand)" + "[root] null_resource.about (expand)" -> "[root] coder_agent.main (expand)" + "[root] null_resource.about (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_metadata.about_info (expand)" + "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.about (expand)" + "[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" + "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" + } } diff --git a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.json b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.json index 0d257f8115cd0..a03346a724115 100644 --- a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.json +++ b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.7.1-dev", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -29,6 +29,7 @@ } ], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -132,6 +133,7 @@ } ], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -253,7 +255,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.14.1" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -381,6 +383,6 @@ ] } ], - "timestamp": "2024-02-08T11:45:52Z", + "timestamp": "2024-05-22T17:03:05Z", "errored": false } diff --git a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.dot b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.dot index ffe2fdf71254d..f3de2ca20df25 100644 --- a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.dot +++ b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.dot @@ -1,9 +1,19 @@ -digraph G { - rankdir = "RL"; - node [shape = rect, fontname = "sans-serif"]; - "coder_agent.main" [label="coder_agent.main"]; - "coder_metadata.about_info" [label="coder_metadata.about_info"]; - "null_resource.about" [label="null_resource.about"]; - "coder_metadata.about_info" -> "null_resource.about"; - "null_resource.about" -> "coder_agent.main"; +digraph { + compound = "true" + newrank = "true" + subgraph "root" { + "[root] coder_agent.main (expand)" [label = "coder_agent.main", shape = "box"] + "[root] coder_metadata.about_info (expand)" [label = "coder_metadata.about_info", shape = "box"] + "[root] null_resource.about (expand)" [label = "null_resource.about", shape = "box"] + "[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"] + "[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"] + "[root] coder_agent.main (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" + "[root] coder_metadata.about_info (expand)" -> "[root] null_resource.about (expand)" + "[root] null_resource.about (expand)" -> "[root] coder_agent.main (expand)" + "[root] null_resource.about (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_metadata.about_info (expand)" + "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.about (expand)" + "[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" + "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" + } } diff --git a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.json b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.json index a33f027b67731..f8abe064ec94b 100644 --- a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.json +++ b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.7.1", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "90e2f3da-90d8-4cfd-8cfd-6e9c9da29a37", + "id": "847150eb-c3b6-497d-9dad-8e62d478cfff", "init_script": "", "login_before_ready": true, "metadata": [ @@ -40,13 +40,14 @@ } ], "motd_file": null, + "order": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "f6f9a6c5-d352-4029-b476-67edfe802806", + "token": "a0c4f2f5-cc40-4731-9028-636033229c9c", "troubleshooting_url": null }, "sensitive_values": { @@ -70,7 +71,7 @@ "daily_cost": 29, "hide": true, "icon": "/icon/server.svg", - "id": "a485c7b2-2b6c-42ab-b6d5-f51b681a5a41", + "id": "3feec3a3-6f9e-4cfb-b122-2273e345def0", "item": [ { "is_null": false, @@ -97,7 +98,7 @@ "value": "squirrel" } ], - "resource_id": "5837178340504502573" + "resource_id": "160324296641913729" }, "sensitive_values": { "item": [ @@ -120,7 +121,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "5837178340504502573", + "id": "160324296641913729", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tf b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tf index 0f6fcdfa423e6..82e7a6f95694e 100644 --- a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tf +++ b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.9.0" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.dot b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.dot index ba97f97407426..ef32a2ea2bc0a 100644 --- a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.dot +++ b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.dot @@ -21,4 +21,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.json b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.json index 169a8883f2596..12a6aaccdd7b7 100644 --- a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.json +++ b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -20,6 +20,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -29,6 +30,7 @@ "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [], "metadata": [] } }, @@ -68,6 +70,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -77,6 +80,7 @@ "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, "metadata": [], @@ -84,6 +88,7 @@ }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], "metadata": [], "token": true } @@ -113,7 +118,7 @@ ], "prior_state": { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -128,10 +133,9 @@ "default": null, "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "245304bd-d7c0-4dc0-b4b2-90a036245af0", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "7fb346d2-b8c2-4f2a-99d1-a8fd54cc479e", "mutable": false, "name": "Example", "option": null, @@ -156,10 +160,9 @@ "default": "ok", "description": "blah blah", "display_name": null, + "ephemeral": false, "icon": null, - "id": "bccaddc6-97f1-48aa-a1c0-3438cc96139d", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "0581cc2a-9e6d-4f04-93a6-88fcbd0757f0", "mutable": false, "name": "Sample", "option": null, @@ -182,7 +185,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.9.0" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -265,5 +268,6 @@ ] } }, - "timestamp": "2023-08-30T19:25:32Z" + "timestamp": "2024-05-22T17:03:11Z", + "errored": false } diff --git a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.dot b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.dot index ba97f97407426..ef32a2ea2bc0a 100644 --- a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.dot +++ b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.dot @@ -21,4 +21,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.json b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.json index c46df3e313f47..ce08e87bce074 100644 --- a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.json +++ b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -15,10 +15,9 @@ "default": null, "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "20e486cd-35aa-4916-8cbf-c8b6fd235cd1", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "5c9f037b-3cc1-4616-b4ba-9e7322856575", "mutable": false, "name": "Example", "option": null, @@ -43,10 +42,9 @@ "default": "ok", "description": "blah blah", "display_name": null, + "ephemeral": false, "icon": null, - "id": "6c077b3f-ba6c-482b-9232-12a3d4892700", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "71a4bcc8-bbcb-4619-9641-df3bc296f58e", "mutable": false, "name": "Sample", "option": null, @@ -72,22 +70,35 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "1414c0f9-be31-4efa-b1c9-57ab7c951b97", + "id": "327e8ab1-90be-4c87-ac7d-09630ae46827", "init_script": "", "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "712872cf-fde6-4683-91a3-9ad9fc759e14", + "token": "794a8a86-3bb9-4b3d-bbea-acff8b513964", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], "metadata": [], "token": true } @@ -100,7 +111,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "9132401905565595068", + "id": "3735840255017039964", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tf b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tf index d0c04b904d7e6..c05e8d5d4ae32 100644 --- a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tf +++ b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.11.0" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.dot b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.dot index 5ed08dde2ae7e..04e1353360488 100644 --- a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.dot +++ b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.dot @@ -33,4 +33,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.json b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.json index 7da089a43ea98..d4f402ce40102 100644 --- a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.json +++ b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -20,6 +20,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -29,6 +30,7 @@ "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [], "metadata": [] } }, @@ -68,6 +70,7 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, @@ -77,6 +80,7 @@ "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, "metadata": [], @@ -84,6 +88,7 @@ }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], "metadata": [], "token": true } @@ -113,7 +118,7 @@ ], "prior_state": { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -130,7 +135,7 @@ "display_name": null, "ephemeral": true, "icon": null, - "id": "858cb978-eef0-47e6-b7b8-7f9093303ad9", + "id": "1e85f9f5-54c2-4a6b-ba7f-8627386b94b7", "mutable": true, "name": "number_example", "option": null, @@ -157,7 +162,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "0add04ee-5c08-4702-b32e-727fc8c3fcd7", + "id": "9908f4c5-87f5-496c-9479-d0f7d49f0fdf", "mutable": false, "name": "number_example_max", "option": null, @@ -196,7 +201,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "90bc3085-b65d-496a-b52c-2a6bfda1c439", + "id": "3f2d0054-0440-4a00-98f6-befa9475a5f4", "mutable": false, "name": "number_example_max_zero", "option": null, @@ -235,7 +240,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "2499264c-7fa4-41da-9c78-6b5c86ddfd9c", + "id": "29abca17-5bd3-4ae3-9bd3-1e45301fc509", "mutable": false, "name": "number_example_min", "option": null, @@ -274,7 +279,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "dd6c2f30-6320-4e4a-ba82-deef628330f1", + "id": "95630cc0-8040-4126-92bb-967dbf8eb2ed", "mutable": false, "name": "number_example_min_max", "option": null, @@ -313,7 +318,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "8e04ddc9-c245-408d-92b0-dec669259b4a", + "id": "c256c60a-fdfe-42f1-bbaa-27880816a7bf", "mutable": false, "name": "number_example_min_zero", "option": null, @@ -348,7 +353,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.11.0" + "version_constraint": "0.22.0" }, "null": { "name": "null", @@ -545,5 +550,6 @@ ] } }, - "timestamp": "2023-08-30T19:25:35Z" + "timestamp": "2024-05-22T17:03:12Z", + "errored": false } diff --git a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.dot b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.dot index 5ed08dde2ae7e..04e1353360488 100644 --- a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.dot +++ b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.dot @@ -33,4 +33,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.json b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.json index d04c4ef4027ab..a09880e54e903 100644 --- a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.json +++ b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -17,7 +17,7 @@ "display_name": null, "ephemeral": true, "icon": null, - "id": "3eac44eb-b74f-471e-ae3a-783083f33b58", + "id": "f7cabe8c-f091-4ced-bc9b-873f54edf61b", "mutable": true, "name": "number_example", "option": null, @@ -44,7 +44,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "b767a52b-0b1d-4bea-a1b1-23180308a25d", + "id": "13b33312-d49b-4df3-af89-5d6ec840a6e4", "mutable": false, "name": "number_example_max", "option": null, @@ -83,7 +83,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "f6857c45-04cf-47ae-85bc-caab3341ead5", + "id": "d5ff002b-d039-42e6-b638-6bc2e3d54c2b", "mutable": false, "name": "number_example_max_zero", "option": null, @@ -122,7 +122,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "634a2e89-47c0-4d4b-aed6-b20177c959d5", + "id": "f382fcba-2634-44e7-ab26-866228d0679a", "mutable": false, "name": "number_example_min", "option": null, @@ -161,7 +161,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "9ae1f0ff-2fe9-460c-97b8-6bb0cb7fb2c7", + "id": "7f1c3032-1ed9-4602-80f8-cc84489bafc9", "mutable": false, "name": "number_example_min_max", "option": null, @@ -200,7 +200,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "e6951857-18a9-44b8-bc0d-d78375fdf92d", + "id": "c474219f-f1e7-4eca-921a-1ace9a8391ee", "mutable": false, "name": "number_example_min_zero", "option": null, @@ -238,22 +238,35 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "870767c4-6479-414c-aa08-a3f659ea3ec2", + "id": "138f6db3-bd8d-4a9a-8e61-abc1fdf3c3af", "init_script": "", "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "59f08143-3fcb-48d6-a80d-3a87863cd865", + "token": "1ef5dec0-3339-4e24-b781-0166cc6a9820", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], "metadata": [], "token": true } @@ -266,7 +279,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "643597385910559727", + "id": "5975950266738511043", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/rich-parameters/external-module/child-external-module/main.tf b/provisioner/terraform/testdata/rich-parameters/external-module/child-external-module/main.tf index a9a604f71d5d6..ac6f4c621a9d0 100644 --- a/provisioner/terraform/testdata/rich-parameters/external-module/child-external-module/main.tf +++ b/provisioner/terraform/testdata/rich-parameters/external-module/child-external-module/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.7.0" + version = "0.22.0" } docker = { source = "kreuzwerker/docker" diff --git a/provisioner/terraform/testdata/rich-parameters/external-module/main.tf b/provisioner/terraform/testdata/rich-parameters/external-module/main.tf index 946e1343451a0..55e942ec24e1f 100644 --- a/provisioner/terraform/testdata/rich-parameters/external-module/main.tf +++ b/provisioner/terraform/testdata/rich-parameters/external-module/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.7.0" + version = "0.22.0" } docker = { source = "kreuzwerker/docker" diff --git a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tf b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tf index 15e8a03d759ec..fc85769c8e9cc 100644 --- a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tf +++ b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.7.0" + version = "0.22.0" } } } diff --git a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.dot b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.dot index 2ecfcae1a2b5d..2deee6a1d36a2 100644 --- a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.dot +++ b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.dot @@ -56,4 +56,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.json b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.json index e3d5497b4d3e1..a881255a41e12 100644 --- a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.json +++ b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "planned_values": { "root_module": { "resources": [ @@ -20,14 +20,17 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, "startup_script_timeout": 300, "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [], "metadata": [] } }, @@ -67,14 +70,17 @@ "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, "startup_script_timeout": 300, "troubleshooting_url": null }, "after_unknown": { + "display_apps": true, "id": true, "init_script": true, "metadata": [], @@ -82,6 +88,7 @@ }, "before_sensitive": false, "after_sensitive": { + "display_apps": [], "metadata": [], "token": true } @@ -111,7 +118,7 @@ ], "prior_state": { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -126,10 +133,9 @@ "default": null, "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "67c923e2-cb0c-4955-b7bb-cdb8b7fab8be", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "2be3cd75-c44b-482e-8f78-679067d8e0a4", "mutable": false, "name": "Example", "option": [ @@ -147,15 +153,17 @@ } ], "optional": false, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "" }, "sensitive_values": { "option": [ {}, {} - ] + ], + "validation": [] } }, { @@ -169,19 +177,21 @@ "default": "4", "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "69ab9bf0-dadf-47ed-8486-b38b8d521c67", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "5a2f0407-8f11-4ac8-980d-75f919959f08", "mutable": false, "name": "number_example", "option": null, "optional": true, + "order": null, "type": "number", - "validation": null, + "validation": [], "value": "4" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } }, { "address": "data.coder_parameter.number_example_max_zero", @@ -194,20 +204,22 @@ "default": "-2", "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "4dcc41e1-8d07-4018-98df-de5fadce5aa3", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "cf4b28cf-ec3c-4f53-ae27-4733a9f7d71a", "mutable": false, "name": "number_example_max_zero", "option": null, "optional": true, + "order": null, "type": "number", "validation": [ { "error": "", "max": 0, + "max_disabled": false, "min": -3, + "min_disabled": false, "monotonic": "", "regex": "" } @@ -231,20 +243,22 @@ "default": "4", "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "c64e111c-496f-458d-924c-5ee13460f2ee", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "70d63380-2020-4377-ae05-cecb12c0d709", "mutable": false, "name": "number_example_min_max", "option": null, "optional": true, + "order": null, "type": "number", "validation": [ { "error": "", "max": 6, + "max_disabled": false, "min": 3, + "min_disabled": false, "monotonic": "", "regex": "" } @@ -268,20 +282,22 @@ "default": "4", "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "ecc13f6b-a8bd-423a-8585-ac08882cd25c", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "ec5827c2-2511-4f16-bd85-6249517c9e5b", "mutable": false, "name": "number_example_min_zero", "option": null, "optional": true, + "order": null, "type": "number", "validation": [ { "error": "", "max": 6, + "max_disabled": false, "min": 0, + "min_disabled": false, "monotonic": "", "regex": "" } @@ -305,19 +321,21 @@ "default": "ok", "description": "blah blah", "display_name": null, + "ephemeral": false, "icon": null, - "id": "ea6bbb0a-fdf5-46b4-8c68-22b59283fa6d", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "eec8845e-4316-450a-a5b7-eaa9567f469a", "mutable": false, "name": "Sample", "option": null, "optional": true, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "ok" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } } ], "child_modules": [ @@ -334,19 +352,21 @@ "default": "abcdef", "description": "First parameter from module", "display_name": null, + "ephemeral": false, "icon": null, - "id": "69e9bbe9-114a-43df-a050-a030efb3b89a", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "3b860d24-85ac-4540-b309-9321e732dfc4", "mutable": true, "name": "First parameter from module", "option": null, "optional": true, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "abcdef" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } }, { "address": "module.this_is_external_module.data.coder_parameter.second_parameter_from_module", @@ -359,19 +379,21 @@ "default": "ghijkl", "description": "Second parameter from module", "display_name": null, + "ephemeral": false, "icon": null, - "id": "607e122d-a7fd-4200-834f-c24e0e9a12c5", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "b36105e3-9bf1-43c7-a857-078ef1e8f95d", "mutable": true, "name": "Second parameter from module", "option": null, "optional": true, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "ghijkl" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } } ], "address": "module.this_is_external_module", @@ -389,19 +411,21 @@ "default": "abcdef", "description": "First parameter from child module", "display_name": null, + "ephemeral": false, "icon": null, - "id": "8cc5d1b7-391f-43ff-91e6-0293724a915b", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "a2bee9f2-8a3c-404c-839b-01b6cd840707", "mutable": true, "name": "First parameter from child module", "option": null, "optional": true, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "abcdef" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } }, { "address": "module.this_is_external_module.module.this_is_external_child_module.data.coder_parameter.child_second_parameter_from_module", @@ -414,19 +438,21 @@ "default": "ghijkl", "description": "Second parameter from child module", "display_name": null, + "ephemeral": false, "icon": null, - "id": "dfb6a1c4-82fd-47d3-b58c-65beddcd8b0d", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "deb13c45-ed6d-45b6-b6eb-d319143fa8f2", "mutable": true, "name": "Second parameter from child module", "option": null, "optional": true, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "ghijkl" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } } ], "address": "module.this_is_external_module.module.this_is_external_child_module" @@ -442,7 +468,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.7.0" + "version_constraint": "0.22.0" }, "module.this_is_external_module:docker": { "name": "docker", @@ -767,5 +793,6 @@ } } }, - "timestamp": "2023-08-30T19:25:30Z" + "timestamp": "2024-05-22T17:03:08Z", + "errored": false } diff --git a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.dot b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.dot index 2ecfcae1a2b5d..2deee6a1d36a2 100644 --- a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.dot +++ b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.dot @@ -56,4 +56,3 @@ digraph { "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } } - diff --git a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.json b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.json index b53dcd8568cef..a82bb9ea1925c 100644 --- a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.json +++ b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.5.5", + "terraform_version": "1.7.5", "values": { "root_module": { "resources": [ @@ -15,10 +15,9 @@ "default": null, "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "3d3a933a-b52b-4b38-bf91-0937615b1b29", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "7fa1e2f7-36a4-49cd-b92a-b3fc8732d359", "mutable": false, "name": "Example", "option": [ @@ -36,15 +35,17 @@ } ], "optional": false, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "" }, "sensitive_values": { "option": [ {}, {} - ] + ], + "validation": [] } }, { @@ -58,19 +59,21 @@ "default": "4", "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "f8b06fc2-f0c6-4483-8d10-d4601dfdd787", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "86a60580-7221-4bab-b229-9cb61bdb56a0", "mutable": false, "name": "number_example", "option": null, "optional": true, + "order": null, "type": "number", - "validation": null, + "validation": [], "value": "4" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } }, { "address": "data.coder_parameter.number_example_max_zero", @@ -83,20 +86,22 @@ "default": "-2", "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "886575fc-1863-49be-9a7d-125077df0ca5", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "ed6bc6e5-b4ff-48b9-88b0-df5faa74ae66", "mutable": false, "name": "number_example_max_zero", "option": null, "optional": true, + "order": null, "type": "number", "validation": [ { "error": "", "max": 0, + "max_disabled": false, "min": -3, + "min_disabled": false, "monotonic": "", "regex": "" } @@ -120,20 +125,22 @@ "default": "4", "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "feb32685-cfdc-4aed-b8bd-290d7e41822f", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "340b19e1-f651-4321-96b1-7908c2c66914", "mutable": false, "name": "number_example_min_max", "option": null, "optional": true, + "order": null, "type": "number", "validation": [ { "error": "", "max": 6, + "max_disabled": false, "min": 3, + "min_disabled": false, "monotonic": "", "regex": "" } @@ -157,20 +164,22 @@ "default": "4", "description": null, "display_name": null, + "ephemeral": false, "icon": null, - "id": "a5e72ae7-67f8-442c-837e-cce15f49fff0", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "f19c6763-2e55-40dd-9b49-82e9181e5b1b", "mutable": false, "name": "number_example_min_zero", "option": null, "optional": true, + "order": null, "type": "number", "validation": [ { "error": "", "max": 6, + "max_disabled": false, "min": 0, + "min_disabled": false, "monotonic": "", "regex": "" } @@ -194,19 +203,21 @@ "default": "ok", "description": "blah blah", "display_name": null, + "ephemeral": false, "icon": null, - "id": "1dcf470f-25f5-4c1d-a68e-1833f8239591", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "02169810-8080-4dc6-a656-5fbda745659e", "mutable": false, "name": "Sample", "option": null, "optional": true, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "ok" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } }, { "address": "coder_agent.dev", @@ -220,21 +231,35 @@ "auth": "token", "connection_timeout": 120, "dir": null, + "display_apps": [ + { + "port_forwarding_helper": true, + "ssh_helper": true, + "vscode": true, + "vscode_insiders": false, + "web_terminal": true + } + ], "env": null, - "id": "126f2d92-9556-4187-be69-5827ba3e7ddd", + "id": "42edc650-ddb6-4ed9-9624-7788d60d1507", "init_script": "", "login_before_ready": true, "metadata": [], "motd_file": null, + "order": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "e2021a4f-4db5-4e26-8ecd-c4b6c6e79e92", + "token": "c767a648-e670-4c6b-a28b-8559033e92a7", "troubleshooting_url": null }, "sensitive_values": { + "display_apps": [ + {} + ], "metadata": [], "token": true } @@ -247,7 +272,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "3170372688900630060", + "id": "7506678111935039701", "triggers": null }, "sensitive_values": {}, @@ -270,19 +295,21 @@ "default": "abcdef", "description": "First parameter from module", "display_name": null, + "ephemeral": false, "icon": null, - "id": "24874d90-5faf-4574-b54d-01a12e25159d", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "11b1ae03-cf81-4f60-9be1-bd4c0586516d", "mutable": true, "name": "First parameter from module", "option": null, "optional": true, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "abcdef" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } }, { "address": "module.this_is_external_module.data.coder_parameter.second_parameter_from_module", @@ -295,19 +322,21 @@ "default": "ghijkl", "description": "Second parameter from module", "display_name": null, + "ephemeral": false, "icon": null, - "id": "015a8629-347a-43f9-ba79-33d895f3b5b7", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "79d87261-bfda-46ee-958d-7d62252101ad", "mutable": true, "name": "Second parameter from module", "option": null, "optional": true, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "ghijkl" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } } ], "address": "module.this_is_external_module", @@ -325,19 +354,21 @@ "default": "abcdef", "description": "First parameter from child module", "display_name": null, + "ephemeral": false, "icon": null, - "id": "85793115-42a5-4e52-be7b-77dcf337ffb6", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "30c4c518-116a-4591-a571-886101cfcdfa", "mutable": true, "name": "First parameter from child module", "option": null, "optional": true, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "abcdef" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } }, { "address": "module.this_is_external_module.module.this_is_external_child_module.data.coder_parameter.child_second_parameter_from_module", @@ -350,19 +381,21 @@ "default": "ghijkl", "description": "Second parameter from child module", "display_name": null, + "ephemeral": false, "icon": null, - "id": "7754596b-a8b1-4a64-9ff1-27dd9473924c", - "legacy_variable": null, - "legacy_variable_name": null, + "id": "4c7d9f15-da45-453e-85eb-1d22c9baa54c", "mutable": true, "name": "Second parameter from child module", "option": null, "optional": true, + "order": null, "type": "string", - "validation": null, + "validation": [], "value": "ghijkl" }, - "sensitive_values": {} + "sensitive_values": { + "validation": [] + } } ], "address": "module.this_is_external_module.module.this_is_external_child_module" diff --git a/provisioner/terraform/testdata/version.txt b/provisioner/terraform/testdata/version.txt new file mode 100644 index 0000000000000..6a126f402d53d --- /dev/null +++ b/provisioner/terraform/testdata/version.txt @@ -0,0 +1 @@ +1.7.5 diff --git a/scripts/lib.sh b/scripts/lib.sh index 2839de2dbf9fa..cc742e936c1cc 100644 --- a/scripts/lib.sh +++ b/scripts/lib.sh @@ -131,18 +131,22 @@ requiredenvs() { } gh_auth() { - local fail=0 - if [[ "${CODER:-}" == "true" ]]; then - if ! output=$(coder external-auth access-token github 2>&1); then - log "ERROR: Could not authenticate with GitHub." - log "$output" - fail=1 + if [[ -z ${GITHUB_TOKEN:-} ]]; then + if [[ -n ${GH_TOKEN:-} ]]; then + export GITHUB_TOKEN=${GH_TOKEN} + elif [[ ${CODER:-} == true ]]; then + if ! output=$(coder external-auth access-token github 2>&1); then + # TODO(mafredri): We could allow checking `gh auth token` here. + log "${output}" + error "Could not authenticate with GitHub using Coder external auth." + else + export GITHUB_TOKEN=${output} + fi + elif token="$(gh auth token --hostname github.com 2>/dev/null)"; then + export GITHUB_TOKEN=${token} else - GITHUB_TOKEN=$(coder external-auth access-token github) - export GITHUB_TOKEN + error "GitHub authentication is required to run this command, please set GITHUB_TOKEN or run 'gh auth login'." fi - else - log "Please authenticate gh CLI by running 'gh auth login'" fi } diff --git a/scripts/release.sh b/scripts/release.sh index d1d2af1502d16..f7babf2809464 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -113,8 +113,17 @@ done # Check dependencies. dependencies gh jq sort -# Authenticate gh CLI -gh_auth +# Authenticate gh CLI. +# NOTE: Coder external-auth won't work because the GitHub App lacks permissions. +if [[ -z ${GITHUB_TOKEN:-} ]]; then + if [[ -n ${GH_TOKEN:-} ]]; then + export GITHUB_TOKEN=${GH_TOKEN} + elif token="$(gh auth token --hostname github.com 2>/dev/null)"; then + export GITHUB_TOKEN=${token} + else + error "GitHub authentication is required to run this command, please set GITHUB_TOKEN or run 'gh auth login'." + fi +fi if [[ -z $increment ]]; then # Default to patch versions. @@ -210,9 +219,11 @@ new_version="${new_version%$'\n'}" # Remove the trailing newline. release_notes="$(execrelative ./release/generate_release_notes.sh --old-version "$old_version" --new-version "$new_version" --ref "$ref")" +mkdir -p build release_notes_file="build/RELEASE-${new_version}.md" +release_notes_file_dryrun="build/RELEASE-${new_version}-DRYRUN.md" if ((dry_run)); then - release_notes_file="build/RELEASE-${new_version}-DRYRUN.md" + release_notes_file=${release_notes_file_dryrun} fi get_editor() { if command -v editor >/dev/null; then @@ -251,25 +262,47 @@ else fi log -if [[ -z ${editor} ]]; then - log "No editor found, please set the \$EDITOR environment variable for edit prompt." -else - while [[ ! ${edit:-} =~ ^[YyNn]$ ]]; do - read -p "Edit release notes in \"${editor}\"? (y/n) " -n 1 -r edit - log - done - if [[ ${edit} =~ ^[Yy]$ ]]; then - "${editor}" "${release_notes_file}" - release_notes2="$(<"$release_notes_file")" - if [[ "${release_notes}" != "${release_notes2}" ]]; then - log "Release notes have been updated!" - release_notes="${release_notes2}" - else - log "No changes detected..." +edit_release_notes() { + if [[ -z ${editor} ]]; then + log "No editor found, please set the \$EDITOR environment variable for edit prompt." + else + while [[ ! ${edit:-} =~ ^[YyNn]$ ]]; do + read -p "Edit release notes in \"${editor}\"? (y/n) " -n 1 -r edit + log + done + if [[ ${edit} =~ ^[Yy]$ ]]; then + "${editor}" "${release_notes_file}" + release_notes2="$(<"$release_notes_file")" + if [[ "${release_notes}" != "${release_notes2}" ]]; then + log "Release notes have been updated!" + release_notes="${release_notes2}" + else + log "No changes detected..." + fi fi fi -fi -log + log + + if ((!dry_run)) && [[ -f ${release_notes_file_dryrun} ]]; then + release_notes_dryrun="$(<"${release_notes_file_dryrun}")" + if [[ "${release_notes}" != "${release_notes_dryrun}" ]]; then + log "WARNING: Release notes differ from dry-run version:" + log + diff -u "${release_notes_file_dryrun}" "${release_notes_file}" || true + log + continue_with_new_release_notes= + while [[ ! ${continue_with_new_release_notes:-} =~ ^[YyNn]$ ]]; do + read -p "Continue with the new release notes anyway? (y/n) " -n 1 -r continue_with_new_release_notes + log + done + if [[ ${continue_with_new_release_notes} =~ ^[Nn]$ ]]; then + log + edit_release_notes + fi + fi + fi +} +edit_release_notes while [[ ! ${preview:-} =~ ^[YyNn]$ ]]; do read -p "Preview release notes? (y/n) " -n 1 -r preview @@ -341,7 +374,7 @@ You can follow the release progress [here](https://github.com/coder/coder/action create_pr_stash=1 fi maybedryrun "${dry_run}" git checkout -b "${pr_branch}" "${remote}/${branch}" - execrelative go run ./release autoversion --channel "${channel}" "${new_version}" --dry-run + execrelative go run ./release autoversion --channel "${channel}" "${new_version}" --dry-run="${dry_run}" maybedryrun "${dry_run}" git add docs maybedryrun "${dry_run}" git commit -m "${title}" # Return to previous branch. @@ -350,6 +383,9 @@ You can follow the release progress [here](https://github.com/coder/coder/action maybedryrun "${dry_run}" git stash pop fi + # Push the branch so it's available for gh to create the PR. + maybedryrun "${dry_run}" git push -u "${remote}" "${pr_branch}" + log "Creating pull request..." maybedryrun "${dry_run}" gh pr create \ --assignee "${pr_review_assignee}" \ diff --git a/scripts/release/check_commit_metadata.sh b/scripts/release/check_commit_metadata.sh index 41b4d4229d155..def18071af019 100755 --- a/scripts/release/check_commit_metadata.sh +++ b/scripts/release/check_commit_metadata.sh @@ -96,10 +96,14 @@ main() { # and main. These are sorted by commit title so that we can group # two cherry-picks together. declare -A cherry_pick_commits + declare -A renamed_cherry_pick_commits + declare -a renamed_cherry_pick_commits_pending git_cherry_out=$( { git log --no-merges --cherry-mark --pretty=format:"%m %H %s" "${to_ref}...origin/main" + echo git log --no-merges --cherry-mark --pretty=format:"%m %H %s" "${from_ref}...origin/main" + echo } | { grep '^=' || true; } | sort -u | sort -k3 ) if [[ -n ${git_cherry_out} ]]; then @@ -107,20 +111,44 @@ main() { # Iterate over the array in groups of two for ((i = 0; i < ${#cherry_picks[@]}; i += 2)); do mapfile -d ' ' -t parts1 <<<"${cherry_picks[i]}" - mapfile -d ' ' -t parts2 <<<"${cherry_picks[i + 1]}" commit1=${parts1[1]} title1=${parts1[*]:2} - commit2=${parts2[1]} - title2=${parts2[*]:2} + + title2= + if ((i + 1 < ${#cherry_picks[@]})); then + mapfile -d ' ' -t parts2 <<<"${cherry_picks[i + 1]}" + commit2=${parts2[1]} + title2=${parts2[*]:2} + fi if [[ ${title1} != "${title2}" ]]; then - error "Invariant failed, cherry-picked commits have different titles: ${title1} != ${title2}" + log "Invariant failed, cherry-picked commits have different titles: \"${title1%$'\n'}\" != \"${title2%$'\n'}\", attempting to check commit body for cherry-pick information..." + + renamed=$(git show "${commit1}" | sed -ne 's/.*cherry picked from commit \([0-9a-f]*\).*/\1/p') + if [[ -n ${renamed} ]]; then + log "Found renamed cherry-pick commit ${commit1} -> ${renamed}" + renamed_cherry_pick_commits[${commit1}]=${renamed} + renamed_cherry_pick_commits[${renamed}]=${commit1} + continue + fi + + log "Not a cherry-pick commit, adding ${commit1} to pending list..." + renamed_cherry_pick_commits_pending+=("${commit1}") + i=$((i - 1)) + continue fi cherry_pick_commits[${commit1}]=${commit2} cherry_pick_commits[${commit2}]=${commit1} done fi + for commit in "${renamed_cherry_pick_commits_pending[@]}"; do + log "Checking if pending commit ${commit} has a corresponding cherry-pick..." + if [[ ! -v renamed_cherry_pick_commits[${commit}] ]]; then + error "Invariant failed, cherry-picked commit ${commit} has no corresponding original commit" + fi + log "Found matching cherry-pick commit ${commit} -> ${renamed_cherry_pick_commits[${commit}]}" + done # Get abbreviated and full commit hashes and titles for each commit. git_log_out="$(git log --no-merges --left-right --pretty=format:"%m %h %H %s" "${range}")" @@ -209,6 +237,15 @@ main() { fi fi + author= + if [[ -v authors[${commit_sha_long}] ]]; then + author=${authors[${commit_sha_long}]} + if [[ ${author} == "app/dependabot" ]]; then + log "Skipping commit by app/dependabot ${commit_sha_short} (${commit_sha_long})" + continue + fi + fi + if [[ ${left_right} == "<" ]]; then # Skip commits that are already in main. log "Skipping commit ${commit_sha_short} from other branch (${commit_sha_long} ${title})" @@ -218,7 +255,7 @@ main() { COMMIT_METADATA_COMMITS+=("${commit_sha_long_orig}") # Safety-check, guarantee all commits had their metadata fetched. - if [[ ! -v authors[${commit_sha_long}] ]] || [[ ! -v labels[${commit_sha_long}] ]]; then + if [[ -z ${author} ]] || [[ ! -v labels[${commit_sha_long}] ]]; then if [[ ${ignore_missing_metadata} != 1 ]]; then error "Metadata missing for commit ${commit_sha_short} (${commit_sha_long})" else @@ -228,8 +265,8 @@ main() { # Store the commit title for later use. COMMIT_METADATA_TITLE[${commit_sha_short}]=${title} - if [[ -v authors[${commit_sha_long}] ]]; then - COMMIT_METADATA_AUTHORS[${commit_sha_short}]="@${authors[${commit_sha_long}]}" + if [[ -n ${author} ]]; then + COMMIT_METADATA_AUTHORS[${commit_sha_short}]="@${author}" fi # Create humanized titles where possible, examples: diff --git a/scripts/release/generate_release_notes.sh b/scripts/release/generate_release_notes.sh index 7aa24ee4fe198..b593ccad3cc5b 100755 --- a/scripts/release/generate_release_notes.sh +++ b/scripts/release/generate_release_notes.sh @@ -147,7 +147,6 @@ for commit in "${commits[@]}"; do title="${title} (${commit})" fi line="- ${title}" - line=${line//) (/, )} if [[ -v COMMIT_METADATA_AUTHORS[${commit}] ]]; then line+=" (${COMMIT_METADATA_AUTHORS[${commit}]})" fi diff --git a/scripts/release/main.go b/scripts/release/main.go index 919205b76db65..3eb67c7b96225 100644 --- a/scripts/release/main.go +++ b/scripts/release/main.go @@ -62,9 +62,9 @@ func main() { Value: serpent.BoolOf(&r.debug), }, { - Flag: "gh-token", + Flag: "github-token", Description: "GitHub personal access token.", - Env: "GH_TOKEN", + Env: "GITHUB_TOKEN", Value: serpent.StringOf(&r.ghToken), }, { @@ -242,10 +242,11 @@ func (r *releaseCommand) promoteVersionToStable(ctx context.Context, inv *serpen updatedBody := removeMainlineBlurb(newStable.GetBody()) updatedBody = addStableSince(time.Now().UTC(), updatedBody) updatedNewStable.Body = github.String(updatedBody) + updatedNewStable.MakeLatest = github.String("true") updatedNewStable.Prerelease = github.Bool(false) updatedNewStable.Draft = github.Bool(false) if !r.dryRun { - _, _, err = client.Repositories.EditRelease(ctx, owner, repo, newStable.GetID(), newStable) + _, _, err = client.Repositories.EditRelease(ctx, owner, repo, newStable.GetID(), updatedNewStable) if err != nil { return xerrors.Errorf("edit release failed: %w", err) } @@ -268,6 +269,10 @@ func cloneRelease(r *github.RepositoryRelease) *github.RepositoryRelease { // // > ## Stable (since April 23, 2024) func addStableSince(date time.Time, body string) string { + // Protect against adding twice. + if strings.Contains(body, "> ## Stable (since") { + return body + } return fmt.Sprintf("> ## Stable (since %s)\n\n", date.Format("January 02, 2006")) + body } diff --git a/scripts/release/main_internal_test.go b/scripts/release/main_internal_test.go index 74a6d46d05c8a..d5d10706683a2 100644 --- a/scripts/release/main_internal_test.go +++ b/scripts/release/main_internal_test.go @@ -131,12 +131,19 @@ func Test_addStableSince(t *testing.T) { date := time.Date(2024, time.April, 23, 0, 0, 0, 0, time.UTC) body := "## Changelog" - expected := "> ## Stable (since April 23, 2024)\n\n## Changelog" - result := addStableSince(date, body) + want := "> ## Stable (since April 23, 2024)\n\n## Changelog" + got := addStableSince(date, body) - if diff := cmp.Diff(expected, result); diff != "" { + if diff := cmp.Diff(want, got); diff != "" { require.Fail(t, "addStableSince() mismatch (-want +got):\n%s", diff) } + + // Test that it doesn't add twice. + got = addStableSince(date, got) + + if diff := cmp.Diff(want, got); diff != "" { + require.Fail(t, "addStableSince() mismatch (-want +got):\n%s", diff, "addStableSince() should not add twice") + } } func Test_release_autoversion(t *testing.T) { diff --git a/scripts/release/tag_version.sh b/scripts/release/tag_version.sh index 16a2011016047..2bf3e88646cc2 100755 --- a/scripts/release/tag_version.sh +++ b/scripts/release/tag_version.sh @@ -86,8 +86,8 @@ fi # shellcheck source=scripts/release/check_commit_metadata.sh source "$SCRIPT_DIR/check_commit_metadata.sh" "$old_version" "$ref" +prev_increment=$increment if ((COMMIT_METADATA_BREAKING == 1)); then - prev_increment=$increment if [[ $increment == patch ]]; then increment=minor fi diff --git a/scripts/release_promote_stable.sh b/scripts/release_promote_stable.sh index 33b55d3855d41..1ac0f8318d749 100755 --- a/scripts/release_promote_stable.sh +++ b/scripts/release_promote_stable.sh @@ -4,6 +4,9 @@ set -euo pipefail # shellcheck source=scripts/lib.sh source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" +# Make sure GITHUB_TOKEN is set for the release command. +gh_auth + # This script is a convenience wrapper around the release promote command. # # Sed hack to make help text look like this script. diff --git a/site/jest.setup.ts b/site/jest.setup.ts index 6282295870681..40bb92fa44965 100644 --- a/site/jest.setup.ts +++ b/site/jest.setup.ts @@ -41,6 +41,7 @@ global.scrollTo = jest.fn(); window.HTMLElement.prototype.scrollIntoView = jest.fn(); window.open = jest.fn(); +navigator.sendBeacon = jest.fn(); // Polyfill the getRandomValues that is used on utils/random.ts Object.defineProperty(global.self, "crypto", { diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index d91a6b430de27..b2cae01d2480a 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -162,6 +162,7 @@ export interface BuildInfoResponse { readonly external_url: string; readonly version: string; readonly dashboard_url: string; + readonly telemetry: boolean; readonly workspace_proxy: boolean; readonly agent_api_version: string; readonly upgrade_message: string; @@ -497,7 +498,6 @@ export interface ExternalAuthConfig { readonly app_installations_url: string; readonly no_refresh: boolean; readonly scopes: readonly string[]; - readonly extra_token_keys: readonly string[]; readonly device_flow: boolean; readonly device_code_url: string; readonly regex: string; diff --git a/site/src/pages/DeploySettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.stories.tsx b/site/src/pages/DeploySettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.stories.tsx index 22a57140511f5..3ed1d8143738e 100644 --- a/site/src/pages/DeploySettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.stories.tsx +++ b/site/src/pages/DeploySettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.stories.tsx @@ -19,7 +19,6 @@ const meta: Meta = { app_installations_url: "", no_refresh: false, scopes: [], - extra_token_keys: [], device_flow: true, device_code_url: "", display_icon: "", diff --git a/site/src/pages/LoginPage/LoginPage.tsx b/site/src/pages/LoginPage/LoginPage.tsx index f05c0b40d981f..d519a7673816b 100644 --- a/site/src/pages/LoginPage/LoginPage.tsx +++ b/site/src/pages/LoginPage/LoginPage.tsx @@ -1,4 +1,4 @@ -import type { FC } from "react"; +import { useEffect, type FC } from "react"; import { Helmet } from "react-helmet-async"; import { useQuery } from "react-query"; import { Navigate, useLocation, useNavigate } from "react-router-dom"; @@ -8,6 +8,7 @@ import { useAuthContext } from "contexts/auth/AuthProvider"; import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata"; import { getApplicationName } from "utils/appearance"; import { retrieveRedirect } from "utils/redirect"; +import { sendDeploymentEvent } from "utils/telemetry"; import { LoginPageView } from "./LoginPageView"; export const LoginPage: FC = () => { @@ -19,16 +20,37 @@ export const LoginPage: FC = () => { signIn, isSigningIn, signInError, + user, } = useAuthContext(); const authMethodsQuery = useQuery(authMethods()); const redirectTo = retrieveRedirect(location.search); const applicationName = getApplicationName(); const navigate = useNavigate(); - const { metadata } = useEmbeddedMetadata(); const buildInfoQuery = useQuery(buildInfo(metadata["build-info"])); + useEffect(() => { + if (!buildInfoQuery.data || isSignedIn) { + // isSignedIn already tracks with window.href! + return; + } + // This uses `navigator.sendBeacon`, so navigating away will not prevent it! + sendDeploymentEvent(buildInfoQuery.data, { + type: "deployment_login", + user_id: user?.id, + }); + }, [isSignedIn, buildInfoQuery.data, user?.id]); + if (isSignedIn) { + if (buildInfoQuery.data) { + // This uses `navigator.sendBeacon`, so window.href + // will not stop the request from being sent! + sendDeploymentEvent(buildInfoQuery.data, { + type: "deployment_login", + user_id: user?.id, + }); + } + // If the redirect is going to a workspace application, and we // are missing authentication, then we need to change the href location // to trigger a HTTP request. This allows the BE to generate the auth @@ -74,6 +96,15 @@ export const LoginPage: FC = () => { isSigningIn={isSigningIn} onSignIn={async ({ email, password }) => { await signIn(email, password); + if (buildInfoQuery.data) { + // This uses `navigator.sendBeacon`, so navigating away + // will not prevent it! + sendDeploymentEvent(buildInfoQuery.data, { + type: "deployment_login", + user_id: user?.id, + }); + } + navigate("/"); }} /> diff --git a/site/src/pages/SetupPage/SetupPage.test.tsx b/site/src/pages/SetupPage/SetupPage.test.tsx index 2f558316d95cc..fb22dcf4f303a 100644 --- a/site/src/pages/SetupPage/SetupPage.test.tsx +++ b/site/src/pages/SetupPage/SetupPage.test.tsx @@ -3,7 +3,7 @@ import userEvent from "@testing-library/user-event"; import { HttpResponse, http } from "msw"; import { createMemoryRouter } from "react-router-dom"; import type { Response, User } from "api/typesGenerated"; -import { MockUser } from "testHelpers/entities"; +import { MockBuildInfo, MockUser } from "testHelpers/entities"; import { renderWithRouter, waitForLoaderToBeRemoved, @@ -99,4 +99,42 @@ describe("Setup Page", () => { await fillForm(); await waitFor(() => screen.findByText("Templates")); }); + it("calls sendBeacon with telemetry", async () => { + const sendBeacon = jest.fn(); + Object.defineProperty(window.navigator, "sendBeacon", { + value: sendBeacon, + }); + renderWithRouter( + createMemoryRouter( + [ + { + path: "/setup", + element: , + }, + { + path: "/templates", + element:

Templates

, + }, + ], + { initialEntries: ["/setup"] }, + ), + ); + await waitForLoaderToBeRemoved(); + await waitFor(() => { + expect(navigator.sendBeacon).toBeCalledWith( + "https://coder.com/api/track-deployment", + new Blob( + [ + JSON.stringify({ + type: "deployment_setup", + deployment_id: MockBuildInfo.deployment_id, + }), + ], + { + type: "application/json", + }, + ), + ); + }); + }); }); diff --git a/site/src/pages/SetupPage/SetupPage.tsx b/site/src/pages/SetupPage/SetupPage.tsx index fc5d0cf35f957..20899157c3b30 100644 --- a/site/src/pages/SetupPage/SetupPage.tsx +++ b/site/src/pages/SetupPage/SetupPage.tsx @@ -1,11 +1,14 @@ -import type { FC } from "react"; +import { useEffect, type FC } from "react"; import { Helmet } from "react-helmet-async"; -import { useMutation } from "react-query"; +import { useMutation, useQuery } from "react-query"; import { Navigate, useNavigate } from "react-router-dom"; +import { buildInfo } from "api/queries/buildInfo"; import { createFirstUser } from "api/queries/users"; import { Loader } from "components/Loader/Loader"; import { useAuthContext } from "contexts/auth/AuthProvider"; +import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata"; import { pageTitle } from "utils/page"; +import { sendDeploymentEvent } from "utils/telemetry"; import { SetupPageView } from "./SetupPageView"; export const SetupPage: FC = () => { @@ -18,7 +21,17 @@ export const SetupPage: FC = () => { } = useAuthContext(); const createFirstUserMutation = useMutation(createFirstUser()); const setupIsComplete = !isConfiguringTheFirstUser; + const { metadata } = useEmbeddedMetadata(); + const buildInfoQuery = useQuery(buildInfo(metadata["build-info"])); const navigate = useNavigate(); + useEffect(() => { + if (!buildInfoQuery.data) { + return; + } + sendDeploymentEvent(buildInfoQuery.data, { + type: "deployment_setup", + }); + }, [buildInfoQuery.data]); if (isLoading) { return ; diff --git a/site/src/pages/SetupPage/SetupPageView.stories.tsx b/site/src/pages/SetupPage/SetupPageView.stories.tsx index 239fb10cab930..030115fbbddb9 100644 --- a/site/src/pages/SetupPage/SetupPageView.stories.tsx +++ b/site/src/pages/SetupPage/SetupPageView.stories.tsx @@ -22,6 +22,15 @@ export const FormError: Story = { }, }; +export const TrialError: Story = { + args: { + error: mockApiError({ + message: "Couldn't generate trial!", + detail: "It looks like your team is already trying Coder.", + }), + }, +}; + export const Loading: Story = { args: { isLoading: true, diff --git a/site/src/pages/SetupPage/SetupPageView.tsx b/site/src/pages/SetupPage/SetupPageView.tsx index af673acacc333..7f97deb973991 100644 --- a/site/src/pages/SetupPage/SetupPageView.tsx +++ b/site/src/pages/SetupPage/SetupPageView.tsx @@ -1,13 +1,16 @@ import LoadingButton from "@mui/lab/LoadingButton"; +import AlertTitle from "@mui/material/AlertTitle"; import Autocomplete from "@mui/material/Autocomplete"; import Checkbox from "@mui/material/Checkbox"; import Link from "@mui/material/Link"; import MenuItem from "@mui/material/MenuItem"; import TextField from "@mui/material/TextField"; +import { isAxiosError } from "axios"; import { type FormikContextType, useFormik } from "formik"; import type { FC } from "react"; import * as Yup from "yup"; import type * as TypesGen from "api/typesGenerated"; +import { Alert, AlertDetail } from "components/Alert/Alert"; import { FormFields, VerticalForm } from "components/Form/Form"; import { CoderIcon } from "components/Icons/CoderIcon"; import { SignInLayout } from "components/SignInLayout/SignInLayout"; @@ -187,7 +190,7 @@ export const SetupPageView: FC = ({
- Start a 30-day free trial of Enterprise + Start a free trial of Enterprise ({ @@ -316,6 +319,21 @@ export const SetupPageView: FC = ({ )} + {isAxiosError(error) && error.response?.data?.message && ( + + {error.response.data.message} + {error.response.data.detail && ( + + {error.response.data.detail} +
+ + Contact Sales + +
+ )} +
+ )} + = ({ const [showControlsAnyway, setShowControlsAnyway] = useState(false); let onClickScheduleIcon: (() => void) | undefined; - let activity: ReactNode = null; if (activityStatus === "connected") { onClickScheduleIcon = () => setShowControlsAnyway((it) => !it); - activity = Connected; const now = dayjs(); const noRequiredStopSoon = @@ -183,12 +180,7 @@ const AutostopDisplay: FC = ({ // User has shown controls manually, or we should warn about a nearby required stop if (!showControlsAnyway && noRequiredStopSoon) { - return ( - <> - {activity} - - - ); + return ; } } @@ -239,24 +231,18 @@ const AutostopDisplay: FC = ({ if (tooltip) { return ( - <> - {activity} - - {display} - {controls} - - + + {display} + {controls} + ); } return ( - <> - {activity} - - {display} - {controls} - - + + {display} + {controls} + ); }; diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 17bb48c1d00bd..da4787419fab9 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -202,6 +202,7 @@ export const MockBuildInfo: TypesGen.BuildInfoResponse = { workspace_proxy: false, upgrade_message: "My custom upgrade message", deployment_id: "510d407f-e521-4180-b559-eab4a6d802b8", + telemetry: true, }; export const MockSupportLinks: TypesGen.LinkConfig[] = [ diff --git a/site/src/utils/telemetry.ts b/site/src/utils/telemetry.ts new file mode 100644 index 0000000000000..3b6906690cd6a --- /dev/null +++ b/site/src/utils/telemetry.ts @@ -0,0 +1,33 @@ +import type { BuildInfoResponse } from "api/typesGenerated"; + +// sendDeploymentEvent sends a CORs payload to coder.com +// to track a deployment event. +export const sendDeploymentEvent = ( + buildInfo: BuildInfoResponse, + payload: { + type: "deployment_setup" | "deployment_login"; + user_id?: string; + }, +) => { + if (typeof navigator === "undefined" || !navigator.sendBeacon) { + // It's fine if we don't report this, it's not required! + return; + } + if (!buildInfo.telemetry) { + return; + } + navigator.sendBeacon( + "https://coder.com/api/track-deployment", + new Blob( + [ + JSON.stringify({ + ...payload, + deployment_id: buildInfo.deployment_id, + }), + ], + { + type: "application/json", + }, + ), + ); +};