Skip to content

Commit f153663

Browse files
committed
feat: add coder_devcontainer resource
This change will allow autostarting Dev Containers. This is implemented as a resource instead of a `schema.TypeSet` on the agent resource to allow definition via Coder modules. Updates coder/coder#16423
1 parent 7e1e25c commit f153663

File tree

4 files changed

+174
-0
lines changed

4 files changed

+174
-0
lines changed

docs/resources/devcontainer.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "coder_devcontainer Resource - terraform-provider-coder"
4+
subcategory: ""
5+
description: |-
6+
Define a Dev Container the agent should know of and attempt to autostart.
7+
---
8+
9+
# coder_devcontainer (Resource)
10+
11+
Define a Dev Container the agent should know of and attempt to autostart.
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `agent_id` (String) The `id` property of a `coder_agent` resource to associate with.
21+
- `workspace_folder` (String) The workspace folder to for the Dev Container.
22+
23+
### Optional
24+
25+
- `config_path` (String) The path to the Dev Container configuration file (devcontainer.json).
26+
27+
### Read-Only
28+
29+
- `id` (String) The ID of this resource.

provider/devcontainer.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
6+
"github.com/google/uuid"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
10+
)
11+
12+
func devcontainerResource() *schema.Resource {
13+
return &schema.Resource{
14+
SchemaVersion: 1,
15+
16+
Description: "Define a Dev Container the agent should know of and attempt to autostart.",
17+
CreateContext: func(_ context.Context, rd *schema.ResourceData, _ interface{}) diag.Diagnostics {
18+
rd.SetId(uuid.NewString())
19+
20+
return nil
21+
},
22+
ReadContext: schema.NoopContext,
23+
DeleteContext: schema.NoopContext,
24+
Schema: map[string]*schema.Schema{
25+
"agent_id": {
26+
Type: schema.TypeString,
27+
Description: "The `id` property of a `coder_agent` resource to associate with.",
28+
ForceNew: true,
29+
Required: true,
30+
},
31+
"workspace_folder": {
32+
Type: schema.TypeString,
33+
Description: "The workspace folder to for the Dev Container.",
34+
ForceNew: true,
35+
Required: true,
36+
ValidateFunc: validation.StringIsNotEmpty,
37+
},
38+
"config_path": {
39+
Type: schema.TypeString,
40+
Description: "The path to the Dev Container configuration file (devcontainer.json).",
41+
ForceNew: true,
42+
Optional: true,
43+
},
44+
},
45+
}
46+
}

provider/devcontainer_test.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package provider_test
2+
3+
import (
4+
"regexp"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
11+
)
12+
13+
func TestDevcontainer(t *testing.T) {
14+
t.Parallel()
15+
16+
resource.Test(t, resource.TestCase{
17+
ProviderFactories: coderFactory(),
18+
IsUnitTest: true,
19+
Steps: []resource.TestStep{{
20+
Config: `
21+
provider "coder" {
22+
}
23+
resource "coder_devcontainer" "example" {
24+
agent_id = "king"
25+
workspace_folder = "/workspace"
26+
config_path = "/workspace/devcontainer.json"
27+
}
28+
`,
29+
Check: func(state *terraform.State) error {
30+
require.Len(t, state.Modules, 1)
31+
require.Len(t, state.Modules[0].Resources, 1)
32+
script := state.Modules[0].Resources["coder_devcontainer.example"]
33+
require.NotNil(t, script)
34+
t.Logf("script attributes: %#v", script.Primary.Attributes)
35+
for key, expected := range map[string]string{
36+
"agent_id": "king",
37+
"workspace_folder": "/workspace",
38+
"config_path": "/workspace/devcontainer.json",
39+
} {
40+
require.Equal(t, expected, script.Primary.Attributes[key])
41+
}
42+
return nil
43+
},
44+
}},
45+
})
46+
}
47+
48+
func TestDevcontainerNoConfigPath(t *testing.T) {
49+
t.Parallel()
50+
51+
resource.Test(t, resource.TestCase{
52+
ProviderFactories: coderFactory(),
53+
IsUnitTest: true,
54+
Steps: []resource.TestStep{{
55+
Config: `
56+
provider "coder" {
57+
}
58+
resource "coder_devcontainer" "example" {
59+
agent_id = "king"
60+
workspace_folder = "/workspace"
61+
}
62+
`,
63+
Check: func(state *terraform.State) error {
64+
require.Len(t, state.Modules, 1)
65+
require.Len(t, state.Modules[0].Resources, 1)
66+
script := state.Modules[0].Resources["coder_devcontainer.example"]
67+
require.NotNil(t, script)
68+
t.Logf("script attributes: %#v", script.Primary.Attributes)
69+
for key, expected := range map[string]string{
70+
"agent_id": "king",
71+
"workspace_folder": "/workspace",
72+
} {
73+
require.Equal(t, expected, script.Primary.Attributes[key])
74+
}
75+
return nil
76+
},
77+
}},
78+
})
79+
}
80+
81+
func TestDevcontainerNoWorkspaceFolder(t *testing.T) {
82+
t.Parallel()
83+
84+
resource.Test(t, resource.TestCase{
85+
ProviderFactories: coderFactory(),
86+
IsUnitTest: true,
87+
Steps: []resource.TestStep{{
88+
Config: `
89+
provider "coder" {
90+
}
91+
resource "coder_devcontainer" "example" {
92+
agent_id = ""
93+
}
94+
`,
95+
ExpectError: regexp.MustCompile(`The argument "workspace_folder" is required, but no definition was found.`),
96+
}},
97+
})
98+
}

provider/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func New() *schema.Provider {
7676
"coder_metadata": metadataResource(),
7777
"coder_script": scriptResource(),
7878
"coder_env": envResource(),
79+
"coder_devcontainer": devcontainerResource(),
7980
},
8081
}
8182
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy