Skip to content

Commit 6e2d762

Browse files
committed
Adds CRUD action support for VolumeGroupSnapshots
Signed-off-by: vbadrina <[email protected]>
1 parent e305329 commit 6e2d762

File tree

18 files changed

+1443
-151
lines changed

18 files changed

+1443
-151
lines changed

frontend/packages/console-app/console-extensions.json

Lines changed: 522 additions & 139 deletions
Large diffs are not rendered by default.

frontend/packages/console-app/locales/en/console-app.json

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@
190190
"Whether or not the plugin might have violated the Console Content Security Policy.": "Whether or not the plugin might have violated the Console Content Security Policy.",
191191
"Backend Service": "Backend Service",
192192
"Proxy Services": "Proxy Services",
193+
"VolumeGroupSnapshots": "VolumeGroupSnapshots",
194+
"VolumeGroupSnapshotClasses": "VolumeGroupSnapshotClasses",
195+
"VolumeGroupSnapshotContents": "VolumeGroupSnapshotContents",
193196
"Delete {{kind}}": "Delete {{kind}}",
194197
"Edit {{kind}}": "Edit {{kind}}",
195198
"Edit labels": "Edit labels",
@@ -615,29 +618,40 @@
615618
"Select an option": "Select an option",
616619
"User Preferences {{activeTab}}": "User Preferences {{activeTab}}",
617620
"Set your individual preferences for the console experience. Any changes will be autosaved.": "Set your individual preferences for the console experience. Any changes will be autosaved.",
618-
"Only {{volumeMode}} volume mode is available for {{storageClass}} with {{accessMode}} access mode": "Only {{volumeMode}} volume mode is available for {{storageClass}} with {{accessMode}} access mode",
619621
"VolumeSnapshotClass with same provisioner as claim": "VolumeSnapshotClass with same provisioner as claim",
620622
"Select volume snapshot class": "Select volume snapshot class",
621623
"PersistentVolumeClaim details": "PersistentVolumeClaim details",
622-
"Create VolumeSnapshot": "Create VolumeSnapshot",
624+
"Create VolumeGroupSnapshot": "Create VolumeGroupSnapshot",
623625
"Edit YAML": "Edit YAML",
624626
"Creating snapshot for claim <1>{{pvcName}}</1>": "Creating snapshot for claim <1>{{pvcName}}</1>",
625627
"PersistentVolumeClaim": "PersistentVolumeClaim",
626628
"PersistentVolumeClaim in {{namespace}} namespace": "PersistentVolumeClaim in {{namespace}} namespace",
627629
"Snapshot Class": "Snapshot Class",
628-
"VolumeSnapshotClass details": "VolumeSnapshotClass details",
630+
"VolumeGroupSnapshotClass details": "VolumeGroupSnapshotClass details",
629631
"Driver": "Driver",
630632
"Deletion policy": "Deletion policy",
633+
"Create VolumeGroupSnapshotClass": "Create VolumeGroupSnapshotClass",
634+
"VolumeGroupSnapshotContent details": "VolumeGroupSnapshotContent details",
635+
"VolumeGroupSnapshot": "VolumeGroupSnapshot",
636+
"VolumeGroupSnapshotClass": "VolumeGroupSnapshotClass",
637+
"Volume handle": "Volume handle",
638+
"GroupSnapshot handle": "GroupSnapshot handle",
639+
"SnapshotClass": "SnapshotClass",
640+
"Create VolumeGroupSnapshotContent": "Create VolumeGroupSnapshotContent",
641+
"VolumeGroupSnapshot details": "VolumeGroupSnapshot details",
642+
"Source": "Source",
643+
"VolumeGroupSnapshotContent": "VolumeGroupSnapshotContent",
644+
"GroupSnapshot content": "GroupSnapshot content",
645+
"Only {{volumeMode}} volume mode is available for {{storageClass}} with {{accessMode}} access mode": "Only {{volumeMode}} volume mode is available for {{storageClass}} with {{accessMode}} access mode",
646+
"Create VolumeSnapshot": "Create VolumeSnapshot",
647+
"VolumeSnapshotClass details": "VolumeSnapshotClass details",
631648
"Create VolumeSnapshotClass": "Create VolumeSnapshotClass",
632649
"VolumeSnapshotContent details": "VolumeSnapshotContent details",
633650
"VolumeSnapshot": "VolumeSnapshot",
634651
"VolumeSnapshotClass": "VolumeSnapshotClass",
635-
"Volume handle": "Volume handle",
636652
"Snapshot handle": "Snapshot handle",
637-
"SnapshotClass": "SnapshotClass",
638653
"Create VolumeSnapshotContent": "Create VolumeSnapshotContent",
639654
"VolumeSnapshot details": "VolumeSnapshot details",
640-
"Source": "Source",
641655
"VolumeSnapshotContent": "VolumeSnapshotContent",
642656
"Snapshot content": "Snapshot content",
643657
"Recommended": "Recommended",

