From d12c9090191717d11a6be92b0f2fe559473992f4 Mon Sep 17 00:00:00 2001 From: kylecarbs Date: Fri, 6 May 2022 01:29:13 +0000 Subject: [PATCH] feat: Add app support This adds what are presently named "devurls" in v1. It seems this is a dated term, since this allows much more than accessing applications via URL. "coder open " will launch any apps defined. If in the web, it'll open either a web terminal or port forward to the desired application. If in the terminal, it'll open the browser, or launch the command over SSH. --- docs/resources/app.md | 65 ++++++++++++++++++++++ examples/resources/coder_app/resource.tf | 32 +++++++++++ internal/provider/provider.go | 69 ++++++++++++++++++++++++ internal/provider/provider_test.go | 44 +++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 docs/resources/app.md create mode 100644 examples/resources/coder_app/resource.tf diff --git a/docs/resources/app.md b/docs/resources/app.md new file mode 100644 index 00000000..8742f0e9 --- /dev/null +++ b/docs/resources/app.md @@ -0,0 +1,65 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "coder_app Resource - terraform-provider-coder" +subcategory: "" +description: |- + Use this resource to define shortcuts to access applications in a workspace. +--- + +# coder_app (Resource) + +Use this resource to define shortcuts to access applications in a workspace. + +## Example Usage + +```terraform +data "coder_workspace" "me" {} + +resource "coder_agent" "dev" { + os = "linux" + arch = "amd64" + dir = "/workspace" + startup_script = < +## Schema + +### Required + +- `agent_id` (String) The "id" property of a "coder_agent" resource to associate with. + +### 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. +- `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/"`. +- `id` (String) The ID of this resource. +- `name` (String) A display name to identify the app. +- `target` (String) A URL to be proxied to from inside the workspace. + + diff --git a/examples/resources/coder_app/resource.tf b/examples/resources/coder_app/resource.tf new file mode 100644 index 00000000..23a0464d --- /dev/null +++ b/examples/resources/coder_app/resource.tf @@ -0,0 +1,32 @@ +data "coder_workspace" "me" {} + +resource "coder_agent" "dev" { + os = "linux" + arch = "amd64" + dir = "/workspace" + startup_script = <\"`.", + ForceNew: true, + Optional: true, + ValidateFunc: func(i interface{}, s string) ([]string, []error) { + _, err := url.Parse(s) + if err != nil { + return nil, []error{err} + } + return nil, nil + }, + }, + "name": { + Type: schema.TypeString, + Description: "A display name to identify the app.", + ForceNew: true, + Optional: true, + }, + "target": { + Type: schema.TypeString, + Description: "A URL to be proxied to from inside the workspace. " + + "Either \"command\" or \"target\" may be specified, but not both.", + ForceNew: true, + Optional: true, + ConflictsWith: []string{"command"}, + }, + }, + }, }, } } diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 3de6fefb..fdb8ce12 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -134,3 +134,47 @@ func TestAgentInstance(t *testing.T) { }}, }) } + +func TestApp(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "coder": provider.New(), + }, + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: ` + provider "coder" { + } + resource "coder_agent" "dev" { + os = "linux" + arch = "amd64" + } + resource "coder_app" "code-server" { + agent_id = coder_agent.dev.id + name = "code-server" + icon = "builtin:vim" + target = "http://localhost:13337" + } + `, + Check: func(state *terraform.State) error { + require.Len(t, state.Modules, 1) + require.Len(t, state.Modules[0].Resources, 2) + resource := state.Modules[0].Resources["coder_app.code-server"] + require.NotNil(t, resource) + for _, key := range []string{ + "agent_id", + "name", + "icon", + "target", + } { + value := resource.Primary.Attributes[key] + t.Logf("%q = %q", key, value) + require.NotNil(t, value) + require.Greater(t, len(value), 0) + } + return nil + }, + }}, + }) +}