diff --git a/apis/components/v1alpha1/kserve_types.go b/apis/components/v1alpha1/kserve_types.go index ff6c43ac8ad..b69d88aed83 100644 --- a/apis/components/v1alpha1/kserve_types.go +++ b/apis/components/v1alpha1/kserve_types.go @@ -74,6 +74,9 @@ type KserveSpec struct { // KserveCommonStatus defines the shared observed state of Kserve type KserveCommonStatus struct { + // DefaultDeploymentMode is the value of the defaultDeploymentMode field + // as read from the "deploy" JSON in the inferenceservice-config ConfigMap + DefaultDeploymentMode string `json:"defaultDeploymentMode,omitempty"` } // KserveStatus defines the observed state of Kserve diff --git a/config/crd/bases/components.platform.opendatahub.io_kserves.yaml b/config/crd/bases/components.platform.opendatahub.io_kserves.yaml index ae49777f844..c64e35fe0ee 100644 --- a/config/crd/bases/components.platform.opendatahub.io_kserves.yaml +++ b/config/crd/bases/components.platform.opendatahub.io_kserves.yaml @@ -216,6 +216,11 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map + defaultDeploymentMode: + description: |- + DefaultDeploymentMode is the value of the defaultDeploymentMode field + as read from the "deploy" JSON in the inferenceservice-config ConfigMap + type: string observedGeneration: format: int64 type: integer diff --git a/config/crd/bases/datasciencecluster.opendatahub.io_datascienceclusters.yaml b/config/crd/bases/datasciencecluster.opendatahub.io_datascienceclusters.yaml index 7c06b2c7ffc..6a1c89dea45 100644 --- a/config/crd/bases/datasciencecluster.opendatahub.io_datascienceclusters.yaml +++ b/config/crd/bases/datasciencecluster.opendatahub.io_datascienceclusters.yaml @@ -718,6 +718,11 @@ spec: kserve: description: Kserve component status. properties: + defaultDeploymentMode: + description: |- + DefaultDeploymentMode is the value of the defaultDeploymentMode field + as read from the "deploy" JSON in the inferenceservice-config ConfigMap + type: string managementState: description: |- Set to one of the following values: diff --git a/controllers/components/kserve/config.go b/controllers/components/kserve/config.go new file mode 100644 index 00000000000..8b85d813a50 --- /dev/null +++ b/controllers/components/kserve/config.go @@ -0,0 +1,26 @@ +package kserve + +import ( + "encoding/json" + "fmt" + + corev1 "k8s.io/api/core/v1" +) + +// ConfigMap Keys +const ( + DeployConfigName = "deploy" + IngressConfigKeyName = "ingress" +) + +type DeployConfig struct { + DefaultDeploymentMode string `json:"defaultDeploymentMode,omitempty"` +} + +func getDeployConfig(cm *corev1.ConfigMap) (*DeployConfig, error) { + deployConfig := DeployConfig{} + if err := json.Unmarshal([]byte(cm.Data[DeployConfigName]), &deployConfig); err != nil { + return nil, fmt.Errorf("error retrieving value for key '%s' from ConfigMap %s. %w", DeployConfigName, cm.Name, err) + } + return &deployConfig, nil +} diff --git a/controllers/components/kserve/kserve_controller.go b/controllers/components/kserve/kserve_controller.go index a0d8870ef67..c5a62beed3a 100644 --- a/controllers/components/kserve/kserve_controller.go +++ b/controllers/components/kserve/kserve_controller.go @@ -157,6 +157,7 @@ func (s *componentHandler) NewComponentReconciler(ctx context.Context, mgr ctrl. WithAction(deploy.NewAction( deploy.WithCache(), )). + WithAction(setStatusFields). WithAction(updatestatus.NewAction()). // must be the final action WithAction(gc.NewAction()). diff --git a/controllers/components/kserve/kserve_controller_actions.go b/controllers/components/kserve/kserve_controller_actions.go index 132fdf4f931..0920de2b6ba 100644 --- a/controllers/components/kserve/kserve_controller_actions.go +++ b/controllers/components/kserve/kserve_controller_actions.go @@ -11,6 +11,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" componentApi "github.com/opendatahub-io/opendatahub-operator/v2/apis/components/v1alpha1" @@ -262,3 +263,23 @@ func customizeKserveConfigMap(ctx context.Context, rr *odhtypes.ReconciliationRe return nil } + +func setStatusFields(ctx context.Context, rr *odhtypes.ReconciliationRequest) error { + k, ok := rr.Instance.(*componentApi.Kserve) + if !ok { + return fmt.Errorf("resource instance %v is not a componentApi.Kserve)", rr.Instance) + } + + kserveConfigMap := corev1.ConfigMap{} + if err := rr.Client.Get(ctx, client.ObjectKey{Name: kserveConfigMapName, Namespace: rr.DSCI.Spec.ApplicationsNamespace}, &kserveConfigMap); err != nil { + return err + } + + ddm, err := getDefaultDeploymentMode(&kserveConfigMap) + if err != nil { + return err + } + + k.Status.DefaultDeploymentMode = ddm + return nil +} diff --git a/controllers/components/kserve/kserve_support.go b/controllers/components/kserve/kserve_support.go index 422a27f3103..d548e39d21d 100644 --- a/controllers/components/kserve/kserve_support.go +++ b/controllers/components/kserve/kserve_support.go @@ -148,24 +148,32 @@ func removeServerlessFeatures(ctx context.Context, cli client.Client, k *compone return serverlessFeatures.Delete(ctx, cli) } +func getDefaultDeploymentMode(inferenceServiceConfigMap *corev1.ConfigMap) (string, error) { + deployConfig, err := getDeployConfig(inferenceServiceConfigMap) + if err != nil { + return "", err + } + + return deployConfig.DefaultDeploymentMode, nil +} + func setDefaultDeploymentMode(inferenceServiceConfigMap *corev1.ConfigMap, defaultmode componentApi.DefaultDeploymentMode) error { - // set data.deploy.defaultDeploymentMode to the model specified in the Kserve spec - var deployData map[string]interface{} - if err := json.Unmarshal([]byte(inferenceServiceConfigMap.Data["deploy"]), &deployData); err != nil { - return fmt.Errorf("error retrieving value for key 'deploy' from configmap %s. %w", kserveConfigMapName, err) + deployData, err := getDeployConfig(inferenceServiceConfigMap) + if err != nil { + return err } - modeFound := deployData["defaultDeploymentMode"] - if modeFound != string(defaultmode) { - deployData["defaultDeploymentMode"] = defaultmode + + if deployData.DefaultDeploymentMode != string(defaultmode) { + deployData.DefaultDeploymentMode = string(defaultmode) deployDataBytes, err := json.MarshalIndent(deployData, "", " ") if err != nil { return fmt.Errorf("could not set values in configmap %s. %w", kserveConfigMapName, err) } - inferenceServiceConfigMap.Data["deploy"] = string(deployDataBytes) + inferenceServiceConfigMap.Data[DeployConfigName] = string(deployDataBytes) var ingressData map[string]interface{} - if err = json.Unmarshal([]byte(inferenceServiceConfigMap.Data["ingress"]), &ingressData); err != nil { - return fmt.Errorf("error retrieving value for key 'ingress' from configmap %s. %w", kserveConfigMapName, err) + if err = json.Unmarshal([]byte(inferenceServiceConfigMap.Data[IngressConfigKeyName]), &ingressData); err != nil { + return fmt.Errorf("error retrieving value for key '%s' from configmap %s. %w", IngressConfigKeyName, kserveConfigMapName, err) } if defaultmode == componentApi.RawDeployment { ingressData["disableIngressCreation"] = true @@ -176,7 +184,7 @@ func setDefaultDeploymentMode(inferenceServiceConfigMap *corev1.ConfigMap, defau if err != nil { return fmt.Errorf("could not set values in configmap %s. %w", kserveConfigMapName, err) } - inferenceServiceConfigMap.Data["ingress"] = string(ingressDataBytes) + inferenceServiceConfigMap.Data[IngressConfigKeyName] = string(ingressDataBytes) } return nil diff --git a/docs/api-overview.md b/docs/api-overview.md index cc5445e6a7a..926028e7d10 100644 --- a/docs/api-overview.md +++ b/docs/api-overview.md @@ -805,6 +805,9 @@ _Appears in:_ - [DSCKserveStatus](#dsckservestatus) - [KserveStatus](#kservestatus) +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `defaultDeploymentMode` _string_ | DefaultDeploymentMode is the value of the defaultDeploymentMode field
as read from the "deploy" JSON in the inferenceservice-config ConfigMap | | | #### KserveList @@ -862,6 +865,7 @@ _Appears in:_ | `phase` _string_ | | | | | `observedGeneration` _integer_ | | | | | `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#condition-v1-meta) array_ | | | | +| `defaultDeploymentMode` _string_ | DefaultDeploymentMode is the value of the defaultDeploymentMode field
as read from the "deploy" JSON in the inferenceservice-config ConfigMap | | | #### Kueue diff --git a/tests/e2e/helper_test.go b/tests/e2e/helper_test.go index 8f3a2a8bc45..e46b7b1f0c3 100644 --- a/tests/e2e/helper_test.go +++ b/tests/e2e/helper_test.go @@ -161,6 +161,7 @@ func setupDSCInstance(name string) *dscv1.DataScienceCluster { ManagementState: operatorv1.Removed, }, KserveCommonSpec: componentApi.KserveCommonSpec{ + DefaultDeploymentMode: componentApi.Serverless, Serving: infrav1.ServingSpec{ ManagementState: operatorv1.Managed, Name: "knative-serving", diff --git a/tests/e2e/kserve_test.go b/tests/e2e/kserve_test.go index 2ee44672577..70398ab1ebd 100644 --- a/tests/e2e/kserve_test.go +++ b/tests/e2e/kserve_test.go @@ -74,6 +74,7 @@ func (k *KserveTestCtx) validateKserveInstance(t *testing.T) { k.testDsc.Spec.Components.Kserve.Serving.IngressGateway.Certificate.Type), jq.Match(`.status.phase == "%s"`, readyStatus), + jq.Match(`.status.defaultDeploymentMode == "%s"`, k.testDsc.Spec.Components.Kserve.DefaultDeploymentMode), )), )) @@ -86,6 +87,7 @@ func (k *KserveTestCtx) validateKserveInstance(t *testing.T) { jq.Match(`.status.conditions[] | select(.type == "%s") | .status == "%s"`, modelcontroller.ReadyConditionType, metav1.ConditionTrue), jq.Match(`.status.installedComponents."%s" == true`, kserve.LegacyComponentName), jq.Match(`.status.components.%s.managementState == "%s"`, componentApi.KserveComponentName, operatorv1.Managed), + jq.Match(`.status.components.%s.defaultDeploymentMode == "%s"`, componentApi.KserveComponentName, k.testDsc.Spec.Components.Kserve.DefaultDeploymentMode), )), ))