这是indexloc提供的服务,不要输入任何密码
Skip to content

Add project name validation #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions vercel/data_source_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package vercel
import (
"context"
"fmt"
"regexp"

"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
Expand Down Expand Up @@ -33,6 +34,10 @@ For more detailed information, please see the [Vercel documentation](https://ver
Type: types.StringType,
Validators: []tfsdk.AttributeValidator{
stringLengthBetween(1, 52),
stringRegex(
regexp.MustCompile(`^[a-z0-9\-]{0,100}$`),
"The name of a Project can only contain up to 100 alphanumeric lowercase characters and hyphens",
),
},
Description: "The name of the project.",
},
Expand Down
5 changes: 5 additions & 0 deletions vercel/resource_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"regexp"
"strings"

"github.com/hashicorp/terraform-plugin-framework/diag"
Expand Down Expand Up @@ -43,6 +44,10 @@ deployments, you may not want to create a Project within the same terraform work
Type: types.StringType,
Validators: []tfsdk.AttributeValidator{
stringLengthBetween(1, 52),
stringRegex(
regexp.MustCompile(`^[a-z0-9\-]{0,100}$`),
"The name of a Project can only contain up to 100 alphanumeric lowercase characters and hyphens",
),
},
Description: "The desired name for the project.",
},
Expand Down
70 changes: 57 additions & 13 deletions vercel/validator_framework.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,81 @@
package vercel

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"

"github.com/hashicorp/terraform-plugin-framework/tfsdk"
)

