Skip to content

Commit

Permalink
feat: add slug to app, rename name to display_name (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
deansheather authored Oct 20, 2022
1 parent bcd1524 commit c474eba
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 41 deletions.
35 changes: 20 additions & 15 deletions docs/resources/app.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ EOF
}
resource "coder_app" "code-server" {
agent_id = coder_agent.dev.id
name = "VS Code"
icon = data.coder_workspace.me.access_url + "/icons/vscode.svg"
url = "http://localhost:13337"
share = "owner"
subdomain = false
agent_id = coder_agent.dev.id
slug = "code-server"
display_name = "VS Code"
icon = data.coder_workspace.me.access_url + "/icons/vscode.svg"
url = "http://localhost:13337"
share = "owner"
subdomain = false
healthcheck {
url = "http://localhost:13337/healthz"
interval = 5
Expand All @@ -40,17 +41,19 @@ resource "coder_app" "code-server" {
}
resource "coder_app" "vim" {
agent_id = coder_agent.dev.id
name = "Vim"
icon = "${data.coder_workspace.me.access_url}/icon/vim.svg"
command = "vim"
agent_id = coder_agent.dev.id
slug = "vim"
display_name = "Vim"
icon = "${data.coder_workspace.me.access_url}/icon/vim.svg"
command = "vim"
}
resource "coder_app" "intellij" {
agent_id = coder_agent.dev.id
icon = "${data.coder_workspace.me.access_url}/icon/intellij.svg"
name = "JetBrains IntelliJ"
command = "projector run"
agent_id = coder_agent.dev.id
icon = "${data.coder_workspace.me.access_url}/icon/intellij.svg"
slug = "intellij"
display_name = "JetBrains IntelliJ"
command = "projector run"
}
```

Expand All @@ -60,13 +63,15 @@ resource "coder_app" "intellij" {
### Required

- `agent_id` (String) The "id" property of a "coder_agent" resource to associate with.
- `slug` (String) A hostname-friendly name for the app. This is used in URLs to access the app. May contain alphanumerics and hyphens. Cannot start/end with a hyphen or contain two consecutive hyphens.

### Optional

- `command` (String) A command to run in a terminal opening this app. In the web, this will open in a new tab. In the CLI, this will SSH and execute the command. Either "command" or "url" may be specified, but not both.
- `display_name` (String) A display name to identify the app. Defaults to the slug.
- `healthcheck` (Block Set, Max: 1) HTTP health checking to determine the application readiness. (see [below for nested schema](#nestedblock--healthcheck))
- `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/icons. Use a built-in icon with `data.coder_workspace.me.access_url + "/icons/<path>"`.
- `name` (String) A display name to identify the app.
- `name` (String, Deprecated) A display name to identify the app.
- `relative_path` (Boolean, Deprecated) Specifies whether the URL will be accessed via a relative path or wildcard. Use if wildcard routing is unavailable. Defaults to true.
- `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).
- `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.
Expand Down
31 changes: 17 additions & 14 deletions examples/resources/coder_app/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ EOF
}

resource "coder_app" "code-server" {
agent_id = coder_agent.dev.id
name = "VS Code"
icon = data.coder_workspace.me.access_url + "/icons/vscode.svg"
url = "http://localhost:13337"
share = "owner"
subdomain = false
agent_id = coder_agent.dev.id
slug = "code-server"
display_name = "VS Code"
icon = data.coder_workspace.me.access_url + "/icons/vscode.svg"
url = "http://localhost:13337"
share = "owner"
subdomain = false
healthcheck {
url = "http://localhost:13337/healthz"
interval = 5
Expand All @@ -25,15 +26,17 @@ resource "coder_app" "code-server" {
}

resource "coder_app" "vim" {
agent_id = coder_agent.dev.id
name = "Vim"
icon = "${data.coder_workspace.me.access_url}/icon/vim.svg"
command = "vim"
agent_id = coder_agent.dev.id
slug = "vim"
display_name = "Vim"
icon = "${data.coder_workspace.me.access_url}/icon/vim.svg"
command = "vim"
}

resource "coder_app" "intellij" {
agent_id = coder_agent.dev.id
icon = "${data.coder_workspace.me.access_url}/icon/intellij.svg"
name = "JetBrains IntelliJ"
command = "projector run"
agent_id = coder_agent.dev.id
icon = "${data.coder_workspace.me.access_url}/icon/intellij.svg"
slug = "intellij"
display_name = "JetBrains IntelliJ"
command = "projector run"
}
61 changes: 52 additions & 9 deletions provider/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@ package provider
import (
"context"
"net/url"
"regexp"

"github.com/google/uuid"
"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

var (
// appSlugRegex is the regex used to validate the slug of a coder_app
// resource. It must be a valid hostname and cannot contain two consecutive
// hyphens or start/end with a hyphen.
//
// This regex is duplicated in the Coder source code, so make sure to update
// it there as well.
//
// There are test cases for this regex in the Coder product.
appSlugRegex = regexp.MustCompile(`^[a-z0-9](-?[a-z0-9])*$`)
)

func appResource() *schema.Resource {
return &schema.Resource{
Description: "Use this resource to define shortcuts to access applications in a workspace.",
Expand Down Expand Up @@ -54,19 +67,40 @@ func appResource() *schema.Resource {
return nil, nil
},
},
"name": {
"slug": {
Type: schema.TypeString,
Description: "A hostname-friendly name for the app. This is " +
"used in URLs to access the app. May contain " +
"alphanumerics and hyphens. Cannot start/end with a " +
"hyphen or contain two consecutive hyphens.",
ForceNew: true,
Required: true,
ValidateDiagFunc: func(val interface{}, c cty.Path) diag.Diagnostics {
valStr, ok := val.(string)
if !ok {
return diag.Errorf("expected string, got %T", val)
}

if !appSlugRegex.MatchString(valStr) {
return diag.Errorf("invalid coder_app slug, must be a valid hostname (%q, cannot contain two consecutive hyphens or start/end with a hyphen): %q", appSlugRegex.String(), valStr)
}

return nil
},
},
"display_name": {
Type: schema.TypeString,
Description: "A display name to identify the app.",
Description: "A display name to identify the app. Defaults to the slug.",
ForceNew: true,
Optional: true,
},
"relative_path": {
Type: schema.TypeBool,
Deprecated: "`relative_path` on apps is deprecated, use `subdomain` instead.",
Description: "Specifies whether the URL will be accessed via a relative " +
"path or wildcard. Use if wildcard routing is unavailable. Defaults to true.",
ForceNew: true,
Optional: true,
"name": {
Type: schema.TypeString,
Description: "A display name to identify the app.",
Deprecated: "`name` on apps is deprecated, use `display_name` instead",
ForceNew: true,
Optional: true,
ConflictsWith: []string{"display_name"},
},
"subdomain": {
Type: schema.TypeBool,
Expand All @@ -77,6 +111,15 @@ func appResource() *schema.Resource {
ForceNew: true,
Optional: true,
},
"relative_path": {
Type: schema.TypeBool,
Deprecated: "`relative_path` on apps is deprecated, use `subdomain` instead.",
Description: "Specifies whether the URL will be accessed via a relative " +
"path or wildcard. Use if wildcard routing is unavailable. Defaults to true.",
ForceNew: true,
Optional: true,
ConflictsWith: []string{"subdomain"},
},
"share": {
Type: schema.TypeString,
Description: `Determines the "level" which the application ` +
Expand Down
9 changes: 6 additions & 3 deletions provider/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ func TestApp(t *testing.T) {
}
resource "coder_app" "code-server" {
agent_id = coder_agent.dev.id
name = "code-server"
slug = "code-server"
display_name = "code-server"
icon = "builtin:vim"
subdomain = false
url = "http://localhost:13337"
Expand All @@ -51,7 +52,8 @@ func TestApp(t *testing.T) {
require.NotNil(t, resource)
for _, key := range []string{
"agent_id",
"name",
"slug",
"display_name",
"icon",
"subdomain",
// Should be set by default even though it isn't
Expand Down Expand Up @@ -128,7 +130,8 @@ func TestApp(t *testing.T) {
}
resource "coder_app" "code-server" {
agent_id = coder_agent.dev.id
name = "code-server"
slug = "code-server"
display_name = "code-server"
icon = "builtin:vim"
url = "http://localhost:13337"
%s
Expand Down

0 comments on commit c474eba

Please sign in to comment.