Skip to content

Commit

Permalink
Merge branch 'opendatahub-io:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
yzhao583 authored Aug 7, 2024
2 parents 0a97a7e + d83304c commit eee94ce
Show file tree
Hide file tree
Showing 75 changed files with 5,117 additions and 1,318 deletions.
1 change: 0 additions & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

Self checklist (all need to be checked):
- [ ] The developer has manually tested the changes and verified that the changes work
- [ ] Commits have been squashed into descriptive, self-contained units of work (e.g. 'WIP' and 'Implements feedback' style messages have been removed)
- [ ] Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
- [ ] The developer has added tests or explained why testing cannot be added (unit or cypress tests for related changes)

Expand Down
190 changes: 190 additions & 0 deletions backend/src/routes/api/connection-types/connectionTypeUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { PatchUtils, V1ConfigMap } from '@kubernetes/client-node';
import { KnownLabels, KubeFastifyInstance, RecursivePartial } from '../../../types';
import { getNamespaces } from '../../../utils/notebookUtils';
import { errorHandler } from '../../../utils';

const isConnectionTypeConfigMap = (configMap: V1ConfigMap): boolean =>
configMap.metadata.labels &&
configMap.metadata.labels[KnownLabels.DASHBOARD_RESOURCE] === 'true' &&
configMap.metadata.labels[KnownLabels.CONNECTION_TYPE] === 'true';

const isExistingConnectionType = async (
fastify: KubeFastifyInstance,
name: string,
): Promise<boolean> => {
const coreV1Api = fastify.kube.coreV1Api;
const { dashboardNamespace } = getNamespaces(fastify);

const response = await coreV1Api.readNamespacedConfigMap(name, dashboardNamespace);
return isConnectionTypeConfigMap(response.body);
};

export const listConnectionTypes = async (fastify: KubeFastifyInstance): Promise<V1ConfigMap[]> => {
const { dashboardNamespace } = getNamespaces(fastify);
const coreV1Api = fastify.kube.coreV1Api;
const connectionTypes: V1ConfigMap[] = [];

let _continue: string = undefined;
let remainingItemCount = 1;
try {
while (remainingItemCount) {
const response = await coreV1Api.listNamespacedConfigMap(
dashboardNamespace,
undefined,
undefined,
_continue,
undefined,
`${KnownLabels.DASHBOARD_RESOURCE} = true, ${KnownLabels.CONNECTION_TYPE} = true`,
);
connectionTypes.push(...(response?.body?.items ?? []));
remainingItemCount = response?.body.metadata?.remainingItemCount;
_continue = response?.body.metadata?._continue;
}
return connectionTypes;
} catch (e) {
fastify.log.error(`Error fetching configmaps for connection types: `, e);
throw new Error(`Failed to list connection types: ${errorHandler(e)}.`);
}
};

export const getConnectionType = async (
fastify: KubeFastifyInstance,
name: string,
): Promise<V1ConfigMap> => {
const { dashboardNamespace } = getNamespaces(fastify);
const coreV1Api = fastify.kube.coreV1Api;
try {
const response = await coreV1Api.readNamespacedConfigMap(name, dashboardNamespace);
if (!isConnectionTypeConfigMap(response.body)) {
throw new Error(`object is not a connection type.`);
}
return response.body;
} catch (e) {
fastify.log.error(`Error fetching connection type: `, e);
throw new Error(`Failed to get connection type: ${errorHandler(e)}.`);
}
};

export const createConnectionType = async (
fastify: KubeFastifyInstance,
connectionType: V1ConfigMap,
): Promise<{ success: boolean; error: string }> => {
const coreV1Api = fastify.kube.coreV1Api;
const { dashboardNamespace } = getNamespaces(fastify);

if (!isConnectionTypeConfigMap(connectionType)) {
const error = 'Unable to add connection type, incorrect labels.';
fastify.log.error(error);
return { success: false, error };
}

try {
await coreV1Api.createNamespacedConfigMap(dashboardNamespace, connectionType);
return { success: true, error: '' };
} catch (e) {
const error = `Unable to add connection type: ${errorHandler(e)}.`;
fastify.log.error(error);
return { success: false, error };
}
};

export const updateConnectionType = async (
fastify: KubeFastifyInstance,
name: string,
connectionType: V1ConfigMap,
): Promise<{ success: boolean; error: string }> => {
const coreV1Api = fastify.kube.coreV1Api;
const { dashboardNamespace } = getNamespaces(fastify);

if (!isConnectionTypeConfigMap(connectionType)) {
const error = 'Unable to add connection type, incorrect labels.';
fastify.log.error(error);
return { success: false, error };
}

try {
const validConnectionType = await isExistingConnectionType(fastify, name);
if (!validConnectionType) {
const error = `Unable to update connection type, object is not a connection type`;
fastify.log.error(error);
return { success: false, error };
}

await coreV1Api.replaceNamespacedConfigMap(name, dashboardNamespace, connectionType);
return { success: true, error: '' };
} catch (e) {
const error = `Unable to update connection type: ${errorHandler(e)}.`;
fastify.log.error(error);
return { success: false, error };
}
};

