mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-01-16 05:16:08 +02:00
Fixed validation for possibleValues option (#3228)
* Fixed validation for possibleValues option * Change oneof-custom to possible-values * go generate Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com>
This commit is contained in:
parent
f431054b6f
commit
e97242b7e7
@ -19,7 +19,7 @@ type abapAddonAssemblyKitPublishTargetVectorOptions struct {
|
||||
AbapAddonAssemblyKitEndpoint string `json:"abapAddonAssemblyKitEndpoint,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
TargetVectorScope string `json:"targetVectorScope,omitempty" validate:"oneof=T P"`
|
||||
TargetVectorScope string `json:"targetVectorScope,omitempty" validate:"possible-values=T P"`
|
||||
MaxRuntimeInMinutes int `json:"maxRuntimeInMinutes,omitempty"`
|
||||
PollingIntervalInSeconds int `json:"pollingIntervalInSeconds,omitempty"`
|
||||
AddonDescriptor string `json:"addonDescriptor,omitempty"`
|
||||
|
@ -18,11 +18,11 @@ import (
|
||||
)
|
||||
|
||||
type artifactPrepareVersionOptions struct {
|
||||
BuildTool string `json:"buildTool,omitempty" validate:"oneof=custom docker dub golang gradle maven mta npm pip sbt yarn"`
|
||||
BuildTool string `json:"buildTool,omitempty" validate:"possible-values=custom docker dub golang gradle maven mta npm pip sbt yarn"`
|
||||
CommitUserName string `json:"commitUserName,omitempty"`
|
||||
CustomVersionField string `json:"customVersionField,omitempty"`
|
||||
CustomVersionSection string `json:"customVersionSection,omitempty"`
|
||||
CustomVersioningScheme string `json:"customVersioningScheme,omitempty" validate:"oneof=docker maven pep440 semver2"`
|
||||
CustomVersioningScheme string `json:"customVersioningScheme,omitempty" validate:"possible-values=docker maven pep440 semver2"`
|
||||
DockerVersionSource string `json:"dockerVersionSource,omitempty"`
|
||||
FetchCoordinates bool `json:"fetchCoordinates,omitempty"`
|
||||
FilePath string `json:"filePath,omitempty"`
|
||||
@ -36,7 +36,7 @@ type artifactPrepareVersionOptions struct {
|
||||
UnixTimestamp bool `json:"unixTimestamp,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
VersioningTemplate string `json:"versioningTemplate,omitempty"`
|
||||
VersioningType string `json:"versioningType,omitempty" validate:"oneof=cloud cloud_noTag library"`
|
||||
VersioningType string `json:"versioningType,omitempty" validate:"possible-values=cloud cloud_noTag library"`
|
||||
}
|
||||
|
||||
type artifactPrepareVersionCommonPipelineEnvironment struct {
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
type batsExecuteTestsOptions struct {
|
||||
OutputFormat string `json:"outputFormat,omitempty" validate:"oneof=tap junit"`
|
||||
OutputFormat string `json:"outputFormat,omitempty" validate:"possible-values=tap junit"`
|
||||
Repository string `json:"repository,omitempty"`
|
||||
TestPackage string `json:"testPackage,omitempty"`
|
||||
TestPath string `json:"testPath,omitempty"`
|
||||
|
@ -39,7 +39,7 @@ type checkmarxExecuteScanOptions struct {
|
||||
VulnerabilityThresholdHigh int `json:"vulnerabilityThresholdHigh,omitempty"`
|
||||
VulnerabilityThresholdLow int `json:"vulnerabilityThresholdLow,omitempty"`
|
||||
VulnerabilityThresholdMedium int `json:"vulnerabilityThresholdMedium,omitempty"`
|
||||
VulnerabilityThresholdResult string `json:"vulnerabilityThresholdResult,omitempty" validate:"oneof=FAILURE"`
|
||||
VulnerabilityThresholdResult string `json:"vulnerabilityThresholdResult,omitempty" validate:"possible-values=FAILURE"`
|
||||
VulnerabilityThresholdUnit string `json:"vulnerabilityThresholdUnit,omitempty"`
|
||||
IsOptimizedAndScheduled bool `json:"isOptimizedAndScheduled,omitempty"`
|
||||
}
|
||||
|
@ -21,15 +21,15 @@ type detectExecuteScanOptions struct {
|
||||
Token string `json:"token,omitempty"`
|
||||
CodeLocation string `json:"codeLocation,omitempty"`
|
||||
ProjectName string `json:"projectName,omitempty"`
|
||||
Scanners []string `json:"scanners,omitempty"`
|
||||
Scanners []string `json:"scanners,omitempty" validate:"possible-values=signature source"`
|
||||
ScanPaths []string `json:"scanPaths,omitempty"`
|
||||
DependencyPath string `json:"dependencyPath,omitempty"`
|
||||
Unmap bool `json:"unmap,omitempty"`
|
||||
ScanProperties []string `json:"scanProperties,omitempty"`
|
||||
ServerURL string `json:"serverUrl,omitempty"`
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
FailOn []string `json:"failOn,omitempty"`
|
||||
VersioningModel string `json:"versioningModel,omitempty" validate:"oneof=major major-minor semantic full"`
|
||||
FailOn []string `json:"failOn,omitempty" validate:"possible-values=ALL BLOCKER CRITICAL MAJOR MINOR NONE"`
|
||||
VersioningModel string `json:"versioningModel,omitempty" validate:"possible-values=major major-minor semantic full"`
|
||||
Version string `json:"version,omitempty"`
|
||||
CustomScanVersion string `json:"customScanVersion,omitempty"`
|
||||
ProjectSettingsFile string `json:"projectSettingsFile,omitempty"`
|
||||
|
@ -60,7 +60,7 @@ type fortifyExecuteScanOptions struct {
|
||||
DeltaMinutes int `json:"deltaMinutes,omitempty"`
|
||||
SpotCheckMinimum int `json:"spotCheckMinimum,omitempty"`
|
||||
FprDownloadEndpoint string `json:"fprDownloadEndpoint,omitempty"`
|
||||
VersioningModel string `json:"versioningModel,omitempty" validate:"oneof=major major-minor semantic full"`
|
||||
VersioningModel string `json:"versioningModel,omitempty" validate:"possible-values=major major-minor semantic full"`
|
||||
PythonInstallCommand string `json:"pythonInstallCommand,omitempty"`
|
||||
ReportTemplateID int `json:"reportTemplateId,omitempty"`
|
||||
FilterSetTitle string `json:"filterSetTitle,omitempty"`
|
||||
|
@ -22,9 +22,9 @@ type gctsCreateRepositoryOptions struct {
|
||||
Host string `json:"host,omitempty"`
|
||||
Client string `json:"client,omitempty"`
|
||||
RemoteRepositoryURL string `json:"remoteRepositoryURL,omitempty"`
|
||||
Role string `json:"role,omitempty" validate:"oneof=SOURCE TARGET"`
|
||||
Role string `json:"role,omitempty" validate:"possible-values=SOURCE TARGET"`
|
||||
VSID string `json:"vSID,omitempty"`
|
||||
Type string `json:"type,omitempty" validate:"oneof=GIT"`
|
||||
Type string `json:"type,omitempty" validate:"possible-values=GIT"`
|
||||
}
|
||||
|
||||
// GctsCreateRepositoryCommand Creates a Git repository on an ABAP system
|
||||
|
@ -23,9 +23,9 @@ type gctsDeployOptions struct {
|
||||
Client string `json:"client,omitempty"`
|
||||
Commit string `json:"commit,omitempty"`
|
||||
RemoteRepositoryURL string `json:"remoteRepositoryURL,omitempty"`
|
||||
Role string `json:"role,omitempty" validate:"oneof=SOURCE TARGET"`
|
||||
Role string `json:"role,omitempty" validate:"possible-values=SOURCE TARGET"`
|
||||
VSID string `json:"vSID,omitempty"`
|
||||
Type string `json:"type,omitempty" validate:"oneof=GIT"`
|
||||
Type string `json:"type,omitempty" validate:"possible-values=GIT"`
|
||||
Branch string `json:"branch,omitempty"`
|
||||
Scope string `json:"scope,omitempty"`
|
||||
Rollback bool `json:"rollback,omitempty"`
|
||||
|
@ -22,7 +22,7 @@ type githubSetCommitStatusOptions struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
Repository string `json:"repository,omitempty"`
|
||||
Status string `json:"status,omitempty" validate:"oneof=failure pending success"`
|
||||
Status string `json:"status,omitempty" validate:"possible-values=failure pending success"`
|
||||
TargetURL string `json:"targetUrl,omitempty"`
|
||||
Token string `json:"token,omitempty"`
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ type gitopsUpdateDeploymentOptions struct {
|
||||
ChartPath string `json:"chartPath,omitempty"`
|
||||
HelmValues []string `json:"helmValues,omitempty"`
|
||||
DeploymentName string `json:"deploymentName,omitempty"`
|
||||
Tool string `json:"tool,omitempty" validate:"oneof=kubectl helm"`
|
||||
Tool string `json:"tool,omitempty" validate:"possible-values=kubectl helm"`
|
||||
}
|
||||
|
||||
// GitopsUpdateDeploymentCommand Updates Kubernetes Deployment Manifest in an Infrastructure Git Repository
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
type integrationArtifactResourceOptions struct {
|
||||
APIServiceKey string `json:"apiServiceKey,omitempty"`
|
||||
IntegrationFlowID string `json:"integrationFlowId,omitempty"`
|
||||
Operation string `json:"operation,omitempty" validate:"oneof=create update delete"`
|
||||
Operation string `json:"operation,omitempty" validate:"possible-values=create update delete"`
|
||||
ResourcePath string `json:"resourcePath,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ type kubernetesDeployOptions struct {
|
||||
ContainerRegistrySecret string `json:"containerRegistrySecret,omitempty"`
|
||||
CreateDockerRegistrySecret bool `json:"createDockerRegistrySecret,omitempty"`
|
||||
DeploymentName string `json:"deploymentName,omitempty"`
|
||||
DeployTool string `json:"deployTool,omitempty" validate:"oneof=kubectl helm helm3"`
|
||||
DeployTool string `json:"deployTool,omitempty" validate:"possible-values=kubectl helm helm3"`
|
||||
ForceUpdates bool `json:"forceUpdates,omitempty"`
|
||||
HelmDeployWaitSeconds int `json:"helmDeployWaitSeconds,omitempty"`
|
||||
HelmValues []string `json:"helmValues,omitempty"`
|
||||
@ -41,7 +41,7 @@ type kubernetesDeployOptions struct {
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
TillerNamespace string `json:"tillerNamespace,omitempty"`
|
||||
DockerConfigJSON string `json:"dockerConfigJSON,omitempty"`
|
||||
DeployCommand string `json:"deployCommand,omitempty" validate:"oneof=apply replace"`
|
||||
DeployCommand string `json:"deployCommand,omitempty" validate:"possible-values=apply replace"`
|
||||
}
|
||||
|
||||
// KubernetesDeployCommand Deployment to Kubernetes test or production namespace within the specified Kubernetes cluster.
|
||||
|
@ -23,7 +23,7 @@ type mtaBuildOptions struct {
|
||||
Version string `json:"version,omitempty"`
|
||||
Extensions string `json:"extensions,omitempty"`
|
||||
Jobs int `json:"jobs,omitempty"`
|
||||
Platform string `json:"platform,omitempty" validate:"oneof=CF NEO XSA"`
|
||||
Platform string `json:"platform,omitempty" validate:"possible-values=CF NEO XSA"`
|
||||
ApplicationName string `json:"applicationName,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
Target string `json:"target,omitempty"`
|
||||
|
@ -16,8 +16,8 @@ import (
|
||||
)
|
||||
|
||||
type nexusUploadOptions struct {
|
||||
Version string `json:"version,omitempty" validate:"oneof=nexus2 nexus3"`
|
||||
Format string `json:"format,omitempty" validate:"oneof=maven npm"`
|
||||
Version string `json:"version,omitempty" validate:"possible-values=nexus2 nexus3"`
|
||||
Format string `json:"format,omitempty" validate:"possible-values=maven npm"`
|
||||
Url string `json:"url,omitempty"`
|
||||
MavenRepository string `json:"mavenRepository,omitempty"`
|
||||
NpmRepository string `json:"npmRepository,omitempty"`
|
||||
|
@ -23,7 +23,7 @@ type protecodeExecuteScanOptions struct {
|
||||
ScanImage string `json:"scanImage,omitempty"`
|
||||
DockerRegistryURL string `json:"dockerRegistryUrl,omitempty"`
|
||||
DockerConfigJSON string `json:"dockerConfigJSON,omitempty"`
|
||||
CleanupMode string `json:"cleanupMode,omitempty" validate:"oneof=none binary complete"`
|
||||
CleanupMode string `json:"cleanupMode,omitempty" validate:"possible-values=none binary complete"`
|
||||
FilePath string `json:"filePath,omitempty"`
|
||||
IncludeLayers bool `json:"includeLayers,omitempty"`
|
||||
TimeoutMinutes string `json:"timeoutMinutes,omitempty"`
|
||||
|
@ -24,7 +24,7 @@ type sonarExecuteScanOptions struct {
|
||||
Organization string `json:"organization,omitempty"`
|
||||
CustomTLSCertificateLinks []string `json:"customTlsCertificateLinks,omitempty"`
|
||||
SonarScannerDownloadURL string `json:"sonarScannerDownloadUrl,omitempty"`
|
||||
VersioningModel string `json:"versioningModel,omitempty" validate:"oneof=major major-minor semantic full"`
|
||||
VersioningModel string `json:"versioningModel,omitempty" validate:"possible-values=major major-minor semantic full"`
|
||||
Version string `json:"version,omitempty"`
|
||||
CustomScanVersion string `json:"customScanVersion,omitempty"`
|
||||
ProjectKey string `json:"projectKey,omitempty"`
|
||||
@ -37,7 +37,7 @@ type sonarExecuteScanOptions struct {
|
||||
ChangeID string `json:"changeId,omitempty"`
|
||||
ChangeBranch string `json:"changeBranch,omitempty"`
|
||||
ChangeTarget string `json:"changeTarget,omitempty"`
|
||||
PullRequestProvider string `json:"pullRequestProvider,omitempty" validate:"oneof=GitHub"`
|
||||
PullRequestProvider string `json:"pullRequestProvider,omitempty" validate:"possible-values=GitHub"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
Repository string `json:"repository,omitempty"`
|
||||
GithubToken string `json:"githubToken,omitempty"`
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
type vaultRotateSecretIdOptions struct {
|
||||
SecretStore string `json:"secretStore,omitempty" validate:"oneof=jenkins ado"`
|
||||
SecretStore string `json:"secretStore,omitempty" validate:"possible-values=jenkins ado"`
|
||||
JenkinsURL string `json:"jenkinsUrl,omitempty"`
|
||||
JenkinsCredentialDomain string `json:"jenkinsCredentialDomain,omitempty"`
|
||||
JenkinsUsername string `json:"jenkinsUsername,omitempty"`
|
||||
|
@ -55,7 +55,7 @@ type whitesourceExecuteScanOptions struct {
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
UserToken string `json:"userToken,omitempty"`
|
||||
VersioningModel string `json:"versioningModel,omitempty"`
|
||||
VulnerabilityReportFormat string `json:"vulnerabilityReportFormat,omitempty" validate:"oneof=xlsx json xml"`
|
||||
VulnerabilityReportFormat string `json:"vulnerabilityReportFormat,omitempty" validate:"possible-values=xlsx json xml"`
|
||||
VulnerabilityReportTitle string `json:"vulnerabilityReportTitle,omitempty"`
|
||||
ProjectSettingsFile string `json:"projectSettingsFile,omitempty"`
|
||||
GlobalSettingsFile string `json:"globalSettingsFile,omitempty"`
|
||||
|
@ -21,8 +21,8 @@ type xsDeployOptions struct {
|
||||
DeployOpts string `json:"deployOpts,omitempty"`
|
||||
OperationIDLogPattern string `json:"operationIdLogPattern,omitempty"`
|
||||
MtaPath string `json:"mtaPath,omitempty"`
|
||||
Action string `json:"action,omitempty" validate:"oneof=NONE Resume Abort Retry"`
|
||||
Mode string `json:"mode,omitempty" validate:"oneof=NONE DEPLOY BG_DEPLOY"`
|
||||
Action string `json:"action,omitempty" validate:"possible-values=NONE Resume Abort Retry"`
|
||||
Mode string `json:"mode,omitempty" validate:"possible-values=NONE DEPLOY BG_DEPLOY"`
|
||||
OperationID string `json:"operationId,omitempty"`
|
||||
APIURL string `json:"apiUrl,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
|
@ -70,7 +70,7 @@ type {{ .StepName }}Options struct {
|
||||
{{ if ne (has $value.Name $names) true -}}
|
||||
{{ $names | last }}{{ $value.Name | golangName }} {{ $value.Type }} ` + "`json:\"{{$value.Name}},omitempty\"" +
|
||||
"{{ if or $value.PossibleValues $value.MandatoryIf}} validate:\"" +
|
||||
"{{ if $value.PossibleValues }}oneof={{ range $i,$a := $value.PossibleValues }}{{if gt $i 0 }} {{ end }}{{.}}{{ end }}{{ end }}" +
|
||||
"{{ if $value.PossibleValues }}possible-values={{ range $i,$a := $value.PossibleValues }}{{if gt $i 0 }} {{ end }}{{.}}{{ end }}{{ end }}" +
|
||||
"{{ if and $value.PossibleValues $value.MandatoryIf }},{{ end }}" +
|
||||
"{{ if $value.MandatoryIf }}required_if={{ range $i,$a := $value.MandatoryIf }}{{ if gt $i 0 }} {{ end }}{{ $a.Name | title }} {{ $a.Value }}{{ end }}{{ end }}" +
|
||||
"\"{{ end }}`" + `
|
||||
|
@ -20,9 +20,9 @@ import (
|
||||
|
||||
type testStepOptions struct {
|
||||
Param0 string `json:"param0,omitempty"`
|
||||
Param1 string `json:"param1,omitempty" validate:"oneof=value1 value2 value3"`
|
||||
Param1 string `json:"param1,omitempty" validate:"possible-values=value1 value2 value3"`
|
||||
Param2 string `json:"param2,omitempty" validate:"required_if=Param1 value1"`
|
||||
Param3 string `json:"param3,omitempty" validate:"oneof=value1 value2 value3,required_if=Param1 value1 Param2 value2"`
|
||||
Param3 string `json:"param3,omitempty" validate:"possible-values=value1 value2 value3,required_if=Param1 value1 Param2 value2"`
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,9 +19,9 @@ import (
|
||||
|
||||
type testStepOptions struct {
|
||||
Param0 string `json:"param0,omitempty"`
|
||||
Param1 string `json:"param1,omitempty" validate:"oneof=value1 value2 value3"`
|
||||
Param1 string `json:"param1,omitempty" validate:"possible-values=value1 value2 value3"`
|
||||
Param2 string `json:"param2,omitempty" validate:"required_if=Param1 value1"`
|
||||
Param3 string `json:"param3,omitempty" validate:"oneof=value1 value2 value3,required_if=Param1 value1 Param2 value2"`
|
||||
Param3 string `json:"param3,omitempty" validate:"possible-values=value1 value2 value3,required_if=Param1 value1 Param2 value2"`
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,7 +2,9 @@ package validation
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-playground/locales/en"
|
||||
@ -26,6 +28,7 @@ type validationOption func(*validation) error
|
||||
|
||||
func New(opts ...validationOption) (*validation, error) {
|
||||
validator := valid.New()
|
||||
validator.RegisterValidation("possible-values", isPossibleValues)
|
||||
enTranslator := en.New()
|
||||
universalTranslator := ut.New(enTranslator, enTranslator)
|
||||
translator, found := universalTranslator.GetTranslator("en")
|
||||
@ -60,19 +63,19 @@ func WithJSONNamesForStructFields() validationOption {
|
||||
func WithPredefinedErrorMessages() validationOption {
|
||||
translations := []Translation{
|
||||
{
|
||||
Tag: "oneof",
|
||||
Tag: "possible-values",
|
||||
RegisterFn: func(ut ut.Translator) error {
|
||||
return ut.Add("oneof", "The {0} must use the following values: {1}. ", true)
|
||||
return ut.Add("possible-values", "The {0} must use the following values: {1}", true)
|
||||
},
|
||||
TranslationFn: func(ut ut.Translator, fe valid.FieldError) string {
|
||||
t, _ := ut.T("oneof", fe.Field(), fe.Param())
|
||||
t, _ := ut.T("possible-values", fe.Field(), fe.Param())
|
||||
return t
|
||||
},
|
||||
}, {
|
||||
Tag: "required_if",
|
||||
RegisterFn: func(ut ut.Translator) error {
|
||||
// TODO: Improve the message for condition required_if for several fields
|
||||
return ut.Add("required_if", "The {0} is required since the {1} is {2}. ", true)
|
||||
return ut.Add("required_if", "The {0} is required since the {1} is {2}", true)
|
||||
},
|
||||
TranslationFn: func(ut ut.Translator, fe valid.FieldError) string {
|
||||
params := []string{fe.Field()}
|
||||
@ -107,7 +110,7 @@ func (v *validation) ValidateStruct(s interface{}) error {
|
||||
return err
|
||||
}
|
||||
for _, err := range errs.(valid.ValidationErrors) {
|
||||
errStr += err.Translate(v.Translator)
|
||||
errStr += err.Translate(v.Translator) + ". "
|
||||
}
|
||||
return errors.New(errStr)
|
||||
}
|
||||
@ -126,3 +129,41 @@ func registerTranslations(translations []Translation, validator *valid.Validate,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isPossibleValues(fl valid.FieldLevel) bool {
|
||||
vals := strings.Split(strings.TrimSpace(fl.Param()), " ")
|
||||
|
||||
field := fl.Field()
|
||||
switch field.Kind() {
|
||||
case reflect.String:
|
||||
val := field.String()
|
||||
// Empty value can be used
|
||||
vals = append(vals, "")
|
||||
return contains(vals, val)
|
||||
case reflect.Int:
|
||||
val := strconv.FormatInt(field.Int(), 10)
|
||||
return contains(vals, val)
|
||||
case reflect.Slice:
|
||||
slice, ok := field.Interface().([]string)
|
||||
if !ok {
|
||||
panic("Only []string can be used as slice type")
|
||||
}
|
||||
for _, val := range slice {
|
||||
if !contains(vals, val) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
|
||||
}
|
||||
}
|
||||
|
||||
func contains(slice []string, str string) bool {
|
||||
for _, v := range slice {
|
||||
if v == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -9,10 +9,11 @@ import (
|
||||
)
|
||||
|
||||
type testStruct struct {
|
||||
Field1 int `json:"field1,omitempty" validate:"eq=1"`
|
||||
Field2 string `json:"field2,omitempty" validate:"oneof=value1 value2 value3"`
|
||||
Field3 string `json:"field3,omitempty" validate:"required_if=Field1 1 Field4 test"`
|
||||
Field4 string `json:"field4,omitempty"`
|
||||
Field1 int `json:"field1,omitempty" validate:"eq=1"`
|
||||
Field2 string `json:"field2,omitempty" validate:"possible-values=value1 value2 value3"`
|
||||
Field3 string `json:"field3,omitempty" validate:"required_if=Field1 1 Field4 test"`
|
||||
Field4 string `json:"field4,omitempty"`
|
||||
Field5 []string `json:"field5,omitempty" validate:"possible-values=val1 val2 val3 val4"`
|
||||
}
|
||||
|
||||
func TestValidateStruct(t *testing.T) {
|
||||
@ -24,6 +25,19 @@ func TestValidateStruct(t *testing.T) {
|
||||
Field2: "value1",
|
||||
Field3: "field3",
|
||||
Field4: "test",
|
||||
Field5: []string{"val1", "val2", "val3"},
|
||||
}
|
||||
err = validation.ValidateStruct(tStruct)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("success case - empty values for string and []string", func(t *testing.T) {
|
||||
validation, err := New(WithPredefinedErrorMessages(), WithJSONNamesForStructFields())
|
||||
assert.NoError(t, err)
|
||||
tStruct := testStruct{
|
||||
Field1: 1,
|
||||
Field3: "field3",
|
||||
Field4: "test",
|
||||
}
|
||||
err = validation.ValidateStruct(tStruct)
|
||||
assert.NoError(t, err)
|
||||
@ -36,11 +50,13 @@ func TestValidateStruct(t *testing.T) {
|
||||
Field1: 1,
|
||||
Field2: "value4",
|
||||
Field4: "test",
|
||||
Field5: []string{"val1", "val2", "val5"},
|
||||
}
|
||||
err = validation.ValidateStruct(testStruct)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "Key: 'testStruct.Field2' Error:Field validation for 'Field2' failed on the 'oneof'")
|
||||
assert.Contains(t, err.Error(), "tagKey: 'testStruct.Field3' Error:Field validation for 'Field3' failed on the 'required_if' tag")
|
||||
assert.Contains(t, err.Error(), "Key: 'testStruct.Field2' Error:Field validation for 'Field2' failed on the 'possible-values' tag.")
|
||||
assert.Contains(t, err.Error(), "Key: 'testStruct.Field3' Error:Field validation for 'Field3' failed on the 'required_if' tag.")
|
||||
assert.Contains(t, err.Error(), "Key: 'testStruct.Field5' Error:Field validation for 'Field5' failed on the 'possible-values' tag.")
|
||||
})
|
||||
|
||||
t.Run("error case - predefined error messages without naming fields from json tags", func(t *testing.T) {
|
||||
@ -50,11 +66,13 @@ func TestValidateStruct(t *testing.T) {
|
||||
Field1: 1,
|
||||
Field2: "value4",
|
||||
Field4: "test",
|
||||
Field5: []string{"val1", "val2", "val5"},
|
||||
}
|
||||
err = validation.ValidateStruct(testStruct)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "The Field2 must use the following values: value1 value2 value3.")
|
||||
assert.Contains(t, err.Error(), "The Field3 is required since the Field1 is 1.")
|
||||
assert.Contains(t, err.Error(), "The Field5 must use the following values: val1 val2 val3 val4.")
|
||||
})
|
||||
|
||||
t.Run("failed case - predefined error messages with naming fields from json tags", func(t *testing.T) {
|
||||
@ -64,28 +82,30 @@ func TestValidateStruct(t *testing.T) {
|
||||
Field1: 1,
|
||||
Field2: "value4",
|
||||
Field4: "test",
|
||||
Field5: []string{"val1", "val2", "val5"},
|
||||
}
|
||||
err = validation.ValidateStruct(testStruct)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "The field2 must use the following values: value1 value2 value3.")
|
||||
assert.Contains(t, err.Error(), "The field3 is required since the Field1 is 1.")
|
||||
assert.Contains(t, err.Error(), "The field5 must use the following values: val1 val2 val3 val4.")
|
||||
})
|
||||
|
||||
t.Run("failed case - custom error messages", func(t *testing.T) {
|
||||
translations := []Translation{
|
||||
{
|
||||
Tag: "oneof",
|
||||
Tag: "possible-values",
|
||||
RegisterFn: func(ut ut.Translator) error {
|
||||
return ut.Add("oneof", "Custom error message for {0}. ", true)
|
||||
return ut.Add("possible-values", "Custom error message for {0}", true)
|
||||
},
|
||||
TranslationFn: func(ut ut.Translator, fe valid.FieldError) string {
|
||||
t, _ := ut.T("oneof", fe.Field())
|
||||
t, _ := ut.T("possible-values", fe.Field())
|
||||
return t
|
||||
},
|
||||
}, {
|
||||
Tag: "required_if",
|
||||
RegisterFn: func(ut ut.Translator) error {
|
||||
return ut.Add("required_if", "Custom error message for {0}. ", true)
|
||||
return ut.Add("required_if", "Custom error message for {0}", true)
|
||||
},
|
||||
TranslationFn: func(ut ut.Translator, fe valid.FieldError) string {
|
||||
t, _ := ut.T("required_if", fe.Field())
|
||||
@ -99,10 +119,12 @@ func TestValidateStruct(t *testing.T) {
|
||||
Field1: 1,
|
||||
Field2: "value4",
|
||||
Field4: "test",
|
||||
Field5: []string{"val1", "val2", "val5"},
|
||||
}
|
||||
err = validation.ValidateStruct(testStruct)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "Custom error message for Field2")
|
||||
assert.Contains(t, err.Error(), "Custom error message for Field3")
|
||||
assert.Contains(t, err.Error(), "Custom error message for Field5")
|
||||
})
|
||||
}
|
||||
|
@ -65,9 +65,9 @@ spec:
|
||||
type: "[]string"
|
||||
default:
|
||||
- signature
|
||||
# possibleValues:
|
||||
# - signature
|
||||
# - source
|
||||
possibleValues:
|
||||
- signature
|
||||
- source
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
@ -146,13 +146,13 @@ spec:
|
||||
type: "[]string"
|
||||
default:
|
||||
- BLOCKER
|
||||
# possibleValues:
|
||||
# - ALL
|
||||
# - BLOCKER
|
||||
# - CRITICAL
|
||||
# - MAJOR
|
||||
# - MINOR
|
||||
# - NONE
|
||||
possibleValues:
|
||||
- ALL
|
||||
- BLOCKER
|
||||
- CRITICAL
|
||||
- MAJOR
|
||||
- MINOR
|
||||
- NONE
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
|
Loading…
Reference in New Issue
Block a user