Skip to content

Commit d11408c

Browse files
authored
Add check if DestinationRule CRD is present before creating it (#316)
* Add check for DestinationRule CRD * Add API extensions to operator's scheme * Add permission for CRD resource
1 parent 97a5a5d commit d11408c

File tree

6 files changed

+52
-4
lines changed

6 files changed

+52
-4
lines changed

config/rbac/role.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ rules:
6060
- list
6161
- update
6262
- watch
63+
- apiGroups:
64+
- apiextensions.k8s.io
65+
resources:
66+
- customresourcedefinitions
67+
verbs:
68+
- get
69+
- list
70+
- watch
6371
- apiGroups:
6472
- apps
6573
resources:

controllers/destination_rule.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
trustyaiopendatahubiov1alpha1 "github.com/trustyai-explainability/trustyai-service-operator/api/v1alpha1"
99
templateParser "github.com/trustyai-explainability/trustyai-service-operator/controllers/templates"
10+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
1011
"k8s.io/apimachinery/pkg/api/errors"
1112
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1213
"k8s.io/apimachinery/pkg/types"
@@ -16,6 +17,7 @@ import (
1617

1718
const (
1819
destinationRuleTemplatePath = "service/destination-rule.tmpl.yaml"
20+
destinationRuleCDRName = "destinationrules.networking.istio.io"
1921
)
2022

2123
// DestinationRuleConfig has the variables for the DestinationRule template
@@ -25,7 +27,25 @@ type DestinationRuleConfig struct {
2527
DestinationRuleName string
2628
}
2729

30+
// isDestinationRuleCRDPresent returns true if the DestinationRule CRD is present, false otherwise
31+
func (r *TrustyAIServiceReconciler) isDestinationRuleCRDPresent(ctx context.Context) (bool, error) {
32+
crd := &apiextensionsv1.CustomResourceDefinition{}
33+
34+
err := r.Get(ctx, types.NamespacedName{Name: destinationRuleCDRName}, crd)
35+
if err != nil {
36+
if !errors.IsNotFound(err) {
37+
return false, fmt.Errorf("error getting "+destinationRuleCDRName+" CRD: %v", err)
38+
}
39+
// Not found
40+
return false, nil
41+
}
42+
43+
// Found
44+
return true, nil
45+
}
46+
2847
func (r *TrustyAIServiceReconciler) ensureDestinationRule(ctx context.Context, instance *trustyaiopendatahubiov1alpha1.TrustyAIService) error {
48+
2949
destinationRuleName := instance.Name + "-internal"
3050

3151
existingDestinationRule := &unstructured.Unstructured{}

controllers/inference_services.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,26 @@ func (r *TrustyAIServiceReconciler) patchKServe(ctx context.Context, instance *t
275275
// Only if the Istio sidecar annotation is set
276276
annotations := infService.GetAnnotations()
277277
if inject, exists := annotations["sidecar.istio.io/inject"]; exists && inject == "true" {
278-
err := r.ensureDestinationRule(ctx, instance)
278+
279+
// Check if DestinationRule CRD is present. If there's an error, don't proceed and return the error
280+
exists, err := r.isDestinationRuleCRDPresent(ctx)
279281
if err != nil {
280-
return fmt.Errorf("failed to ensure DestinationRule: %v", err)
282+
log.FromContext(ctx).Error(err, "Error verifying DestinationRule CRD is present")
283+
return err
284+
}
285+
286+
// Try to create the DestinationRule, since CRD exists
287+
if exists {
288+
err := r.ensureDestinationRule(ctx, instance)
289+
if err != nil {
290+
return fmt.Errorf("failed to ensure DestinationRule: %v", err)
291+
}
292+
} else {
293+
// DestinationRule CRD does not exist. Do not attempt to create it and log error
294+
err := fmt.Errorf("the DestinationRule CRD is not present in this cluster")
295+
log.FromContext(ctx).Error(err, "InferenceService has service mesh annotation but DestinationRule CRD not found")
281296
}
297+
282298
}
283299

284300
// Update the InferenceService

controllers/trustyaiservice_controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ type TrustyAIServiceReconciler struct {
7070
//+kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=clusterrolebindings,verbs=get;list;watch;create;update;delete
7171
//+kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=get;create;update
7272
//+kubebuilder:rbac:groups=networking.istio.io,resources=destinationrules,verbs=create;list;watch;get;update;patch;delete
73+
//+kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=list;watch;get
7374

7475
// Reconcile is part of the main kubernetes reconciliation loop which aims to
7576
// move the current state of the cluster closer to the desired state.

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ require (
8888
gopkg.in/inf.v0 v0.9.1 // indirect
8989
gopkg.in/yaml.v2 v2.4.0 // indirect
9090
gopkg.in/yaml.v3 v3.0.1 // indirect
91-
k8s.io/apiextensions-apiserver v0.26.4 // indirect
91+
k8s.io/apiextensions-apiserver v0.26.4
9292
k8s.io/component-base v0.26.4 // indirect
9393
k8s.io/klog/v2 v2.100.1 // indirect
9494
k8s.io/kube-openapi v0.0.0-20230515203736-54b630e78af5 // indirect

main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ package main
1818

1919
import (
2020
"flag"
21+
"os"
22+
2123
kservev1alpha1 "github.com/kserve/kserve/pkg/apis/serving/v1alpha1"
2224
kservev1beta1 "github.com/kserve/kserve/pkg/apis/serving/v1beta1"
2325
routev1 "github.com/openshift/api/route/v1"
2426
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
25-
"os"
27+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2628

2729
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
2830
// to ensure that exec-entrypoint and run can make use of them.
@@ -52,6 +54,7 @@ func init() {
5254
utilruntime.Must(kservev1alpha1.AddToScheme(scheme))
5355
utilruntime.Must(kservev1beta1.AddToScheme(scheme))
5456
utilruntime.Must(routev1.AddToScheme(scheme))
57+
utilruntime.Must(apiextensionsv1.AddToScheme(scheme))
5558
//+kubebuilder:scaffold:scheme
5659
}
5760

0 commit comments

Comments
 (0)