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 tests for adding/removing disks/nics to/from a vm template #3070

Merged
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
Expand Up @@ -109,9 +109,9 @@ Object.freeze(networkTabCol);

export const diskTabCol = {
name: 0,
size: 1,
interface: 2,
type: 3,
source: 1,
size: 2,
interface: 3,
storageClass: 4,
};
Object.freeze(diskTabCol);
Expand Up @@ -15,7 +15,7 @@ import { vmConfig, getProvisionConfigs, getTestDataVolume } from './vm.wizard.co
import { ProvisionConfigName } from './utils/constants/wizard';

describe('KubeVirt VM detail - edit cdroms', () => {
const testDataVolume = getTestDataVolume(testName);
const testDataVolume = getTestDataVolume();

beforeAll(async () => {
createResources([testDataVolume]);
Expand All @@ -25,7 +25,7 @@ describe('KubeVirt VM detail - edit cdroms', () => {
deleteResources([testDataVolume]);
});
const leakedResources = new Set<string>();
const provisionConfigs = getProvisionConfigs(testName);
const provisionConfigs = getProvisionConfigs();

const configName = ProvisionConfigName.CONTAINER;
const provisionConfig = provisionConfigs.get(configName);
Expand All @@ -36,10 +36,10 @@ describe('KubeVirt VM detail - edit cdroms', () => {
it(
'creates new container CD, then removes it',
async () => {
const vm1Config = vmConfig(configName.toLowerCase(), provisionConfig, testName);
const vm1Config = vmConfig(configName.toLowerCase(), testName, provisionConfig);
vm1Config.startOnCreation = false;

const vm = new VirtualMachine(vmConfig(configName.toLowerCase(), provisionConfig, testName));
const vm = new VirtualMachine(vmConfig(configName.toLowerCase(), testName, provisionConfig));
await withResource(leakedResources, vm.asResource(), async () => {
await vm.create(vm1Config);
await vm.navigateToDetail();
Expand All @@ -66,10 +66,10 @@ describe('KubeVirt VM detail - edit cdroms', () => {
it(
'creates two new container CDs, then ejects and changes them to URL, PVC',
async () => {
const vm1Config = vmConfig(configName.toLowerCase(), provisionConfig, testName);
const vm1Config = vmConfig(configName.toLowerCase(), testName, provisionConfig);
vm1Config.startOnCreation = false;

const vm = new VirtualMachine(vmConfig(configName.toLowerCase(), provisionConfig, testName));
const vm = new VirtualMachine(vmConfig(configName.toLowerCase(), testName, provisionConfig));
await withResource(leakedResources, vm.asResource(), async () => {
await vm.create(vm1Config);
await vm.navigateToDetail();
Expand Down
Expand Up @@ -15,7 +15,7 @@ import { ProvisionConfigName } from './utils/constants/wizard';

describe('KubeVirt VM detail - edit flavor', () => {
const leakedResources = new Set<string>();
const provisionConfigs = getProvisionConfigs(testName);
const provisionConfigs = getProvisionConfigs();

const configName = ProvisionConfigName.CONTAINER;
const provisionConfig = provisionConfigs.get(configName);
Expand All @@ -27,10 +27,10 @@ describe('KubeVirt VM detail - edit flavor', () => {
it(
'changes tiny to large',
async () => {
const vm1Config = vmConfig(configName.toLowerCase(), provisionConfig, testName);
const vm1Config = vmConfig(configName.toLowerCase(), testName, provisionConfig);
Copy link
Member

@atiratree atiratree Dec 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole vmConfig creation is quite painful. the config is modified in 3 places

  1. call getProvisionConfigs
  2. call vmConfig
  3. customize result (you need to be familiar with the config format)
  4. pass it to vm multiple times

IMO, we should introduce builder pattern here with sensible defaults.
e.g

const vm: VirtualMachine = new VMBuilder(ProvisionConfigName.CONTAINER, testname)
    .addStorage(additionalStorage)
    .setNetworks([])
    .startOnCreation(true)
    .build()

vm.create()
console.log(vm.getConfig()) // to inspect

thoughts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes yes yes I agree 100%, I also hate that we need to pass the config twice, first to create the VirtualMachine object and then to the create method.
I'm not sure if this is the right time to do it though because we need to close one epic automation gap epic first and this would be a huge change.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed, I agree it would be nicer but it is a big change in a late moment in the cycle. Lets address as a followup once the automation gap is closed.

vm1Config.startOnCreation = false;

const vm = new VirtualMachine(vmConfig(configName.toLowerCase(), provisionConfig, testName));
const vm = new VirtualMachine(vmConfig(configName.toLowerCase(), testName, provisionConfig));
await withResource(leakedResources, vm.asResource(), async () => {
await vm.create(vm1Config);
await vm.navigateToDetail();
Expand Down Expand Up @@ -72,10 +72,10 @@ describe('KubeVirt VM detail - edit flavor', () => {
it(
'changes tiny to custom',
async () => {
const vm1Config = vmConfig(configName.toLowerCase(), provisionConfig, testName);
const vm1Config = vmConfig(configName.toLowerCase(), testName, provisionConfig);
vm1Config.startOnCreation = false;

const vm = new VirtualMachine(vmConfig(configName.toLowerCase(), provisionConfig, testName));
const vm = new VirtualMachine(vmConfig(configName.toLowerCase(), testName, provisionConfig));
await withResource(leakedResources, vm.asResource(), async () => {
await vm.create(vm1Config);
await vm.navigateToDetail();
Expand Down
@@ -1,4 +1,5 @@
import { OrderedMap } from 'immutable';
import { testName } from '../../../../integration-tests/protractor.conf';
import {
basicVMConfig,
networkInterface,
Expand All @@ -16,22 +17,22 @@ import {
import { resolveStorageDataAttribute, getResourceObject } from './utils/utils';
import { ProvisionConfigName } from './utils/constants/wizard';

export const vmConfig = (name: string, provisionConfig, testName: string) => {
export const vmConfig = (name: string, namespace: string, provisionConfig: ProvisionConfig) => {
const commonSettings = {
startOnCreation: true,
cloudInit: {
useCloudInit: false,
},
namespace: testName,
description: `Default description ${testName}`,
namespace,
description: `Default description ${namespace}`,
flavor: basicVMConfig.flavor,
operatingSystem: basicVMConfig.operatingSystem,
workloadProfile: basicVMConfig.workloadProfile,
};

return {
...commonSettings,
name: `${name}-${testName}`,
name: `${name}-${namespace}`,
provisionSource: provisionConfig.provision,
storageResources: provisionConfig.storageResources,
networkResources: provisionConfig.networkResources,
Expand All @@ -44,7 +45,7 @@ export const kubevirtStorage = getResourceObject(
'configMap',
);

export const getTestDataVolume = (testName: string) =>
export const getTestDataVolume = () =>
dataVolumeManifest({
name: `toclone-${testName}`,
namespace: testName,
Expand All @@ -53,8 +54,8 @@ export const getTestDataVolume = (testName: string) =>
volumeMode: resolveStorageDataAttribute(kubevirtStorage, 'volumeMode'),
});

const getDiskToCloneFrom = (testName: string): StorageResource => {
const testDV = getTestDataVolume(testName);
const getDiskToCloneFrom = (): StorageResource => {
const testDV = getTestDataVolume();
return {
name: testDV.metadata.name,
size: testDV.spec.pvc.resources.requests.storage.slice(0, -2),
Expand All @@ -68,7 +69,7 @@ const getDiskToCloneFrom = (testName: string): StorageResource => {
};
};

export const getProvisionConfigs = (testName: string) =>
export const getProvisionConfigs = () =>
OrderedMap<ProvisionConfigName, ProvisionConfig>()
.set(ProvisionConfigName.URL, {
provision: {
Expand Down Expand Up @@ -98,5 +99,5 @@ export const getProvisionConfigs = (testName: string) =>
method: ProvisionConfigName.DISK,
},
networkResources: [networkInterface],
storageResources: [getDiskToCloneFrom(testName)],
storageResources: [getDiskToCloneFrom()],
});
Expand Up @@ -36,8 +36,8 @@ import {

describe('Kubevirt create VM using wizard', () => {
const leakedResources = new Set<string>();
const provisionConfigs = getProvisionConfigs(testName);
const testDataVolume = getTestDataVolume(testName);
const provisionConfigs = getProvisionConfigs();
const testDataVolume = getTestDataVolume();

beforeAll(async () => {
createResources([multusNAD, testDataVolume]);
Expand All @@ -58,10 +58,10 @@ describe('Kubevirt create VM using wizard', () => {
`Create VM using ${configName}.`,
async () => {
const vm = new VirtualMachine(
vmConfig(configName.toLowerCase(), provisionConfig, testName),
vmConfig(configName.toLowerCase(), testName, provisionConfig),
);
await withResource(leakedResources, vm.asResource(), async () => {
await vm.create(vmConfig(configName.toLowerCase(), provisionConfig, testName));
await vm.create(vmConfig(configName.toLowerCase(), testName, provisionConfig));
});
},
specTimeout,
Expand All @@ -73,8 +73,8 @@ describe('Kubevirt create VM using wizard', () => {
async () => {
const testVMConfig = vmConfig(
'windows10',
provisionConfigs.get(ProvisionConfigName.CONTAINER),
testName,
provisionConfigs.get(ProvisionConfigName.CONTAINER),
);
testVMConfig.networkResources = [];
testVMConfig.operatingSystem = OperatingSystem.WINDOWS_10;
Expand Down Expand Up @@ -122,8 +122,8 @@ describe('Kubevirt create VM using wizard', () => {
async () => {
const testVMConfig = vmConfig(
'test-dv',
provisionConfigs.get(ProvisionConfigName.URL),
testName,
provisionConfigs.get(ProvisionConfigName.URL),
);
testVMConfig.networkResources = [];
const vm = new VirtualMachine(testVMConfig);
Expand All @@ -147,8 +147,8 @@ describe('Kubevirt create VM using wizard', () => {
'Multiple VMs created using "Cloned Disk" method from single source',
async () => {
const clonedDiskProvisionConfig = provisionConfigs.get(ProvisionConfigName.DISK);
const vm1Config = vmConfig('vm1', clonedDiskProvisionConfig, testName);
const vm2Config = vmConfig('vm2', clonedDiskProvisionConfig, testName);
const vm1Config = vmConfig('vm1', testName, clonedDiskProvisionConfig);
const vm2Config = vmConfig('vm2', testName, clonedDiskProvisionConfig);
vm1Config.startOnCreation = false;
vm1Config.networkResources = [];
const vm1 = new VirtualMachine(vm1Config);
Expand Down
@@ -0,0 +1,116 @@
import {
createResource,
deleteResource,
deleteResources,
} from '@console/shared/src/test-utils/utils';
import { get } from 'lodash';
import { testName } from '@console/internal-integration-tests/protractor.conf';
import { TEMPLATE_ACTIONS_TIMEOUT_SECS } from './utils/consts';
import { basicVMConfig, multusNAD, hddDisk, networkInterface, rootDisk } from './utils/mocks';
import { getProvisionConfigs } from './vm.wizard.configs';
import { VirtualMachine } from './models/virtualMachine';
import { VirtualMachineTemplate } from './models/virtualMachineTemplate';
import { ProvisionConfig } from './utils/types';
import { getResourceObject } from './utils/utils';
import { ProvisionConfigName } from './utils/constants/wizard';

describe('Test adding/removing discs/nics to/from a VM template', () => {
const provisionConfigContainer = getProvisionConfigs().get(ProvisionConfigName.CONTAINER);
const commonSettings = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it could incorporate all of these functions and configs, which are quite hard to read IMO

cloudInit: {
useCloudInit: false,
},
namespace: testName,
description: `Default description ${testName}`,
flavor: basicVMConfig.flavor,
operatingSystem: basicVMConfig.operatingSystem,
workloadProfile: basicVMConfig.workloadProfile,
};
const vmTemplateConfig = (name: string, provisionConfig: ProvisionConfig) => {
return {
...commonSettings,
name,
provisionSource: provisionConfig.provision,
storageResources: [],
networkResources: [],
};
};
const vmConfig = (name: string, templateConfig) => {
return {
...commonSettings,
startOnCreation: true,
name,
template: templateConfig.name,
provisionSource: templateConfig.provisionSource,
storageResources: [],
networkResources: [],
};
};

const templateCfg = vmTemplateConfig(
`tmpl-${provisionConfigContainer.provision.method.toLowerCase()}`,
provisionConfigContainer,
);
const vmTemplate = new VirtualMachineTemplate(templateCfg);

const vmCfg = vmConfig(`vmfromtmpl-${vmTemplate.name}`, templateCfg);
const vm = new VirtualMachine(vmCfg);

beforeAll(async () => {
createResource(multusNAD);
await vmTemplate.create(templateCfg);
}, TEMPLATE_ACTIONS_TIMEOUT_SECS);

afterAll(() => {
deleteResources([multusNAD, vmTemplate.asResource()]);
});

describe('Test adding discs/nics to a VM template', () => {
vmCfg.startOnCreation = false;

beforeAll(async () => {
await vmTemplate.addDisk(hddDisk);
await vmTemplate.addNIC(networkInterface);
await vm.create(vmCfg);
}, TEMPLATE_ACTIONS_TIMEOUT_SECS);

afterAll(() => {
deleteResource(vm.asResource());
});

it('Adds a disk to a VM template', async () => {
expect(vm.getAttachedDisks()).toContain(hddDisk);
});

it('Adds a NIC to a VM template', async () => {
expect(vm.getAttachedNICs()).toContain(networkInterface);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the disadvantage of this approach is that Add NIC test will fail if adding disk fails in beforeAll

});

xit('BZ(1779116) Clones disk defined in VM template', async () => {
const dataVolumeName = `${vm.name}-${vmTemplate.name}-${rootDisk.name}-clone`;
const dataVolume = getResourceObject(dataVolumeName, vm.namespace, 'datavolume');
const srcPvc = get(dataVolume, 'spec.source.pvc.name', '');
expect(srcPvc).toEqual(`${vmTemplate.name}-${rootDisk.name}`);
Copy link
Member

@atiratree atiratree Dec 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after #3665 merges, we should check that it is not possible to remove url disk from the template list after the creation.

edit:
I meant edit should not be possible (applies to some vm disks as well)

I guess deletion should be possible - not entirely sure about that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and that the vm source type equals to Attached Clone Disk

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, the naming will change a bit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should also test that datavolume is not leaking after the template deletion

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now disabled, will be addressed in a different PR.

});
});

describe('Test removing discs/nics from a VM template', () => {
beforeAll(async () => {
await vmTemplate.removeDisk(hddDisk.name);
await vmTemplate.removeNIC(networkInterface.name);
await vm.create(vmCfg);
}, TEMPLATE_ACTIONS_TIMEOUT_SECS);

afterAll(() => {
deleteResource(vm.asResource());
});

it('Removes a disk from VM template', async () => {
expect(vm.getAttachedDisks()).not.toContain(hddDisk);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for the remove


it('Removes a NIC from VM template', async () => {
expect(vm.getAttachedNICs()).not.toContain(networkInterface);
});
});
});