Skip to content

Commit fccc10b

Browse files
feat: add 'hidden' field to 'coder_app' provider (#276) (#284)
* feat: add 'hidden' field to 'coder_app' provider * fix: run 'make gen' * test: add integration test for 'coder_app.hidden' * fix: warn on 'hidden' being used with conflicting fields
1 parent e0c0dbe commit fccc10b

File tree

5 files changed

+182
-1
lines changed

5 files changed

+182
-1
lines changed

Diff for: docs/resources/app.md

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ resource "coder_app" "vim" {
6363
- `display_name` (String) A display name to identify the app. Defaults to the slug.
6464
- `external` (Boolean) Specifies whether `url` is opened on the client machine instead of proxied through the workspace.
6565
- `healthcheck` (Block Set, Max: 1) HTTP health checking to determine the application readiness. (see [below for nested schema](#nestedblock--healthcheck))
66+
- `hidden` (Boolean) Determines if the app is visible in the UI.
6667
- `icon` (String) A URL to an icon that will display in the dashboard. View built-in icons here: https://github.com/coder/coder/tree/main/site/static/icon. Use a built-in icon with `"${data.coder_workspace.me.access_url}/icon/<path>"`.
6768
- `name` (String, **Deprecated**: `name` on apps is deprecated, use `display_name` instead) A display name to identify the app.
6869
- `order` (Number) The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order).

Diff for: integration/coder-app-hidden/main.tf

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
terraform {
2+
required_providers {
3+
coder = {
4+
source = "coder/coder"
5+
}
6+
local = {
7+
source = "hashicorp/local"
8+
}
9+
}
10+
}
11+
12+
data "coder_workspace" "me" {}
13+
14+
resource "coder_agent" "dev" {
15+
os = "linux"
16+
arch = "amd64"
17+
dir = "/workspace"
18+
}
19+
20+
resource "coder_app" "hidden" {
21+
agent_id = coder_agent.dev.id
22+
slug = "hidden"
23+
share = "owner"
24+
hidden = true
25+
}
26+
27+
resource "coder_app" "visible" {
28+
agent_id = coder_agent.dev.id
29+
slug = "visible"
30+
share = "owner"
31+
hidden = false
32+
}
33+
34+
resource "coder_app" "defaulted" {
35+
agent_id = coder_agent.dev.id
36+
slug = "defaulted"
37+
share = "owner"
38+
}
39+
40+
locals {
41+
# NOTE: these must all be strings in the output
42+
output = {
43+
"coder_app.hidden.hidden" = tostring(coder_app.hidden.hidden)
44+
"coder_app.visible.hidden" = tostring(coder_app.visible.hidden)
45+
"coder_app.defaulted.hidden" = tostring(coder_app.defaulted.hidden)
46+
}
47+
}
48+
49+
variable "output_path" {
50+
type = string
51+
}
52+
53+
resource "local_file" "output" {
54+
filename = var.output_path
55+
content = jsonencode(local.output)
56+
}
57+
58+
output "output" {
59+
value = local.output
60+
sensitive = true
61+
}
62+

Diff for: integration/integration_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@ func TestIntegration(t *testing.T) {
126126
"workspace_owner.ssh_public_key": `(?s)^ssh-ed25519.+$`,
127127
},
128128
},
129+
{
130+
name: "coder-app-hidden",
131+
minVersion: "v0.0.0",
132+
expectedOutput: map[string]string{
133+
"coder_app.hidden.hidden": "true",
134+
"coder_app.visible.hidden": "false",
135+
"coder_app.defaulted.hidden": "false",
136+
},
137+
},
129138
} {
130139
tt := tt
131140
t.Run(tt.name, func(t *testing.T) {

Diff for: provider/app.go

+37-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,36 @@ func appResource() *schema.Resource {
3030
Description: "Use this resource to define shortcuts to access applications in a workspace.",
3131
CreateContext: func(c context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics {
3232
resourceData.SetId(uuid.NewString())
33-
return nil
33+
34+
diags := diag.Diagnostics{}
35+
36+
hiddenData := resourceData.Get("hidden")
37+
if hidden, ok := hiddenData.(bool); !ok {
38+
return diag.Errorf("hidden should be a bool")
39+
} else if hidden {
40+
if _, ok := resourceData.GetOk("display_name"); ok {
41+
diags = append(diags, diag.Diagnostic{
42+
Severity: diag.Warning,
43+
Summary: "`display_name` set when app is hidden",
44+
})
45+
}
46+
47+
if _, ok := resourceData.GetOk("icon"); ok {
48+
diags = append(diags, diag.Diagnostic{
49+
Severity: diag.Warning,
50+
Summary: "`icon` set when app is hidden",
51+
})
52+
}
53+
54+
if _, ok := resourceData.GetOk("order"); ok {
55+
diags = append(diags, diag.Diagnostic{
56+
Severity: diag.Warning,
57+
Summary: "`order` set when app is hidden",
58+
})
59+
}
60+
}
61+
62+
return diags
3463
},
3564
ReadContext: func(c context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics {
3665
return nil
@@ -204,6 +233,13 @@ func appResource() *schema.Resource {
204233
ForceNew: true,
205234
Optional: true,
206235
},
236+
"hidden": {
237+
Type: schema.TypeBool,
238+
Description: "Determines if the app is visible in the UI.",
239+
Default: false,
240+
ForceNew: true,
241+
Optional: true,
242+
},
207243
},
208244
}
209245
}

Diff for: provider/app_test.go

+73
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ func TestApp(t *testing.T) {
4545
threshold = 6
4646
}
4747
order = 4
48+
hidden = false
4849
}
4950
`,
5051
Check: func(state *terraform.State) error {
@@ -66,6 +67,7 @@ func TestApp(t *testing.T) {
6667
"healthcheck.0.interval",
6768
"healthcheck.0.threshold",
6869
"order",
70+
"hidden",
6971
} {
7072
value := resource.Primary.Attributes[key]
7173
t.Logf("%q = %q", key, value)
@@ -246,4 +248,75 @@ func TestApp(t *testing.T) {
246248
})
247249
}
248250
})
251+
252+
t.Run("Hidden", func(t *testing.T) {
253+
t.Parallel()
254+
255+
cases := []struct {
256+
name string
257+
config string
258+
hidden bool
259+
}{{
260+
name: "Is Hidden",
261+
config: `
262+
provider "coder" {}
263+
resource "coder_agent" "dev" {
264+
os = "linux"
265+
arch = "amd64"
266+
}
267+
resource "coder_app" "test" {
268+
agent_id = coder_agent.dev.id
269+
slug = "test"
270+
display_name = "Testing"
271+
url = "https://google.com"
272+
external = true
273+
hidden = true
274+
}
275+
`,
276+
hidden: true,
277+
}, {
278+
name: "Is Not Hidden",
279+
config: `
280+
provider "coder" {}
281+
resource "coder_agent" "dev" {
282+
os = "linux"
283+
arch = "amd64"
284+
}
285+
resource "coder_app" "test" {
286+
agent_id = coder_agent.dev.id
287+
slug = "test"
288+
display_name = "Testing"
289+
url = "https://google.com"
290+
external = true
291+
hidden = false
292+
}
293+
`,
294+
hidden: false,
295+
}}
296+
for _, tc := range cases {
297+
tc := tc
298+
t.Run(tc.name, func(t *testing.T) {
299+
t.Parallel()
300+
resource.Test(t, resource.TestCase{
301+
Providers: map[string]*schema.Provider{
302+
"coder": provider.New(),
303+
},
304+
IsUnitTest: true,
305+
Steps: []resource.TestStep{{
306+
Config: tc.config,
307+
Check: func(state *terraform.State) error {
308+
require.Len(t, state.Modules, 1)
309+
require.Len(t, state.Modules[0].Resources, 2)
310+
resource := state.Modules[0].Resources["coder_app.test"]
311+
require.NotNil(t, resource)
312+
require.Equal(t, strconv.FormatBool(tc.hidden), resource.Primary.Attributes["hidden"])
313+
return nil
314+
},
315+
ExpectError: nil,
316+
}},
317+
})
318+
})
319+
}
320+
})
321+
249322
}

0 commit comments

Comments
 (0)