Skip to content

Commit

Permalink
Add support for adding dynamic storage providers for a Deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
bipuladh committed Apr 15, 2021
1 parent 68f91a8 commit 48b0be2
Show file tree
Hide file tree
Showing 16 changed files with 836 additions and 584 deletions.
7 changes: 7 additions & 0 deletions frontend/packages/ceph-storage-plugin/console-extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,12 @@
"flags": {
"required": ["OCS"]
}
},
{
"type": "console.storage-provider",
"properties": {
"name": "ObjectBucketClaim",
"Component": { "$codeRef": "storageProvider" }
}
}
]
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
{
"Troubleshoot": "Troubleshoot",
"Add Capacity": "Add Capacity",
"Use existing claim": "Use existing claim",
"Select claim": "Select claim",
"Create new claim": "Create new claim",
"Create": "Create",
"Cancel": "Cancel",
"{{replica}} Replication": "{{replica}} Replication",
"Pool name": "Pool name",
"my-block-pool": "my-block-pool",
Expand All @@ -18,8 +23,6 @@
"Pool creation is not supported for openshift container storage external mode.": "Pool creation is not supported for openshift container storage external mode.",
"A block pool is a logical entity providing elastic capacity to applications and workloads. Pools provide a means of supporting policies for access data resilience and storage efficiency.": "A block pool is a logical entity providing elastic capacity to applications and workloads. Pools provide a means of supporting policies for access data resilience and storage efficiency.",
"Block Pool Creation Form": "Block Pool Creation Form",
"Create": "Create",
"Cancel": "Cancel",
"Name": "Name",
"Bucket Name": "Bucket Name",
"Type": "Type",
Expand Down Expand Up @@ -343,16 +346,14 @@
"Switch to Credentials": "Switch to Credentials",
"Access Key Field": "Access Key Field",
"Secret Key Field": "Secret Key Field",
"Type: Namespace | Policy: {{policyType}}": "Type: Namespace | Policy: {{policyType}}",
"Type: Standard | Tiers: {{tiers}}": "Type: Standard | Tiers: {{tiers}}",
"Create Object Bucket Claim": "Create Object Bucket Claim",
"Edit YAML": "Edit YAML",
" Object Bucket Claim Name": " Object Bucket Claim Name",
" ObjectBucketClaim Name": " ObjectBucketClaim Name",
"my-object-bucket": "my-object-bucket",
"If not provided a generic name will be generated.": "If not provided a generic name will be generated.",
"Defines the object-store service and the bucket provisioner.": "Defines the object-store service and the bucket provisioner.",
"BucketClass": "BucketClass",
"Select BucketClass": "Select BucketClass",
"Create ObjectBucketClaim": "Create ObjectBucketClaim",
"Edit YAML": "Edit YAML",
"Attach to Deployment": "Attach to Deployment",
"Object Bucket Claim Details": "Object Bucket Claim Details",
"Object Bucket": "Object Bucket",
Expand Down
3 changes: 2 additions & 1 deletion frontend/packages/ceph-storage-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
]
},
"exposedModules": {
"alert": "./src/utils/alert-action-path.tsx"
"alert": "./src/utils/alert-action-path.tsx",
"storageProvider": "./src/components/attach-obc/attach-obc-deployment.tsx"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.ceph-attach-obc__subgroup {
margin-left: var(--pf-global--spacer--md);
margin-top: var(--pf-global--spacer--md);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { match as Match } from 'react-router';
import { History } from 'history';
import {
ListDropdown,
resourceObjPath,
ButtonBar,
LoadingBox,
} from '@console/internal/components/utils';
import {
K8sKind,
referenceForModel,
k8sCreate,
k8sPatch,
DeploymentKind,
referenceFor,
} from '@console/internal/module/k8s/';
import { Form, FormGroup, Radio, ActionGroup, Button } from '@patternfly/react-core';
import { useK8sGet } from '@console/internal/components/utils/k8s-get-hook';
import { getName } from '@console/shared';
import { NooBaaObjectBucketClaimModel } from '../../models';
import { CreateOBCForm } from '../object-bucket-claim-page/create-obc';
import { commonReducer, defaultState } from '../object-bucket-page/state';
import { getAttachOBCPatch } from '../../utils';
import './attach-obc-deployment.scss';

const AttachStorage: React.FC<AttachStorageProps> = (props) => {
const { t } = useTranslation();
const [state, dispatch] = React.useReducer(commonReducer, defaultState);
const [createOBC, setCreateOBC] = React.useState(false);
const [selectedOBC, setSelectedOBC] = React.useState('');
const { kindObj, namespace, resourceName, history } = props;

const [deployment, loaded, loadError] = useK8sGet<DeploymentKind>(
kindObj,
resourceName,
namespace,
);

const onSubmit = async (e: { preventDefault: () => void }) => {
e.preventDefault();
try {
let obc = selectedOBC;
if (createOBC) {
dispatch({ type: 'setProgress' });
const obj = await k8sCreate(NooBaaObjectBucketClaimModel, state.payload);
obc = getName(obj);
}
const patch = getAttachOBCPatch(obc, deployment);
const patchedObj = await k8sPatch(kindObj, deployment, patch);
dispatch({ type: 'unsetProgress' });
history.push(`${resourceObjPath(patchedObj, referenceFor(patchedObj))}/environment`);
} catch (err) {
dispatch({ type: 'unsetProgress' });
dispatch({ type: 'setError', message: err.message });
}
};

const onRadioToggle = () => setCreateOBC((val) => !val);

return (
<Form onSubmit={onSubmit} className="co-m-pane__body-group co-m-pane__form">
<FormGroup fieldId="exists" label="ObjectBucketClaim" isRequired>
<Radio
label={t('ceph-storage-plugin~Use existing claim')}
value="exists"
key="exists"
onChange={onRadioToggle}
id="exists"
name="exists"
isChecked={!createOBC}
/>
{!createOBC && (
<div className="ceph-attach-obc__subgroup">
<ListDropdown
resources={[{ kind: referenceForModel(NooBaaObjectBucketClaimModel), namespace }]}
selectedKeyKind={referenceForModel(NooBaaObjectBucketClaimModel)}
placeholder={t('ceph-storage-plugin~Select claim')}
selectedKey={selectedOBC}
onChange={(item) => setSelectedOBC(item)}
/>
</div>
)}
</FormGroup>
<FormGroup fieldId="create">
<Radio
label={t('ceph-storage-plugin~Create new claim')}
value="create"
key="create"
onChange={onRadioToggle}
id="create"
name="create"
isChecked={createOBC}
/>
{createOBC && (
<div className="ceph-attach-obc__subgroup">
<CreateOBCForm state={state} dispatch={dispatch} namespace={namespace} />
</div>
)}
</FormGroup>
<ButtonBar errorMessage={state.error || loadError?.message} inProgress={state.progress}>
<ActionGroup className="pf-c-form">
<Button type="submit" variant="primary" disabled={loadError || !loaded}>
{t('ceph-storage-plugin~Create')}
</Button>
<Button onClick={history.goBack} type="button" variant="secondary">
{t('ceph-storage-plugin~Cancel')}
</Button>
</ActionGroup>
</ButtonBar>
</Form>
);
};

const AttachStorageWrapper: React.FC<AttachStorageWrapperProps> = (props) => {
const {
kindObj,
kindsInFlight,
match: { params },
} = props;
return !kindObj && kindsInFlight ? (
<LoadingBox />
) : (
<AttachStorage namespace={params.ns} resourceName={params.name} {...props} />
);
};

type AttachStorageWrapperProps = {
kindObj: K8sKind;
kindsInFlight: any;
match?: Match<{ ns: string; name: string }>;
history: History;
};

type AttachStorageProps = AttachStorageWrapperProps & {
namespace: string;
resourceName: string;
};

export default AttachStorageWrapper;
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,18 @@ import {
} from '@console/internal/components/utils';
import { DeploymentModel } from '@console/internal/models';
import {
ContainerSpec,
K8sKind,
k8sPatch,
K8sResourceKind,
referenceFor,
DeploymentKind,
} from '@console/internal/module/k8s/';
import { getName } from '@console/shared';
import { getAttachOBCPatch } from '../../utils';

const AttachDeploymentToOBCModal = withHandlePromise((props: AttachDeploymentToOBCModalProps) => {
const { t } = useTranslation();
const [requestDeployment, setRequestedDeployment] = React.useState({});
const [requestDeployment, setRequestedDeployment] = React.useState<DeploymentKind>(null);
const [deploymentObjects, setDeployments] = React.useState({});
const [deploymentNames, setDeploymentNames] = React.useState({});
const { handlePromise, close, cancel, resource, deployments } = props;
Expand All @@ -54,56 +55,10 @@ const AttachDeploymentToOBCModal = withHandlePromise((props: AttachDeploymentToO
setDeploymentNames(deploymentNameList);
}, [deploymentData, deployments]);

const getPatches = () => {
const configMapRef = {
configMapRef: {
name: obcName,
},
};
const secretMapRef = {
secretRef: {
name: obcName,
},
};

const containers: ContainerSpec[] = _.get(
requestDeployment,
'spec.template.spec.containers',
[],
);
const patches = containers.reduce((patch, container, i) => {
if (_.isEmpty(container.envFrom)) {
patch.push({
op: 'add',
path: `/spec/template/spec/containers/${i}/envFrom`,
value: [configMapRef],
});
patch.push({
op: 'add',
path: `/spec/template/spec/containers/${i}/envFrom/-`,
value: secretMapRef,
});
} else {
patch.push({
op: 'add',
path: `/spec/template/spec/containers/${i}/envFrom/-`,
value: configMapRef,
});
patch.push({
op: 'add',
path: `/spec/template/spec/containers/${i}/envFrom/-`,
value: secretMapRef,
});
}
return patch;
}, []);
return patches;
};

const submit: React.FormEventHandler<HTMLFormElement> = (e) => {
e.preventDefault();
handlePromise(
k8sPatch(DeploymentModel, requestDeployment, getPatches()),
k8sPatch(DeploymentModel, requestDeployment, getAttachOBCPatch(obcName, requestDeployment)),
(res) => {
history.push(`${resourceObjPath(res, referenceFor(res))}/environment`);
close();
Expand Down
Loading

0 comments on commit 48b0be2

Please sign in to comment.