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'
+`,
+ );