diff --git a/docs/resources/env.md b/docs/resources/env.md new file mode 100644 index 00000000..5c68f08e --- /dev/null +++ b/docs/resources/env.md @@ -0,0 +1,29 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "coder_env Resource - terraform-provider-coder" +subcategory: "" +description: |- + Use this resource to set an environment variable in a workspace. +--- + +# coder_env (Resource) + +Use this resource to set an environment variable in a workspace. + + + + +## Schema + +### Required + +- `agent_id` (String) The "id" property of a "coder_agent" resource to associate with. +- `name` (String) The name of the environment variable. + +### Optional + +- `value` (String) The value of the environment variable. + +### Read-Only + +- `id` (String) The ID of this resource. diff --git a/provider/env.go b/provider/env.go new file mode 100644 index 00000000..f71ae987 --- /dev/null +++ b/provider/env.go @@ -0,0 +1,48 @@ +package provider + +import ( + "context" + "regexp" + + "github.com/google/uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func envResource() *schema.Resource { + return &schema.Resource{ + Description: "Use this resource to set an environment variable in a workspace.", + CreateContext: func(_ context.Context, rd *schema.ResourceData, _ interface{}) diag.Diagnostics { + rd.SetId(uuid.NewString()) + + return nil + }, + ReadContext: schema.NoopContext, + DeleteContext: schema.NoopContext, + Schema: map[string]*schema.Schema{ + "agent_id": { + Type: schema.TypeString, + Description: `The "id" property of a "coder_agent" resource to associate with.`, + ForceNew: true, + Required: true, + }, + "name": { + Type: schema.TypeString, + Description: "The name of the environment variable.", + ForceNew: true, + Required: true, + ValidateFunc: validation.StringMatch( + regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`), + "must be a valid environment variable name", + ), + }, + "value": { + Type: schema.TypeString, + Description: "The value of the environment variable.", + ForceNew: true, + Optional: true, + }, + }, + } +} diff --git a/provider/env_test.go b/provider/env_test.go new file mode 100644 index 00000000..66925f5e --- /dev/null +++ b/provider/env_test.go @@ -0,0 +1,129 @@ +package provider_test + +import ( + "regexp" + "testing" + + "github.com/coder/terraform-provider-coder/provider" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestEnv(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_env" "example" { + agent_id = "king" + name = "MESSAGE" + value = "Believe in yourself and there will come a day when others will have no choice but to believe with you." + } + `, + Check: func(state *terraform.State) error { + require.Len(t, state.Modules, 1) + require.Len(t, state.Modules[0].Resources, 1) + script := state.Modules[0].Resources["coder_env.example"] + require.NotNil(t, script) + t.Logf("script attributes: %#v", script.Primary.Attributes) + for key, expected := range map[string]string{ + "agent_id": "king", + "name": "MESSAGE", + "value": "Believe in yourself and there will come a day when others will have no choice but to believe with you.", + } { + require.Equal(t, expected, script.Primary.Attributes[key]) + } + return nil + }, + }}, + }) +} + +func TestEnvEmptyValue(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_env" "example" { + agent_id = "king" + name = "MESSAGE" + } + `, + Check: func(state *terraform.State) error { + require.Len(t, state.Modules, 1) + require.Len(t, state.Modules[0].Resources, 1) + script := state.Modules[0].Resources["coder_env.example"] + require.NotNil(t, script) + t.Logf("script attributes: %#v", script.Primary.Attributes) + for key, expected := range map[string]string{ + "agent_id": "king", + "name": "MESSAGE", + "value": "", + } { + require.Equal(t, expected, script.Primary.Attributes[key]) + } + return nil + }, + }}, + }) +} + +func TestEnvBadName(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_env" "example" { + agent_id = "" + name = "bad-name" + } + `, + ExpectError: regexp.MustCompile(`must be a valid environment variable name`), + }}, + }) +} + +func TestEnvNoName(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_env" "example" { + agent_id = "" + } + `, + ExpectError: regexp.MustCompile(`The argument "name" is required, but no definition was found.`), + }}, + }) +} diff --git a/provider/provider.go b/provider/provider.go index 6556146e..fb262c8c 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -80,6 +80,7 @@ func New() *schema.Provider { "coder_app": appResource(), "coder_metadata": metadataResource(), "coder_script": scriptResource(), + "coder_env": envResource(), }, } }