Skip to content

Commit 784e40b

Browse files
Per G. da Silvaclaude
andcommitted
Add CheckObjectSupport validator with unit tests
Add a validator that checks non-CRD and non-CSV bundle objects are of kinds supported by the registry+v1 standard, using operator-registry's Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Per G. da Silva <pegoncal@redhat.com>
1 parent 4121321 commit 784e40b

File tree

4 files changed

+97
-0
lines changed

4 files changed

+97
-0
lines changed

internal/operator-controller/rukpak/render/registryv1/registryv1.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ var BundleValidator = render.BundleValidator{
2929
validators.CheckConversionWebhookCRDReferenceUniqueness,
3030
validators.CheckConversionWebhooksReferenceOwnedCRDs,
3131
validators.CheckWebhookRules,
32+
validators.CheckObjectSupport,
3233
}
3334

3435
// ResourceGenerators a slice of ResourceGenerators required to generate plain resource manifests for

internal/operator-controller/rukpak/render/registryv1/registryv1_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func Test_BundleValidatorHasAllValidationFns(t *testing.T) {
3434
validators.CheckConversionWebhookCRDReferenceUniqueness,
3535
validators.CheckConversionWebhooksReferenceOwnedCRDs,
3636
validators.CheckWebhookRules,
37+
validators.CheckObjectSupport,
3738
}
3839
actualValidationFns := registryv1.BundleValidator
3940

internal/operator-controller/rukpak/render/registryv1/validators/validator.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"k8s.io/apimachinery/pkg/util/validation"
1313

1414
"github.com/operator-framework/api/pkg/operators/v1alpha1"
15+
regv1bundle "github.com/operator-framework/operator-registry/pkg/lib/bundle"
1516

1617
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle"
1718
)
@@ -348,3 +349,16 @@ func CheckWebhookRules(rv1 *bundle.RegistryV1) []error {
348349
}
349350
return errs
350351
}
352+
353+
// CheckObjectSupport checks that the non-CRD and non-CSV bundle objects are supported by the
354+
// registry+v1 standard
355+
func CheckObjectSupport(rv1 *bundle.RegistryV1) []error {
356+
var errs []error
357+
for _, obj := range rv1.Others {
358+
kind := obj.GetObjectKind().GroupVersionKind().Kind
359+
if ok, _ := regv1bundle.IsSupported(kind); !ok {
360+
errs = append(errs, fmt.Errorf("unsupported resource %q with kind %q", obj.GetName(), kind))
361+
}
362+
}
363+
return errs
364+
}

internal/operator-controller/rukpak/render/registryv1/validators/validator_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
99
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
1010
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
12+
"k8s.io/apimachinery/pkg/runtime/schema"
1113

1214
"github.com/operator-framework/api/pkg/operators/v1alpha1"
1315

@@ -1171,3 +1173,82 @@ func Test_CheckWebhookNameIsDNS1123SubDomain(t *testing.T) {
11711173
})
11721174
}
11731175
}
1176+
1177+
func newUnstructuredObject(gvk schema.GroupVersionKind, name string) unstructured.Unstructured {
1178+
obj := unstructured.Unstructured{}
1179+
obj.SetGroupVersionKind(gvk)
1180+
obj.SetName(name)
1181+
return obj
1182+
}
1183+
1184+
func Test_CheckObjectSupport(t *testing.T) {
1185+
for _, tc := range []struct {
1186+
name string
1187+
bundle *bundle.RegistryV1
1188+
expectedErrs []error
1189+
}{
1190+
{
1191+
name: "accepts bundles with no other objects",
1192+
bundle: &bundle.RegistryV1{},
1193+
expectedErrs: nil,
1194+
},
1195+
{
1196+
name: "accepts bundles with supported object kinds",
1197+
bundle: &bundle.RegistryV1{
1198+
Others: []unstructured.Unstructured{
1199+
newUnstructuredObject(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Secret"}, "my-secret"),
1200+
newUnstructuredObject(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ConfigMap"}, "my-configmap"),
1201+
newUnstructuredObject(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ServiceAccount"}, "my-sa"),
1202+
newUnstructuredObject(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Service"}, "my-service"),
1203+
newUnstructuredObject(schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}, "my-clusterrole"),
1204+
newUnstructuredObject(schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}, "my-clusterrolebinding"),
1205+
newUnstructuredObject(schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "Role"}, "my-role"),
1206+
newUnstructuredObject(schema.GroupVersionKind{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "RoleBinding"}, "my-rolebinding"),
1207+
},
1208+
},
1209+
expectedErrs: nil,
1210+
},
1211+
{
1212+
name: "rejects bundles with unsupported object kinds",
1213+
bundle: &bundle.RegistryV1{
1214+
Others: []unstructured.Unstructured{
1215+
newUnstructuredObject(schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"}, "my-deployment"),
1216+
},
1217+
},
1218+
expectedErrs: []error{
1219+
errors.New(`unsupported resource "my-deployment" with kind "Deployment"`),
1220+
},
1221+
},
1222+
{
1223+
name: "reports errors for each unsupported object",
1224+
bundle: &bundle.RegistryV1{
1225+
Others: []unstructured.Unstructured{
1226+
newUnstructuredObject(schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"}, "my-deployment"),
1227+
newUnstructuredObject(schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "StatefulSet"}, "my-statefulset"),
1228+
},
1229+
},
1230+
expectedErrs: []error{
1231+
errors.New(`unsupported resource "my-deployment" with kind "Deployment"`),
1232+
errors.New(`unsupported resource "my-statefulset" with kind "StatefulSet"`),
1233+
},
1234+
},
1235+
{
1236+
name: "accepts supported objects and rejects unsupported objects in the same bundle",
1237+
bundle: &bundle.RegistryV1{
1238+
Others: []unstructured.Unstructured{
1239+
newUnstructuredObject(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ConfigMap"}, "my-configmap"),
1240+
newUnstructuredObject(schema.GroupVersionKind{Group: "batch", Version: "v1", Kind: "Job"}, "my-job"),
1241+
newUnstructuredObject(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Secret"}, "my-secret"),
1242+
},
1243+
},
1244+
expectedErrs: []error{
1245+
errors.New(`unsupported resource "my-job" with kind "Job"`),
1246+
},
1247+
},
1248+
} {
1249+
t.Run(tc.name, func(t *testing.T) {
1250+
errs := validators.CheckObjectSupport(tc.bundle)
1251+
require.Equal(t, tc.expectedErrs, errs)
1252+
})
1253+
}
1254+
}

0 commit comments

Comments
 (0)