Skip to content
This repository was archived by the owner on May 15, 2025. It is now read-only.

Commit 313ec59

Browse files
matifalimafredri
andauthored
Add terraform validation to linting (#170)
Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
1 parent 4b04d18 commit 313ec59

File tree

5 files changed

+114
-51
lines changed

5 files changed

+114
-51
lines changed

.sample/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ resource "coder_app" "MODULE_NAME" {
6969
slug = "MODULE_NAME"
7070
display_name = "MODULE_NAME"
7171
url = "http://localhost:${var.port}"
72-
icon = loocal.icon_url
72+
icon = local.icon_url
7373
subdomain = false
7474
share = "owner"
7575

jetbrains-gateway/main.test.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,16 @@ describe("jetbrains-gateway", async () => {
1111
await testRequiredVariables(import.meta.dir, {
1212
agent_id: "foo",
1313
agent_name: "foo",
14-
folder: "/baz/",
14+
folder: "/home/foo",
1515
});
1616

1717
it("default to first ide", async () => {
1818
const state = await runTerraformApply(import.meta.dir, {
1919
agent_id: "foo",
2020
agent_name: "foo",
21-
folder: "/baz/",
21+
folder: "/home/foo",
2222
jetbrains_ides: '["IU", "GO", "PY"]',
2323
});
24-
expect(state.outputs.jetbrains_ides.value).toBe(
25-
'["IU","232.10203.10","https://download.jetbrains.com/idea/ideaIU-2023.2.4.tar.gz"]',
26-
);
24+
expect(state.outputs.identifier.value).toBe("IU");
2725
});
2826
});

jetbrains-gateway/main.tf

Lines changed: 80 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ variable "agent_name" {
2222
variable "folder" {
2323
type = string
2424
description = "The directory to open in the IDE. e.g. /home/coder/project"
25+
validation {
26+
condition = can(regex("^(?:/[^/]+)+$", var.folder))
27+
error_message = "The folder must be a full path and must not start with a ~."
28+
}
2529
}
2630

2731
variable "default" {
@@ -30,10 +34,6 @@ variable "default" {
3034
description = "Default IDE"
3135
}
3236

33-
locals {
34-
supported_ides = ["IU", "PS", "WS", "PY", "CL", "GO", "RM"]
35-
}
36-
3737
variable "jetbrains_ide_versions" {
3838
type = map(object({
3939
build_number = string
@@ -69,29 +69,28 @@ variable "jetbrains_ide_versions" {
6969
build_number = "232.10203.15"
7070
version = "2023.2.4"
7171
}
72-
7372
}
7473
validation {
7574
condition = (
7675
alltrue([
77-
for code in var.jetbrains_ide_versions : contains(local.supported_ides, code)
76+
for code in keys(var.jetbrains_ide_versions) : contains(["IU", "PS", "WS", "PY", "CL", "GO", "RM"], code)
7877
])
7978
)
80-
error_message = "The jetbrains_ide_versions must contain a map of valid product codes. Valid product codes are ${join(",", local.supported_ides)}."
79+
error_message = "The jetbrains_ide_versions must contain a map of valid product codes. Valid product codes are ${join(",", ["IU", "PS", "WS", "PY", "CL", "GO", "RM"])}."
8180
}
8281
}
8382

8483
variable "jetbrains_ides" {
8584
type = list(string)
8685
description = "The list of IDE product codes."
87-
default = local.supported_ides
86+
default = ["IU", "PS", "WS", "PY", "CL", "GO", "RM"]
8887
validation {
8988
condition = (
9089
alltrue([
91-
for code in var.jetbrains_ides : contains(local.supported_ides, code)
90+
for code in var.jetbrains_ides : contains(["IU", "PS", "WS", "PY", "CL", "GO", "RM"], code)
9291
])
9392
)
94-
error_message = "The jetbrains_ides must be a list of valid product codes. Valid product codes are ${join(",", local.supported_ides)}."
93+
error_message = "The jetbrains_ides must be a list of valid product codes. Valid product codes are ${join(",", ["IU", "PS", "WS", "PY", "CL", "GO", "RM"])}."
9594
}
9695
# check if the list is empty
9796
validation {
@@ -108,58 +107,71 @@ variable "jetbrains_ides" {
108107
locals {
109108
jetbrains_ides = {
110109
"GO" = {
111-
icon = "/icon/goland.svg",
112-
name = "GoLand",
113-
value = jsonencode(["GO", var.jetbrains_ide_versions["GO"].build_number, "https://download.jetbrains.com/go/goland-${var.jetbrains_ide_versions["GO"].version}.tar.gz"])
110+
icon = "/icon/goland.svg",
111+
name = "GoLand",
112+
identifier = "GO",
113+
build_number = var.jetbrains_ide_versions["GO"].build_number,
114+
download_link = "https://download.jetbrains.com/go/goland-${var.jetbrains_ide_versions["GO"].version}.tar.gz"
114115
},
115116
"WS" = {
116-
icon = "/icon/webstorm.svg",
117-
name = "WebStorm",
118-
value = jsonencode(["WS", var.jetbrains_ide_versions["WS"].build_number, "https://download.jetbrains.com/webstorm/WebStorm-${var.jetbrains_ide_versions["WS"].version}.tar.gz"])
117+
icon = "/icon/webstorm.svg",
118+
name = "WebStorm",
119+
identifier = "WS",
120+
build_number = var.jetbrains_ide_versions["WS"].build_number,
121+
download_link = "https://download.jetbrains.com/webstorm/WebStorm-${var.jetbrains_ide_versions["WS"].version}.tar.gz"
119122
},
120123
"IU" = {
121-
icon = "/icon/intellij.svg",
122-
name = "IntelliJ IDEA Ultimate",
123-
value = jsonencode(["IU", var.jetbrains_ide_versions["IU"].build_number, "https://download.jetbrains.com/idea/ideaIU-${var.jetbrains_ide_versions["IU"].version}.tar.gz"])
124+
icon = "/icon/intellij.svg",
125+
name = "IntelliJ IDEA Ultimate",
126+
identifier = "IU",
127+
build_number = var.jetbrains_ide_versions["IU"].build_number,
128+
download_link = "https://download.jetbrains.com/idea/ideaIU-${var.jetbrains_ide_versions["IU"].version}.tar.gz"
124129
},
125130
"PY" = {
126-
icon = "/icon/pycharm.svg",
127-
name = "PyCharm Professional",
128-
value = jsonencode(["PY", var.jetbrains_ide_versions["PY"].build_number, "https://download.jetbrains.com/python/pycharm-professional-${var.jetbrains_ide_versions["PY"].version}.tar.gz"])
131+
icon = "/icon/pycharm.svg",
132+
name = "PyCharm Professional",
133+
identifier = "PY",
134+
build_number = var.jetbrains_ide_versions["PY"].build_number,
135+
download_link = "https://download.jetbrains.com/python/pycharm-professional-${var.jetbrains_ide_versions["PY"].version}.tar.gz"
129136
},
130137
"CL" = {
131-
icon = "/icon/clion.svg",
132-
name = "CLion",
133-
value = jsonencode(["CL", var.jetbrains_ide_versions["CL"].build_number, "https://download.jetbrains.com/cpp/CLion-${var.jetbrains_ide_versions["CL"].version}.tar.gz"])
138+
icon = "/icon/clion.svg",
139+
name = "CLion",
140+
identifier = "CL",
141+
build_number = var.jetbrains_ide_versions["CL"].build_number,
142+
download_link = "https://download.jetbrains.com/cpp/CLion-${var.jetbrains_ide_versions["CL"].version}.tar.gz"
134143
},
135144
"PS" = {
136-
icon = "/icon/phpstorm.svg",
137-
name = "PhpStorm",
138-
value = jsonencode(["PS", var.jetbrains_ide_versions["PS"].build_number, "https://download.jetbrains.com/webide/PhpStorm-${var.jetbrains_ide_versions["PS"].version}.tar.gz"])
145+
icon = "/icon/phpstorm.svg",
146+
name = "PhpStorm",
147+
identifier = "PS",
148+
build_number = var.jetbrains_ide_versions["PS"].build_number,
149+
download_link = "https://download.jetbrains.com/webide/PhpStorm-${var.jetbrains_ide_versions["PS"].version}.tar.gz"
139150
},
140151
"RM" = {
141-
icon = "/icon/rubymine.svg",
142-
name = "RubyMine",
143-
value = jsonencode(["RM", var.jetbrains_ide_versions["RM"].build_number, "https://download.jetbrains.com/ruby/RubyMine-${var.jetbrains_ide_versions["RM"].version}.tar.gz"])
152+
icon = "/icon/rubymine.svg",
153+
name = "RubyMine",
154+
identifier = "RM",
155+
build_number = var.jetbrains_ide_versions["RM"].build_number,
156+
download_link = "https://download.jetbrains.com/ruby/RubyMine-${var.jetbrains_ide_versions["RM"].version}.tar.gz"
144157
}
145158
}
146159
}
147160

148161
data "coder_parameter" "jetbrains_ide" {
149-
type = "list(string)"
162+
type = "string"
150163
name = "jetbrains_ide"
151164
display_name = "JetBrains IDE"
152165
icon = "/icon/gateway.svg"
153166
mutable = true
154-
# check if default is in the jet_brains_ides list and if it is not empty or null otherwise set it to null
155-
default = var.default != null && var.default != "" && contains(var.jetbrains_ides, var.default) ? local.jetbrains_ides[var.default].value : local.jetbrains_ides[var.jetbrains_ides[0]].value
167+
default = var.default == "" ? var.jetbrains_ides[0] : var.default
156168

157169
dynamic "option" {
158-
for_each = { for key, value in local.jetbrains_ides : key => value if contains(var.jetbrains_ides, key) }
170+
for_each = var.jetbrains_ides
159171
content {
160-
icon = option.value.icon
161-
name = option.value.name
162-
value = option.value.value
172+
icon = lookup(local.jetbrains_ides, option.value).icon
173+
name = lookup(local.jetbrains_ides, option.value).name
174+
value = lookup(local.jetbrains_ides, option.value).identifier
163175
}
164176
}
165177
}
@@ -168,9 +180,9 @@ data "coder_workspace" "me" {}
168180

169181
resource "coder_app" "gateway" {
170182
agent_id = var.agent_id
171-
display_name = data.coder_parameter.jetbrains_ide.option[index(data.coder_parameter.jetbrains_ide.option.*.value, data.coder_parameter.jetbrains_ide.value)].name
172183
slug = "gateway"
173-
icon = data.coder_parameter.jetbrains_ide.option[index(data.coder_parameter.jetbrains_ide.option.*.value, data.coder_parameter.jetbrains_ide.value)].icon
184+
display_name = try(lookup(local.jetbrains_ides, data.coder_parameter.jetbrains_ide.value).name, "JetBrains IDE")
185+
icon = try(lookup(local.jetbrains_ides, data.coder_parameter.jetbrains_ide.value).icon, "/icon/gateway.svg")
174186
external = true
175187
url = join("", [
176188
"jetbrains-gateway://connect#type=coder&workspace=",
@@ -184,14 +196,38 @@ resource "coder_app" "gateway" {
184196
"&token=",
185197
"$SESSION_TOKEN",
186198
"&ide_product_code=",
187-
jsondecode(data.coder_parameter.jetbrains_ide.value)[0],
199+
local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].identifier,
188200
"&ide_build_number=",
189-
jsondecode(data.coder_parameter.jetbrains_ide.value)[1],
201+
local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].build_number,
190202
"&ide_download_link=",
191-
jsondecode(data.coder_parameter.jetbrains_ide.value)[2],
203+
local.jetbrains_ides[data.coder_parameter.jetbrains_ide.value].download_link
192204
])
193205
}
194206

195-
output "jetbrains_ides" {
207+
output "identifier" {
196208
value = data.coder_parameter.jetbrains_ide.value
197209
}
210+
211+
output "name" {
212+
value = coder_app.gateway.display_name
213+
}
214+
215+
output "icon" {
216+
value = coder_app.gateway.icon
217+
}
218+
219+
output "download_link" {
220+
value = lookup(local.jetbrains_ides, data.coder_parameter.jetbrains_ide.value).download_link
221+
}
222+
223+
output "build_number" {
224+
value = lookup(local.jetbrains_ides, data.coder_parameter.jetbrains_ide.value).build_number
225+
}
226+
227+
output "version" {
228+
value = var.jetbrains_ide_versions[data.coder_parameter.jetbrains_ide.value].version
229+
}
230+
231+
output "url" {
232+
value = coder_app.gateway.url
233+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"test": "bun test",
55
"fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf",
66
"fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf",
7-
"lint": "bun run lint.ts",
7+
"lint": "bun run lint.ts && ./terraform_validate.sh",
88
"update-version": "./update-version.sh"
99
},
1010
"devDependencies": {

terraform_validate.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/bash
2+
3+
set -euo pipefail
4+
5+
# Function to run terraform init and validate in a directory
6+
run_terraform() {
7+
local dir="$1"
8+
echo "Running terraform init and validate in $dir"
9+
pushd "$dir"
10+
terraform init -upgrade
11+
terraform validate
12+
popd
13+
}
14+
15+
# Main script
16+
main() {
17+
# Get the directory of the script
18+
script_dir=$(dirname "$(readlink -f "$0")")
19+
20+
# Get all subdirectories in the repository
21+
subdirs=$(find "$script_dir" -mindepth 1 -maxdepth 1 -type d -not -name ".*" | sort)
22+
23+
for dir in $subdirs; do
24+
run_terraform "$dir"
25+
done
26+
}
27+
28+
# Run the main script
29+
main

0 commit comments

Comments
 (0)