diff --git a/backend/src/routes/api/namespaces/namespaceUtils.ts b/backend/src/routes/api/namespaces/namespaceUtils.ts index 05b1a7dc7f..f2a99507e5 100644 --- a/backend/src/routes/api/namespaces/namespaceUtils.ts +++ b/backend/src/routes/api/namespaces/namespaceUtils.ts @@ -2,6 +2,7 @@ import { PatchUtils, V1SelfSubjectAccessReview } from '@kubernetes/client-node'; import { NamespaceApplicationCase } from './const'; import { K8sStatus, KubeFastifyInstance, OauthFastifyRequest } from '../../../types'; import { createCustomError } from '../../../utils/requestUtils'; +import { featureFlagEnabled, getDashboardConfig } from '../../../utils/resourceUtils'; import { isK8sStatus, safeURLPassThrough } from '../k8s/pass-through'; const checkNamespacePermission = ( @@ -60,13 +61,22 @@ export const applyNamespaceChange = async ( throw createCustomError('Forbidden', "You don't have the access to update the namespace", 403); } + // calling featureFlagEnabled to set the bool to false if it's set to anything but false ('true', undefined, etc) + const enableServiceMesh = featureFlagEnabled( + getDashboardConfig().spec.dashboardConfig.disableServiceMesh, + ); + let labels = {}; + let annotations = {}; switch (context) { case NamespaceApplicationCase.DSG_CREATION: labels = { 'opendatahub.io/dashboard': 'true', 'modelmesh-enabled': 'true', }; + annotations = { + 'opendatahub.io/service-mesh': String(enableServiceMesh), + }; break; case NamespaceApplicationCase.MODEL_SERVING_PROMOTION: labels = { @@ -78,9 +88,17 @@ export const applyNamespaceChange = async ( } return fastify.kube.coreV1Api - .patchNamespace(name, { metadata: { labels } }, undefined, undefined, undefined, undefined, { - headers: { 'Content-type': PatchUtils.PATCH_FORMAT_JSON_MERGE_PATCH }, - }) + .patchNamespace( + name, + { metadata: { labels, annotations } }, + undefined, + undefined, + undefined, + undefined, + { + headers: { 'Content-type': PatchUtils.PATCH_FORMAT_JSON_MERGE_PATCH }, + }, + ) .then(() => ({ applied: true })) .catch((e) => { fastify.log.error( diff --git a/backend/src/routes/api/notebooks/utils.ts b/backend/src/routes/api/notebooks/utils.ts index c4de264e86..58402891b3 100644 --- a/backend/src/routes/api/notebooks/utils.ts +++ b/backend/src/routes/api/notebooks/utils.ts @@ -1,14 +1,16 @@ -import { KubeFastifyInstance, Notebook, NotebookData, Route } from '../../../types'; +import { KubeFastifyInstance, Notebook, NotebookData } from '../../../types'; import { PatchUtils, V1ContainerStatus, V1Pod, V1PodList } from '@kubernetes/client-node'; import { createCustomError } from '../../../utils/requestUtils'; import { getUserName } from '../../../utils/userUtils'; import { RecursivePartial } from '../../../typeHelpers'; +import { featureFlagEnabled, getDashboardConfig } from '../../../utils/resourceUtils'; import { createNotebook, generateNotebookNameFromUsername, getNamespaces, getNotebook, getRoute, + getServiceMeshGwHost, updateNotebook, } from '../../../utils/notebookUtils'; import { FastifyRequest } from 'fastify'; @@ -27,12 +29,24 @@ export const getNotebookStatus = async ( const notebookName = notebook?.metadata.name; let newNotebook: Notebook; if (isRunning && !notebook?.metadata.annotations?.['opendatahub.io/link']) { - const route = await getRoute(fastify, namespace, notebookName).catch((e) => { - fastify.log.warn(`Failed getting route ${notebookName}: ${e.message}`); - return undefined; - }); - if (route) { - newNotebook = await patchNotebookRoute(fastify, route, namespace, notebookName).catch((e) => { + const enableServiceMesh = featureFlagEnabled( + getDashboardConfig().spec.dashboardConfig.disableServiceMesh, + ); + let host: string; + if (enableServiceMesh) { + host = await getServiceMeshGwHost(fastify, namespace).catch((e) => { + fastify.log.warn(`Failed getting route ${notebookName}: ${e.message}`); + return undefined; + }); + } else { + const route = await getRoute(fastify, namespace, notebookName).catch((e) => { + fastify.log.warn(`Failed getting route ${notebookName}: ${e.message}`); + return undefined; + }); + host = route?.spec.host; + } + if (host) { + newNotebook = await patchNotebookRoute(fastify, host, namespace, notebookName).catch((e) => { fastify.log.warn(`Failed patching route to notebook ${notebookName}: ${e.message}`); return notebook; }); @@ -71,14 +85,14 @@ export const checkPodContainersReady = (pod: V1Pod): boolean => { export const patchNotebookRoute = async ( fastify: KubeFastifyInstance, - route: Route, + host: string, namespace: string, name: string, ): Promise => { const patch: RecursivePartial = { metadata: { annotations: { - 'opendatahub.io/link': `https://${route.spec.host}/notebook/${namespace}/${name}`, + 'opendatahub.io/link': `https://${host}/notebook/${namespace}/${name}/`, }, }, }; diff --git a/backend/src/types.ts b/backend/src/types.ts index 8dc3a0cac8..9c3bfc2270 100644 --- a/backend/src/types.ts +++ b/backend/src/types.ts @@ -27,6 +27,7 @@ export type DashboardConfig = K8sResourceCommon & { disableModelServing: boolean; disableProjectSharing: boolean; disableCustomServingRuntimes: boolean; + disableServiceMesh: boolean; modelMetricsNamespace: string; disablePipelines: boolean; }; @@ -410,6 +411,9 @@ export type Notebook = K8sResourceCommon & { 'opendatahub.io/link': string; // redirect notebook url 'opendatahub.io/username': string; // the untranslated username behind the notebook + // Openshift Service Mesh specific annotations. They're needed to orchestrate additional resources for nb namespaces. + 'opendatahub.io/service-mesh': string; + // TODO: Can we get this from the data in the Notebook?? 'notebooks.opendatahub.io/last-image-selection': string; // the last image they selected 'notebooks.opendatahub.io/last-size-selection': string; // the last notebook size they selected diff --git a/backend/src/utils/constants.ts b/backend/src/utils/constants.ts index 0aa5d0965f..5cfb504c71 100644 --- a/backend/src/utils/constants.ts +++ b/backend/src/utils/constants.ts @@ -51,6 +51,7 @@ export const blankDashboardCR: DashboardConfig = { disableModelServing: false, disableProjectSharing: false, disableCustomServingRuntimes: false, + disableServiceMesh: true, modelMetricsNamespace: '', disablePipelines: false, }, diff --git a/backend/src/utils/notebookUtils.ts b/backend/src/utils/notebookUtils.ts index 769efce71d..867f68e3bc 100644 --- a/backend/src/utils/notebookUtils.ts +++ b/backend/src/utils/notebookUtils.ts @@ -1,4 +1,4 @@ -import { getDashboardConfig } from './resourceUtils'; +import { featureFlagEnabled, getDashboardConfig } from './resourceUtils'; import { EnvironmentVariable, ImageInfo, @@ -68,6 +68,32 @@ export const getRoute = async ( return kubeResponse.body as Route; }; +export const getServiceMeshGwHost = async ( + fastify: KubeFastifyInstance, + namespace: string, +): Promise => { + const kubeResponse = await fastify.kube.coreV1Api.readNamespace(namespace).catch((res) => { + const e = res.response.body; + const error = createCustomError('Error getting Namespace', e.message, e.code); + fastify.log.error(error); + throw error; + }); + + const annotations = kubeResponse.body.metadata?.annotations; + + if (!annotations || !annotations['service-mesh.opendatahub.io/public-gateway-host-external']) { + const error = createCustomError( + 'Annotation not found', + `Could not find annotation 'service-mesh.opendatahub.io/public-gateway-host-external' for namespace: ${namespace}`, + 404, + ); + fastify.log.error(error); + throw error; + } + + return annotations['service-mesh.opendatahub.io/public-gateway-host-external']; +}; + export const createRBAC = async ( fastify: KubeFastifyInstance, namespace: string, @@ -256,6 +282,10 @@ export const assembleNotebook = async ( }, })); + const serviceMeshEnabled = String( + !featureFlagEnabled(getDashboardConfig().spec?.dashboardConfig?.disableServiceMesh), + ); + return { apiVersion: 'kubeflow.org/v1', kind: 'Notebook', @@ -265,12 +295,15 @@ export const assembleNotebook = async ( 'opendatahub.io/odh-managed': 'true', 'opendatahub.io/user': translatedUsername, 'opendatahub.io/dashboard': 'true', + 'sidecar.istio.io/inject': String(serviceMeshEnabled), }, annotations: { 'notebooks.opendatahub.io/oauth-logout-url': `${url}/notebookController/${translatedUsername}/home`, 'notebooks.opendatahub.io/last-size-selection': notebookSize.name, 'notebooks.opendatahub.io/last-image-selection': imageSelection, + 'notebooks.opendatahub.io/inject-oauth': String(!serviceMeshEnabled), 'opendatahub.io/username': username, + 'opendatahub.io/service-mesh': serviceMeshEnabled, 'kubeflow-resource-stopped': null, }, name: name, @@ -444,7 +477,16 @@ export const createNotebook = async ( notebookAssembled.metadata.annotations = {}; } - notebookAssembled.metadata.annotations['notebooks.opendatahub.io/inject-oauth'] = 'true'; + const enableServiceMesh = featureFlagEnabled( + getDashboardConfig().spec.dashboardConfig.disableServiceMesh, + ); + + notebookAssembled.metadata.annotations['notebooks.opendatahub.io/inject-oauth'] = String( + !enableServiceMesh, + ); + notebookAssembled.metadata.annotations['opendatahub.io/service-mesh'] = String(enableServiceMesh); + notebookAssembled.metadata.labels['sidecar.istio.io/inject'] = String(enableServiceMesh); + const notebookContainers = notebookAssembled.spec.template.spec.containers; if (!notebookContainers[0]) { diff --git a/backend/src/utils/resourceUtils.ts b/backend/src/utils/resourceUtils.ts index 44cbeec139..d6d4dd426e 100644 --- a/backend/src/utils/resourceUtils.ts +++ b/backend/src/utils/resourceUtils.ts @@ -590,6 +590,9 @@ export const getDashboardConfig = (): DashboardConfig => { return dashboardConfigWatcher.getResources()?.[0]; }; +export const featureFlagEnabled = (disabledSettingState?: boolean): boolean => + disabledSettingState === false; + export const updateDashboardConfig = (): Promise => { return dashboardConfigWatcher.updateResults(); }; diff --git a/docs/dashboard_config.md b/docs/dashboard_config.md index c0cb9891c9..e9c20b0b96 100644 --- a/docs/dashboard_config.md +++ b/docs/dashboard_config.md @@ -23,6 +23,7 @@ The following are a list of features that are supported, along with there defaul | disableProjectSharing | false | Disables Project Sharing from Data Science Projects. | | disableCustomServingRuntimes | false | Disables Custom Serving Runtimes from the Admin Panel. | | modelMetricsNamespace | false | Enables the namespace in which the Model Serving Metrics' Prometheus Operator is installed. | +| disableServiceMesh | true | Disables use of service mesh for routing and authorization. | ## Defaults diff --git a/frontend/src/__mocks__/mockDashboardConfig.ts b/frontend/src/__mocks__/mockDashboardConfig.ts index b388678b38..e0386ce25e 100644 --- a/frontend/src/__mocks__/mockDashboardConfig.ts +++ b/frontend/src/__mocks__/mockDashboardConfig.ts @@ -51,6 +51,7 @@ export const mockDashboardConfig = ({ disableProjects, disableModelServing, disableCustomServingRuntimes, + disableServiceMesh: true, modelMetricsNamespace: 'test-project', disablePipelines: false, disableProjectSharing: false, diff --git a/frontend/src/api/k8s/notebooks.ts b/frontend/src/api/k8s/notebooks.ts index d7a86ba07e..601a6db204 100644 --- a/frontend/src/api/k8s/notebooks.ts +++ b/frontend/src/api/k8s/notebooks.ts @@ -26,11 +26,14 @@ import { } from '~/concepts/pipelines/elyra/utils'; import { createRoleBinding } from '~/api'; import { Volume, VolumeMount } from '~/types'; +import { DashboardConfig } from '~/types'; +import { featureFlagEnabled } from '~/utilities/utils'; import { assemblePodSpecOptions, getshmVolume, getshmVolumeMount } from './utils'; const assembleNotebook = ( data: StartNotebookData, username: string, + enableServiceMesh: boolean, canEnablePipelines?: boolean, ): NotebookKind => { const { @@ -92,6 +95,7 @@ const assembleNotebook = ( 'opendatahub.io/odh-managed': 'true', 'opendatahub.io/user': translatedUsername, [KnownLabels.DASHBOARD_RESOURCE]: 'true', + 'sidecar.istio.io/inject': String(enableServiceMesh), }, annotations: { 'openshift.io/display-name': notebookName.trim(), @@ -99,7 +103,8 @@ const assembleNotebook = ( 'notebooks.opendatahub.io/oauth-logout-url': `${origin}/projects/${projectName}?notebookLogout=${notebookId}`, 'notebooks.opendatahub.io/last-size-selection': notebookSize.name, 'notebooks.opendatahub.io/last-image-selection': imageSelection, - 'notebooks.opendatahub.io/inject-oauth': 'true', + 'notebooks.opendatahub.io/inject-oauth': String(!enableServiceMesh), + 'opendatahub.io/service-mesh': String(enableServiceMesh), 'opendatahub.io/username': username, }, name: notebookId, @@ -187,6 +192,24 @@ const getStopPatch = (): Patch => ({ value: getStopPatchDataString(), }); +const getInjectOAuthPatch = (enableServiceMesh: boolean): Patch => ({ + op: 'add', + path: '/metadata/annotations/notebooks.opendatahub.io~1inject-oauth', + value: String(!enableServiceMesh), +}); + +const getProxyInjectPatch = (enableServiceMesh: boolean): Patch => ({ + op: 'add', + path: '/metadata/labels/sidecar.istio.io~1inject', + value: String(enableServiceMesh), +}); + +const getServiceMeshPatch = (enableServiceMesh: boolean): Patch => ({ + op: 'add', + path: '/metadata/annotations/opendatahub.io~1service-mesh', + value: String(enableServiceMesh), +}); + export const getNotebooks = (namespace: string): Promise => k8sListResource({ model: NotebookModel, @@ -210,10 +233,19 @@ export const startNotebook = async ( name: string, namespace: string, tolerationChanges: TolerationChanges, + dashboardConfig: DashboardConfig, enablePipelines?: boolean, ): Promise => { - const patches: Patch[] = []; - patches.push(startPatch); + const enableServiceMesh = featureFlagEnabled( + dashboardConfig.spec.dashboardConfig.disableServiceMesh, + ); + + const patches: Patch[] = [ + startPatch, + getInjectOAuthPatch(enableServiceMesh), + getServiceMeshPatch(enableServiceMesh), + getProxyInjectPatch(enableServiceMesh), + ]; const tolerationPatch = getTolerationPatch(tolerationChanges); if (tolerationPatch) { @@ -242,9 +274,10 @@ export const startNotebook = async ( export const createNotebook = ( data: StartNotebookData, username: string, + enableServiceMesh: boolean, canEnablePipelines?: boolean, ): Promise => { - const notebook = assembleNotebook(data, username, canEnablePipelines); + const notebook = assembleNotebook(data, username, enableServiceMesh, canEnablePipelines); const notebookPromise = k8sCreateResource({ model: NotebookModel, @@ -264,9 +297,10 @@ export const updateNotebook = ( existingNotebook: NotebookKind, data: StartNotebookData, username: string, + enableServiceMesh: boolean, ): Promise => { data.notebookId = existingNotebook.metadata.name; - const notebook = assembleNotebook(data, username); + const notebook = assembleNotebook(data, username, enableServiceMesh); const oldNotebook = structuredClone(existingNotebook); const container = oldNotebook.spec.template.spec.containers[0]; @@ -287,9 +321,10 @@ export const updateNotebook = ( export const createNotebookWithoutStarting = ( data: StartNotebookData, username: string, + enableServiceMesh: boolean, ): Promise => new Promise((resolve, reject) => - createNotebook(data, username).then((notebook) => + createNotebook(data, username, enableServiceMesh).then((notebook) => setTimeout( () => stopNotebook(notebook.metadata.name, notebook.metadata.namespace) @@ -299,7 +334,6 @@ export const createNotebookWithoutStarting = ( ), ), ); - export const deleteNotebook = (notebookName: string, namespace: string): Promise => k8sDeleteResource({ model: NotebookModel, diff --git a/frontend/src/api/k8s/routes.ts b/frontend/src/api/k8s/routes.ts index 74d815fc33..19adaa849f 100644 --- a/frontend/src/api/k8s/routes.ts +++ b/frontend/src/api/k8s/routes.ts @@ -1,6 +1,6 @@ import { k8sGetResource } from '@openshift/dynamic-plugin-sdk-utils'; -import { RouteModel } from '~/api/models'; -import { K8sAPIOptions, RouteKind } from '~/k8sTypes'; +import { RouteModel, ProjectModel } from '~/api/models'; +import { K8sAPIOptions, RouteKind, ProjectKind } from '~/k8sTypes'; import { applyK8sAPIOptions } from '~/api/apiMergeUtils'; export const getRoute = ( @@ -14,3 +14,17 @@ export const getRoute = ( queryOptions: { name, ns: namespace }, }), ); + +export const getServiceMeshGwHost = async (namespace: string): Promise => { + const queryOptions = { + name: namespace, + }; + return k8sGetResource({ model: ProjectModel, queryOptions }) + .then( + (project) => + project?.metadata?.annotations?.[ + 'service-mesh.opendatahub.io/public-gateway-host-external' + ] || null, + ) + .catch((error) => error); +}; diff --git a/frontend/src/k8sTypes.ts b/frontend/src/k8sTypes.ts index 2795ef2eed..8022ae0d7a 100644 --- a/frontend/src/k8sTypes.ts +++ b/frontend/src/k8sTypes.ts @@ -68,6 +68,7 @@ export type NotebookAnnotations = Partial<{ 'notebooks.kubeflow.org/last-activity': string; // datestamp of last use 'opendatahub.io/link': string; // redirect notebook url 'opendatahub.io/username': string; // the untranslated username behind the notebook + 'opendatahub.io/service-mesh': string; // Openshift Service Mesh : determines if mesh configuration should be applied 'notebooks.opendatahub.io/last-image-selection': string; // the last image they selected 'notebooks.opendatahub.io/last-size-selection': string; // the last notebook size they selected }>; diff --git a/frontend/src/pages/projects/notebook/NotebookStatusToggle.tsx b/frontend/src/pages/projects/notebook/NotebookStatusToggle.tsx index cc63f9c3a6..7265109254 100644 --- a/frontend/src/pages/projects/notebook/NotebookStatusToggle.tsx +++ b/frontend/src/pages/projects/notebook/NotebookStatusToggle.tsx @@ -102,6 +102,7 @@ const NotebookStatusToggle: React.FC = ({ notebookName, notebookNamespace, tolerationSettings, + dashboardConfig, enablePipelines && !currentlyHasPipelines(notebook), ).then(() => { fireNotebookTrackingEvent('started'); diff --git a/frontend/src/pages/projects/notebook/useRouteForNotebook.ts b/frontend/src/pages/projects/notebook/useRouteForNotebook.ts index 9a78c22a5e..e0f9ff3730 100644 --- a/frontend/src/pages/projects/notebook/useRouteForNotebook.ts +++ b/frontend/src/pages/projects/notebook/useRouteForNotebook.ts @@ -1,6 +1,8 @@ import * as React from 'react'; -import { getRoute } from '~/api'; +import { getServiceMeshGwHost, getRoute } from '~/api'; import { FAST_POLL_INTERVAL } from '~/utilities/const'; +import { useAppContext } from '~/app/AppContext'; +import { featureFlagEnabled } from '~/utilities/utils'; const useRouteForNotebook = ( notebookName?: string, @@ -10,6 +12,10 @@ const useRouteForNotebook = ( const [route, setRoute] = React.useState(null); const [loaded, setLoaded] = React.useState(false); const [loadError, setLoadError] = React.useState(null); + const { dashboardConfig } = useAppContext(); + const enableServiceMesh = featureFlagEnabled( + dashboardConfig.spec.dashboardConfig.disableServiceMesh, + ); React.useEffect(() => { let watchHandle: ReturnType; @@ -19,12 +25,17 @@ const useRouteForNotebook = ( return; } if (notebookName && projectName) { - getRoute(notebookName, projectName) - .then((route) => { + // if not using service mesh fetch openshift route, otherwise get Istio Ingress Gateway route + const getRoutePromise = !enableServiceMesh + ? getRoute(notebookName, projectName).then((route) => route?.spec.host) + : getServiceMeshGwHost(projectName); + + getRoutePromise + .then((host) => { if (cancelled) { return; } - setRoute(`https://${route.spec.host}/notebook/${projectName}/${notebookName}`); + setRoute(`https://${host}/notebook/${projectName}/${notebookName}/`); setLoadError(null); setLoaded(true); }) @@ -46,7 +57,7 @@ const useRouteForNotebook = ( cancelled = true; clearTimeout(watchHandle); }; - }, [notebookName, projectName, isRunning]); + }, [notebookName, projectName, isRunning, enableServiceMesh]); return [route, loaded, loadError]; }; diff --git a/frontend/src/pages/projects/screens/spawner/SpawnerFooter.tsx b/frontend/src/pages/projects/screens/spawner/SpawnerFooter.tsx index fbf05a466d..719c522a6a 100644 --- a/frontend/src/pages/projects/screens/spawner/SpawnerFooter.tsx +++ b/frontend/src/pages/projects/screens/spawner/SpawnerFooter.tsx @@ -17,8 +17,9 @@ import { } from '~/pages/projects/types'; import { useUser } from '~/redux/selectors'; import { ProjectDetailsContext } from '~/pages/projects/ProjectDetailsContext'; -import { AppContext } from '~/app/AppContext'; +import { AppContext, useAppContext } from '~/app/AppContext'; import { fireTrackingEvent } from '~/utilities/segmentIOUtils'; +import { featureFlagEnabled } from '~/utilities/utils'; import { createPvcDataForNotebook, createConfigMapsAndSecretsForNotebook, @@ -76,6 +77,10 @@ const SpawnerFooter: React.FC = ({ editNotebook, existingDataConnections, ); + const { dashboardConfig } = useAppContext(); + const enableServiceMesh = featureFlagEnabled( + dashboardConfig.spec.dashboardConfig.disableServiceMesh, + ); const afterStart = (name: string, type: 'created' | 'updated') => { const { gpus, notebookSize, image } = startNotebookData; @@ -149,7 +154,7 @@ const SpawnerFooter: React.FC = ({ envFrom, tolerationSettings, }; - updateNotebook(editNotebook, newStartNotebookData, username) + updateNotebook(editNotebook, newStartNotebookData, username, enableServiceMesh) .then((notebook) => afterStart(notebook.metadata.name, 'updated')) .catch(handleError); } @@ -207,7 +212,7 @@ const SpawnerFooter: React.FC = ({ tolerationSettings, }; - createNotebook(newStartData, username, canEnablePipelines) + createNotebook(newStartData, username, enableServiceMesh, canEnablePipelines) .then((notebook) => afterStart(notebook.metadata.name, 'created')) .catch(handleError); }; diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 4781bc9072..036f9e592f 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -88,6 +88,7 @@ export type DashboardCommonConfig = { disableModelServing: boolean; disableProjectSharing: boolean; disableCustomServingRuntimes: boolean; + disableServiceMesh: boolean; modelMetricsNamespace: string; disablePipelines: boolean; }; diff --git a/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml b/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml index 8108ce32aa..5ffa094e85 100644 --- a/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml +++ b/manifests/crd/odhdashboardconfigs.opendatahub.io.crd.yaml @@ -49,6 +49,8 @@ spec: type: boolean disableCustomServingRuntimes: type: boolean + disableServiceMesh: + type: boolean modelMetricsNamespace: type: string disablePipelines: diff --git a/manifests/overlays/minimal/README.md b/manifests/overlays/minimal/README.md new file mode 100644 index 0000000000..d43bde3167 --- /dev/null +++ b/manifests/overlays/minimal/README.md @@ -0,0 +1,4 @@ +## Dashboard Minimal overlay + +This overlay is specifically used to trim deployment options such as replica count and probes times. +Might be useful for resource-constrained environments such as [Openshift Local](https://developers.redhat.com/products/openshift-local/overview) (aka `crc`). \ No newline at end of file diff --git a/manifests/overlays/minimal/deployment-resources-patch.yaml b/manifests/overlays/minimal/deployment-resources-patch.yaml new file mode 100644 index 0000000000..447c4dd4da --- /dev/null +++ b/manifests/overlays/minimal/deployment-resources-patch.yaml @@ -0,0 +1,12 @@ +# these three replaces are for testing on less powerful clusters (crc) +- op: replace + path: /spec/replicas + value: 1 + +- op: replace + path: /spec/template/spec/containers/0/livenessProbe/periodSeconds + value: 300 + +- op: replace + path: /spec/template/spec/containers/0/readinessProbe/periodSeconds + value: 300 diff --git a/manifests/overlays/minimal/kustomization.yaml b/manifests/overlays/minimal/kustomization.yaml new file mode 100644 index 0000000000..0f22fe3732 --- /dev/null +++ b/manifests/overlays/minimal/kustomization.yaml @@ -0,0 +1,13 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +bases: +- ../../base + +patchesJson6902: +- path: deployment-resources-patch.yaml + target: + group: apps + version: v1 + kind: Deployment + name: odh-dashboard diff --git a/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml b/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml index 677c300dc9..0a84db9ffc 100644 --- a/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml +++ b/manifests/overlays/odhdashboardconfig/odh-dashboard-config.yaml @@ -18,6 +18,7 @@ spec: disableModelServing: true disableProjectSharing: true disableCustomServingRuntimes: true + disableServiceMesh: true modelMetricsNamespace: '' notebookController: enabled: true diff --git a/manifests/overlays/service-mesh/OWNERS b/manifests/overlays/service-mesh/OWNERS new file mode 100644 index 0000000000..899fa5820f --- /dev/null +++ b/manifests/overlays/service-mesh/OWNERS @@ -0,0 +1,10 @@ +# Each list is sorted alphabetically, additions should maintain that order +approvers: +- aslakknutsen +- bartoszmajsak +- cam-garrison + +reviewers: +- aslakknutsen +- bartoszmajsak +- cam-garrison diff --git a/manifests/overlays/service-mesh/kustomization.yaml b/manifests/overlays/service-mesh/kustomization.yaml new file mode 100644 index 0000000000..f1b6062baf --- /dev/null +++ b/manifests/overlays/service-mesh/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +bases: +- ../../base + +patchesStrategicMerge: +# when using bases: +# - ../../base +# the entire directory is truncated and the lookup is performed in base/ +# for this reason the files must be there as well. with the same content, as they will be in fact used +- patches/oauth-client-patch.yaml +- patches/oauth-config-patch.yaml + +# # needs to be patchesJson6902, patches seems to be ignored +# # also: inline patches do not work, operator complains about overlays/service-mesh being +# # a directory and not a kustomization.yaml file +patchesJson6902: +- path: patches/route-patch.yaml + target: + group: route.openshift.io + version: v1 + kind: Route + name: odh-dashboard +- path: patches/service-patch.yaml + target: + version: v1 + kind: Service + name: odh-dashboard +- path: patches/service-account-patch.yaml + target: + version: v1 + kind: ServiceAccount + name: odh-dashboard +- path: patches/deployment-patch.yaml + target: + group: apps + version: v1 + kind: Deployment + name: odh-dashboard diff --git a/manifests/overlays/service-mesh/patches/deployment-patch.yaml b/manifests/overlays/service-mesh/patches/deployment-patch.yaml new file mode 100644 index 0000000000..5d57c09c3d --- /dev/null +++ b/manifests/overlays/service-mesh/patches/deployment-patch.yaml @@ -0,0 +1,13 @@ +# remove the oauth proxy container. NOTE: this will break if another container is added above. +- op: remove + path: /spec/template/spec/containers/1 + +# remove the volumes, no longer needed and secrets that are mounted are no longer created. +- op: remove + path: /spec/template/spec/volumes + +# add istio inject label +- op: add + path: /spec/template/metadata/annotations + value: + sidecar.istio.io/inject: "true" diff --git a/manifests/overlays/service-mesh/patches/oauth-client-patch.yaml b/manifests/overlays/service-mesh/patches/oauth-client-patch.yaml new file mode 100644 index 0000000000..80d7896300 --- /dev/null +++ b/manifests/overlays/service-mesh/patches/oauth-client-patch.yaml @@ -0,0 +1,5 @@ +$patch: delete +apiVersion: v1 +kind: Secret +metadata: + name: dashboard-oauth-client diff --git a/manifests/overlays/service-mesh/patches/oauth-config-patch.yaml b/manifests/overlays/service-mesh/patches/oauth-config-patch.yaml new file mode 100644 index 0000000000..9e94d0a655 --- /dev/null +++ b/manifests/overlays/service-mesh/patches/oauth-config-patch.yaml @@ -0,0 +1,5 @@ +$patch: delete +apiVersion: v1 +kind: Secret +metadata: + name: dashboard-oauth-config diff --git a/manifests/overlays/service-mesh/patches/route-patch.yaml b/manifests/overlays/service-mesh/patches/route-patch.yaml new file mode 100644 index 0000000000..095c567051 --- /dev/null +++ b/manifests/overlays/service-mesh/patches/route-patch.yaml @@ -0,0 +1,9 @@ +- op: remove + path: /metadata/annotations + +- op: replace + path: /spec/port/targetPort + value: 8080 + +- op: remove + path: /spec/tls diff --git a/manifests/overlays/service-mesh/patches/service-account-patch.yaml b/manifests/overlays/service-mesh/patches/service-account-patch.yaml new file mode 100644 index 0000000000..7d76e98337 --- /dev/null +++ b/manifests/overlays/service-mesh/patches/service-account-patch.yaml @@ -0,0 +1,2 @@ +- op: remove + path: /metadata/annotations diff --git a/manifests/overlays/service-mesh/patches/service-patch.yaml b/manifests/overlays/service-mesh/patches/service-patch.yaml new file mode 100644 index 0000000000..7c4f062e85 --- /dev/null +++ b/manifests/overlays/service-mesh/patches/service-patch.yaml @@ -0,0 +1,9 @@ +- op: remove + path: /metadata/annotations + +- op: replace + path: /spec/ports/0 + value: + protocol: TCP + targetPort: 8080 + port: 80