export const patchConnectionType = async (
fastify: KubeFastifyInstance,
name: string,
partialConfigMap: RecursivePartial<V1ConfigMap>,
): Promise<{ success: boolean; error: string }> => {
const coreV1Api = fastify.kube.coreV1Api;
const { dashboardNamespace } = getNamespaces(fastify);

if (
(partialConfigMap.metadata.labels?.[KnownLabels.DASHBOARD_RESOURCE] &&
partialConfigMap.metadata.labels[KnownLabels.DASHBOARD_RESOURCE] !== 'true') ||
(partialConfigMap.metadata.labels?.[KnownLabels.CONNECTION_TYPE] &&
partialConfigMap.metadata.labels[KnownLabels.CONNECTION_TYPE] !== 'true')
) {
const error = 'Unable to update connection type, incorrect labels.';
fastify.log.error(error);
return { success: false, error };
}

try {
const validConnectionType = await isExistingConnectionType(fastify, name);
if (!validConnectionType) {
const error = `Unable to update connection type, object is not a connection type`;
fastify.log.error(error);
return { success: false, error };
}
const options = {
headers: { 'Content-type': PatchUtils.PATCH_FORMAT_JSON_PATCH },
};

await coreV1Api.patchNamespacedConfigMap(
name,
dashboardNamespace,
partialConfigMap,
undefined,
undefined,
undefined,
undefined,
options,
);
return { success: true, error: '' };
} catch (e) {
const error = `Unable to update connection type: ${errorHandler(e)}.`;
fastify.log.error(error);
return { success: false, error };
}
};

export const deleteConnectionType = async (
fastify: KubeFastifyInstance,
name: string,
): Promise<{ success: boolean; error: string }> => {
const { dashboardNamespace } = getNamespaces(fastify);
const coreV1Api = fastify.kube.coreV1Api;
try {
const validConnectionType = await isExistingConnectionType(fastify, name);
if (!validConnectionType) {
const error = `Unable to delete connection type, object is not a connection type`;
fastify.log.error(error);
return { success: false, error };
}
await coreV1Api.deleteNamespacedConfigMap(name, dashboardNamespace);
return { success: true, error: '' };
} catch (e) {
const error = `Unable to delete connection type: ${errorHandler(e)}.`;
fastify.log.error(error);
return { success: false, error };
}
};
91 changes: 91 additions & 0 deletions backend/src/routes/api/connection-types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { V1ConfigMap } from '@kubernetes/client-node';
import { FastifyReply, FastifyRequest } from 'fastify';
import { KubeFastifyInstance, RecursivePartial } from '../../../types';
import { secureAdminRoute } from '../../../utils/route-security';
import {
getConnectionType,
listConnectionTypes,
createConnectionType,
updateConnectionType,
patchConnectionType,
deleteConnectionType,
} from './connectionTypeUtils';

module.exports = async (fastify: KubeFastifyInstance) => {
fastify.get(
'/',
secureAdminRoute(fastify)(async (request: FastifyRequest, reply: FastifyReply) =>
listConnectionTypes(fastify)
.then((res) => res)
.catch((res) => {
reply.send(res);
}),
),
);

fastify.get(
'/:name',
secureAdminRoute(fastify)(
async (request: FastifyRequest<{ Params: { name: string } }>, reply: FastifyReply) =>
getConnectionType(fastify, request.params.name)
.then((res) => res)
.catch((res) => {
reply.send(res);
}),
),
);

fastify.post(
'/',
secureAdminRoute(fastify)(
async (request: FastifyRequest<{ Body: V1ConfigMap }>, reply: FastifyReply) =>
createConnectionType(fastify, request.body)
.then((res) => res)
.catch((res) => {
reply.send(res);
}),
),
);

fastify.put(
'/:name',
secureAdminRoute(fastify)(
async (
request: FastifyRequest<{ Params: { name: string }; Body: V1ConfigMap }>,
reply: FastifyReply,
) =>
updateConnectionType(fastify, request.params.name, request.body)
.then((res) => res)
.catch((res) => {
reply.send(res);
}),
),
);

fastify.patch(
'/:name',
secureAdminRoute(fastify)(
async (
request: FastifyRequest<{ Params: { name: string }; Body: RecursivePartial<V1ConfigMap> }>,
reply: FastifyReply,
) =>
patchConnectionType(fastify, request.params.name, request.body)
.then((res) => res)
.catch((res) => {
reply.send(res);
}),
),
);

fastify.delete(
'/:name',
secureAdminRoute(fastify)(
async (request: FastifyRequest<{ Params: { name: string } }>, reply: FastifyReply) =>
deleteConnectionType(fastify, request.params.name)
.then((res) => res)
.catch((res) => {
reply.send(res);
}),
),
);
};
1 change: 1 addition & 0 deletions backend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,7 @@ export enum KnownLabels {
PROJECT_SHARING = 'opendatahub.io/project-sharing',
MODEL_SERVING_PROJECT = 'modelmesh-enabled',
DATA_CONNECTION_AWS = 'opendatahub.io/managed',
CONNECTION_TYPE = 'opendatahub.io/connection-type',
}

type ComponentNames =
Expand Down
Loading

0 comments on commit eee94ce

Please sign in to comment.