Files
tf_provider/internal/provider/validators.go
T

156 lines
4.6 KiB
Go

package provider
import (
"context"
"encoding/json"
"fmt"
"strings"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)
// stringOneOfValidator validates that a string value is one of the allowed values.
type stringOneOfValidator struct {
values []string
}
func (v stringOneOfValidator) Description(ctx context.Context) string {
return fmt.Sprintf("value must be one of: %v", v.values)
}
func (v stringOneOfValidator) MarkdownDescription(ctx context.Context) string {
return fmt.Sprintf("value must be one of: %v", v.values)
}
func (v stringOneOfValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
return
}
value := req.ConfigValue.ValueString()
for _, allowed := range v.values {
if value == allowed {
return
}
}
resp.Diagnostics.AddAttributeError(
req.Path,
"Invalid value",
fmt.Sprintf("Value must be one of %v, got: %s", v.values, value),
)
}
func StringOneOf(values ...string) validator.String {
return stringOneOfValidator{
values: values,
}
}
// validJSONArrayValidator проверяет, что строка является валидным JSON массивом
type validJSONArrayValidator struct{}
func (v validJSONArrayValidator) Description(ctx context.Context) string {
return "value must be a valid JSON array (e.g., [\"item1\", \"item2\"])"
}
func (v validJSONArrayValidator) MarkdownDescription(ctx context.Context) string {
return "value must be a valid JSON array (e.g., `[\"item1\", \"item2\"]`)"
}
func (v validJSONArrayValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
return
}
value := req.ConfigValue.ValueString()
if value == "" {
// Пустая строка не валидна - должен быть либо null, либо JSON массив
resp.Diagnostics.AddAttributeError(
req.Path,
"Invalid JSON Array",
"Empty string is not a valid JSON array. Use jsonencode([...]) or omit the attribute.",
)
return
}
var arr []interface{}
if err := json.Unmarshal([]byte(value), &arr); err != nil {
resp.Diagnostics.AddAttributeError(
req.Path,
"Invalid JSON Array",
fmt.Sprintf("Value must be a valid JSON array: %s", err),
)
}
}
func ValidJSONArray() validator.String {
return validJSONArrayValidator{}
}
// validJSONArrayOrEmptyValidator проверяет JSON массив или разрешает пустую строку
// Используется для accessIpList где "" означает "доступ отовсюду"
type validJSONArrayOrEmptyValidator struct{}
func (v validJSONArrayOrEmptyValidator) Description(ctx context.Context) string {
return "value must be a valid JSON array or empty string (empty = access from anywhere)"
}
func (v validJSONArrayOrEmptyValidator) MarkdownDescription(ctx context.Context) string {
return "value must be a valid JSON array or empty string (empty = access from anywhere)"
}
func (v validJSONArrayOrEmptyValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
return
}
value := req.ConfigValue.ValueString()
if value == "" {
// Пустая строка разрешена - означает доступ отовсюду
return
}
var arr []interface{}
if err := json.Unmarshal([]byte(value), &arr); err != nil {
resp.Diagnostics.AddAttributeError(
req.Path,
"Invalid JSON Array",
fmt.Sprintf("Value must be a valid JSON array or empty string: %s", err),
)
}
}
func ValidJSONArrayOrEmpty() validator.String {
return validJSONArrayOrEmptyValidator{}
}
type uuidLikeValidator struct{}
func (v uuidLikeValidator) Description(ctx context.Context) string {
return "value must be a UUID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)"
}
func (v uuidLikeValidator) MarkdownDescription(ctx context.Context) string {
return "value must be a UUID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)"
}
func (v uuidLikeValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
return
}
value := strings.TrimSpace(req.ConfigValue.ValueString())
if value == "" || !uuidLikeRegex.MatchString(value) {
resp.Diagnostics.AddAttributeError(
req.Path,
"Invalid UUID",
fmt.Sprintf("Value must be a UUID, got: %q", req.ConfigValue.ValueString()),
)
}
}
func UUIDLike() validator.String {
return uuidLikeValidator{}
}