Compare commits

...

15 Commits

Author SHA1 Message Date
Stephen Kirby 82ed9e4dc7 chore: patch 2.12.4 (#13925)
* fix(site): enable dormant workspace to be deleted (#13850)

(cherry picked from commit 01b30eaa32)

* chore: add SVG desktop icon (#13765)

* chore: add SVG desktop icon

* fix: add desktop icon to to icons.json

(cherry picked from commit 21a923a7a0)

* fix: update import order for Storybook

---------

Co-authored-by: Bruno Quaresma <bruno@coder.com>
Co-authored-by: Michael Smith <throwawayclover@gmail.com>
2024-07-17 20:36:52 -04:00
Steven Masley 534d4ea752 chore: external auth validate response "Forbidden" should return invalid, not an error (#13446)
* chore: add unit test to delete workspace from suspended user
* chore: account for forbidden as well as unauthorized response codes

(cherry picked from commit 27f26910b6)
2024-06-24 17:38:32 +00:00
Stephen Kirby 8ce8700424 fixed changelog script release channel flag (#13649)
(cherry picked from commit b9d83c75de)
2024-06-24 17:38:12 +00:00
Stephen Kirby b9779af5b2 fixed script ref (#13647)
(cherry picked from commit 3d6c9799e3)
2024-06-24 17:38:02 +00:00
Mathias Fredriksson e54ff57a9a chore(scripts): fix release promote stable to set latest tag (#13471)
(cherry picked from commit 9a757f8e74)
2024-06-21 19:37:12 +00:00
Mathias Fredriksson ae220f52e7 chore(scripts): fix dry run for autoversion in release.sh (#13470)
(cherry picked from commit 3b7f9534fb)
2024-06-21 19:37:06 +00:00
Kyle Carberry 90f82da311 fix: write server config to telemetry (#13590)
* fix: add external auth configs to telemetry

* Refactor telemetry to send the entire config

* gen

* Fix linting

(cherry picked from commit 3a1fa04590)
2024-06-21 19:36:53 +00:00
Kyle Carberry 201cb1cbed fix: display trial errors in the dashboard (#13601)
* fix: display trial errors in the dashboard

The error was essentially being ignored before!

* Remove day mention in product of trial

* fmt

(cherry picked from commit 7049d7a881)
2024-06-21 19:36:37 +00:00
Kyle Carberry b701620a01 feat: add cross-origin reporting for telemetry in the dashboard (#13612)
* feat: add cross-origin reporting for telemetry in the dashboard

* Respect the telemetry flag

* Fix embedded metadata

* Fix compilation error

* Fix linting

(cherry picked from commit 0793a4b35b)
2024-06-21 19:36:31 +00:00
Kyle Carberry 0703fc6888 fix: track login page correctly (#13618)
(cherry picked from commit 495eea452f)
2024-06-21 19:36:25 +00:00
Kyle Carberry a9e5648557 fix: remove connected button (#13625)
It didn't make a lot of sense in current form. It will when we improve autostop.

(cherry picked from commit 3ef12ac284)
2024-06-21 19:36:19 +00:00
Jon Ayers 3fbfb534d0 fix: only render tooltip when require_active_version enabled (#13484)
(cherry picked from commit 7995d7c3d6)
2024-06-06 02:53:47 +00:00
Colin Adler 5e69a9d18b fix(site): show workspace start button when require active version is enabled (#13482)
(cherry picked from commit f1b42a15fa)
2024-06-06 02:35:33 +00:00
Mathias Fredriksson ba0bf43de4 chore(scripts): fix unbound variable in tag_version.sh (#13428)
(cherry picked from commit a51076a4cd)
2024-06-04 16:15:21 +00:00
Colin Adler 40af6206cc chore: upgrade terraform to v1.8.5 (#13429)
(cherry picked from commit b723da9e91)
2024-06-04 16:14:45 +00:00
75 changed files with 629 additions and 380 deletions
+1 -1
View File
@@ -7,5 +7,5 @@ runs:
- name: Install Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.7.5
terraform_version: 1.8.4
terraform_wrapper: false
+1
View File
@@ -33,4 +33,5 @@ extend-exclude = [
"**/pnpm-lock.yaml",
"tailnet/testdata/**",
"site/src/pages/SetupPage/countries.tsx",
"provisioner/terraform/testdata/**",
]
+1 -1
View File
@@ -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",
})
+10 -23
View File
@@ -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 {
+4 -6
View File
@@ -8717,6 +8717,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"
@@ -9782,12 +9786,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"
+4 -6
View File
@@ -7761,6 +7761,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"
@@ -8769,12 +8773,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"
+1
View File
@@ -450,6 +450,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,
+17 -2
View File
@@ -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:
+1 -1
View File
@@ -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
}
+6 -6
View File
@@ -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) {
+49 -87
View File
@@ -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() {}
-11
View File
@@ -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
+74
View File
@@ -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()
+3 -2
View File
@@ -392,7 +392,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
@@ -2162,11 +2162,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"`
+1 -1
View File
@@ -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",
+2 -5
View File
@@ -1234,6 +1234,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
@@ -1248,6 +1249,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 | | |
@@ -2009,7 +2011,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",
@@ -2382,7 +2383,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",
@@ -2801,7 +2801,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",
@@ -2824,7 +2823,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. |
@@ -8844,7 +8842,6 @@ _None_
"device_flow": true,
"display_icon": "string",
"display_name": "string",
"extra_token_keys": ["string"],
"id": "string",
"no_refresh": true,
"regex": "string",
+1 -1
View File
@@ -54,7 +54,7 @@ RUN mkdir -p /opt/terraform
# The below step is optional if you wish to keep the existing version.
# See https://github.com/coder/coder/blob/main/provisioner/terraform/install.go#L23-L24
# for supported Terraform versions.
ARG TERRAFORM_VERSION=1.7.5
ARG TERRAFORM_VERSION=1.8.4
RUN apk update && \
apk del terraform && \
curl -LOs https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip \
+1 -1
View File
@@ -171,7 +171,7 @@ RUN apt-get update --quiet && apt-get install --yes \
# NOTE: In scripts/Dockerfile.base we specifically install Terraform version 1.7.5.
# Installing the same version here to match.
RUN wget -O /tmp/terraform.zip "https://releases.hashicorp.com/terraform/1.7.5/terraform_1.7.5_linux_amd64.zip" && \
RUN wget -O /tmp/terraform.zip "https://releases.hashicorp.com/terraform/1.8.4/terraform_1.8.4_linux_amd64.zip" && \
unzip /tmp/terraform.zip -d /usr/local/bin && \
rm -f /tmp/terraform.zip && \
chmod +x /usr/local/bin/terraform && \
+16
View File
@@ -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)
@@ -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{
+1 -1
View File
@@ -250,7 +250,7 @@ EOF
main() {
MAINLINE=1
STABLE=0
TERRAFORM_VERSION="1.7.5"
TERRAFORM_VERSION="1.8.4"
if [ "${TRACE-}" ]; then
set -x
+2 -2
View File
@@ -20,10 +20,10 @@ var (
// when Terraform is not available on the system.
// NOTE: Keep this in sync with the version in scripts/Dockerfile.base.
// NOTE: Keep this in sync with the version in install.sh.
TerraformVersion = version.Must(version.NewVersion("1.7.5"))
TerraformVersion = version.Must(version.NewVersion("1.8.4"))
minTerraformVersion = version.Must(version.NewVersion("1.1.0"))
maxTerraformVersion = version.Must(version.NewVersion("1.7.9")) // use .9 to automatically allow patch releases
maxTerraformVersion = version.Must(version.NewVersion("1.8.9")) // use .9 to automatically allow patch releases
terraformMinorVersionMismatch = xerrors.New("Terraform binary minor version mismatch.")
)
+6 -3
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
}
],
@@ -259,6 +260,8 @@
]
}
],
"timestamp": "2024-05-22T17:02:40Z",
"timestamp": "2024-05-31T22:25:19Z",
"applyable": true,
"complete": true,
"errored": false
}
+5 -5
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -26,7 +26,7 @@
}
],
"env": null,
"id": "f26b1d53-799e-4fbb-9fd3-71e60b37eacd",
"id": "2941e1eb-40f5-41cf-9e08-8f0f1a80d430",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -38,7 +38,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "ce663074-ebea-44cb-b6d1-321f590f7982",
"token": "3105121f-9b54-4c91-b497-9da9bb05c5b6",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -69,7 +69,7 @@
"outputs": {
"script": ""
},
"random": "8031375470547649400"
"random": "3895262600016319159"
},
"sensitive_values": {
"inputs": {},
@@ -84,7 +84,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "3370916843136140681",
"id": "5027788252939043492",
"triggers": null
},
"sensitive_values": {},
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -204,6 +205,8 @@
]
}
},
"timestamp": "2024-05-22T17:02:43Z",
"timestamp": "2024-05-31T22:25:20Z",
"applyable": true,
"complete": true,
"errored": false
}
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -26,7 +26,7 @@
}
],
"env": null,
"id": "9d869fc3-c185-4278-a5d2-873f809a4449",
"id": "da093356-6550-4e76-bb9e-0269cede7e31",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -38,7 +38,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "418bb1d6-49d8-4340-ac84-ed6991457ff9",
"token": "ebcb7f0e-4b80-4972-b434-1a42aa650d78",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -57,7 +57,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "3681188688307687011",
"id": "2686005653093770315",
"triggers": null
},
"sensitive_values": {},
@@ -74,7 +74,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "6055360096088266226",
"id": "1732714319726388691",
"triggers": null
},
"sensitive_values": {},
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -204,6 +205,8 @@
]
}
},
"timestamp": "2024-05-22T17:02:45Z",
"timestamp": "2024-05-31T22:25:22Z",
"applyable": true,
"complete": true,
"errored": false
}
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -26,7 +26,7 @@
}
],
"env": null,
"id": "d9c497fe-1dc4-4551-b46d-282f775e9509",
"id": "e56c4e1a-6b1a-4007-880c-875dc6400b73",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -38,7 +38,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "6fa01f69-de93-4610-b942-b787118146f8",
"token": "b3666f42-cc88-454e-93bd-553f71306dbe",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -57,7 +57,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "2012753940926517215",
"id": "8818573993093135925",
"triggers": null
},
"sensitive_values": {},
@@ -73,7 +73,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "2163283012438694669",
"id": "2487290649323445841",
"triggers": null
},
"sensitive_values": {},
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -42,7 +42,8 @@
"display_apps": [
{}
],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -203,6 +204,8 @@
]
}
},
"timestamp": "2024-05-22T17:02:50Z",
"timestamp": "2024-05-31T22:25:26Z",
"applyable": true,
"complete": true,
"errored": false
}
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -26,7 +26,7 @@
}
],
"env": null,
"id": "c55cfcad-5422-46e5-a144-e933660bacd3",
"id": "cd49cbe2-97f4-4980-9b13-4e4008f4d594",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -38,7 +38,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "e170615d-a3a2-4dc4-a65e-4990ceeb79e5",
"token": "4b1c44cb-d960-42ef-b19e-60d169085657",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -57,7 +57,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "3512108359019802900",
"id": "6613171819431602989",
"triggers": null
},
"sensitive_values": {},
+6 -3
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -42,7 +42,8 @@
"display_apps": [
{}
],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -203,6 +204,8 @@
]
}
},
"timestamp": "2024-05-22T17:02:48Z",
"timestamp": "2024-05-31T22:25:24Z",
"applyable": true,
"complete": true,
"errored": false
}
+4 -4
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -26,7 +26,7 @@
}
],
"env": null,
"id": "3fb63a4e-bb0e-4380-9ed9-8b1581943b1f",
"id": "dac3e164-c9d2-43e2-89ee-54ce5955e551",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -38,7 +38,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "eb5720a7-91fd-4e37-8085-af3c8205702c",
"token": "99ccf297-47b1-4c7c-819e-0bac896b12bd",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -57,7 +57,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "2929624824161973000",
"id": "5268162908997861371",
"triggers": null
},
"sensitive_values": {},
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -118,7 +119,7 @@
],
"prior_state": {
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -227,6 +228,8 @@
]
}
},
"timestamp": "2024-05-22T17:02:52Z",
"timestamp": "2024-05-31T22:25:28Z",
"applyable": true,
"complete": true,
"errored": false
}
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -54,7 +54,7 @@
}
],
"env": null,
"id": "923df4d0-cf96-4cf8-aaff-426e58927a81",
"id": "2fcac464-b22b-4567-8391-7cdf592dae14",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -66,7 +66,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "f5328221-90c7-4056-83b4-7b76d6f46580",
"token": "57bcc78a-ed9b-46f9-9901-ffbdfb325871",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -85,7 +85,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "4621387386750422041",
"id": "7076770981685522602",
"triggers": null
},
"sensitive_values": {},
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -118,7 +119,7 @@
],
"prior_state": {
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -222,6 +223,8 @@
]
}
},
"timestamp": "2024-05-22T17:02:55Z",
"timestamp": "2024-05-31T22:25:30Z",
"applyable": true,
"complete": true,
"errored": false
}
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -52,7 +52,7 @@
}
],
"env": null,
"id": "48a24332-1a90-48d9-9e03-b4e9f09c6eab",
"id": "c924e5b7-e2cb-4eb5-993e-3cc489ed5213",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -64,7 +64,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "6a2ae93f-3f25-423d-aa97-b2f1c5d9c20b",
"token": "cc8ceb98-822f-4b8f-b645-2162fada1dfb",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -83,7 +83,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "8095584601893320918",
"id": "7049248910828562611",
"triggers": null
},
"sensitive_values": {},
+6 -3
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -224,6 +225,8 @@
]
}
],
"timestamp": "2024-05-22T17:02:57Z",
"timestamp": "2024-05-31T22:25:32Z",
"applyable": true,
"complete": true,
"errored": false
}
+6 -6
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -26,7 +26,7 @@
}
],
"env": null,
"id": "3bc8e20f-2024-4014-ac11-806e7e1a1e24",
"id": "b691d6a2-76de-4441-ac90-3260282dc1fb",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -38,7 +38,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "6ef0492b-8dbe-4c61-8eb8-a37acb671278",
"token": "244bf23b-b483-46f9-b2ff-7a6e746c836f",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -57,8 +57,8 @@
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"agent_id": "3bc8e20f-2024-4014-ac11-806e7e1a1e24",
"id": "7ba714fa-f2b8-4d33-8987-f67466505033",
"agent_id": "b691d6a2-76de-4441-ac90-3260282dc1fb",
"id": "66ce959f-b821-4657-9bdb-6290c3b3a0b9",
"instance_id": "example"
},
"sensitive_values": {},
@@ -74,7 +74,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "4065206823139127011",
"id": "3867175311980978156",
"triggers": null
},
"sensitive_values": {},
+6 -3
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -326,6 +327,8 @@
]
}
],
"timestamp": "2024-05-22T17:02:59Z",
"timestamp": "2024-05-31T22:25:34Z",
"applyable": true,
"complete": true,
"errored": false
}
+8 -8
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -26,7 +26,7 @@
}
],
"env": null,
"id": "d8d2ed23-193d-4784-9ce5-7bc0d879bb14",
"id": "d3eece5c-3d36-4e77-a67c-284d6a665004",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -38,7 +38,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "0555adfc-e969-4fd2-8cfd-47560bd1b5a3",
"token": "793d9e17-fe59-4e70-83ee-76397b81a5bd",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -58,13 +58,13 @@
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"agent_id": "d8d2ed23-193d-4784-9ce5-7bc0d879bb14",
"agent_id": "d3eece5c-3d36-4e77-a67c-284d6a665004",
"command": null,
"display_name": "app1",
"external": false,
"healthcheck": [],
"icon": null,
"id": "11fa3ff2-d6ba-41ca-b1df-6c98d395c0b8",
"id": "02a5c323-badd-4a9d-bb5e-6926b8c3f317",
"name": null,
"order": null,
"relative_path": null,
@@ -89,13 +89,13 @@
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"agent_id": "d8d2ed23-193d-4784-9ce5-7bc0d879bb14",
"agent_id": "d3eece5c-3d36-4e77-a67c-284d6a665004",
"command": null,
"display_name": "app2",
"external": false,
"healthcheck": [],
"icon": null,
"id": "cd1a2e37-adbc-49f0-bd99-033c62a1533e",
"id": "3f9b0fb0-fc06-49ed-b869-27b570b86b47",
"name": null,
"order": null,
"relative_path": null,
@@ -119,7 +119,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "4490911212417021152",
"id": "6739553050203442390",
"triggers": null
},
"sensitive_values": {},
+12 -6
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -61,7 +62,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -91,7 +93,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -121,7 +124,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -460,6 +464,8 @@
]
}
},
"timestamp": "2024-05-22T17:03:01Z",
"timestamp": "2024-05-31T22:25:36Z",
"applyable": true,
"complete": true,
"errored": false
}
+10 -10
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -26,7 +26,7 @@
}
],
"env": null,
"id": "0ffc6582-b017-404e-b83f-48e4a5ab38bc",
"id": "2cd8a28d-b73c-4801-8748-5681512b99ed",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -38,7 +38,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "b7f0a913-ecb1-4c80-8559-fbcb435d53d0",
"token": "68c874c4-2f0d-4dff-9fd7-67209e9a08c7",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -71,7 +71,7 @@
}
],
"env": null,
"id": "1780ae95-844c-4d5c-94fb-6ccfe4a7656d",
"id": "2e773a6e-0e57-428d-bdf8-414c2aaa55fc",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -83,7 +83,7 @@
"startup_script": null,
"startup_script_behavior": "non-blocking",
"startup_script_timeout": 30,
"token": "695f8765-3d3d-4da0-9a5a-bb7b1f568bde",
"token": "98944f07-1265-4329-8fd3-c92aac95855c",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -116,7 +116,7 @@
}
],
"env": null,
"id": "333b7856-24ac-46be-9ae3-e4981b25481d",
"id": "9568f00b-0bd8-4982-a502-7b37562b1fa3",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -128,7 +128,7 @@
"startup_script": null,
"startup_script_behavior": "blocking",
"startup_script_timeout": 300,
"token": "50ddfb93-264f-4f64-8c8d-db7d8d37c0a1",
"token": "8bf8789b-9efc-4517-aa30-89b99c46dd75",
"troubleshooting_url": "https://coder.com/troubleshoot"
},
"sensitive_values": {
@@ -161,7 +161,7 @@
}
],
"env": null,
"id": "90736626-71c9-4b76-bdfc-f6ce9b3dda05",
"id": "403e5299-2f3e-499c-b90a-2fa6fc9e44e6",
"init_script": "",
"login_before_ready": false,
"metadata": [],
@@ -173,7 +173,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "8c4ae7b9-12b7-4a9c-a55a-a98cfb049103",
"token": "a10e5bfb-9756-4210-a112-877f2cfbdc0a",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -192,7 +192,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "6980014108785645805",
"id": "2053669122262711043",
"triggers": null
},
"sensitive_values": {},
+6 -3
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -445,6 +446,8 @@
]
}
],
"timestamp": "2024-05-22T17:03:03Z",
"timestamp": "2024-05-31T22:25:38Z",
"applyable": true,
"complete": true,
"errored": false
}
+10 -10
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -26,7 +26,7 @@
}
],
"env": null,
"id": "c950352c-7c4a-41cc-9049-ad07ded85c47",
"id": "26bc229a-d911-4d91-8b18-c59a2f2939f4",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -38,7 +38,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "143c3974-49f5-4898-815b-c4044283ebc8",
"token": "3be506a9-b085-4bd8-a6e9-ac1769aedac5",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -57,13 +57,13 @@
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"agent_id": "c950352c-7c4a-41cc-9049-ad07ded85c47",
"agent_id": "26bc229a-d911-4d91-8b18-c59a2f2939f4",
"command": null,
"display_name": null,
"external": false,
"healthcheck": [],
"icon": null,
"id": "23135384-0e9f-4efc-b74c-d3e5e878ed67",
"id": "cbfb480c-49f0-41dc-a5e5-fa8ab21514e7",
"name": null,
"order": null,
"relative_path": null,
@@ -87,7 +87,7 @@
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"agent_id": "c950352c-7c4a-41cc-9049-ad07ded85c47",
"agent_id": "26bc229a-d911-4d91-8b18-c59a2f2939f4",
"command": null,
"display_name": null,
"external": false,
@@ -99,7 +99,7 @@
}
],
"icon": null,
"id": "01e73639-0fd1-4bcb-bd88-d22eb8244627",
"id": "6cc74cc4-edd4-482a-be9c-46243008081d",
"name": null,
"order": null,
"relative_path": null,
@@ -125,13 +125,13 @@
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"agent_id": "c950352c-7c4a-41cc-9049-ad07ded85c47",
"agent_id": "26bc229a-d911-4d91-8b18-c59a2f2939f4",
"command": null,
"display_name": null,
"external": false,
"healthcheck": [],
"icon": null,
"id": "058c9054-9714-4a5f-9fde-8a451ab58620",
"id": "7b2131ed-3850-439e-8942-6c83fe02ce0c",
"name": null,
"order": null,
"relative_path": null,
@@ -155,7 +155,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "9051436019409847411",
"id": "6270198559972381862",
"triggers": null
},
"sensitive_values": {},
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -42,7 +42,8 @@
"display_apps": [],
"metadata": [
{}
]
],
"token": true
}
},
{
@@ -431,6 +432,8 @@
]
}
],
"timestamp": "2024-05-22T17:03:06Z",
"timestamp": "2024-05-31T22:25:42Z",
"applyable": true,
"complete": true,
"errored": false
}
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -26,7 +26,7 @@
}
],
"env": null,
"id": "8352a117-1250-44ef-bba2-0abdb2a77665",
"id": "15b21cea-46cb-4e70-b648-56dceff97236",
"init_script": "",
"login_before_ready": true,
"metadata": [
@@ -47,7 +47,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "b46fd197-3be4-42f8-9c47-5a9e71a76ef6",
"token": "3308a570-7944-4238-aca8-fbc3644d7548",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -71,7 +71,7 @@
"daily_cost": 29,
"hide": true,
"icon": "/icon/server.svg",
"id": "1f7911d4-5b64-4e20-af9b-b6ee2aff602b",
"id": "28db1106-e6f0-41ff-b707-3100a99cadff",
"item": [
{
"is_null": false,
@@ -86,7 +86,7 @@
"value": ""
}
],
"resource_id": "7229373774865666851"
"resource_id": "3221770356529482934"
},
"sensitive_values": {
"item": [
@@ -110,7 +110,7 @@
"daily_cost": 20,
"hide": true,
"icon": "/icon/server.svg",
"id": "34fe7a46-2a2f-4628-8946-ef80a7ffdb5e",
"id": "a30b56a6-c122-485a-a128-4210600ad17f",
"item": [
{
"is_null": false,
@@ -119,7 +119,7 @@
"value": "world"
}
],
"resource_id": "7229373774865666851"
"resource_id": "3221770356529482934"
},
"sensitive_values": {
"item": [
@@ -139,7 +139,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "7229373774865666851",
"id": "3221770356529482934",
"triggers": null
},
"sensitive_values": {},
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -42,7 +42,8 @@
"display_apps": [],
"metadata": [
{}
]
],
"token": true
}
},
{
@@ -383,6 +384,8 @@
]
}
],
"timestamp": "2024-05-22T17:03:05Z",
"timestamp": "2024-05-31T22:25:40Z",
"applyable": true,
"complete": true,
"errored": false
}
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -26,7 +26,7 @@
}
],
"env": null,
"id": "847150eb-c3b6-497d-9dad-8e62d478cfff",
"id": "5d102462-7646-4aae-bdac-c8b9906fb5b3",
"init_script": "",
"login_before_ready": true,
"metadata": [
@@ -47,7 +47,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "a0c4f2f5-cc40-4731-9028-636033229c9c",
"token": "1d1ccced-ce84-4cbf-a80f-f17a59e948a0",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -71,7 +71,7 @@
"daily_cost": 29,
"hide": true,
"icon": "/icon/server.svg",
"id": "3feec3a3-6f9e-4cfb-b122-2273e345def0",
"id": "35194a0a-0012-4da3-9e3a-a4d7bdcc9638",
"item": [
{
"is_null": false,
@@ -98,7 +98,7 @@
"value": "squirrel"
}
],
"resource_id": "160324296641913729"
"resource_id": "2094194534443319186"
},
"sensitive_values": {
"item": [
@@ -121,7 +121,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "160324296641913729",
"id": "2094194534443319186",
"triggers": null
},
"sensitive_values": {},
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -118,7 +119,7 @@
],
"prior_state": {
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -135,7 +136,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "7fb346d2-b8c2-4f2a-99d1-a8fd54cc479e",
"id": "5f79d935-c5bc-47e4-8152-eed302afc455",
"mutable": false,
"name": "Example",
"option": null,
@@ -162,7 +163,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "0581cc2a-9e6d-4f04-93a6-88fcbd0757f0",
"id": "e8af506e-91e7-457a-8e68-f33109f30e6a",
"mutable": false,
"name": "Sample",
"option": null,
@@ -268,6 +269,8 @@
]
}
},
"timestamp": "2024-05-22T17:03:11Z",
"timestamp": "2024-05-31T22:25:46Z",
"applyable": true,
"complete": true,
"errored": false
}
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -17,7 +17,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "5c9f037b-3cc1-4616-b4ba-9e7322856575",
"id": "487e2328-8fa1-472f-a35d-5c017f5a2621",
"mutable": false,
"name": "Example",
"option": null,
@@ -44,7 +44,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "71a4bcc8-bbcb-4619-9641-df3bc296f58e",
"id": "c85ec281-458c-4932-a10d-049be7e1b8f8",
"mutable": false,
"name": "Sample",
"option": null,
@@ -80,7 +80,7 @@
}
],
"env": null,
"id": "327e8ab1-90be-4c87-ac7d-09630ae46827",
"id": "3d98abaf-7a38-450f-9fc9-eaebbebb1f1f",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -92,7 +92,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "794a8a86-3bb9-4b3d-bbea-acff8b513964",
"token": "3000e759-60df-4470-8f51-50ea4bc6a1ad",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -111,7 +111,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "3735840255017039964",
"id": "4580074114866058503",
"triggers": null
},
"sensitive_values": {},
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -118,7 +119,7 @@
],
"prior_state": {
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -135,7 +136,7 @@
"display_name": null,
"ephemeral": true,
"icon": null,
"id": "1e85f9f5-54c2-4a6b-ba7f-8627386b94b7",
"id": "c2d5292e-1dea-434b-b5cc-dc288c2a512b",
"mutable": true,
"name": "number_example",
"option": null,
@@ -162,7 +163,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "9908f4c5-87f5-496c-9479-d0f7d49f0fdf",
"id": "689418c1-935c-40ad-aa9f-37ab4f8d9501",
"mutable": false,
"name": "number_example_max",
"option": null,
@@ -201,7 +202,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "3f2d0054-0440-4a00-98f6-befa9475a5f4",
"id": "bc7db79f-d6ef-45a2-9bbf-50710eb1db8c",
"mutable": false,
"name": "number_example_max_zero",
"option": null,
@@ -240,7 +241,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "29abca17-5bd3-4ae3-9bd3-1e45301fc509",
"id": "5e88eade-4255-4693-86bf-2c0331ca2a06",
"mutable": false,
"name": "number_example_min",
"option": null,
@@ -279,7 +280,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "95630cc0-8040-4126-92bb-967dbf8eb2ed",
"id": "26c34bb9-535d-45d7-bebd-1dcb2300f242",
"mutable": false,
"name": "number_example_min_max",
"option": null,
@@ -318,7 +319,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "c256c60a-fdfe-42f1-bbaa-27880816a7bf",
"id": "3b55387f-0117-4d34-b585-14959f4a9267",
"mutable": false,
"name": "number_example_min_zero",
"option": null,
@@ -550,6 +551,8 @@
]
}
},
"timestamp": "2024-05-22T17:03:12Z",
"timestamp": "2024-05-31T22:25:48Z",
"applyable": true,
"complete": true,
"errored": false
}
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -17,7 +17,7 @@
"display_name": null,
"ephemeral": true,
"icon": null,
"id": "f7cabe8c-f091-4ced-bc9b-873f54edf61b",
"id": "1f836366-337f-47a9-bc49-f4810b2f1078",
"mutable": true,
"name": "number_example",
"option": null,
@@ -44,7 +44,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "13b33312-d49b-4df3-af89-5d6ec840a6e4",
"id": "d58e721b-0134-42b6-b4b9-bb012f43a439",
"mutable": false,
"name": "number_example_max",
"option": null,
@@ -83,7 +83,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "d5ff002b-d039-42e6-b638-6bc2e3d54c2b",
"id": "4c3ff771-15ab-4a33-8067-45d5d44a5f7e",
"mutable": false,
"name": "number_example_max_zero",
"option": null,
@@ -122,7 +122,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "f382fcba-2634-44e7-ab26-866228d0679a",
"id": "11f8f368-f829-403a-8ad9-3a10df1db0bf",
"mutable": false,
"name": "number_example_min",
"option": null,
@@ -161,7 +161,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "7f1c3032-1ed9-4602-80f8-cc84489bafc9",
"id": "9de03421-e747-4084-b808-90464beb8ab4",
"mutable": false,
"name": "number_example_min_max",
"option": null,
@@ -200,7 +200,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "c474219f-f1e7-4eca-921a-1ace9a8391ee",
"id": "eb75256a-66d6-45d6-a0f5-331a885742e4",
"mutable": false,
"name": "number_example_min_zero",
"option": null,
@@ -248,7 +248,7 @@
}
],
"env": null,
"id": "138f6db3-bd8d-4a9a-8e61-abc1fdf3c3af",
"id": "e6810890-032b-4a01-9562-b9a8428dcc97",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -260,7 +260,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "1ef5dec0-3339-4e24-b781-0166cc6a9820",
"token": "c162e35d-a066-472c-a469-91d6b116fa6f",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -279,7 +279,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "5975950266738511043",
"id": "8464994280406150541",
"triggers": null
},
"sensitive_values": {},
+17 -14
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.2",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"planned_values": {
"root_module": {
"resources": [
@@ -31,7 +31,8 @@
},
"sensitive_values": {
"display_apps": [],
"metadata": []
"metadata": [],
"token": true
}
},
{
@@ -118,7 +119,7 @@
],
"prior_state": {
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -135,7 +136,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "2be3cd75-c44b-482e-8f78-679067d8e0a4",
"id": "e5891365-ddf0-417c-a5d7-9ae7cdc76754",
"mutable": false,
"name": "Example",
"option": [
@@ -179,7 +180,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "5a2f0407-8f11-4ac8-980d-75f919959f08",
"id": "b95cd221-cdca-4d6e-98d0-e4fb6d90dc32",
"mutable": false,
"name": "number_example",
"option": null,
@@ -206,7 +207,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "cf4b28cf-ec3c-4f53-ae27-4733a9f7d71a",
"id": "e1e5bce0-ea22-401d-8253-1b9175077abc",
"mutable": false,
"name": "number_example_max_zero",
"option": null,
@@ -245,7 +246,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "70d63380-2020-4377-ae05-cecb12c0d709",
"id": "26a6eaca-c9ae-4130-a734-6c290637b250",
"mutable": false,
"name": "number_example_min_max",
"option": null,
@@ -284,7 +285,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "ec5827c2-2511-4f16-bd85-6249517c9e5b",
"id": "ad985f1d-21fe-4ce1-988d-903084016cb4",
"mutable": false,
"name": "number_example_min_zero",
"option": null,
@@ -323,7 +324,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "eec8845e-4316-450a-a5b7-eaa9567f469a",
"id": "9465cc3a-703a-4218-8fa4-d16a1631e648",
"mutable": false,
"name": "Sample",
"option": null,
@@ -354,7 +355,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "3b860d24-85ac-4540-b309-9321e732dfc4",
"id": "547f8420-0630-4c4d-9507-e2d63640d0d9",
"mutable": true,
"name": "First parameter from module",
"option": null,
@@ -381,7 +382,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "b36105e3-9bf1-43c7-a857-078ef1e8f95d",
"id": "5c32dcad-d54a-474f-97f0-fbcc8aaba9bd",
"mutable": true,
"name": "Second parameter from module",
"option": null,
@@ -413,7 +414,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "a2bee9f2-8a3c-404c-839b-01b6cd840707",
"id": "2362ba5e-0779-472c-bd3c-22446fd14075",
"mutable": true,
"name": "First parameter from child module",
"option": null,
@@ -440,7 +441,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "deb13c45-ed6d-45b6-b6eb-d319143fa8f2",
"id": "0a8f6df4-364f-4d5f-b935-7dee8c568e10",
"mutable": true,
"name": "Second parameter from child module",
"option": null,
@@ -793,6 +794,8 @@
}
}
},
"timestamp": "2024-05-22T17:03:08Z",
"timestamp": "2024-05-31T22:25:44Z",
"applyable": true,
"complete": true,
"errored": false
}
+14 -14
View File
@@ -1,6 +1,6 @@
{
"format_version": "1.0",
"terraform_version": "1.7.5",
"terraform_version": "1.8.4",
"values": {
"root_module": {
"resources": [
@@ -17,7 +17,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "7fa1e2f7-36a4-49cd-b92a-b3fc8732d359",
"id": "9f041124-ccf3-4b7b-9e0d-4d37335a6f98",
"mutable": false,
"name": "Example",
"option": [
@@ -61,7 +61,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "86a60580-7221-4bab-b229-9cb61bdb56a0",
"id": "ab5035e4-8dab-453d-92bc-9b866af26c78",
"mutable": false,
"name": "number_example",
"option": null,
@@ -88,7 +88,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "ed6bc6e5-b4ff-48b9-88b0-df5faa74ae66",
"id": "bdf84ab6-1029-4645-a2df-cd897f30c145",
"mutable": false,
"name": "number_example_max_zero",
"option": null,
@@ -127,7 +127,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "340b19e1-f651-4321-96b1-7908c2c66914",
"id": "b283766e-7e58-459d-a81f-aa71a95bbc0b",
"mutable": false,
"name": "number_example_min_max",
"option": null,
@@ -166,7 +166,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "f19c6763-2e55-40dd-9b49-82e9181e5b1b",
"id": "7a4f8f6d-d81a-4b15-9d5b-6f221f2a6b07",
"mutable": false,
"name": "number_example_min_zero",
"option": null,
@@ -205,7 +205,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "02169810-8080-4dc6-a656-5fbda745659e",
"id": "fd12f0d0-87dc-4d88-bcdc-352c11bd2144",
"mutable": false,
"name": "Sample",
"option": null,
@@ -241,7 +241,7 @@
}
],
"env": null,
"id": "42edc650-ddb6-4ed9-9624-7788d60d1507",
"id": "a20d4cf7-2d49-4ab8-8858-a9e1531e7033",
"init_script": "",
"login_before_ready": true,
"metadata": [],
@@ -253,7 +253,7 @@
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "c767a648-e670-4c6b-a28b-8559033e92a7",
"token": "0d8692b3-746f-4f2e-b0cc-7952ee240ba4",
"troubleshooting_url": null
},
"sensitive_values": {
@@ -272,7 +272,7 @@
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "7506678111935039701",
"id": "9033341587141190203",
"triggers": null
},
"sensitive_values": {},
@@ -297,7 +297,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "11b1ae03-cf81-4f60-9be1-bd4c0586516d",
"id": "6be6ebff-574c-4ab6-b314-a65f4f20446e",
"mutable": true,
"name": "First parameter from module",
"option": null,
@@ -324,7 +324,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "79d87261-bfda-46ee-958d-7d62252101ad",
"id": "d7e3d42e-dc51-47f2-ae5f-1b1bdaa85e25",
"mutable": true,
"name": "Second parameter from module",
"option": null,
@@ -356,7 +356,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "30c4c518-116a-4591-a571-886101cfcdfa",
"id": "69f71896-5cc4-44d0-ae7a-b7a5514a07ae",
"mutable": true,
"name": "First parameter from child module",
"option": null,
@@ -383,7 +383,7 @@
"display_name": null,
"ephemeral": false,
"icon": null,
"id": "4c7d9f15-da45-453e-85eb-1d22c9baa54c",
"id": "9a2b177e-8f3c-4d6b-b302-3ba2f0e6c76b",
"mutable": true,
"name": "Second parameter from child module",
"option": null,
+1 -1
View File
@@ -1 +1 @@
1.7.5
1.8.4
+1 -1
View File
@@ -26,7 +26,7 @@ RUN apk add --no-cache \
# Terraform was disabled in the edge repo due to a build issue.
# https://gitlab.alpinelinux.org/alpine/aports/-/commit/f3e263d94cfac02d594bef83790c280e045eba35
# Using wget for now. Note that busybox unzip doesn't support streaming.
RUN ARCH="$(arch)"; if [ "${ARCH}" == "x86_64" ]; then ARCH="amd64"; elif [ "${ARCH}" == "aarch64" ]; then ARCH="arm64"; fi; wget -O /tmp/terraform.zip "https://releases.hashicorp.com/terraform/1.7.5/terraform_1.7.5_linux_${ARCH}.zip" && \
RUN ARCH="$(arch)"; if [ "${ARCH}" == "x86_64" ]; then ARCH="amd64"; elif [ "${ARCH}" == "aarch64" ]; then ARCH="arm64"; fi; wget -O /tmp/terraform.zip "https://releases.hashicorp.com/terraform/1.8.4/terraform_1.8.4_linux_${ARCH}.zip" && \
busybox unzip /tmp/terraform.zip -d /usr/local/bin && \
rm -f /tmp/terraform.zip && \
chmod +x /usr/local/bin/terraform && \
+3 -3
View File
@@ -217,7 +217,7 @@ release_branch=${tag_version[0]}
new_version=${tag_version[1]}
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")"
release_notes="$(execrelative ./release/generate_release_notes.sh --old-version "$old_version" --new-version "$new_version" --ref "$ref" --$channel)"
mkdir -p build
release_notes_file="build/RELEASE-${new_version}.md"
@@ -374,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.
@@ -384,7 +384,7 @@ You can follow the release progress [here](https://github.com/coder/coder/action
fi
# Push the branch so it's available for gh to create the PR.
maybedryrun "${dry_run}" git push -u "{remote}" "${pr_branch}"
maybedryrun "${dry_run}" git push -u "${remote}" "${pr_branch}"
log "Creating pull request..."
maybedryrun "${dry_run}" gh pr create \
+1
View File
@@ -242,6 +242,7 @@ 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 {
+1 -1
View File
@@ -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
+1
View File
@@ -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", {
+1 -1
View File
@@ -171,6 +171,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;
@@ -506,7 +507,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;
@@ -19,7 +19,6 @@ const meta: Meta<typeof ExternalAuthSettingsPageView> = {
app_installations_url: "",
no_refresh: false,
scopes: [],
extra_token_keys: [],
device_flow: true,
device_code_url: "",
display_icon: "",
+33 -2
View File
@@ -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("/");
}}
/>
+39 -1
View File
@@ -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: <SetupPage />,
},
{
path: "/templates",
element: <h1>Templates</h1>,
},
],
{ 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",
},
),
);
});
});
});
+15 -2
View File
@@ -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 <Loader fullscreen />;
@@ -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,
+19 -1
View File
@@ -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<SetupPageViewProps> = ({
<div css={{ fontSize: 14, paddingTop: 4 }}>
<span css={{ display: "block", fontWeight: 600 }}>
Start a 30-day free trial of Enterprise
Start a free trial of Enterprise
</span>
<span
css={(theme) => ({
@@ -316,6 +319,21 @@ export const SetupPageView: FC<SetupPageViewProps> = ({
</>
)}
{isAxiosError(error) && error.response?.data?.message && (
<Alert severity="error">
<AlertTitle>{error.response.data.message}</AlertTitle>
{error.response.data.detail && (
<AlertDetail>
{error.response.data.detail}
<br />
<Link target="_blank" href="https://coder.com/contact/sales">
Contact Sales
</Link>
</AlertDetail>
)}
</Alert>
)}
<LoadingButton
fullWidth
loading={isLoading}
@@ -1,4 +1,5 @@
import type { Meta, StoryObj } from "@storybook/react";
import { userEvent, within, expect } from "@storybook/test";
import * as Mocks from "testHelpers/entities";
import { WorkspaceActions } from "./WorkspaceActions";
@@ -140,3 +141,15 @@ export const CancelHiddenForUser: Story = {
isOwner: false,
},
};
export const CanDeleteDormantWorkspace: Story = {
args: {
workspace: Mocks.MockDormantWorkspace,
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.click(canvas.getByRole("button", { name: "More options" }));
const deleteButton = canvas.getByText("Delete…");
await expect(deleteButton).toBeEnabled();
},
};
@@ -172,6 +172,10 @@ export const WorkspaceActions: FC<WorkspaceActionsProps> = ({
</>
)}
{!canBeUpdated &&
workspace.template_require_active_version &&
buttonMapping.start}
{isRestarting
? buttonMapping.restarting
: actions.map((action) => (
@@ -240,7 +244,11 @@ function getTooltipText(
return "";
}
if (!mustUpdate && canChangeVersions) {
if (
!mustUpdate &&
canChangeVersions &&
workspace.template_require_active_version
) {
return "This template requires automatic updates on workspace startup, but template administrators can ignore this policy.";
}
@@ -49,7 +49,7 @@ export const abilitiesByWorkspaceStatus = (
return {
actions: ["activate"],
canCancel: false,
canAcceptJobs: false,
canAcceptJobs: true,
};
}
@@ -18,7 +18,6 @@ import {
import type { Template, Workspace } from "api/typesGenerated";
import { TopbarData, TopbarIcon } from "components/FullPageLayout/Topbar";
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
import { Pill } from "components/Pill/Pill";
import { useTime } from "hooks/useTime";
import { getWorkspaceActivityStatus } from "modules/workspaces/activity";
import {
@@ -170,11 +169,9 @@ const AutostopDisplay: FC<AutostopDisplayProps> = ({
const [showControlsAnyway, setShowControlsAnyway] = useState(false);
let onClickScheduleIcon: (() => void) | undefined;
let activity: ReactNode = null;
if (activityStatus === "connected") {
onClickScheduleIcon = () => setShowControlsAnyway((it) => !it);
activity = <Pill type="active">Connected</Pill>;
const now = dayjs();
const noRequiredStopSoon =
@@ -183,12 +180,7 @@ const AutostopDisplay: FC<AutostopDisplayProps> = ({
// User has shown controls manually, or we should warn about a nearby required stop
if (!showControlsAnyway && noRequiredStopSoon) {
return (
<>
{activity}
<WorkspaceScheduleContainer onClickIcon={onClickScheduleIcon} />
</>
);
return <WorkspaceScheduleContainer onClickIcon={onClickScheduleIcon} />;
}
}
@@ -239,24 +231,18 @@ const AutostopDisplay: FC<AutostopDisplayProps> = ({
if (tooltip) {
return (
<>
{activity}
<WorkspaceScheduleContainer onClickIcon={onClickScheduleIcon}>
<Tooltip title={tooltip}>{display}</Tooltip>
{controls}
</WorkspaceScheduleContainer>
</>
<WorkspaceScheduleContainer onClickIcon={onClickScheduleIcon}>
<Tooltip title={tooltip}>{display}</Tooltip>
{controls}
</WorkspaceScheduleContainer>
);
}
return (
<>
{activity}
<WorkspaceScheduleContainer onClickIcon={onClickScheduleIcon}>
{display}
{controls}
</WorkspaceScheduleContainer>
</>
<WorkspaceScheduleContainer onClickIcon={onClickScheduleIcon}>
{display}
{controls}
</WorkspaceScheduleContainer>
);
};
+1
View File
@@ -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[] = [
+1
View File
@@ -25,6 +25,7 @@
"datagrip.svg",
"dataspell.svg",
"debian.svg",
"desktop.svg",
"discord.svg",
"do.png",
"docker-white.svg",
+33
View File
@@ -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",
},
),
);
};
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M31 6V22C31 23.65 29.65 25 28 25H4C2.35 25 1 23.65 1 22V6C1 4.35 2.35 3 4 3H28C29.65 3 31 4.35 31 6Z" fill="#2197F3"/>
<path d="M21 27H17V24C17 23.4478 16.5522 23 16 23C15.4478 23 15 23.4478 15 24V27H11C10.4478 27 10 27.4478 10 28C10 28.5522 10.4478 29 11 29H21C21.5522 29 22 28.5522 22 28C22 27.4478 21.5522 27 21 27Z" fill="#FFC10A"/>
<path d="M31 17V22C31 23.65 29.65 25 28 25H4C2.35 25 1 23.65 1 22V17H31Z" fill="#3F51B5"/>
</svg>

After

Width:  |  Height:  |  Size: 684 B