diff --git a/README.md b/README.md
index 3f2842a6..76710f00 100644
--- a/README.md
+++ b/README.md
@@ -163,6 +163,8 @@ Feel free to submit an issue in such a case, Intersmash welcomes community contr
| Red Hat JBoss EAP 7 | JBoss EAP 7.4.z (and XP 4.z) | |
| | | |
| Hyperfoil | 0.24.2 | Supports provisioning via the Operator, both on **Kubernetes** and **OpenShift** |
+| | | |
+| Open Data Hub | 2.22.0 | Supports provisioning on OpenShift via the Operator |
Since multiple deliverables can be bound to a given service version, e.g.: container images, operator CRs, or Helm Charts,
more information can be found in [the provisioners' documentation](./provisioners/README.md), or in the resources there linked.
@@ -175,7 +177,7 @@ We welcome community contributions to other Kubernetes implementations.
## Future goals
-* OpenShift AI provisioning
+* Full support for OpenShift AI provisioning
* Documentation and examples enhancements
see the [current milestone](https://github.com/Intersmash/intersmash/milestone/2) for a complete list of issues.
diff --git a/core/src/main/java/org/jboss/intersmash/IntersmashConfig.java b/core/src/main/java/org/jboss/intersmash/IntersmashConfig.java
index 55a6a0a0..4623a4f4 100644
--- a/core/src/main/java/org/jboss/intersmash/IntersmashConfig.java
+++ b/core/src/main/java/org/jboss/intersmash/IntersmashConfig.java
@@ -85,6 +85,13 @@ public class IntersmashConfig {
private static final String HYPERFOIL_OPERATOR_PACKAGE_MANIFEST = "intersmash.hyperfoil.operators.package_manifest";
private static final String COMMUNITY_HYPERFOIL_OPERATOR_PACKAGE_MANIFEST = "hyperfoil-bundle";
private static final String DEFAULT_HYPERFOIL_OPERATOR_PACKAGE_MANIFEST = COMMUNITY_HYPERFOIL_OPERATOR_PACKAGE_MANIFEST;
+ private static final String OPEN_DATA_HUB_OPERATOR_CATALOG_SOURCE_NAME = "intersmash.odh.operators.catalog_source";
+ private static final String OPEN_DATA_HUB_OPERATOR_INDEX_IMAGE = "intersmash.odh.operators.index_image";
+ private static final String OPEN_DATA_HUB_OPERATOR_CHANNEL = "intersmash.odh.operators.channel";
+ private static final String OPEN_DATA_HUB_OPERATOR_PACKAGE_MANIFEST = "intersmash.odh.operators.package_manifest";
+ private static final String COMMUNITY_OPEN_DATA_HUB_OPERATOR_PACKAGE_MANIFEST = "opendatahub-operator";
+ private static final String DEFAULT_OPEN_DATA_HUB_OPERATOR_PACKAGE_MANIFEST = COMMUNITY_OPEN_DATA_HUB_OPERATOR_PACKAGE_MANIFEST;
+
// Bootable Jar
private static final String BOOTABLE_JAR_IMAGE_URL = "intersmash.bootable.jar.image";
@@ -407,4 +414,43 @@ public static String keycloakOperatorChannel() {
public static String keycloakOperatorPackageManifest() {
return XTFConfig.get(KEYCLOAK_OPERATOR_PACKAGE_MANIFEST, DEFAULT_KEYCLOAK_OPERATOR_PACKAGE_MANIFEST);
}
+
+ /**
+ * Read the configuration property for the Open Data Hub Operator catalog source, i.e. {@code intersmash.odh.operators.catalog_source}.
+ *
+ * @return The value for the {@code intersmash.odh.operators.catalog_source} property or the default catalog source,
+ * i.e. the value of {@code intersmash.olm.operators.catalog_source} property.
+ */
+ public static String openDataHubOperatorCatalogSource() {
+ return XTFConfig.get(OPEN_DATA_HUB_OPERATOR_CATALOG_SOURCE_NAME, defaultOperatorCatalogSourceName());
+ }
+
+ /**
+ * Read the configuration property for the Open Data Hub Operator index image, i.e. {@code intersmash.odh.operators.index_image}.
+ *
+ * @return The value for the {@code intersmash.odh.operators.index_image} property, representing a custom index image.
+ */
+ public static String openDataHubOperatorIndexImage() {
+ return XTFConfig.get(OPEN_DATA_HUB_OPERATOR_INDEX_IMAGE);
+ }
+
+ /**
+ * Read the configuration property for the Open Data Hub Operator channel to be used, i.e. {@code intersmash.odh.operators.channel}.
+ *
+ * @return The value for the {@code intersmash.odh.operators.channel} property. If not provided the default operator
+ * channel is used.
+ */
+ public static String openDataHubOperatorChannel() {
+ return XTFConfig.get(OPEN_DATA_HUB_OPERATOR_CHANNEL);
+ }
+
+ /**
+ * Read the configuration property for the Open Data Hub Operator channel to be used, i.e. {@code intersmash.odh.operators.package_manifest}.
+ *
+ * @return The value for the {@code intersmash.odh.operators.package_manifest} property or the default package manifest
+ * that should be used for this operator, i.e. {@code opendatahub-operator} property.
+ */
+ public static String openDataHubOperatorPackageManifest() {
+ return XTFConfig.get(OPEN_DATA_HUB_OPERATOR_PACKAGE_MANIFEST, DEFAULT_OPEN_DATA_HUB_OPERATOR_PACKAGE_MANIFEST);
+ }
}
diff --git a/core/src/main/java/org/jboss/intersmash/provision/operator/OperatorProvisioner.java b/core/src/main/java/org/jboss/intersmash/provision/operator/OperatorProvisioner.java
index 951d94f4..476ea923 100644
--- a/core/src/main/java/org/jboss/intersmash/provision/operator/OperatorProvisioner.java
+++ b/core/src/main/java/org/jboss/intersmash/provision/operator/OperatorProvisioner.java
@@ -64,8 +64,8 @@
public abstract class OperatorProvisioner
implements Provisioner, Scalable {
// cache the current csv and list of provided custom resource definitions
- static String currentCSV;
- final String packageManifestName;
+ protected static String currentCSV;
+ protected final String packageManifestName;
private CatalogSource catalogSource;
private final A operatorApplication;
private PackageManifest packageManifest;
@@ -180,6 +180,16 @@ private String getCatalogSourceNamespace() {
return namespace;
}
+ /**
+ * The CatalogSource is in the "openshift-marketplace" namespace by default on OpenShift, in the "olm" one on K8s.
+ * When a custom operator image must be used, then a custom CatalogSource will be created in the current namespace.
+ *
+ * @return namespace where the custom CatalogSource is located
+ */
+ protected String getTargetNamespace() {
+ return this.client().getNamespace();
+ }
+
/**
* Initialize a reference to a proper catalog source which will be used to pull the required operator image.
*
@@ -350,7 +360,7 @@ public void subscribe(String installPlanApproval, Map envVariabl
log.info("Subscribing the {} operator", packageManifestName);
// oc get packagemanifest wildfly -o template --template {{.status.defaultChannel}}
final String catalogSourceNamespace = getCatalogSourceNamespace();
- final String targetNamespace = this.client().getNamespace();
+ final String targetNamespace = getTargetNamespace();
Subscription operatorSubscription = (envVariables == null || envVariables.isEmpty())
? new Subscription(catalogSourceNamespace, targetNamespace, getOperatorCatalogSource(),
packageManifestName,
@@ -462,7 +472,7 @@ protected void waitForOperatorPod() {
if (operatorSpec.length != 3) {
throw new IllegalStateException("Failed to get operator deployment spec from csvs!");
}
- BooleanSupplier bs = () -> this.client().inNamespace(this.client().getNamespace()).pods().list().getItems().stream()
+ BooleanSupplier bs = () -> this.client().inNamespace(this.getTargetNamespace()).pods().list().getItems().stream()
.filter(p -> !com.google.common.base.Strings.isNullOrEmpty(p.getMetadata().getLabels().get(operatorSpec[1]))
&& p.getMetadata().getLabels().get(operatorSpec[1]).equals(operatorSpec[2])
&& p.getStatus().getContainerStatuses().size() > 0
@@ -486,8 +496,8 @@ protected FailFastCheck getFailFastCheck() {
* Documentation: https://docs.openshift.com/container-platform/4.4/operators/olm-deleting-operators-from-cluster.html#olm-deleting-operator-from-a-cluster-using-cli_olm-deleting-operators-from-a-cluster
*/
public void unsubscribe() {
- this.execute("delete", "subscription", packageManifestName, "--ignore-not-found");
- this.execute("delete", "csvs", currentCSV, "--ignore-not-found");
+ removeSubscription();
+ removeClusterServiceVersion();
for (String customResource : getCustomResourceDefinitions()) {
final String crds = this.execute("get", "crd", customResource, "--ignore-not-found");
if (crds != null && !crds.isEmpty()) {
@@ -496,6 +506,14 @@ public void unsubscribe() {
}
}
+ protected void removeClusterServiceVersion() {
+ this.execute("delete", "csvs", currentCSV, "--ignore-not-found");
+ }
+
+ protected void removeSubscription() {
+ this.execute("delete", "subscription", packageManifestName, "--ignore-not-found");
+ }
+
public String getCurrentCSV() {
return currentCSV;
}
diff --git a/docs/Operator-Based-Provisioning.md b/docs/Operator-Based-Provisioning.md
index c6c859dc..7bd56cae 100644
--- a/docs/Operator-Based-Provisioning.md
+++ b/docs/Operator-Based-Provisioning.md
@@ -19,8 +19,9 @@ extended easily, since Intersmash _provisioners_ are pluggable components.
| Red Hat Build of keycloak (RHBK) | 24.0.3-opr.1 | stable-v24 | https://github.com/keycloak/keycloak/tree/main/operator | Latest Keycloak, based on Quarkus. |
| Red Hat SSO - **DEPRECATED** | 7.6.8-opr-001 | stable | https://github.com/keycloak/keycloak-operator | Latest Red Hat SSO Operator, based on legacy Keycloak |
| WildFly | 1.0.0 | alpha | https://github.com/wildfly/wildfly-operator | As available on https://operatorhub.io/operator/wildfly |
-| Red Hat JBoss EAP | 3.0.0 | stable | https://github.com/wildfly/wildfly-operator | As available on the OpenShift OperatorHub |
+| Red Hat JBoss EAP | 3.0.0 | stable | https://github.com/wildfly/wildfly-operator | As available from the OpenShift OperatorHub |
| Hyperfoil | 0.24.2 | alpha | https://github.com/Hyperfoil/hyperfoil-operator | Available for both **Kubernetes** and **OpenShift**. We force the CRs version for the used Hyperfoil runtime to be 0.24.2, see https://github.com/Hyperfoil/hyperfoil-operator/issues/18 |
+| Open Data Hub | 2.22.0 | fast | https://github.com/opendatahub-io/opendatahub-operator | As available from the OpenShift OperatorHub |
Intersmash operator-based provisioners implement a common contract and high level behavior which is defined by the
[OperatorProvisioner](../core/src/main/java/org/jboss/intersmash/provision/openshift/operator/OperatorProvisioner.java)
diff --git a/docs/Provisioner-by-Product.md b/docs/Provisioner-by-Product.md
index 9b02bc50..bdc90804 100644
--- a/docs/Provisioner-by-Product.md
+++ b/docs/Provisioner-by-Product.md
@@ -20,6 +20,7 @@ The provisioner is selected by a factory, based on the _Application class_ type
| **Keycloak & Red Hat Build of Keycloak Operator** (see KeycloakOperatorApplication) | KeycloakOperatorProvisioner | :heavy_check_mark: | :heavy_check_mark: |
| **Red Hat SSO Operator** (see RhSsoOperatorApplication) - **DEPRECATED** | RhSsoOperatorProvisioner | :x: | :heavy_check_mark: |
| **WildFly & JBoss EAP 8 Operator** (see WildflyOperatorApplication) | WildflyOperatorProvisioner | :heavy_check_mark: | :heavy_check_mark: |
+| **Open Data Hub operator** (see OpenDataHubOperatorApplication) | OpenDataHubOpenShiftOperatorProvisioner | :heavy_check_mark: | :x: |
| **Template based services** | | | |
| **JBoss EAP 7 Legacy s2i Build Template** (see Eap7LegacyS2iBuildTemplateApplication) | Eap7LegacyS2iBuildTemplateProvisioner | :x: | :heavy_check_mark: |
| **JBoss EAP 7 Legacy s2i Deployment Template** (see Eap7TemplateOpenShiftApplication) | Eap7TemplateOpenShiftProvisioner | :x: | :heavy_check_mark: |
diff --git a/provisioners/pom.xml b/provisioners/pom.xml
index a4b9ee85..ebd2cc18 100644
--- a/provisioners/pom.xml
+++ b/provisioners/pom.xml
@@ -236,25 +236,26 @@
java-generator-maven-plugin
+ default-crd-generation
generate
+
+ target/generated-sources
+
+
+ false
+
+ true
+
-
- target/generated-sources
-
-
- false
-
- true
-
diff --git a/provisioners/src/main/java/org/jboss/intersmash/application/operator/OpenDataHubOperatorApplication.java b/provisioners/src/main/java/org/jboss/intersmash/application/operator/OpenDataHubOperatorApplication.java
new file mode 100644
index 00000000..b37b9f2d
--- /dev/null
+++ b/provisioners/src/main/java/org/jboss/intersmash/application/operator/OpenDataHubOperatorApplication.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.intersmash.application.operator;
+
+import io.opendatahub.datasciencecluster.v1.DataScienceCluster;
+import io.opendatahub.dscinitialization.v1.DSCInitialization;
+
+/**
+ * End user Application interface which presents an Open Data Hub/OpenShift AI operator application.
+ * Only relevant model APIs are currently exposed, more would be added on demand
+ *
+ * The application will be deployed by:
+ *
+ * - {@link org.jboss.intersmash.provision.operator.OpenDataHubOperatorProvisioner}
+ *
+ */
+public interface OpenDataHubOperatorApplication extends OperatorApplication {
+
+ /**
+ * Provides read access to the deployed {@link DataScienceCluster} instance.
+ * @return A {@link DataScienceCluster} instance that is deployed.
+ */
+ DataScienceCluster getDataScienceCluster();
+
+ /**
+ * Provides read access to the {@link DSCInitialization} instance that should be used to initialize the
+ * deployed {@link DataScienceCluster}, represented by {@link #getDataScienceCluster} getter.
+ * @return A {@link DSCInitialization} instance that configures the deployed {@link DataScienceCluster}
+ */
+ DSCInitialization getDSCInitialization();
+}
diff --git a/provisioners/src/main/java/org/jboss/intersmash/provision/openshift/OpenDataHubOpenShiftOperatorProvisioner.java b/provisioners/src/main/java/org/jboss/intersmash/provision/openshift/OpenDataHubOpenShiftOperatorProvisioner.java
new file mode 100644
index 00000000..a134d12b
--- /dev/null
+++ b/provisioners/src/main/java/org/jboss/intersmash/provision/openshift/OpenDataHubOpenShiftOperatorProvisioner.java
@@ -0,0 +1,116 @@
+/**
+ * Copyright (C) 2023 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.intersmash.provision.openshift;
+
+import org.jboss.intersmash.application.operator.OpenDataHubOperatorApplication;
+import org.jboss.intersmash.provision.operator.OpenDataHubOperatorProvisioner;
+import org.jboss.intersmash.provision.operator.model.odh.DSCInitializationList;
+import org.jboss.intersmash.provision.operator.model.odh.DataScienceClusterList;
+import org.jboss.intersmash.provision.operator.model.odh.FeatureTrackerList;
+import org.jboss.intersmash.provision.operator.model.odh.MonitoringList;
+
+import cz.xtf.core.openshift.OpenShifts;
+import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition;
+import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinitionList;
+import io.fabric8.kubernetes.client.NamespacedKubernetesClientAdapter;
+import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
+import io.fabric8.kubernetes.client.dsl.Resource;
+import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext;
+import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperationsImpl;
+import io.fabric8.openshift.client.NamespacedOpenShiftClient;
+import io.opendatahub.datasciencecluster.v1.DataScienceCluster;
+import io.opendatahub.dscinitialization.v1.DSCInitialization;
+import io.opendatahub.features.v1.FeatureTracker;
+import io.opendatahub.platform.services.v1alpha1.Monitoring;
+import lombok.NonNull;
+
+/**
+ * A {@link org.jboss.intersmash.provision.Provisioner} that extends {@link OpenDataHubOperatorProvisioner} and
+ * is able to deploy the Open Data Hub Operator on OpenShift specifically.
+ */
+public class OpenDataHubOpenShiftOperatorProvisioner
+ // leverage Open Data Hub common Operator based provisioner behavior
+ extends OpenDataHubOperatorProvisioner
+ // ... and common OpenShift provisioning logic, too
+ implements OpenShiftProvisioner {
+
+ private static final String OPENSHIFT_OPERATORS_NAMESPACE = "openshift-operators";
+
+ public OpenDataHubOpenShiftOperatorProvisioner(
+ @NonNull OpenDataHubOperatorApplication application) {
+ super(application);
+ }
+
+ @Override
+ protected String getTargetNamespace() {
+ return OPENSHIFT_OPERATORS_NAMESPACE;
+ }
+
+ @Override
+ public NamespacedKubernetesClientAdapter client() {
+ return OpenShifts.admin();
+ }
+
+ @Override
+ public String execute(String... args) {
+ return OpenShiftProvisioner.super.execute(args);
+ }
+
+ // =================================================================================================================
+ // Related to generic provisioning behavior
+ // =================================================================================================================
+ @Override
+ protected void removeClusterServiceVersion() {
+ this.execute("delete", "csvs", currentCSV, "-n", this.getTargetNamespace(), "--ignore-not-found");
+ }
+
+ @Override
+ protected void removeSubscription() {
+ this.execute("delete", "subscription", packageManifestName, "-n", this.getTargetNamespace(), "--ignore-not-found");
+ }
+
+ // =================================================================================================================
+ // Client related
+ // =================================================================================================================
+ @Override
+ public NonNamespaceOperation> customResourceDefinitionsClient() {
+ return OpenShifts.admin().apiextensions().v1().customResourceDefinitions();
+ }
+
+ @Override
+ protected HasMetadataOperationsImpl dataScienceClusterCustomResourcesClient(
+ CustomResourceDefinitionContext crdc) {
+ return OpenShifts.admin().newHasMetadataOperation(crdc, DataScienceCluster.class, DataScienceClusterList.class);
+ }
+
+ @Override
+ protected HasMetadataOperationsImpl dscInitializationCustomResourcesClient(
+ CustomResourceDefinitionContext crdc) {
+ return OpenShifts.admin().newHasMetadataOperation(crdc, DSCInitialization.class, DSCInitializationList.class);
+ }
+
+ @Override
+ protected HasMetadataOperationsImpl featureTrackerCustomResourcesClient(
+ CustomResourceDefinitionContext crdc) {
+ return OpenShifts.admin().newHasMetadataOperation(crdc, FeatureTracker.class, FeatureTrackerList.class);
+ }
+
+ @Override
+ protected HasMetadataOperationsImpl monitoringCustomResourcesClient(
+ CustomResourceDefinitionContext crdc) {
+ return OpenShifts.admin().newHasMetadataOperation(crdc, Monitoring.class, MonitoringList.class);
+ }
+}
diff --git a/provisioners/src/main/java/org/jboss/intersmash/provision/operator/OpenDataHubOperatorProvisioner.java b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/OpenDataHubOperatorProvisioner.java
new file mode 100644
index 00000000..6cbdff48
--- /dev/null
+++ b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/OpenDataHubOperatorProvisioner.java
@@ -0,0 +1,257 @@
+/**
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.intersmash.provision.operator;
+
+import java.util.List;
+
+import org.jboss.intersmash.IntersmashConfig;
+import org.jboss.intersmash.application.operator.OpenDataHubOperatorApplication;
+import org.jboss.intersmash.provision.Provisioner;
+import org.jboss.intersmash.provision.operator.model.odh.DSCInitializationList;
+import org.jboss.intersmash.provision.operator.model.odh.DataScienceClusterList;
+import org.jboss.intersmash.provision.operator.model.odh.FeatureTrackerList;
+import org.jboss.intersmash.provision.operator.model.odh.MonitoringList;
+import org.slf4j.event.Level;
+
+import cz.xtf.core.waiting.SimpleWaiter;
+import cz.xtf.core.waiting.failfast.FailFastCheck;
+import io.fabric8.kubernetes.api.model.StatusDetails;
+import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition;
+import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinitionList;
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient;
+import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
+import io.fabric8.kubernetes.client.dsl.Resource;
+import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext;
+import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperationsImpl;
+import io.opendatahub.datasciencecluster.v1.DataScienceCluster;
+import io.opendatahub.dscinitialization.v1.DSCInitialization;
+import io.opendatahub.features.v1.FeatureTracker;
+import io.opendatahub.platform.services.v1alpha1.Monitoring;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Defines the contract and default behavior of an Operator based provisioner for the Open Data Hub Operator
+ */
+@Slf4j
+public abstract class OpenDataHubOperatorProvisioner extends
+ OperatorProvisioner implements Provisioner {
+
+ public OpenDataHubOperatorProvisioner(OpenDataHubOperatorApplication application) {
+ super(application, OpenDataHubOperatorProvisioner.OPERATOR_ID);
+ }
+
+ // =================================================================================================================
+ // Related to generic provisioning behavior
+ // =================================================================================================================
+ @Override
+ public String getOperatorCatalogSource() {
+ return IntersmashConfig.openDataHubOperatorCatalogSource();
+ }
+
+ @Override
+ public String getOperatorIndexImage() {
+ return IntersmashConfig.openDataHubOperatorIndexImage();
+ }
+
+ @Override
+ public String getOperatorChannel() {
+ return IntersmashConfig.openDataHubOperatorChannel();
+ }
+
+ @Override
+ public void deploy() {
+ FailFastCheck ffCheck = getFailFastCheck();
+
+ subscribe();
+
+ dataScienceClusterClient().createOrReplace(getApplication().getDataScienceCluster());
+ new SimpleWaiter(() -> dataScienceCluster().get().getStatus() != null)
+ .failFast(ffCheck)
+ .reason("Wait for status field to be initialized.")
+ .level(Level.DEBUG)
+ .waitFor();
+
+ dscInitializationClient().createOrReplace(getApplication().getDSCInitialization());
+ }
+
+ @Override
+ public void undeploy() {
+ // remove the CRs
+ List deletionDetails = dataScienceCluster().delete();
+ boolean deleted = deletionDetails.stream().allMatch(d -> d.getCauses().isEmpty());
+ if (!deleted) {
+ log.warn("Wasn't able to remove the 'DataScienceCluster' resource");
+ }
+ new SimpleWaiter(() -> dataScienceCluster().get() == null)
+ .reason("Waiting for the the 'DataScienceCluster' resource to be removed.")
+ .level(Level.DEBUG)
+ .waitFor();
+
+ if (getApplication().getDSCInitialization() != null) {
+ final String appName = getApplication().getName();
+ deletionDetails = dscInitializationClient().withName(appName).delete();
+ deleted = deletionDetails.stream().allMatch(d -> d.getCauses().isEmpty());
+ if (!deleted) {
+ log.warn("Wasn't able to remove the 'DSCInitialization' resources created for '{}' instance!",
+ appName);
+ }
+ new SimpleWaiter(() -> dscInitializationClient().list().getItems().isEmpty()).level(Level.DEBUG).waitFor();
+ }
+ // delete the OLM subscription
+ unsubscribe();
+ new SimpleWaiter(() -> getPods().isEmpty())
+ .reason("Waiting for the all the HyperFoil pods to be stopped.")
+ .level(Level.DEBUG)
+ .waitFor();
+ }
+
+ @Override
+ public void scale(int replicas, boolean wait) {
+ throw new UnsupportedOperationException("Scaling is not implemented by Open Data Hub operator based provisioning");
+ }
+
+ // =================================================================================================================
+ // Client related
+ // =================================================================================================================
+ // this is the packagemanifest for the operator;
+ // you can get it with command:
+ // oc get packagemanifest -o template --template='{{ .metadata.name }}'
+ public static String OPERATOR_ID = IntersmashConfig.openDataHubOperatorPackageManifest();
+
+ // this is the name of the CustomResourceDefinition(s)
+ // you can get it with command:
+ // oc get crd > -o template --template='{{ .metadata.name }}'
+ protected static String ODH_DATA_SCIENCE_CLUSTER_CRD_NAME = "datascienceclusters.datasciencecluster.opendatahub.io";
+
+ protected static String ODH_DSC_INITIALIZATION_CRD_NAME = "dscinitializations.dscinitialization.opendatahub.io";
+
+ protected static String ODH_FEATURE_TRACKER_CRD_NAME = "featuretrackers.features.opendatahub.io";
+
+ protected static String ODH_MONITORING_CRD_NAME = "monitorings.services.platform.opendatahub.io";
+
+ /**
+ * Generic CRD client which is used by client builders default implementation to build the CRDs client
+ *
+ * @return A {@link NonNamespaceOperation} instance that represents a
+ */
+ protected abstract NonNamespaceOperation> customResourceDefinitionsClient();
+
+ // datascienceclusters.datasciencecluster.opendatahub.io
+ protected abstract HasMetadataOperationsImpl dataScienceClusterCustomResourcesClient(
+ CustomResourceDefinitionContext crdc);
+
+ // dscinitializations.dscinitialization.opendatahub.io
+ protected abstract HasMetadataOperationsImpl dscInitializationCustomResourcesClient(
+ CustomResourceDefinitionContext crdc);
+
+ // featuretrackers.features.opendatahub.io
+ protected abstract HasMetadataOperationsImpl featureTrackerCustomResourcesClient(
+ CustomResourceDefinitionContext crdc);
+
+ // monitorings.services.platform.opendatahub.io
+ protected abstract HasMetadataOperationsImpl monitoringCustomResourcesClient(
+ CustomResourceDefinitionContext crdc);
+
+ private static NonNamespaceOperation> ODH_DATA_SCIENCE_CLUSTER_CLIENT;
+ private static NonNamespaceOperation> ODH_DSC_INITIALIZATION_CLIENT;
+ private static NonNamespaceOperation> ODH_FEATURE_TRACKER_CLIENT;
+ private static NonNamespaceOperation> ODH_MONITORING_CLIENT;
+
+ /**
+ * Get a client capable of working with {@link OpenDataHubOperatorProvisioner#ODH_DATA_SCIENCE_CLUSTER_CLIENT} custom resource.
+ *
+ * @return client for operations with {@link OpenDataHubOperatorProvisioner#ODH_DATA_SCIENCE_CLUSTER_CLIENT} custom resource
+ */
+ public NonNamespaceOperation> dataScienceClusterClient() {
+ if (ODH_DATA_SCIENCE_CLUSTER_CLIENT == null) {
+ CustomResourceDefinition crd = customResourceDefinitionsClient()
+ .withName(ODH_DATA_SCIENCE_CLUSTER_CRD_NAME).get();
+ if (crd == null) {
+ throw new RuntimeException(String.format("[%s] custom resource is not provided by [%s] operator.",
+ ODH_DATA_SCIENCE_CLUSTER_CRD_NAME, OPERATOR_ID));
+ }
+ ODH_DATA_SCIENCE_CLUSTER_CLIENT = dataScienceClusterCustomResourcesClient(
+ CustomResourceDefinitionContext.fromCrd(crd));
+ }
+ return ODH_DATA_SCIENCE_CLUSTER_CLIENT;
+ }
+
+ /**
+ * Get a client capable of working with {@link OpenDataHubOperatorProvisioner#ODH_DSC_INITIALIZATION_CLIENT} custom resource.
+ *
+ * @return client for operations with {@link OpenDataHubOperatorProvisioner#ODH_DSC_INITIALIZATION_CLIENT} custom resource
+ */
+ public NonNamespaceOperation> dscInitializationClient() {
+ if (ODH_DSC_INITIALIZATION_CLIENT == null) {
+ CustomResourceDefinition crd = customResourceDefinitionsClient()
+ .withName(ODH_DSC_INITIALIZATION_CRD_NAME).get();
+ if (crd == null) {
+ throw new RuntimeException(String.format("[%s] custom resource is not provided by [%s] operator.",
+ ODH_DSC_INITIALIZATION_CRD_NAME, OPERATOR_ID));
+ }
+ ODH_DSC_INITIALIZATION_CLIENT = dscInitializationCustomResourcesClient(
+ CustomResourceDefinitionContext.fromCrd(crd));
+ }
+ return ODH_DSC_INITIALIZATION_CLIENT;
+ }
+
+ /**
+ * Get a client capable of working with {@link OpenDataHubOperatorProvisioner#ODH_FEATURE_TRACKER_CLIENT} custom resource.
+ *
+ * @return client for operations with {@link OpenDataHubOperatorProvisioner#ODH_FEATURE_TRACKER_CLIENT} custom resource
+ */
+ public NonNamespaceOperation> featureTrackerClient() {
+ if (ODH_FEATURE_TRACKER_CLIENT == null) {
+ CustomResourceDefinition crd = customResourceDefinitionsClient()
+ .withName(ODH_FEATURE_TRACKER_CRD_NAME).get();
+ if (crd == null) {
+ throw new RuntimeException(String.format("[%s] custom resource is not provided by [%s] operator.",
+ ODH_FEATURE_TRACKER_CRD_NAME, OPERATOR_ID));
+ }
+ ODH_FEATURE_TRACKER_CLIENT = featureTrackerCustomResourcesClient(CustomResourceDefinitionContext.fromCrd(crd));
+ }
+ return ODH_FEATURE_TRACKER_CLIENT;
+ }
+
+ /**
+ * Get a client capable of working with {@link OpenDataHubOperatorProvisioner#ODH_MONITORING_CLIENT} custom resource.
+ *
+ * @return client for operations with {@link OpenDataHubOperatorProvisioner#ODH_MONITORING_CLIENT} custom resource
+ */
+ public NonNamespaceOperation> monitoringClient() {
+ if (ODH_MONITORING_CLIENT == null) {
+ CustomResourceDefinition crd = customResourceDefinitionsClient()
+ .withName(ODH_MONITORING_CRD_NAME).get();
+ if (crd == null) {
+ throw new RuntimeException(String.format("[%s] custom resource is not provided by [%s] operator.",
+ ODH_MONITORING_CRD_NAME, OPERATOR_ID));
+ }
+ ODH_MONITORING_CLIENT = monitoringCustomResourcesClient(CustomResourceDefinitionContext.fromCrd(crd));
+ }
+ return ODH_MONITORING_CLIENT;
+ }
+
+ /**
+ * Get a reference to an {@link DataScienceCluster} instance.
+ * Use get() to obtain the actual object, or null in case it does not exist on tested cluster.
+ *
+ * @return A concrete {@link Resource} instance representing the {@link DataScienceCluster} resource definition
+ */
+ public Resource dataScienceCluster() {
+ return dataScienceClusterClient().withName(getApplication().getName());
+ }
+
+}
diff --git a/provisioners/src/main/java/org/jboss/intersmash/provision/operator/OpenDataHubOperatorProvisionerFactory.java b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/OpenDataHubOperatorProvisionerFactory.java
new file mode 100644
index 00000000..d88ed7f5
--- /dev/null
+++ b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/OpenDataHubOperatorProvisionerFactory.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2023 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.intersmash.provision.operator;
+
+import org.jboss.intersmash.application.Application;
+import org.jboss.intersmash.application.openshift.OpenShiftApplication;
+import org.jboss.intersmash.application.operator.OpenDataHubOperatorApplication;
+import org.jboss.intersmash.provision.ProvisionerFactory;
+import org.jboss.intersmash.provision.openshift.OpenDataHubOpenShiftOperatorProvisioner;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * This factory is loaded by the Service loader via SPI and will release a concrete instance of
+ * {@link OpenDataHubOperatorProvisioner} that is responsible for deploying an Open Data Hub application service
+ * represented by {@link OpenDataHubOperatorApplication} instances.
+ */
+@Slf4j
+public class OpenDataHubOperatorProvisionerFactory
+ implements ProvisionerFactory {
+
+ @Override
+ public OpenDataHubOperatorProvisioner getProvisioner(Application application) {
+ if (OpenDataHubOperatorApplication.class.isAssignableFrom(application.getClass())) {
+ if (OpenShiftApplication.class.isAssignableFrom(application.getClass())) {
+ return new OpenDataHubOpenShiftOperatorProvisioner((OpenDataHubOperatorApplication) application);
+ }
+ throw new UnsupportedOperationException(
+ "Open Data Hub operator based provisioner requires OpenShift");
+ }
+ return null;
+ }
+}
diff --git a/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/DSCInitializationList.java b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/DSCInitializationList.java
new file mode 100644
index 00000000..c59117a8
--- /dev/null
+++ b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/DSCInitializationList.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.intersmash.provision.operator.model.odh;
+
+import io.fabric8.kubernetes.client.CustomResourceList;
+import io.opendatahub.dscinitialization.v1.DSCInitialization;
+
+/**
+ * Used by {@link org.jboss.intersmash.provision.operator.OpenDataHubOperatorProvisioner} client methods,
+ * this class represents a concrete {@link java.util.List} of {@link DSCInitialization} instances.
+ */
+public class DSCInitializationList extends CustomResourceList {
+}
diff --git a/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/DataScienceClusterList.java b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/DataScienceClusterList.java
new file mode 100644
index 00000000..51856bcf
--- /dev/null
+++ b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/DataScienceClusterList.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.intersmash.provision.operator.model.odh;
+
+import io.fabric8.kubernetes.client.CustomResourceList;
+import io.opendatahub.datasciencecluster.v1.DataScienceCluster;
+
+/**
+ * Used by {@link org.jboss.intersmash.provision.operator.OpenDataHubOperatorProvisioner} client methods,
+ * this class represents a concrete {@link java.util.List} of {@link DataScienceCluster} instances.
+ */
+public class DataScienceClusterList extends CustomResourceList {
+}
diff --git a/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/FeatureTrackerList.java b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/FeatureTrackerList.java
new file mode 100644
index 00000000..115d20b4
--- /dev/null
+++ b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/FeatureTrackerList.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.intersmash.provision.operator.model.odh;
+
+import io.fabric8.kubernetes.client.CustomResourceList;
+import io.opendatahub.features.v1.FeatureTracker;
+
+/**
+ * Used by {@link org.jboss.intersmash.provision.operator.OpenDataHubOperatorProvisioner} client methods,
+ * this class represents a concrete {@link java.util.List} of {@link FeatureTracker} instances.
+ */
+public class FeatureTrackerList extends CustomResourceList {
+}
diff --git a/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/MonitoringList.java b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/MonitoringList.java
new file mode 100644
index 00000000..b366daf3
--- /dev/null
+++ b/provisioners/src/main/java/org/jboss/intersmash/provision/operator/model/odh/MonitoringList.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.intersmash.provision.operator.model.odh;
+
+import io.fabric8.kubernetes.client.CustomResourceList;
+import io.opendatahub.platform.services.v1alpha1.Monitoring;
+
+/**
+ * Used by {@link org.jboss.intersmash.provision.operator.OpenDataHubOperatorProvisioner} client methods,
+ * this class represents a concrete {@link java.util.List} of {@link Monitoring} instances.
+ */
+public class MonitoringList extends CustomResourceList {
+}
diff --git a/provisioners/src/main/resources/META-INF/services/org.jboss.intersmash.provision.ProvisionerFactory b/provisioners/src/main/resources/META-INF/services/org.jboss.intersmash.provision.ProvisionerFactory
index fb869619..f5351e30 100644
--- a/provisioners/src/main/resources/META-INF/services/org.jboss.intersmash.provision.ProvisionerFactory
+++ b/provisioners/src/main/resources/META-INF/services/org.jboss.intersmash.provision.ProvisionerFactory
@@ -16,5 +16,4 @@ org.jboss.intersmash.provision.openshift.Eap7LegacyS2iBuildTemplateProvisionerFa
org.jboss.intersmash.provision.openshift.Eap7TemplateOpenShiftProvisionerFactory
org.jboss.intersmash.provision.operator.HyperfoilOperatorProvisionerFactory
org.jboss.intersmash.provision.openshift.auto.OpenShiftAutoProvisionerFactory
-
-
+org.jboss.intersmash.provision.operator.OpenDataHubOperatorProvisionerFactory
diff --git a/provisioners/src/main/resources/crds/datasciencecluster.opendatahub.io_datascienceclusters.yaml b/provisioners/src/main/resources/crds/datasciencecluster.opendatahub.io_datascienceclusters.yaml
new file mode 100644
index 00000000..7c06b2c7
--- /dev/null
+++ b/provisioners/src/main/resources/crds/datasciencecluster.opendatahub.io_datascienceclusters.yaml
@@ -0,0 +1,972 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.16.1
+ name: datascienceclusters.datasciencecluster.opendatahub.io
+spec:
+ group: datasciencecluster.opendatahub.io
+ names:
+ kind: DataScienceCluster
+ listKind: DataScienceClusterList
+ plural: datascienceclusters
+ shortNames:
+ - dsc
+ singular: datasciencecluster
+ scope: Cluster
+ versions:
+ - name: v1
+ schema:
+ openAPIV3Schema:
+ description: DataScienceCluster is the Schema for the datascienceclusters
+ API.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: DataScienceClusterSpec defines the desired state of the cluster.
+ properties:
+ components:
+ description: Override and fine tune specific component configurations.
+ properties:
+ codeflare:
+ description: |-
+ CodeFlare component configuration.
+ If CodeFlare Operator has been installed in the cluster, it should be uninstalled first before enabling component.
+ properties:
+ devFlags:
+ description: Add developer fields
+ properties:
+ manifests:
+ description: List of custom manifests for the given component
+ items:
+ properties:
+ contextDir:
+ default: manifests
+ description: contextDir is the relative path to
+ the folder containing manifests in a repository,
+ default value "manifests"
+ type: string
+ sourcePath:
+ default: ""
+ description: 'sourcePath is the subpath within contextDir
+ where kustomize builds start. Examples include
+ any sub-folder or path: `base`, `overlays/dev`,
+ `default`, `odh` etc.'
+ type: string
+ uri:
+ default: ""
+ description: uri is the URI point to a git repo
+ with tag/branch. e.g. https://github.com/org/repo/tarball/
+ type: string
+ type: object
+ type: array
+ type: object
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ dashboard:
+ description: Dashboard component configuration.
+ properties:
+ devFlags:
+ description: Add developer fields
+ properties:
+ manifests:
+ description: List of custom manifests for the given component
+ items:
+ properties:
+ contextDir:
+ default: manifests
+ description: contextDir is the relative path to
+ the folder containing manifests in a repository,
+ default value "manifests"
+ type: string
+ sourcePath:
+ default: ""
+ description: 'sourcePath is the subpath within contextDir
+ where kustomize builds start. Examples include
+ any sub-folder or path: `base`, `overlays/dev`,
+ `default`, `odh` etc.'
+ type: string
+ uri:
+ default: ""
+ description: uri is the URI point to a git repo
+ with tag/branch. e.g. https://github.com/org/repo/tarball/
+ type: string
+ type: object
+ type: array
+ type: object
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ datasciencepipelines:
+ description: |-
+ DataSciencePipeline component configuration.
+ Requires OpenShift Pipelines Operator to be installed before enable component
+ properties:
+ devFlags:
+ description: Add developer fields
+ properties:
+ manifests:
+ description: List of custom manifests for the given component
+ items:
+ properties:
+ contextDir:
+ default: manifests
+ description: contextDir is the relative path to
+ the folder containing manifests in a repository,
+ default value "manifests"
+ type: string
+ sourcePath:
+ default: ""
+ description: 'sourcePath is the subpath within contextDir
+ where kustomize builds start. Examples include
+ any sub-folder or path: `base`, `overlays/dev`,
+ `default`, `odh` etc.'
+ type: string
+ uri:
+ default: ""
+ description: uri is the URI point to a git repo
+ with tag/branch. e.g. https://github.com/org/repo/tarball/
+ type: string
+ type: object
+ type: array
+ type: object
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ kserve:
+ description: |-
+ Kserve component configuration.
+ Requires OpenShift Serverless and OpenShift Service Mesh Operators to be installed before enable component
+ Does not support enabled ModelMeshServing at the same time
+ properties:
+ defaultDeploymentMode:
+ description: |-
+ Configures the default deployment mode for Kserve. This can be set to 'Serverless' or 'RawDeployment'.
+ The value specified in this field will be used to set the default deployment mode in the 'inferenceservice-config' configmap for Kserve.
+ This field is optional. If no default deployment mode is specified, Kserve will use Serverless mode.
+ enum:
+ - Serverless
+ - RawDeployment
+ pattern: ^(Serverless|RawDeployment)$
+ type: string
+ devFlags:
+ description: Add developer fields
+ properties:
+ manifests:
+ description: List of custom manifests for the given component
+ items:
+ properties:
+ contextDir:
+ default: manifests
+ description: contextDir is the relative path to
+ the folder containing manifests in a repository,
+ default value "manifests"
+ type: string
+ sourcePath:
+ default: ""
+ description: 'sourcePath is the subpath within contextDir
+ where kustomize builds start. Examples include
+ any sub-folder or path: `base`, `overlays/dev`,
+ `default`, `odh` etc.'
+ type: string
+ uri:
+ default: ""
+ description: uri is the URI point to a git repo
+ with tag/branch. e.g. https://github.com/org/repo/tarball/
+ type: string
+ type: object
+ type: array
+ type: object
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ nim:
+ description: Configures and enables NVIDIA NIM integration
+ properties:
+ managementState:
+ default: Managed
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ serving:
+ description: |-
+ Serving configures the KNative-Serving stack used for model serving. A Service
+ Mesh (Istio) is prerequisite, since it is used as networking layer.
+ properties:
+ ingressGateway:
+ description: |-
+ IngressGateway allows to customize some parameters for the Istio Ingress Gateway
+ that is bound to KNative-Serving.
+ properties:
+ certificate:
+ description: |-
+ Certificate specifies configuration of the TLS certificate securing communication
+ for the gateway.
+ properties:
+ secretName:
+ description: |-
+ SecretName specifies the name of the Kubernetes Secret resource that contains a
+ TLS certificate secure HTTP communications for the KNative network.
+ type: string
+ type:
+ default: OpenshiftDefaultIngress
+ description: |-
+ Type specifies if the TLS certificate should be generated automatically, or if the certificate
+ is provided by the user. Allowed values are:
+ * SelfSigned: A certificate is going to be generated using an own private key.
+ * Provided: Pre-existence of the TLS Secret (see SecretName) with a valid certificate is assumed.
+ * OpenshiftDefaultIngress: Default ingress certificate configured for OpenShift
+ enum:
+ - SelfSigned
+ - Provided
+ - OpenshiftDefaultIngress
+ type: string
+ type: object
+ domain:
+ description: |-
+ Domain specifies the host name for intercepting incoming requests.
+ Most likely, you will want to use a wildcard name, like *.example.com.
+ If not set, the domain of the OpenShift Ingress is used.
+ If you choose to generate a certificate, this is the domain used for the certificate request.
+ type: string
+ type: object
+ managementState:
+ default: Managed
+ enum:
+ - Managed
+ - Unmanaged
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ name:
+ default: knative-serving
+ description: |-
+ Name specifies the name of the KNativeServing resource that is going to be
+ created to instruct the KNative Operator to deploy KNative serving components.
+ This resource is created in the "knative-serving" namespace.
+ type: string
+ type: object
+ type: object
+ kueue:
+ description: Kueue component configuration.
+ properties:
+ devFlags:
+ description: Add developer fields
+ properties:
+ manifests:
+ description: List of custom manifests for the given component
+ items:
+ properties:
+ contextDir:
+ default: manifests
+ description: contextDir is the relative path to
+ the folder containing manifests in a repository,
+ default value "manifests"
+ type: string
+ sourcePath:
+ default: ""
+ description: 'sourcePath is the subpath within contextDir
+ where kustomize builds start. Examples include
+ any sub-folder or path: `base`, `overlays/dev`,
+ `default`, `odh` etc.'
+ type: string
+ uri:
+ default: ""
+ description: uri is the URI point to a git repo
+ with tag/branch. e.g. https://github.com/org/repo/tarball/
+ type: string
+ type: object
+ type: array
+ type: object
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ modelmeshserving:
+ description: ModelMeshServing component configuration.
+ properties:
+ devFlags:
+ description: Add developer fields
+ properties:
+ manifests:
+ description: List of custom manifests for the given component
+ items:
+ properties:
+ contextDir:
+ default: manifests
+ description: contextDir is the relative path to
+ the folder containing manifests in a repository,
+ default value "manifests"
+ type: string
+ sourcePath:
+ default: ""
+ description: 'sourcePath is the subpath within contextDir
+ where kustomize builds start. Examples include
+ any sub-folder or path: `base`, `overlays/dev`,
+ `default`, `odh` etc.'
+ type: string
+ uri:
+ default: ""
+ description: uri is the URI point to a git repo
+ with tag/branch. e.g. https://github.com/org/repo/tarball/
+ type: string
+ type: object
+ type: array
+ type: object
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ modelregistry:
+ description: ModelRegistry component configuration.
+ properties:
+ devFlags:
+ description: Add developer fields
+ properties:
+ manifests:
+ description: List of custom manifests for the given component
+ items:
+ properties:
+ contextDir:
+ default: manifests
+ description: contextDir is the relative path to
+ the folder containing manifests in a repository,
+ default value "manifests"
+ type: string
+ sourcePath:
+ default: ""
+ description: 'sourcePath is the subpath within contextDir
+ where kustomize builds start. Examples include
+ any sub-folder or path: `base`, `overlays/dev`,
+ `default`, `odh` etc.'
+ type: string
+ uri:
+ default: ""
+ description: uri is the URI point to a git repo
+ with tag/branch. e.g. https://github.com/org/repo/tarball/
+ type: string
+ type: object
+ type: array
+ type: object
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ registriesNamespace:
+ default: odh-model-registries
+ description: Namespace for model registries to be installed,
+ configurable only once when model registry is enabled, defaults
+ to "odh-model-registries"
+ maxLength: 63
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$
+ type: string
+ type: object
+ x-kubernetes-validations:
+ - message: RegistriesNamespace is immutable when model registry
+ is Managed
+ rule: (self.managementState != 'Managed') || (oldSelf.registriesNamespace
+ == '') || (oldSelf.managementState != 'Managed')|| (self.registriesNamespace
+ == oldSelf.registriesNamespace)
+ ray:
+ description: Ray component configuration.
+ properties:
+ devFlags:
+ description: Add developer fields
+ properties:
+ manifests:
+ description: List of custom manifests for the given component
+ items:
+ properties:
+ contextDir:
+ default: manifests
+ description: contextDir is the relative path to
+ the folder containing manifests in a repository,
+ default value "manifests"
+ type: string
+ sourcePath:
+ default: ""
+ description: 'sourcePath is the subpath within contextDir
+ where kustomize builds start. Examples include
+ any sub-folder or path: `base`, `overlays/dev`,
+ `default`, `odh` etc.'
+ type: string
+ uri:
+ default: ""
+ description: uri is the URI point to a git repo
+ with tag/branch. e.g. https://github.com/org/repo/tarball/
+ type: string
+ type: object
+ type: array
+ type: object
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ trainingoperator:
+ description: Training Operator component configuration.
+ properties:
+ devFlags:
+ description: Add developer fields
+ properties:
+ manifests:
+ description: List of custom manifests for the given component
+ items:
+ properties:
+ contextDir:
+ default: manifests
+ description: contextDir is the relative path to
+ the folder containing manifests in a repository,
+ default value "manifests"
+ type: string
+ sourcePath:
+ default: ""
+ description: 'sourcePath is the subpath within contextDir
+ where kustomize builds start. Examples include
+ any sub-folder or path: `base`, `overlays/dev`,
+ `default`, `odh` etc.'
+ type: string
+ uri:
+ default: ""
+ description: uri is the URI point to a git repo
+ with tag/branch. e.g. https://github.com/org/repo/tarball/
+ type: string
+ type: object
+ type: array
+ type: object
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ trustyai:
+ description: TrustyAI component configuration.
+ properties:
+ devFlags:
+ description: Add developer fields
+ properties:
+ manifests:
+ description: List of custom manifests for the given component
+ items:
+ properties:
+ contextDir:
+ default: manifests
+ description: contextDir is the relative path to
+ the folder containing manifests in a repository,
+ default value "manifests"
+ type: string
+ sourcePath:
+ default: ""
+ description: 'sourcePath is the subpath within contextDir
+ where kustomize builds start. Examples include
+ any sub-folder or path: `base`, `overlays/dev`,
+ `default`, `odh` etc.'
+ type: string
+ uri:
+ default: ""
+ description: uri is the URI point to a git repo
+ with tag/branch. e.g. https://github.com/org/repo/tarball/
+ type: string
+ type: object
+ type: array
+ type: object
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ workbenches:
+ description: Workbenches component configuration.
+ properties:
+ devFlags:
+ description: Add developer fields
+ properties:
+ manifests:
+ description: List of custom manifests for the given component
+ items:
+ properties:
+ contextDir:
+ default: manifests
+ description: contextDir is the relative path to
+ the folder containing manifests in a repository,
+ default value "manifests"
+ type: string
+ sourcePath:
+ default: ""
+ description: 'sourcePath is the subpath within contextDir
+ where kustomize builds start. Examples include
+ any sub-folder or path: `base`, `overlays/dev`,
+ `default`, `odh` etc.'
+ type: string
+ uri:
+ default: ""
+ description: uri is the URI point to a git repo
+ with tag/branch. e.g. https://github.com/org/repo/tarball/
+ type: string
+ type: object
+ type: array
+ type: object
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ type: object
+ type: object
+ status:
+ description: DataScienceClusterStatus defines the observed state of DataScienceCluster.
+ properties:
+ components:
+ description: Expose component's specific status
+ properties:
+ codeflare:
+ description: CodeFlare component status.
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ dashboard:
+ description: Dashboard component status.
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ url:
+ type: string
+ type: object
+ datasciencepipelines:
+ description: DataSciencePipeline component status.
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ kserve:
+ description: Kserve component status.
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ kueue:
+ description: Kueue component status.
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ modelmeshserving:
+ description: ModelMeshServing component status.
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ modelregistry:
+ description: ModelRegistry component status.
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ registriesNamespace:
+ type: string
+ type: object
+ ray:
+ description: Ray component status.
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ trainingoperator:
+ description: Training Operator component status.
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ trustyai:
+ description: TrustyAI component status.
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ workbenches:
+ description: Workbenches component status.
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ type: object
+ conditions:
+ description: Conditions describes the state of the DataScienceCluster
+ resource.
+ items:
+ description: |-
+ Condition represents the state of the operator's
+ reconciliation functionality.
+ properties:
+ lastHeartbeatTime:
+ format: date-time
+ type: string
+ lastTransitionTime:
+ format: date-time
+ type: string
+ message:
+ type: string
+ reason:
+ type: string
+ status:
+ type: string
+ type:
+ description: ConditionType is the state of the operator's reconciliation
+ functionality.
+ type: string
+ required:
+ - status
+ - type
+ type: object
+ type: array
+ errorMessage:
+ type: string
+ installedComponents:
+ additionalProperties:
+ type: boolean
+ description: List of components with status if installed or not
+ type: object
+ observedGeneration:
+ description: The generation observed by the deployment controller.
+ format: int64
+ type: integer
+ phase:
+ description: |-
+ Phase describes the Phase of DataScienceCluster reconciliation state
+ This is used by OLM UI to provide status information to the user
+ type: string
+ relatedObjects:
+ description: |-
+ RelatedObjects is a list of objects created and maintained by this operator.
+ Object references will be added to this list after they have been created AND found in the cluster.
+ items:
+ description: ObjectReference contains enough information to let
+ you inspect or modify the referred object.
+ properties:
+ apiVersion:
+ description: API version of the referent.
+ type: string
+ fieldPath:
+ description: |-
+ If referring to a piece of an object instead of an entire object, this string
+ should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
+ For example, if the object reference is to a container within a pod, this would take on a value like:
+ "spec.containers{name}" (where "name" refers to the name of the container that triggered
+ the event) or if no container name is specified "spec.containers[2]" (container with
+ index 2 in this pod). This syntax is chosen only to have some well-defined way of
+ referencing a part of an object.
+ type: string
+ kind:
+ description: |-
+ Kind of the referent.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ name:
+ description: |-
+ Name of the referent.
+ More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
+ type: string
+ namespace:
+ description: |-
+ Namespace of the referent.
+ More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
+ type: string
+ resourceVersion:
+ description: |-
+ Specific resourceVersion to which this reference is made, if any.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
+ type: string
+ uid:
+ description: |-
+ UID of the referent.
+ More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ release:
+ description: Version and release type
+ properties:
+ name:
+ type: string
+ version:
+ type: string
+ type: object
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/provisioners/src/main/resources/crds/dscinitialization.opendatahub.io_dscinitializations.yaml b/provisioners/src/main/resources/crds/dscinitialization.opendatahub.io_dscinitializations.yaml
new file mode 100644
index 00000000..d1750a44
--- /dev/null
+++ b/provisioners/src/main/resources/crds/dscinitialization.opendatahub.io_dscinitializations.yaml
@@ -0,0 +1,315 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.16.1
+ name: dscinitializations.dscinitialization.opendatahub.io
+spec:
+ group: dscinitialization.opendatahub.io
+ names:
+ kind: DSCInitialization
+ listKind: DSCInitializationList
+ plural: dscinitializations
+ shortNames:
+ - dsci
+ singular: dscinitialization
+ scope: Cluster
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ - description: Current Phase
+ jsonPath: .status.phase
+ name: Phase
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Created At
+ type: string
+ name: v1
+ schema:
+ openAPIV3Schema:
+ description: DSCInitialization is the Schema for the dscinitializations API.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: DSCInitializationSpec defines the desired state of DSCInitialization.
+ properties:
+ applicationsNamespace:
+ default: opendatahub
+ description: Namespace for applications to be installed, non-configurable,
+ default to "opendatahub"
+ maxLength: 63
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$
+ type: string
+ x-kubernetes-validations:
+ - message: ApplicationsNamespace is immutable
+ rule: self == oldSelf
+ devFlags:
+ description: |-
+ Internal development useful field to test customizations.
+ This is not recommended to be used in production environment.
+ properties:
+ logLevel:
+ description: Override Zap log level. Can be "debug", "info", "error"
+ or a number (more verbose).
+ type: string
+ logmode:
+ default: production
+ description: '## DEPRECATED ##: Ignored, use LogLevel instead'
+ enum:
+ - devel
+ - development
+ - prod
+ - production
+ - default
+ type: string
+ manifestsUri:
+ description: Custom manifests uri for odh-manifests
+ type: string
+ type: object
+ monitoring:
+ description: Enable monitoring on specified namespace
+ properties:
+ managementState:
+ description: |-
+ Set to one of the following values:
+
+ - "Managed" : the operator is actively managing the component and trying to keep it active.
+ It will only upgrade the component if it is safe to do so
+
+ - "Removed" : the operator is actively managing the component and will not install it,
+ or if it is installed, the operator will try to remove it
+ enum:
+ - Managed
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ namespace:
+ default: opendatahub
+ description: |-
+ monitoring spec exposed to DSCI api
+ Namespace for monitoring if it is enabled
+ maxLength: 63
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$
+ type: string
+ type: object
+ serviceMesh:
+ description: |-
+ Configures Service Mesh as networking layer for Data Science Clusters components.
+ The Service Mesh is a mandatory prerequisite for single model serving (KServe) and
+ you should review this configuration if you are planning to use KServe.
+ For other components, it enhances user experience; e.g. it provides unified
+ authentication giving a Single Sign On experience.
+ properties:
+ auth:
+ description: |-
+ Auth holds configuration of authentication and authorization services
+ used by Service Mesh in Opendatahub.
+ properties:
+ audiences:
+ default:
+ - https://kubernetes.default.svc
+ description: |-
+ Audiences is a list of the identifiers that the resource server presented
+ with the token identifies as. Audience-aware token authenticators will verify
+ that the token was intended for at least one of the audiences in this list.
+ If no audiences are provided, the audience will default to the audience of the
+ Kubernetes apiserver (kubernetes.default.svc).
+ items:
+ type: string
+ type: array
+ namespace:
+ description: |-
+ Namespace where it is deployed. If not provided, the default is to
+ use '-auth-provider' suffix on the ApplicationsNamespace of the DSCI.
+ maxLength: 63
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$
+ type: string
+ type: object
+ controlPlane:
+ description: ControlPlane holds configuration of Service Mesh
+ used by Opendatahub.
+ properties:
+ metricsCollection:
+ default: Istio
+ description: |-
+ MetricsCollection specifies if metrics from components on the Mesh namespace
+ should be collected. Setting the value to "Istio" will collect metrics from the
+ control plane and any proxies on the Mesh namespace (like gateway pods). Setting
+ to "None" will disable metrics collection.
+ enum:
+ - Istio
+ - None
+ type: string
+ name:
+ default: data-science-smcp
+ description: Name is a name Service Mesh Control Plane. Defaults
+ to "data-science-smcp".
+ type: string
+ namespace:
+ default: istio-system
+ description: Namespace is a namespace where Service Mesh is
+ deployed. Defaults to "istio-system".
+ maxLength: 63
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$
+ type: string
+ type: object
+ managementState:
+ default: Removed
+ enum:
+ - Managed
+ - Unmanaged
+ - Removed
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ type: object
+ trustedCABundle:
+ description: |-
+ When set to `Managed`, adds odh-trusted-ca-bundle Configmap to all namespaces that includes
+ cluster-wide Trusted CA Bundle in .data["ca-bundle.crt"].
+ Additionally, this fields allows admins to add custom CA bundles to the configmap using the .CustomCABundle field.
+ properties:
+ customCABundle:
+ default: ""
+ description: |-
+ A custom CA bundle that will be available for all components in the
+ Data Science Cluster(DSC). This bundle will be stored in odh-trusted-ca-bundle
+ ConfigMap .data.odh-ca-bundle.crt .
+ type: string
+ managementState:
+ default: Removed
+ description: managementState indicates whether and how the operator
+ should manage customized CA bundle
+ enum:
+ - Managed
+ - Removed
+ - Unmanaged
+ pattern: ^(Managed|Unmanaged|Force|Removed)$
+ type: string
+ required:
+ - customCABundle
+ - managementState
+ type: object
+ required:
+ - applicationsNamespace
+ type: object
+ status:
+ description: DSCInitializationStatus defines the observed state of DSCInitialization.
+ properties:
+ conditions:
+ description: Conditions describes the state of the DSCInitializationStatus
+ resource
+ items:
+ description: |-
+ Condition represents the state of the operator's
+ reconciliation functionality.
+ properties:
+ lastHeartbeatTime:
+ format: date-time
+ type: string
+ lastTransitionTime:
+ format: date-time
+ type: string
+ message:
+ type: string
+ reason:
+ type: string
+ status:
+ type: string
+ type:
+ description: ConditionType is the state of the operator's reconciliation
+ functionality.
+ type: string
+ required:
+ - status
+ - type
+ type: object
+ type: array
+ errorMessage:
+ type: string
+ phase:
+ description: |-
+ Phase describes the Phase of DSCInitializationStatus
+ This is used by OLM UI to provide status information to the user
+ type: string
+ relatedObjects:
+ description: |-
+ RelatedObjects is a list of objects created and maintained by this operator.
+ Object references will be added to this list after they have been created AND found in the cluster
+ items:
+ description: ObjectReference contains enough information to let
+ you inspect or modify the referred object.
+ properties:
+ apiVersion:
+ description: API version of the referent.
+ type: string
+ fieldPath:
+ description: |-
+ If referring to a piece of an object instead of an entire object, this string
+ should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
+ For example, if the object reference is to a container within a pod, this would take on a value like:
+ "spec.containers{name}" (where "name" refers to the name of the container that triggered
+ the event) or if no container name is specified "spec.containers[2]" (container with
+ index 2 in this pod). This syntax is chosen only to have some well-defined way of
+ referencing a part of an object.
+ type: string
+ kind:
+ description: |-
+ Kind of the referent.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ name:
+ description: |-
+ Name of the referent.
+ More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
+ type: string
+ namespace:
+ description: |-
+ Namespace of the referent.
+ More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
+ type: string
+ resourceVersion:
+ description: |-
+ Specific resourceVersion to which this reference is made, if any.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
+ type: string
+ uid:
+ description: |-
+ UID of the referent.
+ More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ release:
+ description: Version and release type
+ properties:
+ name:
+ type: string
+ version:
+ type: string
+ type: object
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/provisioners/src/main/resources/crds/features.opendatahub.io_featuretrackers.yaml b/provisioners/src/main/resources/crds/features.opendatahub.io_featuretrackers.yaml
new file mode 100644
index 00000000..c0110c7f
--- /dev/null
+++ b/provisioners/src/main/resources/crds/features.opendatahub.io_featuretrackers.yaml
@@ -0,0 +1,101 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.16.1
+ name: featuretrackers.features.opendatahub.io
+spec:
+ group: features.opendatahub.io
+ names:
+ kind: FeatureTracker
+ listKind: FeatureTrackerList
+ plural: featuretrackers
+ singular: featuretracker
+ scope: Cluster
+ versions:
+ - name: v1
+ schema:
+ openAPIV3Schema:
+ description: |-
+ FeatureTracker represents a cluster-scoped resource in the Data Science Cluster,
+ specifically designed for monitoring and managing objects created via the internal Features API.
+ This resource serves a crucial role in cross-namespace resource management, acting as
+ an owner reference for various resources. The primary purpose of the FeatureTracker
+ is to enable efficient garbage collection by Kubernetes. This is essential for
+ ensuring that resources are automatically cleaned up and reclaimed when they are
+ no longer required.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: FeatureTrackerSpec defines the desired state of FeatureTracker.
+ properties:
+ appNamespace:
+ type: string
+ source:
+ description: Source describes the type of object that created the
+ related Feature to this FeatureTracker.
+ properties:
+ name:
+ type: string
+ type:
+ type: string
+ type: object
+ type: object
+ status:
+ description: FeatureTrackerStatus defines the observed state of FeatureTracker.
+ properties:
+ conditions:
+ items:
+ description: |-
+ Condition represents the state of the operator's
+ reconciliation functionality.
+ properties:
+ lastHeartbeatTime:
+ format: date-time
+ type: string
+ lastTransitionTime:
+ format: date-time
+ type: string
+ message:
+ type: string
+ reason:
+ type: string
+ status:
+ type: string
+ type:
+ description: ConditionType is the state of the operator's reconciliation
+ functionality.
+ type: string
+ required:
+ - status
+ - type
+ type: object
+ type: array
+ phase:
+ description: |-
+ Phase describes the Phase of FeatureTracker reconciliation state.
+ This is used by OLM UI to provide status information to the user.
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/provisioners/src/main/resources/crds/services.platform.opendatahub.io_monitorings.yaml b/provisioners/src/main/resources/crds/services.platform.opendatahub.io_monitorings.yaml
new file mode 100644
index 00000000..56e4caec
--- /dev/null
+++ b/provisioners/src/main/resources/crds/services.platform.opendatahub.io_monitorings.yaml
@@ -0,0 +1,141 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.16.1
+ name: monitorings.services.platform.opendatahub.io
+spec:
+ group: services.platform.opendatahub.io
+ names:
+ kind: Monitoring
+ listKind: MonitoringList
+ plural: monitorings
+ singular: monitoring
+ scope: Cluster
+ versions:
+ - additionalPrinterColumns:
+ - description: Ready
+ jsonPath: .status.conditions[?(@.type=="Ready")].status
+ name: Ready
+ type: string
+ - description: Reason
+ jsonPath: .status.conditions[?(@.type=="Ready")].reason
+ name: Reason
+ type: string
+ - description: URL
+ jsonPath: .status.url
+ name: URL
+ type: string
+ name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: Monitoring is the Schema for the monitorings API
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: MonitoringSpec defines the desired state of Monitoring
+ properties:
+ namespace:
+ default: opendatahub
+ description: |-
+ monitoring spec exposed to DSCI api
+ Namespace for monitoring if it is enabled
+ maxLength: 63
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$
+ type: string
+ type: object
+ status:
+ description: MonitoringStatus defines the observed state of Monitoring
+ properties:
+ conditions:
+ items:
+ description: Condition contains details for one aspect of the current
+ state of this API Resource.
+ properties:
+ lastTransitionTime:
+ description: |-
+ lastTransitionTime is the last time the condition transitioned from one status to another.
+ This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: |-
+ message is a human readable message indicating details about the transition.
+ This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: |-
+ observedGeneration represents the .metadata.generation that the condition was set based upon.
+ For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
+ with respect to the current state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: |-
+ reason contains a programmatic identifier indicating the reason for the condition's last transition.
+ Producers of specific condition types may define expected values and meanings for this field,
+ and whether the values are considered a guaranteed API.
+ The value should be a CamelCase string.
+ This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ observedGeneration:
+ format: int64
+ type: integer
+ phase:
+ type: string
+ url:
+ type: string
+ type: object
+ type: object
+ x-kubernetes-validations:
+ - message: Monitoring name must be default-monitoring
+ rule: self.metadata.name == 'default-monitoring'
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/testsuite/integration-tests/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/OpenDataHubOpenShiftOperatorProvisionerTest.java b/testsuite/integration-tests/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/OpenDataHubOpenShiftOperatorProvisionerTest.java
new file mode 100644
index 00000000..67c876b2
--- /dev/null
+++ b/testsuite/integration-tests/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/OpenDataHubOpenShiftOperatorProvisionerTest.java
@@ -0,0 +1,172 @@
+package org.jboss.intersmash.testsuite.provision.openshift;
+
+import java.io.IOException;
+
+import org.jboss.intersmash.application.operator.OpenDataHubOperatorApplication;
+import org.jboss.intersmash.junit5.IntersmashExtension;
+import org.jboss.intersmash.provision.olm.OperatorGroup;
+import org.jboss.intersmash.provision.openshift.OpenDataHubOpenShiftOperatorProvisioner;
+import org.jboss.intersmash.testsuite.junit5.categories.NotForProductizedExecutionProfile;
+import org.jboss.intersmash.testsuite.junit5.categories.OpenShiftTest;
+import org.jboss.intersmash.testsuite.openshift.ProjectCreationCapable;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.slf4j.event.Level;
+
+import cz.xtf.core.config.OpenShiftConfig;
+import cz.xtf.core.openshift.OpenShifts;
+import cz.xtf.core.waiting.SimpleWaiter;
+import cz.xtf.junit5.annotations.CleanBeforeAll;
+import io.fabric8.kubernetes.api.model.DeletionPropagation;
+import io.opendatahub.datasciencecluster.v1.DataScienceCluster;
+import io.opendatahub.datasciencecluster.v1.DataScienceClusterBuilder;
+import io.opendatahub.datasciencecluster.v1.datascienceclusterspec.components.kserve.Nim;
+import io.opendatahub.datasciencecluster.v1.datascienceclusterspec.components.kserve.Serving;
+import io.opendatahub.datasciencecluster.v1.datascienceclusterspec.components.kserve.serving.ingressgateway.Certificate;
+import io.opendatahub.dscinitialization.v1.DSCInitialization;
+import io.opendatahub.dscinitialization.v1.DSCInitializationBuilder;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Integration test that validates the functionality of the {@link OpenDataHubOpenShiftOperatorProvisioner} class.
+ * The test subscribes the Open Data Hub operator, then defines CRs instances and compare them with the ones returned by
+ * OpenShift upon creation.
+ */
+@Slf4j
+@CleanBeforeAll
+@OpenShiftTest
+@NotForProductizedExecutionProfile
+public class OpenDataHubOpenShiftOperatorProvisionerTest implements ProjectCreationCapable {
+ private static final OpenDataHubOpenShiftOperatorProvisioner operatorProvisioner = initializeOperatorProvisioner();
+
+ private static OpenDataHubOpenShiftOperatorProvisioner initializeOperatorProvisioner() {
+ OpenDataHubOpenShiftOperatorProvisioner operatorProvisioner = new OpenDataHubOpenShiftOperatorProvisioner(
+ new OpenDataHubOperatorApplication() {
+
+ private static final String APP_NAME = "example-odh";
+
+ @Override
+ public DataScienceCluster getDataScienceCluster() {
+ return new DataScienceClusterBuilder()
+ .withNewMetadata()
+ .withName(APP_NAME)
+ .endMetadata()
+ .withNewSpec()
+ .withNewComponents()
+ .withNewKserve()
+ .withNewNim()
+ .withManagementState(Nim.ManagementState.Managed)
+ .endNim()
+ .withNewServing()
+ .withNewIngressGateway()
+ .withNewCertificate()
+ .withType(Certificate.Type.OpenshiftDefaultIngress)
+ .endCertificate()
+ .endIngressGateway()
+ .withManagementState(Serving.ManagementState.Managed)
+ .endServing()
+ .endKserve()
+ .withNewModelregistry()
+ .withRegistriesNamespace("odh-model-registries")
+ .endModelregistry()
+ .endComponents()
+ .endSpec()
+ .build();
+ }
+
+ @Override
+ public DSCInitialization getDSCInitialization() {
+ return new DSCInitializationBuilder()
+ .withNewMetadata()
+ .withName(APP_NAME)
+ .endMetadata()
+ .withNewSpec()
+ .withApplicationsNamespace(OpenShifts.master().getNamespace())
+ .endSpec()
+ .build();
+ }
+
+ @Override
+ public String getName() {
+ return APP_NAME;
+ }
+ });
+ return operatorProvisioner;
+ }
+
+ @BeforeAll
+ public static void createOperatorGroup() throws IOException {
+ operatorProvisioner.configure();
+ IntersmashExtension.operatorCleanup(false, true);
+ // create operator group - this should be done by InteropExtension
+ OpenShifts.adminBinary().execute("apply", "-f",
+ new OperatorGroup(OpenShiftConfig.namespace()).save().getAbsolutePath());
+ // clean any leftovers
+ operatorProvisioner.unsubscribe();
+ // Let's skip subscribe operation here since we use regular deploy/undeploy where subscribe is called anyway.
+ }
+
+ @AfterAll
+ public static void removeOperatorGroup() {
+ // clean any leftovers
+ operatorProvisioner.unsubscribe();
+ OpenShifts.adminBinary().execute("delete", "operatorgroup", "--all");
+ operatorProvisioner.dismiss();
+ }
+
+ @AfterEach
+ public void customResourcesCleanup() {
+ final String appName = operatorProvisioner.getApplication().getName();
+ operatorProvisioner.dataScienceClusterClient().withName(appName).withPropagationPolicy(DeletionPropagation.FOREGROUND)
+ .delete();
+ operatorProvisioner.dscInitializationClient().withName(appName).withPropagationPolicy(DeletionPropagation.FOREGROUND)
+ .delete();
+ }
+
+ /**
+ * This test case creates and validates minimal {@link DataScienceCluster} and {@link DSCInitialization} CRs
+ *
+ * This is not an integration test, the goal here is to assess that the created CRs are configured as per the
+ * model specification.
+ */
+ @Test
+ public void testMinimalDataScienceCluster() {
+ operatorProvisioner.subscribe();
+ try {
+ verifyMinimalDataScienceCluster(operatorProvisioner.getApplication().getDataScienceCluster(),
+ operatorProvisioner.getApplication().getDSCInitialization());
+ } finally {
+ operatorProvisioner.unsubscribe();
+ }
+ }
+
+ private void verifyMinimalDataScienceCluster(final DataScienceCluster dataScienceCluster,
+ final DSCInitialization dscInitialization) {
+ // create and verify that objects exist
+ operatorProvisioner.dataScienceClusterClient().resource(dataScienceCluster).create();
+ new SimpleWaiter(() -> operatorProvisioner.dataScienceClusterClient().list().getItems().size() == 1)
+ .level(Level.DEBUG)
+ .waitFor();
+ operatorProvisioner.dscInitializationClient().resource(dscInitialization).create();
+ new SimpleWaiter(() -> operatorProvisioner.dscInitializationClient().list().getItems().size() == 1)
+ .level(Level.DEBUG)
+ .waitFor();
+ final DataScienceCluster createdDataScienceCluster = operatorProvisioner.dataScienceCluster().get();
+ Assertions.assertNotNull(createdDataScienceCluster);
+ // the DataScienceCluster spec gets populated on creation, so we just check that it is not null
+ Assertions.assertNotNull(createdDataScienceCluster.getSpec());
+ Assertions.assertNotNull(operatorProvisioner.dataScienceCluster().get().getSpec());
+ // the Monitoring spec gets populated on creation, so we verify 1st level resources individually
+ final DSCInitialization createdDscInitialization = operatorProvisioner.dscInitializationClient()
+ .withName(dscInitialization.getMetadata().getName()).get();
+ Assertions.assertEquals(dscInitialization.getSpec().getDevFlags(), createdDscInitialization.getSpec().getDevFlags());
+ Assertions.assertNotNull(createdDscInitialization.getSpec().getMonitoring());
+ Assertions.assertEquals(dscInitialization.getSpec().getServiceMesh(),
+ createdDscInitialization.getSpec().getServiceMesh());
+ Assertions.assertEquals(dscInitialization.getSpec().getTrustedCABundle(),
+ createdDscInitialization.getSpec().getTrustedCABundle());
+ }
+}
diff --git a/testsuite/integration-tests/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/OpenShiftProvisionerTestBase.java b/testsuite/integration-tests/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/OpenShiftProvisionerTestBase.java
index f473f142..4bb4b262 100644
--- a/testsuite/integration-tests/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/OpenShiftProvisionerTestBase.java
+++ b/testsuite/integration-tests/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/OpenShiftProvisionerTestBase.java
@@ -49,11 +49,11 @@
import org.jboss.intersmash.application.operator.InfinispanOperatorApplication;
import org.jboss.intersmash.application.operator.KafkaOperatorApplication;
import org.jboss.intersmash.application.operator.KeycloakOperatorApplication;
+import org.jboss.intersmash.application.operator.OpenDataHubOperatorApplication;
import org.jboss.intersmash.provision.operator.model.infinispan.infinispan.InfinispanBuilder;
import org.jboss.intersmash.test.deployments.DeploymentsProvider;
import org.jboss.intersmash.test.deployments.TestDeploymentProperties;
import org.jboss.intersmash.test.deployments.WildflyDeploymentApplicationConfiguration;
-import org.jboss.intersmash.testsuite.IntersmashTestsuiteProperties;
import org.jboss.intersmash.testsuite.junit5.categories.OpenShiftTest;
import org.jboss.intersmash.util.CommandLineBasedKeystoreGenerator;
import org.jboss.intersmash.util.openshift.WildflyOpenShiftUtils;
@@ -70,6 +70,10 @@
import io.fabric8.kubernetes.api.model.EnvVar;
import io.fabric8.kubernetes.api.model.EnvVarBuilder;
import io.fabric8.kubernetes.api.model.Secret;
+import io.opendatahub.datasciencecluster.v1.DataScienceCluster;
+import io.opendatahub.datasciencecluster.v1.DataScienceClusterBuilder;
+import io.opendatahub.dscinitialization.v1.DSCInitialization;
+import io.opendatahub.dscinitialization.v1.DSCInitializationBuilder;
import io.strimzi.api.kafka.model.AclOperation;
import io.strimzi.api.kafka.model.AclResourcePatternType;
import io.strimzi.api.kafka.model.AclRule;
@@ -780,4 +784,44 @@ public String getName() {
}
};
}
+
+ /**
+ * Provide an instance of {@link OpenDataHubOperatorApplication}, that represents a minimal Open Data Hub
+ * application service that is used for instance by {@link ProvisionerCleanupTestCase}
+ *
+ * @return A concreate instance of {@link OpenDataHubOperatorApplication}, that represents a minimal Open Data Hub
+ * application service.
+ */
+ static OpenDataHubOperatorApplication getOpenDataHubOperatorApplication() {
+ return new OpenDataHubOperatorApplication() {
+
+ private static final String APP_NAME = "example-odh";
+
+ @Override
+ public DataScienceCluster getDataScienceCluster() {
+ return new DataScienceClusterBuilder()
+ .withNewMetadata()
+ .withName(APP_NAME)
+ .endMetadata()
+ .build();
+ }
+
+ @Override
+ public DSCInitialization getDSCInitialization() {
+ return new DSCInitializationBuilder()
+ .withNewMetadata()
+ .withName(APP_NAME)
+ .endMetadata()
+ .withNewSpec()
+ .withApplicationsNamespace(OpenShifts.master().getNamespace())
+ .endSpec()
+ .build();
+ }
+
+ @Override
+ public String getName() {
+ return APP_NAME;
+ }
+ };
+ }
}
diff --git a/testsuite/integration-tests/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/ProvisionerCleanupTestCase.java b/testsuite/integration-tests/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/ProvisionerCleanupTestCase.java
index 3ca1f853..50f994c8 100644
--- a/testsuite/integration-tests/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/ProvisionerCleanupTestCase.java
+++ b/testsuite/integration-tests/src/test/java/org/jboss/intersmash/testsuite/provision/openshift/ProvisionerCleanupTestCase.java
@@ -62,7 +62,10 @@ private static Stream provisionerProvider() {
, new PostgreSQLImageOpenShiftProvisioner(
OpenShiftProvisionerTestBase.getPostgreSQLImageOpenShiftApplication()),
new PostgreSQLTemplateOpenShiftProvisioner(
- OpenShiftProvisionerTestBase.getPostgreSQLTemplateOpenShiftApplication()));
+ OpenShiftProvisionerTestBase.getPostgreSQLTemplateOpenShiftApplication())
+ // ODH
+ , new OpenDataHubOpenShiftOperatorProvisioner(
+ OpenShiftProvisionerTestBase.getOpenDataHubOperatorApplication()));
} else if (IntersmashTestsuiteProperties.isProductizedTestExecutionProfileEnabled()) {
return Stream.of(
// RHDG