Skip to content

Commit c267a9e

Browse files
committed
Adds CRUD support for VolumeGroupSnapshot and others
Signed-off-by: vbadrina <[email protected]>
1 parent e305329 commit c267a9e

File tree

16 files changed

+1399
-149
lines changed

16 files changed

+1399
-149
lines changed

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

Lines changed: 509 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",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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 {
6+
SectionHeading,
7+
ResourceSummary,
8+
navFactory,
9+
Kebab,
10+
} from '@console/internal/components/utils';
11+
import { VolumeGroupSnapshotClassKind } from '@console/internal/module/k8s';
12+
13+
const { editYaml, events } = navFactory;
14+
15+
const Details: React.FC<DetailsProps> = ({ obj }) => {
16+
const { t } = useTranslation();
17+
return (
18+
<div className="co-m-pane__body">
19+
<SectionHeading text={t('console-app~VolumeGroupSnapshotClass details')} />
20+
<div className="row">
21+
<div className="col-md-6 col-xs-12">
22+
<ResourceSummary resource={obj}>
23+
<dt>{t('console-app~Driver')}</dt>
24+
<dd>{obj?.driver}</dd>
25+
<dt>{t('console-app~Deletion policy')}</dt>
26+
<dd>{obj?.deletionPolicy}</dd>
27+
</ResourceSummary>
28+
</div>
29+
</div>
30+
</div>
31+
);
32+
};
33+
34+
const VolumeGroupSnapshotClassDetailsPage: React.FC<DetailsPageProps> = (props) => {
35+
const pages = [
36+
{
37+
href: '',
38+
// t('console-app~Details')
39+
nameKey: 'console-app~Details',
40+
component: Details,
41+
},
42+
editYaml(),
43+
events(ResourceEventStream),
44+
];
45+
return <DetailsPage {...props} menuActions={Kebab.factory.common} pages={pages} />;
46+
};
47+
48+
type DetailsProps = {
49+
obj: VolumeGroupSnapshotClassKind;
50+
};
51+
52+
export default VolumeGroupSnapshotClassDetailsPage;
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
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+
useListPageFilter,
8+
ListPageCreate,
9+
ListPageFilter,
10+
ListPageHeader,
11+
VirtualizedTable,
12+
TableColumn,
13+
RowProps,
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, ResourceKebab, 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+
referenceForModel,
22+
VolumeGroupSnapshotClassKind,
23+
Selector,
24+
} from '@console/internal/module/k8s';
25+
import { getAnnotations } from '@console/shared';
26+
27+
const tableColumnInfo = [
28+
{ id: 'name' },
29+
{ className: classNames('pf-m-hidden', 'pf-m-visible-on-md'), id: 'driver' },
30+
{ className: classNames('pf-m-hidden', 'pf-m-visible-on-md'), id: 'deletionPolicy' },
31+
{ className: Kebab.columnClass, id: '' },
32+
];
33+
34+
const defaultSnapshotClassAnnotation: string = 'snapshot.storage.kubernetes.io/is-default-class';
35+
export const isDefaultSnapshotClass = (VolumeGroupSnapshotClass: VolumeGroupSnapshotClassKind) =>
36+
getAnnotations(VolumeGroupSnapshotClass, { defaultSnapshotClassAnnotation: 'false' })[
37+
defaultSnapshotClassAnnotation
38+
] === 'true';
39+
40+
const Row: React.FC<RowProps<VolumeGroupSnapshotClassKind>> = ({ obj }) => {
41+
const { name } = obj?.metadata || {};
42+
const { deletionPolicy, driver } = obj || {};
43+
const { t } = useTranslation();
44+
45+
return (
46+
<>
47+
<TableData {...tableColumnInfo[0]}>
48+
<ResourceLink name={name} kind={referenceForModel(VolumeGroupSnapshotClassModel)}>
49+
{isDefaultSnapshotClass(obj) && (
50+
<span className="small text-muted co-resource-item__help-text">
51+
{t('public~Default')}
52+
</span>
53+
)}
54+
</ResourceLink>
55+
</TableData>
56+
<TableData {...tableColumnInfo[1]}>{driver}</TableData>
57+
<TableData {...tableColumnInfo[2]}>{deletionPolicy}</TableData>
58+
<TableData {...tableColumnInfo[3]}>
59+
<ResourceKebab
60+
kind={referenceForModel(VolumeGroupSnapshotClassModel)}
61+
resource={obj}
62+
actions={Kebab.factory.common}
63+
/>
64+
</TableData>
65+
</>
66+
);
67+
};
68+
69+
const VolumeGroupSnapshotClassTable: React.FC<VolumeGroupSnapshotClassTableProps> = (props) => {
70+
const { t } = useTranslation();
71+
const getTableColumns = (): TableColumn<VolumeGroupSnapshotClassKind>[] => [
72+
{
73+
title: t('console-app~Name'),
74+
sort: 'metadata.name',
75+
transforms: [sortable],
76+
id: tableColumnInfo[0].id,
77+
},
78+
{
79+
title: t('console-app~Driver'),
80+
sort: 'driver',
81+
transforms: [sortable],
82+
props: { className: tableColumnInfo[1].className },
83+
id: tableColumnInfo[1].id,
84+
},
85+
{
86+
title: t('console-app~Deletion policy'),
87+
sort: 'deletionPolicy',
88+
transforms: [sortable],
89+
props: { className: tableColumnInfo[2].className },
90+
id: tableColumnInfo[2].id,
91+
},
92+
{
93+
title: '',
94+
props: { className: tableColumnInfo[3].className },
95+
id: tableColumnInfo[3].id,
96+
},
97+
];
98+
const [columns] = useActiveColumns({ columns: getTableColumns() });
99+
100+
return (
101+
<VirtualizedTable<VolumeGroupSnapshotClassKind>
102+
{...props}
103+
aria-label={t('console-app~VolumeGroupSnapshotClasses')}
104+
label={t('console-app~VolumeGroupSnapshotClasses')}
105+
columns={columns}
106+
Row={Row}
107+
/>
108+
);
109+
};
110+
111+
const VolumeGroupSnapshotClassPage: React.FC<VolumeGroupSnapshotClassPageProps> = ({
112+
canCreate = true,
113+
showTitle = true,
114+
namespace,
115+
selector,
116+
}) => {
117+
const { t } = useTranslation();
118+
const [resources, loaded, loadError] = useK8sWatchResource<VolumeGroupSnapshotClassKind[]>({
119+
groupVersionKind: {
120+
group: VolumeGroupSnapshotClassModel.apiGroup,
121+
kind: VolumeGroupSnapshotClassModel.kind,
122+
version: VolumeGroupSnapshotClassModel.apiVersion,
123+
},
124+
isList: true,
125+
namespaced: true,
126+
namespace,
127+
selector,
128+
});
129+
const [data, filteredData, onFilterChange] = useListPageFilter(resources);
130+
const resourceKind = referenceForModel(VolumeGroupSnapshotClassModel);
131+
132+
return (
133+
<>
134+
<ListPageHeader
135+
title={showTitle ? t(VolumeGroupSnapshotClassModel.labelPluralKey) : undefined}
136+
>
137+
{canCreate && (
138+
<ListPageCreate groupVersionKind={resourceKind}>
139+
{t('console-app~Create VolumeGroupSnapshotClass')}
140+
</ListPageCreate>
141+
)}
142+
</ListPageHeader>
143+
<ListPageBody>
144+
<ListPageFilter data={data} loaded={loaded} onFilterChange={onFilterChange} />
145+
<VolumeGroupSnapshotClassTable
146+
unfilteredData={resources}
147+
data={filteredData}
148+
loaded={loaded}
149+
loadError={loadError}
150+
/>
151+
</ListPageBody>
152+
</>
153+
);
154+
};
155+
156+
type VolumeGroupSnapshotClassPageProps = {
157+
namespace?: string;
158+
canCreate?: boolean;
159+
showTitle?: boolean;
160+
selector?: Selector;
161+
};
162+
163+
type VolumeGroupSnapshotClassTableProps = {
164+
data: VolumeGroupSnapshotClassKind[];
165+
unfilteredData: VolumeGroupSnapshotClassKind[];
166+
loaded: boolean;
167+
loadError: any;
168+
};
169+
export default VolumeGroupSnapshotClassPage;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
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 {
6+
SectionHeading,
7+
ResourceSummary,
8+
ResourceLink,
9+
navFactory,
10+
Kebab,
11+
} from '@console/internal/components/utils';
12+
import { VolumeGroupSnapshotClassModel, VolumeGroupSnapshotModel } from '@console/internal/models';
13+
import { referenceForModel, VolumeGroupSnapshotContentKind } from '@console/internal/module/k8s';
14+
import { Status } from '@console/shared';
15+
import { volumeSnapshotStatus } from '../../status';
16+
17+
const { editYaml, events } = navFactory;
18+
19+
const Details: React.FC<DetailsProps> = ({ obj }) => {
20+
const { t } = useTranslation();
21+
const { deletionPolicy, driver } = obj?.spec;
22+
const { volumeHandles, groupSnapshotHandles } = obj?.spec?.source || {};
23+
const { name: snapshotName, namespace: snapshotNamespace } =
24+
obj?.spec?.volumeGroupSnapshotRef || {};
25+
26+
return (
27+
<div className="co-m-pane__body">
28+
<SectionHeading text={t('console-app~VolumeGroupSnapshotContent details')} />
29+
<div className="row">
30+
<div className="col-md-6 col-xs-12">
31+
<ResourceSummary resource={obj}>
32+
<dt>{t('console-app~Status')}</dt>
33+
<dd>
34+
<Status status={volumeSnapshotStatus(obj)} />
35+
</dd>
36+
</ResourceSummary>
37+
</div>
38+
<div className="col-md-6">
39+
<dl className="co-m-pane__details">
40+
<dt>{t('console-app~VolumeGroupSnapshot')}</dt>
41+
<dd>
42+
<ResourceLink
43+
kind={referenceForModel(VolumeGroupSnapshotModel)}
44+
name={snapshotName}
45+
namespace={snapshotNamespace}
46+
/>
47+
</dd>
48+
<dt>{t('console-app~VolumeGroupSnapshotClass')}</dt>
49+
<dd>
50+
<ResourceLink
51+
kind={referenceForModel(VolumeGroupSnapshotClassModel)}
52+
name={obj?.spec?.volumeGroupSnapshotClassName}
53+
/>
54+
</dd>
55+
<dt>{t('console-app~Deletion policy')}</dt>
56+
<dd>{deletionPolicy}</dd>
57+
<dt>{t('console-app~Driver')}</dt>
58+
<dd>{driver}</dd>
59+
{volumeHandles && (
60+
<>
61+
<dt>{t('console-app~Volume handle')}</dt>
62+
{volumeHandles.map((handle) => (
63+
<dd>{handle}</dd>
64+
))}
65+
</>
66+
)}
67+
{groupSnapshotHandles && (
68+
<>
69+
<dt>{t('console-app~GroupSnapshot handle')}</dt>
70+
<dd>{groupSnapshotHandles.volumeGroupSnapshotHandle}</dd>
71+
</>
72+
)}
73+
</dl>
74+
</div>
75+
</div>
76+
</div>
77+
);
78+
};
79+
80+
const VolumeGroupSnapshotContentDetailsPage: React.FC<DetailsPageProps> = (props) => {
81+
const pages = [
82+
{
83+
href: '',
84+
// t('console-app~Details')
85+
nameKey: 'console-app~Details',
86+
component: Details,
87+
},
88+
editYaml(),
89+
events(ResourceEventStream),
90+
];
91+
return (
92+
<DetailsPage
93+
{...props}
94+
getResourceStatus={volumeSnapshotStatus}
95+
menuActions={Kebab.factory.common}
96+
pages={pages}
97+
/>
98+
);
99+
};
100+
101+
type DetailsProps = {
102+
obj: VolumeGroupSnapshotContentKind;
103+
};
104+
105+
export default VolumeGroupSnapshotContentDetailsPage;

0 commit comments

Comments
 (0)