-
Notifications
You must be signed in to change notification settings - Fork 615
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
Introduce Metal3 plugin for openshift console #1539
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 @@ | ||
export const DASH = '-'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export default {}; | ||
export * from './selectors'; | ||
export * from './constants'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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'); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
reviewers: | ||
- jtomasek | ||
- honza | ||
- flofuchs | ||
- knowncitizen | ||
- dantrainor | ||
approvers: | ||
- jtomasek | ||
- honza | ||
- flofuchs | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<typeof ColHead>) => ( | ||
<ListHeader> | ||
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. |
||
<ColHead {...props} className={columnClasses} sortField="metadata.name"> | ||
Name | ||
</ColHead> | ||
{/* <ColHead {...props} className={statusColumnClasses}> | ||
Status | ||
</ColHead> */} | ||
<ColHead {...props} className={columnClasses}> | ||
Machine | ||
</ColHead> | ||
{/* <ColHead {...props} className={roleColumnClasses}> | ||
Role | ||
</ColHead> */} | ||
<ColHead {...props} className={columnClasses} sortField="spec.bmc.address"> | ||
Management Address | ||
</ColHead> | ||
</ListHeader> | ||
); | ||
|
||
const HostRow = ({ obj: host }: React.ComponentProps<typeof ResourceRow>) => { | ||
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. I had to switch from using React.FC as it did not satisfy react/prop-types lint rule. |
||
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 ( | ||
<ResourceRow obj={host}> | ||
<div className={columnClasses}> | ||
<ResourceLink | ||
kind={referenceForModel(BaremetalHostModel)} | ||
name={name} | ||
namespace={namespace} | ||
/> | ||
</div> | ||
{/* <div className={statusColumnClasses}> | ||
<WithResources resourceMap={machineName ? hostResourceMap : {}}> | ||
<BaremetalHostStatus host={host} /> | ||
</WithResources> | ||
</div> */} | ||
<div className={columnClasses}> | ||
<MachineCell host={host} /> | ||
</div> | ||
{/* <div className={roleColumnClasses}> | ||
<WithResources resourceMap={machineName ? hostResourceMap : {}}> | ||
<BaremetalHostRole /> | ||
</WithResources> | ||
</div> */} | ||
<div className={columnClasses}>{address}</div> | ||
</ResourceRow> | ||
); | ||
}; | ||
|
||
const HostList = (props: React.ComponentProps<typeof List>) => ( | ||
<List {...props} Header={HostHeader} Row={HostRow} /> | ||
); | ||
|
||
// 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) => ( | ||
<ListPage | ||
{...props} | ||
canCreate | ||
rowFilters={filters} | ||
createButtonText="Add Host" | ||
kind={referenceForModel(BaremetalHostModel)} | ||
ListComponent={HostList} | ||
/> | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<ResourceLink | ||
kind={referenceForModel(MachineModel)} | ||
name={machineName} | ||
namespace={namespace} | ||
title={machineName} | ||
/> | ||
); | ||
} | ||
// 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 ( | ||
// <RequireCreatePermission model={MachineModel} namespace={ns}> | ||
// <Link to={href}> | ||
// <span className="co-icon-and-text"> | ||
// <Icon type="pf" name="add-circle-o" className="co-icon-and-text__icon" /> | ||
// Add machine | ||
// </span> | ||
// </Link> | ||
// </RequireCreatePermission> | ||
// ); | ||
// } | ||
return <>{DASH}</>; | ||
}; | ||
|
||
export default MachineCell; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { K8sKind } from '@console/internal/module/k8s'; | ||
|
||
export const BaremetalHostModel: K8sKind = { | ||
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. See my comment on KubeVirt models - shouldn't we use @spadgett In 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. I agree, although when I add the crd flag, I am getting 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. Fixed the problem and added 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.
There's currently a duality in how Console references models. Non-CRD models are typically referenced only by their Getting |
||
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, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<ConsumedExtensions> = [ | ||
{ | ||
type: 'ModelDefinition', | ||
properties: { | ||
models: [BaremetalHostModel], | ||
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. You can also do -import { BaremetalHostModel } from './models';
+import * as models from './models'; -models: [BaremetalHostModel],
+models: _.values(models), like in #1592 to avoid manually importing individual models (if you expect to have lots of them). 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. I don't expect there to be many more models, so I listed it explicitly here 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'm fine with that. |
||
}, | ||
}, | ||
{ | ||
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, | ||
}, | ||
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. If you want to put your nav link after an existing one, you can use 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. Done |
||
}, | ||
}, | ||
{ | ||
type: 'Page/Resource/List', | ||
properties: { | ||
model: BaremetalHostModel, | ||
loader: () => | ||
import('./components/host' /* webpackChunkName: "metal3-baremetalhost" */).then( | ||
(m) => m.BaremetalHostsPage, | ||
), | ||
}, | ||
}, | ||
]; | ||
|
||
export default plugin; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); |
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.
Nit: sources should have one trailing newline by default.
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.
Done
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.
Looks like it's still missing the final newline