From 6ee9188dd1ce9aab13d9b9598b7bf57ba4fcfbc2 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Tue, 5 Nov 2024 21:38:05 +0000 Subject: [PATCH 1/3] fix: use `codersdk` functions for validating name attributes --- .golangci.yml | 6 +-- internal/codersdkvalidator/display_name.go | 47 +++++++++++++++++++ internal/codersdkvalidator/name.go | 47 +++++++++++++++++++ .../template_version_name.go | 47 +++++++++++++++++++ internal/codersdkvalidator/user_real_name.go | 47 +++++++++++++++++++ internal/provider/group_resource.go | 8 ++-- internal/provider/template_resource.go | 10 ++-- internal/provider/user_resource.go | 6 +-- internal/provider/util.go | 7 --- 9 files changed, 201 insertions(+), 24 deletions(-) create mode 100644 internal/codersdkvalidator/display_name.go create mode 100644 internal/codersdkvalidator/name.go create mode 100644 internal/codersdkvalidator/template_version_name.go create mode 100644 internal/codersdkvalidator/user_real_name.go diff --git a/.golangci.yml b/.golangci.yml index 223cf95..679a35a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,5 @@ -# Visit https://golangci-lint.run/ for usage documentation -# and information on other useful linters +# Visit https://golangci-lint.run/ for usage documentation and information on +# other useful linters issues: max-per-linter: 0 max-same-issues: 0 @@ -24,4 +24,4 @@ linters: - unconvert - unparam - unused - - vet \ No newline at end of file + - vet diff --git a/internal/codersdkvalidator/display_name.go b/internal/codersdkvalidator/display_name.go new file mode 100644 index 0000000..2c08c78 --- /dev/null +++ b/internal/codersdkvalidator/display_name.go @@ -0,0 +1,47 @@ +package codersdkvalidator + +import ( + "context" + + "github.com/coder/coder/v2/codersdk" + "github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" +) + +type displayNameValidator struct { + err error +} + +func DisplayName() validator.String { + return displayNameValidator{} +} + +var _ validator.String = displayNameValidator{} + +func (v displayNameValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { + if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { + return + } + + name := req.ConfigValue.ValueString() + if v.err = codersdk.DisplayNameValid(name); v.err != nil { + resp.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic( + req.Path, + v.Description(ctx), + name, + )) + } +} + +var _ validator.Describer = displayNameValidator{} + +func (v displayNameValidator) Description(_ context.Context) string { + if v.err != nil { + return v.err.Error() + } + return "value must be a valid display name" +} + +func (v displayNameValidator) MarkdownDescription(ctx context.Context) string { + return v.Description(ctx) +} diff --git a/internal/codersdkvalidator/name.go b/internal/codersdkvalidator/name.go new file mode 100644 index 0000000..2c82fc0 --- /dev/null +++ b/internal/codersdkvalidator/name.go @@ -0,0 +1,47 @@ +package codersdkvalidator + +import ( + "context" + + "github.com/coder/coder/v2/codersdk" + "github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" +) + +type nameValidator struct { + err error +} + +func Name() validator.String { + return nameValidator{} +} + +var _ validator.String = nameValidator{} + +func (v nameValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { + if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { + return + } + + name := req.ConfigValue.ValueString() + if v.err = codersdk.NameValid(name); v.err != nil { + resp.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic( + req.Path, + v.Description(ctx), + name, + )) + } +} + +var _ validator.Describer = nameValidator{} + +func (v nameValidator) Description(_ context.Context) string { + if v.err != nil { + return v.err.Error() + } + return "value must be a valid name" +} + +func (v nameValidator) MarkdownDescription(ctx context.Context) string { + return v.Description(ctx) +} diff --git a/internal/codersdkvalidator/template_version_name.go b/internal/codersdkvalidator/template_version_name.go new file mode 100644 index 0000000..729182f --- /dev/null +++ b/internal/codersdkvalidator/template_version_name.go @@ -0,0 +1,47 @@ +package codersdkvalidator + +import ( + "context" + + "github.com/coder/coder/v2/codersdk" + "github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" +) + +type templateVersionNameValidator struct { + err error +} + +func TemplateVersionName() validator.String { + return templateVersionNameValidator{} +} + +var _ validator.String = templateVersionNameValidator{} + +func (v templateVersionNameValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { + if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { + return + } + + name := req.ConfigValue.ValueString() + if v.err = codersdk.TemplateVersionNameValid(name); v.err != nil { + resp.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic( + req.Path, + v.Description(ctx), + name, + )) + } +} + +var _ validator.Describer = templateVersionNameValidator{} + +func (v templateVersionNameValidator) Description(_ context.Context) string { + if v.err != nil { + return v.err.Error() + } + return "value must be a valid template version name" +} + +func (v templateVersionNameValidator) MarkdownDescription(ctx context.Context) string { + return v.Description(ctx) +} diff --git a/internal/codersdkvalidator/user_real_name.go b/internal/codersdkvalidator/user_real_name.go new file mode 100644 index 0000000..e33f5a0 --- /dev/null +++ b/internal/codersdkvalidator/user_real_name.go @@ -0,0 +1,47 @@ +package codersdkvalidator + +import ( + "context" + + "github.com/coder/coder/v2/codersdk" + "github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" +) + +type userRealNameValidator struct { + err error +} + +func UserRealName() validator.String { + return userRealNameValidator{} +} + +var _ validator.String = userRealNameValidator{} + +func (v userRealNameValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { + if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { + return + } + + name := req.ConfigValue.ValueString() + if v.err = codersdk.UserRealNameValid(name); v.err != nil { + resp.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic( + req.Path, + v.Description(ctx), + name, + )) + } +} + +var _ validator.Describer = userRealNameValidator{} + +func (v userRealNameValidator) Description(_ context.Context) string { + if v.err != nil { + return v.err.Error() + } + return "value must be a valid name for a user" +} + +func (v userRealNameValidator) MarkdownDescription(ctx context.Context) string { + return v.Description(ctx) +} diff --git a/internal/provider/group_resource.go b/internal/provider/group_resource.go index a7dcd6a..cbafac6 100644 --- a/internal/provider/group_resource.go +++ b/internal/provider/group_resource.go @@ -6,8 +6,8 @@ import ( "strings" "github.com/coder/coder/v2/codersdk" + "github.com/coder/terraform-provider-coderd/internal/codersdkvalidator" "github.com/google/uuid" - "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" @@ -77,8 +77,7 @@ func (r *GroupResource) Schema(ctx context.Context, req resource.SchemaRequest, MarkdownDescription: "The unique name of the group.", Required: true, Validators: []validator.String{ - stringvalidator.LengthBetween(1, 36), - stringvalidator.RegexMatches(nameValidRegex, "Group names must be alpahnumeric with hyphens."), + codersdkvalidator.Name(), }, }, "display_name": schema.StringAttribute{ @@ -86,8 +85,7 @@ func (r *GroupResource) Schema(ctx context.Context, req resource.SchemaRequest, Computed: true, Optional: true, Validators: []validator.String{ - stringvalidator.LengthBetween(1, 64), - stringvalidator.RegexMatches(displayNameRegex, "Group display names must be alphanumeric with spaces"), + codersdkvalidator.DisplayName(), }, Default: stringdefault.StaticString(""), }, diff --git a/internal/provider/template_resource.go b/internal/provider/template_resource.go index f1d7adc..a14d8d6 100644 --- a/internal/provider/template_resource.go +++ b/internal/provider/template_resource.go @@ -12,6 +12,7 @@ import ( "cdr.dev/slog" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/provisionersdk" + "github.com/coder/terraform-provider-coderd/internal/codersdkvalidator" "github.com/google/uuid" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" @@ -257,8 +258,7 @@ func (r *TemplateResource) Schema(ctx context.Context, req resource.SchemaReques MarkdownDescription: "The name of the template.", Required: true, Validators: []validator.String{ - stringvalidator.LengthBetween(1, 32), - stringvalidator.RegexMatches(nameValidRegex, "Template names must be alphanumeric with hyphens."), + codersdkvalidator.Name(), }, }, "display_name": schema.StringAttribute{ @@ -266,8 +266,7 @@ func (r *TemplateResource) Schema(ctx context.Context, req resource.SchemaReques Optional: true, Computed: true, Validators: []validator.String{ - stringvalidator.LengthBetween(1, 64), - stringvalidator.RegexMatches(displayNameRegex, "Template display names must be alphanumeric with spaces."), + codersdkvalidator.DisplayName(), }, }, "description": schema.StringAttribute{ @@ -417,8 +416,7 @@ func (r *TemplateResource) Schema(ctx context.Context, req resource.SchemaReques Optional: true, Computed: true, Validators: []validator.String{ - stringvalidator.LengthBetween(1, 64), - stringvalidator.RegexMatches(templateVersionNameRegex, "Template version names must be alphanumeric with underscores and dots."), + codersdkvalidator.TemplateVersionName(), }, }, "message": schema.StringAttribute{ diff --git a/internal/provider/user_resource.go b/internal/provider/user_resource.go index a560df5..3fa570e 100644 --- a/internal/provider/user_resource.go +++ b/internal/provider/user_resource.go @@ -22,6 +22,7 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/coder/coder/v2/codersdk" + "github.com/coder/terraform-provider-coderd/internal/codersdkvalidator" ) // Ensure provider defined types fully satisfy framework interfaces. @@ -71,8 +72,7 @@ func (r *UserResource) Schema(ctx context.Context, req resource.SchemaRequest, r MarkdownDescription: "Username of the user.", Required: true, Validators: []validator.String{ - stringvalidator.LengthBetween(1, 32), - stringvalidator.RegexMatches(nameValidRegex, "Username must be alphanumeric with hyphens."), + codersdkvalidator.Name(), }, }, "name": schema.StringAttribute{ @@ -80,7 +80,7 @@ func (r *UserResource) Schema(ctx context.Context, req resource.SchemaRequest, r Computed: true, Optional: true, Validators: []validator.String{ - stringvalidator.LengthBetween(1, 128), + codersdkvalidator.UserRealName(), }, }, "email": schema.StringAttribute{ diff --git a/internal/provider/util.go b/internal/provider/util.go index 12be3f3..d56fadb 100644 --- a/internal/provider/util.go +++ b/internal/provider/util.go @@ -8,18 +8,11 @@ import ( "net/http" "os" "path/filepath" - "regexp" "github.com/coder/coder/v2/codersdk" "github.com/google/uuid" ) -var ( - nameValidRegex = regexp.MustCompile("^[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*$") - templateVersionNameRegex = regexp.MustCompile(`^[a-zA-Z0-9]+(?:[_.-]{1}[a-zA-Z0-9]+)*$`) - displayNameRegex = regexp.MustCompile(`^[^\s](.*[^\s])?$`) -) - func PtrTo[T any](v T) *T { return &v } From 3a61f81bff603cf3cfc389b569d4df5b33097135 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Tue, 5 Nov 2024 21:49:04 +0000 Subject: [PATCH 2/3] oh nice --- internal/codersdkvalidator/display_name.go | 39 +------------- internal/codersdkvalidator/name.go | 39 +------------- .../template_version_name.go | 39 +------------- internal/codersdkvalidator/user_real_name.go | 39 +------------- .../codersdkvalidator/validator_from_func.go | 51 +++++++++++++++++++ 5 files changed, 55 insertions(+), 152 deletions(-) create mode 100644 internal/codersdkvalidator/validator_from_func.go diff --git a/internal/codersdkvalidator/display_name.go b/internal/codersdkvalidator/display_name.go index 2c08c78..1000c32 100644 --- a/internal/codersdkvalidator/display_name.go +++ b/internal/codersdkvalidator/display_name.go @@ -1,47 +1,10 @@ package codersdkvalidator import ( - "context" - "github.com/coder/coder/v2/codersdk" - "github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) -type displayNameValidator struct { - err error -} - func DisplayName() validator.String { - return displayNameValidator{} -} - -var _ validator.String = displayNameValidator{} - -func (v displayNameValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { - if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { - return - } - - name := req.ConfigValue.ValueString() - if v.err = codersdk.DisplayNameValid(name); v.err != nil { - resp.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic( - req.Path, - v.Description(ctx), - name, - )) - } -} - -var _ validator.Describer = displayNameValidator{} - -func (v displayNameValidator) Description(_ context.Context) string { - if v.err != nil { - return v.err.Error() - } - return "value must be a valid display name" -} - -func (v displayNameValidator) MarkdownDescription(ctx context.Context) string { - return v.Description(ctx) + return validatorFromFunc(codersdk.DisplayNameValid, "value must be a valid display name") } diff --git a/internal/codersdkvalidator/name.go b/internal/codersdkvalidator/name.go index 2c82fc0..14adb25 100644 --- a/internal/codersdkvalidator/name.go +++ b/internal/codersdkvalidator/name.go @@ -1,47 +1,10 @@ package codersdkvalidator import ( - "context" - "github.com/coder/coder/v2/codersdk" - "github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) -type nameValidator struct { - err error -} - func Name() validator.String { - return nameValidator{} -} - -var _ validator.String = nameValidator{} - -func (v nameValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { - if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { - return - } - - name := req.ConfigValue.ValueString() - if v.err = codersdk.NameValid(name); v.err != nil { - resp.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic( - req.Path, - v.Description(ctx), - name, - )) - } -} - -var _ validator.Describer = nameValidator{} - -func (v nameValidator) Description(_ context.Context) string { - if v.err != nil { - return v.err.Error() - } - return "value must be a valid name" -} - -func (v nameValidator) MarkdownDescription(ctx context.Context) string { - return v.Description(ctx) + return validatorFromFunc(codersdk.NameValid, "value must be a valid name") } diff --git a/internal/codersdkvalidator/template_version_name.go b/internal/codersdkvalidator/template_version_name.go index 729182f..32c69d6 100644 --- a/internal/codersdkvalidator/template_version_name.go +++ b/internal/codersdkvalidator/template_version_name.go @@ -1,47 +1,10 @@ package codersdkvalidator import ( - "context" - "github.com/coder/coder/v2/codersdk" - "github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) -type templateVersionNameValidator struct { - err error -} - func TemplateVersionName() validator.String { - return templateVersionNameValidator{} -} - -var _ validator.String = templateVersionNameValidator{} - -func (v templateVersionNameValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { - if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { - return - } - - name := req.ConfigValue.ValueString() - if v.err = codersdk.TemplateVersionNameValid(name); v.err != nil { - resp.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic( - req.Path, - v.Description(ctx), - name, - )) - } -} - -var _ validator.Describer = templateVersionNameValidator{} - -func (v templateVersionNameValidator) Description(_ context.Context) string { - if v.err != nil { - return v.err.Error() - } - return "value must be a valid template version name" -} - -func (v templateVersionNameValidator) MarkdownDescription(ctx context.Context) string { - return v.Description(ctx) + return validatorFromFunc(codersdk.TemplateVersionNameValid, "value must be a valid template version name") } diff --git a/internal/codersdkvalidator/user_real_name.go b/internal/codersdkvalidator/user_real_name.go index e33f5a0..5bf9686 100644 --- a/internal/codersdkvalidator/user_real_name.go +++ b/internal/codersdkvalidator/user_real_name.go @@ -1,47 +1,10 @@ package codersdkvalidator import ( - "context" - "github.com/coder/coder/v2/codersdk" - "github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) -type userRealNameValidator struct { - err error -} - func UserRealName() validator.String { - return userRealNameValidator{} -} - -var _ validator.String = userRealNameValidator{} - -func (v userRealNameValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { - if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { - return - } - - name := req.ConfigValue.ValueString() - if v.err = codersdk.UserRealNameValid(name); v.err != nil { - resp.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic( - req.Path, - v.Description(ctx), - name, - )) - } -} - -var _ validator.Describer = userRealNameValidator{} - -func (v userRealNameValidator) Description(_ context.Context) string { - if v.err != nil { - return v.err.Error() - } - return "value must be a valid name for a user" -} - -func (v userRealNameValidator) MarkdownDescription(ctx context.Context) string { - return v.Description(ctx) + return validatorFromFunc(codersdk.UserRealNameValid, "value must be a valid name for a user") } diff --git a/internal/codersdkvalidator/validator_from_func.go b/internal/codersdkvalidator/validator_from_func.go new file mode 100644 index 0000000..e7e9993 --- /dev/null +++ b/internal/codersdkvalidator/validator_from_func.go @@ -0,0 +1,51 @@ +package codersdkvalidator + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" +) + +type functionValidator struct { + check func(string) error + defaultMessage string + err error +} + +func validatorFromFunc(check func(string) error, defaultMessage string) functionValidator { + return functionValidator{ + check: check, + defaultMessage: defaultMessage, + } +} + +var _ validator.String = functionValidator{} + +func (v functionValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { + if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { + return + } + + name := req.ConfigValue.ValueString() + if v.err = v.check(name); v.err != nil { + resp.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic( + req.Path, + v.Description(ctx), + name, + )) + } +} + +var _ validator.Describer = functionValidator{} + +func (v functionValidator) Description(_ context.Context) string { + if v.err != nil { + return v.err.Error() + } + return "value must be a valid name" +} + +func (v functionValidator) MarkdownDescription(ctx context.Context) string { + return v.Description(ctx) +} From 0d27b318d829cc5793d8de88477ace93a93dfee6 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 7 Nov 2024 18:10:08 +0000 Subject: [PATCH 3/3] review feedback --- internal/codersdkvalidator/group_name.go | 10 ++++++++++ internal/codersdkvalidator/validator_from_func.go | 2 +- internal/provider/group_resource.go | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 internal/codersdkvalidator/group_name.go diff --git a/internal/codersdkvalidator/group_name.go b/internal/codersdkvalidator/group_name.go new file mode 100644 index 0000000..20313db --- /dev/null +++ b/internal/codersdkvalidator/group_name.go @@ -0,0 +1,10 @@ +package codersdkvalidator + +import ( + "github.com/coder/coder/v2/codersdk" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" +) + +func GroupName() validator.String { + return validatorFromFunc(codersdk.GroupNameValid, "value must be a valid group name") +} diff --git a/internal/codersdkvalidator/validator_from_func.go b/internal/codersdkvalidator/validator_from_func.go index e7e9993..9d5e631 100644 --- a/internal/codersdkvalidator/validator_from_func.go +++ b/internal/codersdkvalidator/validator_from_func.go @@ -43,7 +43,7 @@ func (v functionValidator) Description(_ context.Context) string { if v.err != nil { return v.err.Error() } - return "value must be a valid name" + return v.defaultMessage } func (v functionValidator) MarkdownDescription(ctx context.Context) string { diff --git a/internal/provider/group_resource.go b/internal/provider/group_resource.go index cbafac6..fa370a0 100644 --- a/internal/provider/group_resource.go +++ b/internal/provider/group_resource.go @@ -77,7 +77,7 @@ func (r *GroupResource) Schema(ctx context.Context, req resource.SchemaRequest, MarkdownDescription: "The unique name of the group.", Required: true, Validators: []validator.String{ - codersdkvalidator.Name(), + codersdkvalidator.GroupName(), }, }, "display_name": schema.StringAttribute{ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy