diff --git a/docs/data-sources/parameter.md b/docs/data-sources/parameter.md index 31a4234a..7483c9d0 100644 --- a/docs/data-sources/parameter.md +++ b/docs/data-sources/parameter.md @@ -28,7 +28,7 @@ Use this data source to configure editable options for workspaces. - `legacy_variable_name` (String) Name of the legacy Terraform variable. Coder will use it to lookup the variable value. - `mutable` (Boolean) Whether this value can be changed after workspace creation. This can be destructive for values like region, so use with caution! - `option` (Block List, Max: 64) Each "option" block defines a value for a user to select from. (see [below for nested schema](#nestedblock--option)) -- `type` (String) The type of this parameter. Must be one of: "number", "string", or "bool". +- `type` (String) The type of this parameter. Must be one of: "number", "string", "bool", or "list(string)". - `validation` (Block List, Max: 1) Validate the input of a parameter. (see [below for nested schema](#nestedblock--validation)) ### Read-Only diff --git a/examples/resources/coder_parameter/resource.tf b/examples/resources/coder_parameter/resource.tf index 4d1206cd..cbbc3ec7 100644 --- a/examples/resources/coder_parameter/resource.tf +++ b/examples/resources/coder_parameter/resource.tf @@ -74,4 +74,10 @@ data "coder_parameter" "cat_lives" { data "coder_parameter" "fairy_tale" { name = "Fairy Tale" type = "string" +} + +data "coder_parameter" "users" { + name = "System users" + type = "list(string)" + default = jsonencode(["root", "user1", "user2"]) } \ No newline at end of file diff --git a/provider/parameter.go b/provider/parameter.go index ce364166..c547f384 100644 --- a/provider/parameter.go +++ b/provider/parameter.go @@ -4,6 +4,7 @@ import ( "context" "crypto/sha256" "encoding/hex" + "encoding/json" "fmt" "net/url" "os" @@ -180,8 +181,8 @@ func parameterDataSource() *schema.Resource { Type: schema.TypeString, Default: "string", Optional: true, - ValidateFunc: validation.StringInSlice([]string{"number", "string", "bool"}, false), - Description: `The type of this parameter. Must be one of: "number", "string", or "bool".`, + ValidateFunc: validation.StringInSlice([]string{"number", "string", "bool", "list(string)"}, false), + Description: `The type of this parameter. Must be one of: "number", "string", "bool", or "list(string)".`, }, "mutable": { Type: schema.TypeBool, @@ -328,6 +329,12 @@ func valueIsType(typ, value string) diag.Diagnostics { if err != nil { return diag.Errorf("%q is not a bool", value) } + case "list(string)": + var items []string + err := json.Unmarshal([]byte(value), &items) + if err != nil { + return diag.Errorf("%q is not an array of strings", value) + } case "string": // Anything is a string! default: diff --git a/provider/parameter_test.go b/provider/parameter_test.go index 71d1e7e2..6b42673c 100644 --- a/provider/parameter_test.go +++ b/provider/parameter_test.go @@ -359,6 +359,51 @@ data "coder_parameter" "region" { require.Equal(t, expected, state.Primary.Attributes[key]) } }, + }, { + Name: "ListOfStrings", + Config: ` +data "coder_parameter" "region" { + name = "Region" + type = "list(string)" + default = jsonencode(["us-east-1", "eu-west-1", "ap-northeast-1"]) +}`, + Check: func(state *terraform.ResourceState) { + for key, expected := range map[string]string{ + "name": "Region", + "type": "list(string)", + "default": `["us-east-1","eu-west-1","ap-northeast-1"]`, + } { + attributeValue, ok := state.Primary.Attributes[key] + require.True(t, ok, "attribute %q is expected", key) + require.Equal(t, expected, attributeValue) + } + }, + }, { + Name: "ListOfStringsButMigrated", + Config: ` +variable "old_region" { + type = list(string) + default = ["us-west-1a"] # for testing purposes, no need to set via env TF_... +} + +data "coder_parameter" "region" { + name = "Region" + type = "list(string)" + default = "[\"us-east-1\", \"eu-west-1\", \"ap-northeast-1\"]" + legacy_variable_name = "old_region" + legacy_variable = jsonencode(var.old_region) +}`, + Check: func(state *terraform.ResourceState) { + for key, expected := range map[string]string{ + "name": "Region", + "type": "list(string)", + "default": `["us-west-1a"]`, + } { + attributeValue, ok := state.Primary.Attributes[key] + require.True(t, ok, "attribute %q is expected", key) + require.Equal(t, expected, attributeValue) + } + }, }} { tc := tc t.Run(tc.Name, func(t *testing.T) { @@ -376,7 +421,6 @@ data "coder_parameter" "region" { require.Len(t, state.Modules[0].Resources, 1) param := state.Modules[0].Resources["data.coder_parameter.region"] require.NotNil(t, param) - t.Logf("parameter attributes: %#v", param.Primary.Attributes) if tc.Check != nil { tc.Check(param) }