Initial commit
This commit is contained in:
commit
e4c8a6fbf4
186 changed files with 29501 additions and 0 deletions
85
stackit/validate/validate.go
Normal file
85
stackit/validate/validate.go
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package validate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/core"
|
||||
)
|
||||
|
||||
type Validator struct {
|
||||
description string
|
||||
markdownDescription string
|
||||
validate ValidationFn
|
||||
}
|
||||
|
||||
type ValidationFn func(context.Context, validator.StringRequest, *validator.StringResponse)
|
||||
|
||||
var _ = validator.String(&Validator{})
|
||||
|
||||
func (v *Validator) Description(_ context.Context) string {
|
||||
return v.description
|
||||
}
|
||||
|
||||
func (v *Validator) MarkdownDescription(_ context.Context) string {
|
||||
return v.markdownDescription
|
||||
}
|
||||
|
||||
func (v *Validator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { // nolint:gocritic // function signature required by Terraform
|
||||
if req.ConfigValue.IsUnknown() || req.ConfigValue.IsNull() {
|
||||
return
|
||||
}
|
||||
v.validate(ctx, req, resp)
|
||||
}
|
||||
|
||||
func UUID() *Validator {
|
||||
return &Validator{
|
||||
description: "validate string is UUID",
|
||||
validate: func(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
if _, err := uuid.Parse(req.ConfigValue.ValueString()); err != nil {
|
||||
resp.Diagnostics.AddError("not a valid UUID", err.Error())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func IP() *Validator {
|
||||
return &Validator{
|
||||
description: "validate string is IP address",
|
||||
validate: func(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
if net.ParseIP(req.ConfigValue.ValueString()) == nil {
|
||||
resp.Diagnostics.AddError("not a valid IP address", "")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NoSeparator() *Validator {
|
||||
return &Validator{
|
||||
description: "validate string does not contain internal separator",
|
||||
validate: func(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
if strings.Contains(req.ConfigValue.ValueString(), core.Separator) {
|
||||
resp.Diagnostics.AddError("Invalid character found.", fmt.Sprintf("The string should not contain a '%s'", core.Separator))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func SemanticMinorVersion() *Validator {
|
||||
return &Validator{
|
||||
description: "validate string does not contain internal separator",
|
||||
validate: func(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
exp := `^\d+\.\d+?$`
|
||||
r := regexp.MustCompile(exp)
|
||||
version := req.ConfigValue.ValueString()
|
||||
if !r.MatchString(version) {
|
||||
resp.Diagnostics.AddError("Invalid version.", "The version should be a valid semantic version only containing major and minor version. The version should not contain a leading `v`. Got "+version)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
210
stackit/validate/validate_test.go
Normal file
210
stackit/validate/validate_test.go
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
package validate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
func TestUUID(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
input string
|
||||
isValid bool
|
||||
}{
|
||||
{
|
||||
"ok",
|
||||
"cae27bba-c43d-498a-861e-d11d241c4ff8",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"too short",
|
||||
"a-b-c-d",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Empty",
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not UUID",
|
||||
"www-541-%",
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
r := validator.StringResponse{}
|
||||
UUID().ValidateString(context.Background(), validator.StringRequest{
|
||||
ConfigValue: types.StringValue(tt.input),
|
||||
}, &r)
|
||||
|
||||
if !tt.isValid && !r.Diagnostics.HasError() {
|
||||
t.Fatalf("Should have failed")
|
||||
}
|
||||
if tt.isValid && r.Diagnostics.HasError() {
|
||||
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIP(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
input string
|
||||
isValid bool
|
||||
}{
|
||||
{
|
||||
"ok IP4",
|
||||
"111.222.111.222",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ok IP6",
|
||||
"2001:0db8:85a3:08d3::0370:7344",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"too short",
|
||||
"0.1.2",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Empty",
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Not an IP",
|
||||
"for-sure-not-an-IP",
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
r := validator.StringResponse{}
|
||||
IP().ValidateString(context.Background(), validator.StringRequest{
|
||||
ConfigValue: types.StringValue(tt.input),
|
||||
}, &r)
|
||||
|
||||
if !tt.isValid && !r.Diagnostics.HasError() {
|
||||
t.Fatalf("Should have failed")
|
||||
}
|
||||
if tt.isValid && r.Diagnostics.HasError() {
|
||||
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoSeparator(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
input string
|
||||
isValid bool
|
||||
}{
|
||||
{
|
||||
"ok",
|
||||
"ABCD",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ok-2",
|
||||
"#$%&/()=.;-",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"Empty",
|
||||
"",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"not ok",
|
||||
"ab,",
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
r := validator.StringResponse{}
|
||||
NoSeparator().ValidateString(context.Background(), validator.StringRequest{
|
||||
ConfigValue: types.StringValue(tt.input),
|
||||
}, &r)
|
||||
|
||||
if !tt.isValid && !r.Diagnostics.HasError() {
|
||||
t.Fatalf("Should have failed")
|
||||
}
|
||||
if tt.isValid && r.Diagnostics.HasError() {
|
||||
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSemanticMinorVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
input string
|
||||
isValid bool
|
||||
}{
|
||||
{
|
||||
"ok",
|
||||
"1.20",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ok-2",
|
||||
"1.3",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ok-3",
|
||||
"10.1",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"Empty",
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not ok",
|
||||
"afssfdfs",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not ok-major-version",
|
||||
"1",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not ok-patch-version",
|
||||
"1.20.1",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not ok-version",
|
||||
"v1.20.1",
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
r := validator.StringResponse{}
|
||||
SemanticMinorVersion().ValidateString(context.Background(), validator.StringRequest{
|
||||
ConfigValue: types.StringValue(tt.input),
|
||||
}, &r)
|
||||
|
||||
if !tt.isValid && !r.Diagnostics.HasError() {
|
||||
t.Fatalf("Should have failed")
|
||||
}
|
||||
if tt.isValid && r.Diagnostics.HasError() {
|
||||
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue