Skip to content

Commit

Permalink
refactor: new validation rule interface (#399)
Browse files Browse the repository at this point in the history
## Description
New interface to help with working with rule names in a consistent way
across the ecosystem.

Plugins would be required to implement it for easy integration with
programs like `validatorctl`. They can do that by embedding
`validationrule.ManuallyNamed` or `validationrule.AutomaticallyNamed`
into their rule struct and implementing the required methods. If they
embed `validationrule.AutomaticallyNamed`, they don't need to implement
`SetName`. Example:

```go
type MyRule struct {
	validationrule.ManuallyNamed `json:",inline"`

	...
}
```

They should also assert that their rule implements the interface.
Example:

```go
var _ validationrule.Interface = (*MyRule)(nil)
```

For rules that are manually named, it is expected that only pointers to
rules can implement the interface because of the pointer receiver of
implementations of `SetName`. Example:

```go
func (r *MyRule) SetName(name string) { ... }
```

---------

Signed-off-by: Matt Welke <matt.welke@spectrocloud.com>
  • Loading branch information
mattwelke committed Aug 22, 2024
1 parent 528e21f commit 6b16845
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 7 deletions.
2 changes: 1 addition & 1 deletion hauler-manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,4 @@ metadata:
spec:
files:
- name: validatorctl
path: https://github.com/validator-labs/validatorctl/releases/download/v0.1.1/validator-linux-ARCH
path: https://github.com/validator-labs/validatorctl/releases/download/v0.1.2/validator-linux-ARCH
12 changes: 6 additions & 6 deletions pkg/validationresult/validation_result.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ type Patcher interface {
Patch(ctx context.Context, obj client.Object, opts ...patch.Option) error
}

// ValidationRule is an interface for validation rules.
type ValidationRule interface {
// Validator is an interface for building ValidationResults.
type Validator interface {
client.Object
GetKind() string
PluginCode() string
ResultCount() int
}

// Build creates a new ValidationResult for a specific ValidationRule.
func Build(r ValidationRule) *v1alpha1.ValidationResult {
// Build creates a new ValidationResult for a specific Validator.
func Build(r Validator) *v1alpha1.ValidationResult {
return &v1alpha1.ValidationResult{
TypeMeta: metav1.TypeMeta{
APIVersion: v1alpha1.APIVersion,
Expand All @@ -61,8 +61,8 @@ func Build(r ValidationRule) *v1alpha1.ValidationResult {
}
}

// Name returns the name of a ValidationResult for a specific ValidationRule.
func Name(r ValidationRule) string {
// Name returns the name of a ValidationResult for a specific Validator.
func Name(r Validator) string {
name := fmt.Sprintf("validator-plugin-%s-%s", r.PluginCode(), r.GetName())
return util.Sanitize(name)
}
Expand Down
38 changes: 38 additions & 0 deletions pkg/validationrule/validation_rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Package validationrule describes validation rules.
package validationrule

// Interface defines validation rule behavior.
type Interface interface {
// Name returns the name of the rule.
Name() string
// SetName sets the name of the rule if it is a rule that requires manually specifying its name.
// This should be a no-op for rules that automatically generate their name.
SetName(string)
// RequiresName returns whether the validation rule requires its name to be manually specified.
// This should return false for rules that automatically generate their name.
RequiresName() bool
}

// ManuallyNamed can be embedded into a rule struct to indicate that the rule requires its name to
// be manually specified.
type ManuallyNamed struct{}

// RequiresName returns true.
func (ManuallyNamed) RequiresName() bool {
return true
}

// AutomaticallyNamed can be embedded into a rule struct to indicate that the rule does not require
// its name to be manually specified because it is automatically generated from other data in the
// rule.
type AutomaticallyNamed struct{}

// RequiresName returns false.
func (AutomaticallyNamed) RequiresName() bool {
return false
}

// SetName is a no-op because the rule does not support manually specifying its name.
func (AutomaticallyNamed) SetName(string) {
// no-op
}

0 comments on commit 6b16845

Please sign in to comment.