Add snapshotClass parameter validation

Validate the snapshotClass parameter in Action.validate(): it must only
appear on snapshot actions, must be a string, and must not be empty.
Follows the same validation pattern as the dataMover parameter.

Ref: #8807

Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
This commit is contained in:
Shubham Pampattiwar
2026-07-24 14:55:43 -07:00
parent 5fa1cc3bf5
commit 436c82b977
2 changed files with 94 additions and 0 deletions
@@ -118,5 +118,19 @@ func (a *Action) validate() error {
}
}
if raw, ok := a.Parameters[SnapshotClassParameter]; ok {
if a.Type != Snapshot {
return fmt.Errorf("parameter %q is only supported for the %q action, but the action type is %q",
SnapshotClassParameter, Snapshot, a.Type)
}
snapshotClass, ok := raw.(string)
if !ok {
return fmt.Errorf("parameter %q must be a string, got %T", SnapshotClassParameter, raw)
}
if snapshotClass == "" {
return fmt.Errorf("parameter %q must not be empty", SnapshotClassParameter)
}
}
return nil
}
@@ -658,6 +658,86 @@ func TestValidate(t *testing.T) {
},
wantErr: false,
},
{
name: "snapshot action with valid snapshotClass",
res: &ResourcePolicies{
Version: "v1",
VolumePolicies: []VolumePolicy{
{
Action: Action{
Type: Snapshot,
Parameters: map[string]any{"snapshotClass": "my-vsc"},
},
Conditions: map[string]any{"storageClass": []string{"gp2"}},
},
},
},
wantErr: false,
},
{
name: "snapshot action with both snapshotClass and dataMover",
res: &ResourcePolicies{
Version: "v1",
VolumePolicies: []VolumePolicy{
{
Action: Action{
Type: Snapshot,
Parameters: map[string]any{"snapshotClass": "my-vsc", "dataMover": "velero-fs"},
},
Conditions: map[string]any{"storageClass": []string{"gp2"}},
},
},
},
wantErr: false,
},
{
name: "snapshotClass parameter on non-snapshot action is rejected",
res: &ResourcePolicies{
Version: "v1",
VolumePolicies: []VolumePolicy{
{
Action: Action{
Type: FSBackup,
Parameters: map[string]any{"snapshotClass": "my-vsc"},
},
Conditions: map[string]any{"storageClass": []string{"gp2"}},
},
},
},
wantErr: true,
},
{
name: "snapshot action with non-string snapshotClass is rejected",
res: &ResourcePolicies{
Version: "v1",
VolumePolicies: []VolumePolicy{
{
Action: Action{
Type: Snapshot,
Parameters: map[string]any{"snapshotClass": 123},
},
Conditions: map[string]any{"storageClass": []string{"gp2"}},
},
},
},
wantErr: true,
},
{
name: "snapshot action with empty snapshotClass is rejected",
res: &ResourcePolicies{
Version: "v1",
VolumePolicies: []VolumePolicy{
{
Action: Action{
Type: Snapshot,
Parameters: map[string]any{"snapshotClass": ""},
},
Conditions: map[string]any{"storageClass": []string{"gp2"}},
},
},
},
wantErr: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {