Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Trusty DB fields #3305

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 10 additions & 16 deletions frontend/src/api/trustyai/k8s.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,6 @@ import { TRUSTYAI_DEFINITION_NAME } from '~/concepts/trustyai/const';
import { applyK8sAPIOptions } from '~/api/apiMergeUtils';
import { TrustyAIApplicationsModel } from '~/api/models/trustyai';

const trustyAIDefaultCRSpec: TrustyAIKind['spec'] = {
storage: {
format: 'PVC',
folder: '/inputs',
size: '1Gi',
},
data: {
filename: 'data.csv',
format: 'CSV',
},
metrics: {
schedule: '5s',
},
};

export const getTrustyAICR = async (
namespace: string,
opts?: K8sAPIOptions,
Expand All @@ -43,6 +28,7 @@ export const getTrustyAICR = async (

export const createTrustyAICR = async (
namespace: string,
secretName: string,
opts?: K8sAPIOptions,
): Promise<TrustyAIKind> => {
const resource: TrustyAIKind = {
Expand All @@ -52,7 +38,15 @@ export const createTrustyAICR = async (
name: TRUSTYAI_DEFINITION_NAME,
namespace,
},
spec: trustyAIDefaultCRSpec,
spec: {
storage: {
format: 'DATABASE',
databaseConfigurations: secretName,
},
metrics: {
schedule: '5s',
},
},
};

return k8sCreateResource<TrustyAIKind>(
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/components/FieldGroupHelpLabelIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from 'react';
import { Popover } from '@patternfly/react-core';
import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
import DashboardPopupIconButton from '~/concepts/dashboard/DashboardPopupIconButton';

type FieldGroupHelpLabelIconProps = {
content: React.ComponentProps<typeof Popover>['bodyContent'];
};

const FieldGroupHelpLabelIcon: React.FC<FieldGroupHelpLabelIconProps> = ({ content }) => (
<Popover bodyContent={content}>
<DashboardPopupIconButton icon={<OutlinedQuestionCircleIcon />} aria-label="More info" />
</Popover>
);

export default FieldGroupHelpLabelIcon;
13 changes: 5 additions & 8 deletions frontend/src/concepts/k8s/ResourceNameDefinitionTooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import * as React from 'react';
import { Popover, Stack, StackItem } from '@patternfly/react-core';
import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
import DashboardPopupIconButton from '~/concepts/dashboard/DashboardPopupIconButton';
import { Stack, StackItem } from '@patternfly/react-core';
import FieldGroupHelpLabelIcon from '~/components/FieldGroupHelpLabelIcon';

const ResourceNameDefinitionTooltip: React.FC = () => (
<Popover
bodyContent={
<FieldGroupHelpLabelIcon
content={
<Stack hasGutter>
<StackItem>Resource names are what your resources are labeled in OpenShift.</StackItem>
<StackItem>Resource names are not editable after creation.</StackItem>
</Stack>
}
>
<DashboardPopupIconButton icon={<OutlinedQuestionCircleIcon />} aria-label="More info" />
</Popover>
/>
);

export default ResourceNameDefinitionTooltip;
15 changes: 14 additions & 1 deletion frontend/src/concepts/k8s/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { K8sResourceCommon } from '@openshift/dynamic-plugin-sdk-utils';
import { K8sDSGResource } from '~/k8sTypes';
import { K8sCondition, K8sDSGResource } from '~/k8sTypes';
import { genRandomChars } from '~/utilities/string';

export const PreInstalledName = 'Pre-installed';
Expand Down Expand Up @@ -108,3 +108,16 @@ export const translateDisplayNameForK8s = (

export const isValidK8sName = (name?: string): boolean =>
name === undefined || (name.length > 0 && /^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/.test(name));

type ResourceWithConditions = K8sResourceCommon & { status?: { conditions?: K8sCondition[] } };

export const getConditionForType = (
resource: ResourceWithConditions,
type: string,
): K8sCondition | undefined => resource.status?.conditions?.find((c) => c.type === type);

export const isConditionInStatus = (
resource: ResourceWithConditions,
type: string,
status: string,
): boolean => getConditionForType(resource, type)?.status === status;
6 changes: 4 additions & 2 deletions frontend/src/concepts/trustyai/const.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const TRUSTYAI_ROUTE_NAME = 'trustyai-service';

export const TRUSTYAI_DEFINITION_NAME = 'trustyai-service';

export const TRUSTYAI_SECRET_NAME = 'trustyai-db-secret';

export const TRUSTYAI_INSTALL_MODAL_TEST_ID = 'trusty-db-config';
62 changes: 0 additions & 62 deletions frontend/src/concepts/trustyai/content/InstallTrustyAICheckbox.tsx

This file was deleted.

110 changes: 110 additions & 0 deletions frontend/src/concepts/trustyai/content/InstallTrustyModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import * as React from 'react';
import { Form, Modal, Radio } from '@patternfly/react-core';
import DashboardModalFooter from '~/concepts/dashboard/DashboardModalFooter';
import TrustyDBSecretFields from '~/concepts/trustyai/content/TrustyDBSecretFields';
import useTrustyInstallModalData, {
TrustyInstallModalFormType,
} from '~/concepts/trustyai/content/useTrustyInstallModalData';
import { UseManageTrustyAICRReturnType } from '~/concepts/trustyai/useManageTrustyAICR';
import FieldGroupHelpLabelIcon from '~/components/FieldGroupHelpLabelIcon';
import TrustyDBExistingSecretField from '~/concepts/trustyai/content/TrustyDBExistingSecretField';

type InstallTrustyModalProps = {
onClose: () => void;
namespace: string;
onInstallExistingDB: UseManageTrustyAICRReturnType['installCRForExistingDB'];
onInstallNewDB: UseManageTrustyAICRReturnType['installCRForNewDB'];
};

const InstallTrustyModal: React.FC<InstallTrustyModalProps> = ({
onClose,
namespace,
onInstallNewDB,
onInstallExistingDB,
}) => {
const [submitting, setSubmitting] = React.useState(false);
const [installError, setInstallError] = React.useState<Error | undefined>();
const formData = useTrustyInstallModalData(namespace);

return (
<Modal
title="Configure TrustyAI service"
isOpen
variant="medium"
onClose={onClose}
footer={
<DashboardModalFooter
onCancel={onClose}
onSubmit={() => {
let promise: Promise<void>;
if (formData.type === TrustyInstallModalFormType.EXISTING) {
promise = onInstallExistingDB(formData.data);
} else {
promise = onInstallNewDB(formData.data);
}
setSubmitting(true);
setInstallError(undefined);
promise
.then(() => {
onClose();
})
.catch((e) => {
setInstallError(e);
})
.finally(() => {
setSubmitting(false);
});
}}
submitLabel="Configure"
isSubmitLoading={submitting}
isSubmitDisabled={!formData.canSubmit || submitting}
error={installError}
alertTitle="Install error"
/>
}
>
<Form
onSubmit={(e) => {
e.preventDefault();
}}
>
<Radio
id="existing"
label={
<>
Specify an existing secret{' '}
<FieldGroupHelpLabelIcon content="Provide the name of an existing Kubernetes secret within your project." />
</>
}
name="secret-value"
isChecked={formData.type === TrustyInstallModalFormType.EXISTING}
onChange={() => formData.onModeChange(TrustyInstallModalFormType.EXISTING)}
body={
formData.type === TrustyInstallModalFormType.EXISTING && (
<TrustyDBExistingSecretField formData={formData} />
)
}
/>
<Radio
id="new"
label={
<>
Create a new secret{' '}
<FieldGroupHelpLabelIcon content="Consult the product documentation for more information on these fields." />
</>
}
name="secret-value"
isChecked={formData.type === TrustyInstallModalFormType.NEW}
onChange={() => formData.onModeChange(TrustyInstallModalFormType.NEW)}
body={
formData.type === TrustyInstallModalFormType.NEW && (
<TrustyDBSecretFields data={formData.data} onDataChange={formData.onDataChange} />
)
}
/>
</Form>
</Modal>
);
};

export default InstallTrustyModal;

This file was deleted.

Loading
Loading