http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiExpectTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiExpectTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiExpectTest.java new file mode 100644 index 0000000..493630b --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiExpectTest.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.features; + +import org.jclouds.cloudstack.CloudStackContext; +import org.jclouds.cloudstack.domain.AsyncCreateResponse; +import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import java.net.URI; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +import static org.testng.Assert.assertNotNull; + +/** +* Test the CloudStack VolumeApi +* +*/ +@Test(groups = "unit", testName = "VolumeApiExpectTest") +public class VolumeApiExpectTest extends BaseCloudStackExpectTest<VolumeApi> { + + public void testCreateVolumeFromCustomDiskOffering() throws NoSuchAlgorithmException, CertificateException { + VolumeApi client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=createVolume&name=VolumeApiExpectTest-jclouds-volume&diskofferingid=0473f5dd-bca5-4af4-a9b6-db9e8a88a2f6&zoneid=6f9a2921-b22a-4149-8b71-6ffc275a2177&size=1&apiKey=identity&signature=%2BoEjGobVFLr58k19LeAE81bZkKM%3D")) + .addHeader("Accept", "application/json") + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/queryasyncjobresultresponse-createvolume.json")) + .build()); + + AsyncCreateResponse response = client.createVolumeFromCustomDiskOfferingInZone("VolumeApiExpectTest-jclouds-volume", "0473f5dd-bca5-4af4-a9b6-db9e8a88a2f6", "6f9a2921-b22a-4149-8b71-6ffc275a2177", 1); + assertNotNull(response); + } + + @Override + protected VolumeApi clientFrom(CloudStackContext context) { + return context.getApi().getVolumeApi(); + } +}
http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiLiveTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiLiveTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiLiveTest.java new file mode 100644 index 0000000..7ffc3b4 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiLiveTest.java @@ -0,0 +1,264 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.features; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNotSame; +import static org.testng.AssertJUnit.assertNull; +import static org.testng.AssertJUnit.assertTrue; + +import java.util.NoSuchElementException; +import java.util.Set; + +import javax.annotation.Resource; + +import org.jclouds.cloudstack.CloudStackApi; +import org.jclouds.cloudstack.domain.AsyncCreateResponse; +import org.jclouds.cloudstack.domain.DiskOffering; +import org.jclouds.cloudstack.domain.Snapshot; +import org.jclouds.cloudstack.domain.VirtualMachine; +import org.jclouds.cloudstack.domain.Volume; +import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest; +import org.jclouds.cloudstack.options.ListVolumesOptions; +import org.jclouds.logging.Logger; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * Tests behavior of {@code VolumeApi} + */ +@Test(groups = "live", singleThreaded = true, testName = "VolumeApiLiveTest") +public class VolumeApiLiveTest extends BaseCloudStackApiLiveTest { + + @Resource Logger logger = Logger.NULL; + + protected String prefix = System.getProperty("user.name") + "-" + getClass().getSimpleName(); + + private String zoneId; + + @BeforeMethod(groups = "live") + public void setZoneId() { + Set<Zone> zones = client.getZoneApi().listZones(); + assertNotNull(zones); + assertFalse(zones.isEmpty()); + zoneId = Iterables.get(zones, 0).getId(); + } + + public void testListVolumes() { + Set<Volume> volumes = client.getVolumeApi().listVolumes(); + assertNotNull(volumes); + assertFalse(volumes.isEmpty()); + + for (Volume volume : volumes) { + checkVolume(volume); + } + } + + public void testListVolumesById() { + Iterable<String> volumeIds = Iterables.transform(client.getVolumeApi().listVolumes(), new Function<Volume, String>() { + public String apply(Volume input) { + return input.getId(); + } + }); + assertNotNull(volumeIds); + assertFalse(Iterables.isEmpty(volumeIds)); + + for (String id : volumeIds) { + Set<Volume> found = client.getVolumeApi().listVolumes(ListVolumesOptions.Builder.id(id)); + assertNotNull(found); + assertEquals(1, found.size()); + Volume volume = Iterables.getOnlyElement(found); + assertEquals(id, volume.getId()); + checkVolume(volume); + } + } + + public void testListVolumesNonexistantId() { + Set<Volume> found = client.getVolumeApi().listVolumes(ListVolumesOptions.Builder.id("foo")); + assertNotNull(found); + assertTrue(found.isEmpty()); + } + + public void testGetVolumeById() { + Iterable<String> volumeIds = Iterables.transform(client.getVolumeApi().listVolumes(), new Function<Volume, String>() { + public String apply(Volume input) { + return input.getId(); + } + }); + assertNotNull(volumeIds); + assertFalse(Iterables.isEmpty(volumeIds)); + + for (String id : volumeIds) { + Volume found = client.getVolumeApi().getVolume(id); + assertNotNull(found); + assertEquals(id, found.getId()); + checkVolume(found); + } + } + + public void testGetVolumeNonexistantId() { + Volume found = client.getVolumeApi().getVolume("foo"); + assertNull(found); + } + + protected DiskOffering getPreferredDiskOffering() { + for (DiskOffering candidate : client.getOfferingApi().listDiskOfferings()) { + //any will do + return candidate; + } + throw new AssertionError("No suitable DiskOffering found."); + } + protected Snapshot getPreferredSnapshot() { + for (Snapshot candidate : client.getSnapshotApi().listSnapshots()) { + if (candidate.getState() == Snapshot.State.BACKED_UP) + return candidate; + } + throw new AssertionError("No suitable Snapshot found."); + } + + protected VirtualMachine getPreferredVirtualMachine() { + for (VirtualMachine candidate : client.getVirtualMachineApi().listVirtualMachines()) { +// this is a guess:: + if (candidate.getState() == VirtualMachine.State.RUNNING || candidate.getState() == VirtualMachine.State.STOPPED) + return candidate; + } + throw new AssertionError("No suitable VirtualMachine found."); + } + + protected Volume createPreferredVolumeFromDisk() { + AsyncCreateResponse job = client.getVolumeApi().createVolumeFromDiskOfferingInZone(prefix + "-jclouds-volume", + getPreferredDiskOffering().getId(), zoneId); + assertTrue(jobComplete.apply(job.getJobId())); + logger.info("created volume " + job.getId()); + return findVolumeWithId(job.getId()); + } + + public void testCreateVolumeFromDiskofferingInZoneAndDeleteVolume() { + logger.info("testCreateVolumeFromDiskofferingInZoneAndDeleteVolume"); + Volume volume = createPreferredVolumeFromDisk(); + checkVolume(volume); + client.getVolumeApi().deleteVolume(volume.getId()); + } + + /** Test requires a custom disk offering to be available */ + public void testCreateVolumeFromCustomDiskOffering() { + final int size = 1; + DiskOffering offering = null; + for (DiskOffering candidate : client.getOfferingApi().listDiskOfferings()) { + if (candidate.isCustomized()) { + offering = candidate; + break; + } + } + + assertNotNull("No custom disk offering found!", offering); + + AsyncCreateResponse job = client.getVolumeApi().createVolumeFromCustomDiskOfferingInZone( + prefix + "-jclouds-volume", offering.getId(), zoneId, size); + assertTrue(jobComplete.apply(job.getJobId())); + logger.info("created volume " + job.getId()); + + Volume volume = findVolumeWithId(job.getId()); + try { + checkVolume(volume); + assertEquals(volume.getSize(), size * 1024 * 1024 * 1024); + } finally { + client.getVolumeApi().deleteVolume(volume.getId()); + } + } + + /** test requires that a VM exist */ + public void testCreateVolumeFromDiskofferingInZoneAndAttachVolumeToVirtualMachineAndDetachAndDelete() { + logger.info("testCreateVolumeFromDiskofferingInZoneAndAttachVolumeToVirtualMachineAndDetachAndDelete"); + final Volume volume = createPreferredVolumeFromDisk(); + try { + + checkVolume(volume); + + VirtualMachine virtualMachine = getPreferredVirtualMachine(); + + logger.info("attaching volume %s to vm %s", volume, virtualMachine); + AsyncCreateResponse job = client.getVolumeApi().attachVolume(volume.getId(), virtualMachine.getId()); + assertTrue(jobComplete.apply(job.getJobId())); + Volume attachedVolume = findVolumeWithId(volume.getId()); + + checkVolume(attachedVolume); + assertEquals(virtualMachine.getId(), attachedVolume.getVirtualMachineId()); + assertNotNull(attachedVolume.getAttached()); + + logger.info("detaching volume %s from vm %s", volume, virtualMachine); + job = client.getVolumeApi().detachVolume(volume.getId()); + assertTrue(jobComplete.apply(job.getJobId())); + Volume detachedVolume = findVolumeWithId(volume.getId()); + + checkVolume(detachedVolume); + assertNull(detachedVolume.getAttached()); + + } finally { + client.getVolumeApi().deleteVolume(volume.getId()); + } + } + + public void testCreateVolumeFromSnapshotInZoneAndDeleteVolume() { + logger.info("testCreateVolumeFromSnapshotInZoneAndDeleteVolume (takes ~3m)"); + assertNotNull(getPreferredSnapshot()); + + AsyncCreateResponse job = client.getVolumeApi().createVolumeFromSnapshotInZone(prefix + "-jclouds-volume", + getPreferredSnapshot().getId(), zoneId); + assertTrue(jobComplete.apply(job.getJobId())); + Volume volume = findVolumeWithId(job.getId()); + + checkVolume(volume); + client.getVolumeApi().deleteVolume(volume.getId()); + } + + static void checkVolume(final Volume volume) { + assertNotNull(volume.getId()); + assertNotNull(volume.getName()); + assertNotSame(Volume.Type.UNRECOGNIZED, volume.getType()); + } + + Volume findVolumeWithId(final String id) { + return findVolumeWithId(client, id); + } + + static Volume findVolumeWithId(final CloudStackApi client, final String id) { + for (Volume v : client.getVolumeApi().listVolumes()) + if (v.getId().equals(id)) return v; + throw new NoSuchElementException("no volume with id " + id); + } + +// //uncomment to force a cleanup of volumes (since test failures can leave messes) +// public void deleteAllWeUsed() { +// for (Volume v: client.getVolumeApi().listVolumes()) { +// if (v.getName().startsWith(prefix)) { +// logger.warn("found apparent detritus, deleting: %s", v); +// try { +// client.getVolumeApi().deleteVolume(v.getId()); +// } catch (Exception e) { +// logger.warn(e, "failed to delete %s: %s", v, e); +// } +// } +// } +// } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiTest.java new file mode 100644 index 0000000..9002f46 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/VolumeApiTest.java @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.features; + +import static org.jclouds.reflect.Reflection2.method; + +import java.io.IOException; + +import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; +import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.Fallbacks.VoidOnNotFoundOr404; +import org.jclouds.cloudstack.internal.BaseCloudStackApiTest; +import org.jclouds.cloudstack.options.ListVolumesOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.reflect.Invokable; +/** + * Tests behavior of {@code EventApi} + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during +// surefire +@Test(groups = "unit", testName = "VolumeApiTest") +public class VolumeApiTest extends BaseCloudStackApiTest<VolumeApi> { + + public void testListVolumes() throws SecurityException, NoSuchMethodException, IOException { + Invokable<?, ?> method = method(VolumeApi.class, "listVolumes", ListVolumesOptions[].class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of()); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=listVolumes&listAll=true HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertSaxResponseParserClassEquals(method, null); + assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testGetVolume() throws SecurityException, NoSuchMethodException, IOException { + Invokable<?, ?> method = method(VolumeApi.class, "getVolume", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L)); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=listVolumes&listAll=true&id=111 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertSaxResponseParserClassEquals(method, null); + assertFallbackClassEquals(method, NullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + HttpRequest createVolumeFromSnapshot = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "createVolume") + .addQueryParam("name", "jclouds-volume") + .addQueryParam("snapshotid", "999") + .addQueryParam("zoneid", "111").build(); + + public void testCreateVolumeWithSnapshot() throws SecurityException, NoSuchMethodException, IOException { + Invokable<?, ?> method = method(VolumeApi.class, "createVolumeFromSnapshotInZone", String.class, String.class, + String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of("jclouds-volume", 999L, 111l)); + + assertRequestLineEquals(httpRequest, createVolumeFromSnapshot.getRequestLine()); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertSaxResponseParserClassEquals(method, null); + checkFilters(httpRequest); + + } + + HttpRequest createVolumeFromDiskOffering = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "createVolume") + .addQueryParam("name", "jclouds-volume") + .addQueryParam("diskofferingid", "999") + .addQueryParam("zoneid", "111").build(); + + public void testCreateVolumeFromDiskOffering() throws SecurityException, NoSuchMethodException, IOException { + Invokable<?, ?> method = method(VolumeApi.class, "createVolumeFromDiskOfferingInZone", String.class, String.class, + String.class); + + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of("jclouds-volume", 999L, 111L)); + + assertRequestLineEquals(httpRequest, createVolumeFromDiskOffering.getRequestLine()); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertSaxResponseParserClassEquals(method, null); + checkFilters(httpRequest); + + } + + public void testAttachVolume() throws SecurityException, NoSuchMethodException, IOException { + Invokable<?, ?> method = method(VolumeApi.class, "attachVolume", String.class, String.class); + + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L, 999L)); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=attachVolume&id=111&virtualmachineid=999 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertSaxResponseParserClassEquals(method, null); + checkFilters(httpRequest); + + } + + public void testDetachVolume() throws SecurityException, NoSuchMethodException, IOException { + Invokable<?, ?> method = method(VolumeApi.class, "detachVolume", String.class); + + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L)); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=detachVolume&id=111 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertSaxResponseParserClassEquals(method, null); + checkFilters(httpRequest); + + } + + public void testDeleteVolume() throws SecurityException, NoSuchMethodException, IOException { + Invokable<?, ?> method = method(VolumeApi.class, "deleteVolume", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L)); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=deleteVolume&id=111 HTTP/1.1"); + assertPayloadEquals(httpRequest, null, null, false); + + assertSaxResponseParserClassEquals(method, null); + assertFallbackClassEquals(method, VoidOnNotFoundOr404.class); + checkFilters(httpRequest); + + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java new file mode 100644 index 0000000..2d709ad --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.features; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import org.jclouds.cloudstack.CloudStackContext; +import org.jclouds.cloudstack.domain.NetworkType; +import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * Test the CloudStack ZoneApi + */ +@Test(groups = "unit", testName = "ZoneApiExpectTest") +public class ZoneApiExpectTest extends BaseCloudStackExpectTest<ZoneApi> { + + + public void testListZonesWhenResponseIs2xx() { + ZoneApi client = requestSendsResponse( + HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "listZones") + .addQueryParam("listAll", "true") + .addQueryParam("apiKey", "identity") + .addQueryParam("signature", "8iHCtck0qfxFTqJ8reyAObRf31I%3D") + .addHeader("Accept", "application/json") + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/listzonesresponse.json")) + .build()); + + assertEquals(client.listZones(), + ImmutableSet.of( + Zone.builder() + .id("1") + .name("San Jose 1") + .networkType(NetworkType.ADVANCED) + .securityGroupsEnabled(false).build(), + Zone.builder() + .id("2") + .name("Chicago") + .networkType(NetworkType.ADVANCED) + .securityGroupsEnabled(true).build())); + } + + public void testListZonesWhenResponseIs404() { + ZoneApi client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=listZones&listAll=true&apiKey=identity&signature=8iHCtck0qfxFTqJ8reyAObRf31I%3D")) + .addHeader("Accept", "application/json") + .build(), + HttpResponse.builder() + .statusCode(404) + .build()); + + assertEquals(client.listZones(), ImmutableSet.of()); + } + + @Override + protected ZoneApi clientFrom(CloudStackContext context) { + return context.getApi().getZoneApi(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiLiveTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiLiveTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiLiveTest.java new file mode 100644 index 0000000..ae1b480 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiLiveTest.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.features; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.util.Set; + +import org.jclouds.cloudstack.domain.NetworkType; +import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest; +import org.jclouds.cloudstack.options.ListZonesOptions; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; + +/** + * Tests behavior of {@code ZoneApiLiveTest} + */ +@Test(groups = "live", singleThreaded = true, testName = "ZoneApiLiveTest") +public class ZoneApiLiveTest extends BaseCloudStackApiLiveTest { + + public void testListZones() throws Exception { + Set<Zone> response = client.getZoneApi().listZones(); + assert null != response; + long zoneCount = response.size(); + assertTrue(zoneCount >= 0); + for (Zone zone : response) { + Zone newDetails = Iterables.getOnlyElement(client.getZoneApi().listZones( + ListZonesOptions.Builder.id(zone.getId()))); + assertEquals(zone, newDetails); + assertEquals(zone, client.getZoneApi().getZone(zone.getId())); + assert zone.getId() != null : zone; + assert zone.getName() != null : zone; + assert zone.getNetworkType() != null && zone.getNetworkType() != NetworkType.UNRECOGNIZED : zone; + switch (zone.getNetworkType()) { + case ADVANCED: + // TODO + // assert zone.getVLAN() != null : zone; + // assert zone.getDomain() == null : zone; + // assert zone.getDomainId() == null : zone; + // assert zone.getGuestCIDRAddress() != null : zone; + break; + case BASIC: + assert zone.getVLAN() == null : zone; + assert zone.getDNS().size() >= 0 : zone; + assert zone.getInternalDNS().size() >= 0 : zone; + assert zone.getDomain() == null : zone; + assert zone.getDomainId() == null : zone; + assert zone.getGuestCIDRAddress() == null : zone; + break; + } + + } + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiTest.java new file mode 100644 index 0000000..bb5674f --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/features/ZoneApiTest.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.features; + +import static org.jclouds.reflect.Reflection2.method; + +import java.io.IOException; + +import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; +import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.cloudstack.internal.BaseCloudStackApiTest; +import org.jclouds.cloudstack.options.ListZonesOptions; +import org.jclouds.functions.IdentityFunction; +import org.jclouds.http.functions.ParseFirstJsonValueNamed; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.testng.annotations.Test; + +import com.google.common.base.Functions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.reflect.Invokable; +/** + * Tests behavior of {@code ZoneApi} + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during +// surefire +@Test(groups = "unit", testName = "ZoneApiTest") +public class ZoneApiTest extends BaseCloudStackApiTest<ZoneApi> { + public void testListZones() throws SecurityException, NoSuchMethodException, IOException { + Invokable<?, ?> method = method(ZoneApi.class, "listZones", ListZonesOptions[].class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of()); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + // now make sure request filters apply by replaying + httpRequest = (GeneratedHttpRequest) Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + httpRequest = (GeneratedHttpRequest) Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + + assertRequestLineEquals( + httpRequest, + "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true&apiKey=identity&signature=8iHCtck0qfxFTqJ8reyAObRf31I%3D HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class); + assertSaxResponseParserClassEquals(method, null); + assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testListZonesOptions() throws SecurityException, NoSuchMethodException, IOException { + Invokable<?, ?> method = method(ZoneApi.class, "listZones", ListZonesOptions[].class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(ListZonesOptions.Builder.available(true).domainId("5") + .id("6"))); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true&available=true&domainid=5&id=6 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class); + assertSaxResponseParserClassEquals(method, null); + assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testGetZone() throws SecurityException, NoSuchMethodException, IOException { + Invokable<?, ?> method = method(ZoneApi.class, "getZone", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(6)); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true&id=6 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, + Functions.compose(IdentityFunction.INSTANCE, IdentityFunction.INSTANCE).getClass()); + assertSaxResponseParserClassEquals(method, null); + assertFallbackClassEquals(method, NullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/filters/QuerySignerTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/filters/QuerySignerTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/filters/QuerySignerTest.java new file mode 100644 index 0000000..2af22ba --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/filters/QuerySignerTest.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.filters; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.ContextBuilder; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.IntegrationTestClient; +import org.jclouds.logging.config.NullLoggingModule; +import org.jclouds.providers.AnonymousProviderMetadata; +import org.jclouds.rest.internal.BaseRestApiTest.MockModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.inject.Injector; +import com.google.inject.Module; + +/** + * Tests behavior of {@code QuerySigner} + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during +// surefire +@Test(groups = "unit", testName = "QuerySignerTest") +public class QuerySignerTest { + public static final Injector INJECTOR = ContextBuilder + .newBuilder( + AnonymousProviderMetadata.forApiOnEndpoint(IntegrationTestClient.class, + "http://localhost:8080/client/api")) + .credentials("apiKey", "secretKey") + .apiVersion("2.2") + .modules(ImmutableList.<Module> of(new MockModule(), new NullLoggingModule())).buildInjector(); + + + @Test + void testCreateStringToSign() { + QuerySigner filter = INJECTOR.getInstance(QuerySigner.class); + + assertEquals( + filter.createStringToSign(HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api?command=listZones").build()), + "apikey=apikey&command=listzones"); + } + + @Test + void testCreateStringToSignWithBrackets() { + // This test asserts that key *names* are not URL-encoded - only values + // should be encoded, according to "CloudStack API Developerâs Guide". + QuerySigner filter = INJECTOR.getInstance(QuerySigner.class); + + assertEquals( + filter.createStringToSign(HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api?command=deployVirtualMachine&iptonetworklist[0].ip=127.0.0.1&iptonetworklist[0].networkid=1").build()), + "apikey=apikey&command=deployvirtualmachine&iptonetworklist[0].ip=127.0.0.1&iptonetworklist[0].networkid=1"); + } + + @Test + void testFilter() { + QuerySigner filter = INJECTOR.getInstance(QuerySigner.class); + + assertEquals( + filter.filter( + HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api?command=listZones").build()) + .getRequestLine(), + "GET http://localhost:8080/client/api?command=listZones&apiKey=apiKey&signature=2UG8AcnMaozL3BINdjgkJ%2BRzjEY%3D HTTP/1.1"); + } + + @Test + void testFilterTwice() { + QuerySigner filter = INJECTOR.getInstance(QuerySigner.class); + HttpRequest request = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api?command=listZones").build(); + for (int i = 0; i < 2; i++) { + request = filter.filter(request); + assertEquals( + request.getRequestLine(), + "GET http://localhost:8080/client/api?command=listZones&apiKey=apiKey&signature=2UG8AcnMaozL3BINdjgkJ%2BRzjEY%3D HTTP/1.1"); + } + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/BlockUntilJobCompletesAndReturnResultTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/BlockUntilJobCompletesAndReturnResultTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/BlockUntilJobCompletesAndReturnResultTest.java new file mode 100644 index 0000000..85c7c6c --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/BlockUntilJobCompletesAndReturnResultTest.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.functions; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.testng.Assert.assertEquals; + +import org.jclouds.cloudstack.CloudStackApi; +import org.jclouds.cloudstack.domain.AsyncCreateResponse; +import org.jclouds.cloudstack.domain.AsyncJob; +import org.jclouds.cloudstack.domain.AsyncJobError; +import org.jclouds.cloudstack.domain.AsyncJobError.ErrorCode; +import org.jclouds.cloudstack.features.AsyncJobApi; +import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult; +import org.testng.annotations.Test; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.util.concurrent.UncheckedExecutionException; + +@Test(groups = "unit", testName = "BlockUntilJobCompletesAndReturnResultTest") +public class BlockUntilJobCompletesAndReturnResultTest { + + public void testApply() { + String id = "1"; + String jobId = "2"; + + CloudStackApi client = createMock(CloudStackApi.class); + Predicate<String> jobComplete = Predicates.alwaysTrue(); + AsyncJobApi jobClient = createMock(AsyncJobApi.class); + + expect(client.getAsyncJobApi()).andReturn(jobClient).atLeastOnce(); + expect(jobClient.getAsyncJob(jobId)).andReturn(AsyncJob.builder().id(jobId).result("foo").build()).atLeastOnce(); + + replay(client); + replay(jobClient); + + assertEquals( + new BlockUntilJobCompletesAndReturnResult(client, jobComplete).<String>apply(AsyncCreateResponse.builder().id(id).jobId( + jobId).build()), "foo"); + + verify(client); + verify(jobClient); + + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testJobDoesntCompleteThrowsIllegalStateException() { + String id = "1"; + String jobId = "2"; + + CloudStackApi client = createMock(CloudStackApi.class); + // the alwaysfalse predicate should blow up with IllegalStateException + Predicate<String> jobComplete = Predicates.alwaysFalse(); + AsyncJobApi jobClient = createMock(AsyncJobApi.class); + + expect(client.getAsyncJobApi()).andReturn(jobClient).atLeastOnce(); + expect(jobClient.getAsyncJob(jobId)).andReturn(AsyncJob.builder().id(jobId).result("foo").build()).atLeastOnce(); + + replay(client); + replay(jobClient); + + assertEquals( + new BlockUntilJobCompletesAndReturnResult(client, jobComplete).<String>apply( + AsyncCreateResponse.builder().id(id).jobId(jobId).build()), "foo"); + + verify(client); + verify(jobClient); + + } + + @Test(expectedExceptions = UncheckedExecutionException.class) + public void testJobWithErrorThrowsUncheckedExecutionException() { + String id = "1"; + String jobId = "2"; + + CloudStackApi client = createMock(CloudStackApi.class); + Predicate<String> jobComplete = Predicates.alwaysTrue(); + AsyncJobApi jobClient = createMock(AsyncJobApi.class); + + expect(client.getAsyncJobApi()).andReturn(jobClient).atLeastOnce(); + expect(jobClient.getAsyncJob(jobId)).andReturn( + AsyncJob.builder().id(jobId) + .error(AsyncJobError.builder().errorCode(ErrorCode.INTERNAL_ERROR).errorText("ERRROR").build()) + .result("foo").build()) + .atLeastOnce(); + + replay(client); + replay(jobClient); + + assertEquals( + new BlockUntilJobCompletesAndReturnResult(client, jobComplete).<String>apply( + AsyncCreateResponse.builder().id(id).jobId(jobId).build()), "foo"); + + verify(client); + verify(jobClient); + + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/CreateSecurityGroupIfNeededTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/CreateSecurityGroupIfNeededTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/CreateSecurityGroupIfNeededTest.java new file mode 100644 index 0000000..7d840dc --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/CreateSecurityGroupIfNeededTest.java @@ -0,0 +1,233 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.functions; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; +import static org.jclouds.util.Predicates2.retry; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.testng.Assert.assertEquals; + +import java.net.UnknownHostException; +import javax.inject.Singleton; + +import org.jclouds.cloudstack.CloudStackApi; +import org.jclouds.cloudstack.domain.IngressRule; +import org.jclouds.cloudstack.domain.SecurityGroup; +import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.cloudstack.domain.ZoneSecurityGroupNamePortsCidrs; +import org.jclouds.cloudstack.features.AsyncJobApi; +import org.jclouds.cloudstack.features.SecurityGroupApi; +import org.jclouds.cloudstack.features.ZoneApi; +import org.jclouds.cloudstack.predicates.JobComplete; +import org.jclouds.cloudstack.suppliers.ZoneIdToZoneSupplier; +import org.testng.annotations.Test; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; +import com.google.inject.name.Names; + +@Test(groups = "unit", testName = "CreateSecurityGroupIfNeededTest") +public class CreateSecurityGroupIfNeededTest { + + @Test + public void testApply() throws UnknownHostException { + final CloudStackApi client = createMock(CloudStackApi.class); + SecurityGroupApi secClient = createMock(SecurityGroupApi.class); + ZoneApi zoneClient = createMock(ZoneApi.class); + AsyncJobApi jobClient = createMock(AsyncJobApi.class); + + SecurityGroup group = createMock(SecurityGroup.class); + + Zone zone = createMock(Zone.class); + + expect(group.getIngressRules()).andReturn(ImmutableSet.<IngressRule> of()); + expect(group.getId()).andReturn("sec-1234").anyTimes(); + expect(zone.isSecurityGroupsEnabled()).andReturn(true); + + expect(client.getSecurityGroupApi()).andReturn(secClient) + .anyTimes(); + expect(client.getZoneApi()).andReturn(zoneClient); + expect(client.getAsyncJobApi()).andReturn(jobClient).anyTimes(); + + expect(zoneClient.getZone("zone-abc1")).andReturn(zone); + expect(secClient.createSecurityGroup("group-1")).andReturn(group); + expect(secClient.authorizeIngressPortsToCIDRs("sec-1234", + "TCP", + 22, + 22, + ImmutableSet.of("0.0.0.0/0"))).andReturn("job-1234"); + + replay(client, secClient, zoneClient, zone, group); + + ZoneSecurityGroupNamePortsCidrs input = ZoneSecurityGroupNamePortsCidrs.builder() + .zone("zone-abc1") + .name("group-1") + .ports(ImmutableSet.of(22)) + .cidrs(ImmutableSet.<String> of()).build(); + + CreateSecurityGroupIfNeeded parser = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral<Supplier<String>>() { + }).toInstance(Suppliers.ofInstance("1")); + bind(CloudStackApi.class).toInstance(client); + bind(new TypeLiteral<CacheLoader<String, Zone>>() {}). + to(ZoneIdToZone.class); + bind(new TypeLiteral<Supplier<LoadingCache<String, Zone>>>() {}). + to(ZoneIdToZoneSupplier.class); + bind(String.class).annotatedWith(Names.named(PROPERTY_SESSION_INTERVAL)).toInstance("60"); + } + + @Provides + @Singleton + protected Predicate<String> jobComplete(JobComplete jobComplete) { + return retry(jobComplete, 1200, 1, 5, SECONDS); + } + + }).getInstance(CreateSecurityGroupIfNeeded.class); + + assertEquals(parser.apply(input), group); + + verify(client, secClient, zoneClient, zone, group); + } + + + @Test + public void testApplyGroupAlreadyExists() throws UnknownHostException { + final CloudStackApi client = createMock(CloudStackApi.class); + SecurityGroupApi secClient = createMock(SecurityGroupApi.class); + ZoneApi zoneClient = createMock(ZoneApi.class); + AsyncJobApi jobClient = createMock(AsyncJobApi.class); + + SecurityGroup group = createMock(SecurityGroup.class); + + Zone zone = createMock(Zone.class); + + expect(group.getId()).andReturn("sec-1234").anyTimes(); + expect(zone.isSecurityGroupsEnabled()).andReturn(true); + + expect(client.getSecurityGroupApi()).andReturn(secClient) + .anyTimes(); + expect(client.getZoneApi()).andReturn(zoneClient); + expect(client.getAsyncJobApi()).andReturn(jobClient).anyTimes(); + + expect(zoneClient.getZone("zone-abc2")).andReturn(zone); + expect(secClient.createSecurityGroup("group-1")).andThrow(new IllegalStateException()); + expect(secClient.getSecurityGroupByName("group-1")).andReturn(group); + + replay(client, secClient, zoneClient, zone, group); + + ZoneSecurityGroupNamePortsCidrs input = ZoneSecurityGroupNamePortsCidrs.builder() + .zone("zone-abc2") + .name("group-1") + .ports(ImmutableSet.of(22)) + .cidrs(ImmutableSet.<String> of()).build(); + + CreateSecurityGroupIfNeeded parser = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral<Supplier<String>>() { + }).toInstance(Suppliers.ofInstance("1")); + bind(CloudStackApi.class).toInstance(client); + bind(new TypeLiteral<CacheLoader<String, Zone>>() {}). + to(ZoneIdToZone.class); + bind(new TypeLiteral<Supplier<LoadingCache<String, Zone>>>() {}). + to(ZoneIdToZoneSupplier.class); + bind(String.class).annotatedWith(Names.named(PROPERTY_SESSION_INTERVAL)).toInstance("60"); + } + + @Provides + @Singleton + protected Predicate<String> jobComplete(JobComplete jobComplete) { + return retry(jobComplete, 1200, 1, 5, SECONDS); + } + + }).getInstance(CreateSecurityGroupIfNeeded.class); + + assertEquals(parser.apply(input), group); + + verify(client, secClient, zoneClient, zone, group); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testApplyZoneNoSecurityGroups() throws UnknownHostException { + final CloudStackApi client = createMock(CloudStackApi.class); + SecurityGroupApi secClient = createMock(SecurityGroupApi.class); + ZoneApi zoneClient = createMock(ZoneApi.class); + AsyncJobApi jobClient = createMock(AsyncJobApi.class); + + SecurityGroup group = createMock(SecurityGroup.class); + + Zone zone = createMock(Zone.class); + + expect(zone.isSecurityGroupsEnabled()).andReturn(false); + + expect(client.getZoneApi()).andReturn(zoneClient); + + expect(zoneClient.getZone("zone-abc3")).andReturn(zone); + + replay(client, zoneClient, zone); + + ZoneSecurityGroupNamePortsCidrs input = ZoneSecurityGroupNamePortsCidrs.builder() + .zone("zone-abc3") + .name("group-1") + .ports(ImmutableSet.of(22)) + .cidrs(ImmutableSet.<String> of()).build(); + + CreateSecurityGroupIfNeeded parser = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral<Supplier<String>>() { + }).toInstance(Suppliers.ofInstance("1")); + bind(CloudStackApi.class).toInstance(client); + bind(new TypeLiteral<CacheLoader<String, Zone>>() {}). + to(ZoneIdToZone.class); + bind(new TypeLiteral<Supplier<LoadingCache<String, Zone>>>() {}). + to(ZoneIdToZoneSupplier.class); + bind(String.class).annotatedWith(Names.named(PROPERTY_SESSION_INTERVAL)).toInstance("60"); + } + + @Provides + @Singleton + protected Predicate<String> jobComplete(JobComplete jobComplete) { + return retry(jobComplete, 1200, 1, 5, SECONDS); + } + + }).getInstance(CreateSecurityGroupIfNeeded.class); + + assertEquals(parser.apply(input), group); + + verify(client, zoneClient, zone); + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ParseAsyncJobFromHttpResponseTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ParseAsyncJobFromHttpResponseTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ParseAsyncJobFromHttpResponseTest.java new file mode 100644 index 0000000..04aeee3 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ParseAsyncJobFromHttpResponseTest.java @@ -0,0 +1,217 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.functions; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.io.InputStream; + +import org.jclouds.cloudstack.domain.AsyncJob; +import org.jclouds.cloudstack.domain.AsyncJob.ResultCode; +import org.jclouds.cloudstack.domain.AsyncJob.Status; +import org.jclouds.cloudstack.domain.AsyncJobError; +import org.jclouds.cloudstack.domain.AsyncJobError.ErrorCode; +import org.jclouds.cloudstack.domain.IPForwardingRule; +import org.jclouds.cloudstack.domain.PublicIPAddress; +import org.jclouds.cloudstack.domain.Template; +import org.jclouds.cloudstack.domain.TemplateExtraction; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.domain.JsonBall; +import org.jclouds.http.HttpResponse; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.inject.Guice; +import com.google.inject.Injector; + +@Test(groups = "unit") +public class ParseAsyncJobFromHttpResponseTest { + + Injector i = Guice.createInjector(new GsonModule() { + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + + }); + + public void testWithNoResult() { + String input = "{ \"queryasyncjobresultresponse\" : {\"jobid\":860,\"jobstatus\":0,\"jobprocstatus\":0,\"jobresultcode\":0} }"; + + AsyncJob<PublicIPAddress> expects = AsyncJob.<PublicIPAddress>builder() + .id("860") + .status(Status.IN_PROGRESS) + .progress(0) + .resultCode(ResultCode.SUCCESS).build(); + + ParseAsyncJobFromHttpResponse parser = i.getInstance(ParseAsyncJobFromHttpResponse.class); + @SuppressWarnings("unchecked") + AsyncJob<PublicIPAddress> response = (AsyncJob<PublicIPAddress>) parser.apply(HttpResponse.builder() + .statusCode(200).message("ok") + .payload(input).build()); + + assertEquals(response, expects); + } + + public void testWithSuccessTrueResultSetsNullResult() { + String input = "{ \"queryasyncjobresultresponse\" : {\"jobid\":1138,\"jobstatus\":1,\"jobprocstatus\":0,\"jobresultcode\":0,\"jobresulttype\":\"object\",\"jobresult\":{\"success\":true}} }"; + + AsyncJob<PublicIPAddress> expects = AsyncJob.<PublicIPAddress>builder() + .id("1138") + .status(Status.SUCCEEDED) + .progress(0) + .resultType("object") + .resultCode(ResultCode.SUCCESS).build(); + + ParseAsyncJobFromHttpResponse parser = i.getInstance(ParseAsyncJobFromHttpResponse.class); + @SuppressWarnings("unchecked") + AsyncJob<PublicIPAddress> response = (AsyncJob<PublicIPAddress>) parser.apply(HttpResponse.builder() + .statusCode(200).message("ok") + .payload(input).build()); + assertEquals(response, expects); + } + + public void testWithErrorSetsResultNullSoToAvoidClassCastExceptions() { + String input = "{ \"queryasyncjobresultresponse\" : {\"jobid\":1103,\"jobstatus\":2,\"jobprocstatus\":0,\"jobresultcode\":530,\"jobresulttype\":\"object\",\"jobresult\":{\"errorcode\":530,\"errortext\":\"Internal error executing command, please contact your system administrator\"}} }"; + + AsyncJob<PublicIPAddress> expects = AsyncJob + .<PublicIPAddress>builder() + .id("1103") + .status(Status.FAILED) + .progress(0) + .resultType("object") + .error(AsyncJobError.builder().errorCode(ErrorCode.INTERNAL_ERROR).errorText("Internal error executing " + + "command, please contact your system administrator").build()) + .resultCode(ResultCode.FAIL).build(); + + ParseAsyncJobFromHttpResponse parser = i.getInstance(ParseAsyncJobFromHttpResponse.class); + @SuppressWarnings("unchecked") + AsyncJob<PublicIPAddress> response = (AsyncJob<PublicIPAddress>) parser.apply(HttpResponse.builder() + .statusCode(200).message("ok") + .payload(input).build()); + assertEquals(response, expects); + } + + public void testWithUnknownResultReturnsStringifiedJson() { + String input = "{ \"queryasyncjobresultresponse\" : {\"jobid\":860,\"jobstatus\":0,\"jobprocstatus\":0,\"jobresultcode\":0,\"jobresult\":{\"foo\":{\"bar\":1}}}}"; + + AsyncJob<?> expects = AsyncJob.builder() + .id("860") + .status(Status.IN_PROGRESS) + .progress(0) + .resultCode(ResultCode.SUCCESS) + .result("{\"bar\":1}") + .build(); + + ParseAsyncJobFromHttpResponse parser = i.getInstance(ParseAsyncJobFromHttpResponse.class); + @SuppressWarnings("unchecked") + AsyncJob<PublicIPAddress> response = (AsyncJob<PublicIPAddress>) parser.apply(HttpResponse.builder() + .statusCode(200).message("ok") + .payload(input).build()); + assertEquals(response, expects); + } + + public void testWithBadResultReturnsMap() { + // Not the best result object, but this is an unexpected error case. + // Cloud.com have verified + // that this case will not happen. This code is only here to prevent + // exceptions from being + // thrown in case they change their minds. + String input = "{ \"queryasyncjobresultresponse\" : {\"jobid\":860,\"jobstatus\":0,\"jobprocstatus\":0,\"jobresultcode\":0,\"jobresult\":{\"foo\":{\"bar\":1},\"foo2\":{\"bar2\":2}}}}"; + + AsyncJob<?> expects = AsyncJob.builder() + .id("860") + .status(Status.IN_PROGRESS) + .progress(0) + .resultCode(ResultCode.SUCCESS) + .result(ImmutableMap.of("foo", new JsonBall("{\"bar\":1}"), "foo2", new JsonBall("{\"bar2\":2}"))).build(); + + ParseAsyncJobFromHttpResponse parser = i.getInstance(ParseAsyncJobFromHttpResponse.class); + @SuppressWarnings("unchecked") + AsyncJob<PublicIPAddress> response = (AsyncJob<PublicIPAddress>) parser.apply(HttpResponse.builder() + .statusCode(200).message("ok") + .payload(input).build()); + assertEquals(response, expects); + } + + public void testPublicIPAddress() { + InputStream is = getClass().getResourceAsStream("/queryasyncjobresultresponse-ipaddress.json"); + AsyncJob<PublicIPAddress> expects = AsyncJob + .<PublicIPAddress>builder() + .id("860") + .status(Status.SUCCEEDED) + .progress(0) + .resultType("object") + .resultCode(ResultCode.SUCCESS) + .result( + PublicIPAddress + .builder() + .id("6") + .IPAddress("72.52.126.35") + .allocated( + new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-02-23T20:15:01-0800")) + .zoneId("1").zoneName("San Jose 1").isSourceNAT(false).account("adrian").domainId("1") + .domain("ROOT").usesVirtualNetwork(true).isStaticNAT(false).associatedNetworkId("204") + .networkId("200").state(PublicIPAddress.State.ALLOCATING).build() + + ).build(); + + ParseAsyncJobFromHttpResponse parser = i.getInstance(ParseAsyncJobFromHttpResponse.class); + @SuppressWarnings("unchecked") + AsyncJob<PublicIPAddress> response = (AsyncJob<PublicIPAddress>) parser.apply(HttpResponse.builder() + .statusCode(200).message("ok") + .payload(is).build()); + assertEquals(response, expects); + } + + public void testIPForwardingRule() { + InputStream is = getClass().getResourceAsStream("/queryasyncjobresultresponse-ipforwardingrule.json"); + AsyncJob<IPForwardingRule> expects = AsyncJob + .<IPForwardingRule>builder() + .id("1133") + .status(Status.SUCCEEDED) + .progress(0) + .resultType("object") + .resultCode(ResultCode.SUCCESS) + .result( + IPForwardingRule.builder().id("109").protocol("tcp").virtualMachineId("226") + .virtualMachineName("i-3-226-VM").IPAddressId("36").IPAddress("72.52.126.65").startPort(22) + .endPort(22).state("Active").build()).build(); + + ParseAsyncJobFromHttpResponse parser = i.getInstance(ParseAsyncJobFromHttpResponse.class); + @SuppressWarnings("unchecked") + AsyncJob<IPForwardingRule> response = (AsyncJob<IPForwardingRule>) parser.apply(HttpResponse.builder() + .statusCode(200).message("ok") + .payload(is).build()); + assertEquals(response, expects); + } + + public void testOverloadedKeyName() { + InputStream is = getClass().getResourceAsStream("/queryasyncjobresultresponse-createtemplate.json"); + ParseAsyncJobFromHttpResponse parser = i.getInstance(ParseAsyncJobFromHttpResponse.class); + AsyncJob<?> response = parser.apply(HttpResponse.builder().statusCode(200).message("ok").payload(is).build()); + assertTrue(response.getResult() instanceof Template, "response expected to be Template, actually is " + response.getResult().getClass()); + + is = getClass().getResourceAsStream("/queryasyncjobresultresponse-extracttemplate.json"); + response = parser.apply(HttpResponse.builder().statusCode(200).message("ok").payload(is).build()); + assertTrue(response.getResult() instanceof TemplateExtraction, "response expected to be TemplateExtraction, actually is " + response.getResult().getClass()); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ParseAsyncJobsFromHttpResponseTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ParseAsyncJobsFromHttpResponseTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ParseAsyncJobsFromHttpResponseTest.java new file mode 100644 index 0000000..bb04433 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ParseAsyncJobsFromHttpResponseTest.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.util.Set; + +import org.jclouds.cloudstack.domain.AsyncJob; +import org.jclouds.http.HttpResponse; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +@Test(groups = "unit") +public class ParseAsyncJobsFromHttpResponseTest { + + Injector injector = Guice.createInjector(new GsonModule() { + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + + }); + + public void testCanParse() { + InputStream is = getClass().getResourceAsStream("/listasyncjobsresponse.json"); + + ParseAsyncJobsFromHttpResponse parser = injector.getInstance(ParseAsyncJobsFromHttpResponse.class); + Set<AsyncJob<?>> response = parser.apply(HttpResponse.builder().statusCode(200).message("ok").payload(is).build()); + + assertEquals(response.size(), 77); + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ReuseOrAssociateNewPublicIPAddressTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ReuseOrAssociateNewPublicIPAddressTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ReuseOrAssociateNewPublicIPAddressTest.java new file mode 100644 index 0000000..327e1c1 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/ReuseOrAssociateNewPublicIPAddressTest.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.functions; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.jclouds.cloudstack.options.AssociateIPAddressOptions.Builder.networkId; +import static org.jclouds.cloudstack.options.ListPublicIPAddressesOptions.Builder.allocatedOnly; +import static org.testng.Assert.assertEquals; + +import org.jclouds.cloudstack.CloudStackApi; +import org.jclouds.cloudstack.domain.AsyncCreateResponse; +import org.jclouds.cloudstack.domain.Network; +import org.jclouds.cloudstack.domain.PublicIPAddress; +import org.jclouds.cloudstack.features.AddressApi; +import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +@Test(groups = "unit") +public class ReuseOrAssociateNewPublicIPAddressTest { + String networkId = "99l"; + String zoneId = "100l"; + // note that it is associated network, not networkId + PublicIPAddress address = PublicIPAddress.builder().id("200").state(PublicIPAddress.State.ALLOCATED) + .associatedNetworkId(networkId).zoneId(zoneId).build(); + + public void testReuseWorks() throws SecurityException, NoSuchMethodException { + + // create mocks + CloudStackApi client = createMock(CloudStackApi.class); + BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult = createMock(BlockUntilJobCompletesAndReturnResult.class); + AddressApi addressClient = createMock(AddressApi.class); + expect(client.getAddressApi()).andReturn(addressClient).atLeastOnce(); + + // an address is available + expect(addressClient.listPublicIPAddresses(allocatedOnly(true).networkId(networkId))).andReturn( + ImmutableSet.<PublicIPAddress> of(address)); + + replay(client); + replay(blockUntilJobCompletesAndReturnResult); + replay(addressClient); + + assertEquals( + new ReuseOrAssociateNewPublicIPAddress(client, blockUntilJobCompletesAndReturnResult).apply(Network + .builder().id(networkId).zoneId(zoneId).build()), address); + + verify(client); + verify(blockUntilJobCompletesAndReturnResult); + verify(addressClient); + + } + + public void testAssociateWorks() throws SecurityException, NoSuchMethodException { + + // create mocks + CloudStackApi client = createMock(CloudStackApi.class); + BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult = createMock(BlockUntilJobCompletesAndReturnResult.class); + AddressApi addressClient = createMock(AddressApi.class); + expect(client.getAddressApi()).andReturn(addressClient).atLeastOnce(); + + // no ip addresses available + expect(addressClient.listPublicIPAddresses(allocatedOnly(true).networkId(networkId))).andReturn( + ImmutableSet.<PublicIPAddress> of()); + + AsyncCreateResponse job = AsyncCreateResponse.builder().id("1").jobId("2").build(); + // make sure we created the job relating to a new ip + expect(addressClient.associateIPAddressInZone(zoneId, networkId(networkId))).andReturn(job); + + expect(blockUntilJobCompletesAndReturnResult.apply(job)).andReturn(address); + + replay(client); + replay(addressClient); + replay(blockUntilJobCompletesAndReturnResult); + + assertEquals( + new ReuseOrAssociateNewPublicIPAddress(client, blockUntilJobCompletesAndReturnResult).apply(Network + .builder().id(networkId).zoneId(zoneId).build()), address); + + verify(client); + verify(addressClient); + verify(blockUntilJobCompletesAndReturnResult); + + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java new file mode 100644 index 0000000..75bfd18 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.functions; + +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.find; +import static com.google.common.collect.Iterables.getOnlyElement; +import static org.testng.Assert.assertEquals; + +import java.util.NoSuchElementException; +import java.util.Set; + +import org.jclouds.cloudstack.domain.IPForwardingRule; +import org.jclouds.cloudstack.domain.Network; +import org.jclouds.cloudstack.domain.PublicIPAddress; +import org.jclouds.cloudstack.domain.VirtualMachine; +import org.jclouds.cloudstack.features.NATApiLiveTest; +import org.jclouds.cloudstack.features.VirtualMachineApiLiveTest; +import org.jclouds.cloudstack.predicates.NetworkPredicates; +import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.base.Predicate; +import com.google.common.cache.CacheBuilder; +import com.google.common.collect.ImmutableSet; +import com.google.common.net.HostAndPort; + +/** + * Tests behavior of {@code StaticNATVirtualMachineInNetwork} + */ +@Test(groups = "live", singleThreaded = true, testName = "StaticNATVirtualMachineInNetworkLiveTest") +public class StaticNATVirtualMachineInNetworkLiveTest extends NATApiLiveTest { + private PublicIPAddress ip = null; + private VirtualMachine vm; + private IPForwardingRule rule; + private Network network; + private boolean networksDisabled; + + @BeforeGroups(groups = "live") + public void setupClient() { + super.setupContext(); + prefix += "nat"; + try { + network = find(client.getNetworkApi().listNetworks(), NetworkPredicates.supportsStaticNAT()); + String defaultTemplate = template != null ? template.getImageId() : null; + vm = VirtualMachineApiLiveTest.createVirtualMachineInNetwork(network, + defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), client, jobComplete, + virtualMachineRunning); + if (vm.getPassword() != null && !loginCredentials.getOptionalPassword().isPresent()) + loginCredentials = loginCredentials.toBuilder().password(vm.getPassword()).build(); + } catch (NoSuchElementException e) { + networksDisabled = true; + } + } + + public void testCreateIPForwardingRule() throws Exception { + if (networksDisabled) + return; + BlockUntilJobCompletesAndReturnResult blocker = new BlockUntilJobCompletesAndReturnResult(client, jobComplete); + StaticNATVirtualMachineInNetwork fn = new StaticNATVirtualMachineInNetwork(client, reuseOrAssociate, network); + CreatePortForwardingRulesForIP createPortForwardingRulesForIP = new CreatePortForwardingRulesForIP(client, + blocker, CacheBuilder.newBuilder().<String, Set<IPForwardingRule>> build( + new GetIPForwardingRulesByVirtualMachine(client))); + + // logger + injector.injectMembers(blocker); + injector.injectMembers(fn); + injector.injectMembers(createPortForwardingRulesForIP); + + ip = fn.apply(vm); + + createPortForwardingRulesForIP.apply(ip, ImmutableSet.of(22)); + + rule = getOnlyElement(filter(client.getNATApi().getIPForwardingRulesForIPAddress(ip.getId()), + new Predicate<IPForwardingRule>() { + @Override + public boolean apply(IPForwardingRule rule) { + return rule != null && rule.getStartPort() == 22; + } + })); + assertEquals(rule.getIPAddressId(), ip.getId()); + assertEquals(rule.getVirtualMachineId(), vm.getId()); + assertEquals(rule.getStartPort(), 22); + assertEquals(rule.getProtocol(), "tcp"); + checkRule(rule); + HostAndPort socket = HostAndPort.fromParts(ip.getIPAddress(), 22); + checkSSH(socket); + } + + @AfterGroups(groups = "live") + @Override + protected void tearDownContext() { + if (rule != null) { + client.getNATApi().deleteIPForwardingRule(rule.getId()); + } + if (vm != null) { + jobComplete.apply(client.getVirtualMachineApi().destroyVirtualMachine(vm.getId())); + } + if (ip != null) { + client.getAddressApi().disassociateIPAddress(ip.getId()); + } + super.tearDownContext(); + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/WindowsLoginCredentialsFromEncryptedDataTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/WindowsLoginCredentialsFromEncryptedDataTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/WindowsLoginCredentialsFromEncryptedDataTest.java new file mode 100644 index 0000000..a59ecad --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/functions/WindowsLoginCredentialsFromEncryptedDataTest.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.cloudstack.functions; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; + +import org.jclouds.cloudstack.domain.EncryptedPasswordAndPrivateKey; +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.encryption.internal.JCECrypto; +import org.testng.annotations.Test; + +public class WindowsLoginCredentialsFromEncryptedDataTest { + + private static final String PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEowIBAAKCAQEAmN6GOSMnyGNWN19ETBh11tJB5OGs3Dps8kPWqAhF9RyL/mKwkW26vH+h/5Z5\n" + + "cA5T80pK72kNnXObFaMHNoX3lavrc6yXF+8F3f1tlFX2Z+iB1pYXz1oBPqT6oOmc2XzcsJuJRakd\n" + + "zwRwHDaqljpaW7+TZlxhMa1DmUkD/HHMxDCK8jbUIZDc6BZSrnj2uPwHwW737NRE4aC3fcu4LMwf\n" + + "b2VotbNGNiAnNmrb/vtIIGkFE8NYEMpiz0WYTWX4eVKpJImv1PR6G1fMLSvudJs0ARObuLDvuonn\n" + + "SCFFdkibrwMKYbHVGGh6FoY1Vy0sqI55dgQU1kSNouiDgOGxgx+TIwIDAQABAoIBAHCS/nk5QGS7\n" + + "cpRYXa1EHhNSxx/MaUXM6MoH1x3q6cm1egqdlrWh/vAtdZkIsOkqQ/xX65Me493dcomegwNN6KOZ\n" + + "9Uw7/xCq/sEZjga8vzaJ7IOgCGy0NVJyn/a70rv+zW5pO8/G2KLI+95rC3iSBFSoYd3xjcnNdIh/\n" + + "UqYnD8oxYpKmf7418pMPsBrkglkFlbVBPiDXdpoSziqSN6uWQG4Yh0WR87aElhM9JJW50Hh6h7g5\n" + + "OvgCBzS8G+KXCjqimk108+/ed5Nl6VhPAf79yCVZUueKBhaf2r0Kkyxg7M/Y+LJwcoUusIP7Cv7G\n" + + "xyzG2vi21prWRCm2sVCUDyQy5qECgYEA92jGVAaB3OGEUIXn7eVE3U3FQH37XcJMGsHqBIzDG13p\n" + + "C97HdN21rwRkz+G2eAsIxA+p9BsO7dSmtKC60kl6iMRgltS3W7xoC37N9BtjhpciHcLg8c70oyDx\n" + + "qHiLKuDi90mZ1FPmWupO4FJnGEB3evHUKZSpTrVVMzt+tyEn/psCgYEAni1hrYoMkQgN3sEC3CKB\n" + + "0jQkrOMvY219B8Tdf9LXSuP6z9POagDBDhkeT3xn8rAOmOfVGHYdO0CvPqmAkmXhf+g+OREdecQa\n" + + "uY0FmvcTt+Dx0c6pRZmm5AhvUVXFXqONsSg79iviXbUy5Hik0k5HTs5E6B4obrh5W+xfMTUXghkC\n" + + "gYBn92uAW8uumkYT4HF6EuJBbTD6zPYYjFGW3O4OQ2ip02jfSBrhDVoP1fTXNq6K+3gPi9WLcuNv\n" + + "JfF37iMTwzTuzDcaqwDyV9YRHpRFhEzqfhAkGYSVmLZM5scmWKGCv0YhTJiMFUWz5sqGkZopIs4S\n" + + "qBTT9FjBbooDIXk6U4CPCQKBgFdVBxEhnz6UC9RpDIMuKi88yuMJrChhUx7u+ryQVH3s0ZXdg6HT\n" + + "OMPn6mxIa7v6qJSTq3wN+qW0WQ1n2Kz7wz0zpOctI/EO7RJ1YhrlP+XONLV6PMtIwnQ0lAF8MbTG\n" + + "6HxfknugTyMd4DN0yMu0nHpOOI1P2VMIVzkBkK1CevBBAoGBALROGR7a+eijHdp0/A0chfUoBmud\n" + + "/TsUt+0g/vf1p69rMt6DqEGMgMtp2jIRnwvLElS7gVqnCTEclxNU/0rCXR+V7ImJm8J4f0ff8m0Y\n" + + "Fir9nfCYStszo25NvLFfynS9d/aoBuvqGJaiQyNXiyBJ4MaxxFYagzAWTnDX+kzTlkZ2\n" + + "-----END RSA PRIVATE KEY-----"; + private static final String ENCRYPTED_PASSWORD = "gO1oMoIjjIifv2iqcfIKiQD7ziOTVXsuaBJFEQrZdb8uJH/LsAiJXZeGKEeXlHl/oMoR3HEIoYuHxl+p5iHdrpP889RmxWBDGOWC5iTUzK6CRa5mFmF1I5Lpt7v2YeVoQWihSM8B19BEdBdY1svQp9nyhPB4AqLDrY28x/OrmRh/qYq953i6Y4Z8c76OHqqGcUYM4ePysRlcizSgQjdkEDmKC10Ak3OFRRx3/LqYsFIMiOHeg47APg+UANNTyRiTIia5FDhSeHJzaeYCBRQ7UYH0z2rg4cX3YjOz/MoznjHiaaN4MO+5N3v84VawnqwKOvlwPyI2bmz0+9Tr6DKzqA=="; + + protected final DateService dateService = new SimpleDateFormatDateService(); + + @Test + public void testApply() throws Exception { + WindowsLoginCredentialsFromEncryptedData f = new WindowsLoginCredentialsFromEncryptedData(new JCECrypto()); + + LoginCredentials credentials = f.apply(new EncryptedPasswordAndPrivateKey(ENCRYPTED_PASSWORD, PRIVATE_KEY)); + + assertEquals(credentials.getUser(), "Administrator"); + assertEquals(credentials.getOptionalPassword().get(), "u4.y9mb;nR."); + assertFalse(credentials.getOptionalPrivateKey().isPresent()); + } +}
