Skip to content

Commit bb2167e

Browse files
authored
feat: add tooltip field to workspace app (#435)
* feat: add tooltip field to workspace app * remove duplicate test * run make gen * update tooltip max length to 2048
1 parent c8bc37a commit bb2167e

File tree

4 files changed

+82
-0
lines changed

4 files changed

+82
-0
lines changed

docs/resources/app.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ resource "coder_app" "code-server" {
3131
display_name = "VS Code"
3232
icon = "${data.coder_workspace.me.access_url}/icon/code.svg"
3333
url = "http://localhost:13337"
34+
tooltip = "You need to [Install Coder Desktop](https://coder.com/docs/user-guides/desktop#install-coder-desktop) to use this button."
3435
share = "owner"
3536
subdomain = false
3637
open_in = "window"
@@ -71,6 +72,7 @@ resource "coder_app" "vim" {
7172
- `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).
7273
- `share` (String) Determines the level which the application is shared at. Valid levels are `"owner"` (default), `"authenticated"` and `"public"`. Level `"owner"` disables sharing on the app, so only the workspace owner can access it. Level `"authenticated"` shares the app with all authenticated users. Level `"public"` shares it with any user, including unauthenticated users. Permitted application sharing levels can be configured site-wide via a flag on `coder server` (Enterprise only).
7374
- `subdomain` (Boolean) Determines whether the app will be accessed via it's own subdomain or whether it will be accessed via a path on Coder. If wildcards have not been setup by the administrator then apps with `subdomain` set to `true` will not be accessible. Defaults to `false`.
75+
- `tooltip` (String) Markdown text that is displayed when hovering over workspace apps.
7476
- `url` (String) An external url if `external=true` or a URL to be proxied to from inside the workspace. This should be of the form `http://localhost:PORT[/SUBPATH]`. Either `command` or `url` may be specified, but not both.
7577

7678
### Read-Only

examples/resources/coder_app/resource.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ resource "coder_app" "code-server" {
1616
display_name = "VS Code"
1717
icon = "${data.coder_workspace.me.access_url}/icon/code.svg"
1818
url = "http://localhost:13337"
19+
tooltip = "You need to [Install Coder Desktop](https://coder.com/docs/user-guides/desktop#install-coder-desktop) to use this button."
1920
share = "owner"
2021
subdomain = false
2122
open_in = "window"

provider/app.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ var (
2727
const (
2828
appDisplayNameMaxLength = 64 // database column limit
2929
appGroupNameMaxLength = 64
30+
appTooltipMaxLength = 2048
3031
)
3132

3233
func appResource() *schema.Resource {
@@ -273,6 +274,23 @@ func appResource() *schema.Resource {
273274
return diag.Errorf(`invalid "coder_app" open_in value, must be one of "tab", "slim-window": %q`, valStr)
274275
},
275276
},
277+
"tooltip": {
278+
Type: schema.TypeString,
279+
Description: "Markdown text that is displayed when hovering over workspace apps.",
280+
ForceNew: true,
281+
Optional: true,
282+
ValidateDiagFunc: func(val any, c cty.Path) diag.Diagnostics {
283+
valStr, ok := val.(string)
284+
if !ok {
285+
return diag.Errorf("expected string, got %T", val)
286+
}
287+
288+
if len(valStr) > appTooltipMaxLength {
289+
return diag.Errorf("tooltip is too long (max %d characters)", appTooltipMaxLength)
290+
}
291+
return nil
292+
},
293+
},
276294
},
277295
}
278296
}

provider/app_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"regexp"
66
"strconv"
7+
"strings"
78
"testing"
89

910
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
@@ -44,6 +45,7 @@ func TestApp(t *testing.T) {
4445
order = 4
4546
hidden = false
4647
open_in = "slim-window"
48+
tooltip = "You need to [Install Coder Desktop](https://coder.com/docs/user-guides/desktop#install-coder-desktop) to use this button."
4749
}
4850
`,
4951
Check: func(state *terraform.State) error {
@@ -68,6 +70,7 @@ func TestApp(t *testing.T) {
6870
"order",
6971
"hidden",
7072
"open_in",
73+
"tooltip",
7174
} {
7275
value := resource.Primary.Attributes[key]
7376
t.Logf("%q = %q", key, value)
@@ -535,4 +538,62 @@ func TestApp(t *testing.T) {
535538
})
536539
}
537540
})
541+
542+
t.Run("Tooltip", func(t *testing.T) {
543+
t.Parallel()
544+
545+
cases := []struct {
546+
name string
547+
tooltip string
548+
expectError *regexp.Regexp
549+
}{
550+
{
551+
name: "Empty",
552+
tooltip: "",
553+
},
554+
{
555+
name: "ValidTooltip",
556+
tooltip: "You need to [Install Coder Desktop](https://coder.com/docs/user-guides/desktop" +
557+
"#install-coder-desktop) to use this button.",
558+
},
559+
{
560+
name: "TooltipTooLong",
561+
tooltip: strings.Repeat("a", 2049),
562+
expectError: regexp.MustCompile("tooltip is too long"),
563+
},
564+
}
565+
566+
for _, c := range cases {
567+
c := c
568+
569+
t.Run(c.name, func(t *testing.T) {
570+
t.Parallel()
571+
572+
config := fmt.Sprintf(`
573+
provider "coder" {}
574+
resource "coder_agent" "dev" {
575+
os = "linux"
576+
arch = "amd64"
577+
}
578+
resource "coder_app" "code-server" {
579+
agent_id = coder_agent.dev.id
580+
slug = "code-server"
581+
display_name = "Testing"
582+
url = "http://localhost:13337"
583+
open_in = "slim-window"
584+
tooltip = "%s"
585+
}
586+
`, c.tooltip)
587+
588+
resource.Test(t, resource.TestCase{
589+
ProviderFactories: coderFactory(),
590+
IsUnitTest: true,
591+
Steps: []resource.TestStep{{
592+
Config: config,
593+
ExpectError: c.expectError,
594+
}},
595+
})
596+
})
597+
}
598+
})
538599
}

0 commit comments

Comments
 (0)