func validateFramework() validatorStringOneOf {
resp, err := http.Get("https://api-frameworks.zeit.sh/")
func validateFramework() validatorFramework {
return validatorFramework{}
}

type validatorFramework struct {
frameworks []string
}

func (v validatorFramework) Description(ctx context.Context) string {
if v.frameworks == nil {
return "The framework provided is not supported on Vercel"
}
return stringOneOf(v.frameworks...).Description(ctx)
}

func (v validatorFramework) MarkdownDescription(ctx context.Context) string {
if v.frameworks == nil {
return "The framework provided is not supported on Vercel"
}
return stringOneOf(v.frameworks...).MarkdownDescription(ctx)
}

func (v validatorFramework) Validate(ctx context.Context, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) {
apires, err := http.Get("https://api-frameworks.zeit.sh/")
if err != nil {
panic(fmt.Errorf("unable to retrieve Vercel frameworks: unexpected error: %w", err))
resp.Diagnostics.AddAttributeError(
req.AttributePath,
"Unable to validate attribute",
fmt.Sprintf("Unable to retrieve Vercel frameworks: unexpected error: %s", err),
)
return
}
if resp.StatusCode != 200 {
panic(fmt.Errorf("unable to retrieve Vercel frameworks: unexpected status code %d", resp.StatusCode))
if apires.StatusCode != 200 {
resp.Diagnostics.AddAttributeError(
req.AttributePath,
"Unable to validate attribute",
fmt.Sprintf("Unable to retrieve Vercel frameworks: unexpected status code: %d", apires.StatusCode),
)
return
}

defer resp.Body.Close()
responseBody, err := ioutil.ReadAll(resp.Body)
defer apires.Body.Close()
responseBody, err := ioutil.ReadAll(apires.Body)
if err != nil {
panic(fmt.Errorf("error reading api-frameworks.zeit.sh response body: %w", err))
resp.Diagnostics.AddAttributeError(
req.AttributePath,
"Unable to validate attribute",
fmt.Sprintf("Unable to retrieve Vercel frameworks: error reading response body: %s", err),
)
return
}
var fwList []struct {
Slug string `json:"slug"`
}
err = json.Unmarshal(responseBody, &fwList)
if resp.StatusCode != 200 {
panic(fmt.Errorf("unable to parse Vercel frameworks response: %w", err))
if err != nil {
resp.Diagnostics.AddAttributeError(
req.AttributePath,
"Unable to validate attribute",
fmt.Sprintf("Unable to retrieve Vercel frameworks: error parsing frameworks response: %s", err),
)
return
}
var frameworks []string
for _, fw := range fwList {
frameworks = append(frameworks, fw.Slug)
v.frameworks = append(v.frameworks, fw.Slug)
}

return stringOneOf(frameworks...)
stringOneOf(v.frameworks...).Validate(ctx, req, resp)
}
8 changes: 4 additions & 4 deletions vercel/validator_int64_items_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ func (v validatorInt64ItemsIn) keys() (out []string) {
}

func (v validatorInt64ItemsIn) Description(ctx context.Context) string {
return fmt.Sprintf("set item must be one of %s", strings.Join(v.keys(), " "))
return fmt.Sprintf("Item must be one of %s", strings.Join(v.keys(), " "))
}
func (v validatorInt64ItemsIn) MarkdownDescription(ctx context.Context) string {
return fmt.Sprintf("set item must be one of `%s`", strings.Join(v.keys(), "` `"))
return fmt.Sprintf("Item must be one of `%s`", strings.Join(v.keys(), "` `"))
}

func (v validatorInt64ItemsIn) Validate(ctx context.Context, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) {
Expand All @@ -52,8 +52,8 @@ func (v validatorInt64ItemsIn) Validate(ctx context.Context, req tfsdk.ValidateA
if _, ok := v.Items[item.Value]; !ok {
resp.Diagnostics.AddAttributeError(
req.AttributePath,
"Invalid Item",
fmt.Sprintf(" item must be one of %s, got: %d.", strings.Join(v.keys(), " "), item.Value),
"Invalid value provided",
fmt.Sprintf("Item must be one of %s, got: %d.", strings.Join(v.keys(), " "), item.Value),
)
return
}
Expand Down
6 changes: 3 additions & 3 deletions vercel/validator_map_items_min_count.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ type validatorMapItemsMinCount struct {
}

func (v validatorMapItemsMinCount) Description(ctx context.Context) string {
return fmt.Sprintf("map must contain at least %d item(s)", v.Min)
return fmt.Sprintf("Map must contain at least %d item(s)", v.Min)
}
func (v validatorMapItemsMinCount) MarkdownDescription(ctx context.Context) string {
return fmt.Sprintf("map must contain at least `%d` item(s)", v.Min)
return fmt.Sprintf("Map must contain at least `%d` item(s)", v.Min)
}

func (v validatorMapItemsMinCount) Validate(ctx context.Context, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) {
Expand All @@ -40,7 +40,7 @@ func (v validatorMapItemsMinCount) Validate(ctx context.Context, req tfsdk.Valid
if count < v.Min {
resp.Diagnostics.AddAttributeError(
req.AttributePath,
"Invalid Map Count",
"Invalid value provided",
fmt.Sprintf(
"Map must contain at least %d items, got: %d.",
v.Min,
Expand Down
10 changes: 7 additions & 3 deletions vercel/validator_string_length_between.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ type validatorStringLengthBetween struct {
}

func (v validatorStringLengthBetween) Description(ctx context.Context) string {
return fmt.Sprintf("string length must be between %d and %d", v.Min, v.Max)
return fmt.Sprintf("String length must be between %d and %d", v.Min, v.Max)
}
func (v validatorStringLengthBetween) MarkdownDescription(ctx context.Context) string {
return fmt.Sprintf("string length must be between `%d` and `%d`", v.Min, v.Max)
return fmt.Sprintf("String length must be between `%d` and `%d`", v.Min, v.Max)
}

func (v validatorStringLengthBetween) Validate(ctx context.Context, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) {
Expand All @@ -39,7 +39,11 @@ func (v validatorStringLengthBetween) Validate(ctx context.Context, req tfsdk.Va
}
strLen := len(str.Value)
if strLen < v.Min || strLen > v.Max {
resp.Diagnostics.AddAttributeError(req.AttributePath, "Invalid String Length", fmt.Sprintf("String length must be between %d and %d, got: %d.", v.Min, v.Max, strLen))
resp.Diagnostics.AddAttributeError(
req.AttributePath,
"Invalid value provided",
fmt.Sprintf("String length must be between %d and %d, got: %d.", v.Min, v.Max, strLen),
)
return
}
}
6 changes: 3 additions & 3 deletions vercel/validator_string_one_of.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ func (v validatorStringOneOf) keys() (out []string) {
}

func (v validatorStringOneOf) Description(ctx context.Context) string {
return fmt.Sprintf("item must be one of %s", strings.Join(v.keys(), " "))
return fmt.Sprintf("Item must be one of %s", strings.Join(v.keys(), " "))
}
func (v validatorStringOneOf) MarkdownDescription(ctx context.Context) string {
return fmt.Sprintf("item must be one of `%s`", strings.Join(v.keys(), "` `"))
return fmt.Sprintf("Item must be one of `%s`", strings.Join(v.keys(), "` `"))
}

func (v validatorStringOneOf) Validate(ctx context.Context, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) {
Expand All @@ -51,7 +51,7 @@ func (v validatorStringOneOf) Validate(ctx context.Context, req tfsdk.ValidateAt
if _, ok := v.Items[item.Value]; !ok {
resp.Diagnostics.AddAttributeError(
req.AttributePath,
"Invalid Item",
"Invalid value provided",
fmt.Sprintf("Item must be one of %s, got: %s.", strings.Join(v.keys(), " "), item.Value),
)
return
Expand Down
49 changes: 49 additions & 0 deletions vercel/validator_string_regex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package vercel

import (
"context"
"regexp"

"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
)

func stringRegex(re *regexp.Regexp, errorMessage string) validatorStringRegex {
return validatorStringRegex{
Re: re,
ErrorMessage: errorMessage,
}
}

type validatorStringRegex struct {
Re *regexp.Regexp
ErrorMessage string
}

func (v validatorStringRegex) Description(ctx context.Context) string {
return v.ErrorMessage
}
func (v validatorStringRegex) MarkdownDescription(ctx context.Context) string {
return v.ErrorMessage
}

func (v validatorStringRegex) Validate(ctx context.Context, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) {
var str types.String
diags := tfsdk.ValueAs(ctx, req.AttributeConfig, &str)
resp.Diagnostics.Append(diags...)
if diags.HasError() {
return
}
if str.Unknown || str.Null {
return
}
ok := v.Re.MatchString(str.Value)
if !ok {
resp.Diagnostics.AddAttributeError(
req.AttributePath,
"Invalid value provided",
v.ErrorMessage,
)
return
}
}
2 changes: 1 addition & 1 deletion vercel/validator_string_set_items_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (v validatorStringSetItemsIn) Validate(ctx context.Context, req tfsdk.Valid
if _, ok := v.Items[item.Value]; !ok {
resp.Diagnostics.AddAttributeError(
req.AttributePath,
"Invalid Set Item",
"Invalid value provided",
fmt.Sprintf("Set item must be one of %s, got: %s.", strings.Join(v.keys(), " "), item.Value),
)
return
Expand Down