mirror of
https://github.com/coder/coder.git
synced 2026-09-21 20:51:01 +08:00
feat: enable Terraform debug mode via deployment configuration (#8260)
This commit is contained in:
+3
@@ -74,6 +74,9 @@ Use a YAML configuration file when your server launch become unwieldy.
|
||||
Write out the current server config as YAML to stdout.
|
||||
|
||||
[1mIntrospection / Logging Options[0m
|
||||
--enable-terraform-debug-mode bool, $CODER_ENABLE_TERRAFORM_DEBUG_MODE (default: false)
|
||||
Allow administrators to enable Terraform debug output.
|
||||
|
||||
--log-human string, $CODER_LOGGING_HUMAN (default: /dev/stderr)
|
||||
Output human-readable logs to a given file.
|
||||
|
||||
|
||||
+3
@@ -197,6 +197,9 @@ introspection:
|
||||
# Output Stackdriver compatible logs to a given file.
|
||||
# (default: <unset>, type: string)
|
||||
stackdriverPath: ""
|
||||
# Allow administrators to enable Terraform debug output.
|
||||
# (default: false, type: bool)
|
||||
enableTerraformDebugMode: false
|
||||
oauth2:
|
||||
github:
|
||||
# Client ID for Login with GitHub.
|
||||
|
||||
Generated
+3
@@ -7270,6 +7270,9 @@ const docTemplate = `{
|
||||
"disable_session_expiry_refresh": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enable_terraform_debug_mode": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"experiments": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
||||
Generated
+3
@@ -6493,6 +6493,9 @@
|
||||
"disable_session_expiry_refresh": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enable_terraform_debug_mode": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"experiments": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
||||
@@ -316,7 +316,8 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
|
||||
builder := wsbuilder.New(workspace, database.WorkspaceTransition(createBuild.Transition)).
|
||||
Initiator(apiKey.UserID).
|
||||
RichParameterValues(createBuild.RichParameterValues).
|
||||
LogLevel(string(createBuild.LogLevel))
|
||||
LogLevel(string(createBuild.LogLevel)).
|
||||
DeploymentValues(api.Options.DeploymentValues)
|
||||
|
||||
if createBuild.TemplateVersionID != uuid.Nil {
|
||||
builder = builder.VersionID(createBuild.TemplateVersionID)
|
||||
|
||||
@@ -640,11 +640,50 @@ func TestWorkspaceBuildStatus(t *testing.T) {
|
||||
func TestWorkspaceBuildDebugMode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("DebugModeDisabled", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create user
|
||||
deploymentValues := coderdtest.DeploymentValues(t)
|
||||
deploymentValues.EnableTerraformDebugMode = false
|
||||
|
||||
adminClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, DeploymentValues: deploymentValues})
|
||||
owner := coderdtest.CreateFirstUser(t, adminClient)
|
||||
|
||||
// Template author: create a template
|
||||
version := coderdtest.CreateTemplateVersion(t, adminClient, owner.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, adminClient, owner.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, adminClient, version.ID)
|
||||
|
||||
// Template author: create a workspace
|
||||
workspace := coderdtest.CreateWorkspace(t, adminClient, owner.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, adminClient, workspace.LatestBuild.ID)
|
||||
|
||||
// Template author: try to start a workspace build in debug mode
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
_, err := adminClient.CreateWorkspaceBuild(ctx, workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
TemplateVersionID: workspace.LatestBuild.TemplateVersionID,
|
||||
Transition: codersdk.WorkspaceTransitionStart,
|
||||
LogLevel: "debug",
|
||||
})
|
||||
|
||||
// Template author: expect an error as the debug mode is disabled
|
||||
require.NotNil(t, err)
|
||||
var sdkError *codersdk.Error
|
||||
isSdkError := xerrors.As(err, &sdkError)
|
||||
require.True(t, isSdkError)
|
||||
require.Contains(t, sdkError.Message, "Terraform debug mode is disabled in the deployment configuration.")
|
||||
})
|
||||
t.Run("AsRegularUser", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create users
|
||||
templateAuthorClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
deploymentValues := coderdtest.DeploymentValues(t)
|
||||
deploymentValues.EnableTerraformDebugMode = true
|
||||
|
||||
templateAuthorClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, DeploymentValues: deploymentValues})
|
||||
templateAuthor := coderdtest.CreateFirstUser(t, templateAuthorClient)
|
||||
regularUserClient, _ := coderdtest.CreateAnotherUser(t, templateAuthorClient, templateAuthor.OrganizationID)
|
||||
|
||||
@@ -672,15 +711,54 @@ func TestWorkspaceBuildDebugMode(t *testing.T) {
|
||||
var sdkError *codersdk.Error
|
||||
isSdkError := xerrors.As(err, &sdkError)
|
||||
require.True(t, isSdkError)
|
||||
require.Contains(t, sdkError.Message, "Workspace builds with a custom log level are restricted to template authors only.")
|
||||
require.Contains(t, sdkError.Message, "Workspace builds with a custom log level are restricted to administrators only.")
|
||||
})
|
||||
t.Run("AsTemplateAuthor", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create users
|
||||
adminClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
deploymentValues := coderdtest.DeploymentValues(t)
|
||||
deploymentValues.EnableTerraformDebugMode = true
|
||||
|
||||
adminClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, DeploymentValues: deploymentValues})
|
||||
admin := coderdtest.CreateFirstUser(t, adminClient)
|
||||
templateAuthorClient, _ := coderdtest.CreateAnotherUser(t, adminClient, admin.OrganizationID, rbac.RoleTemplateAdmin())
|
||||
|
||||
// Template author: create a template
|
||||
version := coderdtest.CreateTemplateVersion(t, templateAuthorClient, admin.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, templateAuthorClient, admin.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, templateAuthorClient, version.ID)
|
||||
|
||||
// Template author: create a workspace
|
||||
workspace := coderdtest.CreateWorkspace(t, templateAuthorClient, admin.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, templateAuthorClient, workspace.LatestBuild.ID)
|
||||
|
||||
// Template author: try to start a workspace build in debug mode
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
_, err := templateAuthorClient.CreateWorkspaceBuild(ctx, workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
TemplateVersionID: workspace.LatestBuild.TemplateVersionID,
|
||||
Transition: codersdk.WorkspaceTransitionStart,
|
||||
LogLevel: "debug",
|
||||
})
|
||||
|
||||
// Template author: expect an error as the debug mode is disabled
|
||||
require.NotNil(t, err)
|
||||
var sdkError *codersdk.Error
|
||||
isSdkError := xerrors.As(err, &sdkError)
|
||||
require.True(t, isSdkError)
|
||||
require.Contains(t, sdkError.Message, "Workspace builds with a custom log level are restricted to administrators only.")
|
||||
})
|
||||
t.Run("AsAdmin", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create users
|
||||
deploymentValues := coderdtest.DeploymentValues(t)
|
||||
deploymentValues.EnableTerraformDebugMode = true
|
||||
|
||||
adminClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, DeploymentValues: deploymentValues})
|
||||
admin := coderdtest.CreateFirstUser(t, adminClient)
|
||||
templateAdminClient, _ := coderdtest.CreateAnotherUser(t, adminClient, admin.OrganizationID, rbac.RoleTemplateAdmin())
|
||||
|
||||
// Interact as template admin
|
||||
echoResponses := &echo.Responses{
|
||||
@@ -713,19 +791,19 @@ func TestWorkspaceBuildDebugMode(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
}
|
||||
version := coderdtest.CreateTemplateVersion(t, templateAdminClient, admin.OrganizationID, echoResponses)
|
||||
template := coderdtest.CreateTemplate(t, templateAdminClient, admin.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, templateAdminClient, version.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, adminClient, admin.OrganizationID, echoResponses)
|
||||
template := coderdtest.CreateTemplate(t, adminClient, admin.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, adminClient, version.ID)
|
||||
|
||||
// Create workspace
|
||||
workspace := coderdtest.CreateWorkspace(t, templateAdminClient, admin.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, templateAdminClient, workspace.LatestBuild.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, adminClient, admin.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, adminClient, workspace.LatestBuild.ID)
|
||||
|
||||
// Create workspace build
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
build, err := templateAdminClient.CreateWorkspaceBuild(ctx, workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
build, err := adminClient.CreateWorkspaceBuild(ctx, workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
TemplateVersionID: workspace.LatestBuild.TemplateVersionID,
|
||||
Transition: codersdk.WorkspaceTransitionStart,
|
||||
ProvisionerState: []byte(" "),
|
||||
@@ -733,10 +811,10 @@ func TestWorkspaceBuildDebugMode(t *testing.T) {
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
build = coderdtest.AwaitWorkspaceBuildJob(t, templateAdminClient, build.ID)
|
||||
build = coderdtest.AwaitWorkspaceBuildJob(t, adminClient, build.ID)
|
||||
|
||||
// Watch for incoming logs
|
||||
logs, closer, err := templateAdminClient.WorkspaceBuildLogsAfter(ctx, build.ID, 0)
|
||||
logs, closer, err := adminClient.WorkspaceBuildLogsAfter(ctx, build.ID, 0)
|
||||
require.NoError(t, err)
|
||||
defer closer.Close()
|
||||
|
||||
|
||||
@@ -34,11 +34,13 @@ import (
|
||||
// build, job, err := b.Build(...)
|
||||
type Builder struct {
|
||||
// settings that control the kind of build you get
|
||||
workspace database.Workspace
|
||||
trans database.WorkspaceTransition
|
||||
version versionTarget
|
||||
state stateTarget
|
||||
logLevel string
|
||||
workspace database.Workspace
|
||||
trans database.WorkspaceTransition
|
||||
version versionTarget
|
||||
state stateTarget
|
||||
logLevel string
|
||||
deploymentValues *codersdk.DeploymentValues
|
||||
|
||||
richParameterValues []codersdk.WorkspaceBuildParameter
|
||||
initiator uuid.UUID
|
||||
reason database.BuildReason
|
||||
@@ -128,6 +130,12 @@ func (b Builder) LogLevel(l string) Builder {
|
||||
return b
|
||||
}
|
||||
|
||||
func (b Builder) DeploymentValues(dv *codersdk.DeploymentValues) Builder {
|
||||
// nolint: revive
|
||||
b.deploymentValues = dv
|
||||
return b
|
||||
}
|
||||
|
||||
func (b Builder) Initiator(u uuid.UUID) Builder {
|
||||
// nolint: revive
|
||||
b.initiator = u
|
||||
@@ -638,11 +646,19 @@ func (b *Builder) authorize(authFunc func(action rbac.Action, object rbac.Object
|
||||
}
|
||||
}
|
||||
|
||||
if b.logLevel != "" && !authFunc(rbac.ActionUpdate, template) {
|
||||
if b.logLevel != "" && !authFunc(rbac.ActionRead, rbac.ResourceDeploymentValues) {
|
||||
return BuildError{
|
||||
http.StatusBadRequest,
|
||||
"Workspace builds with a custom log level are restricted to template authors only.",
|
||||
xerrors.New("Workspace builds with a custom log level are restricted to template authors only."),
|
||||
"Workspace builds with a custom log level are restricted to administrators only.",
|
||||
xerrors.New("Workspace builds with a custom log level are restricted to administrators only."),
|
||||
}
|
||||
}
|
||||
|
||||
if b.logLevel != "" && b.deploymentValues != nil && !b.deploymentValues.EnableTerraformDebugMode {
|
||||
return BuildError{
|
||||
http.StatusBadRequest,
|
||||
"Terraform debug mode is disabled in the deployment configuration.",
|
||||
xerrors.New("Terraform debug mode is disabled in the deployment configuration."),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
+13
-2
@@ -165,6 +165,7 @@ type DeploymentValues struct {
|
||||
WgtunnelHost clibase.String `json:"wgtunnel_host,omitempty" typescript:",notnull"`
|
||||
DisableOwnerWorkspaceExec clibase.Bool `json:"disable_owner_workspace_exec,omitempty" typescript:",notnull"`
|
||||
ProxyHealthStatusInterval clibase.Duration `json:"proxy_health_status_interval,omitempty" typescript:",notnull"`
|
||||
EnableTerraformDebugMode clibase.Bool `json:"enable_terraform_debug_mode,omitempty" typescript:",notnull"`
|
||||
|
||||
Config clibase.YAMLConfigPath `json:"config,omitempty" typescript:",notnull"`
|
||||
WriteConfig clibase.Bool `json:"write_config,omitempty" typescript:",notnull"`
|
||||
@@ -1215,10 +1216,20 @@ when required by your organization's security policy.`,
|
||||
YAML: "stackdriverPath",
|
||||
Annotations: clibase.Annotations{}.Mark(annotationExternalProxies, "true"),
|
||||
},
|
||||
{
|
||||
Name: "Enable Terraform debug mode",
|
||||
Description: "Allow administrators to enable Terraform debug output.",
|
||||
Flag: "enable-terraform-debug-mode",
|
||||
Env: "CODER_ENABLE_TERRAFORM_DEBUG_MODE",
|
||||
Default: "false",
|
||||
Value: &c.EnableTerraformDebugMode,
|
||||
Group: &deploymentGroupIntrospectionLogging,
|
||||
YAML: "enableTerraformDebugMode",
|
||||
},
|
||||
// ☢️ Dangerous settings
|
||||
{
|
||||
Name: "DANGEROUS: Allow all CORs requests",
|
||||
Description: "For security reasons, CORs requests are blocked except between workspace apps owned by the same user. If external requests are required, setting this to true will set all cors headers as '*'. This should never be used in production.",
|
||||
Name: "DANGEROUS: Allow all CORS requests",
|
||||
Description: "For security reasons, CORS requests are blocked except between workspace apps owned by the same user. If external requests are required, setting this to true will set all cors headers as '*'. This should never be used in production.",
|
||||
Flag: "dangerous-allow-cors-requests",
|
||||
Env: "CODER_DANGEROUS_ALLOW_CORS_REQUESTS",
|
||||
Hidden: true, // Hidden, should only be used by yarn dev server
|
||||
|
||||
@@ -196,6 +196,7 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \
|
||||
"disable_password_auth": true,
|
||||
"disable_path_apps": true,
|
||||
"disable_session_expiry_refresh": true,
|
||||
"enable_terraform_debug_mode": true,
|
||||
"experiments": ["string"],
|
||||
"git_auth": {
|
||||
"value": [
|
||||
|
||||
@@ -1873,6 +1873,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
||||
"disable_password_auth": true,
|
||||
"disable_path_apps": true,
|
||||
"disable_session_expiry_refresh": true,
|
||||
"enable_terraform_debug_mode": true,
|
||||
"experiments": ["string"],
|
||||
"git_auth": {
|
||||
"value": [
|
||||
@@ -2204,6 +2205,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
||||
"disable_password_auth": true,
|
||||
"disable_path_apps": true,
|
||||
"disable_session_expiry_refresh": true,
|
||||
"enable_terraform_debug_mode": true,
|
||||
"experiments": ["string"],
|
||||
"git_auth": {
|
||||
"value": [
|
||||
@@ -2398,6 +2400,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
||||
| `disable_password_auth` | boolean | false | | |
|
||||
| `disable_path_apps` | boolean | false | | |
|
||||
| `disable_session_expiry_refresh` | boolean | false | | |
|
||||
| `enable_terraform_debug_mode` | boolean | false | | |
|
||||
| `experiments` | array of string | false | | |
|
||||
| `git_auth` | [clibase.Struct-array_codersdk_GitAuthConfig](#clibasestruct-array_codersdk_gitauthconfig) | false | | |
|
||||
| `http_address` | string | false | | Http address is a string because it may be set to zero to disable. |
|
||||
|
||||
@@ -223,6 +223,17 @@ Disable workspace apps that are not served from subdomains. Path-based apps can
|
||||
|
||||
Disable automatic session expiry bumping due to activity. This forces all sessions to become invalid after the session expiry duration has been reached.
|
||||
|
||||
### --enable-terraform-debug-mode
|
||||
|
||||
| | |
|
||||
| ----------- | ----------------------------------------------------------- |
|
||||
| Type | <code>bool</code> |
|
||||
| Environment | <code>$CODER_ENABLE_TERRAFORM_DEBUG_MODE</code> |
|
||||
| YAML | <code>introspection.logging.enableTerraformDebugMode</code> |
|
||||
| Default | <code>false</code> |
|
||||
|
||||
Allow administrators to enable Terraform debug output.
|
||||
|
||||
### --swagger-enable
|
||||
|
||||
| | |
|
||||
|
||||
@@ -74,6 +74,9 @@ Use a YAML configuration file when your server launch become unwieldy.
|
||||
Write out the current server config as YAML to stdout.
|
||||
|
||||
[1mIntrospection / Logging Options[0m
|
||||
--enable-terraform-debug-mode bool, $CODER_ENABLE_TERRAFORM_DEBUG_MODE (default: false)
|
||||
Allow administrators to enable Terraform debug output.
|
||||
|
||||
--log-human string, $CODER_LOGGING_HUMAN (default: /dev/stderr)
|
||||
Output human-readable logs to a given file.
|
||||
|
||||
|
||||
@@ -374,6 +374,7 @@ export interface DeploymentValues {
|
||||
readonly wgtunnel_host?: string
|
||||
readonly disable_owner_workspace_exec?: boolean
|
||||
readonly proxy_health_status_interval?: number
|
||||
readonly enable_terraform_debug_mode?: boolean
|
||||
// This is likely an enum in an external package ("github.com/coder/coder/cli/clibase.YAMLConfigPath")
|
||||
readonly config?: string
|
||||
readonly write_config?: boolean
|
||||
|
||||
@@ -156,6 +156,25 @@ export const FailedWithLogs: Story = {
|
||||
},
|
||||
}
|
||||
|
||||
export const FailedWithRetry: Story = {
|
||||
args: {
|
||||
...Running.args,
|
||||
workspace: {
|
||||
...Mocks.MockFailedWorkspace,
|
||||
latest_build: {
|
||||
...Mocks.MockFailedWorkspace.latest_build,
|
||||
job: {
|
||||
...Mocks.MockFailedWorkspace.latest_build.job,
|
||||
error:
|
||||
"recv workspace provision: plan terraform: terraform plan: exit status 1",
|
||||
},
|
||||
},
|
||||
},
|
||||
failedBuildLogs: makeFailedBuildLogs(),
|
||||
canRetryDebugMode: true,
|
||||
},
|
||||
}
|
||||
|
||||
export const Deleting: Story = {
|
||||
args: {
|
||||
...Running.args,
|
||||
|
||||
@@ -60,7 +60,7 @@ export interface WorkspaceProps {
|
||||
builds?: TypesGen.WorkspaceBuild[]
|
||||
templateWarnings?: TypesGen.TemplateVersionWarning[]
|
||||
canUpdateWorkspace: boolean
|
||||
canUpdateTemplate: boolean
|
||||
canRetryDebugMode: boolean
|
||||
canChangeVersions: boolean
|
||||
hideSSHButton?: boolean
|
||||
hideVSCodeDesktopButton?: boolean
|
||||
@@ -92,7 +92,7 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
|
||||
resources,
|
||||
builds,
|
||||
canUpdateWorkspace,
|
||||
canUpdateTemplate,
|
||||
canRetryDebugMode,
|
||||
canChangeVersions,
|
||||
workspaceErrors,
|
||||
hideSSHButton,
|
||||
@@ -236,7 +236,7 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
|
||||
<Alert
|
||||
severity="error"
|
||||
actions={
|
||||
canUpdateTemplate && (
|
||||
canRetryDebugMode && (
|
||||
<Button
|
||||
key={0}
|
||||
onClick={handleBuildRetry}
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
MockTemplateVersion3,
|
||||
MockUser,
|
||||
MockEntitlementsWithScheduling,
|
||||
MockDeploymentConfig,
|
||||
} from "testHelpers/entities"
|
||||
import * as api from "../../api/api"
|
||||
import { Workspace } from "../../api/typesGenerated"
|
||||
@@ -39,6 +40,9 @@ const { t } = i18next
|
||||
const renderWorkspacePage = async () => {
|
||||
jest.spyOn(api, "getTemplate").mockResolvedValueOnce(MockTemplate)
|
||||
jest.spyOn(api, "getTemplateVersionRichParameters").mockResolvedValueOnce([])
|
||||
jest
|
||||
.spyOn(api, "getDeploymentValues")
|
||||
.mockResolvedValueOnce(MockDeploymentConfig)
|
||||
jest.spyOn(api, "watchStartupLogs").mockImplementation((_, options) => {
|
||||
options.onDone()
|
||||
return new WebSocket("")
|
||||
|
||||
@@ -61,6 +61,7 @@ export const WorkspaceReadyPage = ({
|
||||
workspace,
|
||||
template,
|
||||
templateVersion,
|
||||
deploymentValues,
|
||||
builds,
|
||||
getBuildsError,
|
||||
buildError,
|
||||
@@ -75,6 +76,9 @@ export const WorkspaceReadyPage = ({
|
||||
const deadline = getDeadline(workspace)
|
||||
const canUpdateWorkspace = Boolean(permissions?.updateWorkspace)
|
||||
const canUpdateTemplate = Boolean(permissions?.updateTemplate)
|
||||
const canRetryDebugMode =
|
||||
Boolean(permissions?.viewDeploymentValues) &&
|
||||
Boolean(deploymentValues?.enable_terraform_debug_mode)
|
||||
const { t } = useTranslation("workspacePage")
|
||||
const favicon = getFaviconByStatus(workspace.latest_build)
|
||||
const navigate = useNavigate()
|
||||
@@ -166,7 +170,7 @@ export const WorkspaceReadyPage = ({
|
||||
resources={workspace.latest_build.resources}
|
||||
builds={builds}
|
||||
canUpdateWorkspace={canUpdateWorkspace}
|
||||
canUpdateTemplate={canUpdateTemplate}
|
||||
canRetryDebugMode={canRetryDebugMode}
|
||||
canChangeVersions={canUpdateTemplate}
|
||||
hideSSHButton={featureVisibility["browser_only"]}
|
||||
hideVSCodeDesktopButton={featureVisibility["browser_only"]}
|
||||
|
||||
@@ -1583,6 +1583,13 @@ export const MockPermissions: Permissions = {
|
||||
viewDeploymentStats: true,
|
||||
}
|
||||
|
||||
export const MockDeploymentConfig: Types.DeploymentConfig = {
|
||||
config: {
|
||||
enable_terraform_debug_mode: true,
|
||||
},
|
||||
options: [],
|
||||
}
|
||||
|
||||
export const MockAppearance: TypesGen.AppearanceConfig = {
|
||||
logo_url: "",
|
||||
service_banner: {
|
||||
|
||||
@@ -55,6 +55,7 @@ export interface WorkspaceContext {
|
||||
template?: TypesGen.Template
|
||||
permissions?: Permissions
|
||||
templateVersion?: TypesGen.TemplateVersion
|
||||
deploymentValues?: TypesGen.DeploymentValues
|
||||
build?: TypesGen.WorkspaceBuild
|
||||
// Builds
|
||||
builds?: TypesGen.WorkspaceBuild[]
|
||||
@@ -100,6 +101,7 @@ export const checks = {
|
||||
readWorkspace: "readWorkspace",
|
||||
updateWorkspace: "updateWorkspace",
|
||||
updateTemplate: "updateTemplate",
|
||||
viewDeploymentValues: "viewDeploymentValues",
|
||||
} as const
|
||||
|
||||
const permissionsToCheck = (
|
||||
@@ -130,6 +132,12 @@ const permissionsToCheck = (
|
||||
},
|
||||
action: "update",
|
||||
},
|
||||
[checks.viewDeploymentValues]: {
|
||||
object: {
|
||||
resource_type: "deployment_config",
|
||||
},
|
||||
action: "read",
|
||||
},
|
||||
} as const)
|
||||
|
||||
export const workspaceMachine = createMachine(
|
||||
@@ -488,6 +496,7 @@ export const workspaceMachine = createMachine(
|
||||
template: (_, event) => event.data.template,
|
||||
templateVersion: (_, event) => event.data.templateVersion,
|
||||
permissions: (_, event) => event.data.permissions as Permissions,
|
||||
deploymentValues: (_, event) => event.data.deploymentValues,
|
||||
}),
|
||||
assignError: assign({
|
||||
error: (_, event) => event.data,
|
||||
@@ -740,10 +749,17 @@ async function loadInitialWorkspaceData({
|
||||
}),
|
||||
])
|
||||
|
||||
const canViewDeploymentValues = Boolean(
|
||||
(permissions as Permissions)?.viewDeploymentValues,
|
||||
)
|
||||
const deploymentValues = canViewDeploymentValues
|
||||
? (await API.getDeploymentValues())?.config
|
||||
: undefined
|
||||
return {
|
||||
workspace,
|
||||
template,
|
||||
templateVersion,
|
||||
permissions,
|
||||
deploymentValues,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user