frontend/packages/console-app/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@
7070
"consolePluginBackendDetail": "src/components/console-operator/ConsolePluginBackendDetail.tsx",
7171
"consolePluginProxyDetail": "src/components/console-operator/ConsolePluginProxyDetail.tsx",
7272
"getConsoleOperatorConfigFlag": "src/hooks/useCanGetConsoleOperatorConfig.ts",
73-
"usePerspectivesAvailable": "src/components/user-preferences/perspective/usePerspectivesAvailable.ts"
73+
"usePerspectivesAvailable": "src/components/user-preferences/perspective/usePerspectivesAvailable.ts",
74+
"defaultProvider": "src/actions/providers/default-provider.ts"
7475
}
7576
}
76-
}
77+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as React from 'react';
2+
import { Action } from '@console/dynamic-plugin-sdk/';
3+
import { K8sResourceCommon, referenceFor } from '@console/internal/module/k8s';
4+
import { useK8sModel } from '@console/shared/src/hooks/useK8sModel';
5+
import { getCommonResourceActions } from '../creators/common-factory';
6+
7+
export const useDefaultActionsProvider = (
8+
resource: K8sResourceCommon,
9+
): [Action[], boolean, Error] => {
10+
const [kindObj, inFlight] = useK8sModel(referenceFor(resource));
11+
12+
const actions = React.useMemo(() => [...getCommonResourceActions(kindObj, resource)], [
13+
kindObj,
14+
resource,
15+
]);
16+
17+
return [actions, !inFlight, undefined];
18+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import * as React from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import { ResourceEventStream } from '@console/internal/components/events';
4+
import { DetailsPage, DetailsPageProps } from '@console/internal/components/factory';
5+
import { navFactory, ResourceSummary, SectionHeading } from '@console/internal/components/utils';
6+
import { referenceForModel, VolumeGroupSnapshotClassKind } from '@console/internal/module/k8s';
7+
import { ActionMenu, ActionMenuVariant, ActionServiceProvider } from '@console/shared';
8+
9+
const { editYaml, events } = navFactory;
10+
11+
const Details: React.FC<DetailsProps> = ({ obj }) => {
12+
const { t } = useTranslation();
13+
return (
14+
<div className="co-m-pane__body">
15+
<SectionHeading text={t('console-app~VolumeGroupSnapshotClass details')} />
16+
<div className="row">
17+
<div className="col-md-6 col-xs-12">
18+
<ResourceSummary resource={obj}>
19+
<dt>{t('console-app~Driver')}</dt>
20+
<dd>{obj?.driver}</dd>
21+
<dt>{t('console-app~Deletion policy')}</dt>
22+
<dd>{obj?.deletionPolicy}</dd>
23+
</ResourceSummary>
24+
</div>
25+
</div>
26+
</div>
27+
);
28+
};
29+
30+
const VolumeGroupSnapshotClassDetailsPage: React.FC<DetailsPageProps> = (props) => {
31+
const pages = [
32+
{
33+
href: '',
34+
// t('console-app~Details')
35+
nameKey: 'console-app~Details',
36+
component: Details,
37+
},
38+
editYaml(),
39+
events(ResourceEventStream),
40+
];
41+
42+
const customActionMenu = (kindObj, obj) => {
43+
const resourceKind = referenceForModel(kindObj);
44+
const context = { [resourceKind]: obj };
45+
return (
46+
<ActionServiceProvider context={context}>
47+
{({ actions, options, loaded }) =>
48+
loaded && (
49+
<ActionMenu actions={actions} options={options} variant={ActionMenuVariant.DROPDOWN} />
50+
)
51+
}
52+
</ActionServiceProvider>
53+
);
54+
};
55+
56+
return <DetailsPage {...props} customActionMenu={customActionMenu} pages={pages} />;
57+
};
58+
59+
type DetailsProps = {
60+
obj: VolumeGroupSnapshotClassKind;
61+
};
62+
63+
export default VolumeGroupSnapshotClassDetailsPage;
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import * as React from 'react';
2+
import { sortable } from '@patternfly/react-table';
3+
import * as classNames from 'classnames';
4+
import { useTranslation } from 'react-i18next';
5+
import {
6+
ListPageBody,
7+
ListPageCreate,
8+
ListPageFilter,
9+
ListPageHeader,
10+
RowProps,
11+
TableColumn,
12+
useListPageFilter,
13+
VirtualizedTable,
14+
} from '@console/dynamic-plugin-sdk/src/lib-core';
15+
import { TableData } from '@console/internal/components/factory';
16+
import { useActiveColumns } from '@console/internal/components/factory/Table/active-columns-hook';
17+
import { Kebab, ResourceLink } from '@console/internal/components/utils';
18+
import { useK8sWatchResource } from '@console/internal/components/utils/k8s-watch-hook';
19+
import { VolumeGroupSnapshotClassModel } from '@console/internal/models';
20+
import {
21+
referenceFor,
22+
referenceForModel,
23+
Selector,
24+
VolumeGroupSnapshotClassKind,
25+
} from '@console/internal/module/k8s';
26+
import { getAnnotations, LazyActionMenu } from '@console/shared';
27+
28+
const tableColumnInfo = [
29+
{ id: 'name' },
30+
{ className: classNames('pf-m-hidden', 'pf-m-visible-on-md'), id: 'driver' },
31+
{ className: classNames('pf-m-hidden', 'pf-m-visible-on-md'), id: 'deletionPolicy' },
32+
{ className: Kebab.columnClass, id: '' },
33+
];
34+
35+
const defaultSnapshotClassAnnotation: string = 'snapshot.storage.kubernetes.io/is-default-class';
36+
export const isDefaultSnapshotClass = (VolumeGroupSnapshotClass: VolumeGroupSnapshotClassKind) =>
37+
getAnnotations(VolumeGroupSnapshotClass, { defaultSnapshotClassAnnotation: 'false' })[
38+
defaultSnapshotClassAnnotation
39+
] === 'true';
40+
41+
const Row: React.FC<RowProps<VolumeGroupSnapshotClassKind>> = ({ obj }) => {
42+
const { name } = obj?.metadata || {};
43+
const { deletionPolicy, driver } = obj || {};
44+
const { t } = useTranslation();
45+
const resourceKind = referenceFor(obj);
46+
const context = { [resourceKind]: obj };
47+
48+
return (
49+
<>
50+
<TableData {...tableColumnInfo[0]}>
51+
<ResourceLink name={name} kind={referenceForModel(VolumeGroupSnapshotClassModel)}>
52+
{isDefaultSnapshotClass(obj) && (
53+
<span className="small text-muted co-resource-item__help-text">
54+
{t('public~Default')}
55+
</span>
56+
)}
57+
</ResourceLink>
58+
</TableData>
59+
<TableData {...tableColumnInfo[1]}>{driver}</TableData>
60+
<TableData {...tableColumnInfo[2]}>{deletionPolicy}</TableData>
61+
<TableData {...tableColumnInfo[3]}>
62+
<LazyActionMenu context={context} />
63+
</TableData>
64+
</>
65+
);
66+
};
67+
68+
const VolumeGroupSnapshotClassTable: React.FC<VolumeGroupSnapshotClassTableProps> = (props) => {
69+
const { t } = useTranslation();
70+
const getTableColumns = (): TableColumn<VolumeGroupSnapshotClassKind>[] => [
71+
{
72+
title: t('console-app~Name'),
73+
sort: 'metadata.name',
74+
transforms: [sortable],
75+
id: tableColumnInfo[0].id,
76+
},
77+
{
78+
title: t('console-app~Driver'),
79+
sort: 'driver',
80+
transforms: [sortable],
81+
props: { className: tableColumnInfo[1].className },
82+
id: tableColumnInfo[1].id,
83+
},
84+
{
85+
title: t('console-app~Deletion policy'),
86+
sort: 'deletionPolicy',
87+
transforms: [sortable],
88+
props: { className: tableColumnInfo[2].className },
89+
id: tableColumnInfo[2].id,
90+
},
91+
{
92+
title: '',
93+
props: { className: tableColumnInfo[3].className },
94+
id: tableColumnInfo[3].id,
95+
},
96+
];
97+
const [columns] = useActiveColumns({ columns: getTableColumns() });
98+
99+
return (
100+
<VirtualizedTable<VolumeGroupSnapshotClassKind>
101+
{...props}
102+
aria-label={t('console-app~VolumeGroupSnapshotClasses')}
103+
label={t('console-app~VolumeGroupSnapshotClasses')}
104+
columns={columns}
105+
Row={Row}
106+
/>
107+
);
108+
};
109+
110+
const VolumeGroupSnapshotClassPage: React.FC<VolumeGroupSnapshotClassPageProps> = ({
111+
canCreate = true,
112+
showTitle = true,
113+
namespace,
114+
selector,
115+
}) => {
116+
const { t } = useTranslation();
117+
const [resources, loaded, loadError] = useK8sWatchResource<VolumeGroupSnapshotClassKind[]>({
118+
groupVersionKind: {
119+
group: VolumeGroupSnapshotClassModel.apiGroup,
120+
kind: VolumeGroupSnapshotClassModel.kind,
121+
version: VolumeGroupSnapshotClassModel.apiVersion,
122+
},
123+
isList: true,
124+
namespaced: true,
125+
namespace,
126+
selector,
127+
});
128+
const [data, filteredData, onFilterChange] = useListPageFilter(resources);
129+
const resourceKind = referenceForModel(VolumeGroupSnapshotClassModel);
130+
131+
return (
132+
<>
133+
<ListPageHeader
134+
title={showTitle ? t(VolumeGroupSnapshotClassModel.labelPluralKey) : undefined}
135+
>
136+
{canCreate && (
137+
<ListPageCreate groupVersionKind={resourceKind}>
138+
{t('console-app~Create VolumeGroupSnapshotClass')}
139+
</ListPageCreate>
140+
)}
141+
</ListPageHeader>
142+
<ListPageBody>
143+
<ListPageFilter data={data} loaded={loaded} onFilterChange={onFilterChange} />
144+
<VolumeGroupSnapshotClassTable
145+
unfilteredData={resources}
146+
data={filteredData}
147+
loaded={loaded}
148+
loadError={loadError}
149+
/>
150+
</ListPageBody>
151+
</>
152+
);
153+
};
154+
155+
type VolumeGroupSnapshotClassPageProps = {
156+
namespace?: string;
157+
canCreate?: boolean;
158+
showTitle?: boolean;
159+
selector?: Selector;
160+
};
161+
162+
type VolumeGroupSnapshotClassTableProps = {
163+
data: VolumeGroupSnapshotClassKind[];
164+
unfilteredData: VolumeGroupSnapshotClassKind[];
165+
loaded: boolean;
166+
loadError: any;
167+
};
168+
export default VolumeGroupSnapshotClassPage;

0 commit comments

Comments
 (0)