diff --git a/frontend/packages/kubevirt-plugin/src/components/vm-templates/vm-template.tsx b/frontend/packages/kubevirt-plugin/src/components/vm-templates/vm-template.tsx new file mode 100644 index 000000000000..34ae9fd001cb --- /dev/null +++ b/frontend/packages/kubevirt-plugin/src/components/vm-templates/vm-template.tsx @@ -0,0 +1,149 @@ +import * as React from 'react'; +import * as _ from 'lodash'; +import * as classNames from 'classnames'; +import { sortable } from '@patternfly/react-table'; + +import { + TemplateSource, + getTemplateOperatingSystems, + getTemplateFlavors, + TEMPLATE_TYPE_LABEL, +} from 'kubevirt-web-ui-components'; + +import { ListPage, Table, TableRow, TableData } from '@console/internal/components/factory'; +import { Kebab, ResourceLink, ResourceKebab } from '@console/internal/components/utils'; +import { getName, getNamespace, DASH, getUid } from '@console/shared'; +import { TemplateModel } from '@console/internal/models'; +import { K8sResourceKind } from '../../../../../public/module/k8s/index'; + +export const menuActions = Kebab.factory.common; + +const { kind } = TemplateModel; +const selector = { + matchLabels: { [TEMPLATE_TYPE_LABEL]: 'vm' }, +}; +const labelPlural = 'Virtual Machine Templates'; + +const tableColumnClass = classNames('col-lg-2', 'col-sm-4', 'col-xs-4'); +const tableColumnClassHiddenOnSmall = classNames('col-lg-2', 'hidden-sm', 'hidden-xs'); + +const tableColumnClasses = [ + tableColumnClass, + tableColumnClass, + tableColumnClass, + tableColumnClassHiddenOnSmall, + tableColumnClassHiddenOnSmall, + tableColumnClassHiddenOnSmall, + Kebab.columnClass, +]; + +const VmTempleateTableHeader = () => { + return [ + { + title: 'Name', + sortField: 'metadata.name', + transforms: [sortable], + props: { className: tableColumnClasses[0] }, + }, + { + title: 'Namespace', + sortField: 'metadata.namespace', + transforms: [sortable], + props: { className: tableColumnClasses[1] }, + }, + { + title: 'Description', + sortField: 'metadata.annotations.description', + transforms: [sortable], + props: { className: tableColumnClasses[2] }, + }, + { + title: 'Source', + props: { className: tableColumnClasses[3] }, + }, + { + title: 'OS', + props: { className: tableColumnClasses[4] }, + }, + { + title: 'Flavor', + props: { className: tableColumnClasses[5] }, + }, + { + title: '', + props: { className: tableColumnClasses[6] }, + }, + ]; +}; +VmTempleateTableHeader.displayName = 'VmTemplateTableHeader'; + +const VmTemplateTableRow = ({ template, index, key, style }: VmTemplateTableRowProps) => { + const os = getTemplateOperatingSystems([template])[0]; + + return ( + + + + + + + + + {_.get(template.metadata, 'annotations.description', DASH)} + + + + + {os ? os.name || os.id : DASH} + {getTemplateFlavors([template])[0]} + + + + + ); +}; +VmTemplateTableRow.displayName = 'VmTemplateTableRow'; + +const VirtualMachineTemplates: React.FC< + React.ComponentProps & VirtualMachineTemplatesProps +> = (props) => ( + +); + +const VirtualMachineTemplatesPage: React.FC< + React.ComponentProps & VirtualMachineTemplatesPageProps +> = (props) => ( + +); + +type VmTemplateTableRowProps = { + template: K8sResourceKind; + index: number; + key: string; + style: any; +}; +type VirtualMachineTemplatesProps = {}; +type VirtualMachineTemplatesPageProps = {}; + +export { VirtualMachineTemplates, VirtualMachineTemplatesPage }; diff --git a/frontend/packages/kubevirt-plugin/src/models.ts b/frontend/packages/kubevirt-plugin/src/models.ts index 12cf1eeedb96..a7f7102e5b75 100644 --- a/frontend/packages/kubevirt-plugin/src/models.ts +++ b/frontend/packages/kubevirt-plugin/src/models.ts @@ -48,24 +48,6 @@ export const VirtualMachineInstanceReplicaSetModel: K8sKind = { id: 'virtualmachineinstancereplicaset', }; -/* TODO(mlibra): migrate templates -export const VmTemplateModel: K8sKind = { - label: 'Template', - labelPlural: 'Templates', - apiVersion: 'v1', - path: 'templates', - apiGroup: 'template.openshift.io', - plural: 'vmtemplates', - namespaced: true, - abbr: 'VMT', - kind: 'Template', - id: 'vmtemplate', - selector: { - matchLabels: {[TEMPLATE_TYPE_LABEL]: 'vm'}, - }, -}; -*/ - export const NetworkAttachmentDefinitionModel: K8sKind = { label: 'Network Attachment Definition', labelPlural: 'Network Attachment Definitions', diff --git a/frontend/packages/kubevirt-plugin/src/plugin.ts b/frontend/packages/kubevirt-plugin/src/plugin.ts index baefbe7795d3..f003897e08d9 100644 --- a/frontend/packages/kubevirt-plugin/src/plugin.ts +++ b/frontend/packages/kubevirt-plugin/src/plugin.ts @@ -7,7 +7,9 @@ import { ModelFeatureFlag, YAMLTemplate, ModelDefinition, + RoutePage, } from '@console/plugin-sdk'; +import { TemplateModel } from '@console/internal/models'; import * as models from './models'; import { yamlTemplates } from './yaml-templates'; @@ -20,7 +22,8 @@ type ConsumedExtensions = | ResourceDetailsPage | ModelFeatureFlag | YAMLTemplate - | ModelDefinition; + | ModelDefinition + | RoutePage; const FLAG_KUBEVIRT = 'KUBEVIRT'; @@ -50,6 +53,21 @@ const plugin: Plugin = [ mergeAfter: 'Pods', }, }, + { + // NOTE(yaacov): vmtemplates is a template resource with a selector. + // 'NavItem/ResourceNS' is used, and not 'NavItem/Href', because it injects + // the namespace needed to get the correct link to a resource ( template with selector ) in our case. + type: 'NavItem/ResourceNS', + properties: { + section: 'Workloads', + componentProps: { + name: 'Virtual Machine Templates', + resource: 'vmtemplates', + required: FLAG_KUBEVIRT, + }, + mergeAfter: 'Virtual Machines', + }, + }, { type: 'Page/Resource/List', properties: { @@ -67,6 +85,14 @@ const plugin: Plugin = [ template: yamlTemplates.getIn([models.VirtualMachineModel, 'default']), }, }, + { + type: 'YAMLTemplate', + properties: { + model: TemplateModel, + template: yamlTemplates.getIn([TemplateModel, 'vm-template']), + templateName: 'vm-template', + }, + }, { type: 'Page/Resource/Details', properties: { @@ -77,6 +103,16 @@ const plugin: Plugin = [ ).then((m) => m.VirtualMachinesDetailsPage), }, }, + { + type: 'Page/Route', + properties: { + path: [`/k8s/ns/:ns/vmtemplates`, '/k8s/all-namespaces/vmtemplates'], + loader: () => + import( + './components/vm-templates/vm-template' /* webpackChunkName: "kubevirt-vmtemplates" */ + ).then((m) => m.VirtualMachineTemplatesPage), + }, + }, ]; export default plugin; diff --git a/frontend/packages/kubevirt-plugin/src/yaml-templates.ts b/frontend/packages/kubevirt-plugin/src/yaml-templates.ts index ef5da2e7aaeb..5fcc57aa2551 100644 --- a/frontend/packages/kubevirt-plugin/src/yaml-templates.ts +++ b/frontend/packages/kubevirt-plugin/src/yaml-templates.ts @@ -1,10 +1,12 @@ import { Map as ImmutableMap } from 'immutable'; +import { TemplateModel } from '@console/internal/models'; import { VirtualMachineModel } from './models'; -export const yamlTemplates = ImmutableMap().setIn( - [VirtualMachineModel, 'default'], - ` +export const yamlTemplates = ImmutableMap() + .setIn( + [VirtualMachineModel, 'default'], + ` apiVersion: ${VirtualMachineModel.apiGroup}/${VirtualMachineModel.apiVersion} kind: ${VirtualMachineModel.kind} metadata: @@ -39,4 +41,76 @@ spec: cloudInitNoCloud: userDataBase64: SGkuXG4= `, -); + ) + .setIn( + [TemplateModel, 'vm-template'], + ` +apiVersion: ${TemplateModel.apiGroup}/${TemplateModel.apiVersion} +kind: ${TemplateModel.kind} +metadata: + name: vm-template-example + labels: + kubevirt.io/os: fedora27 + miq.github.io/kubevirt-is-vm-template: 'true' + template.kubevirt.io/type: vm + annotations: + description: VM template example + iconClass: icon-fedora + tags: 'kubevirt,ocp,template,linux,virtualmachine' +objects: + - apiVersion: kubevirt.io/v1alpha3 + kind: VirtualMachine + metadata: + creationTimestamp: null + labels: + kubevirt-vm: 'vm-\${NAME}' + kubevirt.io/os: fedora27 + name: '\${NAME}' + spec: + running: false + template: + metadata: + creationTimestamp: null + labels: + kubevirt-vm: 'vm-\${NAME}' + kubevirt.io/os: fedora27 + spec: + domain: + cpu: + cores: '\${CPU_CORES}' + devices: + disks: + - disk: + bus: virtio + name: containerdisk + - disk: + bus: virtio + name: cloudinitdisk + machine: + type: '' + resources: + requests: + memory: '\${MEMORY}' + terminationGracePeriodSeconds: 0 + volumes: + - containerDisk: + image: 'registry:5000/kubevirt/fedora-cloud-container-disk-demo:devel' + name: containerdisk + - cloudInitNoCloud: + userData: |- + #cloud-config + password: fedora + chpasswd: { expire: False } + name: cloudinitdisk + status: {} +parameters: + - name: NAME + description: Name for the new VM + - name: MEMORY + description: Amount of memory + value: 4096Mi + - name: CPU_CORES + description: Amount of cores + value: '4' +`, + );