Skip to content

Commit fda79c6

Browse files
authored
Merge branch 'main' into mafredri/feat-add-app-usage-to-template-insights
2 parents 97ef37b + ef9d84c commit fda79c6

File tree

256 files changed

+8417
-2699
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

256 files changed

+8417
-2699
lines changed

.github/actions/setup-tf/action.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ runs:
77
- name: Install Terraform
88
uses: hashicorp/setup-terraform@v2
99
with:
10-
terraform_version: ~1.5
10+
terraform_version: 1.5.5
1111
terraform_wrapper: false
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: cert-manager.io/v1
2+
kind: Certificate
3+
metadata:
4+
name: pr${PR_NUMBER}-tls
5+
namespace: pr-deployment-certs
6+
spec:
7+
secretName: pr${PR_NUMBER}-tls
8+
issuerRef:
9+
name: letsencrypt
10+
kind: ClusterIssuer
11+
dnsNames:
12+
- "${PR_HOSTNAME}"
13+
- "*.${PR_HOSTNAME}"

.github/pr-deployments/rbac.yaml

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
apiVersion: v1
2+
kind: ServiceAccount
3+
metadata:
4+
name: coder-workspace-pr${PR_NUMBER}
5+
namespace: pr${PR_NUMBER}
6+
7+
---
8+
apiVersion: rbac.authorization.k8s.io/v1
9+
kind: Role
10+
metadata:
11+
name: coder-workspace-pr${PR_NUMBER}
12+
namespace: pr${PR_NUMBER}
13+
rules:
14+
- apiGroups: ["*"]
15+
resources: ["*"]
16+
verbs: ["*"]
17+
18+
---
19+
apiVersion: rbac.authorization.k8s.io/v1
20+
kind: RoleBinding
21+
metadata:
22+
name: coder-workspace-pr${PR_NUMBER}
23+
namespace: pr${PR_NUMBER}
24+
subjects:
25+
- kind: ServiceAccount
26+
name: coder-workspace-pr${PR_NUMBER}
27+
namespace: pr${PR_NUMBER}
28+
roleRef:
29+
apiGroup: rbac.authorization.k8s.io
30+
kind: Role
31+
name: coder-workspace-pr${PR_NUMBER}
+313
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
terraform {
2+
required_providers {
3+
coder = {
4+
source = "coder/coder"
5+
version = "~> 0.11.0"
6+
}
7+
kubernetes = {
8+
source = "hashicorp/kubernetes"
9+
version = "~> 2.22"
10+
}
11+
}
12+
}
13+
14+
provider "coder" {
15+
}
16+
17+
variable "namespace" {
18+
type = string
19+
description = "The Kubernetes namespace to create workspaces in (must exist prior to creating workspaces)"
20+
}
21+
22+
data "coder_parameter" "cpu" {
23+
name = "cpu"
24+
display_name = "CPU"
25+
description = "The number of CPU cores"
26+
default = "2"
27+
icon = "/icon/memory.svg"
28+
mutable = true
29+
option {
30+
name = "2 Cores"
31+
value = "2"
32+
}
33+
option {
34+
name = "4 Cores"
35+
value = "4"
36+
}
37+
option {
38+
name = "6 Cores"
39+
value = "6"
40+
}
41+
option {
42+
name = "8 Cores"
43+
value = "8"
44+
}
45+
}
46+
47+
data "coder_parameter" "memory" {
48+
name = "memory"
49+
display_name = "Memory"
50+
description = "The amount of memory in GB"
51+
default = "2"
52+
icon = "/icon/memory.svg"
53+
mutable = true
54+
option {
55+
name = "2 GB"
56+
value = "2"
57+
}
58+
option {
59+
name = "4 GB"
60+
value = "4"
61+
}
62+
option {
63+
name = "6 GB"
64+
value = "6"
65+
}
66+
option {
67+
name = "8 GB"
68+
value = "8"
69+
}
70+
}
71+
72+
data "coder_parameter" "home_disk_size" {
73+
name = "home_disk_size"
74+
display_name = "Home disk size"
75+
description = "The size of the home disk in GB"
76+
default = "10"
77+
type = "number"
78+
icon = "/emojis/1f4be.png"
79+
mutable = false
80+
validation {
81+
min = 1
82+
max = 99999
83+
}
84+
}
85+
86+
provider "kubernetes" {
87+
config_path = null
88+
}
89+
90+
data "coder_workspace" "me" {}
91+
92+
resource "coder_agent" "main" {
93+
os = "linux"
94+
arch = "amd64"
95+
startup_script_timeout = 180
96+
startup_script = <<-EOT
97+
set -e
98+
99+
# install and start code-server
100+
curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server
101+
/tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
102+
103+
EOT
104+
105+
# The following metadata blocks are optional. They are used to display
106+
# information about your workspace in the dashboard. You can remove them
107+
# if you don't want to display any information.
108+
# For basic resources, you can use the `coder stat` command.
109+
# If you need more control, you can write your own script.
110+
metadata {
111+
display_name = "CPU Usage"
112+
key = "0_cpu_usage"
113+
script = "coder stat cpu"
114+
interval = 10
115+
timeout = 1
116+
}
117+
118+
metadata {
119+
display_name = "RAM Usage"
120+
key = "1_ram_usage"
121+
script = "coder stat mem"
122+
interval = 10
123+
timeout = 1
124+
}
125+
126+
metadata {
127+
display_name = "Home Disk"
128+
key = "3_home_disk"
129+
script = "coder stat disk --path $${HOME}"
130+
interval = 60
131+
timeout = 1
132+
}
133+
134+
metadata {
135+
display_name = "CPU Usage (Host)"
136+
key = "4_cpu_usage_host"
137+
script = "coder stat cpu --host"
138+
interval = 10
139+
timeout = 1
140+
}
141+
142+
metadata {
143+
display_name = "Memory Usage (Host)"
144+
key = "5_mem_usage_host"
145+
script = "coder stat mem --host"
146+
interval = 10
147+
timeout = 1
148+
}
149+
150+
metadata {
151+
display_name = "Load Average (Host)"
152+
key = "6_load_host"
153+
# get load avg scaled by number of cores
154+
script = <<EOT
155+
echo "`cat /proc/loadavg | awk '{ print $1 }'` `nproc`" | awk '{ printf "%0.2f", $1/$2 }'
156+
EOT
157+
interval = 60
158+
timeout = 1
159+
}
160+
}
161+
162+
# code-server
163+
resource "coder_app" "code-server" {
164+
agent_id = coder_agent.main.id
165+
slug = "code-server"
166+
display_name = "code-server"
167+
icon = "/icon/code.svg"
168+
url = "http://localhost:13337?folder=/home/coder"
169+
subdomain = false
170+
share = "owner"
171+
172+
healthcheck {
173+
url = "http://localhost:13337/healthz"
174+
interval = 3
175+
threshold = 10
176+
}
177+
}
178+
179+
resource "kubernetes_persistent_volume_claim" "home" {
180+
metadata {
181+
name = "coder-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}-home"
182+
namespace = var.namespace
183+
labels = {
184+
"app.kubernetes.io/name" = "coder-pvc"
185+
"app.kubernetes.io/instance" = "coder-pvc-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
186+
"app.kubernetes.io/part-of" = "coder"
187+
//Coder-specific labels.
188+
"com.coder.resource" = "true"
189+
"com.coder.workspace.id" = data.coder_workspace.me.id
190+
"com.coder.workspace.name" = data.coder_workspace.me.name
191+
"com.coder.user.id" = data.coder_workspace.me.owner_id
192+
"com.coder.user.username" = data.coder_workspace.me.owner
193+
}
194+
annotations = {
195+
"com.coder.user.email" = data.coder_workspace.me.owner_email
196+
}
197+
}
198+
wait_until_bound = false
199+
spec {
200+
access_modes = ["ReadWriteOnce"]
201+
resources {
202+
requests = {
203+
storage = "${data.coder_parameter.home_disk_size.value}Gi"
204+
}
205+
}
206+
}
207+
}
208+
209+
resource "kubernetes_deployment" "main" {
210+
count = data.coder_workspace.me.start_count
211+
depends_on = [
212+
kubernetes_persistent_volume_claim.home
213+
]
214+
wait_for_rollout = false
215+
metadata {
216+
name = "coder-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
217+
namespace = var.namespace
218+
labels = {
219+
"app.kubernetes.io/name" = "coder-workspace"
220+
"app.kubernetes.io/instance" = "coder-workspace-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
221+
"app.kubernetes.io/part-of" = "coder"
222+
"com.coder.resource" = "true"
223+
"com.coder.workspace.id" = data.coder_workspace.me.id
224+
"com.coder.workspace.name" = data.coder_workspace.me.name
225+
"com.coder.user.id" = data.coder_workspace.me.owner_id
226+
"com.coder.user.username" = data.coder_workspace.me.owner
227+
}
228+
annotations = {
229+
"com.coder.user.email" = data.coder_workspace.me.owner_email
230+
}
231+
}
232+
233+
spec {
234+
replicas = 1
235+
selector {
236+
match_labels = {
237+
"app.kubernetes.io/name" = "coder-workspace"
238+
}
239+
}
240+
241+
template {
242+
metadata {
243+
labels = {
244+
"app.kubernetes.io/name" = "coder-workspace"
245+
}
246+
}
247+
spec {
248+
security_context {
249+
run_as_user = 1000
250+
fs_group = 1000
251+
}
252+
253+
service_account_name = "coder-workspace-${var.namespace}"
254+
container {
255+
name = "dev"
256+
image = "bencdr/devops-tools"
257+
image_pull_policy = "Always"
258+
command = ["sh", "-c", coder_agent.main.init_script]
259+
security_context {
260+
run_as_user = "1000"
261+
}
262+
env {
263+
name = "CODER_AGENT_TOKEN"
264+
value = coder_agent.main.token
265+
}
266+
resources {
267+
requests = {
268+
"cpu" = "250m"
269+
"memory" = "512Mi"
270+
}
271+
limits = {
272+
"cpu" = "${data.coder_parameter.cpu.value}"
273+
"memory" = "${data.coder_parameter.memory.value}Gi"
274+
}
275+
}
276+
volume_mount {
277+
mount_path = "/home/coder"
278+
name = "home"
279+
read_only = false
280+
}
281+
}
282+
283+
volume {
284+
name = "home"
285+
persistent_volume_claim {
286+
claim_name = kubernetes_persistent_volume_claim.home.metadata.0.name
287+
read_only = false
288+
}
289+
}
290+
291+
affinity {
292+
// This affinity attempts to spread out all workspace pods evenly across
293+
// nodes.
294+
pod_anti_affinity {
295+
preferred_during_scheduling_ignored_during_execution {
296+
weight = 1
297+
pod_affinity_term {
298+
topology_key = "kubernetes.io/hostname"
299+
label_selector {
300+
match_expressions {
301+
key = "app.kubernetes.io/name"
302+
operator = "In"
303+
values = ["coder-workspace"]
304+
}
305+
}
306+
}
307+
}
308+
}
309+
}
310+
}
311+
}
312+
}
313+
}

0 commit comments

Comments
 (0)