From efabdec427ac3efb9849c70b13ae02b28c3129f0 Mon Sep 17 00:00:00 2001 From: Jon Ayers Date: Fri, 6 Oct 2023 01:01:43 +0000 Subject: [PATCH 1/5] feat: support configurable web terminal rendering - Added a deployment option for configuring web terminal rendering. Valid values are 'webgl', 'canvas', and 'dom'. --- cli/testdata/coder_server_--help.golden | 4 ++++ cli/testdata/server-config.yaml.golden | 4 ++++ coderd/apidoc/docs.go | 3 +++ coderd/apidoc/swagger.json | 3 +++ codersdk/deployment.go | 12 +++++++++++ docs/api/general.md | 1 + docs/api/schemas.md | 3 +++ docs/cli/server.md | 11 ++++++++++ .../cli/testdata/coder_server_--help.golden | 4 ++++ site/src/AppRouter.tsx | 2 +- site/src/api/typesGenerated.ts | 1 + .../pages/TerminalPage/TerminalPage.test.tsx | 2 +- site/src/pages/TerminalPage/TerminalPage.tsx | 21 ++++++++++++------- 13 files changed, 61 insertions(+), 10 deletions(-) diff --git a/cli/testdata/coder_server_--help.golden b/cli/testdata/coder_server_--help.golden index cb389b93a5ec4..45e38863aa61e 100644 --- a/cli/testdata/coder_server_--help.golden +++ b/cli/testdata/coder_server_--help.golden @@ -66,6 +66,10 @@ Clients include the coder cli, vs code extension, and the web UI. --ssh-hostname-prefix string, $CODER_SSH_HOSTNAME_PREFIX (default: coder.) The SSH deployment prefix is used in the Host of the ssh config. + --web-terminal-renderer string, $CODER_WEB_TERMINAL_RENDERER (default: webgl) + The framework to use when rendering the terminal. Valid values are + 'canvas', 'webgl', or 'dom'. + CONFIG OPTIONS: Use a YAML configuration file when your server launch become unwieldy. diff --git a/cli/testdata/server-config.yaml.golden b/cli/testdata/server-config.yaml.golden index 689004ba5be57..25721ecc82489 100644 --- a/cli/testdata/server-config.yaml.golden +++ b/cli/testdata/server-config.yaml.golden @@ -411,6 +411,10 @@ client: # incorrectly can break SSH to your deployment, use cautiously. # (default: , type: string-array) sshConfigOptions: [] + # The framework to use when rendering the terminal. Valid values are 'canvas', + # 'webgl', or 'dom'. + # (default: webgl, type: string) + webTerminalRenderer: webgl # Support links to display in the top right drop down menu. # (default: , type: struct[[]codersdk.LinkConfig]) supportLinks: [] diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 0e8c9f63dd7cc..32424c5ffe1a2 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -8209,6 +8209,9 @@ const docTemplate = `{ "verbose": { "type": "boolean" }, + "web_terminal_renderer": { + "type": "string" + }, "wgtunnel_host": { "type": "string" }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index a14c65f120df4..71c7cbef07a7e 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -7347,6 +7347,9 @@ "verbose": { "type": "boolean" }, + "web_terminal_renderer": { + "type": "string" + }, "wgtunnel_host": { "type": "string" }, diff --git a/codersdk/deployment.go b/codersdk/deployment.go index bd89af4201a10..1fe52cc34f3f0 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -180,6 +180,7 @@ type DeploymentValues struct { ProxyHealthStatusInterval clibase.Duration `json:"proxy_health_status_interval,omitempty" typescript:",notnull"` EnableTerraformDebugMode clibase.Bool `json:"enable_terraform_debug_mode,omitempty" typescript:",notnull"` UserQuietHoursSchedule UserQuietHoursScheduleConfig `json:"user_quiet_hours_schedule,omitempty" typescript:",notnull"` + WebTerminalRenderer clibase.String `json:"web_terminal_renderer,omitempty" typescript:",notnull"` Config clibase.YAMLConfigPath `json:"config,omitempty" typescript:",notnull"` WriteConfig clibase.Bool `json:"write_config,omitempty" typescript:",notnull"` @@ -1762,7 +1763,18 @@ Write out the current server config as YAML to stdout.`, Group: &deploymentGroupUserQuietHoursSchedule, YAML: "defaultQuietHoursSchedule", }, + { + Name: "Web Terminal Renderer", + Description: "The framework to use when rendering the terminal. Valid values are 'canvas', 'webgl', or 'dom'.", + Flag: "web-terminal-renderer", + Env: "CODER_WEB_TERMINAL_RENDERER", + Default: "webgl", + Value: &c.WebTerminalRenderer, + Group: &deploymentGroupClient, + YAML: "webTerminalRenderer", + }, } + return opts } diff --git a/docs/api/general.md b/docs/api/general.md index bd6942fd3d271..1362b6edcd280 100644 --- a/docs/api/general.md +++ b/docs/api/general.md @@ -389,6 +389,7 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \ "default_schedule": "string" }, "verbose": true, + "web_terminal_renderer": "string", "wgtunnel_host": "string", "wildcard_access_url": { "forceQuery": true, diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 6ca7143579930..f3bcc6cb9e43e 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -2246,6 +2246,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "default_schedule": "string" }, "verbose": true, + "web_terminal_renderer": "string", "wgtunnel_host": "string", "wildcard_access_url": { "forceQuery": true, @@ -2614,6 +2615,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "default_schedule": "string" }, "verbose": true, + "web_terminal_renderer": "string", "wgtunnel_host": "string", "wildcard_access_url": { "forceQuery": true, @@ -2687,6 +2689,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `update_check` | boolean | false | | | | `user_quiet_hours_schedule` | [codersdk.UserQuietHoursScheduleConfig](#codersdkuserquiethoursscheduleconfig) | false | | | | `verbose` | boolean | false | | | +| `web_terminal_renderer` | string | false | | | | `wgtunnel_host` | string | false | | | | `wildcard_access_url` | [clibase.URL](#clibaseurl) | false | | | | `write_config` | boolean | false | | | diff --git a/docs/cli/server.md b/docs/cli/server.md index 0db6c9e871489..ca2d5bf0650bd 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -997,6 +997,17 @@ Enables trace exporting to Honeycomb.io using the provided API Key. Periodically check for new releases of Coder and inform the owner. The check is performed once per day. +### --web-terminal-renderer + +| | | +| ----------- | ----------------------------------------- | +| Type | string | +| Environment | $CODER_WEB_TERMINAL_RENDERER | +| YAML | client.webTerminalRenderer | +| Default | webgl | + +The framework to use when rendering the terminal. Valid values are 'canvas', 'webgl', or 'dom'. + ### --wildcard-access-url | | | diff --git a/enterprise/cli/testdata/coder_server_--help.golden b/enterprise/cli/testdata/coder_server_--help.golden index f9faa4e5bf66c..2b07a9b095cb0 100644 --- a/enterprise/cli/testdata/coder_server_--help.golden +++ b/enterprise/cli/testdata/coder_server_--help.golden @@ -67,6 +67,10 @@ Clients include the coder cli, vs code extension, and the web UI. --ssh-hostname-prefix string, $CODER_SSH_HOSTNAME_PREFIX (default: coder.) The SSH deployment prefix is used in the Host of the ssh config. + --web-terminal-renderer string, $CODER_WEB_TERMINAL_RENDERER (default: webgl) + The framework to use when rendering the terminal. Valid values are + 'canvas', 'webgl', or 'dom'. + CONFIG OPTIONS: Use a YAML configuration file when your server launch become unwieldy. diff --git a/site/src/AppRouter.tsx b/site/src/AppRouter.tsx index abef366dbcbfa..3568b3230ab0a 100644 --- a/site/src/AppRouter.tsx +++ b/site/src/AppRouter.tsx @@ -339,7 +339,7 @@ export const AppRouter: FC = () => { {/* Terminal and CLI auth pages don't have the dashboard layout */} } + element={} /> } /> } /> diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 45b2676666904..a4e6a7df8c7f9 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -404,6 +404,7 @@ export interface DeploymentValues { readonly proxy_health_status_interval?: number; readonly enable_terraform_debug_mode?: boolean; readonly user_quiet_hours_schedule?: UserQuietHoursScheduleConfig; + readonly web_terminal_renderer?: string; readonly config?: string; readonly write_config?: boolean; readonly address?: string; diff --git a/site/src/pages/TerminalPage/TerminalPage.test.tsx b/site/src/pages/TerminalPage/TerminalPage.test.tsx index d8fb9d28ddd69..e922f0ff4fc74 100644 --- a/site/src/pages/TerminalPage/TerminalPage.test.tsx +++ b/site/src/pages/TerminalPage/TerminalPage.test.tsx @@ -37,7 +37,7 @@ Object.defineProperty(window, "TextEncoder", { const renderTerminal = async ( route = `/${MockUser.username}/${MockWorkspace.name}/terminal`, ) => { - const utils = renderWithAuth(, { + const utils = renderWithAuth(, { route, path: "/:username/:workspace/terminal", }); diff --git a/site/src/pages/TerminalPage/TerminalPage.tsx b/site/src/pages/TerminalPage/TerminalPage.tsx index 9292c5c657a0d..157b338df2bb8 100644 --- a/site/src/pages/TerminalPage/TerminalPage.tsx +++ b/site/src/pages/TerminalPage/TerminalPage.tsx @@ -7,6 +7,7 @@ import { colors } from "theme/colors"; import { v4 as uuidv4 } from "uuid"; import * as XTerm from "xterm"; import { WebglAddon } from "xterm-addon-webgl"; +import { CanvasAddon } from "xterm-addon-canvas"; import { FitAddon } from "xterm-addon-fit"; import { WebLinksAddon } from "xterm-addon-web-links"; import { Unicode11Addon } from "xterm-addon-unicode11"; @@ -28,6 +29,8 @@ import { LoadedScriptsAlert, LoadingScriptsAlert, } from "./TerminalAlerts"; +import { useQuery } from "@tanstack/react-query"; +import { deploymentConfig } from "api/queries/deployment"; export const Language = { workspaceErrorMessagePrefix: "Unable to fetch workspace: ", @@ -35,11 +38,7 @@ export const Language = { websocketErrorMessagePrefix: "WebSocket failed: ", }; -type TerminalPageProps = React.PropsWithChildren<{ - renderer: "webgl" | "dom"; -}>; - -const TerminalPage: FC = ({ renderer }) => { +const TerminalPage: FC = () => { const navigate = useNavigate(); const styles = useStyles(); const { proxy } = useProxy(); @@ -101,6 +100,8 @@ const TerminalPage: FC = ({ renderer }) => { prevLifecycleState.current = lifecycleState; }, [lifecycleState]); + const config = useQuery(deploymentConfig()); + // handleWebLink handles opening of URLs in the terminal! const handleWebLink = useCallback( (uri: string) => { @@ -166,9 +167,13 @@ const TerminalPage: FC = ({ renderer }) => { background: colors.gray[16], }, }); - // DOM is the default renderer. - if (renderer === "webgl") { + if (config.data && config.data.config.web_terminal_renderer === "webgl") { terminal.loadAddon(new WebglAddon()); + } else if ( + config.data && + config.data.config.web_terminal_renderer === "canvas" + ) { + terminal.loadAddon(new CanvasAddon()); } const fitAddon = new FitAddon(); setFitAddon(fitAddon); @@ -208,7 +213,7 @@ const TerminalPage: FC = ({ renderer }) => { window.removeEventListener("resize", listener); terminal.dispose(); }; - }, [renderer, sendEvent, xtermRef, handleWebLink]); + }, [config.data, sendEvent, xtermRef, handleWebLink]); // Triggers the initial terminal connection using // the reconnection token and workspace name found From b26a2e677ca994fab5d2b30cd89c12165d39a85c Mon Sep 17 00:00:00 2001 From: Jon Ayers Date: Fri, 6 Oct 2023 02:16:00 +0000 Subject: [PATCH 2/5] make canvas default --- codersdk/deployment.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codersdk/deployment.go b/codersdk/deployment.go index 1fe52cc34f3f0..3a09c31de4b7b 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -1765,10 +1765,10 @@ Write out the current server config as YAML to stdout.`, }, { Name: "Web Terminal Renderer", - Description: "The framework to use when rendering the terminal. Valid values are 'canvas', 'webgl', or 'dom'.", + Description: "The renderer to use when opening a web terminal. Valid values are 'canvas', 'webgl', or 'dom'.", Flag: "web-terminal-renderer", Env: "CODER_WEB_TERMINAL_RENDERER", - Default: "webgl", + Default: "canvas", Value: &c.WebTerminalRenderer, Group: &deploymentGroupClient, YAML: "webTerminalRenderer", From 454189285839ea029c7e636f2ee55350588e5541 Mon Sep 17 00:00:00 2001 From: Jon Ayers Date: Fri, 6 Oct 2023 02:35:40 +0000 Subject: [PATCH 3/5] make golden --- cli/testdata/coder_server_--help.golden | 4 ++-- cli/testdata/server-config.yaml.golden | 6 +++--- docs/cli/server.md | 4 ++-- enterprise/cli/testdata/coder_server_--help.golden | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cli/testdata/coder_server_--help.golden b/cli/testdata/coder_server_--help.golden index 45e38863aa61e..68953eb14e434 100644 --- a/cli/testdata/coder_server_--help.golden +++ b/cli/testdata/coder_server_--help.golden @@ -66,8 +66,8 @@ Clients include the coder cli, vs code extension, and the web UI. --ssh-hostname-prefix string, $CODER_SSH_HOSTNAME_PREFIX (default: coder.) The SSH deployment prefix is used in the Host of the ssh config. - --web-terminal-renderer string, $CODER_WEB_TERMINAL_RENDERER (default: webgl) - The framework to use when rendering the terminal. Valid values are + --web-terminal-renderer string, $CODER_WEB_TERMINAL_RENDERER (default: canvas) + The renderer to use when opening a web terminal. Valid values are 'canvas', 'webgl', or 'dom'. CONFIG OPTIONS: diff --git a/cli/testdata/server-config.yaml.golden b/cli/testdata/server-config.yaml.golden index 25721ecc82489..31304d68e1633 100644 --- a/cli/testdata/server-config.yaml.golden +++ b/cli/testdata/server-config.yaml.golden @@ -411,10 +411,10 @@ client: # incorrectly can break SSH to your deployment, use cautiously. # (default: , type: string-array) sshConfigOptions: [] - # The framework to use when rendering the terminal. Valid values are 'canvas', + # The renderer to use when opening a web terminal. Valid values are 'canvas', # 'webgl', or 'dom'. - # (default: webgl, type: string) - webTerminalRenderer: webgl + # (default: canvas, type: string) + webTerminalRenderer: canvas # Support links to display in the top right drop down menu. # (default: , type: struct[[]codersdk.LinkConfig]) supportLinks: [] diff --git a/docs/cli/server.md b/docs/cli/server.md index ca2d5bf0650bd..9258f0f92f7e6 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -1004,9 +1004,9 @@ Periodically check for new releases of Coder and inform the owner. The check is | Type | string | | Environment | $CODER_WEB_TERMINAL_RENDERER | | YAML | client.webTerminalRenderer | -| Default | webgl | +| Default | canvas | -The framework to use when rendering the terminal. Valid values are 'canvas', 'webgl', or 'dom'. +The renderer to use when opening a web terminal. Valid values are 'canvas', 'webgl', or 'dom'. ### --wildcard-access-url diff --git a/enterprise/cli/testdata/coder_server_--help.golden b/enterprise/cli/testdata/coder_server_--help.golden index 2b07a9b095cb0..f4bb522f5ec62 100644 --- a/enterprise/cli/testdata/coder_server_--help.golden +++ b/enterprise/cli/testdata/coder_server_--help.golden @@ -67,8 +67,8 @@ Clients include the coder cli, vs code extension, and the web UI. --ssh-hostname-prefix string, $CODER_SSH_HOSTNAME_PREFIX (default: coder.) The SSH deployment prefix is used in the Host of the ssh config. - --web-terminal-renderer string, $CODER_WEB_TERMINAL_RENDERER (default: webgl) - The framework to use when rendering the terminal. Valid values are + --web-terminal-renderer string, $CODER_WEB_TERMINAL_RENDERER (default: canvas) + The renderer to use when opening a web terminal. Valid values are 'canvas', 'webgl', or 'dom'. CONFIG OPTIONS: From 199bde3c26cb46d8e8810bf30e959e59007c5354 Mon Sep 17 00:00:00 2001 From: Jon Ayers Date: Tue, 10 Oct 2023 17:54:11 +0000 Subject: [PATCH 4/5] try to fix tests --- site/e2e/playwright.config.ts | 1 + site/src/pages/TerminalPage/TerminalPage.tsx | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/site/e2e/playwright.config.ts b/site/e2e/playwright.config.ts index e82a4e841dac0..792944f26dde9 100644 --- a/site/e2e/playwright.config.ts +++ b/site/e2e/playwright.config.ts @@ -49,6 +49,7 @@ export default defineConfig({ `--dangerous-disable-rate-limits ` + `--provisioner-daemons 10 ` + `--provisioner-daemons-echo ` + + `--web-terminal-renderer=dom ` + `--pprof-enable`, env: { ...process.env, diff --git a/site/src/pages/TerminalPage/TerminalPage.tsx b/site/src/pages/TerminalPage/TerminalPage.tsx index 157b338df2bb8..9f4799dd64285 100644 --- a/site/src/pages/TerminalPage/TerminalPage.tsx +++ b/site/src/pages/TerminalPage/TerminalPage.tsx @@ -167,12 +167,9 @@ const TerminalPage: FC = () => { background: colors.gray[16], }, }); - if (config.data && config.data.config.web_terminal_renderer === "webgl") { + if (config.data?.config.web_terminal_renderer === "webgl") { terminal.loadAddon(new WebglAddon()); - } else if ( - config.data && - config.data.config.web_terminal_renderer === "canvas" - ) { + } else if (config.data?.config.web_terminal_renderer === "canvas") { terminal.loadAddon(new CanvasAddon()); } const fitAddon = new FitAddon(); From 7256820bf3e9db255dd43ef094a050725dd8b6ab Mon Sep 17 00:00:00 2001 From: Jon Ayers Date: Tue, 10 Oct 2023 18:06:41 +0000 Subject: [PATCH 5/5] wrong use query --- site/src/pages/TerminalPage/TerminalPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/TerminalPage/TerminalPage.tsx b/site/src/pages/TerminalPage/TerminalPage.tsx index 9f4799dd64285..958d7ef7329e7 100644 --- a/site/src/pages/TerminalPage/TerminalPage.tsx +++ b/site/src/pages/TerminalPage/TerminalPage.tsx @@ -29,7 +29,7 @@ import { LoadedScriptsAlert, LoadingScriptsAlert, } from "./TerminalAlerts"; -import { useQuery } from "@tanstack/react-query"; +import { useQuery } from "react-query"; import { deploymentConfig } from "api/queries/deployment"; export const Language = {