diff --git a/pkg/config/config.go b/pkg/config/config.go index de6caf1f..812cebd0 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -152,6 +152,8 @@ func DefineConfiguration( mainCMD.MarkFlagsMutuallyExclusive(listFieldConstrainsAsStrings(constrain)...) case field.RequiredTogether: mainCMD.MarkFlagsRequiredTogether(listFieldConstrainsAsStrings(constrain)...) + case field.AtLeastOne: + mainCMD.MarkFlagsOneRequired(listFieldConstrainsAsStrings(constrain)...) } } diff --git a/pkg/field/relationships.go b/pkg/field/relationships.go index 902a687c..3ba0db79 100644 --- a/pkg/field/relationships.go +++ b/pkg/field/relationships.go @@ -5,6 +5,7 @@ type Relationship int const ( RequiredTogether Relationship = iota + 1 MutuallyExclusive + AtLeastOne ) type SchemaFieldRelationship struct { @@ -25,3 +26,10 @@ func FieldsMutuallyExclusive(fields ...SchemaField) SchemaFieldRelationship { Fields: fields, } } + +func FieldsAtLeastOneUsed(fields ...SchemaField) SchemaFieldRelationship { + return SchemaFieldRelationship{ + Kind: AtLeastOne, + Fields: fields, + } +} diff --git a/pkg/field/validation.go b/pkg/field/validation.go index 6b6301b4..244969fb 100644 --- a/pkg/field/validation.go +++ b/pkg/field/validation.go @@ -47,6 +47,8 @@ func Validate(c Configuration, v *viper.Viper) error { isNonZero = v.GetInt(f.FieldName) != 0 case reflect.String: isNonZero = v.GetString(f.FieldName) != "" + case reflect.Slice: + isNonZero = len(v.GetStringSlice(f.FieldName)) == 0 default: return fmt.Errorf("field %s has unsupported type %s", f.FieldName, f.FieldType) } @@ -80,6 +82,9 @@ func validateConstraints(fieldsPresent map[string]int, relationships []SchemaFie if present > 0 && present < len(relationship.Fields) && relationship.Kind == RequiredTogether { return makeNeededTogetherError(fieldsPresent, relationship) } + if present == 0 && relationship.Kind == AtLeastOne { + return makeAtLeastOneError(fieldsPresent, relationship) + } } return nil @@ -106,3 +111,14 @@ func makeNeededTogetherError(fields map[string]int, relation SchemaFieldRelation return fmt.Errorf("fields marked as needed together are missing: %s", strings.Join(found, ", ")) } + +func makeAtLeastOneError(fields map[string]int, relation SchemaFieldRelationship) error { + var found []string + for _, f := range relation.Fields { + if fields[f.FieldName] == 0 { + found = append(found, f.FieldName) + } + } + + return fmt.Errorf("at least one field was expected, any of: %s", strings.Join(found, ", ")) +}