From e1d1ef7d398c53b7a412131b921df72195f96463 Mon Sep 17 00:00:00 2001 From: Jiri Tomasek Date: Thu, 6 Jun 2019 17:28:23 +0200 Subject: [PATCH] Add initial metal3 plugin Including basic Baremetal hosts listing page --- .../console-shared/src/constants/index.ts | 1 + frontend/packages/console-shared/src/index.ts | 3 +- .../console-shared/src/selectors/index.ts | 6 + frontend/packages/metal3-plugin/OWNERS | 10 ++ frontend/packages/metal3-plugin/package.json | 13 ++ .../metal3-plugin/src/components/host.tsx | 130 ++++++++++++++++++ .../src/components/machine-cell.tsx | 51 +++++++ frontend/packages/metal3-plugin/src/models.ts | 15 ++ frontend/packages/metal3-plugin/src/plugin.ts | 53 +++++++ .../metal3-plugin/src/selectors/index.ts | 16 +++ 10 files changed, 297 insertions(+), 1 deletion(-) create mode 100644 frontend/packages/console-shared/src/constants/index.ts create mode 100644 frontend/packages/console-shared/src/selectors/index.ts create mode 100644 frontend/packages/metal3-plugin/OWNERS create mode 100644 frontend/packages/metal3-plugin/package.json create mode 100644 frontend/packages/metal3-plugin/src/components/host.tsx create mode 100644 frontend/packages/metal3-plugin/src/components/machine-cell.tsx create mode 100644 frontend/packages/metal3-plugin/src/models.ts create mode 100644 frontend/packages/metal3-plugin/src/plugin.ts create mode 100644 frontend/packages/metal3-plugin/src/selectors/index.ts diff --git a/frontend/packages/console-shared/src/constants/index.ts b/frontend/packages/console-shared/src/constants/index.ts new file mode 100644 index 00000000000..420e8861ee1 --- /dev/null +++ b/frontend/packages/console-shared/src/constants/index.ts @@ -0,0 +1 @@ +export const DASH = '-'; diff --git a/frontend/packages/console-shared/src/index.ts b/frontend/packages/console-shared/src/index.ts index ff8b4c56321..6f48a9cc404 100644 --- a/frontend/packages/console-shared/src/index.ts +++ b/frontend/packages/console-shared/src/index.ts @@ -1 +1,2 @@ -export default {}; +export * from './selectors'; +export * from './constants'; diff --git a/frontend/packages/console-shared/src/selectors/index.ts b/frontend/packages/console-shared/src/selectors/index.ts new file mode 100644 index 00000000000..98abc0c2d68 --- /dev/null +++ b/frontend/packages/console-shared/src/selectors/index.ts @@ -0,0 +1,6 @@ +import * as _ from 'lodash-es'; + +import { K8sResourceKind } from '@console/internal/module/k8s'; + +export const getName = (value: K8sResourceKind): string => _.get(value, 'metadata.name'); +export const getNamespace = (value: K8sResourceKind): string => _.get(value, 'metadata.namespace'); diff --git a/frontend/packages/metal3-plugin/OWNERS b/frontend/packages/metal3-plugin/OWNERS new file mode 100644 index 00000000000..d037d09ebf4 --- /dev/null +++ b/frontend/packages/metal3-plugin/OWNERS @@ -0,0 +1,10 @@ +reviewers: + - jtomasek + - honza + - flofuchs + - knowncitizen + - dantrainor +approvers: + - jtomasek + - honza + - flofuchs \ No newline at end of file diff --git a/frontend/packages/metal3-plugin/package.json b/frontend/packages/metal3-plugin/package.json new file mode 100644 index 00000000000..0e7bf5b18be --- /dev/null +++ b/frontend/packages/metal3-plugin/package.json @@ -0,0 +1,13 @@ +{ + "name": "@console/metal3-plugin", + "version": "0.0.0-fixed", + "description": "Metal Kubed - Bare Metal Host Provisioning for Kubernetes", + "private": true, + "dependencies": { + "@console/plugin-sdk": "0.0.0-fixed", + "@console/shared": "0.0.0-fixed" + }, + "consolePlugin": { + "entry": "src/plugin.ts" + } +} diff --git a/frontend/packages/metal3-plugin/src/components/host.tsx b/frontend/packages/metal3-plugin/src/components/host.tsx new file mode 100644 index 00000000000..8c76972e102 --- /dev/null +++ b/frontend/packages/metal3-plugin/src/components/host.tsx @@ -0,0 +1,130 @@ +import * as React from 'react'; + +import { getName, getNamespace } from '@console/shared'; +// TODO(jtomasek): update import once models are moved to console-shared package +// import { MachineModel, NodeModel } from '@console/internal/models'; +import { referenceForModel } from '@console/internal/module/k8s'; + +import { + ListHeader, + ColHead, + List, + ListPage, + ResourceRow, +} from '@console/internal/components/factory'; + +import { ResourceLink } from '@console/internal/components/utils'; +// import { WithResources } from '@console/shared'; + +import { BaremetalHostModel } from '../models'; +import { getHostBMCAddress } from '../selectors'; +import MachineCell from './machine-cell'; + +// const nameColumnClasses = 'col-lg-2 col-md-4 col-sm-6 col-xs-6'; +// const statusColumnClasses = 'col-lg-2 col-md-4 hidden-sm hidden-xs'; +// const machineColumnClasses = 'col-lg-3 visible-lg'; +// const roleColumnClasses = 'col-lg-2 visible-lg'; +// const addressColumnClasses = 'col-lg-2 visible-lg'; +const columnClasses = 'col-sm-4'; + +const HostHeader = (props: React.ComponentProps) => ( + + + Name + + {/* + Status + */} + + Machine + + {/* + Role + */} + + Management Address + + +); + +const HostRow = ({ obj: host }: React.ComponentProps) => { + const name = getName(host); + const namespace = getNamespace(host); + // const machineName = getHostMachineName(host); + const address = getHostBMCAddress(host); + + // TODO(jtomasek): other resource references will be updated as a subsequent change + // const machineResource = { + // kind: referenceForModel(MachineModel), + // name: machineName, + // namespaced: true, + // namespace, + // isList: false, + // prop: 'machine', + // }; + + // const hostResourceMap = { + // machine: { + // resource: machineResource, + // }, + // nodes: { + // resource: getResource(NodeModel, { namespaced: false }), + // }, + // }; + + return ( + +
+ +
+ {/*
+ + + +
*/} +
+ +
+ {/*
+ + + +
*/} +
{address}
+
+ ); +}; + +const HostList = (props: React.ComponentProps) => ( + +); + +// TODO(jtomasek): re-enable filters once the extension point for list.tsx is in place +const filters = []; +// const filters = [ +// { +// type: 'baremetalhost-status', +// selected: ['online', 'offline'], +// reducer: getSimpleHostStatus, +// items: [{ id: 'online', title: 'online' }, { id: 'offline', title: 'offline' }], +// }, +// ]; + +type BaremetalHostsPageProps = { + namespace: string; +}; + +export const BaremetalHostsPage = (props: BaremetalHostsPageProps) => ( + +); diff --git a/frontend/packages/metal3-plugin/src/components/machine-cell.tsx b/frontend/packages/metal3-plugin/src/components/machine-cell.tsx new file mode 100644 index 00000000000..ee194f676a0 --- /dev/null +++ b/frontend/packages/metal3-plugin/src/components/machine-cell.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; +// import { Link } from 'react-router-dom'; +// import { Icon } from 'patternfly-react'; + +import { DASH } from '@console/shared'; +import { MachineModel } from '@console/internal/models'; +import { ResourceLink /* , RequireCreatePermission */ } from '@console/internal/components/utils'; +import { referenceForModel, K8sResourceKind } from '@console/internal/module/k8s'; + +import { getHostMachineName } from '../selectors'; + +interface MachineCellProps { + host: K8sResourceKind; +} + +const MachineCell = ({ host }: MachineCellProps) => { + const machineName = getHostMachineName(host); + + const { + metadata: { namespace }, + } = host; + + if (machineName) { + return ( + + ); + } + // TODO(jtomasek): Re-enable this once host status is added + // if (canHostAddMachine(host)) { + // const ns = namespace || 'default'; + // const href = `/k8s/ns/${ns}/${referenceForModel(MachineModel)}/~new`; + // return ( + // + // + // + // + // Add machine + // + // + // + // ); + // } + return <>{DASH}; +}; + +export default MachineCell; diff --git a/frontend/packages/metal3-plugin/src/models.ts b/frontend/packages/metal3-plugin/src/models.ts new file mode 100644 index 00000000000..e8204ad97ab --- /dev/null +++ b/frontend/packages/metal3-plugin/src/models.ts @@ -0,0 +1,15 @@ +import { K8sKind } from '@console/internal/module/k8s'; + +export const BaremetalHostModel: K8sKind = { + label: 'Bare Metal Host', + labelPlural: 'Bare Metal Hosts', + apiVersion: 'v1alpha1', + path: 'baremetalhosts', + apiGroup: 'metalkube.org', + plural: 'baremetalhosts', + abbr: 'BMH', + namespaced: true, + kind: 'BareMetalHost', + id: 'baremetalhost', + crd: true, +}; diff --git a/frontend/packages/metal3-plugin/src/plugin.ts b/frontend/packages/metal3-plugin/src/plugin.ts new file mode 100644 index 00000000000..0208f70b470 --- /dev/null +++ b/frontend/packages/metal3-plugin/src/plugin.ts @@ -0,0 +1,53 @@ +import { + Plugin, + ResourceNSNavItem, + ResourceListPage, + ModelFeatureFlag, + ModelDefinition, +} from '@console/plugin-sdk'; + +import { BaremetalHostModel } from './models'; + +type ConsumedExtensions = ResourceNSNavItem | ResourceListPage | ModelFeatureFlag | ModelDefinition; + +const METAL3_FLAG = 'METAL3'; + +const plugin: Plugin = [ + { + type: 'ModelDefinition', + properties: { + models: [BaremetalHostModel], + }, + }, + { + type: 'FeatureFlag/Model', + properties: { + model: BaremetalHostModel, + flag: METAL3_FLAG, + }, + }, + { + type: 'NavItem/ResourceNS', + properties: { + section: 'Compute', + mergeAfter: 'Machine Autoscalers', + componentProps: { + name: 'Bare Metal Hosts', + resource: 'baremetalhosts', + required: METAL3_FLAG, + }, + }, + }, + { + type: 'Page/Resource/List', + properties: { + model: BaremetalHostModel, + loader: () => + import('./components/host' /* webpackChunkName: "metal3-baremetalhost" */).then( + (m) => m.BaremetalHostsPage, + ), + }, + }, +]; + +export default plugin; diff --git a/frontend/packages/metal3-plugin/src/selectors/index.ts b/frontend/packages/metal3-plugin/src/selectors/index.ts new file mode 100644 index 00000000000..bdd78b9e73b --- /dev/null +++ b/frontend/packages/metal3-plugin/src/selectors/index.ts @@ -0,0 +1,16 @@ +import * as _ from 'lodash-es'; + +export const getOperationalStatus = (host) => _.get(host, 'status.operationalStatus'); +export const getProvisioningState = (host) => _.get(host, 'status.provisioning.state'); +export const getHostMachineName = (host) => _.get(host, 'spec.machineRef.name'); +export const getHostBMCAddress = (host) => _.get(host, 'spec.bmc.address'); +export const isHostOnline = (host) => _.get(host, 'spec.online', false); +export const getHostNICs = (host) => _.get(host, 'status.hardware.nics', []); +export const getHostStorage = (host) => _.get(host, 'status.hardware.storage', []); +export const getHostCPUs = (host) => _.get(host, 'status.hardware.cpus', []); +export const getHostRAM = (host) => _.get(host, 'status.hardware.ramGiB'); +export const getHostErrorMessage = (host) => _.get(host, 'status.errorMessage'); +export const getHostDescription = (host) => _.get(host, 'spec.description', ''); +export const isHostPoweredOn = (host) => _.get(host, 'status.poweredOn', false); +export const getHostTotalStorageCapacity = (host) => + _.reduce(getHostStorage(host), (sum, disk) => sum + disk.sizeGiB, 0);