Skip to content

Commit 6f96ddf

Browse files
committed
feat: Add support for regex patterns to EnvEnsure().
1 parent c12ccfc commit 6f96ddf

12 files changed

+191
-80
lines changed

Makefile

+8-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ lint: vuln
213213

214214
.PHONY: test
215215
## test: [test]* Runs ALL tests.
216-
test: unit acc
216+
test: unit examples acc
217217

218218
.PHONY: acc
219219
## acc: [test] Runs Terraform provider acceptance tests. Set NAME= (without 'Test') to run a specific test by name
@@ -229,6 +229,13 @@ unit:
229229
@ $(ECHO) "\033[1;33m=====> Running unit tests...\033[0m"
230230
$(GO) test -run=Test$(NAME) -count=1 -parallel=$(shell nproc) -timeout 30s -coverpkg=./corefunc/... -coverprofile=__coverage.out -v ./corefunc/...
231231

232+
.PHONY: examples
233+
## examples: [test] Runs tests for examples. Set NAME= (without 'Example') to run a specific test by name
234+
examples:
235+
@ $(ECHO) " "
236+
@ $(ECHO) "\033[1;33m=====> Running tests for examples...\033[0m"
237+
$(GO) test -run=Example$(NAME) -count=1 -parallel=$(shell nproc) -timeout 30s -coverpkg=./corefunc/... -coverprofile=__coverage.out -v ./corefunc/...
238+
232239
.PHONY: fuzz
233240
## fuzz: [test]* Runs the fuzzer for 10 minutes. Set NAME= (without 'Fuzz') to run a specific test by name
234241
fuzz:

corefunc/env_ensure.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,39 @@ package corefunc
33
import (
44
"errors"
55
"os"
6+
"regexp"
67
)
78

