Skip to content
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

Add Storage Class #89

Merged
merged 1 commit into from
Jun 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { IonCardContent, IonCardHeader, IonCardTitle, IonCol, IonGrid, IonRow } from '@ionic/react';
import { V1StorageClass } from '@kubernetes/client-node';
import React from 'react';
import { RouteComponentProps } from 'react-router';

import { capitalize } from '../../../../utils/helpers';
import IonCardEqualHeight from '../../../misc/IonCardEqualHeight';
import Configuration from '../../misc/template/Configuration';
import Metadata from '../../misc/template/Metadata';
import Row from '../../misc/template/Row';

interface IStorageClassDetailsProps extends RouteComponentProps {
item: V1StorageClass;
section: string;
type: string;
}

const StorageClassDetails: React.FunctionComponent<IStorageClassDetailsProps> = ({
item,
type,
}: IStorageClassDetailsProps) => {
return (
<IonGrid>
<IonRow>
<Configuration>
<Row obj={item} objKey="provisioner" title="Provisioner" />
<Row obj={item} objKey="reclaimPolicy" title="Reclaim Policy" />
<Row obj={item} objKey="volumeBindingMode" title="Volume Binding Mode" />
<Row
obj={item}
objKey="allowVolumeExpansion"
title="Allow Volume Expansion"
value={(value) => (value ? 'true' : 'false')}
/>
<Row
obj={item}
objKey="mountOptions"
title="Mount Options"
value={(value) => (value ? value.join(', ') : '')}
/>
</Configuration>

{item.parameters ? (
<IonCol sizeXs="12" sizeSm="12" sizeMd="12" sizeLg="6" sizeXl="6">
<IonCardEqualHeight>
<IonCardHeader>
<IonCardTitle>Parameters</IonCardTitle>
</IonCardHeader>
<IonCardContent>
<IonGrid>
{Object.keys(item.parameters).map((key: string) => {
if (item.parameters) {
return <Row key={key} obj={item.parameters} objKey={key} title={capitalize(key)} />;
} else {
return '';
}
})}
</IonGrid>
</IonCardContent>
</IonCardEqualHeight>
</IonCol>
) : null}
</IonRow>

{item.metadata ? <Metadata metadata={item.metadata} type={type} /> : null}
</IonGrid>
);
};

export default StorageClassDetails;
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { IonItem, IonLabel } from '@ionic/react';
import { V1StorageClass } from '@kubernetes/client-node';
import React from 'react';
import { RouteComponentProps } from 'react-router';

import { timeDifference } from '../../../../utils/helpers';

interface IStorageClassItemProps extends RouteComponentProps {
item: V1StorageClass;
section: string;
type: string;
}

const StorageClassItem: React.FunctionComponent<IStorageClassItemProps> = ({
item,
section,
type,
}: IStorageClassItemProps) => {
// - Provisioner: Indicates the type of the provisioner.
// - Reclaim Policy: Dynamically provisioned PersistentVolumes of this storage class are created with this reclaimPolicy.
// - Volume Binding Mode: Indicates how PersistentVolumeClaims should be provisioned and bound.
// - Allow Volume Expansion: Shows whether the storage class allow volume expand
// - Age: The time when the service was created.
return (
<IonItem
routerLink={`/resources/${section}/${type}/${item.metadata ? item.metadata.namespace : ''}/${
item.metadata ? item.metadata.name : ''
}`}
routerDirection="forward"
>
<IonLabel>
<h2>{item.metadata ? item.metadata.name : ''}</h2>
<p>
Provisioner: {item.provisioner}
{item.reclaimPolicy ? ` | Reclaim Policy: ${item.reclaimPolicy}` : ''}
{item.volumeBindingMode ? ` | Volume Binding Mode: ${item.volumeBindingMode}` : ''}
{item.allowVolumeExpansion ? ` | Allow Volume Expansion: ${item.allowVolumeExpansion}` : ''}
{item.metadata && item.metadata.creationTimestamp
? ` | Age: ${timeDifference(
new Date().getTime(),
new Date(item.metadata.creationTimestamp.toString()).getTime(),
)}`
: ''}
</p>
</IonLabel>
</IonItem>
);
};

export default StorageClassItem;
11 changes: 11 additions & 0 deletions src/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { V1LabelSelector, V1Subject } from '@kubernetes/client-node';

// capitalize uppercase the first letter of a string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const capitalize = (s: any) => {
if (s === '' || typeof s !== 'string') {
return s;
}

return s.charAt(0).toUpperCase() + s.slice(1);
};

// formatBytes converts a given number of the unit bytes into a human readable string.
// If the si parameter is true, the function uses 1000 instead of 1024 to convert the given number.
// See: https://stackoverflow.com/a/14919494
Expand Down Expand Up @@ -119,6 +129,7 @@ export const isJSON = (data: string): boolean => {
export const isNamespaced = (type: string): boolean => {
return !(
type === 'persistentvolumes' ||
type === 'storageclasses' ||
type === 'clusterroles' ||
type === 'clusterrolebindings' ||
type === 'customresourcedefinitions' ||
Expand Down
16 changes: 16 additions & 0 deletions src/utils/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import PersistentVolumeClaimDetails from '../components/resources/configAndStora
import PersistentVolumeDetails from '../components/resources/configAndStorage/persistentVolumes/PersistentVolumeDetails';
import SecretDetails from '../components/resources/configAndStorage/secrets/SecretDetails';
import ServiceAccountDetails from '../components/resources/configAndStorage/serviceAccounts/ServiceAccountDetails';
import StorageClassDetails from '../components/resources/configAndStorage/storageclasses/StorageClassDetails';

import ClusterRoleBindingDetails from '../components/resources/rbac/clusterRoleBindings/ClusterRoleBindingDetails';
import ClusterRoleDetails from '../components/resources/rbac/clusterRoles/ClusterRoleDetails';
Expand Down Expand Up @@ -48,6 +49,7 @@ import PersistentVolumeClaimItem from '../components/resources/configAndStorage/
import PersistentVolumeItem from '../components/resources/configAndStorage/persistentVolumes/PersistentVolumeItem';
import SecretItem from '../components/resources/configAndStorage/secrets/SecretItem';
import ServiceAccountItem from '../components/resources/configAndStorage/serviceAccounts/ServiceAccountItem';
import StorageClassItem from '../components/resources/configAndStorage/storageclasses/StorageClassItem';

import ClusterRoleBindingItem from '../components/resources/rbac/clusterRoleBindings/ClusterRoleBindingItem';
import ClusterRoleItem from '../components/resources/rbac/clusterRoles/ClusterRoleItem';
Expand Down Expand Up @@ -320,6 +322,20 @@ export const resources: IAppSections = {
},
detailsComponent: ServiceAccountDetails,
},
storageclasses: {
singleText: 'Storage Class',
pluralText: 'Storage Classes',
icon: '/assets/icons/kubernetes/sc.png',
// eslint-disable-next-line @typescript-eslint/no-unused-vars
listURL: (namespace: string) => {
return `/apis/storage.k8s.io/v1/storageclasses`;
},
listItemComponent: StorageClassItem,
detailsURL: (namespace: string, name: string) => {
return `/apis/storage.k8s.io/v1/storageclasses/${name}`;
},
detailsComponent: StorageClassDetails,
},
},
},
rbac: {
Expand Down