Skip to content

feat: add template editor to the ui #5963

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add stories
  • Loading branch information
kylecarbs committed Feb 7, 2023
commit 33ffd77c36ba9650a64ed60122ee1417fb722d9d
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import { Story } from "@storybook/react"
import {
MockTemplate,
MockTemplateVersion,
MockTemplateVersionFiles,
MockWorkspaceBuildLogs,
MockWorkspaceResource,
MockWorkspaceResource2,
MockWorkspaceResource3,
} from "testHelpers/entities"
import {
TemplateVersionEditor,
TemplateVersionEditorProps,
} from "./TemplateVersionEditor"

export default {
title: "components/TemplateEditor",
title: "components/TemplateVersionEditor",
component: TemplateVersionEditor,
parameters: {
layout: "fullscreen",
Expand All @@ -18,211 +27,30 @@ const Template: Story<TemplateVersionEditorProps> = (args: any) => (

export const Example = Template.bind({})
Example.args = {
initialFiles: {
"README.md": "# Example\n\nThis is an example template.",
"main.tf": `terraform {
required_providers {
coder = {
source = "coder/coder"
version = "0.6.10"
}
docker = {
source = "kreuzwerker/docker"
version = "~> 2.22.0"
}
}
}

# User parameters

variable "region" {
type = string
description = "Which region to deploy to."
default = "us-pittsburgh"
validation {
condition = contains(["us-pittsburgh", "eu-helsinki", "ap-sydney"], var.region)
error_message = "Region must be one of us-pittsburg, eu-helsinki, or ap-sydney."
}
}

variable "dotfiles_uri" {
type = string
description = <<-EOF
Dotfiles repo URI (optional)

see https://dotfiles.github.io
EOF
default = ""
}

locals {
// These are Tailscale IP addresses. Ask Dean or Kyle for help.
docker_host = {
"" = "tcp://100.94.74.63:2375"
"us-pittsburgh" = "tcp://100.94.74.63:2375"
"eu-helsinki" = "tcp://100.117.102.81:2375"
"ap-sydney" = "tcp://100.127.2.1:2375"
}
}

provider "docker" {
host = lookup(local.docker_host, var.region)
}

provider "coder" {}

data "coder_workspace" "me" {}

resource "coder_agent" "dev" {
arch = "amd64"
os = "linux"

login_before_ready = false
startup_script_timeout = 60
startup_script = <<-EOT
set -ex
# install and start code-server
curl -fsSL https://code-server.dev/install.sh | sh -s -- --version 4.8.3
code-server --auth none --port 13337 &
sudo service docker start
DOTFILES_URI=\${var.dotfiles_uri}
rm -f ~/.personalize.log
if [ -n "$DOTFILES_URI" ]; then
coder dotfiles "$DOTFILES_URI" -y 2>&1 | tee -a ~/.personalize.log
fi
if [ -x ~/personalize ]; then
~/personalize 2>&1 | tee -a ~/.personalize.log
elif [ -f ~/personalize ]; then
echo "~/personalize is not executable, skipping..." | tee -a ~/.personalize.log
fi
EOT
}

resource "coder_app" "code-server" {
agent_id = coder_agent.dev.id
slug = "code-server"
display_name = "code-server"
url = "http://localhost:13337/"
icon = "/icon/code.svg"
subdomain = false
share = "owner"

healthcheck {
url = "http://localhost:13337/healthz"
interval = 3
threshold = 10
}
}

resource "docker_volume" "home_volume" {
name = "coder-\${data.coder_workspace.me.id}-home"
# Protect the volume from being deleted due to changes in attributes.
lifecycle {
ignore_changes = all
}
# Add labels in Docker to keep track of orphan resources.
labels {
label = "coder.owner"
value = data.coder_workspace.me.owner
}
labels {
label = "coder.owner_id"
value = data.coder_workspace.me.owner_id
}
labels {
label = "coder.workspace_id"
value = data.coder_workspace.me.id
}
# This field becomes outdated if the workspace is renamed but can
# be useful for debugging or cleaning out dangling volumes.
labels {
label = "coder.workspace_name_at_creation"
value = data.coder_workspace.me.name
}
template: MockTemplate,
templateVersion: MockTemplateVersion,
initialFiles: MockTemplateVersionFiles,
}

resource "coder_metadata" "home_info" {
resource_id = docker_volume.home_volume.id
item {
key = "🤫🤫🤫<br/><br/>"
value = "❤️❤️❤️"
sensitive = true
}
}
export const Logs = Template.bind({})

locals {
container_name = "coder-\${data.coder_workspace.me.owner}-\${lower(data.coder_workspace.me.name)}"
registry_name = "codercom/oss-dogfood"
}
data "docker_registry_image" "dogfood" {
name = "\${local.registry_name}:main"
Logs.args = {
template: MockTemplate,
templateVersion: MockTemplateVersion,
initialFiles: MockTemplateVersionFiles,
buildLogs: MockWorkspaceBuildLogs,
}

resource "docker_image" "dogfood" {
name = "\${local.registry_name}@\${data.docker_registry_image.dogfood.sha256_digest}"
pull_triggers = [
data.docker_registry_image.dogfood.sha256_digest,
sha1(join("", [for f in fileset(path.module, "files/*") : filesha1(f)])),
filesha1("Dockerfile"),
]
keep_locally = true
}
export const Resources = Template.bind({})

resource "docker_container" "workspace" {
count = data.coder_workspace.me.start_count
image = docker_image.dogfood.name
name = local.container_name
# Hostname makes the shell more user friendly: coder@my-workspace:~$
hostname = data.coder_workspace.me.name
# Use the docker gateway if the access URL is 127.0.0.1
entrypoint = ["sh", "-c", replace(coder_agent.dev.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")]
# CPU limits are unnecessary since Docker will load balance automatically
memory = 32768
runtime = "sysbox-runc"
env = [
"CODER_AGENT_TOKEN=\${coder_agent.dev.token}",
"DATOCMS_API_TOKEN=\${var.datocms_api_token}",
]
host {
host = "host.docker.internal"
ip = "host-gateway"
}
volumes {
container_path = "/home/coder/"
volume_name = docker_volume.home_volume.name
read_only = false
}
# Add labels in Docker to keep track of orphan resources.
labels {
label = "coder.owner"
value = data.coder_workspace.me.owner
}
labels {
label = "coder.owner_id"
value = data.coder_workspace.me.owner_id
}
labels {
label = "coder.workspace_id"
value = data.coder_workspace.me.id
}
labels {
label = "coder.workspace_name"
value = data.coder_workspace.me.name
}
}

resource "coder_metadata" "container_info" {
count = data.coder_workspace.me.start_count
resource_id = docker_container.workspace[0].id
item {
key = "memory"
value = docker_container.workspace[0].memory
}
item {
key = "runtime"
value = docker_container.workspace[0].runtime
}
}
`,
},
Resources.args = {
template: MockTemplate,
templateVersion: MockTemplateVersion,
initialFiles: MockTemplateVersionFiles,
buildLogs: MockWorkspaceBuildLogs,
resources: [
MockWorkspaceResource,
MockWorkspaceResource2,
MockWorkspaceResource3,
],
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ export const TemplateVersionEditor: FC<TemplateVersionEditorProps> = ({
buildLogs,
resources,
}) => {
const [selectedTab, setSelectedTab] = useState(0)
const [selectedTab, setSelectedTab] = useState(() => {
// If resources are provided, show them by default!
// This is for Storybook!
return resources ? 1 : 0
})
const [files, setFiles] = useState(initialFiles)
const [createFileOpen, setCreateFileOpen] = useState(false)
const [deleteFileOpen, setDeleteFileOpen] = useState<File>()
Expand Down
33 changes: 33 additions & 0 deletions site/src/testHelpers/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as Types from "../api/types"
import * as TypesGen from "../api/typesGenerated"
import range from "lodash/range"
import { Permissions } from "xServices/auth/authXService"
import { TemplateVersionFiles } from "util/templateVersion"

export const MockTemplateDAUResponse: TypesGen.TemplateDAUsResponse = {
entries: [
Expand Down Expand Up @@ -270,6 +271,38 @@ export const MockTemplate: TypesGen.Template = {
allow_user_cancel_workspace_jobs: true,
}

export const MockTemplateVersionFiles: TemplateVersionFiles = {
"README.md": "# Example\n\nThis is an example template.",
"main.tf": `// Provides info about the workspace.
data "coder_workspace" "me" {}

// Provides the startup script used to download
// the agent and communicate with Coder.
resource "coder_agent" "dev" {
os = "linux"
arch = "amd64"
}

resource "kubernetes_pod" "main" {
// Ensures that the Pod dies when the workspace shuts down!
count = data.coder_workspace.me.start_count
metadata {
name = "dev-\${data.coder_workspace.me.id}"
}
spec {
container {
image = "ubuntu"
command = ["sh", "-c", coder_agent.main.init_script]
env {
name = "CODER_AGENT_TOKEN"
value = coder_agent.main.token
}
}
}
}
`,
}

export const MockWorkspaceApp: TypesGen.WorkspaceApp = {
id: "test-app",
slug: "test-app",
Expand Down