89
/*
910
EnvEnsure ensures that a given environment variable is set to a non-empty value.
1011
If the environment variable is unset or if it is set to an empty string,
1112
EnvEnsure will respond with an error.
1213
14+
Not every Terraform provider checks to ensure that the environment variables it
15+
requires are properly set before performing work, leading to late-stage errors.
16+
This will force an error to occur early in the execution if the environment
17+
variable is not set, or if its value doesn't match the expected patttern.
18+
1319
----
1420
1521
* name (string): The name of the environment variable to check.
22+
23+
* pattern (*regexp.Regexp): The result of a call to `regexp.Compile()` or `regexp.MustCompile()`.
1624
*/
17-
func EnvEnsure(name string) error {
25+
func EnvEnsure(name string, pattern ...*regexp.Regexp) error {
1826
if os.Getenv(name) == "" {
1927
return errors.New("environment variable " + name + " is not defined") // lint:allow_errorf
2028
}
2129

30+
if len(pattern) > 0 && pattern[0] != nil {
31+
if !pattern[0].MatchString(os.Getenv(name)) {
32+
return errors.New( // lint:allow_errorf
33+
"environment variable " + name + " does not match pattern " + pattern[0].String(),
34+
)
35+
}
36+
37+
return nil
38+
}
39+
2240
return nil
2341
}

corefunc/env_ensure_test.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package corefunc
33
import (
44
"fmt"
55
"os"
6+
"regexp"
67
"testing"
78

89
"github.com/northwood-labs/terraform-provider-corefunc/testfixtures"
@@ -27,11 +28,27 @@ func ExampleEnvEnsure() {
2728
// environment variable MY_ENV_VAR_NOT_SET is not defined
2829
}
2930

31+
func ExampleEnvEnsure_pattern() {
32+
_ = os.Setenv("AWS_VAULT", "dev")
33+
34+
// This will not throw an error because it is defined, and there is no pattern to match.
35+
err := EnvEnsure("AWS_VAULT")
36+
fmt.Println(err)
37+
38+
// This will throw an error because the pattern does not match.
39+
err = EnvEnsure("AWS_VAULT", regexp.MustCompile(`(non)?prod$`))
40+
fmt.Println(err)
41+
42+
// Output:
43+
// <nil>
44+
// environment variable AWS_VAULT does not match pattern (non)?prod$
45+
}
46+
3047
func TestEnvEnsure(t *testing.T) {
3148
for name, tc := range testfixtures.EnvEnsureTestTable {
3249
t.Run(name, func(t *testing.T) {
3350
_ = os.Setenv(tc.EnvVarName, tc.SetValue)
34-
err := EnvEnsure(tc.EnvVarName)
51+
err := EnvEnsure(tc.EnvVarName, tc.Pattern)
3552

3653
if tc.ExpectedErr != nil {
3754
expectedErrorMsg := tc.ExpectedErr.Error()

corefuncprovider/env_ensure_data_source.go

+20-7
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ import (
44
"context"
55
"fmt"
66
"os"
7+
"regexp"
78
"strings"
89

9-
"github.com/northwood-labs/terraform-provider-corefunc/corefunc"
10-
1110
"github.com/hashicorp/terraform-plugin-framework/datasource"
1211
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
1312
"github.com/hashicorp/terraform-plugin-framework/resource"
1413
"github.com/hashicorp/terraform-plugin-framework/types"
1514
"github.com/hashicorp/terraform-plugin-log/tflog"
1615
"github.com/lithammer/dedent"
16+
"github.com/northwood-labs/terraform-provider-corefunc/corefunc"
1717
)
1818

1919
// Ensure the implementation satisfies the expected interfaces.
@@ -28,9 +28,10 @@ type (
2828

2929
// envEnsureDataSourceModel maps the data source schema data.
3030
envEnsureDataSourceModel struct {
31-
ID types.Int64 `tfsdk:"id"`
32-
Name types.String `tfsdk:"name"`
33-
Value types.String `tfsdk:"value"`
31+
ID types.Int64 `tfsdk:"id"`
32+
Name types.String `tfsdk:"name"`
33+
Pattern types.String `tfsdk:"pattern"`
34+
Value types.String `tfsdk:"value"`
3435
}
3536
)
3637

@@ -70,6 +71,11 @@ func (d *envEnsureDataSource) Schema(
7071
If the environment variable is unset or if it is set to an empty string,
7172
it will trigger a Terraform-level error.
7273
74+
Not every Terraform provider checks to ensure that the environment variables it
75+
requires are properly set before performing work, leading to late-stage errors.
76+
This will force an error to occur early in the execution if the environment
77+
variable is not set, or if its value doesn't match the expected patttern.
78+
7379
Maps to the ` + linkPackage("EnvEnsure") + ` Go method, which can be used in
7480
` + Terratest + `.
7581
`)),
@@ -82,6 +88,10 @@ func (d *envEnsureDataSource) Schema(
8288
Description: "The name of the environment variable to check.",
8389
Required: true,
8490
},
91+
"pattern": schema.StringAttribute{
92+
Description: "A valid Go ([re2](https://github.com/google/re2/wiki/Syntax)) regular expression pattern.",
93+
Optional: true,
94+
},
8595
"value": schema.StringAttribute{
8696
Description: "The value of the environment variable, if it exists.",
8797
Computed: true,
@@ -140,10 +150,13 @@ func (d *envEnsureDataSource) Read(
140150

141151
state.ID = types.Int64Value(1)
142152

143-
err := corefunc.EnvEnsure(state.Name.ValueString())
153+
err := corefunc.EnvEnsure(
154+
state.Name.ValueString(),
155+
regexp.MustCompile(state.Pattern.ValueString()),
156+
)
144157
if err != nil {
145158
resp.Diagnostics.AddError(
146-
"Undefined Environment Variable",
159+
"Problem with Environment Variable",
147160
err.Error(),
148161
)
149162

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
data "corefunc_env_ensure" "env" {
2+
name = "{{ .EnvVarName }}"
3+
{{- with .Pattern }}
4+
pattern = "{{ . }}"
5+
{{- end }}
6+
}

corefuncprovider/env_ensure_data_source_test.go

+16-11
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package corefuncprovider
22

33
import (
4+
"bytes"
45
"fmt"
6+
"log"
57
"os"
68
"regexp"
79
"strings"
810
"testing"
11+
"text/template"
912

1013
"github.com/northwood-labs/terraform-provider-corefunc/testfixtures"
1114

@@ -24,17 +27,23 @@ func TestAccEnvEnsureDataSource(t *testing.T) {
2427

2528
_ = os.Setenv(tc.EnvVarName, tc.SetValue)
2629

30+
buf := new(bytes.Buffer)
31+
tmpl := template.Must(
32+
template.ParseFiles("env_ensure_data_source_fixture.tftpl"),
33+
)
34+
35+
err := tmpl.Execute(buf, tc)
36+
if err != nil {
37+
log.Fatalln(err)
38+
}
39+
2740
// We expect the error to be nil.
2841
if tc.ExpectedErr == nil {
2942
resource.Test(t, resource.TestCase{
3043
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
3144
Steps: []resource.TestStep{
3245
{
33-
Config: providerConfig + `
34-
data "corefunc_env_ensure" "env" {
35-
name = "` + tc.EnvVarName + `"
36-
}
37-
`,
46+
Config: providerConfig + buf.String(),
3847
Check: resource.ComposeAggregateTestCheckFunc(
3948
resource.TestCheckResourceAttr("data.corefunc_env_ensure.env", "value", tc.SetValue),
4049
),
@@ -48,12 +57,8 @@ func TestAccEnvEnsureDataSource(t *testing.T) {
4857
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
4958
Steps: []resource.TestStep{
5059
{
51-
Config: providerConfig + `
52-
data "corefunc_env_ensure" "env" {
53-
name = "` + tc.EnvVarName + `"
54-
}
55-
`,
56-
ExpectError: regexp.MustCompile("environment variable (\\w+) is not defined"),
60+
Config: providerConfig + buf.String(),
61+
ExpectError: regexp.MustCompile("environment variable (\\w+) (is not defined|does not match pattern)"),
5762
},
5863
},
5964
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
data "corefunc_str_truncate_label" "truncated" {
2+
prefix = "NW-ZZZ-CLOUD-TEST-APP-CLOUD-PROD-CRIT"
3+
label = "K8S Pods Not Running Deployment Check"
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
data "corefunc_str_truncate_label" "label" {
2+
prefix = "{{ .Prefix }}"
3+
label = "{{ .Label }}"
4+
max_length = {{ .MaxLength }}
5+
}

corefuncprovider/truncate_label_data_source_test.go

+30-20
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
11
package corefuncprovider
22

33
import (
4+
"bytes"
45
"fmt"
6+
"log"
57
"strings"
68
"testing"
9+
"text/template"
710

811
"github.com/northwood-labs/terraform-provider-corefunc/testfixtures"
912

1013
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
1114
)
1215

1316
func TestAccTruncateLabelDataSourceDefaultMaxLength64(t *testing.T) {
17+
buf := new(bytes.Buffer)
18+
tmpl := template.Must(
19+
template.ParseFiles("truncate_label_data_source_fixture_default64.tftpl"),
20+
)
21+
22+
err := tmpl.Execute(buf, nil)
23+
if err != nil {
24+
log.Fatalln(err)
25+
}
26+
1427
resource.Test(t, resource.TestCase{
1528
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
1629
Steps: []resource.TestStep{
1730
{
18-
Config: providerConfig + `
19-
data "corefunc_str_truncate_label" "truncated" {
20-
prefix = "NW-ZZZ-CLOUD-TEST-APP-CLOUD-PROD-CRIT"
21-
label = "K8S Pods Not Running Deployment Check"
22-
}
23-
`,
31+
Config: providerConfig + buf.String(),
2432
Check: resource.ComposeAggregateTestCheckFunc(
2533
resource.TestCheckResourceAttr(
2634
"data.corefunc_str_truncate_label.truncated",
@@ -43,24 +51,26 @@ func TestAccTruncateLabelDataSource(t *testing.T) {
4351
strings.TrimSpace(name),
4452
)
4553

54+
buf := new(bytes.Buffer)
55+
tmpl := template.Must(
56+
template.ParseFiles("truncate_label_data_source_fixture_maxlength.tftpl"),
57+
)
58+
59+
// Minimum value for the provider is 1.
60+
if tc.MaxLength == 0 {
61+
tc.MaxLength += 1
62+
}
63+
64+
err := tmpl.Execute(buf, tc)
65+
if err != nil {
66+
log.Fatalln(err)
67+
}
68+
4669
resource.Test(t, resource.TestCase{
4770
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
4871
Steps: []resource.TestStep{
4972
{
50-
Config: providerConfig + `
51-
data "corefunc_str_truncate_label" "label" {
52-
prefix = "` + tc.Prefix + `"
53-
label = "` + tc.Label + `"
54-
max_length = ` +
55-
func() string {
56-
if tc.MaxLength == 0 {
57-
tc.MaxLength += 1
58-
}
59-
60-
return fmt.Sprint(tc.MaxLength)
61-
}() + `
62-
}
63-
`,
73+
Config: providerConfig + buf.String(),
6474
Check: resource.ComposeAggregateTestCheckFunc(
6575
resource.TestCheckResourceAttr(
6676
"data.corefunc_str_truncate_label.label",

docs/data-sources/env_ensure.md

+24-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ description: |-
66
Ensures that a given environment variable is set to a non-empty value.
77
If the environment variable is unset or if it is set to an empty string,
88
it will trigger a Terraform-level error.
9+
Not every Terraform provider checks to ensure that the environment variables it
10+
requires are properly set before performing work, leading to late-stage errors.
11+
This will force an error to occur early in the execution if the environment
12+
variable is not set, or if its value doesn't match the expected patttern.
913
Maps to the corefunc.EnvEnsure() https://pkg.go.dev/github.com/northwood-labs/terraform-provider-corefunc/corefunc#EnvEnsure Go method, which can be used in
1014
Terratest https://terratest.gruntwork.io.
1115
---
@@ -17,6 +21,11 @@ Ensures that a given environment variable is set to a non-empty value.
1721
If the environment variable is unset or if it is set to an empty string,
1822
it will trigger a Terraform-level error.
1923

24+
Not every Terraform provider checks to ensure that the environment variables it
25+
requires are properly set before performing work, leading to late-stage errors.
26+
This will force an error to occur early in the execution if the environment
27+
variable is not set, or if its value doesn't match the expected patttern.
28+
2029
Maps to the [`corefunc.EnvEnsure()`](https://pkg.go.dev/github.com/northwood-labs/terraform-provider-corefunc/corefunc#EnvEnsure) Go method, which can be used in
2130
[Terratest](https://terratest.gruntwork.io).
2231

@@ -45,13 +54,19 @@ data "corefunc_env_ensure" "aws_pager" {
4554
name = "AWS_PAGER"
4655
}
4756
48-
# `aws_pager_value` is the read-only attribute containing the value of the
49-
# environment variable
50-
output "aws_pager_value" {
51-
value = data.corefunc_env_ensure.aws_pager.value
57+
#=> [Error] Problem with Environment Variable: environment variable
58+
#=> AWS_PAGER is not defined
59+
60+
#-------------------------------------------------------------------------
61+
# AWS_VAULT="dev"
62+
63+
data "corefunc_env_ensure" "aws_vault" {
64+
name = "AWS_VAULT"
65+
pattern = "(non)?prod$" # Must end with "prod" or "nonprod".
5266
}
5367
54-
#=> [Error] Undefined Environment Variable: environment variable AWS_PAGER is not defined
68+
#=> [Error] Problem with Environment Variable: environment variable
69+
#=> AWS_VAULT does not match pattern (non)?prod$
5570
```
5671

5772
<!-- schema generated by tfplugindocs -->
@@ -61,6 +76,10 @@ output "aws_pager_value" {
6176

6277
* `name` (String) The name of the environment variable to check.
6378

79+
### Optional
80+
81+
* `pattern` (String) A valid Go ([re2](https://github.com/google/re2/wiki/Syntax)) regular expression pattern.
82+
6483
### Read-Only
6584

6685
* `id` (Number) Not used. Required by the [Terraform Plugin Framework](https://developer.hashicorp.com/terraform/plugin/framework).

0 commit comments

Comments
 (0)