Skip to content

Commit ec5b604

Browse files
authored
feat: allow validation to be used with options (#202)
1 parent f5dc37c commit ec5b604

File tree

4 files changed

+145
-14
lines changed

4 files changed

+145
-14
lines changed

Diff for: README.md

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,39 @@
11
# terraform-provider-coder
22

3-
See [Coder](https://github.com/coder/coder).
3+
Terraform provider for [Coder](https://github.com/coder/coder).
4+
5+
### Developing
6+
7+
Follow the instructions outlined in the [Terraform documentation](https://developer.hashicorp.com/terraform/cli/config/config-file#development-overrides-for-provider-developers)
8+
to setup your local Terraform to use your local version rather than the registry version.
9+
10+
1. Create a file named `.terraformrc` in your `$HOME` directory
11+
2. Add the following content:
12+
```hcl
13+
provider_installation {
14+
# Override the coder/coder provider to use your local version
15+
dev_overrides {
16+
"coder/coder" = "/path/to/terraform-provider-coder"
17+
}
18+
19+
# For all other providers, install them directly from their origin provider
20+
# registries as normal. If you omit this, Terraform will _only_ use
21+
# the dev_overrides block, and so no other providers will be available.
22+
direct {}
23+
}
24+
```
25+
3. (optional, but recommended) Validate your configuration:
26+
1. Create a new `main.tf` file and include:
27+
```hcl
28+
terraform {
29+
required_providers {
30+
coder = {
31+
source = "coder/coder"
32+
}
33+
}
34+
}
35+
```
36+
2. Run `terraform init` and observe a warning like `Warning: Provider development overrides are in effect`
37+
4. Run `go build -o terraform-provider-coder` to build the provider binary, which Terraform will try locate and execute
38+
5. All local Terraform runs will now use your local provider!
39+
6. _**NOTE**: we vendor in this provider into `github.com/coder/coder`, so if you're testing with a local clone then you should also run `go mod edit -replace github.com/coder/terraform-provider-coder=/path/to/terraform-provider-coder` in your clone._

Diff for: examples/resources/coder_parameter/resource.tf

+30
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,34 @@ data "coder_parameter" "users" {
8484
display_name = "System users"
8585
type = "list(string)"
8686
default = jsonencode(["root", "user1", "user2"])
87+
}
88+
89+
data "coder_parameter" "home_volume_size" {
90+
name = "Home Volume Size"
91+
description = <<-EOF
92+
How large should your home volume be?
93+
EOF
94+
type = "number"
95+
default = 30
96+
mutable = true
97+
order = 3
98+
99+
option {
100+
name = "30GB"
101+
value = 30
102+
}
103+
104+
option {
105+
name = "60GB"
106+
value = 60
107+
}
108+
109+
option {
110+
name = "100GB"
111+
value = 100
112+
}
113+
114+
validation {
115+
monotonic = "increasing"
116+
}
87117
}

Diff for: provider/parameter.go

+12-11
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,11 @@ func parameterDataSource() *schema.Resource {
231231
},
232232
},
233233
"option": {
234-
Type: schema.TypeList,
235-
Description: "Each \"option\" block defines a value for a user to select from.",
236-
ForceNew: true,
237-
Optional: true,
238-
MaxItems: 64,
239-
ConflictsWith: []string{"validation"},
234+
Type: schema.TypeList,
235+
Description: "Each \"option\" block defines a value for a user to select from.",
236+
ForceNew: true,
237+
Optional: true,
238+
MaxItems: 64,
240239
Elem: &schema.Resource{
241240
Schema: map[string]*schema.Schema{
242241
"name": {
@@ -276,11 +275,10 @@ func parameterDataSource() *schema.Resource {
276275
},
277276
},
278277
"validation": {
279-
Type: schema.TypeList,
280-
MaxItems: 1,
281-
Optional: true,
282-
Description: "Validate the input of a parameter.",
283-
ConflictsWith: []string{"option"},
278+
Type: schema.TypeList,
279+
MaxItems: 1,
280+
Optional: true,
281+
Description: "Validate the input of a parameter.",
284282
Elem: &schema.Resource{
285283
Schema: map[string]*schema.Schema{
286284
"min": {
@@ -410,6 +408,9 @@ func (v *Validation) Valid(typ, value string) error {
410408
if !v.MaxDisabled {
411409
return fmt.Errorf("a max cannot be specified for a %s type", typ)
412410
}
411+
if v.Monotonic != "" {
412+
return fmt.Errorf("monotonic validation can only be specified for number types, not %s types", typ)
413+
}
413414
}
414415
if typ != "string" && v.Regex != "" {
415416
return fmt.Errorf("a regex cannot be specified for a %s type", typ)

Diff for: provider/parameter_test.go

+66-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func TestParameter(t *testing.T) {
7373
}
7474
},
7575
}, {
76-
Name: "ValidationWithOptions",
76+
Name: "RegexValidationWithOptions",
7777
Config: `
7878
data "coder_parameter" "region" {
7979
name = "Region"
@@ -88,7 +88,23 @@ func TestParameter(t *testing.T) {
8888
}
8989
}
9090
`,
91-
ExpectError: regexp.MustCompile("conflicts with option"),
91+
ExpectError: regexp.MustCompile("a regex cannot be specified for a number type"),
92+
}, {
93+
Name: "MonotonicValidationWithNonNumberType",
94+
Config: `
95+
data "coder_parameter" "region" {
96+
name = "Region"
97+
type = "string"
98+
option {
99+
name = "1"
100+
value = "1"
101+
}
102+
validation {
103+
monotonic = "increasing"
104+
}
105+
}
106+
`,
107+
ExpectError: regexp.MustCompile("monotonic validation can only be specified for number types, not string types"),
92108
}, {
93109
Name: "ValidationRegexMissingError",
94110
Config: `
@@ -424,6 +440,54 @@ data "coder_parameter" "region" {
424440
require.Equal(t, expected, state.Primary.Attributes[key])
425441
}
426442
},
443+
}, {
444+
Name: "NumberValidation_MonotonicWithOptions",
445+
Config: `
446+
data "coder_parameter" "region" {
447+
name = "Region"
448+
type = "number"
449+
description = <<-EOF
450+
Always pick a larger region.
451+
EOF
452+
default = 1
453+
454+
option {
455+
name = "Small"
456+
value = 1
457+
}
458+
459+
option {
460+
name = "Medium"
461+
value = 2
462+
}
463+
464+
option {
465+
name = "Large"
466+
value = 3
467+
}
468+
469+
validation {
470+
monotonic = "increasing"
471+
}
472+
}
473+
`,
474+
Check: func(state *terraform.ResourceState) {
475+
for key, expected := range map[string]any{
476+
"name": "Region",
477+
"type": "number",
478+
"validation.#": "1",
479+
"option.0.name": "Small",
480+
"option.0.value": "1",
481+
"option.1.name": "Medium",
482+
"option.1.value": "2",
483+
"option.2.name": "Large",
484+
"option.2.value": "3",
485+
"default": "1",
486+
"validation.0.monotonic": "increasing",
487+
} {
488+
require.Equal(t, expected, state.Primary.Attributes[key])
489+
}
490+
},
427491
}, {
428492
Name: "NumberValidation_Min",
429493
Config: `

0 commit comments

Comments
 (0)