refactor: reorganize code to make it more readable (#71)

This commit is contained in:
Mateusz Filipowicz
2025-03-21 11:52:55 +01:00
committed by GitHub
parent 86fdc0b27a
commit cdc0254289
69 changed files with 404 additions and 524 deletions

View File

@@ -30,15 +30,15 @@ type cidrValidator struct {
allowEmpty bool
}
func (v cidrValidator) Description(ctx context.Context) string {
func (v cidrValidator) Description(_ context.Context) string {
return "value must be a valid CIDR notation (e.g., '192.168.1.0/24')"
}
func (v cidrValidator) MarkdownDescription(ctx context.Context) string {
func (v cidrValidator) MarkdownDescription(_ context.Context) string {
return "value must be a valid CIDR notation (e.g., `192.168.1.0/24`)"
}
func (v cidrValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
func (v cidrValidator) ValidateString(_ context.Context, req validator.StringRequest, resp *validator.StringResponse) {
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
return
}

View File

@@ -3,7 +3,7 @@ package validators
import (
"context"
"github.com/biter777/countries"
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)
@@ -24,7 +24,7 @@ func (c countryCodeAlpha2Validator) MarkdownDescription(ctx context.Context) str
func (c countryCodeAlpha2Validator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
code := req.ConfigValue
if base.IsEmptyString(code) {
if types.IsEmptyString(code) {
return
}

View File

@@ -1,48 +0,0 @@
package validators
import (
"context"
"fmt"
"regexp"
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)
// A common regex pattern for validating email addresses
// This is a simplified version and may not catch all edge cases
var emailRegex = regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)
// Email returns a validator which ensures that the string value is a valid email address.
func Email() validator.String {
return emailValidator{}
}
type emailValidator struct{}
func (v emailValidator) Description(_ context.Context) string {
return "must be a valid email address"
}
func (v emailValidator) MarkdownDescription(ctx context.Context) string {
return v.Description(ctx)
}
func (v emailValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
value := req.ConfigValue
if !base.IsDefined(value) {
return
}
val := value.ValueString()
if !emailRegex.MatchString(val) {
resp.Diagnostics.Append(
validatordiag.InvalidAttributeValueDiagnostic(
req.Path,
v.Description(ctx),
fmt.Sprintf("%q is not a valid email address", val),
),
)
}
}

View File

@@ -1,82 +0,0 @@
package validators_test
import (
"context"
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
"testing"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
)
func TestEmailValidator(t *testing.T) {
t.Parallel()
type testCase struct {
val types.String
expectError bool
}
tests := map[string]testCase{
"unknown": {
val: types.StringUnknown(),
},
"null": {
val: types.StringNull(),
},
"valid-simple": {
val: types.StringValue("test@example.com"),
},
"valid-with-dots": {
val: types.StringValue("john.doe@example.com"),
},
"valid-with-plus": {
val: types.StringValue("john+test@example.com"),
},
"valid-with-subdomain": {
val: types.StringValue("john@sub.example.com"),
},
"valid-with-numbers": {
val: types.StringValue("user123@example.com"),
},
"invalid-no-at": {
val: types.StringValue("testexample.com"),
expectError: true,
},
"invalid-no-domain": {
val: types.StringValue("test@"),
expectError: true,
},
"invalid-no-tld": {
val: types.StringValue("test@example"),
expectError: true,
},
"invalid-space": {
val: types.StringValue("test user@example.com"),
expectError: true,
},
"invalid-special-chars": {
val: types.StringValue("test*user@example.com"),
expectError: true,
},
}
for name, test := range tests {
name, test := name, test
t.Run(name, func(t *testing.T) {
t.Parallel()
request := validator.StringRequest{
ConfigValue: test.val,
}
response := validator.StringResponse{}
validators.Email().ValidateString(context.Background(), request, &response)
if !response.Diagnostics.HasError() && test.expectError {
t.Fatal("expected error, got no error")
}
if response.Diagnostics.HasError() && !test.expectError {
t.Fatalf("got unexpected error: %s", response.Diagnostics)
}
})
}
}

View File

@@ -1,47 +0,0 @@
package validators
import (
"context"
"fmt"
"regexp"
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)
var hexColorRegex = regexp.MustCompile("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$")
// HexColor returns a validator which ensures that the string value is a valid hex color code.
// Valid formats are: #RGB or #RRGGBB
func HexColor() validator.String {
return hexColorValidator{}
}
type hexColorValidator struct{}
func (v hexColorValidator) Description(_ context.Context) string {
return "must be a valid hex color code (e.g., #FFF or #FFFFFF)"
}
func (v hexColorValidator) MarkdownDescription(ctx context.Context) string {
return v.Description(ctx)
}
func (v hexColorValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
value := req.ConfigValue
if !base.IsDefined(value) {
return
}
val := value.ValueString()
if !hexColorRegex.MatchString(val) {
resp.Diagnostics.Append(
validatordiag.InvalidAttributeValueDiagnostic(
req.Path,
v.Description(ctx),
fmt.Sprintf("%q is not a valid hex color code", val),
),
)
}
}

View File

@@ -1,75 +0,0 @@
package validators_test
import (
"context"
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
"testing"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
)
func TestHexColorValidator(t *testing.T) {
t.Parallel()
type testCase struct {
val types.String
expectError bool
}
tests := map[string]testCase{
"unknown": {
val: types.StringUnknown(),
},
"null": {
val: types.StringNull(),
},
"valid-6-digits": {
val: types.StringValue("#123456"),
},
"valid-3-digits": {
val: types.StringValue("#123"),
},
"valid-uppercase": {
val: types.StringValue("#ABCDEF"),
},
"valid-mixed-case": {
val: types.StringValue("#aBcDeF"),
},
"invalid-missing-hash": {
val: types.StringValue("123456"),
expectError: true,
},
"invalid-too-short": {
val: types.StringValue("#12"),
expectError: true,
},
"invalid-too-long": {
val: types.StringValue("#1234567"),
expectError: true,
},
"invalid-wrong-chars": {
val: types.StringValue("#12345G"),
expectError: true,
},
}
for name, test := range tests {
name, test := name, test
t.Run(name, func(t *testing.T) {
t.Parallel()
request := validator.StringRequest{
ConfigValue: test.val,
}
response := validator.StringResponse{}
validators.HexColor().ValidateString(context.Background(), request, &response)
if !response.Diagnostics.HasError() && test.expectError {
t.Fatal("expected error, got no error")
}
if response.Diagnostics.HasError() && !test.expectError {
t.Fatalf("got unexpected error: %s", response.Diagnostics)
}
})
}
}

View File

@@ -3,10 +3,10 @@ package validators
import (
"context"
"fmt"
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
"regexp"
"strings"
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)
@@ -32,7 +32,7 @@ func (v hostnameValidator) MarkdownDescription(ctx context.Context) string {
func (v hostnameValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
value := req.ConfigValue
if !base.IsDefined(value) {
if !types.IsDefined(value) {
return
}

View File

@@ -3,7 +3,7 @@ package validators
import (
"context"
"fmt"
"github.com/filipowm/terraform-provider-unifi/internal/utils"
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)

View File

@@ -3,7 +3,7 @@ package validators
import (
"context"
"fmt"
"github.com/filipowm/terraform-provider-unifi/internal/utils"
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)

View File

@@ -0,0 +1 @@
package validators

View File

@@ -0,0 +1,27 @@
package validators
import (
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"regexp"
)
var (
TimeFormatRegex = regexp.MustCompile(`^[0-9][0-9]:[0-9][0-9]$`)
TimeFormat = stringvalidator.RegexMatches(TimeFormatRegex, "must be a valid time in 24-hour format (HH:MM)")
DateFormatRegex = regexp.MustCompile(`^(20[0-9]{2})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$`)
DateFormat = stringvalidator.RegexMatches(DateFormatRegex, "must be a valid date in the format YYYY-MM-DD")
PortRangeRegexp = regexp.MustCompile("(([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5])|([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5])-([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5]))+(,([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5])|,([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5])-([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5])){0,14}")
PortRangeV2 = validation.StringMatch(PortRangeRegexp, "invalid port range")
MacRegex = regexp.MustCompile(`^([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$`)
Mac = stringvalidator.RegexMatches(MacRegex, "invalid MAC address")
HexColorRegex = regexp.MustCompile("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$")
HexColor = stringvalidator.RegexMatches(HexColorRegex, "invalid hex color code")
EmailRegex = regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)
Email = stringvalidator.RegexMatches(EmailRegex, "invalid email address")
)

View File

@@ -3,6 +3,7 @@ package validators
import (
"context"
"fmt"
"strings"
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
"github.com/hashicorp/terraform-plugin-framework/attr"
@@ -182,6 +183,33 @@ func RequiredTogetherIf(conditionPath path.Expression, conditionValue attr.Value
}
}
func mapPathToExpression(p string) path.Expression {
parts := strings.Split(p, ".")
root := parts[0]
exp := path.MatchRoot(root)
for _, part := range parts[1:] {
exp = exp.AtName(part)
}
return exp
}
func mapPathsToExpressions(paths ...string) []path.Expression {
var expressions []path.Expression
for _, p := range paths {
expressions = append(expressions, mapPathToExpression(p))
}
return expressions
}
func RequiredSimpleTogetherIf(conditionPath string, conditionValue attr.Value, targetExpressions ...string) RequiredTogetherIfValidator {
return RequiredTogetherIfValidator{
ConditionPath: mapPathToExpression(conditionPath),
ConditionValue: conditionValue,
TargetExpressions: mapPathsToExpressions(targetExpressions...),
CheckOnlyIfSet: false,
}
}
// RequiredTogetherIfSet creates a validator that ensures a set of target attributes
// are configured together if a condition attribute is set (not null), regardless of its value.
func RequiredTogetherIfSet(conditionPath path.Expression, targetExpressions ...path.Expression) RequiredTogetherIfValidator {

View File

@@ -3,7 +3,7 @@ package validators
import (
"context"
"fmt"
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)
@@ -41,7 +41,7 @@ func (v stringLengthExactlyValidator) ValidateString(ctx context.Context, req va
}
value := req.ConfigValue
if !base.IsDefined(value) {
if !types.IsDefined(value) {
return
}
val := value.ValueString()

View File

@@ -3,10 +3,10 @@ package validators
import (
"context"
"fmt"
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
"strings"
"time"
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)
@@ -29,7 +29,7 @@ func (v timezoneValidator) MarkdownDescription(ctx context.Context) string {
func (v timezoneValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
value := req.ConfigValue
if !base.IsDefined(value) {
if !types.IsDefined(value) {
return
}

View File

@@ -3,9 +3,9 @@ package validators
import (
"context"
"fmt"
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
"net/url"
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)
@@ -37,7 +37,7 @@ func (v urlValidator) MarkdownDescription(ctx context.Context) string {
func (v urlValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
value := req.ConfigValue
if !base.IsDefined(value) {
if !types.IsDefined(value) {
return
}