-
Notifications
You must be signed in to change notification settings - Fork 667
Feature: Expand cluster modal #2348
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| @import '~@patternfly/patternfly/sass-utilities/colors'; | ||
|
|
||
| .add-capacity-modal--padding { | ||
| .co-storage-class-dropdown { | ||
| .dropdown { | ||
| width: 20.25rem; | ||
| button { | ||
| width: 100%; | ||
| } | ||
| } | ||
| } | ||
| .form-group input { | ||
| max-width: 15rem; | ||
| margin-right: 5px; | ||
| } | ||
| .toolTip_dropdown { | ||
| button { | ||
| position: absolute; | ||
| left: 7rem; | ||
| top: 8.5rem; | ||
| } | ||
| } | ||
| padding-top: 2em; | ||
| } | ||
|
|
||
| .add-capacity-modal__span { | ||
| margin-left: 3em; | ||
| color: $pf-color-black-500; | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| import * as React from 'react'; | ||
| import * as _ from 'lodash'; | ||
| import { DashboardCardHelp } from '@console/internal/components/dashboard/dashboard-card/card-help'; | ||
| import { RequestSizeInput, withHandlePromise } from '@console/internal/components/utils/index'; | ||
| import { | ||
| createModalLauncher, | ||
| ModalBody, | ||
| ModalSubmitFooter, | ||
| ModalTitle, | ||
| } from '@console/internal/components/factory'; | ||
| import { k8sPatch, K8sResourceKind } from '@console/internal/module/k8s'; | ||
| import { OCSServiceModel } from '../../../models'; | ||
| import './_add-capacity-modal.scss'; | ||
| import { OCSStorageClassDropdown } from '../storage-class-dropdown'; | ||
|
|
||
| export const AddCapacityModal = withHandlePromise((props: AddCapacityModalProps) => { | ||
| const { ocsConfig, close, cancel } = props; | ||
| const dropdownUnits = { | ||
| Ti: 'Ti', | ||
| }; | ||
| const requestSizeUnit = dropdownUnits.Ti; | ||
| const [requestSizeValue, setRequestSizeValue] = React.useState(''); | ||
| const [storageClass, setStorageClass] = React.useState(''); | ||
| const [inProgress, setProgress] = React.useState(false); | ||
| const [errorMessage, setError] = React.useState(''); | ||
| const storageClassTooltip = | ||
| 'The Storage Class will be used to request storage from the underlying infrastructure to create the backing persistent volumes that will be used to provide the OpenShift Container Storage (OCS) service.'; | ||
|
|
||
|
||
| const submit = (event: React.FormEvent<EventTarget>) => { | ||
| event.preventDefault(); | ||
| setProgress(true); | ||
| const presentCapacity = _.get(ocsConfig, 'spec.storageDeviceSets[0].count'); | ||
| const newValue = parseInt(presentCapacity, 10) + parseInt(requestSizeValue, 10) * 3; | ||
| const patch = { | ||
| op: 'replace', | ||
| path: `/spec/storageDeviceSets/0/count`, | ||
| value: newValue, | ||
| }; | ||
| props | ||
| .handlePromise(k8sPatch(OCSServiceModel, ocsConfig, [patch])) | ||
| .then(() => { | ||
| setProgress(false); | ||
| close(); | ||
| }) | ||
| .catch((error) => { | ||
| setError(error); | ||
| setProgress(false); | ||
| throw error; | ||
| }); | ||
| }; | ||
|
|
||
| const handleRequestSizeInputChange = (capacityObj: any) => { | ||
| setRequestSizeValue(capacityObj.value); | ||
| }; | ||
|
|
||
| const handleStorageClass = (sc: K8sResourceKind) => { | ||
| setStorageClass(sc.metadata.name); | ||
| }; | ||
|
|
||
| return ( | ||
| <form onSubmit={submit} className="modal-content modal-content--no-inner-scroll"> | ||
| <ModalTitle>Add Capacity</ModalTitle> | ||
| <ModalBody> | ||
| Increase the capacity of <strong>{ocsConfig.metadata.name}</strong>. | ||
| <div className="add-capacity-modal--padding"> | ||
| <div className="form-group"> | ||
| <label className="control-label" htmlFor="request-size-input"> | ||
| Requested Capacity | ||
| <span className="add-capacity-modal__span"> | ||
| Used:{' '} | ||
| {_.get( | ||
| ocsConfig, | ||
| 'spec.storageDeviceSets[0].dataPVCTemplate.spec.resources.requests.storage', | ||
| )} | ||
| </span> | ||
| </label> | ||
| <RequestSizeInput | ||
| name="requestSize" | ||
| placeholder={requestSizeValue} | ||
| onChange={handleRequestSizeInputChange} | ||
| defaultRequestSizeUnit={requestSizeUnit} | ||
| defaultRequestSizeValue={requestSizeValue} | ||
| dropdownUnits={dropdownUnits} | ||
| required | ||
| /> | ||
| </div> | ||
| <div className="toolTip_dropdown"> | ||
| <DashboardCardHelp>{storageClassTooltip}</DashboardCardHelp> | ||
| </div> | ||
| <OCSStorageClassDropdown | ||
| onChange={handleStorageClass} | ||
| name="storageClass" | ||
| defaultClass={storageClass} | ||
| required | ||
| /> | ||
| </div> | ||
| </ModalBody> | ||
| <ModalSubmitFooter | ||
| inProgress={inProgress} | ||
| errorMessage={errorMessage} | ||
| submitText="Add" | ||
| cancel={cancel} | ||
| /> | ||
| </form> | ||
| ); | ||
| }); | ||
|
|
||
| export type AddCapacityModalProps = { | ||
| kind?: any; | ||
| ocsConfig?: any; | ||
| handlePromise: <T>(promise: Promise<T>) => Promise<T>; | ||
| cancel?: () => void; | ||
| close?: () => void; | ||
| }; | ||
|
|
||
|
||
| export const addCapacityModal = createModalLauncher(AddCapacityModal); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import * as React from 'react'; | ||
| import * as _ from 'lodash'; | ||
| import { Firehose } from '@console/internal/components/utils'; | ||
| import { StorageClassDropdownInner } from '@console/internal/components/utils/storage-class-dropdown'; | ||
| import { K8sResourceKind } from '@console/internal/module/k8s'; | ||
|
|
||
| const cephStorageProvisioners = ['ceph.rook.io/block', 'cephfs.csi.ceph.com', 'rbd.csi.ceph.com']; | ||
|
|
||
| export const OCSStorageClassDropdown: React.FC<OCSStorageClassDropdownProps> = (props) => ( | ||
| <Firehose resources={[{ kind: 'StorageClass', prop: 'StorageClass', isList: true }]}> | ||
| <StorageClassDropdown {...props} /> | ||
| </Firehose> | ||
| ); | ||
|
|
||
| const StorageClassDropdown = (props: any) => { | ||
| const scConfig = _.cloneDeep(props); | ||
| /* 'S' of Storage should be Capital as its defined key in resourses object */ | ||
| const scLoaded = _.get(scConfig.resources.StorageClass, 'loaded'); | ||
| const scData = _.get(scConfig.resources.StorageClass, 'data', []) as K8sResourceKind[]; | ||
|
|
||
| const filteredSCData = scData.filter((sc: K8sResourceKind) => { | ||
| return cephStorageProvisioners.every( | ||
| (provisioner: string) => !_.get(sc, 'provisioner').includes(provisioner), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure you want
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @spadgett right now provisioners are coming in the form of
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I see. The storage stuff is not in my wheelhouse :) |
||
| ); | ||
| }); | ||
|
|
||
| if (scLoaded) { | ||
| scConfig.resources.StorageClass.data = filteredSCData; | ||
| } | ||
|
|
||
| return <StorageClassDropdownInner {...scConfig} />; | ||
| }; | ||
|
|
||
| type OCSStorageClassDropdownProps = { | ||
| id?: string; | ||
| loaded?: boolean; | ||
| resources?: any; | ||
| name: string; | ||
| onChange: (object) => void; | ||
| describedBy?: string; | ||
| defaultClass: string; | ||
| required?: boolean; | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ import { | |
| Plugin, | ||
| DashboardsOverviewQuery, | ||
| RoutePage, | ||
| ClusterServiceVersionAction, | ||
| } from '@console/plugin-sdk'; | ||
| import { GridPosition } from '@console/internal/components/dashboard'; | ||
| import { OverviewQuery } from '@console/internal/components/dashboards-page/overview-dashboard/queries'; | ||
|
|
@@ -29,7 +30,8 @@ type ConsumedExtensions = | |
| | DashboardsCard | ||
| | DashboardsOverviewHealthPrometheusSubsystem | ||
| | DashboardsOverviewQuery | ||
| | RoutePage; | ||
| | RoutePage | ||
| | ClusterServiceVersionAction; | ||
|
|
||
| const CEPH_FLAG = 'CEPH'; | ||
| // keeping this for testing, will be removed once ocs operator available | ||
|
|
@@ -196,6 +198,23 @@ const plugin: Plugin<ConsumedExtensions> = [ | |
| required: CEPH_FLAG, | ||
| }, | ||
| }, | ||
| { | ||
| type: 'ClusterServiceVersion/Action', | ||
| properties: { | ||
| kind: 'StorageCluster', | ||
|
||
| label: 'Add Capacity', | ||
| callback: (kind, ocsConfig) => () => { | ||
| const clusterObject = { ocsConfig }; | ||
| import( | ||
| './components/modals/add-capacity-modal/add-capacity-modal' /* webpackChunkName: "ceph-storage-add-capacity-modal" */ | ||
| ) | ||
| .then((m) => m.addCapacityModal(clusterObject)) | ||
| .catch((e) => { | ||
| throw e; | ||
| }); | ||
| }, | ||
| }, | ||
| }, | ||
| ]; | ||
|
|
||
| export default plugin; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { K8sResourceKindReference } from '@console/internal/module/k8s'; | ||
| import { Extension } from './extension'; | ||
|
|
||
| namespace ExtensionProperties { | ||
| export interface ClusterServiceVersionAction { | ||
| /** the kind this action is for */ | ||
| kind: K8sResourceKindReference; | ||
| /** label of action */ | ||
| label: string; | ||
| /** action callback */ | ||
| callback: (kind: K8sResourceKindReference, obj: any) => () => any; | ||
| } | ||
| } | ||
|
|
||
| export interface ClusterServiceVersionAction | ||
| extends Extension<ExtensionProperties.ClusterServiceVersionAction> { | ||
| type: 'ClusterServiceVersion/Action'; | ||
| } | ||
|
|
||
| export const isClusterServiceVersionAction = ( | ||
| e: Extension<any>, | ||
| ): e is ClusterServiceVersionAction => e.type === 'ClusterServiceVersion/Action'; |

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alpha imports.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack