package jetbrains.buildServer.clouds.vmware;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import jetbrains.buildServer.BaseTestCase;
import jetbrains.buildServer.clouds.*;
import jetbrains.buildServer.clouds.base.stubs.DummyCloudManagerBase;
import jetbrains.buildServer.clouds.server.CloudManagerBase;
import jetbrains.buildServer.clouds.server.impl.profile.CloudProfileDataImpl;
import jetbrains.buildServer.clouds.server.impl.profile.CloudProfileImpl;
import jetbrains.buildServer.clouds.vmware.stubs.FakeApiConnector;
import jetbrains.buildServer.clouds.vmware.tasks.VmwareUpdateTaskManager;
import jetbrains.buildServer.clouds.vmware.web.VMWareWebConstants;
import jetbrains.buildServer.serverSide.InvalidProperty;
import org.jetbrains.annotations.NotNull;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static jetbrains.buildServer.clouds.vmware.VmwareCloudIntegrationTest.PROFILE_ID;
import static jetbrains.buildServer.clouds.vmware.VmwareCloudIntegrationTest.TEST_SERVER_UUID;
/**
* Created by Sergey.Pak on 6/9/2016.
*/
@Test
public class VmwarePropertiesProcessorTest extends BaseTestCase {
private VmwarePropertiesProcessor myProcessor;
private Map<String, String> myProperties;
private Collection<CloudProfile> myProfiles;
private Map<String, CloudClientEx> myClients;
private static final String PROJECT_ID = "project4";
@BeforeMethod
@Override
protected void setUp() throws Exception {
super.setUp();
final CloudManagerBase cloudManager = new DummyCloudManagerBase(){
@NotNull
@Override
public Collection<CloudProfile> listProfilesByProject(final String projectId, final boolean includeFromSubprojects) {
return myProfiles;
}
@Override
public Collection<CloudProfile> listAllProfiles() {
return myProfiles;
}
@NotNull
@Override
public CloudClientEx getClient(final String projectId, @NotNull final String profileId) {
return myClients.get(profileId);
}
};
myProcessor = new VmwarePropertiesProcessor(cloudManager);
myProfiles = new ArrayList<>();
myClients = new HashMap<>();
myProperties = new HashMap<>();
myProperties.put(VMWareWebConstants.USERNAME, "un");
myProperties.put(VMWareWebConstants.SECURE_PASSWORD, "pw");
myProperties.put(VMWareWebConstants.SERVER_URL, "http://localhost:9099");
}
public void check_base_properties(){
check_no_errors();
myProperties.remove(VMWareWebConstants.USERNAME);
expect_error(VMWareWebConstants.USERNAME, "Value should be set");
myProperties.put(VMWareWebConstants.USERNAME, "un");
myProperties.remove(VMWareWebConstants.SECURE_PASSWORD);
expect_error(VMWareWebConstants.SECURE_PASSWORD, "Value should be set");
myProperties.put(VMWareWebConstants.SECURE_PASSWORD, "pw");
myProperties.remove(VMWareWebConstants.SERVER_URL);
expect_error(VMWareWebConstants.SERVER_URL, "Value should be set");
}
public void check_profile_instance_limit(){
myProperties.put(VMWareWebConstants.PROFILE_INSTANCE_LIMIT, "2");
check_no_errors();
myProperties.put(VMWareWebConstants.PROFILE_INSTANCE_LIMIT, "0");
expect_error("vmware_profile_instance_limit", "Must be a positive integer or empty");
myProperties.put(VMWareWebConstants.PROFILE_INSTANCE_LIMIT, "aaaa");
expect_error("vmware_profile_instance_limit", "Must be a positive integer or empty");
}
public void check_same_source_ids_new_profile() throws IOException {
final CloudProfileDataImpl profileData = new CloudProfileDataImpl();
profileData.setCloudCode(VmwareConstants.TYPE);
profileData.setName("Vmware profile");
CloudClientParameters cloudClientParameters = new CloudClientParameters();
cloudClientParameters.setParameter(VMWareWebConstants.SERVER_URL, "http://localhost:8080");
cloudClientParameters.setCloudImages(CloudImageParameters.collectionFromJson("[{sourceVmName:'image1', behaviour:'START_STOP'}," +
"{sourceVmName:'image2',snapshot:'snap*',folder:'cf',pool:'rp',maxInstances:3,behaviour:'ON_DEMAND_CLONE', " +
"customizationSpec:'someCustomization'}," +
"{sourceVmName:'image_template', snapshot:'" + VmwareConstants.CURRENT_STATE +
"',folder:'cf',pool:'rp',maxInstances:3,behaviour:'FRESH_CLONE', customizationSpec: 'linux'}]"));
profileData.setParameters(cloudClientParameters);
final String profileId = "vmw-1";
myProfiles.add(new CloudProfileImpl(PROJECT_ID, profileId, profileData));
myProperties.put(VMWareWebConstants.SERVER_URL, "http://localhost:8080");
myProperties.put(CloudImageParameters.SOURCE_IMAGES_JSON,
"[{'source-id':'image2',sourceVmName:'image2',snapshot:'snap*',folder:'cf',pool:'rp',maxInstances:3,behaviour:'ON_DEMAND_CLONE', " +
"customizationSpec:'someCustomization'}]");
myClients.put(profileId, createClient(cloudClientParameters));
expect_error("source_images_json", "The cloud profile 'Vmware profile' already contains an image named 'IMAGE2'. Select a different VM or change the custom name.");
}
public void check_same_source_ids_edit_profile() throws IOException {
{
final String profileId = "vmw-1";
final CloudProfileDataImpl profileData = new CloudProfileDataImpl();
profileData.setCloudCode(VmwareConstants.TYPE);
profileData.setName("Vmware profile");
CloudClientParameters cloudClientParameters = new CloudClientParameters();
cloudClientParameters.setParameter(VMWareWebConstants.SERVER_URL, "http://localhost:8080");
cloudClientParameters.setCloudImages(CloudImageParameters.collectionFromJson("[{'source-id':'image1',sourceVmName:'image1', behaviour:'START_STOP'}," +
"{'source-id':'image2',sourceVmName:'image2',snapshot:'snap*',folder:'cf',pool:'rp',maxInstances:3,behaviour:'ON_DEMAND_CLONE', " +
"customizationSpec:'someCustomization'}," +
"{'source-id':'image_template',sourceVmName:'image_template', snapshot:'" + VmwareConstants.CURRENT_STATE +
"',folder:'cf',pool:'rp',maxInstances:3,behaviour:'FRESH_CLONE', customizationSpec: 'linux'}]"));
profileData.setParameters(cloudClientParameters);
myProfiles.add(new CloudProfileImpl(PROJECT_ID, profileId, profileData));
myClients.put(profileId, createClient(cloudClientParameters));
}
{
final String profileId = "vmw-2";
final CloudProfileDataImpl profileData = new CloudProfileDataImpl();
profileData.setCloudCode(VmwareConstants.TYPE);
profileData.setName("Vmware profile 2");
CloudClientParameters cloudClientParameters = new CloudClientParameters();
cloudClientParameters.setParameter(VMWareWebConstants.SERVER_URL, "http://localhost:8080");
cloudClientParameters.setCloudImages(CloudImageParameters.collectionFromJson("[{'source-id':'image3',sourceVmName:'image3', behaviour:'START_STOP'}," +
"{'source-id':'image4',sourceVmName:'image4',snapshot:'snap*',folder:'cf',pool:'rp',maxInstances:3,behaviour:'ON_DEMAND_CLONE', " +
"customizationSpec:'someCustomization'}," +
"{'source-id':'image_template2',sourceVmName:'image_template2', snapshot:'" + VmwareConstants.CURRENT_STATE +
"',folder:'cf',pool:'rp',maxInstances:3,behaviour:'FRESH_CLONE', customizationSpec: 'linux'}]"));
profileData.setParameters(cloudClientParameters);
myProfiles.add(new CloudProfileImpl(PROJECT_ID, profileId, profileData));
myClients.put(profileId, createClient(cloudClientParameters));
}
myProperties.put(CloudConstants.PROFILE_ID, "vmw-2");
myProperties.put(VMWareWebConstants.SERVER_URL, "http://localhost:8080");
myProperties.put(CloudImageParameters.SOURCE_IMAGES_JSON,
"[{'source-id':'image2',sourceVmName:'image2',snapshot:'snap*',folder:'cf',pool:'rp',maxInstances:3,behaviour:'ON_DEMAND_CLONE', " +
"customizationSpec:'someCustomization'}]");
expect_error("source_images_json", "The cloud profile 'Vmware profile' already contains an image named 'IMAGE2'. Select a different VM or change the custom name.");
myProperties.put(CloudImageParameters.SOURCE_IMAGES_JSON,
"[{'source-id':'image3',sourceVmName:'image2',nickname:'image3',snapshot:'snap*',folder:'cf',pool:'rp',maxInstances:3,behaviour:'ON_DEMAND_CLONE', " +
"customizationSpec:'someCustomization'}]");
check_no_errors();
}
public void check_same_source_same_server_url() throws IOException {
{
final String profileId = "vmw-1";
final CloudProfileDataImpl profileData = new CloudProfileDataImpl();
profileData.setCloudCode(VmwareConstants.TYPE);
profileData.setName("Vmware profile");
CloudClientParameters cloudClientParameters = new CloudClientParameters();
cloudClientParameters.setParameter(VMWareWebConstants.SERVER_URL, "http://localhost:8081");
cloudClientParameters.setCloudImages(CloudImageParameters.collectionFromJson("[{'source-id':'image1',sourceVmName:'image1', behaviour:'START_STOP'}," +
"{'source-id':'image2',sourceVmName:'image2',snapshot:'snap*',folder:'cf',pool:'rp',maxInstances:3,behaviour:'ON_DEMAND_CLONE', " +
"customizationSpec:'someCustomization'}," +
"{'source-id':'image_template',sourceVmName:'image_template', snapshot:'" + VmwareConstants.CURRENT_STATE +
"',folder:'cf',pool:'rp',maxInstances:3,behaviour:'FRESH_CLONE', customizationSpec: 'linux'}]"));
profileData.setParameters(cloudClientParameters);
myProfiles.add(new CloudProfileImpl(PROJECT_ID, profileId, profileData));
myClients.put(profileId, createClient(cloudClientParameters));
}
{
final String profileId = "vmw-2";
final CloudProfileDataImpl profileData = new CloudProfileDataImpl();
profileData.setCloudCode(VmwareConstants.TYPE);
profileData.setName("Vmware profile 2");
CloudClientParameters cloudClientParameters = new CloudClientParameters();
cloudClientParameters.setParameter(VMWareWebConstants.SERVER_URL, "http://localhost:8082");
cloudClientParameters.setCloudImages(CloudImageParameters.collectionFromJson("[{'source-id':'image3',sourceVmName:'image3', behaviour:'START_STOP'}," +
"{'source-id':'image4',sourceVmName:'image4',snapshot:'snap*',folder:'cf',pool:'rp',maxInstances:3,behaviour:'ON_DEMAND_CLONE', " +
"customizationSpec:'someCustomization'}," +
"{'source-id':'image_template2',sourceVmName:'image_template2', snapshot:'" + VmwareConstants.CURRENT_STATE +
"',folder:'cf',pool:'rp',maxInstances:3,behaviour:'FRESH_CLONE', customizationSpec: 'linux'}]"));
profileData.setParameters(cloudClientParameters);
myProfiles.add(new CloudProfileImpl(PROJECT_ID, profileId, profileData));
myClients.put(profileId, createClient(cloudClientParameters));
}
myProperties.put(VMWareWebConstants.SERVER_URL, "http://localhost:8081");
myProperties.put(CloudImageParameters.SOURCE_IMAGES_JSON,
"[{'source-id':'image2',sourceVmName:'image2',snapshot:'snap*',folder:'cf',pool:'rp',maxInstances:3,behaviour:'ON_DEMAND_CLONE', " +
"customizationSpec:'someCustomization'}]");
expect_error("source_images_json", "The cloud profile 'Vmware profile' already contains an image named 'IMAGE2'. Select a different VM or change the custom name.");
myProperties.put(VMWareWebConstants.SERVER_URL, "http://localhost:8082");
check_no_errors();
}
private void expect_error(String fieldName, String reasonText){
final Collection<InvalidProperty> process = myProcessor.process(myProperties);
if (process.size() == 0){
fail("Expected 1 InvalidProperty: " + fieldName + " - " + reasonText);
}
StringBuilder errors = new StringBuilder();
process.stream()
.filter(i-> !(reasonText.equals(i.getInvalidReason()) && i.getPropertyName().equals(fieldName)))
.map(InvalidProperty::toString)
.forEachOrdered(p -> {
errors.append(p).append("\n");
});
if (errors.length() > 0)
fail("Unexpected failures: \n" + errors.toString());
}
private void check_no_errors(){
final Collection<InvalidProperty> process = myProcessor.process(myProperties);
if (process.size() != 0){
StringBuilder errors = new StringBuilder("Unexpected failures:\n");
process.stream().map(InvalidProperty::toString).forEachOrdered(p->{
errors.append(p).append("\n");
});
fail(errors.toString());
}
}
private CloudClientEx createClient(CloudClientParameters clientParameters) throws IOException {
final Collection<VmwareCloudImageDetails> images = VMWareCloudClientFactory.parseImageDataInternal(clientParameters);
FakeApiConnector apiConnector = new FakeApiConnector(TEST_SERVER_UUID, PROFILE_ID);
VMWareCloudClient client = new VMWareCloudClient(clientParameters, apiConnector, new VmwareUpdateTaskManager(), createTempDir());
client.populateImagesData(images, 1000, 1000);
return client;
}
@AfterMethod
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
}