Skip to content

Commit

Permalink
Update pipelineServer
Browse files Browse the repository at this point in the history
  • Loading branch information
pnaik1 committed Oct 25, 2023
1 parent fe4bcd9 commit 7d9492b
Show file tree
Hide file tree
Showing 11 changed files with 327 additions and 264 deletions.
2 changes: 1 addition & 1 deletion frontend/src/components/FieldList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type InputFieldProps = {
value: string;
};

const FieldListField = ({ options, onChange, value }: InputFieldProps) => {
export const FieldListField = ({ options, onChange, value }: InputFieldProps) => {
const ComponentField = options.isPassword ? PasswordInput : TextInput;

return (
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/concepts/pipelines/NoPipelineServer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ const NoPipelineServer: React.FC<NoPipelineServerProps> = ({ variant }) => (
<EmptyState>
<EmptyStateIcon icon={WrenchIcon} />
<Title headingLevel="h2" size="lg">
No pipeline server
Enable pipelines
</Title>
<EmptyStateBody>To import a pipeline, first create a pipeline server.</EmptyStateBody>
<EmptyStateBody>
To create and manage pipelines, first enable them by configuring a pipeline server
</EmptyStateBody>
<Flex direction={{ default: 'column' }}>
<FlexItem spacer={{ default: 'spacerLg' }} />
<FlexItem>
Expand Down
49 changes: 10 additions & 39 deletions frontend/src/concepts/pipelines/content/ViewPipelineServerModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,10 @@ import {
} from '@patternfly/react-core';
import { usePipelinesAPI } from '~/concepts/pipelines/context';
import PasswordHiddenText from '~/components/PasswordHiddenText';
import useDataConnections from '~/pages/projects/screens/detail/data-connections/useDataConnections';
import { DataConnection } from '~/pages/projects/types';
import { useContextResourceData } from '~/utilities/useContextResourceData';
import {
convertAWSSecretData,
getDataConnectionDisplayName,
} from '~/pages/projects/screens/detail/data-connections/utils';
import { dataEntryToRecord } from '~/utilities/dataEntryToRecord';
import { AWS_KEYS } from '~/pages/projects/dataConnections/const';
import useNamespaceSecret from '~/concepts/projects/apiHooks/useNamespaceSecret';
import { EXTERNAL_DATABASE_SECRET } from '~/concepts/pipelines/content/configurePipelinesServer/const';
import { DSPipelineKind } from '~/k8sTypes';

type ViewPipelineServerModalProps = {
isOpen: boolean;
onClose: () => void;
Expand All @@ -35,22 +26,14 @@ const ViewPipelineServerModal: React.FC<ViewPipelineServerModalProps> = ({
pipelineNamespaceCR,
}) => {
const { namespace } = usePipelinesAPI();
const { data: dataConnections } = useContextResourceData<DataConnection>(
useDataConnections(namespace),
const [pipelineResult] = useNamespaceSecret(
namespace,
pipelineNamespaceCR?.spec.objectStorage.externalStorage?.s3CredentialsSecret.secretName ?? '',
);
const pipelineSecret = dataEntryToRecord(pipelineResult?.values?.data ?? []);
const [result] = useNamespaceSecret(namespace, EXTERNAL_DATABASE_SECRET.NAME);
const databaseSecret = dataEntryToRecord(result?.values?.data ?? []);

const objectStorageDataConnection = dataConnections.find(
(dc) =>
dc.data.metadata.name ===
pipelineNamespaceCR?.spec.objectStorage?.externalStorage?.s3CredentialsSecret?.secretName,
);

const objectStorageRecord: Partial<Record<AWS_KEYS, string>> = objectStorageDataConnection
? dataEntryToRecord(convertAWSSecretData(objectStorageDataConnection))
: {};

return (
<Modal
title="View pipeline server"
Expand All @@ -65,30 +48,22 @@ const ViewPipelineServerModal: React.FC<ViewPipelineServerModalProps> = ({
>
{pipelineNamespaceCR && (
<DescriptionList termWidth="20ch" isHorizontal>
{!!objectStorageDataConnection &&
!!pipelineNamespaceCR?.spec.objectStorage?.externalStorage &&
!!objectStorageRecord && (
{!!pipelineNamespaceCR.spec.objectStorage &&
!!pipelineNamespaceCR.spec.objectStorage.externalStorage &&
!!pipelineNamespaceCR.spec.objectStorage.externalStorage.s3CredentialsSecret
.secretName && (
<>
<Title headingLevel="h2">Object storage connection</Title>
<DescriptionListGroup>
{/* TODO: is this the pipeline name or the secret name? */}
<DescriptionListTerm>Name</DescriptionListTerm>
<DescriptionListDescription>
{getDataConnectionDisplayName(objectStorageDataConnection)}
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
<DescriptionListTerm>Access key</DescriptionListTerm>
<DescriptionListDescription>
{objectStorageRecord?.AWS_ACCESS_KEY_ID}
{pipelineSecret?.AWS_ACCESS_KEY_ID || ''}
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
<DescriptionListTerm>Secret key</DescriptionListTerm>
<DescriptionListDescription>
<PasswordHiddenText
password={objectStorageRecord?.AWS_SECRET_ACCESS_KEY ?? ''}
/>
<PasswordHiddenText password={pipelineSecret?.AWS_SECRET_ACCESS_KEY ?? ''} />
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
Expand All @@ -106,10 +81,6 @@ const ViewPipelineServerModal: React.FC<ViewPipelineServerModalProps> = ({
{pipelineNamespaceCR.spec.objectStorage.externalStorage?.bucket}
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
<DescriptionListTerm>Folder path</DescriptionListTerm>
<DescriptionListDescription>/pipelines</DescriptionListDescription>
</DescriptionListGroup>
</>
)}
{!!pipelineNamespaceCR?.spec.database &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import * as React from 'react';
import { Alert, Button, Form, Modal, Stack, StackItem } from '@patternfly/react-core';
import { EMPTY_AWS_SECRET_DATA } from '~/pages/projects/dataConnections/const';
import './ConfigurePipelinesServerModal.scss';
import { convertAWSSecretData } from '~/pages/projects/screens/detail/data-connections/utils';
import { usePipelinesAPI } from '~/concepts/pipelines/context';
import { isAWSValid } from '~/pages/projects/screens/spawner/spawnerUtils';
import { createPipelinesCR, deleteSecret } from '~/api';
import useDataConnections from '~/pages/projects/screens/detail/data-connections/useDataConnections';
import { EMPTY_AWS_PIPELINE_DATA } from '~/pages/projects/dataConnections/const';
import { PipelinesDatabaseSection } from './PipelinesDatabaseSection';
import { ObjectStorageSection } from './ObjectStorageSection';
import {
Expand All @@ -15,7 +13,8 @@ import {
EMPTY_DATABASE_CONNECTION,
EXTERNAL_DATABASE_SECRET,
} from './const';
import { configureDSPipelineResourceSpec } from './utils';

import { configureDSPipelineResourceSpec, objectStorageIsValid } from './utils';
import { PipelineServerConfigType } from './types';

type ConfigurePipelinesServerModalProps = {
Expand All @@ -25,15 +24,15 @@ type ConfigurePipelinesServerModalProps = {

const FORM_DEFAULTS: PipelineServerConfigType = {
database: { useDefault: true, value: EMPTY_DATABASE_CONNECTION },
objectStorage: { useExisting: true, existingName: '', existingValue: EMPTY_AWS_SECRET_DATA },
objectStorage: { newValue: EMPTY_AWS_PIPELINE_DATA },
};

export const ConfigurePipelinesServerModal: React.FC<ConfigurePipelinesServerModalProps> = ({
onClose,
open,
}) => {
const { project, namespace } = usePipelinesAPI();
const [dataConnections, , , refresh] = useDataConnections(namespace);
const [dataConnections, loaded, , refresh] = useDataConnections(namespace);
const [fetching, setFetching] = React.useState(false);
const [error, setError] = React.useState<Error | null>(null);
const [config, setConfig] = React.useState<PipelineServerConfigType>(FORM_DEFAULTS);
Expand All @@ -44,23 +43,18 @@ export const ConfigurePipelinesServerModal: React.FC<ConfigurePipelinesServerMod
}
}, [open, refresh]);

const canSubmit = () => {
const databaseIsValid = config.database.useDefault
? true
: config.database.value.every(({ key, value }) =>
DATABASE_CONNECTION_FIELDS.filter((field) => field.isRequired)
.map((field) => field.key)
.includes(key as DATABASE_CONNECTION_KEYS)
? !!value
: true,
);

const objectStorageIsValid = config.objectStorage.useExisting
? !!config.objectStorage.existingName
: isAWSValid(config.objectStorage.newValue);
const databaseIsValid = config.database.useDefault
? true
: config.database.value.every(({ key, value }) =>
DATABASE_CONNECTION_FIELDS.filter((field) => field.isRequired)
.map((field) => field.key)
.includes(key as DATABASE_CONNECTION_KEYS)
? !!value
: true,
);

return databaseIsValid && objectStorageIsValid;
};
const objectIsValid = objectStorageIsValid(config.objectStorage.newValue);
const canSubmit = databaseIsValid && objectIsValid;

const onBeforeClose = () => {
onClose();
Expand All @@ -70,25 +64,9 @@ export const ConfigurePipelinesServerModal: React.FC<ConfigurePipelinesServerMod
};

const submit = () => {
let objectStorage: PipelineServerConfigType['objectStorage'];
if (config.objectStorage.useExisting) {
const existingName = config.objectStorage.existingName;
const existingValue = dataConnections?.find((dc) => dc.data.metadata.name === existingName);
if (existingValue) {
objectStorage = {
existingValue: convertAWSSecretData(existingValue),
existingName,
useExisting: true,
};
} else {
throw new Error('Selected data connection does not exist');
}
} else {
objectStorage = {
newValue: config.objectStorage.newValue,
useExisting: false,
};
}
const objectStorage: PipelineServerConfigType['objectStorage'] = {
newValue: config.objectStorage.newValue,
};
setFetching(true);
setError(null);

Expand Down Expand Up @@ -121,24 +99,32 @@ export const ConfigurePipelinesServerModal: React.FC<ConfigurePipelinesServerMod
<Modal
title="Configure pipeline server"
variant="medium"
description="Configuring a pipeline server enables you to create and manage pipelines."
isOpen={open}
onClose={onBeforeClose}
actions={[
<Button
key="configure"
variant="primary"
isDisabled={!canSubmit() || fetching}
isDisabled={!canSubmit || fetching}
isLoading={fetching}
onClick={submit}
>
Configure
Configure pipeline server
</Button>,
<Button key="cancel" variant="link" onClick={onBeforeClose}>
Cancel
</Button>,
]}
>
<Stack hasGutter>
<StackItem>
<Alert
variant="info"
isInline
title="Pipeline server configuration cannot be edited after creation. To use a different configuration after creation, delete the pipeline server and create a new one."
/>
</StackItem>
<StackItem>
<Form
onSubmit={(e) => {
Expand All @@ -149,6 +135,7 @@ export const ConfigurePipelinesServerModal: React.FC<ConfigurePipelinesServerMod
<ObjectStorageSection
setConfig={setConfig}
config={config}
loaded={loaded}
dataConnections={dataConnections}
/>
<PipelinesDatabaseSection setConfig={setConfig} config={config} />
Expand Down
Loading

0 comments on commit 7d9492b

Please sign in to comment.