merge
diff --git a/apis/cloudservers/pom.xml b/apis/cloudservers/pom.xml
index 5eea292..41a3c0a 100644
--- a/apis/cloudservers/pom.xml
+++ b/apis/cloudservers/pom.xml
@@ -37,12 +37,10 @@
<properties>
<test.cloudservers.endpoint>https://auth.api.rackspacecloud.com</test.cloudservers.endpoint>
<test.cloudservers.api-version>1.0</test.cloudservers.api-version>
- <test.cloudservers.build-version />
+ <test.cloudservers.build-version></test.cloudservers.build-version>
<test.cloudservers.identity>${test.rackspace.identity}</test.cloudservers.identity>
<test.cloudservers.credential>${test.rackspace.credential}</test.cloudservers.credential>
- <test.cloudservers.image-id />
- <test.cloudservers.image.login-user />
- <test.cloudservers.image.authenticate-sudo />
+ <test.cloudservers.template></test.cloudservers.template>
<jclouds.osgi.export>org.jclouds.cloudservers*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -120,10 +118,8 @@
<test.cloudstack.build-version>${test.cloudstack.build-version}</test.cloudstack.build-version>
<test.cloudstack.identity>${test.cloudstack.identity}</test.cloudstack.identity>
<test.cloudstack.credential>${test.cloudstack.credential}</test.cloudstack.credential>
- <test.cloudstack.image-id>${test.cloudstack.image-id}</test.cloudstack.image-id>
- <test.cloudstack.image.login-user>${test.cloudstack.image.login-user}</test.cloudstack.image.login-user>
- <test.cloudstack.image.authenticate-sudo>${test.cloudstack.image.authenticate-sudo}</test.cloudstack.image.authenticate-sudo>
- </systemPropertyVariables>
+ <test.cloudstack.template>${test.cloudstack.template}</test.cloudstack.template>
+ </systemPropertyVariables>
</configuration>
</execution>
</executions>
diff --git a/apis/cloudsigma/pom.xml b/apis/cloudsigma/pom.xml
index 454ea1f..d36ea17 100644
--- a/apis/cloudsigma/pom.xml
+++ b/apis/cloudsigma/pom.xml
@@ -36,13 +36,10 @@
<properties>
<test.cloudsigma.endpoint>https://api.cloudsigma.com</test.cloudsigma.endpoint>
<test.cloudsigma.api-version>1.0</test.cloudsigma.api-version>
- <test.cloudsigma.build-version />
+ <test.cloudsigma.build-version></test.cloudsigma.build-version>
<test.cloudsigma.identity>FIXME</test.cloudsigma.identity>
<test.cloudsigma.credential>FIXME</test.cloudsigma.credential>
- <test.cloudsigma.image-id>f3c7c665-cd54-4a78-8fd2-7ec2f028cf29</test.cloudsigma.image-id>
- <test.cloudsigma.image.login-user />
- <test.cloudsigma.image.authenticate-sudo />
-
+ <test.cloudsigma.template>imageId=f3c7c665-cd54-4a78-8fd2-7ec2f028cf29</test.cloudsigma.template>
<jclouds.osgi.export>org.jclouds.cloudsigma*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -107,9 +104,7 @@
<test.cloudsigma.build-version>${test.cloudsigma.build-version}</test.cloudsigma.build-version>
<test.cloudsigma.identity>${test.cloudsigma.identity}</test.cloudsigma.identity>
<test.cloudsigma.credential>${test.cloudsigma.credential}</test.cloudsigma.credential>
- <test.cloudsigma.image-id>${test.cloudsigma.image-id}</test.cloudsigma.image-id>
- <test.cloudsigma.image.login-user>${test.cloudsigma.image.login-user}</test.cloudsigma.image.login-user>
- <test.cloudsigma.image.authenticate-sudo>${test.cloudsigma.image.authenticate-sudo}</test.cloudsigma.image.authenticate-sudo>
+ <test.cloudsigma.template>${test.cloudsigma.template}</test.cloudsigma.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java b/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java
index 1a639fc..36f788d 100644
--- a/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java
+++ b/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java
@@ -57,7 +57,6 @@
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
-import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.HostAndPort;
@@ -84,6 +83,7 @@
protected Predicate<HostAndPort> socketTester;
protected Predicate<DriveInfo> driveNotClaimed;
+ protected String imageId;
@BeforeGroups(groups = { "integration", "live" })
@Override
@@ -97,7 +97,7 @@
socketTester = new RetryablePredicate<HostAndPort>(new InetSocketAddressConnect(), maxDriveImageTime, 1,
TimeUnit.SECONDS);
- if (Strings.emptyToNull(imageId) == null) {
+ if (template == null || template.getImageId() == null) {
imageId = view.getComputeService().templateBuilder().build().getImage().getId();
}
}
diff --git a/apis/cloudstack/pom.xml b/apis/cloudstack/pom.xml
index a61c690..c711e8d 100644
--- a/apis/cloudstack/pom.xml
+++ b/apis/cloudstack/pom.xml
@@ -49,18 +49,15 @@
<properties>
<test.cloudstack.endpoint>http://localhost:8080/client/api</test.cloudstack.endpoint>
- <test.cloudstack.api-version>2.2.12</test.cloudstack.api-version>
- <test.cloudstack.build-version />
+ <test.cloudstack.api-version>3.0.3</test.cloudstack.api-version>
+ <test.cloudstack.build-version></test.cloudstack.build-version>
<test.cloudstack.identity>FIXME_apiKey</test.cloudstack.identity>
<test.cloudstack.credential>FIXME_secretKey</test.cloudstack.credential>
- <test.cloudstack.domainAdminIdentity />
- <test.cloudstack.domainAdminCredential />
- <test.cloudstack.globalAdminIdentity />
- <test.cloudstack.globalAdminCredential />
- <test.cloudstack.image-id />
- <test.cloudstack.image.login-user />
- <test.cloudstack.image.authenticate-sudo />
-
+ <test.cloudstack.domainAdminIdentity></test.cloudstack.domainAdminIdentity>
+ <test.cloudstack.domainAdminCredential></test.cloudstack.domainAdminCredential>
+ <test.cloudstack.globalAdminIdentity></test.cloudstack.globalAdminIdentity>
+ <test.cloudstack.globalAdminCredential></test.cloudstack.globalAdminCredential>
+ <test.cloudstack.template></test.cloudstack.template>
<jclouds.osgi.export>org.jclouds.cloudstack*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -137,9 +134,7 @@
<test.cloudstack.build-version>${test.cloudstack.build-version}</test.cloudstack.build-version>
<test.cloudstack.identity>${test.cloudstack.identity}</test.cloudstack.identity>
<test.cloudstack.credential>${test.cloudstack.credential}</test.cloudstack.credential>
- <test.cloudstack.image-id>${test.cloudstack.image-id}</test.cloudstack.image-id>
- <test.cloudstack.image.login-user>${test.cloudstack.image.login-user}</test.cloudstack.image.login-user>
- <test.cloudstack.image.authenticate-sudo>${test.cloudstack.image.authenticate-sudo}</test.cloudstack.image.authenticate-sudo>
+ <test.cloudstack.template>${test.cloudstack.template}</test.cloudstack.template>
<test.cloudstack.domainAdminIdentity>${test.cloudstack.domainAdminIdentity}</test.cloudstack.domainAdminIdentity>
<test.cloudstack.domainAdminCredential>${test.cloudstack.domainAdminCredential}</test.cloudstack.domainAdminCredential>
<test.cloudstack.globalAdminIdentity>${test.cloudstack.globalAdminIdentity}</test.cloudstack.globalAdminIdentity>
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallClientLiveTest.java
index d2a34b2..73e4a61 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallClientLiveTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallClientLiveTest.java
@@ -75,7 +75,7 @@
}
}));
- String defaultTemplate = (imageId != null && !"".equals(imageId)) ? imageId : null;
+ String defaultTemplate = template != null ? template.getImageId() : null;
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network,
defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()),
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java
index 7f94a60..3fa074e 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java
@@ -92,7 +92,7 @@
public void testCreateVm() {
if (networksDisabled)
return;
- String defaultTemplate = (imageId != null && !"".equals(imageId)) ? imageId : null;
+ String defaultTemplate = template != null ? template.getImageId() : null;
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network,
defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()),
client, jobComplete, virtualMachineRunning);
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupClientLiveTest.java
index 30a9b2c..4320390 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupClientLiveTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupClientLiveTest.java
@@ -171,7 +171,7 @@
public void testCreateVMInSecurityGroup() throws Exception {
if (!securityGroupsSupported)
return;
- String defaultTemplate = (imageId != null && !"".equals(imageId)) ? imageId : null;
+ String defaultTemplate = template != null ? template.getImageId() : null;
vm = VirtualMachineClientLiveTest.createVirtualMachineWithSecurityGroupInZone(zone.getId(),
defaultTemplateOrPreferredInZone(defaultTemplate, client, zone.getId()), group.getId(), client,
jobComplete, virtualMachineRunning);
@@ -200,7 +200,7 @@
public void testCreateVMWithoutSecurityGroupAssignsDefault() throws Exception {
if (!securityGroupsSupported)
return;
- String defaultTemplate = (imageId != null && !"".equals(imageId)) ? imageId : null;
+ String defaultTemplate = template != null ? template.getImageId() : null;
VirtualMachine newVm = VirtualMachineClientLiveTest.createVirtualMachineWithOptionsInZone(DeployVirtualMachineOptions.NONE,
zone.getId(), defaultTemplateOrPreferredInZone(defaultTemplate, client, zone.getId()), client,
jobComplete, virtualMachineRunning);
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateClientLiveTest.java
index 2df4cc8..f2a9fd5 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateClientLiveTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateClientLiveTest.java
@@ -115,8 +115,8 @@
assertNotNull(network);
// Create a VM and stop it
- String templateId = (imageId != null && !"".equals(imageId)) ? imageId : null;
- vmForCreation = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, templateId, client, jobComplete, virtualMachineRunning);
+ String defaultTemplate = template != null ? template.getImageId() : null;
+ vmForCreation = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, defaultTemplate, client, jobComplete, virtualMachineRunning);
assertTrue(jobComplete.apply(client.getVirtualMachineClient().stopVirtualMachine(vmForCreation.getId())), vmForCreation.toString());
// Work out the VM's volume
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java
index fd2a37c..dc0b4fa 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java
@@ -181,8 +181,8 @@
@Test
public void testCreateVirtualMachine() throws Exception {
- String templateId = (imageId != null && !"".equals(imageId)) ? imageId : null;
- vm = createVirtualMachine(client, templateId, jobComplete, virtualMachineRunning);
+ String defaultTemplate = template != null ? template.getImageId() : null;
+ vm = createVirtualMachine(client, defaultTemplate, jobComplete, virtualMachineRunning);
if (vm.getPassword() != null) {
conditionallyCheckSSH();
}
@@ -195,12 +195,12 @@
public void testCreateVirtualMachineWithSpecificIp() throws Exception {
skipIfNotGlobalAdmin();
- String templateId = (imageId != null && !"".equals(imageId)) ? imageId : null;
+ String defaultTemplate = template != null ? template.getImageId() : null;
Network network = null;
try {
Template template = getOnlyElement(
- client.getTemplateClient().listTemplates(ListTemplatesOptions.Builder.id(templateId)));
+ client.getTemplateClient().listTemplates(ListTemplatesOptions.Builder.id(defaultTemplate)));
logger.info("Using template: " + template);
Set<Network> allSafeNetworksInZone = adminClient.getNetworkClient().listNetworks(
@@ -252,7 +252,7 @@
ipsToNetworks.put(ipAddress, network.getId());
vm = createVirtualMachineInNetworkWithIp(
- adminClient, templateId, ImmutableSet.of(requiredNetwork, network),
+ adminClient, defaultTemplate, ImmutableSet.of(requiredNetwork, network),
ipsToNetworks, adminJobComplete, adminVirtualMachineRunning);
logger.info("Created VM: " + vm);
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java
index 6298852..0710ae3 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java
@@ -64,7 +64,7 @@
prefix += "nat";
try {
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.supportsStaticNAT());
- String defaultTemplate = (imageId != null && !"".equals(imageId)) ? imageId : null;
+ String defaultTemplate = template != null ? template.getImageId() : null;
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network,
defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), client, jobComplete,
virtualMachineRunning);
diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java
index d313ccd..8f730d6 100644
--- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java
+++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java
@@ -27,9 +27,6 @@
import java.util.Date;
import java.util.Map;
-import javax.inject.Named;
-
-import org.jclouds.Constants;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.filters.FormSigner;
@@ -111,8 +108,7 @@
}
@Override
- protected String provideTimeStamp(final DateService dateService,
- @Named(Constants.PROPERTY_SESSION_INTERVAL) int expiration) {
+ protected String provideTimeStamp(final DateService dateService) {
return "2009-11-08T15:54:08.897Z";
}
}
diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchExpectTest.java
index d4576ac..765f423 100644
--- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchExpectTest.java
+++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchExpectTest.java
@@ -23,9 +23,6 @@
import java.net.URI;
import java.util.Map;
-import javax.inject.Named;
-
-import org.jclouds.Constants;
import org.jclouds.aws.domain.Region;
import org.jclouds.cloudwatch.config.CloudWatchRestClientModule;
import org.jclouds.date.DateService;
@@ -69,8 +66,7 @@
}
@Override
- protected String provideTimeStamp(final DateService dateService,
- @Named(Constants.PROPERTY_SESSION_INTERVAL) int expiration) {
+ protected String provideTimeStamp(final DateService dateService) {
return "2009-11-08T15:54:08.897Z";
}
}
diff --git a/apis/deltacloud/pom.xml b/apis/deltacloud/pom.xml
index 2c32c61..bfef9b8 100644
--- a/apis/deltacloud/pom.xml
+++ b/apis/deltacloud/pom.xml
@@ -50,13 +50,10 @@
<properties>
<test.deltacloud.endpoint>http://localhost:3001/api</test.deltacloud.endpoint>
<test.deltacloud.api-version>0.3.0</test.deltacloud.api-version>
- <test.deltacloud.build-version />
+ <test.deltacloud.build-version></test.deltacloud.build-version>
<test.deltacloud.identity>mockuser</test.deltacloud.identity>
<test.deltacloud.credential>mockpassword</test.deltacloud.credential>
- <test.deltacloud.image-id />
- <test.deltacloud.image.login-user />
- <test.deltacloud.image.authenticate-sudo />
-
+ <test.deltacloud.template></test.deltacloud.template>
<jclouds.osgi.export>org.jclouds.deltacloud*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -120,9 +117,7 @@
<test.deltacloud.build-version>${test.deltacloud.build-version}</test.deltacloud.build-version>
<test.deltacloud.identity>${test.deltacloud.identity}</test.deltacloud.identity>
<test.deltacloud.credential>${test.deltacloud.credential}</test.deltacloud.credential>
- <test.deltacloud.image-id>${test.deltacloud.image-id}</test.deltacloud.image-id>
- <test.deltacloud.image.login-user>${test.deltacloud.image.login-user}</test.deltacloud.image.login-user>
- <test.deltacloud.image.authenticate-sudo>${test.deltacloud.image.authenticate-sudo}</test.deltacloud.image.authenticate-sudo>
+ <test.deltacloud.template>${test.deltacloud.template}</test.deltacloud.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/apis/ec2/pom.xml b/apis/ec2/pom.xml
index 11e1e06..d7d6073 100644
--- a/apis/ec2/pom.xml
+++ b/apis/ec2/pom.xml
@@ -36,13 +36,11 @@
<properties>
<test.ec2.endpoint>https://ec2.us-east-1.amazonaws.com</test.ec2.endpoint>
<test.ec2.api-version>2010-06-15</test.ec2.api-version>
- <test.ec2.build-version />
+ <test.ec2.build-version></test.ec2.build-version>
<test.ec2.identity>${test.aws.identity}</test.ec2.identity>
<test.ec2.credential>${test.aws.credential}</test.ec2.credential>
- <test.ec2.image-id />
- <test.ec2.image.login-user />
- <test.ec2.image.authenticate-sudo />
-
+ <test.ec2.template></test.ec2.template>
+ <test.ec2.ebs-template>hardwareId=m1.small,imageId=us-west-2/ami-38c64a08</test.ec2.ebs-template>
<jclouds.osgi.export>org.jclouds.ec2*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -128,9 +126,8 @@
<test.ec2.build-version>${test.ec2.build-version}</test.ec2.build-version>
<test.ec2.identity>${test.ec2.identity}</test.ec2.identity>
<test.ec2.credential>${test.ec2.credential}</test.ec2.credential>
- <test.ec2.image-id>${test.ec2.image-id}</test.ec2.image-id>
- <test.ec2.image.login-user>${test.ec2.image.login-user}</test.ec2.image.login-user>
- <test.ec2.image.authenticate-sudo>${test.ec2.image.authenticate-sudo}</test.ec2.image.authenticate-sudo>
+ <test.ec2.template>${test.ec2.template}</test.ec2.template>
+ <test.ec2.ebs-template>${test.ec2.ebs-template}</test.ec2.ebs-template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2ImageParser.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2ImageParser.java
index dfbf062..fc97830 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2ImageParser.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2ImageParser.java
@@ -32,10 +32,10 @@
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.Image.Status;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.compute.domain.Image.Status;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.compute.util.ComputeServiceUtils;
@@ -100,7 +100,7 @@
OperatingSystem.Builder osBuilder = OperatingSystem.builder();
osBuilder.is64Bit(from.getArchitecture() == Architecture.X86_64);
- OsFamily family = parseOsFamilyOrUnrecognized(from.getImageLocation());
+ OsFamily family = parseOsFamily(from);
osBuilder.family(family);
osBuilder.version(ComputeServiceUtils.parseVersionOrReturnEmptyString(family, from.getImageLocation(),
osVersionMap));
@@ -131,4 +131,20 @@
return builder.build();
}
+ /**
+ * First treats windows as a special case: check if platform==windows.
+ * Then tries matching based on the image name.
+ * And then falls back to checking other types of platform.
+ */
+ private OsFamily parseOsFamily(org.jclouds.ec2.domain.Image from) {
+ if (from.getPlatform() != null && from.getPlatform().equalsIgnoreCase("windows")) {
+ return OsFamily.WINDOWS;
+ }
+
+ OsFamily family = parseOsFamilyOrUnrecognized(from.getImageLocation());
+ if (family == OsFamily.UNRECOGNIZED && from.getPlatform() != null) {
+ family = parseOsFamilyOrUnrecognized(from.getPlatform());
+ }
+ return family;
+ }
}
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java b/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java
index 48047b3..264b012 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java
@@ -40,11 +40,15 @@
import org.jclouds.ec2.services.WindowsAsyncClient;
import org.jclouds.ec2.services.WindowsClient;
import org.jclouds.ec2.suppliers.DescribeAvailabilityZonesInRegion;
-import org.jclouds.ec2.suppliers.DescribeRegionsForConfiguredRegions;
+import org.jclouds.ec2.suppliers.DescribeRegionsForRegionURIs;
import org.jclouds.location.config.LocationModule;
import org.jclouds.location.suppliers.RegionIdToURISupplier;
import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
+import org.jclouds.location.suppliers.RegionIdsSupplier;
+import org.jclouds.location.suppliers.ZoneIdToURISupplier;
import org.jclouds.location.suppliers.ZoneIdsSupplier;
+import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
+import org.jclouds.location.suppliers.derived.ZoneIdToURIFromJoinOnRegionIdToURI;
import org.jclouds.location.suppliers.derived.ZoneIdsFromRegionIdToZoneIdsValues;
import org.jclouds.rest.ConfiguresRestClient;
@@ -81,13 +85,13 @@
super(syncClientType, asyncClientType, sync2Async);
}
-
-
@Override
protected void installLocations() {
install(new LocationModule());
bind(RegionIdToZoneIdsSupplier.class).to(DescribeAvailabilityZonesInRegion.class).in(Scopes.SINGLETON);
- bind(RegionIdToURISupplier.class).to(DescribeRegionsForConfiguredRegions.class).in(Scopes.SINGLETON);
+ bind(RegionIdToURISupplier.class).to(DescribeRegionsForRegionURIs.class).in(Scopes.SINGLETON);
bind(ZoneIdsSupplier.class).to(ZoneIdsFromRegionIdToZoneIdsValues.class).in(Scopes.SINGLETON);
+ bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class).in(Scopes.SINGLETON);
+ bind(ZoneIdToURISupplier.class).to(ZoneIdToURIFromJoinOnRegionIdToURI.class).in(Scopes.SINGLETON);
}
}
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java b/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java
index a199231..0a11cb6 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java
@@ -269,9 +269,9 @@
this.dnsName = dnsName; // nullable on runinstances.
this.imageId = imageId; // nullable on runinstances.
this.instanceId = checkNotNull(instanceId, "instanceId");
- this.instanceState = checkNotNull(instanceState, "instanceState");
- this.rawState = checkNotNull(rawState, "rawState");
- this.instanceType = checkNotNull(instanceType, "instanceType");
+ this.instanceState = checkNotNull(instanceState, "instanceState for %s/%s", region, instanceId);
+ this.rawState = checkNotNull(rawState, "rawState for %s/%s", region, instanceId);
+ this.instanceType = checkNotNull(instanceType, "instanceType for %s/%s", region, instanceId);
this.ipAddress = ipAddress;
this.kernelId = kernelId;
this.keyName = keyName;
@@ -283,10 +283,10 @@
this.privateIpAddress = privateIpAddress;// nullable on runinstances.
this.ramdiskId = ramdiskId;
this.reason = reason;
- this.rootDeviceType = checkNotNull(rootDeviceType, "rootDeviceType");
+ this.rootDeviceType = checkNotNull(rootDeviceType, "rootDeviceType for %s/%s", region, instanceId);
this.rootDeviceName = rootDeviceName;
- this.ebsBlockDevices = ImmutableMap.copyOf(checkNotNull(ebsBlockDevices, "ebsBlockDevices"));
- this.groupIds = ImmutableSet.copyOf(checkNotNull(groupIds, "groupIds"));
+ this.ebsBlockDevices = ImmutableMap.copyOf(checkNotNull(ebsBlockDevices, "ebsBlockDevices for %s/%s", region, instanceId));
+ this.groupIds = ImmutableSet.copyOf(checkNotNull(groupIds, "groupIds for %s/%s", region, instanceId));
}
/**
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java b/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java
index 14f003f..427560b 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java
@@ -97,7 +97,7 @@
private String availabilityZone;
private Status status;
private Date createTime;
- private Set<Attachment> attachments;
+ private Set<Attachment> attachments = ImmutableSet.of();
public Builder region(String region) {
this.region = region;
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java
index 96d361e..62019a2 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java
@@ -114,6 +114,7 @@
@Path("/")
@FormParams(keys = ACTION, values = "TerminateInstances")
@XMLResponseParser(InstanceStateChangeHandler.class)
+ @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<? extends InstanceStateChange>> terminateInstancesInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForConfiguredRegions.java b/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForRegionURIs.java
similarity index 76%
rename from apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForConfiguredRegions.java
rename to apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForRegionURIs.java
index 6e3d7ab..b802aeb 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForConfiguredRegions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForRegionURIs.java
@@ -20,7 +20,6 @@
import java.net.URI;
import java.util.Map;
-import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -31,29 +30,23 @@
import org.jclouds.location.suppliers.RegionIdToURISupplier;
import org.jclouds.util.Suppliers2;
-import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.collect.Maps;
@Singleton
-public class DescribeRegionsForConfiguredRegions implements RegionIdToURISupplier {
+public class DescribeRegionsForRegionURIs implements RegionIdToURISupplier {
private final AvailabilityZoneAndRegionClient client;
- private final Supplier<Set<String>> regions;
@Inject
- public DescribeRegionsForConfiguredRegions(EC2Client client, @Region Supplier<Set<String>> regions) {
+ public DescribeRegionsForRegionURIs(EC2Client client) {
this.client = client.getAvailabilityZoneAndRegionServices();
- this.regions = regions;
}
@Singleton
@Region
@Override
public Map<String, Supplier<URI>> get() {
- Set<String> regionWhiteList = regions.get();
Map<String, URI> regionToUris = client.describeRegions();
- if (regionWhiteList.size() > 0)
- regionToUris = Maps.filterKeys(regionToUris, Predicates.in(regionWhiteList));
return Maps.transformValues(regionToUris, Suppliers2.<URI> ofInstanceFunction());
}
}
\ No newline at end of file
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/BaseReservationHandler.java b/apis/ec2/src/main/java/org/jclouds/ec2/xml/BaseReservationHandler.java
index 38fe564..807d555 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/xml/BaseReservationHandler.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/BaseReservationHandler.java
@@ -72,7 +72,10 @@
protected Builder builder;
protected int itemDepth;
- boolean inInstancesSet;
+ protected boolean inInstancesSet;
+ protected boolean inProductCodes;
+ protected boolean inGroupSet;
+
// attachments
private String volumeId;
private Attachment.Status attachmentStatus;
@@ -88,12 +91,17 @@
private Set<RunningInstance> instances = Sets.newLinkedHashSet();
+
public void startElement(String uri, String name, String qName, Attributes attrs) {
if (equalsOrSuffix(qName, "item")) {
itemDepth++;
} else if (equalsOrSuffix(qName, "instancesSet")) {
inInstancesSet = true;
- }
+ } else if (equalsOrSuffix(qName, "productCodes")) {
+ inProductCodes = true;
+ } else if (equalsOrSuffix(qName, "groupSet")) {
+ inGroupSet = true;
+ }
}
public void endElement(String uri, String name, String qName) {
@@ -102,6 +110,10 @@
itemDepth--;
} else if (equalsOrSuffix(qName, "instancesSet")) {
inInstancesSet = false;
+ } else if (equalsOrSuffix(qName, "productCodes")) {
+ inProductCodes = false;
+ } else if (equalsOrSuffix(qName, "groupSet")) {
+ inGroupSet = false;
} else if (equalsOrSuffix(qName, "groupId")) {
groupIds.add(currentOrNull(currentText));
} else if (equalsOrSuffix(qName, "ownerId")) {
@@ -219,7 +231,7 @@
}
protected boolean endOfInstanceItem() {
- return itemDepth <= 2 && inInstancesSet;
+ return itemDepth <= 2 && inInstancesSet && !inProductCodes && !inGroupSet;
}
public void characters(char ch[], int start, int length) {
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandler.java b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandler.java
index 5d5cd37..af493eb 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandler.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandler.java
@@ -55,7 +55,7 @@
String pending = currentText.toString().trim();
if (pending.indexOf("Walrus") == -1)
regionEndpoint = URI.create(pending.startsWith("http") ? pending : String.format("https://%s", pending));
- } else if (qName.equals("item") && region != null) {
+ } else if (qName.equals("item") && region != null && regionEndpoint != null) {
regionEndpoints.put(region, regionEndpoint);
this.region = null;
this.regionEndpoint = null;
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/BaseEC2ComputeServiceExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/BaseEC2ComputeServiceExpectTest.java
index f663fde..37867fb 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/BaseEC2ComputeServiceExpectTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/BaseEC2ComputeServiceExpectTest.java
@@ -59,8 +59,7 @@
private static final class TestEC2RestClientModule extends EC2RestClientModule<EC2Client, EC2AsyncClient> {
@Override
@Provides
- protected String provideTimeStamp(final DateService dateService,
- @Named(Constants.PROPERTY_SESSION_INTERVAL) final int expiration) {
+ protected String provideTimeStamp(DateService dateService) {
return CONSTANT_DATE;
}
}
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java
index f5ebb78..b204a07 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java
@@ -29,8 +29,8 @@
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.TemplateBuilderSpec;
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.NodePredicates;
@@ -41,7 +41,6 @@
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.BlockDevice;
-import org.jclouds.ec2.domain.InstanceType;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
@@ -57,6 +56,7 @@
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.jclouds.util.InetAddresses2;
+import org.testng.SkipException;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
@@ -74,6 +74,8 @@
@Test(groups = "live", singleThreaded = true)
public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
+ protected TemplateBuilderSpec ebsTemplate;
+
public EC2ComputeServiceLiveTest() {
provider = "ec2";
}
@@ -227,12 +229,24 @@
}
}
+ @Override
+ protected Properties setupProperties() {
+ Properties overrides = super.setupProperties();
+ String ebsSpec = setIfTestSystemPropertyPresent(overrides, provider + ".ebs-template");
+ if (ebsSpec != null)
+ ebsTemplate = TemplateBuilderSpec.parse(ebsSpec);
+ return overrides;
+ }
+
/**
* Note we cannot use the micro size as it has no ephemeral space.
*/
- @Test(enabled = true)
+ @Test
public void testMapEBS() throws Exception {
-
+ if (ebsTemplate == null) {
+ throw new SkipException("Test cannot run without the parameter test." + provider
+ + ".ebs-template; this property should be in the format defined in TemplateBuilderSpec");
+ }
InstanceClient instanceClient = EC2Client.class.cast(view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi())
.getInstanceServices();
@@ -242,8 +256,7 @@
String group = this.group + "e";
int volumeSize = 8;
- final Template template = view.getComputeService().templateBuilder().hardwareId(InstanceType.M1_SMALL)
- .osFamily(OsFamily.UBUNTU).osVersionMatches("10.04").imageDescriptionMatches(".*ebs.*").build();
+ final Template template = view.getComputeService().templateBuilder().from(ebsTemplate).build();
Location zone = Iterables.find(view.getComputeService().listAssignableLocations(), new Predicate<Location>() {
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/EC2ImageParserTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/EC2ImageParserTest.java
index c364f1b..765659f 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/EC2ImageParserTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/EC2ImageParserTest.java
@@ -24,10 +24,10 @@
import java.util.Set;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
+import org.jclouds.compute.domain.Image.Status;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.compute.domain.Image.Status;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
@@ -64,24 +64,48 @@
assertEquals(image.getBackendStatus(), "available");
}
- assertEquals(Iterables.get(result, 0), new ImageBuilder().operatingSystem(
+ assertImageEquals(Iterables.get(result, 0), new ImageBuilder().operatingSystem(
new OperatingSystem.Builder().family(OsFamily.UNRECOGNIZED).arch("paravirtual").version("").description(
"137112412989/amzn-ami-0.9.7-beta.i386-ebs").is64Bit(false).build()).description("Amazon")
.defaultCredentials(new LoginCredentials("ec2-user", false)).id("us-east-1/ami-82e4b5c7").name(
"amzn-ami-0.9.7-beta.i386-ebs").providerId("ami-82e4b5c7").location(defaultLocation)
.userMetadata(ImmutableMap.of("owner", "137112412989", "rootDeviceType", "ebs")).status(
- Status.AVAILABLE).build());
+ Status.AVAILABLE).backendStatus("available").build());
- assertEquals(Iterables.get(result, 3), new ImageBuilder().operatingSystem(
+ assertImageEquals(Iterables.get(result, 3), new ImageBuilder().operatingSystem(
new OperatingSystem.Builder().family(OsFamily.UNRECOGNIZED).arch("paravirtual").version("").description(
"amzn-ami-us-west-1/amzn-ami-0.9.7-beta.x86_64.manifest.xml").is64Bit(true).build())
.description("Amazon Linux AMI x86_64 S3").defaultCredentials(new LoginCredentials("ec2-user", false))
.id("us-east-1/ami-f2e4b5b7").providerId("ami-f2e4b5b7").name("amzn-ami-0.9.7-beta.x86_64-S3").location(
defaultLocation)
.userMetadata(ImmutableMap.of("owner", "137112412989", "rootDeviceType", "ebs")).status(
- Status.AVAILABLE).build());
+ Status.AVAILABLE).backendStatus("available").build());
+
+ assertImageEquals(Iterables.get(result, 4), new ImageBuilder().operatingSystem(
+ new OperatingSystem.Builder().family(OsFamily.WINDOWS).arch("hvm").version("2008").description(
+ "amazon/NameGivesNoClue_Server-2008-R2_SP1-Language_Packs-64Bit-Base-2012.05.10")
+ .is64Bit(true).build())
+ .description("Microsoft Windows Server 2008 R2 SP1 Datacenter 64-bit Multi-language AMI provided by Amazon")
+ .defaultCredentials(new LoginCredentials("root", false))
+ .id("us-east-1/ami-85457ff1").providerId("ami-85457ff1").name("NameGivesNoClue_Server-2008-R2_SP1-Language_Packs-64Bit-Base-2012.05.10")
+ .location(defaultLocation)
+ .userMetadata(ImmutableMap.of("owner", "801119661308", "rootDeviceType", "ebs"))
+ .status(Status.AVAILABLE).backendStatus("available").build());
+
}
+ private void assertImageEquals(org.jclouds.compute.domain.Image actual, org.jclouds.compute.domain.Image expected) {
+ // Note that ImageImpl.equals does not compare operating system etc; there's an explicit comment:
+ // equals from super is sufficient to establish identity equivalence
+ assertEquals(actual, expected);
+ assertEquals(actual.getOperatingSystem(), expected.getOperatingSystem());
+ assertEquals(actual.getStatus(), expected.getStatus());
+ assertEquals(actual.getBackendStatus(), expected.getBackendStatus());
+ assertEquals(actual.getVersion(), expected.getVersion());
+ assertEquals(actual.getDescription(), expected.getDescription());
+ assertEquals(actual.getDefaultCredentials(), expected.getDefaultCredentials());
+ }
+
static Location defaultLocation = new LocationBuilder().scope(LocationScope.REGION).id("us-east-1").description(
"us-east-1").build();
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2RestClientModuleExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2RestClientModuleExpectTest.java
new file mode 100644
index 0000000..cee0074
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2RestClientModuleExpectTest.java
@@ -0,0 +1,143 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.ec2.config;
+
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.jclouds.ec2.internal.BaseEC2ExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.location.Region;
+import org.jclouds.location.Zone;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.location.functions.ZoneToEndpoint;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "EC2RestClientModuleExpectTest")
+public class EC2RestClientModuleExpectTest extends BaseEC2ExpectTest<Injector> {
+ private Injector injector;
+
+ public EC2RestClientModuleExpectTest() {
+ Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse> builder();
+ builder.put(describeRegionsRequest, describeRegionsResponse);
+ builder.putAll(describeAvailabilityZonesRequestResponse);
+
+ injector = requestsSendResponses(builder.build());
+ }
+
+ public void testLocationIdAndURIBindings() {
+
+ assertEquals(injector.getInstance(Key.get(new TypeLiteral<Supplier<Set<String>>>() {
+ }, Region.class)).get(), ImmutableSet.<String> of("sa-east-1", "ap-northeast-1", "eu-west-1", "us-east-1",
+ "us-west-1", "us-west-2", "ap-southeast-1"));
+
+ assertEquals(injector.getInstance(Key.get(new TypeLiteral<Supplier<Set<String>>>() {
+ }, Zone.class)).get(), ImmutableSet.<String> of("sa-east-1a", "sa-east-1b", "ap-northeast-1a", "ap-northeast-1b",
+ "eu-west-1a", "eu-west-1b", "eu-west-1c", "us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d",
+ "us-east-1e", "us-west-1a", "us-west-1b", "us-west-1c", "us-west-2a", "us-west-2b", "us-west-2c",
+ "ap-southeast-1a", "ap-southeast-1b"));
+
+ Map<String, Supplier<URI>> regionToURISupplier = injector.getInstance(
+ Key.get(new TypeLiteral<Supplier<Map<String, Supplier<URI>>>>() {
+ }, Region.class)).get();
+
+ assertEquals(regionToURISupplier.get("sa-east-1").get(), URI.create("https://ec2.sa-east-1.amazonaws.com"));
+ assertEquals(regionToURISupplier.get("ap-northeast-1").get(),
+ URI.create("https://ec2.ap-northeast-1.amazonaws.com"));
+ assertEquals(regionToURISupplier.get("eu-west-1").get(), URI.create("https://ec2.eu-west-1.amazonaws.com"));
+ assertEquals(regionToURISupplier.get("us-east-1").get(), URI.create("https://ec2.us-east-1.amazonaws.com"));
+ assertEquals(regionToURISupplier.get("us-west-1").get(), URI.create("https://ec2.us-west-1.amazonaws.com"));
+ assertEquals(regionToURISupplier.get("us-west-2").get(), URI.create("https://ec2.us-west-2.amazonaws.com"));
+ assertEquals(regionToURISupplier.get("ap-southeast-1").get(),
+ URI.create("https://ec2.ap-southeast-1.amazonaws.com"));
+
+ Map<String, Supplier<Set<String>>> regionToZoneIdSupplier = injector.getInstance(
+ Key.get(new TypeLiteral<Supplier<Map<String, Supplier<Set<String>>>>>() {
+ }, Zone.class)).get();
+
+ assertEquals(regionToZoneIdSupplier.get("sa-east-1").get(), ImmutableSet.of("sa-east-1a", "sa-east-1b"));
+ assertEquals(regionToZoneIdSupplier.get("ap-northeast-1").get(),
+ ImmutableSet.of("ap-northeast-1a", "ap-northeast-1b"));
+ assertEquals(regionToZoneIdSupplier.get("eu-west-1").get(),
+ ImmutableSet.of("eu-west-1a", "eu-west-1b", "eu-west-1c"));
+ assertEquals(regionToZoneIdSupplier.get("us-east-1").get(),
+ ImmutableSet.of("us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e"));
+ assertEquals(regionToZoneIdSupplier.get("us-west-1").get(),
+ ImmutableSet.of("us-west-1a", "us-west-1b", "us-west-1c"));
+ assertEquals(regionToZoneIdSupplier.get("us-west-2").get(),
+ ImmutableSet.of("us-west-2a", "us-west-2b", "us-west-2c"));
+ assertEquals(regionToZoneIdSupplier.get("ap-southeast-1").get(),
+ ImmutableSet.of("ap-southeast-1a", "ap-southeast-1b"));
+
+ Map<String, Supplier<URI>> zoneToURISupplier = injector.getInstance(
+ Key.get(new TypeLiteral<Supplier<Map<String, Supplier<URI>>>>() {
+ }, Zone.class)).get();
+
+ assertEquals(zoneToURISupplier.get("sa-east-1a").get(), URI.create("https://ec2.sa-east-1.amazonaws.com"));
+
+ assertEquals(zoneToURISupplier.get("ap-northeast-1a").get(),
+ URI.create("https://ec2.ap-northeast-1.amazonaws.com"));
+
+ assertEquals(zoneToURISupplier.get("eu-west-1a").get(), URI.create("https://ec2.eu-west-1.amazonaws.com"));
+
+ assertEquals(zoneToURISupplier.get("us-east-1a").get(), URI.create("https://ec2.us-east-1.amazonaws.com"));
+
+ assertEquals(zoneToURISupplier.get("us-west-1a").get(), URI.create("https://ec2.us-west-1.amazonaws.com"));
+
+ assertEquals(zoneToURISupplier.get("us-west-2a").get(), URI.create("https://ec2.us-west-2.amazonaws.com"));
+
+ assertEquals(zoneToURISupplier.get("ap-southeast-1a").get(),
+ URI.create("https://ec2.ap-southeast-1.amazonaws.com"));
+
+ }
+
+ public void testZoneToEndpoint() {
+ assertEquals(injector.getInstance(ZoneToEndpoint.class).apply("us-west-2a"),
+ URI.create("https://ec2.us-west-2.amazonaws.com"));
+ }
+
+ public void testRegionToEndpointOrProviderIfNull() {
+ assertEquals(injector.getInstance(RegionToEndpointOrProviderIfNull.class).apply("us-west-2"),
+ URI.create("https://ec2.us-west-2.amazonaws.com"));
+ }
+
+ @Override
+ public Injector createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
+ return createInjector(fn, module, props);
+ }
+
+}
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java
new file mode 100644
index 0000000..be74eac
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java
@@ -0,0 +1,99 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.ec2.internal;
+
+import java.net.URI;
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.date.DateService;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.ec2.EC2AsyncClient;
+import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.config.EC2RestClientModule;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.internal.BaseRestClientExpectTest;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+
+public abstract class BaseEC2ExpectTest<T> extends BaseRestClientExpectTest<T> {
+ protected static final String CONSTANT_DATE = "2012-04-16T15:54:08.897Z";
+
+ protected DateService dateService = new SimpleDateFormatDateService();
+
+ protected HttpRequest describeRegionsRequest = HttpRequest
+ .builder()
+ .method("POST")
+ .endpoint(URI.create("https://ec2.us-east-1.amazonaws.com/"))
+ .headers(ImmutableMultimap.of("Host", "ec2.us-east-1.amazonaws.com"))
+ .payload(payloadFromStringWithContentType(
+ "Action=DescribeRegions&Signature=s5OXKqaaeKhJW5FVrRntuMsUL4Ed5fjzgUWeukU96ko%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity",
+ MediaType.APPLICATION_FORM_URLENCODED)).build();
+ protected HttpResponse describeRegionsResponse = HttpResponse.builder().statusCode(200)
+ .payload(payloadFromResourceWithContentType("/regionEndpoints-all.xml", MediaType.APPLICATION_XML))
+ .build();
+
+ protected final Map<HttpRequest, HttpResponse> describeAvailabilityZonesRequestResponse;
+
+ public BaseEC2ExpectTest() {
+ provider = "ec2";
+ FormSigner formSigner = createInjector(Functions.forMap(ImmutableMap.<HttpRequest, HttpResponse> of()),
+ createModule(), setupProperties()).getInstance(FormSigner.class);
+ Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse> builder();
+ for (String region : ImmutableSet.of("ap-northeast-1", "ap-southeast-1", "eu-west-1", "sa-east-1", "us-east-1", "us-west-1", "us-west-2")){
+ builder.put(
+ formSigner.filter(HttpRequest.builder()
+ .method("POST")
+ .endpoint(URI.create("https://ec2." + region + ".amazonaws.com/"))
+ .headers(ImmutableMultimap.of("Host", "ec2." + region + ".amazonaws.com"))
+ .payload(payloadFromStringWithContentType(
+ "Action=DescribeAvailabilityZones&Version=2010-06-15",
+ MediaType.APPLICATION_FORM_URLENCODED)).build()),
+ HttpResponse.builder().statusCode(200)
+ .payload(payloadFromResourceWithContentType(
+ "/availabilityZones-" + region + ".xml", MediaType.APPLICATION_XML)).build());
+
+ }
+ describeAvailabilityZonesRequestResponse = builder.build();
+ }
+
+ @ConfiguresRestClient
+ private static final class TestEC2RestClientModule extends EC2RestClientModule<EC2Client, EC2AsyncClient> {
+ @Override
+ @Provides
+ protected String provideTimeStamp(DateService dateService) {
+ return CONSTANT_DATE;
+ }
+ }
+
+ @Override
+ protected Module createModule() {
+ return new TestEC2RestClientModule();
+ }
+}
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIClientLiveTest.java
new file mode 100644
index 0000000..15e112a
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIClientLiveTest.java
@@ -0,0 +1,186 @@
+package org.jclouds.ec2.services;
+
+import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.imageIds;
+import static org.jclouds.ec2.options.RegisterImageBackedByEbsOptions.Builder.addNewBlockDevice;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.TemplateBuilderSpec;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.compute.predicates.ImagePredicates;
+import org.jclouds.ec2.EC2ApiMetadata;
+import org.jclouds.ec2.domain.BlockDevice;
+import org.jclouds.ec2.domain.Image;
+import org.jclouds.ec2.domain.Image.ImageType;
+import org.jclouds.ec2.domain.Reservation;
+import org.jclouds.ec2.domain.RootDeviceType;
+import org.jclouds.ec2.domain.RunningInstance;
+import org.jclouds.ec2.domain.Snapshot;
+import org.jclouds.ec2.services.AMIClient;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+
+/**
+ * Tests behavior of {@code AMIClient}
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true)
+public class AMIClientLiveTest extends BaseComputeServiceContextLiveTest {
+ private TemplateBuilderSpec ebsTemplate;
+
+ public AMIClientLiveTest() {
+ provider = "ec2";
+ }
+
+ @Override
+ protected Properties setupProperties() {
+ Properties overrides = super.setupProperties();
+ String ebsSpec = setIfTestSystemPropertyPresent(overrides, provider + ".ebs-template");
+ if (ebsSpec != null)
+ ebsTemplate = TemplateBuilderSpec.parse(ebsSpec);
+ return overrides;
+ }
+
+ protected AMIClient client;
+
+ protected Set<String> imagesToDeregister = Sets.newHashSet();
+ protected Set<String> snapshotsToDelete = Sets.newHashSet();
+ protected String regionId;
+ protected String ebsBackedImageId;
+ protected String ebsBackedImageName = "jcloudstest1";
+
+ @Override
+ @BeforeClass(groups = { "integration", "live" })
+ public void setupContext() {
+ super.setupContext();
+ client = view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi().getAMIServices();
+ if (ebsTemplate != null) {
+ Template template = view.getComputeService().templateBuilder().from(ebsTemplate).build();
+ regionId = template.getLocation().getId();
+ for (Image image : client.describeImagesInRegion(regionId)) {
+ if (ebsBackedImageName.equals(image.getName()))
+ client.deregisterImageInRegion(regionId, image.getId());
+ }
+ }
+ }
+
+ public void testDescribeImageNotExists() {
+ assertEquals(client.describeImagesInRegion(null, imageIds("ami-cdf819a3")).size(), 0);
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testDescribeImageBadId() {
+ client.describeImagesInRegion(null, imageIds("asdaasdsa"));
+ }
+
+ public void testDescribeImages() {
+ for (String region : view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi().getAvailabilityZoneAndRegionServices()
+ .describeRegions().keySet()) {
+ Set<? extends Image> allResults = client.describeImagesInRegion(region);
+ assertNotNull(allResults);
+ assert allResults.size() >= 2 : allResults.size();
+ Iterator<? extends Image> iterator = allResults.iterator();
+ String id1 = iterator.next().getId();
+ String id2 = iterator.next().getId();
+ Set<? extends Image> twoResults = client.describeImagesInRegion(region, imageIds(id1, id2));
+ assertNotNull(twoResults);
+ assertEquals(twoResults.size(), 2);
+ iterator = twoResults.iterator();
+ assertEquals(iterator.next().getId(), id1);
+ assertEquals(iterator.next().getId(), id2);
+ }
+ }
+
+ @Test
+ public void testCreateAndListEBSBackedImage() throws Exception {
+ ComputeService computeService = view.getComputeService();
+ Snapshot snapshot = createSnapshot(computeService);
+
+ // List of images before...
+ int sizeBefore = computeService.listImages().size();
+
+ // Register a new image...
+ ebsBackedImageId = client.registerUnixImageBackedByEbsInRegion(regionId, ebsBackedImageName, snapshot.getId(),
+ addNewBlockDevice("/dev/sda2", "myvirtual", 1).withDescription("adrian"));
+ imagesToDeregister.add(ebsBackedImageId);
+ final Image ebsBackedImage = Iterables.getOnlyElement(client.describeImagesInRegion(regionId,
+ imageIds(ebsBackedImageId)));
+ assertEquals(ebsBackedImage.getName(), ebsBackedImageName);
+ assertEquals(ebsBackedImage.getImageType(), ImageType.MACHINE);
+ assertEquals(ebsBackedImage.getRootDeviceType(), RootDeviceType.EBS);
+ assertEquals(ebsBackedImage.getRootDeviceName(), "/dev/sda1");
+ assertEquals(ebsBackedImage.getDescription(), "adrian");
+ assertEquals(
+ ebsBackedImage.getEbsBlockDevices().entrySet(),
+ ImmutableMap.of("/dev/sda1", new Image.EbsBlockDevice(snapshot.getId(), snapshot.getVolumeSize(), true),
+ "/dev/sda2", new Image.EbsBlockDevice(null, 1, false)).entrySet());
+
+ // This is the suggested method to ensure the new image ID is inserted
+ // into the cache
+ // (suggested by adriancole_ on #jclouds)
+ computeService.templateBuilder().imageId(ebsBackedImage.getRegion() + "/" + ebsBackedImageId).build();
+
+ // List of images after - should be one larger than before
+ Set<? extends org.jclouds.compute.domain.Image> after = computeService.listImages();
+ assertEquals(after.size(), sizeBefore + 1);
+
+ // Detailed check: filter for the AMI ID
+ Iterable<? extends org.jclouds.compute.domain.Image> filtered = Iterables.filter(after,
+ ImagePredicates.idEquals(ebsBackedImage.getRegion() + "/" + ebsBackedImageId));
+ assertEquals(Iterables.size(filtered), 1);
+ }
+
+ // Fires up an instance, finds its root volume ID, takes a snapshot, then
+ // terminates the instance.
+ private Snapshot createSnapshot(ComputeService computeService) throws RunNodesException {
+ Template template = computeService.templateBuilder().from(ebsTemplate).build();
+ regionId = template.getLocation().getId();
+ Set<? extends NodeMetadata> nodes = computeService.createNodesInGroup("jcloudstest", 1, template);
+ try {
+ String instanceId = Iterables.getOnlyElement(nodes).getProviderId();
+ Reservation<? extends RunningInstance> reservation = Iterables.getOnlyElement(view
+ .unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi().getInstanceServices()
+ .describeInstancesInRegion(regionId, instanceId));
+ RunningInstance instance = Iterables.getOnlyElement(reservation);
+ BlockDevice device = instance.getEbsBlockDevices().get("/dev/sda1");
+ Snapshot snapshot = view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi().getElasticBlockStoreServices()
+ .createSnapshotInRegion(regionId, device.getVolumeId());
+ snapshotsToDelete.add(snapshot.getId());
+ return snapshot;
+ } finally {
+ computeService.destroyNodesMatching(Predicates.in(nodes));
+ }
+ }
+
+ @Test(dependsOnMethods = "testCreateAndListEBSBackedImage")
+ public void testGetLaunchPermissionForImage() {
+ System.out.println(client.getLaunchPermissionForImageInRegion(regionId, ebsBackedImageId));
+ }
+
+ @Override
+ @AfterClass(groups = { "integration", "live" })
+ protected void tearDownContext() {
+ for (String imageId : imagesToDeregister)
+ client.deregisterImageInRegion(regionId, imageId);
+ for (String snapshotId : snapshotsToDelete)
+ view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi().getElasticBlockStoreServices()
+ .deleteSnapshotInRegion(regionId, snapshotId);
+ super.tearDownContext();
+ }
+
+}
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/BaseEC2AsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/BaseEC2AsyncClientTest.java
index 2890eae..39e689d 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/BaseEC2AsyncClientTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/services/BaseEC2AsyncClientTest.java
@@ -79,7 +79,7 @@
}
@Override
- protected String provideTimeStamp(DateService dateService, int expiration) {
+ protected String provideTimeStamp(DateService dateService) {
return "2009-11-08T15:54:08.897Z";
}
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/EC2ElasticBlockStoreClientExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/EC2ElasticBlockStoreClientExpectTest.java
new file mode 100644
index 0000000..c032187
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/services/EC2ElasticBlockStoreClientExpectTest.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.ec2.services;
+
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+
+import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.domain.Volume;
+import org.jclouds.ec2.internal.BaseEC2ExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.ImmutableMultimap;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "EC2ElasticBlockStoreClientExpectTest")
+public class EC2ElasticBlockStoreClientExpectTest extends BaseEC2ExpectTest<EC2Client> {
+
+ public void testCreateVolumeInAvailabilityZone() {
+ Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse>builder();
+ builder.put(describeRegionsRequest, describeRegionsResponse);
+ builder.putAll(describeAvailabilityZonesRequestResponse);
+ builder.put(
+ HttpRequest.builder()
+ .method("POST")
+ .endpoint(URI.create("https://ec2.us-east-1.amazonaws.com/"))
+ .headers(ImmutableMultimap.of("Host", "ec2.us-east-1.amazonaws.com"))
+ .payload(payloadFromStringWithContentType("Action=CreateVolume&AvailabilityZone=us-east-1a&Signature=FB5hTZHKSAuiygoafIdJh1EnfTu0ogC2VfRQOar85mg%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Size=4&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
+ HttpResponse.builder()
+ .statusCode(200)
+ .payload(payloadFromResource("/created_volume.xml")).build());
+
+ ElasticBlockStoreClient client = requestsSendResponses(builder.build()).getElasticBlockStoreServices();
+ Volume expected = Volume
+ .builder()
+ .id("vol-2a21e543")
+ .status(Volume.Status.CREATING)
+ .availabilityZone("us-east-1a")
+ .region("us-east-1")
+ .id("vol-2a21e543")
+ .size(1)
+ .createTime(dateService.iso8601DateParse("2009-12-28T05:42:53.000Z"))
+ .build();
+
+ assertEquals(client.createVolumeInAvailabilityZone("us-east-1a", 4), expected);
+ }
+
+}
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java
index ac0b44c..3ec4a00 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java
@@ -99,7 +99,7 @@
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
- assertExceptionParserClassEquals(method, null);
+ assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(request);
}
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/xml/RunInstancesResponseHandlerTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/xml/RunInstancesResponseHandlerTest.java
index f52baaf..16d597b 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/xml/RunInstancesResponseHandlerTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/xml/RunInstancesResponseHandlerTest.java
@@ -29,6 +29,7 @@
import org.jclouds.ec2.domain.InstanceState;
import org.jclouds.ec2.domain.InstanceType;
import org.jclouds.ec2.domain.Reservation;
+import org.jclouds.ec2.domain.RootDeviceType;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
@@ -57,7 +58,7 @@
assert dateService != null;
}
- public void testApplyInputStream() {
+ public void testEC2() {
InputStream is = getClass().getResourceAsStream("/run_instances.xml");
@@ -90,6 +91,26 @@
assertEquals(result.toString(), expected.toString());
}
+ public void testCloudBridge() {
+
+ InputStream is = getClass().getResourceAsStream("/run_instances_cloudbridge.xml");
+
+ Reservation<? extends RunningInstance> expected = new Reservation<RunningInstance>(defaultRegion, ImmutableSet
+ .of("default"), ImmutableSet.of(
+
+ new RunningInstance.Builder().region(defaultRegion).groupId("jclouds#greenqloud-computeblock").amiLaunchIndex("0")
+ .imageId("qmi-9ac92558").instanceId("i-01b0dac3").instanceState(InstanceState.PENDING).rawState(
+ "pending").instanceType(InstanceType.M1_SMALL).keyName("jclouds#greenqloud-computeblock#35")
+ .launchTime(dateService.iso8601DateParse("2012-06-15T19:06:35.000+00:00"))
+ .rootDeviceType(RootDeviceType.EBS).availabilityZone("is-1a").build())
+ , "56eeacd9-c790-45c3-85f3-e4380b55e1d8<", null, "r-f847a6ca");
+
+ RunInstancesResponseHandler handler = injector.getInstance(RunInstancesResponseHandler.class);
+ addDefaultRegionToHandler(handler);
+ Reservation<? extends RunningInstance> result = factory.create(handler).parse(is);
+ assertEquals(result.toString(), expected.toString());
+ }
+
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object> of()).atLeastOnce();
diff --git a/apis/ec2/src/test/resources/amzn_images.xml b/apis/ec2/src/test/resources/amzn_images.xml
index 82f97dc..0b1a767 100644
--- a/apis/ec2/src/test/resources/amzn_images.xml
+++ b/apis/ec2/src/test/resources/amzn_images.xml
@@ -82,5 +82,32 @@
<blockDeviceMapping/>
<virtualizationType>paravirtual</virtualizationType>
</item>
+ <item>
+ <imageId>ami-85457ff1</imageId>
+ <imageLocation>amazon/NameGivesNoClue_Server-2008-R2_SP1-Language_Packs-64Bit-Base-2012.05.10</imageLocation>
+ <imageState>available</imageState>
+ <imageOwnerId>801119661308</imageOwnerId>
+ <isPublic>true</isPublic>
+ <architecture>x86_64</architecture>
+ <imageType>machine</imageType>
+ <platform>windows</platform>
+ <imageOwnerAlias>amazon</imageOwnerAlias>
+ <name>NameGivesNoClue_Server-2008-R2_SP1-Language_Packs-64Bit-Base-2012.05.10</name>
+ <description>Microsoft Windows Server 2008 R2 SP1 Datacenter 64-bit Multi-language AMI provided by Amazon</description>
+ <rootDeviceType>ebs</rootDeviceType>
+ <rootDeviceName>/dev/sda1</rootDeviceName>
+ <blockDeviceMapping>
+ <item>
+ <deviceName>/dev/sda1</deviceName>
+ <ebs>
+ <snapshotId>snap-84a433ef</snapshotId>
+ <volumeSize>30</volumeSize>
+ <deleteOnTermination>true</deleteOnTermination>
+ </ebs>
+ </item>
+ </blockDeviceMapping>
+ <virtualizationType>hvm</virtualizationType>
+ <hypervisor>xen</hypervisor>
+ </item>
</imagesSet>
</DescribeImagesResponse>
diff --git a/apis/ec2/src/test/resources/availabilityZones-ap-northeast-1.xml b/apis/ec2/src/test/resources/availabilityZones-ap-northeast-1.xml
new file mode 100644
index 0000000..129daf5
--- /dev/null
+++ b/apis/ec2/src/test/resources/availabilityZones-ap-northeast-1.xml
@@ -0,0 +1,17 @@
+<DescribeAvailabilityZonesResponse xmlns="http://ec2.amazonaws.com/doc/2011-05-15/">
+ <requestId>24251909-7fb6-4080-8ca3-fbb5a1ddb02d</requestId>
+ <availabilityZoneInfo>
+ <item>
+ <zoneName>ap-northeast-1a</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>ap-northeast-1</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>ap-northeast-1b</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>ap-northeast-1</regionName>
+ <messageSet/>
+ </item>
+ </availabilityZoneInfo>
+</DescribeAvailabilityZonesResponse>
\ No newline at end of file
diff --git a/apis/ec2/src/test/resources/availabilityZones-ap-southeast-1.xml b/apis/ec2/src/test/resources/availabilityZones-ap-southeast-1.xml
new file mode 100644
index 0000000..47b33ec
--- /dev/null
+++ b/apis/ec2/src/test/resources/availabilityZones-ap-southeast-1.xml
@@ -0,0 +1,17 @@
+<DescribeAvailabilityZonesResponse xmlns="http://ec2.amazonaws.com/doc/2011-05-15/">
+ <requestId>22c5332d-c331-4310-b695-e21e76c3fdb0</requestId>
+ <availabilityZoneInfo>
+ <item>
+ <zoneName>ap-southeast-1a</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>ap-southeast-1</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>ap-southeast-1b</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>ap-southeast-1</regionName>
+ <messageSet/>
+ </item>
+ </availabilityZoneInfo>
+</DescribeAvailabilityZonesResponse>
\ No newline at end of file
diff --git a/apis/ec2/src/test/resources/availabilityZones-eu-west-1.xml b/apis/ec2/src/test/resources/availabilityZones-eu-west-1.xml
new file mode 100644
index 0000000..921216c
--- /dev/null
+++ b/apis/ec2/src/test/resources/availabilityZones-eu-west-1.xml
@@ -0,0 +1,23 @@
+<DescribeAvailabilityZonesResponse xmlns="http://ec2.amazonaws.com/doc/2011-05-15/">
+ <requestId>386c8215-6ec8-4495-aaa6-8c4175688093</requestId>
+ <availabilityZoneInfo>
+ <item>
+ <zoneName>eu-west-1a</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>eu-west-1</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>eu-west-1b</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>eu-west-1</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>eu-west-1c</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>eu-west-1</regionName>
+ <messageSet/>
+ </item>
+ </availabilityZoneInfo>
+</DescribeAvailabilityZonesResponse>
\ No newline at end of file
diff --git a/apis/ec2/src/test/resources/availabilityZones-sa-east-1.xml b/apis/ec2/src/test/resources/availabilityZones-sa-east-1.xml
new file mode 100644
index 0000000..d6f97c6
--- /dev/null
+++ b/apis/ec2/src/test/resources/availabilityZones-sa-east-1.xml
@@ -0,0 +1,17 @@
+<DescribeAvailabilityZonesResponse xmlns="http://ec2.amazonaws.com/doc/2011-05-15/">
+ <requestId>d2e09bd5-b2ec-4c6b-aac9-6bf1fa217cb5</requestId>
+ <availabilityZoneInfo>
+ <item>
+ <zoneName>sa-east-1a</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>sa-east-1</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>sa-east-1b</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>sa-east-1</regionName>
+ <messageSet/>
+ </item>
+ </availabilityZoneInfo>
+</DescribeAvailabilityZonesResponse>
\ No newline at end of file
diff --git a/apis/ec2/src/test/resources/availabilityZones-us-east-1.xml b/apis/ec2/src/test/resources/availabilityZones-us-east-1.xml
new file mode 100644
index 0000000..52b521e
--- /dev/null
+++ b/apis/ec2/src/test/resources/availabilityZones-us-east-1.xml
@@ -0,0 +1,35 @@
+<DescribeAvailabilityZonesResponse xmlns="http://ec2.amazonaws.com/doc/2011-05-15/">
+ <requestId>ed825abf-edbb-4677-83d5-0fbd86ce5a5d</requestId>
+ <availabilityZoneInfo>
+ <item>
+ <zoneName>us-east-1a</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>us-east-1</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>us-east-1b</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>us-east-1</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>us-east-1c</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>us-east-1</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>us-east-1d</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>us-east-1</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>us-east-1e</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>us-east-1</regionName>
+ <messageSet/>
+ </item>
+ </availabilityZoneInfo>
+</DescribeAvailabilityZonesResponse>
\ No newline at end of file
diff --git a/apis/ec2/src/test/resources/availabilityZones-us-west-1.xml b/apis/ec2/src/test/resources/availabilityZones-us-west-1.xml
new file mode 100644
index 0000000..c74ce18
--- /dev/null
+++ b/apis/ec2/src/test/resources/availabilityZones-us-west-1.xml
@@ -0,0 +1,23 @@
+<DescribeAvailabilityZonesResponse xmlns="http://ec2.amazonaws.com/doc/2011-05-15/">
+ <requestId>dbfb2a5f-ce75-49fb-846b-e2cf2fc5cdbb</requestId>
+ <availabilityZoneInfo>
+ <item>
+ <zoneName>us-west-1a</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>us-west-1</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>us-west-1b</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>us-west-1</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>us-west-1c</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>us-west-1</regionName>
+ <messageSet/>
+ </item>
+ </availabilityZoneInfo>
+</DescribeAvailabilityZonesResponse>
\ No newline at end of file
diff --git a/apis/ec2/src/test/resources/availabilityZones-us-west-2.xml b/apis/ec2/src/test/resources/availabilityZones-us-west-2.xml
new file mode 100644
index 0000000..a782705
--- /dev/null
+++ b/apis/ec2/src/test/resources/availabilityZones-us-west-2.xml
@@ -0,0 +1,23 @@
+<DescribeAvailabilityZonesResponse xmlns="http://ec2.amazonaws.com/doc/2011-05-15/">
+ <requestId>e40c2bc4-7231-4df1-a604-202bb8333332</requestId>
+ <availabilityZoneInfo>
+ <item>
+ <zoneName>us-west-2a</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>us-west-2</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>us-west-2b</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>us-west-2</regionName>
+ <messageSet/>
+ </item>
+ <item>
+ <zoneName>us-west-2c</zoneName>
+ <zoneState>available</zoneState>
+ <regionName>us-west-2</regionName>
+ <messageSet/>
+ </item>
+ </availabilityZoneInfo>
+</DescribeAvailabilityZonesResponse>
\ No newline at end of file
diff --git a/apis/ec2/src/test/resources/regionEndpoints-all.xml b/apis/ec2/src/test/resources/regionEndpoints-all.xml
new file mode 100644
index 0000000..d577f72
--- /dev/null
+++ b/apis/ec2/src/test/resources/regionEndpoints-all.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DescribeRegionsResponse xmlns="http://ec2.amazonaws.com/doc/2011-05-15/">
+ <requestId>8392a998-c7bb-41fc-be15-045f528d7627</requestId>
+ <regionInfo>
+ <item>
+ <regionName>eu-west-1</regionName>
+ <regionEndpoint>ec2.eu-west-1.amazonaws.com</regionEndpoint>
+ </item>
+ <item>
+ <regionName>sa-east-1</regionName>
+ <regionEndpoint>ec2.sa-east-1.amazonaws.com</regionEndpoint>
+ </item>
+ <item>
+ <regionName>us-east-1</regionName>
+ <regionEndpoint>ec2.us-east-1.amazonaws.com</regionEndpoint>
+ </item>
+ <item>
+ <regionName>ap-northeast-1</regionName>
+ <regionEndpoint>ec2.ap-northeast-1.amazonaws.com</regionEndpoint>
+ </item>
+ <item>
+ <regionName>us-west-2</regionName>
+ <regionEndpoint>ec2.us-west-2.amazonaws.com</regionEndpoint>
+ </item>
+ <item>
+ <regionName>us-west-1</regionName>
+ <regionEndpoint>ec2.us-west-1.amazonaws.com</regionEndpoint>
+ </item>
+ <item>
+ <regionName>ap-southeast-1</regionName>
+ <regionEndpoint>ec2.ap-southeast-1.amazonaws.com</regionEndpoint>
+ </item>
+ </regionInfo>
+</DescribeRegionsResponse>
\ No newline at end of file
diff --git a/apis/ec2/src/test/resources/run_instances_cloudbridge.xml b/apis/ec2/src/test/resources/run_instances_cloudbridge.xml
new file mode 100644
index 0000000..37d5ae8
--- /dev/null
+++ b/apis/ec2/src/test/resources/run_instances_cloudbridge.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-06-15/">
+ <requestId>56eeacd9-c790-45c3-85f3-e4380b55e1d8</requestId>
+ <reservationId>r-f847a6ca</reservationId>
+ <ownerId>55ed6530-9b32-48f1-acb7-6ec0d3255a65</ownerId>
+ <groupSet>
+ <item>
+ <groupId>jclouds#greenqloud-computeblock</groupId>
+ </item>
+ <item>
+ <groupId>jclouds#greenqloud-computeblock</groupId>
+ </item>
+ </groupSet>
+ <instancesSet>
+ <item>
+ <instanceId>i-01b0dac3</instanceId>
+ <imageId>qmi-9ac92558</imageId>
+ <instanceState>
+ <code>0</code>
+ <name>pending</name>
+ </instanceState>
+ <privateDnsName/>
+ <dnsName/>
+ <reason/>
+ <keyName>jclouds#greenqloud-computeblock#35</keyName>
+ <amiLaunchIndex>0</amiLaunchIndex>
+ <productCodes>
+ <item>
+ <productCode/>
+ </item>
+ </productCodes>
+ <instanceType>m1.small</instanceType>
+ <launchTime>2012-06-15T19:06:35.000+00:00</launchTime>
+ <placement>
+ <availabilityZone>is-1a</availabilityZone>
+ </placement>
+ <kernelId/>
+ <ramdiskId/>
+ <platform/>
+ <monitoring>
+ <state>disabled</state>
+ </monitoring>
+ <subnetId/>
+ <vpcId/>
+ <privateIpAddress/>
+ <groupSet>
+ <item>
+ <groupId>jclouds#greenqloud-computeblock</groupId>
+ </item>
+ <item>
+ <groupId>jclouds#greenqloud-computeblock</groupId>
+ </item>
+ </groupSet>
+ <stateReason>
+ <code>pending</code>
+ <message>pending</message>
+ </stateReason>
+ <architecture/>
+ <rootDeviceType>ebs</rootDeviceType>
+ <rootDeviceName/>
+ <blockDeviceMapping/>
+ <instanceLifecycle/>
+ <spotInstanceRequestId/>
+ <hypervisor>xen</hypervisor>
+ </item>
+ </instancesSet>
+ <requesterId/>
+</RunInstancesResponse>
\ No newline at end of file
diff --git a/apis/elasticstack/pom.xml b/apis/elasticstack/pom.xml
index 7925103..c2e8d7e 100644
--- a/apis/elasticstack/pom.xml
+++ b/apis/elasticstack/pom.xml
@@ -50,13 +50,10 @@
<properties>
<test.elasticstack.endpoint>https://api.lon-p.elastichosts.com</test.elasticstack.endpoint>
<test.elasticstack.api-version>1.0</test.elasticstack.api-version>
- <test.elasticstack.build-version />
+ <test.elasticstack.build-version></test.elasticstack.build-version>
<test.elasticstack.identity>FIXME</test.elasticstack.identity>
<test.elasticstack.credential>FIXME</test.elasticstack.credential>
- <test.elasticstack.image-id>38df0986-4d85-4b76-b502-3878ffc80161</test.elasticstack.image-id>
- <test.elasticstack.image.login-user />
- <test.elasticstack.image.authenticate-sudo />
-
+ <test.elasticstack.template>imageId=38df0986-4d85-4b76-b502-3878ffc80161</test.elasticstack.template>
<jclouds.osgi.export>org.jclouds.elasticstack*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -120,9 +117,7 @@
<test.elasticstack.build-version>${test.elasticstack.build-version}</test.elasticstack.build-version>
<test.elasticstack.identity>${test.elasticstack.identity}</test.elasticstack.identity>
<test.elasticstack.credential>${test.elasticstack.credential}</test.elasticstack.credential>
- <test.elasticstack.image-id>${test.elasticstack.image-id}</test.elasticstack.image-id>
- <test.elasticstack.image.login-user>${test.elasticstack.image.login-user}</test.elasticstack.image.login-user>
- <test.elasticstack.image.authenticate-sudo>${test.elasticstack.image.authenticate-sudo}</test.elasticstack.image.authenticate-sudo>
+ <test.elasticstack.template>${test.elasticstack.template}</test.elasticstack.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java b/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java
index 54c9fd1..1eea179 100644
--- a/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java
+++ b/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java
@@ -55,7 +55,6 @@
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
-import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.HostAndPort;
@@ -83,6 +82,7 @@
protected RestContext<ElasticStackClient, ElasticStackAsyncClient> cloudStackContext;
protected Predicate<HostAndPort> socketTester;
protected Predicate<DriveInfo> driveNotClaimed;
+ protected String imageId;
@BeforeGroups(groups = { "integration", "live" })
@Override
@@ -96,7 +96,7 @@
socketTester = new RetryablePredicate<HostAndPort>(new InetSocketAddressConnect(), maxDriveImageTime, 1,
TimeUnit.SECONDS);
- if (Strings.emptyToNull(imageId) == null) {
+ if (template == null || template.getImageId() == null) {
imageId = view.getComputeService().templateBuilder().build().getImage().getId();
}
}
diff --git a/apis/eucalyptus/pom.xml b/apis/eucalyptus/pom.xml
index 1e71b8d..67848f5 100644
--- a/apis/eucalyptus/pom.xml
+++ b/apis/eucalyptus/pom.xml
@@ -36,13 +36,11 @@
<properties>
<test.eucalyptus.endpoint>http://ecc.eucalyptus.com:8773/services/Eucalyptus</test.eucalyptus.endpoint>
<test.eucalyptus.api-version>2010-06-15</test.eucalyptus.api-version>
- <test.eucalyptus.build-version />
+ <test.eucalyptus.build-version></test.eucalyptus.build-version>
<test.eucalyptus.identity>FIXME_IDENTITY</test.eucalyptus.identity>
<test.eucalyptus.credential>FIXME_CREDENTIAL</test.eucalyptus.credential>
- <test.eucalyptus.image-id />
- <test.eucalyptus.image.login-user />
- <test.eucalyptus.image.authenticate-sudo />
-
+ <test.eucalyptus.template></test.eucalyptus.template>
+ <test.eucalyptus.ebs-template></test.eucalyptus.ebs-template>
<jclouds.osgi.export>org.jclouds.eucalyptus*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -115,9 +113,8 @@
<test.eucalyptus.build-version>${test.eucalyptus.build-version}</test.eucalyptus.build-version>
<test.eucalyptus.identity>${test.eucalyptus.identity}</test.eucalyptus.identity>
<test.eucalyptus.credential>${test.eucalyptus.credential}</test.eucalyptus.credential>
- <test.eucalyptus.image-id>${test.eucalyptus.image-id}</test.eucalyptus.image-id>
- <test.eucalyptus.image.login-user>${test.eucalyptus.image.login-user}</test.eucalyptus.image.login-user>
- <test.eucalyptus.image.authenticate-sudo>${test.eucalyptus.image.authenticate-sudo}</test.eucalyptus.image.authenticate-sudo>
+ <test.eucalyptus.template>${test.eucalyptus.template}</test.eucalyptus.template>
+ <test.eucalyptus.ebs-template>${test.eucalyptus.ebs-template}</test.eucalyptus.ebs-template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/apis/eucalyptus/src/main/java/org/jclouds/eucalyptus/EucalyptusApiMetadata.java b/apis/eucalyptus/src/main/java/org/jclouds/eucalyptus/EucalyptusApiMetadata.java
index 80855d3..fd7a798 100644
--- a/apis/eucalyptus/src/main/java/org/jclouds/eucalyptus/EucalyptusApiMetadata.java
+++ b/apis/eucalyptus/src/main/java/org/jclouds/eucalyptus/EucalyptusApiMetadata.java
@@ -17,9 +17,7 @@
* under the License.
*/
package org.jclouds.eucalyptus;
-
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
-import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Properties;
@@ -57,8 +55,8 @@
public static Properties defaultProperties() {
Properties properties = EC2ApiMetadata.defaultProperties();
- properties.setProperty(PROPERTY_REGIONS, "Eucalyptus");
- properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "admin");
+ // in version 3, lowecase 'e' version 2, uppercase 'E'
+ properties.setProperty(PROPERTY_REGIONS, "eucalyptus");
properties.setProperty(TIMEOUT_PORT_OPEN, 5 * 60 * 1000 + "");
return properties;
}
@@ -67,7 +65,7 @@
protected Builder(){
super(EC2Client.class, EC2AsyncClient.class);
id("eucalyptus")
- .defaultEndpoint("http://173.205.188.130:8773/services/Eucalyptus")
+ .defaultEndpoint("http://partnercloud.eucalyptus.com:8773/services/Eucalyptus/")
.name("Eucalyptus (EC2 clone) API")
.defaultProperties(EucalyptusApiMetadata.defaultProperties());
}
diff --git a/apis/eucalyptus/src/test/java/org/jclouds/eucalyptus/config/EucalyptusRestClientModuleExpectTest.java b/apis/eucalyptus/src/test/java/org/jclouds/eucalyptus/config/EucalyptusRestClientModuleExpectTest.java
new file mode 100644
index 0000000..722d4b2
--- /dev/null
+++ b/apis/eucalyptus/src/test/java/org/jclouds/eucalyptus/config/EucalyptusRestClientModuleExpectTest.java
@@ -0,0 +1,106 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.eucalyptus.config;
+
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.jclouds.eucalyptus.internal.BaseEucalyptusExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.location.Region;
+import org.jclouds.location.Zone;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.location.functions.ZoneToEndpoint;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "EucalyptusRestClientModuleExpectTest")
+public class EucalyptusRestClientModuleExpectTest extends BaseEucalyptusExpectTest<Injector> {
+ private Injector injector;
+
+ public EucalyptusRestClientModuleExpectTest() {
+ Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse> builder();
+ builder.put(describeRegionsRequest, describeRegionsResponse);
+ builder.put(describeAZRequest, describeAZResponse);
+
+ injector = requestsSendResponses(builder.build());
+ }
+
+ public void testLocationIdAndURIBindings() {
+
+ assertEquals(injector.getInstance(Key.get(new TypeLiteral<Supplier<Set<String>>>() {
+ }, Region.class)).get(), ImmutableSet.<String> of("eucalyptus"));
+
+ assertEquals(injector.getInstance(Key.get(new TypeLiteral<Supplier<Set<String>>>() {
+ }, Zone.class)).get(), ImmutableSet.<String> of("partner01"));
+
+ Map<String, Supplier<URI>> regionToURISupplier = injector.getInstance(
+ Key.get(new TypeLiteral<Supplier<Map<String, Supplier<URI>>>>() {
+ }, Region.class)).get();
+
+ assertEquals(regionToURISupplier.get("eucalyptus").get(), URI.create("http://eucalyptus.partner.eucalyptus.com:8773/services/Eucalyptus"));
+
+ Map<String, Supplier<Set<String>>> regionToZoneIdSupplier = injector.getInstance(
+ Key.get(new TypeLiteral<Supplier<Map<String, Supplier<Set<String>>>>>() {
+ }, Zone.class)).get();
+
+ assertEquals(regionToZoneIdSupplier.get("eucalyptus").get(), ImmutableSet.of("partner01"));
+
+ Map<String, Supplier<URI>> zoneToURISupplier = injector.getInstance(
+ Key.get(new TypeLiteral<Supplier<Map<String, Supplier<URI>>>>() {
+ }, Zone.class)).get();
+
+ assertEquals(zoneToURISupplier.get("partner01").get(), URI.create("http://eucalyptus.partner.eucalyptus.com:8773/services/Eucalyptus"));
+
+ }
+
+ public void testZoneToEndpoint() {
+ assertEquals(injector.getInstance(ZoneToEndpoint.class).apply("partner01"),
+ URI.create("http://eucalyptus.partner.eucalyptus.com:8773/services/Eucalyptus"));
+
+ }
+
+ public void testRegionToEndpointOrProviderIfNull() {
+ assertEquals(injector.getInstance(RegionToEndpointOrProviderIfNull.class).apply("eucalyptus"),
+ URI.create("http://eucalyptus.partner.eucalyptus.com:8773/services/Eucalyptus"));
+ }
+
+ @Override
+ public Injector createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
+ return createInjector(fn, module, props);
+ }
+
+}
diff --git a/apis/eucalyptus/src/test/java/org/jclouds/eucalyptus/internal/BaseEucalyptusExpectTest.java b/apis/eucalyptus/src/test/java/org/jclouds/eucalyptus/internal/BaseEucalyptusExpectTest.java
new file mode 100644
index 0000000..0549fe7
--- /dev/null
+++ b/apis/eucalyptus/src/test/java/org/jclouds/eucalyptus/internal/BaseEucalyptusExpectTest.java
@@ -0,0 +1,91 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.eucalyptus.internal;
+
+import java.net.URI;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.DateService;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.ec2.EC2AsyncClient;
+import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.config.EC2RestClientModule;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.internal.BaseRestClientExpectTest;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+public abstract class BaseEucalyptusExpectTest<T> extends BaseRestClientExpectTest<T> {
+ protected static final String CONSTANT_DATE = "2012-04-16T15:54:08.897Z";
+
+ protected DateService dateService = new SimpleDateFormatDateService();
+
+ protected HttpRequest describeRegionsRequest = HttpRequest
+ .builder()
+ .method("POST")
+ .endpoint(URI.create("http://partnercloud.eucalyptus.com:8773/services/Eucalyptus/"))
+ .headers(ImmutableMultimap.of("Host", "partnercloud.eucalyptus.com:8773"))
+ .payload(payloadFromStringWithContentType(
+ "Action=DescribeRegions&Signature=tp9WpT8503JdxIXYu6Eu2Dmu%2Bd%2FpqviST7N7Fvr%2FyQo%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity",
+ MediaType.APPLICATION_FORM_URLENCODED)).build();
+
+ protected HttpResponse describeRegionsResponse = HttpResponse.builder().statusCode(200)
+ .payload(payloadFromResourceWithContentType("/regionEndpoints-euca.xml", MediaType.APPLICATION_XML))
+ .build();
+
+ protected HttpRequest describeAZRequest = HttpRequest.builder()
+ .method("POST")
+ .endpoint(URI.create("http://eucalyptus.partner.eucalyptus.com:8773/services/Eucalyptus/"))
+ .headers(ImmutableMultimap.of("Host", "eucalyptus.partner.eucalyptus.com:8773"))
+ .payload(payloadFromStringWithContentType(
+ "Action=DescribeAvailabilityZones&Signature=i4OkMed1sqQV7hlF%2Fl1KdbQwmwJ4Fh4o9W32eVGayPk%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity",
+ MediaType.APPLICATION_FORM_URLENCODED)).build();
+
+ protected HttpResponse describeAZResponse = HttpResponse.builder().statusCode(200)
+ .payload(payloadFromResourceWithContentType(
+ "/availabilityZones-eucalyptus.xml", MediaType.APPLICATION_XML)).build();
+
+
+ public BaseEucalyptusExpectTest() {
+ provider = "eucalyptus";
+ }
+
+ @ConfiguresRestClient
+ private static final class TestEucalyptusRestClientModule extends EC2RestClientModule<EC2Client, EC2AsyncClient> {
+ @Override
+ @Provides
+ protected String provideTimeStamp(DateService dateService) {
+ return CONSTANT_DATE;
+ }
+ }
+
+ @Override
+ protected Module createModule() {
+ return new TestEucalyptusRestClientModule();
+ }
+}
diff --git a/apis/eucalyptus/src/test/resources/availabilityZones-eucalyptus.xml b/apis/eucalyptus/src/test/resources/availabilityZones-eucalyptus.xml
new file mode 100644
index 0000000..0c5a052
--- /dev/null
+++ b/apis/eucalyptus/src/test/resources/availabilityZones-eucalyptus.xml
@@ -0,0 +1,11 @@
+<DescribeAvailabilityZonesResponse
+ xmlns="http://ec2.amazonaws.com/doc/2010-06-15/">
+ <availabilityZoneInfo>
+ <item>
+ <zoneName>partner01</zoneName>
+ <zoneState>173.205.188.7 arn:euca:eucalyptus:partner01:cluster:cc_01/</zoneState>
+ <regionName />
+ <messageSet />
+ </item>
+ </availabilityZoneInfo>
+</DescribeAvailabilityZonesResponse>
\ No newline at end of file
diff --git a/apis/eucalyptus/src/test/resources/regionEndpoints-euca.xml b/apis/eucalyptus/src/test/resources/regionEndpoints-euca.xml
new file mode 100644
index 0000000..a3b205c
--- /dev/null
+++ b/apis/eucalyptus/src/test/resources/regionEndpoints-euca.xml
@@ -0,0 +1,12 @@
+<DescribeRegionsResponse xmlns="http://ec2.amazonaws.com/doc/2010-06-15/">
+ <regionInfo>
+ <item>
+ <regionName>eucalyptus</regionName>
+ <regionEndpoint>http://eucalyptus.partner.eucalyptus.com:8773/services/Eucalyptus</regionEndpoint>
+ </item>
+ <item>
+ <regionName>walrus</regionName>
+ <regionEndpoint>http://walrus.partner.eucalyptus.com:8773/services/Walrus</regionEndpoint>
+ </item>
+ </regionInfo>
+</DescribeRegionsResponse>
\ No newline at end of file
diff --git a/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemAsyncBlobStoreTest.java b/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemAsyncBlobStoreTest.java
index 36ea828..c8d3b0d 100644
--- a/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemAsyncBlobStoreTest.java
+++ b/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemAsyncBlobStoreTest.java
@@ -858,7 +858,7 @@
// nothing expected
if (null == expectedBlobKeys || 0 == expectedBlobKeys.size()) {
- assertTrue(blobsRetrieved.isEmpty(), "Wrong blob number retrieved in the containter [" + containerName + "]");
+ assertTrue(blobsRetrieved.isEmpty(), "Wrong blob number retrieved in the container [" + containerName + "]");
return;
}
@@ -868,7 +868,7 @@
expectedBlobKeysCopy.add(value);
}
assertEquals(blobsRetrieved.size(), expectedBlobKeysCopy.size(),
- "Wrong blob number retrieved in the containter [" + containerName + "]");
+ "Wrong blob number retrieved in the container [" + containerName + "]");
for (StorageMetadata data : blobsRetrieved) {
String blobName = data.getName();
if (!expectedBlobKeysCopy.remove(blobName)) {
diff --git a/apis/nova/pom.xml b/apis/nova/pom.xml
index d58260f..5d6ac6c 100644
--- a/apis/nova/pom.xml
+++ b/apis/nova/pom.xml
@@ -36,14 +36,12 @@
<properties>
<test.nova.endpoint>http://localhost:8773/services/Cloud</test.nova.endpoint>
<test.nova.api-version>1.1</test.nova.api-version>
- <test.nova.build-version />
+ <test.nova.build-version></test.nova.build-version>
<test.nova.identity>FIXME_IDENTITY</test.nova.identity>
<test.nova.credential>FIXME_CREDENTIALS</test.nova.credential>
- <test.nova.image-id />
- <test.nova.image.login-user />
- <test.nova.image.authenticate-sudo />
- <test.ssh.keyfile.public />
- <test.ssh.keyfile.private />
+ <test.nova.template></test.nova.template>
+ <test.ssh.keyfile.public></test.ssh.keyfile.public>
+ <test.ssh.keyfile.private></test.ssh.keyfile.private>
<jclouds.osgi.export>org.jclouds.openstack.nova*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -122,9 +120,7 @@
<test.nova.build-version>${test.nova.build-version}</test.nova.build-version>
<test.nova.identity>${test.nova.identity}</test.nova.identity>
<test.nova.credential>${test.nova.credential}</test.nova.credential>
- <test.nova.image-id>${test.nova.image-id}</test.nova.image-id>
- <test.nova.image.login-user>${test.nova.image.login-user}</test.nova.image.login-user>
- <test.nova.image.authenticate-sudo>${test.nova.image.authenticate-sudo}</test.nova.image.authenticate-sudo>
+ <test.nova.template>${test.nova.template}</test.nova.template>
<test.ssh.keyfile.public>${test.ssh.keyfile.public}</test.ssh.keyfile.public>
<test.ssh.keyfile.private>${test.ssh.keyfile.private}</test.ssh.keyfile.private>
</systemPropertyVariables>
diff --git a/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java b/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java
index 769a3af..397ee7e 100644
--- a/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java
+++ b/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java
@@ -214,7 +214,7 @@
while (server == null) {
String serverName = serverPrefix + "createserver" + new SecureRandom().nextInt();
try {
- server = client.createServer(serverName, imageId, flavorId, withFile("/etc/jclouds.txt",
+ server = client.createServer(serverName, template.getImageId(), flavorId, withFile("/etc/jclouds.txt",
"nova".getBytes()).withMetadata(metadata));
} catch (UndeclaredThrowableException e) {
HttpResponseException htpe = (HttpResponseException) e.getCause().getCause();
diff --git a/apis/openstack-keystone/pom.xml b/apis/openstack-keystone/pom.xml
index 4004151..3107a62 100644
--- a/apis/openstack-keystone/pom.xml
+++ b/apis/openstack-keystone/pom.xml
@@ -43,9 +43,7 @@
<test.openstack-keystone.credential>FIXME_CREDENTIALS</test.openstack-keystone.credential>
<test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
- <jclouds.osgi.export>org.jclouds.openstack.v2_0*;version="${project.version}",
- org.jclouds.openstack.keystone.v2_0*;version="${project.version}"
- </jclouds.osgi.export>
+ <jclouds.osgi.export>org.jclouds.openstack*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
diff --git a/apis/openstack-nova-ec2/pom.xml b/apis/openstack-nova-ec2/pom.xml
index 63ee14f..94fba78 100644
--- a/apis/openstack-nova-ec2/pom.xml
+++ b/apis/openstack-nova-ec2/pom.xml
@@ -36,13 +36,11 @@
<properties>
<test.openstack-nova-ec2.endpoint>http://localhost:8773/services/Cloud</test.openstack-nova-ec2.endpoint>
<test.openstack-nova-ec2.api-version>2010-06-15</test.openstack-nova-ec2.api-version>
- <test.openstack-nova-ec2.build-version />
+ <test.openstack-nova-ec2.build-version></test.openstack-nova-ec2.build-version>
<test.openstack-nova-ec2.identity>FIXME_IDENTITY</test.openstack-nova-ec2.identity>
<test.openstack-nova-ec2.credential>FIXME_CREDENTIAL</test.openstack-nova-ec2.credential>
- <test.openstack-nova-ec2.image-id />
- <test.openstack-nova-ec2.image.login-user />
- <test.openstack-nova-ec2.image.authenticate-sudo />
-
+ <test.openstack-nova-ec2.template></test.openstack-nova-ec2.template>
+ <test.openstack-nova-ec2.ebs-template></test.openstack-nova-ec2.ebs-template>
<jclouds.osgi.export>org.jclouds.openstack.nova.ec2*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -120,9 +118,8 @@
<test.openstack-nova-ec2.build-version>${test.openstack-nova-ec2.build-version}</test.openstack-nova-ec2.build-version>
<test.openstack-nova-ec2.identity>${test.openstack-nova-ec2.identity}</test.openstack-nova-ec2.identity>
<test.openstack-nova-ec2.credential>${test.openstack-nova-ec2.credential}</test.openstack-nova-ec2.credential>
- <test.openstack-nova-ec2.image-id>${test.openstack-nova-ec2.image-id}</test.openstack-nova-ec2.image-id>
- <test.openstack-nova-ec2.image.login-user>${test.openstack-nova-ec2.image.login-user}</test.openstack-nova-ec2.image.login-user>
- <test.openstack-nova-ec2.image.authenticate-sudo>${test.openstack-nova-ec2.image.authenticate-sudo}</test.openstack-nova-ec2.image.authenticate-sudo>
+ <test.openstack-nova-ec2.template>${test.openstack-nova-ec2.template}</test.openstack-nova-ec2.template>
+ <test.openstack-nova-ec2.ebs-template>${test.openstack-nova-ec2.ebs-template}</test.openstack-nova-ec2.ebs-template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestClientExpectTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestClientExpectTest.java
index 69b7eed..d1730d9 100644
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestClientExpectTest.java
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestClientExpectTest.java
@@ -2,10 +2,8 @@
import java.net.URI;
-import javax.inject.Named;
import javax.ws.rs.core.MediaType;
-import org.jclouds.Constants;
import org.jclouds.date.DateService;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.HttpRequest;
@@ -45,8 +43,7 @@
private static final class TestNovaEC2RestClientModule extends NovaEC2RestClientModule {
@Override
@Provides
- protected String provideTimeStamp(final DateService dateService,
- @Named(Constants.PROPERTY_SESSION_INTERVAL) final int expiration) {
+ protected String provideTimeStamp(DateService dateService) {
return CONSTANT_DATE;
}
}
diff --git a/apis/openstack-nova/pom.xml b/apis/openstack-nova/pom.xml
index 445f625..44935e3 100644
--- a/apis/openstack-nova/pom.xml
+++ b/apis/openstack-nova/pom.xml
@@ -38,12 +38,10 @@
<test.openstack-nova.endpoint>http://localhost:5000</test.openstack-nova.endpoint>
<!-- keystone version -->
<test.openstack-nova.api-version>1.1</test.openstack-nova.api-version>
- <test.openstack-nova.build-version />
+ <test.openstack-nova.build-version></test.openstack-nova.build-version>
<test.openstack-nova.identity>FIXME_IDENTITY</test.openstack-nova.identity>
<test.openstack-nova.credential>FIXME_CREDENTIALS</test.openstack-nova.credential>
- <test.openstack-nova.image-id />
- <test.openstack-nova.image.login-user />
- <test.openstack-nova.image.authenticate-sudo />
+ <test.openstack-nova.template></test.openstack-nova.template>
<test.jclouds.openstack-nova.auto-allocate-floating-ips>false</test.jclouds.openstack-nova.auto-allocate-floating-ips>
<test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
@@ -130,9 +128,7 @@
<test.openstack-nova.build-version>${test.openstack-nova.build-version}</test.openstack-nova.build-version>
<test.openstack-nova.identity>${test.openstack-nova.identity}</test.openstack-nova.identity>
<test.openstack-nova.credential>${test.openstack-nova.credential}</test.openstack-nova.credential>
- <test.openstack-nova.image-id>${test.openstack-nova.image-id}</test.openstack-nova.image-id>
- <test.openstack-nova.image.login-user>${test.openstack-nova.image.login-user}</test.openstack-nova.image.login-user>
- <test.openstack-nova.image.authenticate-sudo>${test.openstack-nova.image.authenticate-sudo}</test.openstack-nova.image.authenticate-sudo>
+ <test.openstack-nova.template>${test.openstack-nova.template}</test.openstack-nova.template>
<test.jclouds.openstack-nova.auto-allocate-floating-ips>${test.jclouds.openstack-nova.auto-allocate-floating-ips}</test.jclouds.openstack-nova.auto-allocate-floating-ips>
<test.jclouds.keystone.credential-type>${test.jclouds.keystone.credential-type}</test.jclouds.keystone.credential-type>
</systemPropertyVariables>
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInZoneToNodeMetadata.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInZoneToNodeMetadata.java
index f5d1957..548126a 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInZoneToNodeMetadata.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInZoneToNodeMetadata.java
@@ -165,7 +165,7 @@
}
});
} catch (NoSuchElementException e) {
- logger.debug("could not find %s with id(%s) for server(%s)", type, objectId, serverInZone);
+ logger.trace("could not find %s with id(%s) for server(%s)", type, objectId, serverInZone);
}
return null;
}
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
index fa1ec8f..34ca70d 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
@@ -103,9 +103,16 @@
@Override
public ToStringHelper string() {
- return super.string().add("autoAssignFloatingIp", autoAssignFloatingIp)
- .add("securityGroupNames", securityGroupNames).add("generateKeyPair", generateKeyPair)
- .add("keyPairName", keyPairName).add("userData", userData);
+ ToStringHelper toString = super.string();
+ if (!autoAssignFloatingIp)
+ toString.add("autoAssignFloatingIp", autoAssignFloatingIp);
+ if (securityGroupNames.size() != 0)
+ toString.add("securityGroupNames", securityGroupNames);
+ if (generateKeyPair)
+ toString.add("generateKeyPair", generateKeyPair);
+ toString.add("keyPairName", keyPairName);
+ toString.add("userData", userData);
+ return toString;
}
public static final NovaTemplateOptions NONE = new NovaTemplateOptions();
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
index ca6ae80..3b1805e 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
@@ -32,14 +32,12 @@
import javax.inject.Inject;
import javax.inject.Named;
-import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
@@ -71,7 +69,6 @@
private final LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupCache;
private final LoadingCache<ZoneAndName, KeyPair> keyPairCache;
private final NovaClient novaClient;
- private final Provider<TemplateBuilder> templateBuilderProvider;
@Inject
protected ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet(
@@ -80,13 +77,11 @@
GroupNamingConvention.Factory namingConvention,
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
- Provider<TemplateBuilder> templateBuilderProvider,
AllocateAndAddFloatingIpToNode allocateAndAddFloatingIpToNode,
LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupCache,
LoadingCache<ZoneAndName, KeyPair> keyPairCache, NovaClient novaClient) {
super(addNodeWithTagStrategy, listNodesStrategy, namingConvention, executor,
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
- this.templateBuilderProvider = checkNotNull(templateBuilderProvider, "templateBuilderProvider");
this.securityGroupCache = checkNotNull(securityGroupCache, "securityGroupCache");
this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache");
this.allocateAndAddFloatingIpToNode = checkNotNull(allocateAndAddFloatingIpToNode,
@@ -98,16 +93,7 @@
public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
- Template mutableTemplate;
- // ensure we don't mutate the input template, fromTemplate ignores imageId so
- // build directly from imageId if we have it
- if (template.getImage() != null && template.getImage().getId() != null) {
- mutableTemplate = templateBuilderProvider.get().imageId(template.getImage().getId()).fromTemplate(template)
- .build();
- // otherwise build from generic parameters
- } else {
- mutableTemplate = templateBuilderProvider.get().fromTemplate(template).build();
- }
+ Template mutableTemplate = template.clone();
NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(mutableTemplate.getOptions());
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/options/CreateServerOptions.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/options/CreateServerOptions.java
index 7a63d68..00aa5ee 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/options/CreateServerOptions.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/options/CreateServerOptions.java
@@ -26,8 +26,8 @@
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.Map.Entry;
+import java.util.Set;
import javax.inject.Inject;
@@ -40,8 +40,8 @@
import org.jclouds.util.Preconditions2;
import com.google.common.base.Objects;
-import com.google.common.base.Optional;
import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
@@ -133,10 +133,18 @@
}
protected ToStringHelper string() {
- return toStringHelper("").add("keyName", keyName).add("securityGroupNames", securityGroupNames)
- .add("metadata", metadata).add("personality", personality)
- .add("adminPassPresent", adminPass != null)
- .add("userData", userData == null ? null : new String(userData));
+ ToStringHelper toString = Objects.toStringHelper("").omitNullValues();
+ toString.add("keyName", keyName);
+ if (securityGroupNames.size() > 0)
+ toString.add("securityGroupNames", securityGroupNames);
+ if (metadata.size() > 0)
+ toString.add("metadata", metadata);
+ if (personality.size() > 0)
+ toString.add("personality", personality);
+ if (adminPass != null)
+ toString.add("adminPassPresent", true);
+ toString.add("userData", userData == null ? null : new String(userData));
+ return toString;
}
@Override
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/strategy/internal/ParallelMultipartUploadStrategy.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/strategy/internal/ParallelMultipartUploadStrategy.java
index a5b02c5..12481c2 100644
--- a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/strategy/internal/ParallelMultipartUploadStrategy.java
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/strategy/internal/ParallelMultipartUploadStrategy.java
@@ -204,7 +204,7 @@
String eTag = client.putObjectManifest(container, key);
logger.debug(String.format("multipart upload of %s to container %s" +
- " succeffully finished with %s retries", key, container, errors.get()));
+ " successfully finished with %s retries", key, container, errors.get()));
return eTag;
} catch (Exception ex) {
RuntimeException rtex = Throwables2.getFirstThrowableOfType(ex, RuntimeException.class);
diff --git a/apis/vcloud/pom.xml b/apis/vcloud/pom.xml
index bdc529b..4f23e0f 100644
--- a/apis/vcloud/pom.xml
+++ b/apis/vcloud/pom.xml
@@ -36,13 +36,10 @@
<properties>
<test.vcloud.endpoint>FIXME</test.vcloud.endpoint>
<test.vcloud.api-version>1.0</test.vcloud.api-version>
- <test.vcloud.build-version />
+ <test.vcloud.build-version></test.vcloud.build-version>
<test.vcloud.identity>FIXME</test.vcloud.identity>
<test.vcloud.credential>FIXME</test.vcloud.credential>
- <test.vcloud.image-id />
- <test.vcloud.image.login-user />
- <test.vcloud.image.authenticate-sudo />
-
+ <test.vcloud.template></test.vcloud.template>
<jclouds.osgi.export>org.jclouds.vcloud*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -118,9 +115,7 @@
<test.vcloud.build-version>${test.vcloud.build-version}</test.vcloud.build-version>
<test.vcloud.identity>${test.vcloud.identity}</test.vcloud.identity>
<test.vcloud.credential>${test.vcloud.credential}</test.vcloud.credential>
- <test.vcloud.image-id>${test.vcloud.image-id}</test.vcloud.image-id>
- <test.vcloud.image.login-user>${test.vcloud.image.login-user}</test.vcloud.image.login-user>
- <test.vcloud.image.authenticate-sudo>${test.vcloud.image.authenticate-sudo}</test.vcloud.image.authenticate-sudo>
+ <test.vcloud.template>${test.vcloud.template}</test.vcloud.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseContainerIntegrationTest.java b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseContainerIntegrationTest.java
index ec55d60..5ed397c 100644
--- a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseContainerIntegrationTest.java
+++ b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseContainerIntegrationTest.java
@@ -139,7 +139,7 @@
public void testListRootUsesDelimiter() throws InterruptedException {
String containerName = getContainerName();
try {
- String prefix = "rootdelimeter";
+ String prefix = "rootdelimiter";
addTenObjectsUnderPrefix(containerName, prefix);
add15UnderRoot(containerName);
PageSet<? extends StorageMetadata> container = view.getBlobStore().list(containerName);
diff --git a/common/aws/src/main/java/org/jclouds/aws/config/FormSigningRestClientModule.java b/common/aws/src/main/java/org/jclouds/aws/config/FormSigningRestClientModule.java
index 12b90f3..761a292 100644
--- a/common/aws/src/main/java/org/jclouds/aws/config/FormSigningRestClientModule.java
+++ b/common/aws/src/main/java/org/jclouds/aws/config/FormSigningRestClientModule.java
@@ -21,10 +21,8 @@
import java.util.Date;
import java.util.Map;
-import javax.inject.Named;
import javax.inject.Singleton;
-import org.jclouds.Constants;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.date.DateService;
import org.jclouds.date.TimeStamp;
@@ -59,9 +57,8 @@
@Provides
@TimeStamp
- protected String provideTimeStamp(final DateService dateService,
- @Named(Constants.PROPERTY_SESSION_INTERVAL) final int expiration) {
- return dateService.iso8601DateFormat(new Date(System.currentTimeMillis() + (expiration * 1000)));
+ protected String provideTimeStamp(DateService dateService) {
+ return dateService.iso8601DateFormat(new Date(System.currentTimeMillis()));
}
@Provides
diff --git a/common/aws/src/main/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContent.java b/common/aws/src/main/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContent.java
index e4dc779..615801b 100644
--- a/common/aws/src/main/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContent.java
+++ b/common/aws/src/main/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContent.java
@@ -112,7 +112,7 @@
".InUse")))
|| (message != null && (message.indexOf("already exists") != -1 || message.indexOf("is in use") != -1)))
exception = new IllegalStateException(message, exception);
- else if ("AuthFailure".equals(errorCode))
+ else if (errorCode != null && errorCode.indexOf("AuthFailure") != -1)
exception = new AuthorizationException(message, exception);
else if (message != null
&& (message.indexOf("Invalid id") != -1 || message.indexOf("Failed to bind") != -1))
diff --git a/common/aws/src/test/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContentTest.java b/common/aws/src/test/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContentTest.java
index 6df2308..85c6f90 100644
--- a/common/aws/src/test/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContentTest.java
+++ b/common/aws/src/test/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContentTest.java
@@ -56,7 +56,13 @@
assertCodeMakes("GET", URI.create("https://amazonaws.com/foo"), 400, "",
"<Error><Code>Monster.NotFound</Code></Error>", ResourceNotFoundException.class);
}
-
+
+ @Test
+ public void test400WithCloudBridgeNotFoundSetsResourceNotFoundException() {
+ assertCodeMakes("POST", URI.create("https://api.greenqloud.com/"), 400, "",
+ "<Error><Code>Client.InvalidInstanceID.NotFound</Code></Error>", ResourceNotFoundException.class);
+ }
+
@Test
public void test400WithInvalidIdIllegalArgumentException() {
assertCodeMakes("POST", URI.create("https://ec2.us-east-1.amazonaws.com"), 400, "HTTP/1.1 400", "",
@@ -164,6 +170,12 @@
"<Error><Code>AuthFailure</Code></Error>", AuthorizationException.class);
}
+ @Test
+ public void test400WithCloudBridgeAuthFailureSetsAuthorizationException() {
+ assertCodeMakes("POST", URI.create("https://api.greenqloud.com/"), 400, "",
+ "<Error><Code>Client.AuthFailure</Code></Error>", AuthorizationException.class);
+ }
+
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content,
Class<? extends Exception> expected) {
assertCodeMakes(method, uri, statusCode, message, "text/xml", content, expected);
diff --git a/common/openstack/pom.xml b/common/openstack/pom.xml
index af29166..af8aa2a 100644
--- a/common/openstack/pom.xml
+++ b/common/openstack/pom.xml
@@ -35,18 +35,7 @@
<packaging>bundle</packaging>
<properties>
- <jclouds.osgi.export>org.jclouds.openstack.config*;version="${project.version}",
- org.jclouds.openstack.domain*;version="${project.version}"
- org.jclouds.openstack.filters*;version="${project.version}"
- org.jclouds.openstack.functions*;version="${project.version}"
- org.jclouds.openstack.handlers*;version="${project.version}"
- org.jclouds.openstack.internal*;version="${project.version}"
- org.jclouds.openstack.keystone.v1_1*;version="${project.version}"
- org.jclouds.openstack.options*;version="${project.version}"
- org.jclouds.openstack.predicates*;version="${project.version}"
- org.jclouds.openstack.reference*;version="${project.version}"
- org.jclouds.openstack.services*;version="${project.version}"
- </jclouds.osgi.export>
+ <jclouds.osgi.export>org.jclouds.openstack*;version="${project.version}";-noimport:=true</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
</properties>
diff --git a/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNodeAsInitScriptUsingSsh.java b/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNodeAsInitScriptUsingSsh.java
index a3e263a..e2ba40c 100644
--- a/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNodeAsInitScriptUsingSsh.java
+++ b/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNodeAsInitScriptUsingSsh.java
@@ -119,7 +119,7 @@
ssh.connect();
ssh.exec("rm " + initFile);
ssh.exec(Statements.appendFile(initFile, Splitter.on('\n').split(init.render(OsFamily.UNIX)),
- AppendFile.DELIMETER + "_" + init.getInstanceName()).render(OsFamily.UNIX));
+ AppendFile.DELIMITER + "_" + init.getInstanceName()).render(OsFamily.UNIX));
}
ssh.exec("chmod 755 " + initFile);
diff --git a/compute/src/main/java/org/jclouds/compute/callables/SudoAwareInitManager.java b/compute/src/main/java/org/jclouds/compute/callables/SudoAwareInitManager.java
index e94df32..24c3fd0 100644
--- a/compute/src/main/java/org/jclouds/compute/callables/SudoAwareInitManager.java
+++ b/compute/src/main/java/org/jclouds/compute/callables/SudoAwareInitManager.java
@@ -90,7 +90,7 @@
String command = (runAsRoot && Predicates.in(ImmutableSet.of("start", "stop", "run")).apply(action)) ? execScriptAsRoot(action)
: execScriptAsDefaultUser(action);
returnVal = runCommand(command);
- if ("status".equals(action))
+ if (ImmutableSet.of("status", "stdout", "stderr").contains(action))
logger.trace("<< %s(%d)", action, returnVal.getExitStatus());
else if (computeLogger.isTraceEnabled())
computeLogger.trace("<< %s[%s]", action, returnVal);
@@ -103,8 +103,8 @@
String statement = String.format("[%s] as %s@%s", command.replace(
node.getCredentials().getPassword() != null ? node.getCredentials().getPassword() : "XXXXX", "XXXXX"), ssh
.getUsername(), ssh.getHostAddress());
- if (command.endsWith("status"))
- logger.trace(">> running " + statement);
+ if (command.endsWith("status") || command.endsWith("stdout") || command.endsWith("stderr"))
+ logger.trace(">> running %s", statement);
else
computeLogger.debug(">> running " + statement);
ExecResponse returnVal = ssh.exec(command);
diff --git a/compute/src/main/java/org/jclouds/compute/domain/Template.java b/compute/src/main/java/org/jclouds/compute/domain/Template.java
index 9dd98c5..5b6e873 100644
--- a/compute/src/main/java/org/jclouds/compute/domain/Template.java
+++ b/compute/src/main/java/org/jclouds/compute/domain/Template.java
@@ -47,4 +47,11 @@
* options for launching this template, like run scripts or inbound ports
*/
TemplateOptions getOptions();
+
+ /**
+ * clone this template
+ *
+ * @see Object#clone
+ */
+ Template clone();
}
\ No newline at end of file
diff --git a/compute/src/main/java/org/jclouds/compute/domain/TemplateBuilderSpec.java b/compute/src/main/java/org/jclouds/compute/domain/TemplateBuilderSpec.java
index 1192374..604aa64 100644
--- a/compute/src/main/java/org/jclouds/compute/domain/TemplateBuilderSpec.java
+++ b/compute/src/main/java/org/jclouds/compute/domain/TemplateBuilderSpec.java
@@ -152,7 +152,7 @@
.put("authenticateSudo", new AuthenticateSudoParser())
.put("locationId", new LocationIdParser())
.build();
-
+
@VisibleForTesting
String hardwareId;
@VisibleForTesting
@@ -553,4 +553,63 @@
}
}
+ public String getHardwareId() {
+ return hardwareId;
+ }
+
+ public Double getMinCores() {
+ return minCores;
+ }
+
+ public Integer getMinRam() {
+ return minRam;
+ }
+
+ public String getHypervisorMatches() {
+ return hypervisorMatches;
+ }
+
+ public String getImageId() {
+ return imageId;
+ }
+
+ public String getImageNameMatches() {
+ return imageNameMatches;
+ }
+
+ public OsFamily getOsFamily() {
+ return osFamily;
+ }
+
+ public String getOsVersionMatches() {
+ return osVersionMatches;
+ }
+
+ public Boolean getOs64Bit() {
+ return os64Bit;
+ }
+
+ public String getOsArchMatches() {
+ return osArchMatches;
+ }
+
+ public String getOsDescriptionMatches() {
+ return osDescriptionMatches;
+ }
+
+ public String getLoginUser() {
+ return loginUser;
+ }
+
+ public Boolean getAuthenticateSudo() {
+ return authenticateSudo;
+ }
+
+ public String getLocationId() {
+ return locationId;
+ }
+
+ public String getSpecification() {
+ return specification;
+ }
}
diff --git a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java
index 648b828..e8d4155 100644
--- a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java
+++ b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java
@@ -24,6 +24,7 @@
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.size;
import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Iterables.tryFind;
import static com.google.common.collect.Lists.newArrayList;
import static java.lang.String.format;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
@@ -57,6 +58,8 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
@@ -403,27 +406,23 @@
private Predicate<Hardware> buildHardwarePredicate() {
List<Predicate<Hardware>> predicates = newArrayList();
- if (hardwareId != null) {
- predicates.add(hardwareIdPredicate);
- } else {
- if (location != null)
- predicates.add(new Predicate<Hardware>() {
+ if (location != null)
+ predicates.add(new Predicate<Hardware>() {
- @Override
- public boolean apply(Hardware input) {
- return locationPredicate.apply(input);
- }
+ @Override
+ public boolean apply(Hardware input) {
+ return locationPredicate.apply(input);
+ }
- @Override
- public String toString() {
- return locationPredicate.toString();
- }
- });
- if (hypervisor != null)
- predicates.add(hypervisorPredicate);
- predicates.add(hardwareCoresPredicate);
- predicates.add(hardwareRamPredicate);
- }
+ @Override
+ public String toString() {
+ return locationPredicate.toString();
+ }
+ });
+ if (hypervisor != null)
+ predicates.add(hypervisorPredicate);
+ predicates.add(hardwareCoresPredicate);
+ predicates.add(hardwareRamPredicate);
// looks verbose, but explicit <Hardware> type needed for this to compile
// properly
@@ -612,35 +611,87 @@
options = optionsProvider.get();
logger.debug(">> searching params(%s)", this);
Set<? extends Image> images = getImages();
+ Set<? extends Hardware> hardwaresToSearch = hardwares.get();
+
+ Image image = null;
+ if (imageId != null) {
+ image = findImageWithId(images);
+ if (currentLocationWiderThan(image.getLocation()))
+ this.location = image.getLocation();
+ }
+
+ Hardware hardware = null;
+ if (hardwareId != null) {
+ hardware = findHardwareWithId(hardwaresToSearch);
+ if (currentLocationWiderThan(hardware.getLocation()))
+ this.location = hardware.getLocation();
+ }
+
+ // if the user hasn't specified a location id, or an image or hardware
+ // with location, let's search scoped to the implicit one
if (location == null)
location = defaultLocation.get();
- Predicate<Image> imagePredicate = buildImagePredicate();
- Iterable<? extends Image> supportedImages = filter(images, imagePredicate);
- if (size(supportedImages) == 0) {
- if (imagePredicate == idPredicate) {
- throwNoSuchElementExceptionAfterLoggingImageIds(format("%s not found", idPredicate), images);
- } else {
- throwNoSuchElementExceptionAfterLoggingImageIds(format("no image matched predicate: %s", imagePredicate),
- images);
- }
+ if (image == null) {
+ Iterable<? extends Image> supportedImages = findSupportedImages(images);
+ if (hardware == null)
+ hardware = resolveHardware(hardwaresToSearch, supportedImages);
+ image = resolveImage(hardware, supportedImages);
+ } else {
+ if (hardware == null)
+ hardware = resolveHardware(hardwaresToSearch, ImmutableSet.of(image));
}
- Hardware hardware = resolveHardware(hardwareSorter(), supportedImages);
- Image image = resolveImage(hardware, supportedImages);
- logger.debug("<< matched image(%s)", image.getId());
+ logger.debug("<< matched image(%s) hardware(%s) location(%s)", image.getId(), hardware.getId(),
+ location.getId());
return new TemplateImpl(image, hardware, location, options);
}
- protected void throwNoSuchElementExceptionAfterLoggingImageIds(String message, Iterable<? extends Image> images) {
+ private Iterable<? extends Image> findSupportedImages(Set<? extends Image> images) {
+ Predicate<Image> imagePredicate = buildImagePredicate();
+ Iterable<? extends Image> supportedImages = filter(images, imagePredicate);
+ if (size(supportedImages) == 0) {
+ throw throwNoSuchElementExceptionAfterLoggingImageIds(
+ format("no image matched predicate: %s", imagePredicate), images);
+ }
+ return supportedImages;
+ }
+
+ private Image findImageWithId(Set<? extends Image> images) {
+ Image image;
+ // TODO: switch to GetImageStrategy in version 1.5
+ image = tryFind(images, idPredicate).orNull();
+ if (image == null)
+ throwNoSuchElementExceptionAfterLoggingImageIds(format("%s not found", idPredicate), images);
+ return image;
+ }
+
+ private Hardware findHardwareWithId(Set<? extends Hardware> hardwaresToSearch) {
+ Hardware hardware;
+ // TODO: switch to GetHardwareStrategy in version 1.5
+ hardware = tryFind(hardwaresToSearch, hardwareIdPredicate).orNull();
+ if (hardware == null)
+ throw throwNoSuchElementExceptionAfterLoggingHardwareIds(format("%s not found", hardwareIdPredicate),
+ hardwaresToSearch);
+ return hardware;
+ }
+
+ protected NoSuchElementException throwNoSuchElementExceptionAfterLoggingImageIds(String message, Iterable<? extends Image> images) {
NoSuchElementException exception = new NoSuchElementException(message);
if (logger.isTraceEnabled())
logger.warn(exception, "image ids that didn't match: %s", transform(images, imageToId));
throw exception;
}
- protected Hardware resolveHardware(Ordering<Hardware> hardwareOrdering, final Iterable<? extends Image> images) {
- Set<? extends Hardware> hardwarel = hardwares.get();
+ protected NoSuchElementException throwNoSuchElementExceptionAfterLoggingHardwareIds(String message, Iterable<? extends Hardware> hardwares) {
+ NoSuchElementException exception = new NoSuchElementException(message);
+ if (logger.isTraceEnabled())
+ logger.warn(exception, "hardware ids that didn't match: %s", transform(hardwares, hardwareToId));
+ throw exception;
+ }
+
+ protected Hardware resolveHardware(Set<? extends Hardware> hardwarel, final Iterable<? extends Image> images) {
+ Ordering<Hardware> hardwareOrdering = hardwareSorter();
Iterable<? extends Hardware> hardwaresThatAreCompatibleWithOurImages = ImmutableSet.of();
try {
hardwaresThatAreCompatibleWithOurImages = filter(hardwarel, new Predicate<Hardware>() {
@@ -667,11 +718,7 @@
}
if (size(hardwaresThatAreCompatibleWithOurImages) == 0) {
String message = format("no hardware profiles support images matching params: %s", toString());
- NoSuchElementException exception = new NoSuchElementException(message);
- if (logger.isTraceEnabled())
- logger.warn(exception, "hardware profiles %s\nimage ids %s", transform(hardwarel, hardwareToId), transform(
- images, imageToId));
- throw exception;
+ throw throwNoSuchElementExceptionAfterLoggingHardwareIds(message, hardwaresThatAreCompatibleWithOurImages);
}
Predicate<Hardware> hardwarePredicate = buildHardwarePredicate();
Hardware hardware;
@@ -679,13 +726,9 @@
hardware = hardwareOrdering.max(filter(hardwaresThatAreCompatibleWithOurImages, hardwarePredicate));
} catch (NoSuchElementException exception) {
String message = format("no hardware profiles match params: %s", hardwarePredicate);
- exception = new NoSuchElementException(message);
- if (logger.isTraceEnabled())
- logger.warn(exception, "hardware profiles %s", transform(hardwaresThatAreCompatibleWithOurImages,
- hardwareToId));
- throw exception;
+ throw throwNoSuchElementExceptionAfterLoggingHardwareIds(message, hardwaresThatAreCompatibleWithOurImages);
}
- logger.debug("<< matched hardware(%s)", hardware.getId());
+ logger.trace("<< matched hardware(%s)", hardware.getId());
return hardware;
}
@@ -741,59 +784,55 @@
private Predicate<Image> buildImagePredicate() {
List<Predicate<Image>> predicates = newArrayList();
- if (imageId != null) {
- predicates.add(idPredicate);
- } else {
- if (location != null)
- predicates.add(new Predicate<Image>() {
+ if (location != null)
+ predicates.add(new Predicate<Image>() {
- @Override
- public boolean apply(Image input) {
- return locationPredicate.apply(input);
- }
+ @Override
+ public boolean apply(Image input) {
+ return locationPredicate.apply(input);
+ }
- @Override
- public String toString() {
- return locationPredicate.toString();
- }
- });
+ @Override
+ public String toString() {
+ return locationPredicate.toString();
+ }
+ });
- final List<Predicate<OperatingSystem>> osPredicates = newArrayList();
- if (osFamily != null)
- osPredicates.add(osFamilyPredicate);
- if (osName != null)
- osPredicates.add(osNamePredicate);
- if (osDescription != null)
- osPredicates.add(osDescriptionPredicate);
- if (osVersion != null)
- osPredicates.add(osVersionPredicate);
- if (os64Bit != null)
- osPredicates.add(os64BitPredicate);
- if (osArch != null)
- osPredicates.add(osArchPredicate);
- if (osPredicates.size() > 0)
- predicates.add(new Predicate<Image>() {
+ final List<Predicate<OperatingSystem>> osPredicates = newArrayList();
+ if (osFamily != null)
+ osPredicates.add(osFamilyPredicate);
+ if (osName != null)
+ osPredicates.add(osNamePredicate);
+ if (osDescription != null)
+ osPredicates.add(osDescriptionPredicate);
+ if (osVersion != null)
+ osPredicates.add(osVersionPredicate);
+ if (os64Bit != null)
+ osPredicates.add(os64BitPredicate);
+ if (osArch != null)
+ osPredicates.add(osArchPredicate);
+ if (osPredicates.size() > 0)
+ predicates.add(new Predicate<Image>() {
- @Override
- public boolean apply(Image input) {
- return and(osPredicates).apply(input.getOperatingSystem());
- }
+ @Override
+ public boolean apply(Image input) {
+ return and(osPredicates).apply(input.getOperatingSystem());
+ }
- @Override
- public String toString() {
- return and(osPredicates).toString();
- }
+ @Override
+ public String toString() {
+ return and(osPredicates).toString();
+ }
- });
- if (imageVersion != null)
- predicates.add(imageVersionPredicate);
- if (imageName != null)
- predicates.add(imageNamePredicate);
- if (imageDescription != null)
- predicates.add(imageDescriptionPredicate);
- if (imagePredicate != null)
- predicates.add(imagePredicate);
- }
+ });
+ if (imageVersion != null)
+ predicates.add(imageVersionPredicate);
+ if (imageName != null)
+ predicates.add(imageNamePredicate);
+ if (imageDescription != null)
+ predicates.add(imageDescriptionPredicate);
+ if (imagePredicate != null)
+ predicates.add(imagePredicate);
// looks verbose, but explicit <Image> type needed for this to compile
// properly
@@ -958,11 +997,40 @@
@Override
public String toString() {
- return "[biggest=" + biggest + ", fastest=" + fastest + ", imageName=" + imageName + ", imageDescription="
- + imageDescription + ", imageId=" + imageId + ", imagePredicate=" + imagePredicate + ", imageVersion=" + imageVersion + ", location=" + location
- + ", minCores=" + minCores + ", minRam=" + minRam + ", osFamily=" + osFamily + ", osName=" + osName
- + ", osDescription=" + osDescription + ", osVersion=" + osVersion + ", osArch=" + osArch + ", os64Bit="
- + os64Bit + ", hardwareId=" + hardwareId + ", hypervisor=" + hypervisor + "]";
+ return string().toString();
+ }
+
+ /**
+ * @since 1.5
+ */
+ protected ToStringHelper string() {
+ ToStringHelper toString = Objects.toStringHelper("").omitNullValues();
+ if (biggest)
+ toString.add("biggest", biggest);
+ if (fastest)
+ toString.add("fastest", fastest);
+ toString.add("imageName", imageName);
+ toString.add("imageDescription", imageDescription);
+ toString.add("imageId", imageId);
+ toString.add("imagePredicate", imagePredicate);
+ toString.add("imageVersion", imageVersion);
+ if (location != null)
+ toString.add("locationId", location.getId());
+ if (minCores >0) //TODO: make non-primitive
+ toString.add("minCores", minCores);
+ if (minRam >0) //TODO: make non-primitive
+ toString.add("minRam", minRam);
+ if (minRam >0) //TODO: make non-primitive
+ toString.add("minRam", minRam);
+ toString.add("osFamily", osFamily);
+ toString.add("osName", osName);
+ toString.add("osDescription", osDescription);
+ toString.add("osVersion", osVersion);
+ toString.add("osArch", osArch);
+ toString.add("os64Bit", os64Bit);
+ toString.add("hardwareId", hardwareId);
+ toString.add("hypervisor", hypervisor);
+ return toString;
}
@Override
diff --git a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateImpl.java b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateImpl.java
index ee5c096..bc0eb83 100644
--- a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateImpl.java
+++ b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateImpl.java
@@ -129,8 +129,8 @@
* {@inheritDoc}
*/
@Override
- protected Object clone() throws CloneNotSupportedException {
- return new TemplateImpl(image, size, location, options);
+ public Template clone() {
+ return new TemplateImpl(image, size, location, options.clone());
}
}
diff --git a/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java b/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java
index 04e676a..92b07ac 100644
--- a/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java
+++ b/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java
@@ -338,9 +338,9 @@
*/
@Override
public Set<ComputeMetadata> listNodes() {
- logger.debug(">> listing nodes");
+ logger.trace(">> listing nodes");
Set<ComputeMetadata> set = newLinkedHashSet(listNodesStrategy.listNodes());
- logger.debug("<< list(%d)", set.size());
+ logger.trace("<< list(%d)", set.size());
return set;
}
@@ -350,9 +350,9 @@
@Override
public Set<? extends NodeMetadata> listNodesDetailsMatching(Predicate<ComputeMetadata> filter) {
checkNotNull(filter, "filter");
- logger.debug(">> listing node details matching(%s)", filter);
+ logger.trace(">> listing node details matching(%s)", filter);
Set<NodeMetadata> set = newLinkedHashSet(listNodesStrategy.listDetailsOnNodesMatching(filter));
- logger.debug("<< list(%d)", set.size());
+ logger.trace("<< list(%d)", set.size());
return set;
}
diff --git a/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java b/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java
index 534b8b7..a0ad298 100644
--- a/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java
+++ b/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java
@@ -455,11 +455,23 @@
}
protected ToStringHelper string() {
- return Objects.toStringHelper("").add("loginUser", loginUser)
- .add("loginPasswordPresent", (loginPassword != null))
- .add("loginPrivateKeyPresent", (loginPrivateKey != null)).add("authenticateSudo", authenticateSudo)
- .add("port:seconds", port + ":" + seconds).add("taskName", taskName).add("runAsRoot", runAsRoot)
- .add("blockOnComplete", blockOnComplete).add("wrapInInitScript", wrapInInitScript);
+ ToStringHelper toString = Objects.toStringHelper("").omitNullValues();
+ toString.add("loginUser", loginUser);
+ if (loginPassword != null)
+ toString.add("loginPasswordPresent", true);
+ if (loginPrivateKey != null)
+ toString.add("loginPrivateKeyPresent", true);
+ toString.add("authenticateSudo", authenticateSudo);
+ if (port != -1 && seconds != -1) // TODO: not primitives
+ toString.add("blockOnPort:seconds", port + ":" + seconds);
+ toString.add("taskName", taskName);
+ if (!runAsRoot)
+ toString.add("runAsRoot", runAsRoot);
+ if (!blockOnComplete)
+ toString.add("blockOnComplete", blockOnComplete);
+ if (!wrapInInitScript)
+ toString.add("wrapInInitScript", wrapInInitScript);
+ return toString;
}
}
diff --git a/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java b/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java
index e9066f8..ce41ef3 100644
--- a/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java
+++ b/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java
@@ -317,7 +317,9 @@
}
- protected Set<Integer> inboundPorts = ImmutableSet.of(22);
+ private final static Set<Integer> DEFAULT_INBOUND_PORTS = ImmutableSet.of(22);
+
+ protected Set<Integer> inboundPorts = DEFAULT_INBOUND_PORTS;
protected Statement script;
@@ -352,11 +354,24 @@
@Override
public ToStringHelper string() {
- return super.string().add("inboundPorts", inboundPorts).add("scriptPresent", script != null)
- .add("publicKeyPresent", publicKey != null).add("privateKeyPresent", privateKey != null).add("tags", tags)
- .add("blockUntilRunning", blockUntilRunning).add("tags", tags).add("userMetadata", userMetadata);
+ ToStringHelper toString = super.string();
+ if (!DEFAULT_INBOUND_PORTS.equals(inboundPorts))
+ toString.add("inboundPorts", inboundPorts);
+ if (script != null)
+ toString.add("scriptPresent", true);
+ if (publicKey != null)
+ toString.add("publicKeyPresent", true);
+ if (privateKey != null)
+ toString.add("privateKeyPresent", true);
+ if (!blockUntilRunning)
+ toString.add("blockUntilRunning", blockUntilRunning);
+ if (tags.size() != 0)
+ toString.add("tags", tags);
+ if (userMetadata.size() != 0)
+ toString.add("userMetadata", userMetadata);
+ return toString;
}
-
+
public int[] getInboundPorts() {
return Ints.toArray(inboundPorts);
}
diff --git a/compute/src/main/java/org/jclouds/compute/RunScriptData.java b/compute/src/test/java/org/jclouds/compute/RunScriptData.java
similarity index 98%
rename from compute/src/main/java/org/jclouds/compute/RunScriptData.java
rename to compute/src/test/java/org/jclouds/compute/RunScriptData.java
index c2ecded..3087d11 100644
--- a/compute/src/main/java/org/jclouds/compute/RunScriptData.java
+++ b/compute/src/test/java/org/jclouds/compute/RunScriptData.java
@@ -75,7 +75,7 @@
return InitScript.builder()
.name("jboss")
.home(JBOSS_HOME)
- .exportVariables(ImmutableMap.of("jbossHome", JBOSS_HOME))
+ .exportVariables(ImmutableMap.of("JBOSS_HOME", JBOSS_HOME))
.init(appendFile(JBOSS_HOME + "/standalone/configuration/standalone-custom.xml", Splitter.on('\n').split(configuration)))
.run(interpret(new StringBuilder().append("java ").append(' ')
.append("-server -Xms128m -Xmx128m -XX:MaxPermSize=128m -Djava.net.preferIPv4Stack=true -XX:+UseFastAccessorMethods -XX:+TieredCompilation -Xverify:none -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000").append(' ')
diff --git a/compute/src/test/java/org/jclouds/compute/domain/internal/TemplateBuilderImplTest.java b/compute/src/test/java/org/jclouds/compute/domain/internal/TemplateBuilderImplTest.java
index 9a80ef4..1f4bb92 100644
--- a/compute/src/test/java/org/jclouds/compute/domain/internal/TemplateBuilderImplTest.java
+++ b/compute/src/test/java/org/jclouds/compute/domain/internal/TemplateBuilderImplTest.java
@@ -63,6 +63,9 @@
protected Location region = new LocationBuilder().scope(LocationScope.REGION).id("us-east-1").description("us-east-1")
.parent(provider).build();
+ protected Location region2 = new LocationBuilder().scope(LocationScope.REGION).id("us-east-2").description("us-east-2")
+ .parent(provider).build();
+
@SuppressWarnings("unchecked")
public void testLocationPredicateWhenComputeMetadataIsNotLocationBound() {
Image image = createMock(Image.class);
@@ -371,7 +374,7 @@
// make sure big data is not in the exception message
assertEquals(
e.getMessage(),
- "no hardware profiles support images matching params: [biggest=false, fastest=false, imageName=null, imageDescription=null, imageId=us-east-1/imageId, imagePredicate=null, imageVersion=null, location=[id=us-east-1, scope=REGION, description=us-east-1, parent=aws-ec2, iso3166Codes=[], metadata={}], minCores=0.0, minRam=0, osFamily=null, osName=null, osDescription=null, osVersion=null, osArch=null, os64Bit=false, hardwareId=null, hypervisor=null]");
+ "no hardware profiles support images matching params: {imageId=us-east-1/imageId, locationId=us-east-1, os64Bit=false}");
verify(image);
verify(os);
verify(defaultTemplate);
@@ -849,9 +852,63 @@
TemplateBuilder templateBuilder = templateBuilderProvider.get().minRam(512).osFamily(OsFamily.UBUNTU)
.hypervisorMatches("OpenVZ").osVersionMatches("1[10].[10][04]").os64Bit(true);
+ assertEquals(templateBuilder.toString(), "{minRam=512, minRam=512, osFamily=ubuntu, osVersion=1[10].[10][04], os64Bit=true, hypervisor=OpenVZ}");
+
Template template = templateBuilder.build();
assertEquals(template.getHardware().getHypervisor(), "OpenVZ");
assertEquals(template.getImage().getId(), "Ubuntu 11.04 64-bit");
}
+
+
+ @Test
+ public void testImageLocationNonDefault() {
+
+ final Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
+ .<Location> of(region));
+ final Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet
+ .<Image> of(
+ new ImageBuilder()
+ .id("us-east-2/ami-ffff")
+ .providerId("ami-ffff")
+ .name("Ubuntu 11.04 x64")
+ .description("Ubuntu 11.04 x64")
+ .location(region2)
+ .status(Status.AVAILABLE)
+ .operatingSystem(
+ OperatingSystem.builder().name("Ubuntu 11.04 x64").description("Ubuntu 11.04 x64")
+ .is64Bit(true).version("11.04").family(OsFamily.UBUNTU).build()).build()));
+
+ final Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
+ .<Hardware> of(
+ new HardwareBuilder()
+ .ids("m1.small").ram(512)
+ .processors(ImmutableList.of(new Processor(1, 1.0)))
+ .volumes(ImmutableList.<Volume> of(new VolumeImpl((float) 5, true, true))).build()));
+
+ final Provider<TemplateOptions> optionsProvider = new Provider<TemplateOptions>() {
+
+ @Override
+ public TemplateOptions get() {
+ return new TemplateOptions();
+ }
+
+ };
+ Provider<TemplateBuilder> templateBuilderProvider = new Provider<TemplateBuilder>() {
+
+ @Override
+ public TemplateBuilder get() {
+ return createTemplateBuilder(null, locations, images, hardwares, region, optionsProvider, this);
+ }
+
+ };
+
+ TemplateBuilder templateBuilder = templateBuilderProvider.get().hardwareId("m1.small").imageId("us-east-2/ami-ffff");
+
+ assertEquals(templateBuilder.toString(), "{imageId=us-east-2/ami-ffff, hardwareId=m1.small}");
+
+ Template template = templateBuilder.build();
+ assertEquals(template.getLocation().getId(), "us-east-2");
+
+ }
}
diff --git a/compute/src/test/java/org/jclouds/compute/internal/BaseGenericComputeServiceContextLiveTest.java b/compute/src/test/java/org/jclouds/compute/internal/BaseGenericComputeServiceContextLiveTest.java
index c26b11f..bc7a2eb 100644
--- a/compute/src/test/java/org/jclouds/compute/internal/BaseGenericComputeServiceContextLiveTest.java
+++ b/compute/src/test/java/org/jclouds/compute/internal/BaseGenericComputeServiceContextLiveTest.java
@@ -24,6 +24,7 @@
import org.jclouds.apis.BaseViewLiveTest;
import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.domain.TemplateBuilderSpec;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.domain.LoginCredentials.Builder;
import org.jclouds.io.CopyInputStreamInputSupplierMap;
@@ -41,9 +42,7 @@
*/
public abstract class BaseGenericComputeServiceContextLiveTest<W extends ComputeServiceContext> extends BaseViewLiveTest<W> {
- protected String imageId;
- protected String loginUser;
- protected String authenticateSudo;
+ protected TemplateBuilderSpec template;
protected LoginCredentials loginCredentials = LoginCredentials.builder().user("root").build();
// isolate tests from eachother, as default credentialStore is static
@@ -53,19 +52,19 @@
@Override
protected Properties setupProperties() {
Properties overrides = super.setupProperties();
- imageId = setIfTestSystemPropertyPresent(overrides, provider + ".image-id");
- loginUser = setIfTestSystemPropertyPresent(overrides, provider + ".image.login-user");
- authenticateSudo = setIfTestSystemPropertyPresent(overrides, provider + ".image.authenticate-sudo");
-
- if (loginUser != null) {
- Iterable<String> userPass = Splitter.on(':').split(loginUser);
- Builder loginCredentialsBuilder = LoginCredentials.builder();
- loginCredentialsBuilder.user(Iterables.get(userPass, 0));
- if (Iterables.size(userPass) == 2)
- loginCredentialsBuilder.password(Iterables.get(userPass, 1));
- if (authenticateSudo != null)
- loginCredentialsBuilder.authenticateSudo(Boolean.valueOf(authenticateSudo));
- loginCredentials = loginCredentialsBuilder.build();
+ String spec = setIfTestSystemPropertyPresent(overrides, provider + ".template");
+ if (spec != null) {
+ template = TemplateBuilderSpec.parse(spec);
+ if (template.getLoginUser() != null) {
+ Iterable<String> userPass = Splitter.on(':').split(template.getLoginUser());
+ Builder loginCredentialsBuilder = LoginCredentials.builder();
+ loginCredentialsBuilder.user(Iterables.get(userPass, 0));
+ if (Iterables.size(userPass) == 2)
+ loginCredentialsBuilder.password(Iterables.get(userPass, 1));
+ if (template.getAuthenticateSudo() != null)
+ loginCredentialsBuilder.authenticateSudo(template.getAuthenticateSudo());
+ loginCredentials = loginCredentialsBuilder.build();
+ }
}
return overrides;
}
diff --git a/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java b/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java
index d79e9e5..cb9505e 100644
--- a/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java
+++ b/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java
@@ -261,9 +261,9 @@
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
- String login = loginUser != null ? loginUser : "foo:bar";
+ String login = template != null && template.getLoginUser() != null ? template.getLoginUser() : "foo:bar";
overrides.setProperty(propertyKey + ".image.login-user", login);
- boolean auth = authenticateSudo != null ? Boolean.valueOf(authenticateSudo) : true;
+ boolean auth = template != null && template.getAuthenticateSudo() != null ? template.getAuthenticateSudo() : true;
overrides.setProperty(propertyKey + ".image.authenticate-sudo", auth + "");
context = createView(overrides, ImmutableSet.<Module>of(credentialStoreModule));
diff --git a/compute/src/test/java/org/jclouds/compute/options/TemplateOptionsTest.java b/compute/src/test/java/org/jclouds/compute/options/TemplateOptionsTest.java
index 1081d82..486ad27 100644
--- a/compute/src/test/java/org/jclouds/compute/options/TemplateOptionsTest.java
+++ b/compute/src/test/java/org/jclouds/compute/options/TemplateOptionsTest.java
@@ -45,6 +45,7 @@
public void testinstallPrivateKey() throws IOException {
TemplateOptions options = new TemplateOptions();
options.installPrivateKey("-----BEGIN RSA PRIVATE KEY-----");
+ assertEquals(options.toString(), "{privateKeyPresent=true}");
assertEquals(options.getPrivateKey(), "-----BEGIN RSA PRIVATE KEY-----");
}
@@ -75,6 +76,7 @@
public void testauthorizePublicKey() throws IOException {
TemplateOptions options = new TemplateOptions();
options.authorizePublicKey("ssh-rsa");
+ assertEquals(options.toString(), "{publicKeyPresent=true}");
assertEquals(options.getPublicKey(), "ssh-rsa");
}
@@ -105,6 +107,7 @@
public void testblockOnPort() {
TemplateOptions options = new TemplateOptions();
options.blockOnPort(22, 30);
+ assertEquals(options.toString(), "{blockOnPort:seconds=22:30}");
assertEquals(options.getPort(), 22);
assertEquals(options.getSeconds(), 30);
@@ -148,6 +151,7 @@
@Test
public void testinboundPortsStatic() {
TemplateOptions options = inboundPorts(22, 30);
+ assertEquals(options.toString(), "{inboundPorts=[22, 30]}");
assertEquals(options.getInboundPorts()[0], 22);
assertEquals(options.getInboundPorts()[1], 30);
}
@@ -155,6 +159,7 @@
@Test
public void testblockUntilRunningDefault() {
TemplateOptions options = new TemplateOptions();
+ assertEquals(options.toString(), "{}");
assertEquals(options.shouldBlockUntilRunning(), true);
}
@@ -162,6 +167,7 @@
public void testblockUntilRunning() {
TemplateOptions options = new TemplateOptions();
options.blockUntilRunning(false);
+ assertEquals(options.toString(), "{blockUntilRunning=false}");
assertEquals(options.shouldBlockUntilRunning(), false);
}
diff --git a/core/src/main/java/org/jclouds/JcloudsVersion.java b/core/src/main/java/org/jclouds/JcloudsVersion.java
index be7e72b..eaef9fd 100644
--- a/core/src/main/java/org/jclouds/JcloudsVersion.java
+++ b/core/src/main/java/org/jclouds/JcloudsVersion.java
@@ -33,6 +33,7 @@
/**
* @author Andrew Phillips
+ * @author Adrian Cole
*/
public class JcloudsVersion {
@VisibleForTesting
@@ -105,10 +106,10 @@
String alphaOrBetaOrReleaseCandidateVersionIfPresent = versionMatcher.group(4);
if (alphaOrBetaOrReleaseCandidateVersionIfPresent != null) {
- Integer alphaOrReleaseCandidateVersion = Integer.valueOf(versionMatcher.group(5));
+ Integer alphaOrBetaOrReleaseCandidateVersion = Integer.valueOf(versionMatcher.group(5));
if (alphaOrBetaOrReleaseCandidateVersionIfPresent.equals(ALPHA_VERSION_IDENTIFIER)) {
alpha = true;
- alphaVersion = alphaOrReleaseCandidateVersion;
+ alphaVersion = alphaOrBetaOrReleaseCandidateVersion;
beta = false;
betaVersion = null;
releaseCandidate = false;
@@ -117,7 +118,7 @@
alpha = false;
alphaVersion = null;
beta = true;
- betaVersion = alphaOrReleaseCandidateVersion;
+ betaVersion = alphaOrBetaOrReleaseCandidateVersion;
releaseCandidate = false;
releaseCandidateVersion = null;
} else {
@@ -126,7 +127,7 @@
beta = false;
betaVersion = null;
releaseCandidate = true;
- releaseCandidateVersion = alphaOrReleaseCandidateVersion;
+ releaseCandidateVersion = alphaOrBetaOrReleaseCandidateVersion;
}
} else {
alpha = false;
diff --git a/core/src/main/java/org/jclouds/apis/ApiRegistry.java b/core/src/main/java/org/jclouds/apis/ApiRegistry.java
new file mode 100644
index 0000000..78071db
--- /dev/null
+++ b/core/src/main/java/org/jclouds/apis/ApiRegistry.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.apis;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A registry for holding {@link org.jclouds.apis.ApiMetadata}.
+ */
+public class ApiRegistry {
+
+ private static final Set<ApiMetadata> apis = new HashSet<ApiMetadata>();
+
+ public static void registerApi(ApiMetadata api) {
+ apis.add(api);
+ }
+
+ public static void unRegisterApi(ApiMetadata api) {
+ apis.remove(api);
+ }
+
+ public static Iterable<ApiMetadata> fromRegistry() {
+ return Iterable.class.cast(apis);
+ }
+
+ public static void clear() {
+ apis.clear();
+ }
+}
diff --git a/core/src/main/java/org/jclouds/apis/Apis.java b/core/src/main/java/org/jclouds/apis/Apis.java
index fbb4c14..484a6c5 100644
--- a/core/src/main/java/org/jclouds/apis/Apis.java
+++ b/core/src/main/java/org/jclouds/apis/Apis.java
@@ -69,7 +69,7 @@
* @return all available apis
*/
public static Iterable<ApiMetadata> all() {
- return fromServiceLoader();
+ return Iterables.concat(fromServiceLoader(), ApiRegistry.fromRegistry());
}
/**
diff --git a/core/src/main/java/org/jclouds/crypto/SshKeys.java b/core/src/main/java/org/jclouds/crypto/SshKeys.java
index e085d7a..1813851 100644
--- a/core/src/main/java/org/jclouds/crypto/SshKeys.java
+++ b/core/src/main/java/org/jclouds/crypto/SshKeys.java
@@ -124,13 +124,14 @@
/**
*
- * @param used
+ * @param generator
* to generate RSA key pairs
+ * @param rand
+ * for initializing {@code generator}
* @return new 2048 bit keyPair
* @see Crypto#rsaKeyPairGenerator()
*/
- public static KeyPair generateRsaKeyPair(KeyPairGenerator generator) {
- SecureRandom rand = new SecureRandom();
+ public static KeyPair generateRsaKeyPair(KeyPairGenerator generator, SecureRandom rand) {
generator.initialize(2048, rand);
return generator.genKeyPair();
}
@@ -140,15 +141,15 @@
*/
public static Map<String, String> generate() {
try {
- return generate(KeyPairGenerator.getInstance("RSA"));
+ return generate(KeyPairGenerator.getInstance("RSA"), new SecureRandom());
} catch (NoSuchAlgorithmException e) {
propagate(e);
return null;
}
}
- public static Map<String, String> generate(KeyPairGenerator generator) {
- KeyPair pair = generateRsaKeyPair(generator);
+ public static Map<String, String> generate(KeyPairGenerator generator, SecureRandom rand) {
+ KeyPair pair = generateRsaKeyPair(generator, rand);
Builder<String, String> builder = ImmutableMap.builder();
builder.put("public", encodeAsOpenSSH(RSAPublicKey.class.cast(pair.getPublic())));
builder.put("private", encodeAsPem(RSAPrivateKey.class.cast(pair.getPrivate())));
diff --git a/core/src/main/java/org/jclouds/events/handlers/DeadEventLoggingHandler.java b/core/src/main/java/org/jclouds/events/handlers/DeadEventLoggingHandler.java
index 20f709c..c4fbafa 100644
--- a/core/src/main/java/org/jclouds/events/handlers/DeadEventLoggingHandler.java
+++ b/core/src/main/java/org/jclouds/events/handlers/DeadEventLoggingHandler.java
@@ -47,6 +47,6 @@
*/
@Subscribe
public final void handleDeadEvent(DeadEvent deadEvent) {
- logger.warn("detected dead event %s", deadEvent.getEvent());
+ logger.trace("detected dead event %s", deadEvent.getEvent());
}
}
diff --git a/core/src/main/java/org/jclouds/io/payloads/BasePayload.java b/core/src/main/java/org/jclouds/io/payloads/BasePayload.java
index 020a0da..53f523c 100644
--- a/core/src/main/java/org/jclouds/io/payloads/BasePayload.java
+++ b/core/src/main/java/org/jclouds/io/payloads/BasePayload.java
@@ -60,7 +60,7 @@
*/
@Override
public void writeTo(OutputStream outstream) throws IOException {
- checkState(!written || isRepeatable(), "can only be writted to an outputstream once");
+ checkState(!written || isRepeatable(), "can only write to an outputStream once");
written = true;
InputStream in = getInput();
try {
diff --git a/core/src/main/java/org/jclouds/location/functions/RegionToEndpointOrProviderIfNull.java b/core/src/main/java/org/jclouds/location/functions/RegionToEndpointOrProviderIfNull.java
index 52942bb..1548240 100644
--- a/core/src/main/java/org/jclouds/location/functions/RegionToEndpointOrProviderIfNull.java
+++ b/core/src/main/java/org/jclouds/location/functions/RegionToEndpointOrProviderIfNull.java
@@ -56,10 +56,15 @@
@Override
public URI apply(@Nullable Object from) {
- if (from == null || from.equals(defaultProvider))
+ if (from == null)
return defaultUri.get();
checkArgument(from instanceof String, "region is a String argument");
Map<String, Supplier<URI>> regionToEndpoint = regionToEndpointSupplier.get();
+ if (from.equals(defaultProvider)){
+ if (regionToEndpoint.containsKey(from))
+ return regionToEndpoint.get(from).get();
+ return defaultUri.get();
+ }
checkArgument(regionToEndpoint.containsKey(from),
"requested location %s, which is not in the configured locations: %s", from, regionToEndpoint);
return regionToEndpoint.get(from).get();
diff --git a/core/src/main/java/org/jclouds/location/suppliers/derived/ZoneIdToURIFromJoinOnRegionIdToURI.java b/core/src/main/java/org/jclouds/location/suppliers/derived/ZoneIdToURIFromJoinOnRegionIdToURI.java
new file mode 100644
index 0000000..7bbde01
--- /dev/null
+++ b/core/src/main/java/org/jclouds/location/suppliers/derived/ZoneIdToURIFromJoinOnRegionIdToURI.java
@@ -0,0 +1,64 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.location.suppliers.derived;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.location.Region;
+import org.jclouds.location.Zone;
+import org.jclouds.location.suppliers.ZoneIdToURISupplier;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+
+/**
+ *
+ */
+@Singleton
+public class ZoneIdToURIFromJoinOnRegionIdToURI implements ZoneIdToURISupplier {
+
+ private final Supplier<Map<String, Supplier<URI>>> regionIdToURISupplier;
+ private final Supplier<Map<String, Supplier<Set<String>>>> regionIdToZoneIdsSupplier;
+
+ @Inject
+ protected ZoneIdToURIFromJoinOnRegionIdToURI(@Region Supplier<Map<String, Supplier<URI>>> regionIdToURISupplier,
+ @Zone Supplier<Map<String, Supplier<Set<String>>>> regionIdToZoneIdsSupplier) {
+ this.regionIdToURISupplier = regionIdToURISupplier;
+ this.regionIdToZoneIdsSupplier = regionIdToZoneIdsSupplier;
+ }
+
+ @Override
+ public Map<String, Supplier<URI>> get() {
+ Builder<String, Supplier<URI>> builder = ImmutableMap.<String, Supplier<URI>> builder();
+ for (Entry<String, Supplier<URI>> regionToURI : regionIdToURISupplier.get().entrySet()) {
+ for (String zone : regionIdToZoneIdsSupplier.get().get(regionToURI.getKey()).get()) {
+ builder.put(zone, regionToURI.getValue());
+ }
+ }
+ return builder.build();
+ }
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/jclouds/osgi/Activator.java b/core/src/main/java/org/jclouds/osgi/Activator.java
index 64de199..e6ee8f1 100644
--- a/core/src/main/java/org/jclouds/osgi/Activator.java
+++ b/core/src/main/java/org/jclouds/osgi/Activator.java
@@ -18,13 +18,14 @@
*/
package org.jclouds.osgi;
+import org.jclouds.apis.ApiRegistry;
import org.jclouds.providers.ProviderRegistry;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
- ProviderBundleListener bundleListener = new ProviderBundleListener();
+ MetadataBundleListener bundleListener = new MetadataBundleListener();
/**
* Called when this bundle is started so the Framework can perform the
@@ -43,6 +44,7 @@
*/
@Override
public void start(BundleContext context) throws Exception {
+ bundleListener.start(context);
context.addBundleListener(bundleListener);
}
@@ -65,7 +67,9 @@
*/
@Override
public void stop(BundleContext context) throws Exception {
+ bundleListener.stop(context);
context.removeBundleListener(bundleListener);
ProviderRegistry.clear();
+ ApiRegistry.clear();
}
}
diff --git a/core/src/main/java/org/jclouds/osgi/MetadataBundleListener.java b/core/src/main/java/org/jclouds/osgi/MetadataBundleListener.java
new file mode 100644
index 0000000..75d9886
--- /dev/null
+++ b/core/src/main/java/org/jclouds/osgi/MetadataBundleListener.java
@@ -0,0 +1,208 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.osgi;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.apis.ApiRegistry;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.ProviderRegistry;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link BundleListener} that listens for {@link BundleEvent} and searches for {@link org.jclouds.providers.ProviderMetadata} and {@ling org.jclouds.apis.ApiMetadata} in newly
+ * installed Bundles. This is used as a workaround for OSGi environments where the ServiceLoader cannot cross bundle
+ * boundaries.
+ */
+public class MetadataBundleListener implements BundleListener {
+
+ private Map<Long, ProviderMetadata> providerMetadataMap = new HashMap<Long, ProviderMetadata>();
+ private Map<Long, ApiMetadata> apiMetadataMap = new HashMap<Long, ApiMetadata>();
+
+
+ public void start(BundleContext bundleContext) {
+ bundleContext.addBundleListener(this);
+ for (Bundle bundle : bundleContext.getBundles()) {
+ if (bundle.getState() == Bundle.ACTIVE) {
+ ProviderMetadata providerMetadata = getProviderMetadata(bundle);
+ ApiMetadata apiMetadata = getApiMetadata(bundle);
+
+ if (providerMetadata != null) {
+ ProviderRegistry.registerProvider(providerMetadata);
+ providerMetadataMap.put(bundle.getBundleId(), providerMetadata);
+ }
+ if (apiMetadata != null) {
+ ApiRegistry.registerApi(apiMetadata);
+ apiMetadataMap.put(bundle.getBundleId(), apiMetadata);
+ }
+ }
+ }
+ }
+
+ public void stop(BundleContext bundleContext) {
+ providerMetadataMap.clear();
+ apiMetadataMap.clear();
+ }
+
+ @Override
+ public void bundleChanged(BundleEvent event) {
+ ProviderMetadata providerMetadata;
+ ApiMetadata apiMetadata;
+ switch (event.getType()) {
+ case BundleEvent.STARTED:
+ providerMetadata = getProviderMetadata(event.getBundle());
+ apiMetadata = getApiMetadata(event.getBundle());
+ if (providerMetadata != null) {
+ ProviderRegistry.registerProvider(providerMetadata);
+ providerMetadataMap.put(event.getBundle().getBundleId(), providerMetadata);
+ }
+ if (apiMetadata != null) {
+ ApiRegistry.registerApi(apiMetadata);
+ apiMetadataMap.put(event.getBundle().getBundleId(), apiMetadata);
+ }
+ break;
+ case BundleEvent.STOPPING:
+ case BundleEvent.STOPPED:
+ providerMetadata = providerMetadataMap.get(event.getBundle().getBundleId());
+ apiMetadata = apiMetadataMap.get(event.getBundle().getBundleId());
+ if (providerMetadata != null) {
+ ProviderRegistry.uRegisterProvider(providerMetadata);
+ }
+ if (apiMetadata != null) {
+ ApiRegistry.unRegisterApi(apiMetadata);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Creates an instance of {@link ProviderMetadata} from the {@link Bundle}.
+ *
+ * @param bundle
+ * @return
+ */
+ public ProviderMetadata getProviderMetadata(Bundle bundle) {
+ ProviderMetadata metadata = null;
+ String className = getProviderMetadataClassName(bundle);
+ if (className != null && !className.isEmpty()) {
+ try {
+ Class<? extends ProviderMetadata> providerMetadataClass = bundle.loadClass(className);
+ metadata = providerMetadataClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ // ignore
+ } catch (InstantiationException e) {
+ // ignore
+ } catch (IllegalAccessException e) {
+ // ignore
+ }
+ }
+ return metadata;
+ }
+
+ /**
+ * Creates an instance of {@link ApiMetadata} from the {@link Bundle}.
+ *
+ * @param bundle
+ * @return
+ */
+ public ApiMetadata getApiMetadata(Bundle bundle) {
+ ApiMetadata metadata = null;
+ String className = getApiMetadataClassName(bundle);
+ if (className != null && !className.isEmpty()) {
+ try {
+ Class<? extends ApiMetadata> apiMetadataClass = bundle.loadClass(className);
+ metadata = apiMetadataClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ // ignore
+ } catch (InstantiationException e) {
+ // ignore
+ } catch (IllegalAccessException e) {
+ // ignore
+ }
+ }
+ return metadata;
+ }
+
+
+ public String getMetadataClassName(Bundle bundle, String pathToMetadata) {
+ URL resource = bundle.getEntry(pathToMetadata);
+ InputStream is = null;
+ InputStreamReader reader = null;
+ BufferedReader bufferedReader = null;
+ StringBuilder sb = new StringBuilder();
+
+ try {
+ is = resource.openStream();
+ reader = new InputStreamReader(is, "UTF-8");
+ bufferedReader = new BufferedReader(reader);
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ sb.append(line).append("\n");
+ }
+ } catch (Throwable e) {
+ } finally {
+ try {
+ if (reader != null)
+ reader.close();
+ } catch (Throwable e) {
+ }
+ try {
+ if (bufferedReader != null)
+ bufferedReader.close();
+ } catch (Throwable e) {
+ }
+ try {
+ is.close();
+ } catch (Throwable e) {
+ }
+
+ }
+ return sb.toString().trim();
+ }
+
+ /**
+ * Retrieves the {@link ProviderMetadata} class name for the bundle if it exists.
+ *
+ * @param bundle
+ * @return
+ */
+ public String getProviderMetadataClassName(Bundle bundle) {
+ return getMetadataClassName(bundle, "/META-INF/services/org.jclouds.providers.ProviderMetadata");
+ }
+
+ /**
+ * Retrieves the {@link ProviderMetadata} class name for the bundle if it exists.
+ *
+ * @param bundle
+ * @return
+ */
+ public String getApiMetadataClassName(Bundle bundle) {
+ return getMetadataClassName(bundle, "/META-INF/services/org.jclouds.apis.ApiMetadata");
+ }
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/jclouds/osgi/ProviderBundleListener.java b/core/src/main/java/org/jclouds/osgi/ProviderBundleListener.java
deleted file mode 100644
index 01d3a26..0000000
--- a/core/src/main/java/org/jclouds/osgi/ProviderBundleListener.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. jclouds 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.osgi;
-
-import org.jclouds.providers.ProviderMetadata;
-import org.jclouds.providers.ProviderRegistry;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
-
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A {@link BundleListener} that listens for {@link BundleEvent} and searches for {@link org.jclouds.providers.ProviderMetadata} in newly
- * installed Bundles. This is used as a workaround for OSGi environments where the ServiceLoader cannot cross bundle
- * boundaries.
- */
-public class ProviderBundleListener implements BundleListener {
-
- private Map<Long, ProviderMetadata> bundleMetadataMap = new HashMap<Long, ProviderMetadata>();
-
- @Override
- public void bundleChanged(BundleEvent event) {
- ProviderMetadata metadata;
- switch (event.getType()) {
- case BundleEvent.STARTED:
- metadata = getProviderMetadata(event.getBundle());
- if (metadata != null) {
- ProviderRegistry.registerProvider(metadata);
- bundleMetadataMap.put(event.getBundle().getBundleId(), metadata);
- }
- break;
- case BundleEvent.STOPPING:
- case BundleEvent.STOPPED:
- metadata = bundleMetadataMap.get(event.getBundle().getBundleId());
- if (metadata != null) {
- ProviderRegistry.uRegisterProvider(metadata);
- }
- break;
- }
- }
-
- /**
- * Creates an instance of {@link ProviderMetadata} from the {@link Bundle}.
- *
- * @param bundle
- * @return
- */
- public ProviderMetadata getProviderMetadata(Bundle bundle) {
- ProviderMetadata metadata = null;
- String className = getProviderMetadataClassName(bundle);
- if (className != null && !className.isEmpty()) {
- try {
- Class<? extends ProviderMetadata> provideClass = bundle.loadClass(className);
- metadata = provideClass.newInstance();
- } catch (ClassNotFoundException e) {
- // ignore
- } catch (InstantiationException e) {
- // ignore
- } catch (IllegalAccessException e) {
- // ignore
- }
- }
- return metadata;
- }
-
- /**
- * Retrieves the {@link ProviderMetadata} class name for the bundle if it exists.
- *
- * @param bundle
- * @return
- */
- public String getProviderMetadataClassName(Bundle bundle) {
- URL resource = bundle.getEntry("/META-INF/services/org.jclouds.providers.ProviderMetadata");
- InputStream is = null;
- InputStreamReader reader = null;
- BufferedReader bufferedReader = null;
- StringBuilder sb = new StringBuilder();
-
- try {
- is = resource.openStream();
- reader = new InputStreamReader(is, "UTF-8");
- bufferedReader = new BufferedReader(reader);
- String line;
- while ((line = bufferedReader.readLine()) != null) {
- sb.append(line).append("\n");
- }
- } catch (Throwable e) {
- } finally {
- try {
- if (reader != null)
- reader.close();
- } catch (Throwable e) {
- }
- try {
- if (bufferedReader != null)
- bufferedReader.close();
- } catch (Throwable e) {
- }
- try {
- is.close();
- } catch (Throwable e) {
- }
-
- }
- return sb.toString().trim();
- }
-}
\ No newline at end of file
diff --git a/core/src/test/java/org/jclouds/apis/ApisTest.java b/core/src/test/java/org/jclouds/apis/ApisTest.java
index 97a75c6..e16ca5a 100644
--- a/core/src/test/java/org/jclouds/apis/ApisTest.java
+++ b/core/src/test/java/org/jclouds/apis/ApisTest.java
@@ -43,7 +43,7 @@
ApiMetadata apiMetadata;
try {
apiMetadata = Apis.withId("fake-id");
- fail("Looking for a api with an id that doesn't exist should " + "throw an exceptoin.");
+ fail("Looking for a api with an id that doesn't exist should " + "throw an exception.");
} catch (NoSuchElementException nsee) {
; // Expected
}
diff --git a/core/src/test/java/org/jclouds/location/functions/RegionToEndpointOrProviderIfNullTest.java b/core/src/test/java/org/jclouds/location/functions/RegionToEndpointOrProviderIfNullTest.java
index 003999b..48e6daa 100644
--- a/core/src/test/java/org/jclouds/location/functions/RegionToEndpointOrProviderIfNullTest.java
+++ b/core/src/test/java/org/jclouds/location/functions/RegionToEndpointOrProviderIfNullTest.java
@@ -39,6 +39,13 @@
public class RegionToEndpointOrProviderIfNullTest {
@Test
+ public void testWhenRegionNameIsSameAsProviderName() throws SecurityException, NoSuchMethodException {
+ RegionToEndpointOrProviderIfNull fn = new RegionToEndpointOrProviderIfNull("leader", Suppliers.ofInstance(URI
+ .create("http://leader")), Suppliers.<Map<String, Supplier<URI>>>ofInstance(ImmutableMap.of("leader", Suppliers.ofInstance(URI.create("http://leaderregion")))));
+ assertEquals(fn.apply("leader"), URI.create("http://leaderregion"));
+ }
+
+ @Test
public void testWhenFindsRegion() throws SecurityException, NoSuchMethodException {
RegionToEndpointOrProviderIfNull fn = new RegionToEndpointOrProviderIfNull("leader", Suppliers.ofInstance(URI
.create("http://leader")), Suppliers.<Map<String, Supplier<URI>>>ofInstance(ImmutableMap.of("1", Suppliers.ofInstance(URI.create("http://1")))));
diff --git a/core/src/test/java/org/jclouds/providers/ProvidersTest.java b/core/src/test/java/org/jclouds/providers/ProvidersTest.java
index 0432219..d723e3a 100644
--- a/core/src/test/java/org/jclouds/providers/ProvidersTest.java
+++ b/core/src/test/java/org/jclouds/providers/ProvidersTest.java
@@ -49,7 +49,7 @@
try {
providerMetadata = Providers.withId("fake-id");
- fail("Looking for a provider with an id that doesn't exist should " + "throw an exceptoin.");
+ fail("Looking for a provider with an id that doesn't exist should " + "throw an exception.");
} catch (NoSuchElementException nsee) {
; // Expected
}
diff --git a/drivers/gae/src/main/java/org/jclouds/gae/AsyncGaeHttpCommandExecutorService.java b/drivers/gae/src/main/java/org/jclouds/gae/AsyncGaeHttpCommandExecutorService.java
index 62c2318..966c94a 100644
--- a/drivers/gae/src/main/java/org/jclouds/gae/AsyncGaeHttpCommandExecutorService.java
+++ b/drivers/gae/src/main/java/org/jclouds/gae/AsyncGaeHttpCommandExecutorService.java
@@ -96,7 +96,7 @@
request = filter.filter(request);
}
checkRequestHasContentLengthOrChunkedEncoding(request,
- "After filtering, the request has niether chunked encoding nor content length: " + request);
+ "After filtering, the request has neither chunked encoding nor content length: " + request);
logger.debug("Sending request %s: %s", request.hashCode(), request.getRequestLine());
wirePayloadIfEnabled(wire, request);
HTTPRequest nativeRequest = convertToGaeRequest.apply(request);
diff --git a/labs/aws-elb/pom.xml b/labs/aws-elb/pom.xml
index f0feb83..faf1732 100644
--- a/labs/aws-elb/pom.xml
+++ b/labs/aws-elb/pom.xml
@@ -36,16 +36,16 @@
<properties>
<test.aws-elb.endpoint>https://elasticloadbalancing.us-east-1.amazonaws.com</test.aws-elb.endpoint>
<test.aws-elb.api-version>2010-07-01</test.aws-elb.api-version>
- <test.aws-elb.build-version />
+ <test.aws-elb.build-version></test.aws-elb.build-version>
<test.aws-elb.identity>${test.aws.identity}</test.aws-elb.identity>
<test.aws-elb.credential>${test.aws.credential}</test.aws-elb.credential>
<test.aws-elb.compute.provider>aws-ec2</test.aws-elb.compute.provider>
<test.aws-elb.compute.endpoint>https://ec2.us-east-1.amazonaws.com</test.aws-elb.compute.endpoint>
<test.aws-elb.compute.api-version>2010-06-15</test.aws-elb.compute.api-version>
- <test.aws-elb.compute.build-version />
+ <test.aws-elb.compute.build-version></test.aws-elb.compute.build-version>
<test.aws-elb.compute.identity>${test.aws.identity}</test.aws-elb.compute.identity>
<test.aws-elb.compute.credential>${test.aws.credential}</test.aws-elb.compute.credential>
- <test.aws-elb.compute.image-id />
+ <test.aws-elb.compute.template></test.aws-elb.compute.template>
<jclouds.osgi.export>org.jclouds.aws.elb*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
@@ -134,7 +134,7 @@
<test.aws-elb.compute.api-version>${test.aws-elb.compute.api-version}</test.aws-elb.compute.api-version>
<test.aws-elb.compute.identity>${test.aws-elb.compute.identity}</test.aws-elb.compute.identity>
<test.aws-elb.compute.credential>${test.aws-elb.compute.credential}</test.aws-elb.compute.credential>
- <test.aws-elb.compute.image-id>${test.aws-elb.compute.image-id}</test.aws-elb.compute.image-id>
+ <test.aws-elb.compute.template>${test.aws-elb.compute.template}</test.aws-elb.compute.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/labs/carrenza-vcloud-director/pom.xml b/labs/carrenza-vcloud-director/pom.xml
index 5a45d81..490dd0f 100644
--- a/labs/carrenza-vcloud-director/pom.xml
+++ b/labs/carrenza-vcloud-director/pom.xml
@@ -39,15 +39,13 @@
<test.carrenza-vcloud-director.build-version>464915</test.carrenza-vcloud-director.build-version>
<test.carrenza-vcloud-director.identity>FIXME_IDENTITY</test.carrenza-vcloud-director.identity>
<test.carrenza-vcloud-director.credential>FIXME_CREDENTIAL</test.carrenza-vcloud-director.credential>
- <test.carrenza-vcloud-director.image-id />
- <test.carrenza-vcloud-director.image.login-user />
- <test.carrenza-vcloud-director.image.authenticate-sudo />
- <test.carrenza-vcloud-director.catalog-id />
- <test.carrenza-vcloud-director.media-id />
- <test.carrenza-vcloud-director.vapptemplate-id />
- <test.carrenza-vcloud-director.network-name />
- <test.carrenza-vcloud-director.network-id />
- <test.carrenza-vcloud-director.vdc-id />
+ <test.carrenza-vcloud-director.template></test.carrenza-vcloud-director.template>
+ <test.carrenza-vcloud-director.catalog-id></test.carrenza-vcloud-director.catalog-id>
+ <test.carrenza-vcloud-director.media-id></test.carrenza-vcloud-director.media-id>
+ <test.carrenza-vcloud-director.vapptemplate-id></test.carrenza-vcloud-director.vapptemplate-id>
+ <test.carrenza-vcloud-director.network-name></test.carrenza-vcloud-director.network-name>
+ <test.carrenza-vcloud-director.network-id></test.carrenza-vcloud-director.network-id>
+ <test.carrenza-vcloud-director.vdc-id></test.carrenza-vcloud-director.vdc-id>
<jclouds.osgi.export>org.jclouds.carrenza.vcloud.director*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -121,9 +119,7 @@
<test.carrenza-vcloud-director.build-version>${test.carrenza-vcloud-director.build-version}</test.carrenza-vcloud-director.build-version>
<test.carrenza-vcloud-director.identity>${test.carrenza-vcloud-director.identity}</test.carrenza-vcloud-director.identity>
<test.carrenza-vcloud-director.credential>${test.carrenza-vcloud-director.credential}</test.carrenza-vcloud-director.credential>
- <test.carrenza-vcloud-director.image-id>${test.carrenza-vcloud-director.image-id}</test.carrenza-vcloud-director.image-id>
- <test.carrenza-vcloud-director.image.login-user>${test.carrenza-vcloud-director.image.login-user}</test.carrenza-vcloud-director.image.login-user>
- <test.carrenza-vcloud-director.image.authenticate-sudo>${test.carrenza-vcloud-director.image.authenticate-sudo}</test.carrenza-vcloud-director.image.authenticate-sudo>
+ <test.carrenza-vcloud-director.template>${test.carrenza-vcloud-director.template}</test.carrenza-vcloud-director.template>
<test.carrenza-vcloud-director.catalog-id>${test.carrenza-vcloud-director.catalog-id}</test.carrenza-vcloud-director.catalog-id>
<test.carrenza-vcloud-director.media-id>${test.carrenza-vcloud-director.media-id}</test.carrenza-vcloud-director.media-id>
<test.carrenza-vcloud-director.vapptemplate-id>${test.carrenza-vcloud-director.vapptemplate-id}</test.carrenza-vcloud-director.vapptemplate-id>
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/CDMIObject.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/CDMIObject.java
index 5950865..52faa8e 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/CDMIObject.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/CDMIObject.java
@@ -29,137 +29,144 @@
/**
* The base type for all objects in the CDMI model.
*
- * @author Adrian Cole
+ * @author Kenneth Nagin
*/
public class CDMIObject {
- public static Builder<?> builder() {
- return new ConcreteBuilder();
- }
+ public static Builder<?> builder() {
+ return new ConcreteBuilder();
+ }
- public Builder<?> toBuilder() {
- return builder().fromCDMIObject(this);
- }
+ public Builder<?> toBuilder() {
+ return builder().fromCDMIObject(this);
+ }
- private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
- }
+ private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+ }
- public static abstract class Builder<B extends Builder<B>> {
- private String objectID;
- private String objectType;
- private String objectName;
+ public static abstract class Builder<B extends Builder<B>> {
+ private String objectID;
+ private String objectType;
+ private String objectName;
- @SuppressWarnings("unchecked")
- protected B self() {
- return (B) this;
- }
+ @SuppressWarnings("unchecked")
+ protected B self() {
+ return (B) this;
+ }
- /**
- * @see CDMIObject#getObjectID()
- */
- public B objectID(String objectID) {
- this.objectID = objectID;
- return self();
- }
+ /**
+ * @see CDMIObject#getObjectID()
+ */
+ public B objectID(String objectID) {
+ this.objectID = objectID;
+ return self();
+ }
- /**
- * @see CDMIObject#getObjectType()
- */
- public B objectType(String objectType) {
- this.objectType = objectType;
- return self();
- }
+ /**
+ * @see CDMIObject#getObjectType()
+ */
+ public B objectType(String objectType) {
+ this.objectType = objectType;
+ return self();
+ }
- /**
- * @see CDMIObject#getObjectName()
- */
- public B objectName(String objectName) {
- this.objectName = objectName;
- return self();
- }
+ /**
+ * @see CDMIObject#getObjectName()
+ */
+ public B objectName(String objectName) {
+ this.objectName = objectName;
+ return self();
+ }
- public CDMIObject build() {
- return new CDMIObject(this);
- }
+ public CDMIObject build() {
+ return new CDMIObject(this);
+ }
- protected B fromCDMIObject(CDMIObject in) {
- return objectID(in.getObjectID()).objectType(in.getObjectType()).objectName(in.getObjectName());
- }
- }
+ protected B fromCDMIObject(CDMIObject in) {
+ return objectID(in.getObjectID()).objectType(in.getObjectType())
+ .objectName(in.getObjectName());
+ }
+ }
- private final String objectID;
- private final String objectType;
- private final String objectName;
+ private final String objectID;
+ private final String objectType;
+ private final String objectName;
- protected CDMIObject(Builder<?> builder) {
- this.objectID = checkNotNull(builder.objectID, "objectID");
- this.objectType = checkNotNull(builder.objectType, "objectType");
- this.objectName = builder.objectName;
- }
+ protected CDMIObject(Builder<?> builder) {
+ this.objectID = checkNotNull(builder.objectID, "objectID");
+ this.objectType = checkNotNull(builder.objectType, "objectType");
+ this.objectName = builder.objectName;
+ }
- /**
- * Object ID of the object <br/>
- * Every object stored within a CDMI-compliant system shall have a globally unique object
- * identifier (ID) assigned at creation time. The CDMI object ID is a string with requirements
- * for how it is generated and how it obtains its uniqueness. Each offering that implements CDMI
- * is able to produce these identifiers without conflicting with other offerings.
- */
- public String getObjectID() {
- return objectID;
- }
+ /**
+ * Object ID of the object <br/>
+ * Every object stored within a CDMI-compliant system shall have a globally
+ * unique object identifier (ID) assigned at creation time. The CDMI object
+ * ID is a string with requirements for how it is generated and how it
+ * obtains its uniqueness. Each offering that implements CDMI is able to
+ * produce these identifiers without conflicting with other offerings.
+ *
+ * note: CDMI Servers do not always support ObjectID tags, however
+ * downstream jclouds code does not handle null so we return a empty String
+ * instead.
+ */
+ public String getObjectID() {
+ return (objectID == null) ? "" : objectID;
+ }
- /**
- *
- * type of the object
- */
- public String getObjectType() {
- return objectType;
- }
+ /**
+ *
+ * type of the object
+ */
+ public String getObjectType() {
+ return objectType;
+ }
- /**
- * For objects in a container, the objectName field shall be returned. For objects not in a
- * container (objects that are only accessible by ID), the objectName field shall not be
- * returned.
- *
- * Name of the object
- */
- @Nullable
- public String getObjectName() {
- return objectName;
- }
+ /**
+ * For objects in a container, the objectName field shall be returned. For
+ * objects not in a container (objects that are only accessible by ID), the
+ * objectName field shall not be returned.
+ *
+ * Name of the object
+ */
+ @Nullable
+ public String getObjectName() {
+ return (objectName == null) ? "" : objectName;
+ }
- @Override
- public boolean equals(Object o) {
- if (this == o)
- return true;
- if (o == null || getClass() != o.getClass())
- return false;
- CDMIObject that = CDMIObject.class.cast(o);
- return equal(this.objectID, that.objectID) && equal(this.objectName, that.objectName)
- && equal(this.objectType, that.objectType);
- }
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ CDMIObject that = CDMIObject.class.cast(o);
+ return equal(this.objectID, that.objectID)
+ && equal(this.objectName, that.objectName)
+ && equal(this.objectType, that.objectType);
+ }
- public boolean clone(Object o) {
- if (this == o)
- return false;
- if (o == null || getClass() != o.getClass())
- return false;
- CDMIObject that = CDMIObject.class.cast(o);
- return equal(this.objectType, that.objectType);
- }
+ public boolean clone(Object o) {
+ if (this == o)
+ return false;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ CDMIObject that = CDMIObject.class.cast(o);
+ return equal(this.objectType, that.objectType);
+ }
- @Override
- public int hashCode() {
- return Objects.hashCode(objectID, objectName, objectType);
- }
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(objectID, objectName, objectType);
+ }
- @Override
- public String toString() {
- return string().toString();
- }
+ @Override
+ public String toString() {
+ return string().toString();
+ }
- protected ToStringHelper string() {
- return Objects.toStringHelper("").add("objectID", objectID).add("objectName", objectName).add("objectType",
- objectType);
- }
+ protected ToStringHelper string() {
+ return Objects.toStringHelper("").add("objectID", objectID)
+ .add("objectName", objectName).add("objectType", objectType);
+ }
}
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/Container.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/Container.java
index f0d1aff..24567f5 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/Container.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/Container.java
@@ -21,9 +21,15 @@
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.jclouds.domain.JsonBall;
+
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableMap;
@@ -32,103 +38,196 @@
/**
*
- * @author Adrian Cole
+ * @author Kenneth Nagin
*/
public class Container extends CDMIObject {
- public static Builder<?> builder() {
- return new ConcreteBuilder();
- }
+ public static Builder<?> builder() {
+ return new ConcreteBuilder();
+ }
- @Override
- public Builder<?> toBuilder() {
- return builder().fromContainer(this);
- }
+ @Override
+ public Builder<?> toBuilder() {
+ return builder().fromContainer(this);
+ }
- public static class Builder<B extends Builder<B>> extends CDMIObject.Builder<B> {
+ public static class Builder<B extends Builder<B>> extends
+ CDMIObject.Builder<B> {
- private Set<String> children = ImmutableSet.of();
- private Map<String, String> metadata = Maps.newHashMap();
+ private Set<String> children = ImmutableSet.of();
+ private Map<String, JsonBall> metadata = Maps.newHashMap();
- /**
- * @see Container#getChildren()
- */
- public B children(String... children) {
- return children(ImmutableSet.copyOf(checkNotNull(children, "children")));
- }
+ /**
+ * @see Container#getChildren()
+ */
+ public B children(String... children) {
+ return children(ImmutableSet.copyOf(checkNotNull(children,
+ "children")));
+ }
- /**
- * @see Container#getChildren()
- */
- public B children(Set<String> children) {
- this.children = ImmutableSet.copyOf(checkNotNull(children, "children"));
- return self();
- }
+ /**
+ * @see Container#getChildren()
+ */
+ public B children(Set<String> children) {
+ this.children = ImmutableSet.copyOf(checkNotNull(children,
+ "children"));
+ return self();
+ }
- /**
- * @see Container#getMetadata()
- */
- public B metadata(Map<String, String> metadata) {
- this.metadata = ImmutableMap.copyOf(checkNotNull(metadata, "metadata"));
- return self();
- }
+ /**
+ * @see Container#getMetadata()
+ */
+ public B metadata(Map<String, JsonBall> metadata) {
+ this.metadata = ImmutableMap.copyOf(checkNotNull(metadata,
+ "metadata"));
+ return self();
+ }
- @Override
- public Container build() {
- return new Container(this);
- }
+ @Override
+ public Container build() {
+ return new Container(this);
+ }
- public B fromContainer(Container in) {
- return fromCDMIObject(in).children(in.getChildren()).metadata(in.getMetadata());
- }
- }
+ public B fromContainer(Container in) {
+ return fromCDMIObject(in).children(in.getChildren()).metadata(
+ in.getMetadata());
+ }
+ }
- private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
- }
+ private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+ }
- private final Set<String> children;
- private final Map<String, String> metadata;
+ private final Set<String> children;
+ private final Map<String, JsonBall> metadata;
- protected Container(Builder<?> builder) {
- super(builder);
- this.children = ImmutableSet.copyOf(checkNotNull(builder.children, "children"));
- this.metadata = ImmutableMap.copyOf(checkNotNull(builder.metadata, "metadata"));
- }
+ private Map<String, String> userMetaDataIn;
+ private Map<String, String> systemMetaDataIn;
+ private List<Map<String, String>> aclMetaDataIn;
- /**
- * Names of the children objects in the container object. Child container objects end with "/".
- */
- public Set<String> getChildren() {
- return children;
- }
+ protected Container(Builder<?> builder) {
+ super(builder);
+ this.children = ImmutableSet.copyOf(checkNotNull(builder.children,
+ "children"));
+ this.metadata = ImmutableMap.copyOf(checkNotNull(builder.metadata,
+ "metadata"));
+ }
- /**
- * Metadata for the container object. This field includes any user and data system metadata
- * specified in the request body metadata field, along with storage system metadata generated by
- * the cloud storage system.
- */
- public Map<String, String> getMetadata() {
- return metadata;
- }
+ /**
+ * Names of the children objects in the container object. Child container
+ * objects end with "/".
+ */
+ public Set<String> getChildren() {
+ return children;
+ }
- @Override
- public boolean equals(Object o) {
- if (this == o)
- return true;
- if (o == null || getClass() != o.getClass())
- return false;
- Container that = Container.class.cast(o);
- return super.equals(that) && equal(this.children, that.children) && equal(this.metadata, that.metadata);
- }
+ /**
+ * Metadata for the container object. This field includes any user and
+ * system metadata specified in the request body metadata field, along with
+ * storage system metadata generated by the cloud storage system.
+ */
+ public Map<String, JsonBall> getMetadata() {
+ return metadata;
+ }
- @Override
- public int hashCode() {
- return Objects.hashCode(super.hashCode(), children, metadata);
- }
+ /**
+ * Parse Metadata for the container object from the original JsonBall.
+ * System metadata data is prefixed with cdmi. System ACL metadata data is
+ * prefixed with cdmi_acl
+ *
+ */
+ private void parseMetadata() {
+ userMetaDataIn = new HashMap<String, String>();
+ systemMetaDataIn = new HashMap<String, String>();
+ aclMetaDataIn = new ArrayList<Map<String, String>>();
+ Iterator<String> keys = metadata.keySet().iterator();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ JsonBall value = metadata.get(key);
+ if (key.startsWith("cdmi")) {
+ if (key.matches("cdmi_acl")) {
+ String[] cdmi_acl_array = value.toString().split("[{}]");
+ for (int i = 0; i < cdmi_acl_array.length; i++) {
+ if (!(cdmi_acl_array[i].startsWith("[")
+ || cdmi_acl_array[i].startsWith("]") || cdmi_acl_array[i]
+ .startsWith(","))) {
+ HashMap<String, String> aclMap = new HashMap<String, String>();
+ String[] cdmi_acl_member = cdmi_acl_array[i]
+ .split(",");
+ for (String s : cdmi_acl_member) {
+ String cdmi_acl_key = s.substring(0,
+ s.indexOf(":"));
+ String cdmi_acl_value = s.substring(s
+ .indexOf(":") + 1);
+ cdmi_acl_value.replace('"', ' ').trim();
+ aclMap.put(cdmi_acl_key, cdmi_acl_value);
+ }
+ aclMetaDataIn.add(aclMap);
+ }
+ }
+ } else {
+ systemMetaDataIn.put(key, value.toString()
+ .replace('"', ' ').trim());
+ }
+ } else {
+ userMetaDataIn.put(key, value.toString().replace('"', ' ')
+ .trim());
+ }
+ }
+ }
- @Override
- public ToStringHelper string() {
- return super.string().add("children", children).add("metadata", metadata);
- }
+ /**
+ * Get User Metadata for the container object. This field includes any user
+ * metadata
+ */
+ public Map<String, String> getUserMetadata() {
+ if (userMetaDataIn == null) {
+ parseMetadata();
+ }
+ return userMetaDataIn;
+ }
+
+ /**
+ * Get System Metadata for the container object excluding ACL related
+ * metadata
+ */
+ public Map<String, String> getSystemMetadata() {
+ if (systemMetaDataIn == null) {
+ parseMetadata();
+ }
+ return systemMetaDataIn;
+ }
+
+ /**
+ * Get System Metadata for the container object excluding ACL related
+ * metadata
+ */
+ public List<Map<String, String>> getACLMetadata() {
+ if (aclMetaDataIn == null) {
+ parseMetadata();
+ }
+ return aclMetaDataIn;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ Container that = Container.class.cast(o);
+ return super.equals(that) && equal(this.children, that.children)
+ && equal(this.metadata, that.metadata);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), children, metadata);
+ }
+
+ @Override
+ public ToStringHelper string() {
+ return super.string().add("children", children)
+ .add("metadata", metadata);
+ }
}
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerAsyncClient.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerAsyncClient.java
index 1bbf725..f738dfc 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerAsyncClient.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerAsyncClient.java
@@ -19,9 +19,12 @@
package org.jclouds.snia.cdmi.v1.features;
import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.rest.annotations.ExceptionParser;
@@ -40,7 +43,7 @@
* Container Object Resource Operations
*
* @see ContainerClient
- * @author Adrian Cole
+ * @author Kenneth Nagin
* @see <a href="http://www.snia.org/cdmi">api doc</a>
*/
@SkipEncoding( { '/', '=' })
@@ -56,5 +59,25 @@
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/{containerName}/")
ListenableFuture<Container> getContainer(@PathParam("containerName") String containerName);
+
+ /**
+ * @see ContainerClient#createContainer
+ */
+ @PUT
+ @Consumes( { ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON })
+ @Produces( { ObjectTypes.CONTAINER})
+ @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+ @Path("/{containerName}/")
+ ListenableFuture<Container> createContainer(@PathParam("containerName") String containerName);
+
+ /**
+ * @see ContainerClient#createContainer()
+ */
+ @DELETE
+// @Consumes( { ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON })
+ @Consumes( MediaType.APPLICATION_JSON )
+ @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+ @Path("/{containerName}/")
+ ListenableFuture<Void> deleteContainer(@PathParam("containerName") String containerName);
}
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerClient.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerClient.java
index 76df5c7..2bd3b8e 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerClient.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerClient.java
@@ -27,12 +27,15 @@
* Container Object Resource Operations
*
* @see ContainerAsyncClient
- * @author Adrian Cole
+ * @author Kenneth Nagin
* @see <a href="http://www.snia.org/cdmi">api doc</a>
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface ContainerClient {
+ Container createContainer(String containerName);
- Container getContainer(String containerName);
+ Container getContainer(String containerName);
+
+ void deleteContainer(String containerName);
}
diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerClientLiveTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerClientLiveTest.java
index 1ee33f4..012a527 100644
--- a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerClientLiveTest.java
+++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerClientLiveTest.java
@@ -21,6 +21,10 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
import org.jclouds.snia.cdmi.v1.ObjectTypes;
import org.jclouds.snia.cdmi.v1.domain.Container;
import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientLiveTest;
@@ -28,21 +32,49 @@
/**
*
- * @author Adrian Cole
+ * @author Kenneth Nagin
*/
@Test(groups = "live", testName = "ContainerClientLiveTest")
public class ContainerClientLiveTest extends BaseCDMIClientLiveTest {
-
@Test
- public void testGetContainer() throws Exception {
+ public void testCreateContainer() throws Exception {
+ String pContainerName = "MyContainer" + System.currentTimeMillis();
ContainerClient client = cdmiContext.getApi().getContainerClient();
- Container container = client.getContainer("TODO: figure out how to list containers");
+ Logger.getAnonymousLogger().info("createContainer: " + pContainerName);
+ Container container = client.createContainer(pContainerName);
assertNotNull(container);
+ System.out.println(container);
+ Logger.getAnonymousLogger().info("getContainer: " + pContainerName);
+ container = client.getContainer(pContainerName);
+ assertNotNull(container);
+ System.out.println(container);
assertEquals(container.getObjectType(), ObjectTypes.CONTAINER);
assertNotNull(container.getObjectID());
assertNotNull(container.getObjectName());
+ assertEquals(container.getObjectName(), pContainerName + "/");
assertNotNull(container.getChildren());
+ assertEquals(container.getChildren().isEmpty(), true);
+ System.out.println("Children: " + container.getChildren());
assertNotNull(container.getMetadata());
+ assertNotNull(container.getUserMetadata());
+ System.out.println("UserMetaData: " + container.getUserMetadata());
+ assertNotNull(container.getSystemMetadata());
+ System.out.println("SystemMetaData: " + container.getSystemMetadata());
+ assertNotNull(container.getACLMetadata());
+ List<Map<String, String>> aclMetadataOut = container.getACLMetadata();
+ System.out.println("ACLMetaData: ");
+ for (Map<String, String> aclMap : aclMetadataOut) {
+ System.out.println(aclMap);
+ }
+ container = client.getContainer("/");
+ System.out.println("root container: " + container);
+ assertEquals(container.getChildren().contains(pContainerName + "/"), true);
+ Logger.getAnonymousLogger().info("deleteContainer: " + pContainerName);
+ client.deleteContainer(pContainerName);
+ container = client.getContainer("/");
+ System.out.println("root container: " + container);
+ assertEquals(container.getChildren().contains(pContainerName + "/"), false);
+
}
}
diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/parse/ParseContainerTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/parse/ParseContainerTest.java
index 14fea21..2cd3ef4 100644
--- a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/parse/ParseContainerTest.java
+++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/parse/ParseContainerTest.java
@@ -21,6 +21,7 @@
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
+import org.jclouds.domain.JsonBall;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.snia.cdmi.v1.domain.Container;
import org.testng.annotations.Test;
@@ -30,7 +31,7 @@
/**
*
- * @author Adrian Cole
+ * @author Kenneth Nagin
*/
@Test(groups = "unit", testName = "ParseContainerTest")
public class ParseContainerTest extends BaseItemParserTest<Container> {
@@ -47,8 +48,8 @@
.objectType("application/cdmi-container")
.objectID("00007E7F00102E230ED82694DAA975D2")
.objectName("MyContainer/")
- .metadata(ImmutableMap.<String, String>builder()
- .put("cdmi_size", "83")
+ .metadata(ImmutableMap.<String, JsonBall>builder()
+ .put("cdmi_size", new JsonBall("\"83\""))
.build())
.children(ImmutableSet.<String>builder()
.add("MyDataObject.txt")
diff --git a/labs/elb/pom.xml b/labs/elb/pom.xml
index 3e8b49f..48649e2 100644
--- a/labs/elb/pom.xml
+++ b/labs/elb/pom.xml
@@ -37,16 +37,16 @@
<test.elb.zone>us-east-1a</test.elb.zone>
<test.elb.endpoint>https://elasticloadbalancing.us-east-1.amazonaws.com</test.elb.endpoint>
<test.elb.api-version>2010-07-01</test.elb.api-version>
- <test.elb.build-version />
+ <test.elb.build-version></test.elb.build-version>
<test.elb.identity>${test.aws.identity}</test.elb.identity>
<test.elb.credential>${test.aws.credential}</test.elb.credential>
<test.elb.compute.provider>aws-ec2</test.elb.compute.provider>
<test.elb.compute.endpoint>https://ec2.us-east-1.amazonaws.com</test.elb.compute.endpoint>
<test.elb.compute.api-version>2010-06-15</test.elb.compute.api-version>
- <test.elb.compute.build-version />
+ <test.elb.compute.build-version></test.elb.compute.build-version>
<test.elb.compute.identity>${test.aws.identity}</test.elb.compute.identity>
<test.elb.compute.credential>${test.aws.credential}</test.elb.compute.credential>
- <test.elb.compute.image-id />
+ <test.elb.compute.template></test.elb.compute.template>
<jclouds.osgi.export>org.jclouds.elb*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
@@ -134,7 +134,7 @@
<test.elb.compute.build-version>${test.elb.compute.build-version}</test.elb.compute.build-version>
<test.elb.compute.identity>${test.elb.compute.identity}</test.elb.compute.identity>
<test.elb.compute.credential>${test.elb.compute.credential}</test.elb.compute.credential>
- <test.elb.compute.image-id>${test.elb.compute.image-id}</test.elb.compute.image-id>
+ <test.elb.compute.template>${test.elb.compute.template}</test.elb.compute.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/labs/elb/src/test/java/org/jclouds/elb/ELBAsyncClientTest.java b/labs/elb/src/test/java/org/jclouds/elb/ELBAsyncClientTest.java
index bd9a10a..85486c1 100644
--- a/labs/elb/src/test/java/org/jclouds/elb/ELBAsyncClientTest.java
+++ b/labs/elb/src/test/java/org/jclouds/elb/ELBAsyncClientTest.java
@@ -23,9 +23,6 @@
import java.io.IOException;
import java.lang.reflect.Method;
-import javax.inject.Named;
-
-import org.jclouds.Constants;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.date.DateService;
@@ -162,8 +159,7 @@
}
@Override
- protected String provideTimeStamp(final DateService dateService,
- @Named(Constants.PROPERTY_SESSION_INTERVAL) int expiration) {
+ protected String provideTimeStamp(final DateService dateService) {
return "2009-11-08T15:54:08.897Z";
}
}
diff --git a/labs/glesys/pom.xml b/labs/glesys/pom.xml
index 220f66f..bc2b677 100644
--- a/labs/glesys/pom.xml
+++ b/labs/glesys/pom.xml
@@ -36,13 +36,10 @@
<properties>
<test.glesys.endpoint>https://api.glesys.com</test.glesys.endpoint>
<test.glesys.api-version>1</test.glesys.api-version>
- <test.glesys.build-version />
+ <test.glesys.build-version></test.glesys.build-version>
<test.glesys.identity>FIXME</test.glesys.identity>
<test.glesys.credential>FIXME</test.glesys.credential>
- <test.glesys.image-id />
- <test.glesys.image.login-user />
- <test.glesys.image.authenticate-sudo />
-
+ <test.glesys.template></test.glesys.template>
<jclouds.osgi.export>org.jclouds.glesys*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
</properties>
@@ -102,9 +99,7 @@
<test.glesys.build-version>${test.glesys.build-version}</test.glesys.build-version>
<test.glesys.identity>${test.glesys.identity}</test.glesys.identity>
<test.glesys.credential>${test.glesys.credential}</test.glesys.credential>
- <test.glesys.image-id>${test.glesys.image-id}</test.glesys.image-id>
- <test.glesys.image.login-user>${test.glesys.image.login-user}</test.glesys.image.login-user>
- <test.glesys.image.authenticate-sudo>${test.glesys.image.authenticate-sudo}</test.glesys.image.authenticate-sudo>
+ <test.glesys.template>${test.glesys.template}</test.glesys.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/labs/greenqloud-compute/pom.xml b/labs/greenqloud-compute/pom.xml
new file mode 100644
index 0000000..698f58e
--- /dev/null
+++ b/labs/greenqloud-compute/pom.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to jclouds, Inc. (jclouds) under one or more
+ contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. jclouds 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-project</artifactId>
+ <version>1.5.0-SNAPSHOT</version>
+ <relativePath>../../project/pom.xml</relativePath>
+ </parent>
+ <groupId>org.jclouds.labs</groupId>
+ <artifactId>greenqloud-compute</artifactId>
+ <name>jclouds Greenqloud compute provider</name>
+ <description>Compute implementation targeted to Greenqloud Web Services</description>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <test.greenqloud-compute.endpoint>https://api.greenqloud.com</test.greenqloud-compute.endpoint>
+ <test.greenqloud-compute.api-version>2010-06-15</test.greenqloud-compute.api-version>
+ <test.greenqloud-compute.build-version></test.greenqloud-compute.build-version>
+ <test.greenqloud-compute.identity>${test.greenqloud.identity}</test.greenqloud-compute.identity>
+ <test.greenqloud-compute.credential>${test.greenqloud.credential}</test.greenqloud-compute.credential>
+ <test.greenqloud-compute.template></test.greenqloud-compute.template>
+ <test.greenqloud-compute.ebs-template>osFamily=UBUNTU,osVersionMatches=1[012].[01][04],os64Bit=true</test.greenqloud-compute.ebs-template>
+
+ <jclouds.osgi.export>org.jclouds.greenqloud.compute*;version="${project.version}"</jclouds.osgi.export>
+ <jclouds.osgi.import>
+ org.jclouds.compute.internal;version="${project.version}",
+ org.jclouds.rest.internal;version="${project.version}",
+ org.jclouds*;version="${project.version}",
+ *
+ </jclouds.osgi.import>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jclouds.api</groupId>
+ <artifactId>ec2</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.api</groupId>
+ <artifactId>ec2</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-compute</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.driver</groupId>
+ <artifactId>jclouds-log4j</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.driver</groupId>
+ <artifactId>jclouds-sshj</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>live</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>integration</id>
+ <phase>integration-test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <threadCount>1</threadCount>
+ <systemPropertyVariables>
+ <test.greenqloud-compute.endpoint>${test.greenqloud-compute.endpoint}</test.greenqloud-compute.endpoint>
+ <test.greenqloud-compute.api-version>${test.greenqloud-compute.api-version}</test.greenqloud-compute.api-version>
+ <test.greenqloud-compute.build-version>${test.greenqloud-compute.build-version}</test.greenqloud-compute.build-version>
+ <test.greenqloud-compute.identity>${test.greenqloud-compute.identity}</test.greenqloud-compute.identity>
+ <test.greenqloud-compute.credential>${test.greenqloud-compute.credential}</test.greenqloud-compute.credential>
+ <test.greenqloud-compute.template>${test.greenqloud-compute.template}</test.greenqloud-compute.template>
+ </systemPropertyVariables>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
+
diff --git a/labs/greenqloud-compute/src/main/java/org/jclouds/greenqloud/compute/GreenQloudComputeProviderMetadata.java b/labs/greenqloud-compute/src/main/java/org/jclouds/greenqloud/compute/GreenQloudComputeProviderMetadata.java
new file mode 100644
index 0000000..00cd0cd
--- /dev/null
+++ b/labs/greenqloud-compute/src/main/java/org/jclouds/greenqloud/compute/GreenQloudComputeProviderMetadata.java
@@ -0,0 +1,101 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.greenqloud.compute;
+
+import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.ec2.EC2ApiMetadata;
+import org.jclouds.ec2.compute.config.EC2ResolveImagesModule;
+import org.jclouds.ec2.config.EC2RestClientModule;
+import org.jclouds.greenqloud.compute.config.GreenQloudComputeComputeServiceContextModule;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadata;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link org.jclouds.providers.ProviderMetadata} for Greenqloud Compute Cloud.
+ *
+ * @author Adrian Cole
+ */
+public class GreenQloudComputeProviderMetadata extends BaseProviderMetadata {
+
+ /** The serialVersionUID */
+ private static final long serialVersionUID = 7625722444851538962L;
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return builder().fromProviderMetadata(this);
+ }
+
+ public GreenQloudComputeProviderMetadata() {
+ super(builder());
+ }
+
+ public GreenQloudComputeProviderMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = new Properties();
+ properties.setProperty(PROPERTY_REGIONS, "is-1");
+ properties.setProperty(PROPERTY_REGION + ".is-1." + ISO3166_CODES, "IS-1");
+ return properties;
+ }
+
+ public static class Builder extends BaseProviderMetadata.Builder {
+
+ protected Builder(){
+ id("greenqloud-compute")
+ .name("Greenqloud Compute Cloud")
+ .apiMetadata(
+ new EC2ApiMetadata().toBuilder()
+ .defaultModules(ImmutableSet.<Class<? extends Module>>of(EC2RestClientModule.class, EC2ResolveImagesModule.class, GreenQloudComputeComputeServiceContextModule.class))
+ .build())
+ .homepage(URI.create("http://www.greenqloud.com"))
+ .console(URI.create("https://manage.greenqloud.com"))
+ .linkedServices("greenqloud-compute", "greenqloud-storage")
+ .iso3166Codes("IS-1")
+ .endpoint("https://api.greenqloud.com")
+ .defaultProperties(GreenQloudComputeProviderMetadata.defaultProperties());
+ }
+
+ @Override
+ public GreenQloudComputeProviderMetadata build() {
+ return new GreenQloudComputeProviderMetadata(this);
+ }
+
+ @Override
+ public Builder fromProviderMetadata(
+ ProviderMetadata in) {
+ super.fromProviderMetadata(in);
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/labs/greenqloud-compute/src/main/java/org/jclouds/greenqloud/compute/config/GreenQloudComputeComputeServiceContextModule.java b/labs/greenqloud-compute/src/main/java/org/jclouds/greenqloud/compute/config/GreenQloudComputeComputeServiceContextModule.java
new file mode 100644
index 0000000..6bff01b
--- /dev/null
+++ b/labs/greenqloud-compute/src/main/java/org/jclouds/greenqloud/compute/config/GreenQloudComputeComputeServiceContextModule.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.greenqloud.compute.config;
+
+import org.jclouds.ec2.compute.config.EC2ComputeServiceContextModule;
+import org.jclouds.ec2.compute.strategy.ReviseParsedImage;
+import org.jclouds.greenqloud.compute.strategy.GreenQloudComputeReviseParsedImage;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+public class GreenQloudComputeComputeServiceContextModule extends EC2ComputeServiceContextModule {
+
+ @Override
+ protected void configure() {
+ super.configure();
+ bind(ReviseParsedImage.class).to(GreenQloudComputeReviseParsedImage.class);
+ }
+
+}
diff --git a/labs/greenqloud-compute/src/main/java/org/jclouds/greenqloud/compute/strategy/GreenQloudComputeReviseParsedImage.java b/labs/greenqloud-compute/src/main/java/org/jclouds/greenqloud/compute/strategy/GreenQloudComputeReviseParsedImage.java
new file mode 100644
index 0000000..1d54b88
--- /dev/null
+++ b/labs/greenqloud-compute/src/main/java/org/jclouds/greenqloud/compute/strategy/GreenQloudComputeReviseParsedImage.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.greenqloud.compute.strategy;
+
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.util.ComputeServiceUtils;
+import org.jclouds.ec2.compute.strategy.ReviseParsedImage;
+import org.jclouds.logging.Logger;
+
+/**
+ * @author Adrian Cole
+ */
+@Singleton
+public class GreenQloudComputeReviseParsedImage implements ReviseParsedImage {
+ public static final Pattern DEFAULT_PATTERN = Pattern.compile("(([^ ]*) ([0-9.]+) ?.*)");
+
+ @javax.annotation.Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ private final Map<OsFamily, Map<String, String>> osVersionMap;
+
+ @Inject
+ public GreenQloudComputeReviseParsedImage(Map<OsFamily, Map<String, String>> osVersionMap) {
+ this.osVersionMap = osVersionMap;
+ }
+
+ public void reviseParsedImage(org.jclouds.ec2.domain.Image from, ImageBuilder builder, OsFamily family,
+ OperatingSystem.Builder osBuilder) {
+ if (from.getDescription() != null)
+ osBuilder.is64Bit(from.getDescription().contains("64-bit"));
+
+ Matcher matcher = DEFAULT_PATTERN.matcher(from.getDescription());
+ if (matcher.find() && matcher.groupCount() >= 3) {
+ osBuilder.version(ComputeServiceUtils.parseVersionOrReturnEmptyString(family, matcher.group(3), osVersionMap));
+ }
+ }
+}
\ No newline at end of file
diff --git a/labs/greenqloud-compute/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/labs/greenqloud-compute/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
new file mode 100644
index 0000000..ddcff31
--- /dev/null
+++ b/labs/greenqloud-compute/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
@@ -0,0 +1 @@
+org.jclouds.greenqloud.compute.GreenQloudComputeProviderMetadata
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/GreenQloudComputeComputeServiceLiveTest.java
similarity index 63%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/GreenQloudComputeComputeServiceLiveTest.java
index 771a1be..fc332ec 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/GreenQloudComputeComputeServiceLiveTest.java
@@ -16,13 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.greenqloud.compute;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.ec2.compute.EC2ComputeServiceLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
+/**
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "GreenQloudComputeComputeServiceLiveTest")
+public class GreenQloudComputeComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
- void startPool() throws RunNodesException;
-
+ public GreenQloudComputeComputeServiceLiveTest() {
+ provider = "greenqloud-compute";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/GreenQloudComputeProviderTest.java
similarity index 63%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/GreenQloudComputeProviderTest.java
index 771a1be..134d6c7 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/GreenQloudComputeProviderTest.java
@@ -16,13 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.greenqloud.compute;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.ec2.EC2ApiMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadataTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
+@Test(groups = "unit", testName = "GreenQloudComputeProviderTest")
+public class GreenQloudComputeProviderTest extends BaseProviderMetadataTest {
- void startPool() throws RunNodesException;
+ public GreenQloudComputeProviderTest() {
+ super(new GreenQloudComputeProviderMetadata(), new EC2ApiMetadata());
+ }
-}
+}
\ No newline at end of file
diff --git a/labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/GreenQloudComputeTemplateBuilderLiveTest.java b/labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/GreenQloudComputeTemplateBuilderLiveTest.java
new file mode 100644
index 0000000..d233f05
--- /dev/null
+++ b/labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/GreenQloudComputeTemplateBuilderLiveTest.java
@@ -0,0 +1,96 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.greenqloud.compute;
+
+import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.jclouds.aws.util.AWSUtils;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.OsFamilyVersion64Bit;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest;
+import org.jclouds.domain.LocationScope;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "GreenQloudComputeTemplateBuilderLiveTest")
+public class GreenQloudComputeTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
+
+ public GreenQloudComputeTemplateBuilderLiveTest() {
+ provider = "greenqloud-compute";
+ }
+
+ @Override
+ protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
+ return Predicates.not(new Predicate<OsFamilyVersion64Bit>() {
+
+ @Override
+ public boolean apply(OsFamilyVersion64Bit input) {
+ switch (input.family) {
+ case UBUNTU:
+ return (input.version.equals("") || input.version.equals("10.04") || input.version.equals("11.04") || input.version
+ .equals("11.10"))
+ && input.is64Bit;
+ case DEBIAN:
+ return (input.version.equals("") || input.version.equals("6.0")) && input.is64Bit;
+ case CENTOS:
+ return (input.version.equals("") || input.version.equals("5.5") || input.version.equals("5.6") || input.version
+ .equals("6.0"))
+ && input.is64Bit;
+ case FEDORA:
+ return input.version.equals("") && input.is64Bit;
+ default:
+ return false;
+ }
+ }
+
+ });
+ }
+
+ @Test
+ public void testDefaultTemplateBuilder() throws IOException {
+ Template defaultTemplate = view.getComputeService().templateBuilder().build();
+ assert (defaultTemplate.getImage().getProviderId().startsWith("qmi-")) : defaultTemplate;
+ assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "11.10");
+ assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
+ assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
+ assertEquals(defaultTemplate.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
+ assertEquals(defaultTemplate.getHardware().getId(), "m1.small");
+ assertEquals(defaultTemplate.getLocation().getId(), "is-1");
+ assertEquals(defaultTemplate.getLocation().getScope(), LocationScope.REGION);
+ assertEquals(AWSUtils.getRegionFromLocationOrNull(defaultTemplate.getLocation()), "is-1");
+ assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
+ }
+
+ @Override
+ protected Set<String> getIso3166Codes() {
+ return ImmutableSet.<String> of("IS-1");
+ }
+}
diff --git a/labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/strategy/GreenQloudComputeReviseParsedImageTest.java b/labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/strategy/GreenQloudComputeReviseParsedImageTest.java
new file mode 100644
index 0000000..7ad0cdf
--- /dev/null
+++ b/labs/greenqloud-compute/src/test/java/org/jclouds/greenqloud/compute/strategy/GreenQloudComputeReviseParsedImageTest.java
@@ -0,0 +1,256 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.greenqloud.compute.strategy;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.jclouds.compute.config.BaseComputeServiceContextModule;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.ec2.compute.config.EC2ComputeServiceDependenciesModule;
+import org.jclouds.ec2.compute.functions.EC2ImageParser;
+import org.jclouds.ec2.compute.strategy.EC2PopulateDefaultLoginCredentialsForImageStrategy;
+import org.jclouds.ec2.domain.Image;
+import org.jclouds.ec2.xml.DescribeImagesResponseHandlerTest;
+import org.jclouds.greenqloud.compute.strategy.GreenQloudComputeReviseParsedImage;
+import org.jclouds.json.Json;
+import org.jclouds.json.config.GsonModule;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicates;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import com.google.inject.Guice;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "GreenQloudComputeReviseParsedImageTest")
+public class GreenQloudComputeReviseParsedImageTest {
+
+ public void testParseGreenQloudImage() {
+
+ Set<org.jclouds.compute.domain.Image> result = convertImages("/greenqloud_images.xml");
+ assertEquals(result.size(), 9);
+
+ assertEquals(
+ Iterables.get(result, 0).toString(),
+ new ImageBuilder()
+ .operatingSystem(
+ OperatingSystem.builder().family(OsFamily.UBUNTU).version("10.04")
+ .description("Ubuntu Server 10.04 (64-bit)").is64Bit(true)
+ .arch("paravirtual").build())
+ .description("Ubuntu Server 10.04 (64-bit)")
+ .name("Ubuntu Server 10.04.3")
+ .defaultCredentials(new LoginCredentials("root", false))
+ .id("us-east-1/qmi-4e5b842f")
+ .providerId("qmi-4e5b842f")
+ .location(defaultLocation)
+ .userMetadata(
+ ImmutableMap.of("owner", "admin", "rootDeviceType", "ebs", "virtualizationType",
+ "paravirtual", "hypervisor", "xen"))
+ .status(org.jclouds.compute.domain.Image.Status.AVAILABLE).backendStatus("available").build().toString());
+ assertEquals(Iterables.get(result, 0).getStatus(), org.jclouds.compute.domain.Image.Status.AVAILABLE);
+
+ assertEquals(
+ Iterables.get(result, 1).toString(),
+ new ImageBuilder()
+ .operatingSystem(
+ OperatingSystem.builder().family(OsFamily.UBUNTU).version("11.10")
+ .description("Ubuntu Server 11.10 (64-bit)").is64Bit(true)
+ .arch("paravirtual").build())
+ .description("Ubuntu Server 11.10 (64-bit)")
+ .name("Ubuntu Server 11.10")
+ .defaultCredentials(new LoginCredentials("root", false))
+ .id("us-east-1/qmi-9ac92558")
+ .providerId("qmi-9ac92558")
+ .location(defaultLocation)
+ .userMetadata(
+ ImmutableMap.of("owner", "admin", "rootDeviceType", "ebs", "virtualizationType",
+ "paravirtual", "hypervisor", "xen"))
+ .status(org.jclouds.compute.domain.Image.Status.AVAILABLE).backendStatus("available").build().toString());
+ assertEquals(Iterables.get(result, 1).getStatus(), org.jclouds.compute.domain.Image.Status.AVAILABLE);
+
+ assertEquals(
+ Iterables.get(result, 2).toString(),
+ new ImageBuilder()
+ .operatingSystem(
+ OperatingSystem.builder().family(OsFamily.CENTOS).version("5.5")
+ .description("CentOS 5.5 Server 64-bit").is64Bit(true)
+ .arch("paravirtual").build())
+ .description("CentOS 5.5 Server 64-bit")
+ .name("CentOS 5.5 Server")
+ .defaultCredentials(new LoginCredentials("root", false))
+ .id("us-east-1/qmi-33a467aa")
+ .providerId("qmi-33a467aa")
+ .location(defaultLocation)
+ .userMetadata(
+ ImmutableMap.of("owner", "admin", "rootDeviceType", "ebs", "virtualizationType",
+ "paravirtual", "hypervisor", "xen"))
+ .status(org.jclouds.compute.domain.Image.Status.AVAILABLE).backendStatus("available").build().toString());
+ assertEquals(Iterables.get(result, 2).getStatus(), org.jclouds.compute.domain.Image.Status.AVAILABLE);
+
+ assertEquals(
+ Iterables.get(result, 3).toString(),
+ new ImageBuilder()
+ .operatingSystem(
+ OperatingSystem.builder().family(OsFamily.DEBIAN).version("6.0")
+ .description("Debian 6.0 (64-bit)").is64Bit(true)
+ .arch("paravirtual").build())
+ .description("Debian 6.0 (64-bit)")
+ .name("Debian 6.0")
+ .defaultCredentials(new LoginCredentials("root", false))
+ .id("us-east-1/qmi-f2a9d2ba")
+ .providerId("qmi-f2a9d2ba")
+ .location(defaultLocation)
+ .userMetadata(
+ ImmutableMap.of("owner", "admin", "rootDeviceType", "ebs", "virtualizationType",
+ "paravirtual", "hypervisor", "xen"))
+ .status(org.jclouds.compute.domain.Image.Status.AVAILABLE).backendStatus("available").build().toString());
+ assertEquals(Iterables.get(result, 3).getStatus(), org.jclouds.compute.domain.Image.Status.AVAILABLE);
+
+ assertEquals(
+ Iterables.get(result, 4).toString(),
+ new ImageBuilder()
+ .operatingSystem(
+ OperatingSystem.builder().family(OsFamily.CENTOS).version("6.0")
+ .description("CentOS 6.0 (64-bit)").is64Bit(true)
+ .arch("paravirtual").build())
+ .description("CentOS 6.0 (64-bit)")
+ .name("CentOS 6.0")
+ .defaultCredentials(new LoginCredentials("root", false))
+ .id("us-east-1/qmi-96f82145")
+ .providerId("qmi-96f82145")
+ .location(defaultLocation)
+ .userMetadata(
+ ImmutableMap.of("owner", "admin", "rootDeviceType", "ebs", "virtualizationType",
+ "paravirtual", "hypervisor", "xen"))
+ .status(org.jclouds.compute.domain.Image.Status.AVAILABLE).backendStatus("available").build().toString());
+ assertEquals(Iterables.get(result, 4).getStatus(), org.jclouds.compute.domain.Image.Status.AVAILABLE);
+
+ assertEquals(
+ Iterables.get(result, 5).toString(),
+ new ImageBuilder()
+ .operatingSystem(
+ OperatingSystem.builder().family(OsFamily.CENTOS).version("6.0")
+ .description("CentOS 6.0 GUI (64-bit)").is64Bit(true)
+ .arch("paravirtual").build())
+ .description("CentOS 6.0 GUI (64-bit)")
+ .name("CentOS 6.0 GUI")
+ .defaultCredentials(new LoginCredentials("root", false))
+ .id("us-east-1/qmi-42e877f6")
+ .providerId("qmi-42e877f6")
+ .location(defaultLocation)
+ .userMetadata(
+ ImmutableMap.of("owner", "admin", "rootDeviceType", "ebs", "virtualizationType",
+ "paravirtual", "hypervisor", "xen"))
+ .status(org.jclouds.compute.domain.Image.Status.AVAILABLE).backendStatus("available").build().toString());
+ assertEquals(Iterables.get(result, 5).getStatus(), org.jclouds.compute.domain.Image.Status.AVAILABLE);
+
+ assertEquals(
+ Iterables.get(result, 6).toString(),
+ new ImageBuilder()
+ .operatingSystem(
+ OperatingSystem.builder().family(OsFamily.UBUNTU).version("11.04")
+ .description("Ubuntu Server 11.04 (64-bit)").is64Bit(true)
+ .arch("paravirtual").build())
+ .description("Ubuntu Server 11.04 (64-bit)")
+ .name("Ubuntu Server 11.04")
+ .defaultCredentials(new LoginCredentials("root", false))
+ .id("us-east-1/qmi-eed8cea7")
+ .providerId("qmi-eed8cea7")
+ .location(defaultLocation)
+ .userMetadata(
+ ImmutableMap.of("owner", "admin", "rootDeviceType", "ebs", "virtualizationType",
+ "paravirtual", "hypervisor", "xen"))
+ .status(org.jclouds.compute.domain.Image.Status.AVAILABLE).backendStatus("available").build().toString());
+ assertEquals(Iterables.get(result, 6).getStatus(), org.jclouds.compute.domain.Image.Status.AVAILABLE);
+
+ assertEquals(
+ Iterables.get(result, 7).toString(),
+ new ImageBuilder()
+ .operatingSystem(
+ // fedora is not in the image version map, yet
+ OperatingSystem.builder().family(OsFamily.FEDORA).version("")
+ .description("Fedora 16 Server").is64Bit(false)
+ .arch("paravirtual").build())
+ .description("Fedora 16 Server")
+ .name("Fedora 16 Server")
+ .defaultCredentials(new LoginCredentials("root", false))
+ .id("us-east-1/qmi-fa4bdae0")
+ .providerId("qmi-fa4bdae0")
+ .location(defaultLocation)
+ .userMetadata(
+ ImmutableMap.of("owner", "admin", "rootDeviceType", "ebs", "virtualizationType",
+ "paravirtual", "hypervisor", "xen"))
+ .status(org.jclouds.compute.domain.Image.Status.AVAILABLE).backendStatus("available").build().toString());
+ assertEquals(Iterables.get(result, 7).getStatus(), org.jclouds.compute.domain.Image.Status.AVAILABLE);
+
+ assertEquals(
+ Iterables.get(result, 8).toString(),
+ new ImageBuilder()
+ .operatingSystem(
+ OperatingSystem.builder().family(OsFamily.CENTOS).version("5.6")
+ .description("CentOS 5.6 Server GUI 64-bit").is64Bit(true)
+ .arch("paravirtual").build())
+ .description("CentOS 5.6 Server GUI 64-bit")
+ .name("CentOS 5.6 GUI")
+ .defaultCredentials(new LoginCredentials("root", false))
+ .id("us-east-1/qmi-93271d32")
+ .providerId("qmi-93271d32")
+ .location(defaultLocation)
+ .userMetadata(
+ ImmutableMap.of("owner", "admin", "rootDeviceType", "ebs", "virtualizationType",
+ "paravirtual", "hypervisor", "xen"))
+ .status(org.jclouds.compute.domain.Image.Status.AVAILABLE).backendStatus("available").build().toString());
+ assertEquals(Iterables.get(result, 8).getStatus(), org.jclouds.compute.domain.Image.Status.AVAILABLE);
+
+ }
+
+ static Location defaultLocation = new LocationBuilder().scope(LocationScope.REGION).id("us-east-1").description(
+ "us-east-1").build();
+
+ public static Set<org.jclouds.compute.domain.Image> convertImages(String resource) {
+
+ Map<OsFamily, Map<String, String>> map = new BaseComputeServiceContextModule() {
+ }.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice.createInjector(new GsonModule())
+ .getInstance(Json.class));
+
+ // note this method is what mandates the location id as us-east-1
+ Set<Image> result = DescribeImagesResponseHandlerTest.parseImages(resource);
+ EC2ImageParser parser = new EC2ImageParser(EC2ComputeServiceDependenciesModule.toPortableImageStatus,
+ new EC2PopulateDefaultLoginCredentialsForImageStrategy(), map, Suppliers
+ .<Set<? extends Location>> ofInstance(ImmutableSet.<Location> of(defaultLocation)), Suppliers
+ .ofInstance(defaultLocation), new GreenQloudComputeReviseParsedImage(map));
+ return Sets.newLinkedHashSet(Iterables.filter(Iterables.transform(result, parser), Predicates.notNull()));
+ }
+
+}
diff --git a/labs/greenqloud-compute/src/test/resources/greenqloud_images.xml b/labs/greenqloud-compute/src/test/resources/greenqloud_images.xml
new file mode 100644
index 0000000..8052445
--- /dev/null
+++ b/labs/greenqloud-compute/src/test/resources/greenqloud_images.xml
@@ -0,0 +1,257 @@
+<DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2010-06-15/">
+ <requestId>1c016525-12ae-4fc6-8d4e-754692412bbc</requestId>
+ <imagesSet>
+ <item>
+ <imageId>qmi-4e5b842f</imageId>
+ <imageLocation>Ubuntu Server 10.04 (64-bit)</imageLocation>
+ <imageState>available</imageState>
+ <imageOwnerId>admin</imageOwnerId>
+ <isPublic>true</isPublic>
+ <productCodes>
+ <item>
+ <productCode></productCode>
+ </item>
+ </productCodes>
+ <architecture></architecture>
+ <imageType>machine</imageType>
+ <kernelId></kernelId>
+ <ramdiskId></ramdiskId>
+ <platform></platform>
+ <stateReason>
+ <code></code>
+ <message></message>
+ </stateReason>
+ <imageOwnerAlias></imageOwnerAlias>
+ <name>Ubuntu Server 10.04.3</name>
+ <description>Ubuntu Server 10.04 (64-bit)</description>
+ <rootDeviceType>ebs</rootDeviceType>
+ <rootDeviceName></rootDeviceName>
+ <blockDeviceMapping />
+ <hypervisor>xen</hypervisor>
+ </item>
+ <item>
+ <imageId>qmi-9ac92558</imageId>
+ <imageLocation>Ubuntu Server 11.10 (64-bit)</imageLocation>
+ <imageState>available</imageState>
+ <imageOwnerId>admin</imageOwnerId>
+ <isPublic>true</isPublic>
+ <productCodes>
+ <item>
+ <productCode></productCode>
+ </item>
+ </productCodes>
+ <architecture></architecture>
+ <imageType>machine</imageType>
+ <kernelId></kernelId>
+ <ramdiskId></ramdiskId>
+ <platform></platform>
+ <stateReason>
+ <code></code>
+ <message></message>
+ </stateReason>
+ <imageOwnerAlias></imageOwnerAlias>
+ <name>Ubuntu Server 11.10</name>
+ <description>Ubuntu Server 11.10 (64-bit)</description>
+ <rootDeviceType>ebs</rootDeviceType>
+ <rootDeviceName></rootDeviceName>
+ <blockDeviceMapping />
+ <hypervisor>xen</hypervisor>
+ </item>
+ <item>
+ <imageId>qmi-33a467aa</imageId>
+ <imageLocation>CentOS 5.5 Server 64-bit</imageLocation>
+ <imageState>available</imageState>
+ <imageOwnerId>admin</imageOwnerId>
+ <isPublic>true</isPublic>
+ <productCodes>
+ <item>
+ <productCode></productCode>
+ </item>
+ </productCodes>
+ <architecture></architecture>
+ <imageType>machine</imageType>
+ <kernelId></kernelId>
+ <ramdiskId></ramdiskId>
+ <platform></platform>
+ <stateReason>
+ <code></code>
+ <message></message>
+ </stateReason>
+ <imageOwnerAlias></imageOwnerAlias>
+ <name>CentOS 5.5 Server</name>
+ <description>CentOS 5.5 Server 64-bit</description>
+ <rootDeviceType>ebs</rootDeviceType>
+ <rootDeviceName></rootDeviceName>
+ <blockDeviceMapping />
+ <hypervisor>xen</hypervisor>
+ </item>
+ <item>
+ <imageId>qmi-f2a9d2ba</imageId>
+ <imageLocation>Debian 6.0 (64-bit)</imageLocation>
+ <imageState>available</imageState>
+ <imageOwnerId>admin</imageOwnerId>
+ <isPublic>true</isPublic>
+ <productCodes>
+ <item>
+ <productCode></productCode>
+ </item>
+ </productCodes>
+ <architecture></architecture>
+ <imageType>machine</imageType>
+ <kernelId></kernelId>
+ <ramdiskId></ramdiskId>
+ <platform></platform>
+ <stateReason>
+ <code></code>
+ <message></message>
+ </stateReason>
+ <imageOwnerAlias></imageOwnerAlias>
+ <name>Debian 6.0</name>
+ <description>Debian 6.0 (64-bit)</description>
+ <rootDeviceType>ebs</rootDeviceType>
+ <rootDeviceName></rootDeviceName>
+ <blockDeviceMapping />
+ <hypervisor>xen</hypervisor>
+ </item>
+ <item>
+ <imageId>qmi-96f82145</imageId>
+ <imageLocation>CentOS 6.0 (64-bit)</imageLocation>
+ <imageState>available</imageState>
+ <imageOwnerId>admin</imageOwnerId>
+ <isPublic>true</isPublic>
+ <productCodes>
+ <item>
+ <productCode></productCode>
+ </item>
+ </productCodes>
+ <architecture></architecture>
+ <imageType>machine</imageType>
+ <kernelId></kernelId>
+ <ramdiskId></ramdiskId>
+ <platform></platform>
+ <stateReason>
+ <code></code>
+ <message></message>
+ </stateReason>
+ <imageOwnerAlias></imageOwnerAlias>
+ <name>CentOS 6.0</name>
+ <description>CentOS 6.0 (64-bit)</description>
+ <rootDeviceType>ebs</rootDeviceType>
+ <rootDeviceName></rootDeviceName>
+ <blockDeviceMapping />
+ <hypervisor>xen</hypervisor>
+ </item>
+ <item>
+ <imageId>qmi-42e877f6</imageId>
+ <imageLocation>CentOS 6.0 GUI (64-bit)</imageLocation>
+ <imageState>available</imageState>
+ <imageOwnerId>admin</imageOwnerId>
+ <isPublic>true</isPublic>
+ <productCodes>
+ <item>
+ <productCode></productCode>
+ </item>
+ </productCodes>
+ <architecture></architecture>
+ <imageType>machine</imageType>
+ <kernelId></kernelId>
+ <ramdiskId></ramdiskId>
+ <platform></platform>
+ <stateReason>
+ <code></code>
+ <message></message>
+ </stateReason>
+ <imageOwnerAlias></imageOwnerAlias>
+ <name>CentOS 6.0 GUI</name>
+ <description>CentOS 6.0 GUI (64-bit)</description>
+ <rootDeviceType>ebs</rootDeviceType>
+ <rootDeviceName></rootDeviceName>
+ <blockDeviceMapping />
+ <hypervisor>xen</hypervisor>
+ </item>
+ <item>
+ <imageId>qmi-eed8cea7</imageId>
+ <imageLocation>Ubuntu Server 11.04 (64-bit)</imageLocation>
+ <imageState>available</imageState>
+ <imageOwnerId>admin</imageOwnerId>
+ <isPublic>true</isPublic>
+ <productCodes>
+ <item>
+ <productCode></productCode>
+ </item>
+ </productCodes>
+ <architecture></architecture>
+ <imageType>machine</imageType>
+ <kernelId></kernelId>
+ <ramdiskId></ramdiskId>
+ <platform></platform>
+ <stateReason>
+ <code></code>
+ <message></message>
+ </stateReason>
+ <imageOwnerAlias></imageOwnerAlias>
+ <name>Ubuntu Server 11.04</name>
+ <description>Ubuntu Server 11.04 (64-bit)</description>
+ <rootDeviceType>ebs</rootDeviceType>
+ <rootDeviceName></rootDeviceName>
+ <blockDeviceMapping />
+ <hypervisor>xen</hypervisor>
+ </item>
+ <item>
+ <imageId>qmi-fa4bdae0</imageId>
+ <imageLocation>Fedora 16 Server</imageLocation>
+ <imageState>available</imageState>
+ <imageOwnerId>admin</imageOwnerId>
+ <isPublic>true</isPublic>
+ <productCodes>
+ <item>
+ <productCode></productCode>
+ </item>
+ </productCodes>
+ <architecture></architecture>
+ <imageType>machine</imageType>
+ <kernelId></kernelId>
+ <ramdiskId></ramdiskId>
+ <platform></platform>
+ <stateReason>
+ <code></code>
+ <message></message>
+ </stateReason>
+ <imageOwnerAlias></imageOwnerAlias>
+ <name>Fedora 16 Server</name>
+ <description>Fedora 16 Server</description>
+ <rootDeviceType>ebs</rootDeviceType>
+ <rootDeviceName></rootDeviceName>
+ <blockDeviceMapping />
+ <hypervisor>xen</hypervisor>
+ </item>
+ <item>
+ <imageId>qmi-93271d32</imageId>
+ <imageLocation>CentOS 5.6 Server GUI 64-bit</imageLocation>
+ <imageState>available</imageState>
+ <imageOwnerId>admin</imageOwnerId>
+ <isPublic>true</isPublic>
+ <productCodes>
+ <item>
+ <productCode></productCode>
+ </item>
+ </productCodes>
+ <architecture></architecture>
+ <imageType>machine</imageType>
+ <kernelId></kernelId>
+ <ramdiskId></ramdiskId>
+ <platform></platform>
+ <stateReason>
+ <code></code>
+ <message></message>
+ </stateReason>
+ <imageOwnerAlias></imageOwnerAlias>
+ <name>CentOS 5.6 GUI</name>
+ <description>CentOS 5.6 Server GUI 64-bit</description>
+ <rootDeviceType>ebs</rootDeviceType>
+ <rootDeviceName></rootDeviceName>
+ <blockDeviceMapping />
+ <hypervisor>xen</hypervisor>
+ </item>
+ </imagesSet>
+</DescribeImagesResponse>
\ No newline at end of file
diff --git a/labs/greenqloud-storage/pom.xml b/labs/greenqloud-storage/pom.xml
new file mode 100644
index 0000000..f9e9759
--- /dev/null
+++ b/labs/greenqloud-storage/pom.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to jclouds, Inc. (jclouds) under one or more
+ contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. jclouds 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-project</artifactId>
+ <version>1.5.0-SNAPSHOT</version>
+ <relativePath>../../project/pom.xml</relativePath>
+ </parent>
+ <groupId>org.jclouds.labs</groupId>
+ <artifactId>greenqloud-storage</artifactId>
+ <name>jclouds GreenQloud Simple Storage Service (S3) provider</name>
+ <description>Simple Storage Service (S3) implementation targeted to GreenQloud Web Services</description>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <test.greenqloud-storage.endpoint>https://s.greenqloud.com</test.greenqloud-storage.endpoint>
+ <test.greenqloud-storage.api-version>2006-03-01</test.greenqloud-storage.api-version>
+ <test.greenqloud-storage.build-version></test.greenqloud-storage.build-version>
+ <test.greenqloud-storage.identity>${test.greenqloud.identity}</test.greenqloud-storage.identity>
+ <test.greenqloud-storage.credential>${test.greenqloud.credential}</test.greenqloud-storage.credential>
+ <jclouds.osgi.export>org.jclouds.greenqloud.storage*;version="${project.version}"</jclouds.osgi.export>
+ <jclouds.osgi.import>
+ org.jclouds*;version="${project.version}",
+ *
+ </jclouds.osgi.import>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jclouds.api</groupId>
+ <artifactId>s3</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-blobstore</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.api</groupId>
+ <artifactId>s3</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.driver</groupId>
+ <artifactId>jclouds-log4j</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.16</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>live</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>integration</id>
+ <phase>integration-test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <systemPropertyVariables>
+ <test.greenqloud-storage.endpoint>${test.greenqloud-storage.endpoint}</test.greenqloud-storage.endpoint>
+ <test.greenqloud-storage.api-version>${test.greenqloud-storage.api-version}</test.greenqloud-storage.api-version>
+ <test.greenqloud-storage.build-version>${test.greenqloud-storage.build-version}</test.greenqloud-storage.build-version>
+ <test.greenqloud-storage.identity>${test.greenqloud-storage.identity}</test.greenqloud-storage.identity>
+ <test.greenqloud-storage.credential>${test.greenqloud-storage.credential}</test.greenqloud-storage.credential>
+ <jclouds.blobstore.httpstream.url>${jclouds.blobstore.httpstream.url}</jclouds.blobstore.httpstream.url>
+ <jclouds.blobstore.httpstream.md5>${jclouds.blobstore.httpstream.md5}</jclouds.blobstore.httpstream.md5>
+ </systemPropertyVariables>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/labs/greenqloud-storage/src/main/java/org/jclouds/greenqloud/storage/GreenQloudStorageProviderMetadata.java b/labs/greenqloud-storage/src/main/java/org/jclouds/greenqloud/storage/GreenQloudStorageProviderMetadata.java
new file mode 100644
index 0000000..e6e9c009
--- /dev/null
+++ b/labs/greenqloud-storage/src/main/java/org/jclouds/greenqloud/storage/GreenQloudStorageProviderMetadata.java
@@ -0,0 +1,94 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.greenqloud.storage;
+
+import static org.jclouds.location.reference.LocationConstants.ENDPOINT;
+import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadata;
+import org.jclouds.s3.S3ApiMetadata;
+
+/**
+ * Implementation of {@link org.jclouds.providers.ProviderMetadata} for GreenQloud Simple Storage Service (S3).
+ *
+ * @author Adrian Cole
+ */
+public class GreenQloudStorageProviderMetadata extends BaseProviderMetadata {
+
+ /** The serialVersionUID */
+ private static final long serialVersionUID = 1L;
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return builder().fromProviderMetadata(this);
+ }
+
+ public GreenQloudStorageProviderMetadata() {
+ super(builder());
+ }
+
+ public GreenQloudStorageProviderMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = new Properties();
+ properties.setProperty(PROPERTY_REGIONS, "is-1");
+ properties.setProperty(PROPERTY_REGION + ".is-1." + ISO3166_CODES, "IS-1");
+ properties.setProperty(PROPERTY_REGION + "." + "is-1" + "." + ENDPOINT, "https://s.greenqloud.com");
+ return properties;
+ }
+
+ public static class Builder extends BaseProviderMetadata.Builder {
+
+ protected Builder(){
+ id("greenqloud-storage")
+ .name("GreenQloud Simple Storage Service (S3)")
+ .apiMetadata(new S3ApiMetadata())
+ .homepage(URI.create("http://www.greenqloud.com"))
+ .console(URI.create("https://manage.greenqloud.com"))
+ .linkedServices("greenqloud-compute", "greenqloud-storage")
+ .iso3166Codes("IS-1")
+ .endpoint("https://s.greenqloud.com")
+ .defaultProperties(GreenQloudStorageProviderMetadata.defaultProperties());
+ }
+
+ @Override
+ public GreenQloudStorageProviderMetadata build() {
+ return new GreenQloudStorageProviderMetadata(this);
+ }
+
+ @Override
+ public Builder fromProviderMetadata(
+ ProviderMetadata in) {
+ super.fromProviderMetadata(in);
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/labs/greenqloud-storage/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/labs/greenqloud-storage/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
new file mode 100644
index 0000000..a51135a
--- /dev/null
+++ b/labs/greenqloud-storage/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
@@ -0,0 +1 @@
+org.jclouds.greenqloud.storage.GreenQloudStorageProviderMetadata
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/GreenQloudStorageClientLiveTest.java
similarity index 63%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/GreenQloudStorageClientLiveTest.java
index 771a1be..d6329aa 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/GreenQloudStorageClientLiveTest.java
@@ -16,13 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.greenqloud.storage;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.s3.S3ClientLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
-
- void startPool() throws RunNodesException;
-
+/**
+ * Tests behavior of {@code S3Client}
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "GreenQloudStorageClientLiveTest")
+public class GreenQloudStorageClientLiveTest extends S3ClientLiveTest {
+ public GreenQloudStorageClientLiveTest() {
+ provider = "greenqloud-storage";
+ }
}
diff --git a/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/GreenQloudStorageProviderTest.java b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/GreenQloudStorageProviderTest.java
new file mode 100644
index 0000000..93a6153
--- /dev/null
+++ b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/GreenQloudStorageProviderTest.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.greenqloud.storage;
+
+import org.jclouds.providers.internal.BaseProviderMetadataTest;
+import org.jclouds.s3.S3ApiMetadata;
+import org.testng.annotations.Test;
+
+/**
+ * The GreenQloudStorageProviderTest tests the {@link GreenQloudStorageProviderMetadata} class.
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "GreenQloudStorageProviderTest")
+public class GreenQloudStorageProviderTest extends BaseProviderMetadataTest {
+
+ public GreenQloudStorageProviderTest() {
+ super(new GreenQloudStorageProviderMetadata(), new S3ApiMetadata());
+ }
+
+}
\ No newline at end of file
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobIntegrationLiveTest.java
similarity index 63%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobIntegrationLiveTest.java
index 771a1be..8a0d4bb 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobIntegrationLiveTest.java
@@ -16,13 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.greenqloud.storage.blobstore;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.s3.blobstore.integration.S3BlobIntegrationLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "GreenQloudStorageBlobIntegrationLiveTest")
+public class GreenQloudStorageBlobIntegrationLiveTest extends S3BlobIntegrationLiveTest {
- void startPool() throws RunNodesException;
-
+ public GreenQloudStorageBlobIntegrationLiveTest() {
+ provider = "greenqloud-storage";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobLiveTest.java
similarity index 66%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobLiveTest.java
index 771a1be..6a69b15 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobLiveTest.java
@@ -16,13 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.greenqloud.storage.blobstore;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.s3.blobstore.integration.S3BlobLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "GreenQloudStorageBlobLiveTest")
+public class GreenQloudStorageBlobLiveTest extends S3BlobLiveTest {
- void startPool() throws RunNodesException;
-
+ public GreenQloudStorageBlobLiveTest() {
+ provider = "greenqloud-storage";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobMapIntegrationLiveTest.java
similarity index 62%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobMapIntegrationLiveTest.java
index 771a1be..d405dee 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobMapIntegrationLiveTest.java
@@ -16,13 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.greenqloud.storage.blobstore;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.s3.blobstore.integration.S3BlobMapIntegrationLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "GreenQloudStorageBlobMapIntegrationLiveTest")
+public class GreenQloudStorageBlobMapIntegrationLiveTest extends S3BlobMapIntegrationLiveTest {
- void startPool() throws RunNodesException;
-
+ public GreenQloudStorageBlobMapIntegrationLiveTest() {
+ provider = "greenqloud-storage";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobSignerLiveTest.java
similarity index 64%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobSignerLiveTest.java
index 771a1be..32cbba3 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageBlobSignerLiveTest.java
@@ -16,13 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.greenqloud.storage.blobstore;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.s3.blobstore.integration.S3BlobSignerLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
+/**
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "GreenQloudStorageBlobSignerLiveTest")
+public class GreenQloudStorageBlobSignerLiveTest extends S3BlobSignerLiveTest {
- void startPool() throws RunNodesException;
-
+ public GreenQloudStorageBlobSignerLiveTest() {
+ provider = "greenqloud-storage";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageContainerIntegrationLiveTest.java
similarity index 61%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageContainerIntegrationLiveTest.java
index 771a1be..563a27e 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageContainerIntegrationLiveTest.java
@@ -16,13 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.greenqloud.storage.blobstore;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.s3.blobstore.integration.S3ContainerIntegrationLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "GreenQloudStorageContainerIntegrationLiveTest")
+public class GreenQloudStorageContainerIntegrationLiveTest extends S3ContainerIntegrationLiveTest {
- void startPool() throws RunNodesException;
-
+ public GreenQloudStorageContainerIntegrationLiveTest() {
+ provider = "greenqloud-storage";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageContainerLiveTest.java
similarity index 64%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageContainerLiveTest.java
index 771a1be..4453084 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageContainerLiveTest.java
@@ -16,13 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.greenqloud.storage.blobstore;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.s3.blobstore.integration.S3ContainerLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "GreenQloudStorageContainerLiveTest")
+public class GreenQloudStorageContainerLiveTest extends S3ContainerLiveTest {
- void startPool() throws RunNodesException;
-
+ public GreenQloudStorageContainerLiveTest() {
+ provider = "greenqloud-storage";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageInputStreamMapIntegrationLiveTest.java
similarity index 60%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageInputStreamMapIntegrationLiveTest.java
index 771a1be..611b739 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageInputStreamMapIntegrationLiveTest.java
@@ -16,13 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.greenqloud.storage.blobstore;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.s3.blobstore.integration.S3InputStreamMapIntegrationLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "GreenQloudStorageInputStreamMapIntegrationLiveTest")
+public class GreenQloudStorageInputStreamMapIntegrationLiveTest extends
+ S3InputStreamMapIntegrationLiveTest {
- void startPool() throws RunNodesException;
-
+ public GreenQloudStorageInputStreamMapIntegrationLiveTest() {
+ provider = "greenqloud-storage";
+ }
}
diff --git a/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageServiceIntegrationLiveTest.java b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageServiceIntegrationLiveTest.java
new file mode 100644
index 0000000..7ea1a5f
--- /dev/null
+++ b/labs/greenqloud-storage/src/test/java/org/jclouds/greenqloud/storage/blobstore/GreenQloudStorageServiceIntegrationLiveTest.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.greenqloud.storage.blobstore;
+
+import java.util.Set;
+
+import org.jclouds.s3.blobstore.integration.S3ServiceIntegrationLiveTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "GreenQloudStorageServiceIntegrationLiveTest")
+public class GreenQloudStorageServiceIntegrationLiveTest extends S3ServiceIntegrationLiveTest {
+
+ public GreenQloudStorageServiceIntegrationLiveTest() {
+ provider = "greenqloud-storage";
+ }
+
+ @Override
+ protected Set<String> getIso3166Codes() {
+ return ImmutableSet.<String> of("IS-1");
+ }
+
+}
diff --git a/labs/joyent-sdc/pom.xml b/labs/joyent-sdc/pom.xml
index 4dd22ef..e307093 100644
--- a/labs/joyent-sdc/pom.xml
+++ b/labs/joyent-sdc/pom.xml
@@ -50,11 +50,18 @@
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
- <artifactId>jclouds-core</artifactId>
+ <artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
+ <artifactId>jclouds-compute</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
@@ -67,6 +74,12 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.jclouds.driver</groupId>
+ <artifactId>jclouds-sshj</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.0</version>
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCApiMetadata.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCApiMetadata.java
index 3182b60..e9679e8 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCApiMetadata.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCApiMetadata.java
@@ -22,6 +22,10 @@
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.joyent.sdc.v6_5.compute.config.SDCComputeServiceContextModule;
+import org.jclouds.joyent.sdc.v6_5.config.DatacentersAreZonesModule;
+import org.jclouds.joyent.sdc.v6_5.config.SDCProperties;
import org.jclouds.joyent.sdc.v6_5.config.SDCRestClientModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
@@ -59,6 +63,7 @@
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
+ properties.setProperty(SDCProperties.AUTOGENERATE_KEYS, "true");
return properties;
}
@@ -66,10 +71,16 @@
protected Builder() {
super(SDCClient.class, SDCAsyncClient.class);
- id("joyent-sdc").name("Joyent SDC API").identityName("username").credentialName("password")
- .documentation(URI.create("http://sdc.joyent.org/sdcapi.html")).version("~6.5")
- .defaultEndpoint("https://api.joyentcloud.com").defaultProperties(SDCApiMetadata.defaultProperties())
- .defaultModules(ImmutableSet.<Class<? extends Module>> of(SDCRestClientModule.class));
+ id("joyent-sdc")
+ .name("Joyent SDC API")
+ .identityName("username")
+ .credentialName("password")
+ .documentation(URI.create("http://sdc.joyent.org/sdcapi.html"))
+ .version("~6.5")
+ .defaultEndpoint("https://api.joyentcloud.com")
+ .defaultProperties(SDCApiMetadata.defaultProperties())
+ .view(TypeToken.of(ComputeServiceContext.class))
+ .defaultModules(ImmutableSet.<Class<? extends Module>> of(DatacentersAreZonesModule.class, SDCRestClientModule.class, SDCComputeServiceContextModule.class));
}
@Override
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCAsyncClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCAsyncClient.java
index 7a15079..f6b24b6 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCAsyncClient.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCAsyncClient.java
@@ -18,11 +18,20 @@
*/
package org.jclouds.joyent.sdc.v6_5;
+import java.util.Set;
+
+import org.jclouds.javax.annotation.Nullable;
import org.jclouds.joyent.sdc.v6_5.features.DatacenterAsyncClient;
import org.jclouds.joyent.sdc.v6_5.features.DatasetAsyncClient;
+import org.jclouds.joyent.sdc.v6_5.features.KeyAsyncClient;
import org.jclouds.joyent.sdc.v6_5.features.MachineAsyncClient;
import org.jclouds.joyent.sdc.v6_5.features.PackageAsyncClient;
+import org.jclouds.location.Zone;
+import org.jclouds.location.functions.ZoneToEndpoint;
import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.EndpointParam;
+
+import com.google.inject.Provides;
/**
* Provides asynchronous access to SDC via their REST API.
@@ -33,7 +42,15 @@
* @author Adrian Cole
*/
public interface SDCAsyncClient {
-
+
+ /**
+ *
+ * @return the datacenter codes configured
+ */
+ @Provides
+ @Zone
+ Set<String> getConfiguredDatacenters();
+
/**
* Provides asynchronous access to Datacenter features.
*/
@@ -41,20 +58,29 @@
DatacenterAsyncClient getDatacenterClient();
/**
+ * Provides asynchronous access to Key features.
+ */
+ @Delegate
+ KeyAsyncClient getKeyClient();
+
+ /**
* Provides asynchronous access to Machine features.
*/
@Delegate
- MachineAsyncClient getMachineClient();
+ MachineAsyncClient getMachineClientForDatacenter(
+ @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String datacenter);
/**
* Provides asynchronous access to Dataset features.
*/
@Delegate
- DatasetAsyncClient getDatasetClient();
+ DatasetAsyncClient getDatasetClientForDatacenter(
+ @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String datacenter);
/**
* Provides asynchronous access to Package features.
*/
@Delegate
- PackageAsyncClient getPackageClient();
+ PackageAsyncClient getPackageClientForDatacenter(
+ @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String datacenter);
}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCClient.java
index e0488fd..fca489b 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCClient.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCClient.java
@@ -18,14 +18,22 @@
*/
package org.jclouds.joyent.sdc.v6_5;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
+import org.jclouds.javax.annotation.Nullable;
import org.jclouds.joyent.sdc.v6_5.features.DatacenterClient;
import org.jclouds.joyent.sdc.v6_5.features.DatasetClient;
+import org.jclouds.joyent.sdc.v6_5.features.KeyClient;
import org.jclouds.joyent.sdc.v6_5.features.MachineClient;
import org.jclouds.joyent.sdc.v6_5.features.PackageClient;
+import org.jclouds.location.Zone;
+import org.jclouds.location.functions.ZoneToEndpoint;
import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.EndpointParam;
+
+import com.google.inject.Provides;
/**
* Provides synchronous access to SDC.
@@ -39,26 +47,43 @@
public interface SDCClient {
/**
+ *
+ * @return the datacenter codes configured
+ */
+ @Provides
+ @Zone
+ Set<String> getConfiguredDatacenters();
+
+ /**
* Provides synchronous access to Datacenter features.
*/
@Delegate
DatacenterClient getDatacenterClient();
-
+
+ /**
+ * Provides synchronous access to Key features.
+ */
+ @Delegate
+ KeyClient getKeyClient();
+
/**
* Provides synchronous access to Machine features.
*/
@Delegate
- MachineClient getMachineClient();
+ MachineClient getMachineClientForDatacenter(
+ @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String datacenter);
/**
* Provides synchronous access to Dataset features.
*/
@Delegate
- DatasetClient getDatasetClient();
+ DatasetClient getDatasetClientForDatacenter(
+ @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String datacenter);
/**
* Provides synchronous access to Package features.
*/
@Delegate
- PackageClient getPackageClient();
+ PackageClient getPackageClientForDatacenter(
+ @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String datacenter);
}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/binders/BindKeyToJsonPayload.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/binders/BindKeyToJsonPayload.java
new file mode 100644
index 0000000..15dc5e6
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/binders/BindKeyToJsonPayload.java
@@ -0,0 +1,54 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.binders;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+import org.jclouds.json.Json;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+/**
+ *
+ * @author Adrian Cole
+ *
+ */
+@Singleton
+public class BindKeyToJsonPayload extends BindToJsonPayload {
+ @Inject
+ public BindKeyToJsonPayload(Json jsonBinder) {
+ super(jsonBinder);
+ }
+
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
+ // don't include created in the http request
+ return super.bindToRequest(request, Key.class.cast(toBind).toBuilder().created(null).build());
+ }
+
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
+ throw new IllegalStateException("This should be assigned only a single arg");
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/SDCComputeService.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/SDCComputeService.java
new file mode 100644
index 0000000..e6e4cc9
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/SDCComputeService.java
@@ -0,0 +1,153 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.jclouds.Constants;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.callables.RunScriptOnNode;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.extensions.ImageExtension;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.internal.BaseComputeService;
+import org.jclouds.compute.internal.PersistNodeCredentials;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
+import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
+import org.jclouds.compute.strategy.DestroyNodeStrategy;
+import org.jclouds.compute.strategy.GetImageStrategy;
+import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
+import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
+import org.jclouds.compute.strategy.ListNodesStrategy;
+import org.jclouds.compute.strategy.RebootNodeStrategy;
+import org.jclouds.compute.strategy.ResumeNodeStrategy;
+import org.jclouds.compute.strategy.SuspendNodeStrategy;
+import org.jclouds.domain.Credentials;
+import org.jclouds.domain.Location;
+import org.jclouds.joyent.sdc.v6_5.SDCClient;
+import org.jclouds.joyent.sdc.v6_5.compute.internal.KeyAndPrivateKey;
+import org.jclouds.joyent.sdc.v6_5.compute.options.SDCTemplateOptions;
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatacenterAndName;
+import org.jclouds.joyent.sdc.v6_5.features.KeyClient;
+import org.jclouds.joyent.sdc.v6_5.predicates.KeyPredicates;
+import org.jclouds.scriptbuilder.functions.InitAdminAccess;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+
+/**
+ * @author Adrian Cole
+ */
+@Singleton
+public class SDCComputeService extends BaseComputeService {
+ protected final SDCClient novaClient;
+ protected final LoadingCache<DatacenterAndName, KeyAndPrivateKey> keyCache;
+ protected final Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByDatacenterId;
+ protected final GroupNamingConvention.Factory namingConvention;
+
+ @Inject
+ protected SDCComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
+ @Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
+ @Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
+ GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
+ CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
+ DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy,
+ SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
+ Provider<TemplateOptions> templateOptionsProvider,
+ @Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
+ @Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
+ @Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
+ InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
+ RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
+ PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
+ @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, SDCClient novaClient,
+ LoadingCache<DatacenterAndName, KeyAndPrivateKey> keyCache,
+ Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByDatacenterId,
+ GroupNamingConvention.Factory namingConvention, Optional<ImageExtension> imageExtension) {
+ super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
+ getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
+ startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
+ nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
+ persistNodeCredentials, timeouts, executor, imageExtension);
+ this.novaClient = checkNotNull(novaClient, "novaClient");
+ this.keyCache = checkNotNull(keyCache, "keyCache");
+ this.orphanedGroupsByDatacenterId = checkNotNull(orphanedGroupsByDatacenterId, "orphanedGroupsByDatacenterId");
+ this.namingConvention = checkNotNull(namingConvention, "namingConvention");
+ }
+
+ @Override
+ protected void cleanUpIncidentalResourcesOfDeadNodes(Set<? extends NodeMetadata> deadNodes) {
+ Multimap<String, String> zoneToZoneAndGroupNames = orphanedGroupsByDatacenterId.apply(deadNodes);
+ for (String datacenterId : zoneToZoneAndGroupNames.keySet()) {
+ cleanupOrphanedKeysInZone(ImmutableSet.copyOf(zoneToZoneAndGroupNames.get(datacenterId)), datacenterId);
+ }
+ }
+
+ private void cleanupOrphanedKeysInZone(Set<String> groups, String datacenterId) {
+ KeyClient keyClient = novaClient.getKeyClient();
+ for (String group : groups) {
+ for (Key key : Iterables.filter(keyClient.list(),
+ KeyPredicates.nameMatches(namingConvention.create().containsGroup(group)))) {
+ DatacenterAndName datacenterAndName = DatacenterAndName.fromDatacenterAndName(datacenterId, key.getName());
+ logger.debug(">> deleting key(%s)", datacenterAndName);
+ keyClient.delete(key.getName());
+ // TODO: test this clear happens
+ keyCache.invalidate(datacenterAndName);
+ logger.debug("<< deleted key(%s)", datacenterAndName);
+ }
+
+ keyCache.invalidate(DatacenterAndName.fromDatacenterAndName(datacenterId, namingConvention.create()
+ .sharedNameForGroup(group)));
+ }
+ }
+
+ /**
+ * returns template options, except of type {@link SDCTemplateOptions}.
+ */
+ @Override
+ public SDCTemplateOptions templateOptions() {
+ return SDCTemplateOptions.class.cast(super.templateOptions());
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/SDCComputeServiceAdapter.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/SDCComputeServiceAdapter.java
new file mode 100644
index 0000000..97ce63f
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/SDCComputeServiceAdapter.java
@@ -0,0 +1,203 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.transform;
+import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
+
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.joyent.sdc.v6_5.SDCClient;
+import org.jclouds.joyent.sdc.v6_5.domain.Dataset;
+import org.jclouds.joyent.sdc.v6_5.domain.Machine;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatacenterAndId;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatasetInDatacenter;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.MachineInDatacenter;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.PackageInDatacenter;
+import org.jclouds.joyent.sdc.v6_5.options.CreateMachineOptions;
+import org.jclouds.location.Zone;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+
+/**
+ * The adapter used by the SDCComputeServiceContextModule to interface the
+ * SDC-specific domain model to the computeService generic domain model.
+ *
+ * @author Adrian Cole
+ */
+public class SDCComputeServiceAdapter implements
+ ComputeServiceAdapter<MachineInDatacenter, PackageInDatacenter, DatasetInDatacenter, Location> {
+
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ protected final SDCClient sdcClient;
+ protected final Supplier<Set<String>> datacenterIds;
+
+ @Inject
+ public SDCComputeServiceAdapter(SDCClient sdcClient, @Zone Supplier<Set<String>> datacenterIds) {
+ this.sdcClient = checkNotNull(sdcClient, "sdcClient");
+ this.datacenterIds = checkNotNull(datacenterIds, "datacenterIds");
+ }
+
+ @Override
+ public NodeAndInitialCredentials<MachineInDatacenter> createNodeWithGroupEncodedIntoName(String group, String name,
+ Template template) {
+
+ LoginCredentials.Builder credentialsBuilder = LoginCredentials.builder();
+
+ CreateMachineOptions options = new CreateMachineOptions();
+ options.name(name);
+ options.packageName(template.getHardware().getProviderId());
+ options.metadata(metadataAndTagsAsCommaDelimitedValue(template.getOptions()));
+
+ String datacenterId = template.getLocation().getId();
+ String datasetURN = template.getImage().getProviderId();
+
+ logger.debug(">> creating new machine datacenter(%s) datasetURN(%s) options(%s)", datacenterId, datasetURN,
+ options);
+ Machine machine = sdcClient.getMachineClientForDatacenter(datacenterId).createWithDataset(datasetURN, options);
+
+ logger.trace("<< machine(%s)", machine.getId());
+
+ MachineInDatacenter machineInDatacenter = new MachineInDatacenter(machine, datacenterId);
+
+ //TODO machineInDatacenter.metadata for password
+ if (template.getOptions().getLoginPrivateKey() != null){
+ credentialsBuilder.privateKey(template.getOptions().getLoginPrivateKey());
+ }
+ return new NodeAndInitialCredentials<MachineInDatacenter>(machineInDatacenter, machineInDatacenter.slashEncode(),
+ credentialsBuilder.build());
+ }
+
+ @Override
+ public Iterable<PackageInDatacenter> listHardwareProfiles() {
+ Builder<PackageInDatacenter> builder = ImmutableSet.builder();
+ for (final String datacenterId : datacenterIds.get()) {
+ builder.addAll(transform(sdcClient.getPackageClientForDatacenter(datacenterId).list(),
+ new Function<org.jclouds.joyent.sdc.v6_5.domain.Package, PackageInDatacenter>() {
+
+ @Override
+ public PackageInDatacenter apply(org.jclouds.joyent.sdc.v6_5.domain.Package arg0) {
+ return new PackageInDatacenter(arg0, datacenterId);
+ }
+
+ }));
+ }
+ return builder.build();
+ }
+
+ @Override
+ public Iterable<DatasetInDatacenter> listImages() {
+ Builder<DatasetInDatacenter> builder = ImmutableSet.builder();
+ for (final String datacenterId : datacenterIds.get()) {
+ builder.addAll(transform(sdcClient.getDatasetClientForDatacenter(datacenterId).list(),
+ new Function<Dataset, DatasetInDatacenter>() {
+
+ @Override
+ public DatasetInDatacenter apply(Dataset arg0) {
+ return new DatasetInDatacenter(arg0, datacenterId);
+ }
+
+ }));
+ }
+ return builder.build();
+ }
+
+ @Override
+ public Iterable<MachineInDatacenter> listNodes() {
+ Builder<MachineInDatacenter> builder = ImmutableSet.builder();
+ for (final String datacenterId : datacenterIds.get()) {
+ builder.addAll(transform(sdcClient.getMachineClientForDatacenter(datacenterId).list(),
+ new Function<Machine, MachineInDatacenter>() {
+
+ @Override
+ public MachineInDatacenter apply(Machine arg0) {
+ return new MachineInDatacenter(arg0, datacenterId);
+ }
+
+ }));
+ }
+ return builder.build();
+ }
+
+ @Override
+ public Iterable<Location> listLocations() {
+ // locations provided by guice
+ return ImmutableSet.of();
+ }
+
+ @Override
+ public MachineInDatacenter getNode(String id) {
+ DatacenterAndId datacenterAndId = DatacenterAndId.fromSlashEncoded(id);
+ Machine machine = sdcClient.getMachineClientForDatacenter(datacenterAndId.getDatacenter()).get(
+ datacenterAndId.getId());
+ return machine == null ? null : new MachineInDatacenter(machine, datacenterAndId.getDatacenter());
+ }
+
+ @Override
+ public DatasetInDatacenter getImage(String id) {
+ DatacenterAndId datacenterAndId = DatacenterAndId.fromSlashEncoded(id);
+ Dataset dataset = sdcClient.getDatasetClientForDatacenter(datacenterAndId.getDatacenter()).get(
+ datacenterAndId.getId());
+ return dataset == null ? null : new DatasetInDatacenter(dataset, datacenterAndId.getDatacenter());
+ }
+
+ @Override
+ public void destroyNode(String id) {
+ DatacenterAndId datacenterAndId = DatacenterAndId.fromSlashEncoded(id);
+ sdcClient.getMachineClientForDatacenter(datacenterAndId.getDatacenter()).delete(datacenterAndId.getId());
+ }
+
+ @Override
+ public void rebootNode(String id) {
+ DatacenterAndId datacenterAndId = DatacenterAndId.fromSlashEncoded(id);
+ sdcClient.getMachineClientForDatacenter(datacenterAndId.getDatacenter()).reboot(datacenterAndId.getId());
+ }
+
+ @Override
+ public void resumeNode(String id) {
+ DatacenterAndId datacenterAndId = DatacenterAndId.fromSlashEncoded(id);
+ sdcClient.getMachineClientForDatacenter(datacenterAndId.getDatacenter()).stop(datacenterAndId.getId());
+
+ }
+
+ @Override
+ public void suspendNode(String id) {
+ DatacenterAndId datacenterAndId = DatacenterAndId.fromSlashEncoded(id);
+ sdcClient.getMachineClientForDatacenter(datacenterAndId.getDatacenter()).start(datacenterAndId.getId());
+
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/config/SDCComputeServiceContextModule.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/config/SDCComputeServiceContextModule.java
new file mode 100644
index 0000000..b8c5a29
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/config/SDCComputeServiceContextModule.java
@@ -0,0 +1,177 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.config;
+
+import static org.jclouds.joyent.sdc.v6_5.config.SDCProperties.AUTOGENERATE_KEYS;
+
+import java.security.SecureRandom;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
+import org.jclouds.domain.Location;
+import org.jclouds.functions.IdentityFunction;
+import org.jclouds.joyent.sdc.v6_5.compute.SDCComputeService;
+import org.jclouds.joyent.sdc.v6_5.compute.SDCComputeServiceAdapter;
+import org.jclouds.joyent.sdc.v6_5.compute.functions.DatasetInDatacenterToImage;
+import org.jclouds.joyent.sdc.v6_5.compute.functions.DatasetToOperatingSystem;
+import org.jclouds.joyent.sdc.v6_5.compute.functions.MachineInDatacenterToNodeMetadata;
+import org.jclouds.joyent.sdc.v6_5.compute.functions.OrphanedGroupsByDatacenterId;
+import org.jclouds.joyent.sdc.v6_5.compute.functions.PackageInDatacenterToHardware;
+import org.jclouds.joyent.sdc.v6_5.compute.internal.KeyAndPrivateKey;
+import org.jclouds.joyent.sdc.v6_5.compute.loaders.CreateUniqueKey;
+import org.jclouds.joyent.sdc.v6_5.compute.options.SDCTemplateOptions;
+import org.jclouds.joyent.sdc.v6_5.compute.strategy.ApplySDCTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet;
+import org.jclouds.joyent.sdc.v6_5.domain.Dataset;
+import org.jclouds.joyent.sdc.v6_5.domain.Machine;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatacenterAndName;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatasetInDatacenter;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.MachineInDatacenter;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.PackageInDatacenter;
+import org.jclouds.util.Iterables2;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.inject.Injector;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
+
+/**
+ * Module for building a compute service context for SDC
+ *
+ * @author Adrian Cole
+ */
+public class SDCComputeServiceContextModule extends
+ ComputeServiceAdapterContextModule<MachineInDatacenter, PackageInDatacenter, DatasetInDatacenter, Location> {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void configure() {
+ super.configure();
+ bind(
+ new TypeLiteral<ComputeServiceAdapter<MachineInDatacenter, PackageInDatacenter, DatasetInDatacenter, Location>>() {
+ }).to(SDCComputeServiceAdapter.class);
+
+ bind(new TypeLiteral<Function<MachineInDatacenter, NodeMetadata>>() {
+ }).to(MachineInDatacenterToNodeMetadata.class);
+
+ bind(new TypeLiteral<Function<DatasetInDatacenter, Image>>() {
+ }).to(DatasetInDatacenterToImage.class);
+ bind(new TypeLiteral<Function<Dataset, OperatingSystem>>() {
+ }).to(DatasetToOperatingSystem.class);
+
+ bind(new TypeLiteral<Function<PackageInDatacenter, Hardware>>() {
+ }).to(PackageInDatacenterToHardware.class);
+
+ // we aren't converting location from a provider-specific type
+ bind(new TypeLiteral<Function<Location, Location>>() {
+ }).to(Class.class.cast(IdentityFunction.class));
+
+ // how to figure out if a group in a datacenter is no longer in use
+ bind(new TypeLiteral<Function<Set<? extends NodeMetadata>, Multimap<String, String>>>() {
+ }).to(OrphanedGroupsByDatacenterId.class);
+
+ bind(ComputeService.class).to(SDCComputeService.class);
+ bind(TemplateOptions.class).to(SDCTemplateOptions.class);
+
+ bind(CreateNodesWithGroupEncodedIntoNameThenAddToSet.class).to(
+ ApplySDCTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.class);
+
+ bind(new TypeLiteral<CacheLoader<DatacenterAndName, KeyAndPrivateKey>>() {
+ }).to(CreateUniqueKey.class);
+ }
+
+ @Override
+ protected TemplateOptions provideTemplateOptions(Injector injector, TemplateOptions options) {
+ return options.as(SDCTemplateOptions.class)
+ .generateKey(injector.getInstance(
+ com.google.inject.Key.get(boolean.class, Names.named(AUTOGENERATE_KEYS))));
+ }
+
+ @Provides
+ @Singleton
+ protected LoadingCache<DatacenterAndName, KeyAndPrivateKey> keyMap(
+ CacheLoader<DatacenterAndName, KeyAndPrivateKey> in) {
+ return CacheBuilder.newBuilder().build(in);
+ }
+ @Provides
+ @Singleton
+ protected Supplier<Map<String, Location>> createLocationIndexedById(
+ @Memoized Supplier<Set<? extends Location>> locations) {
+ return Suppliers.compose(new Function<Set<? extends Location>, Map<String, Location>>() {
+
+ @Override
+ public Map<String, Location> apply(Set<? extends Location> arg0) {
+ return Maps.uniqueIndex(Iterables2.concreteCopy(arg0), new Function<Location, String>() {
+
+ @Override
+ public String apply(Location arg0) {
+ return arg0.getId();
+ }
+
+ });
+ }
+ }, locations);
+
+ }
+
+ @Provides
+ @Singleton
+ protected SecureRandom provideSecureRandom() {
+ return new SecureRandom();
+ }
+
+ @VisibleForTesting
+ public static final Map<Machine.State, NodeMetadata.Status> toPortableNodeStatus = ImmutableMap
+ .<Machine.State, NodeMetadata.Status> builder()
+ .put(Machine.State.PROVISIONING, NodeMetadata.Status.PENDING)
+ .put(Machine.State.RUNNING, NodeMetadata.Status.RUNNING)
+ .put(Machine.State.STOPPING, NodeMetadata.Status.PENDING)
+ .put(Machine.State.OFFLINE, NodeMetadata.Status.PENDING)
+ .put(Machine.State.STOPPED, NodeMetadata.Status.SUSPENDED)
+ .put(Machine.State.DELETED, NodeMetadata.Status.TERMINATED)
+ .put(Machine.State.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).build();
+
+ @Singleton
+ @Provides
+ protected Map<Machine.State, NodeMetadata.Status> toPortableNodeStatus() {
+ return toPortableNodeStatus;
+ }
+
+}
\ No newline at end of file
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetInDatacenterToImage.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetInDatacenterToImage.java
new file mode 100644
index 0000000..87a4053
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetInDatacenterToImage.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.domain.Location;
+import org.jclouds.joyent.sdc.v6_5.domain.Dataset;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatasetInDatacenter;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+
+/**
+ * A function for transforming a sdc-specific Image into a generic Image object.
+ *
+ * @author Adrian Cole
+ */
+public class DatasetInDatacenterToImage implements Function<DatasetInDatacenter, Image> {
+ private final Function<Dataset, OperatingSystem> imageToOs;
+ private final Supplier<Map<String, Location>> locationIndex;
+
+ @Inject
+ public DatasetInDatacenterToImage(Function<Dataset, OperatingSystem> imageToOs,
+ Supplier<Map<String, Location>> locationIndex) {
+ this.imageToOs = checkNotNull(imageToOs, "imageToOs");
+ this.locationIndex = checkNotNull(locationIndex, "locationIndex");
+ }
+
+ @Override
+ public Image apply(DatasetInDatacenter datasetInDatacenter) {
+ Location location = locationIndex.get().get(datasetInDatacenter.getDatacenter());
+ checkState(location != null, "location %s not in locationIndex: %s", datasetInDatacenter.getDatacenter(),
+ locationIndex.get());
+ Dataset dataset = datasetInDatacenter.get();
+ return new ImageBuilder()
+ .id(datasetInDatacenter.slashEncode())
+ .providerId(dataset.getId())
+ .name(dataset.getName())
+ .operatingSystem(imageToOs.apply(dataset))
+ .description(dataset.getUrn())
+ .version(dataset.getVersion())
+ .location(location)
+ .status(Image.Status.AVAILABLE).build();
+ }
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetToOperatingSystem.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetToOperatingSystem.java
new file mode 100644
index 0000000..e195f7c
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetToOperatingSystem.java
@@ -0,0 +1,82 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.functions;
+
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OperatingSystem.Builder;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.util.ComputeServiceUtils;
+import org.jclouds.joyent.sdc.v6_5.domain.Dataset;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * A function for transforming a sdc specific Dataset into a generic
+ * OperatingSystem object.
+ *
+ * @author Adrian Cole
+ */
+public class DatasetToOperatingSystem implements Function<Dataset, OperatingSystem> {
+ public static final Pattern DEFAULT_PATTERN = Pattern.compile("(([^ ]*) ([0-9.]+) ?.*)");
+ // Windows Machine 2008 R2 x64
+ public static final Pattern WINDOWS_PATTERN = Pattern.compile("Windows (.*) (x[86][64])");
+
+ @javax.annotation.Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ private final Map<OsFamily, Map<String, String>> osVersionMap;
+
+ @Inject
+ public DatasetToOperatingSystem(Map<OsFamily, Map<String, String>> osVersionMap) {
+ this.osVersionMap = osVersionMap;
+ }
+
+ public OperatingSystem apply(Dataset from) {
+ Builder builder = OperatingSystem.builder();
+ builder.name(from.getName());
+ builder.description(from.getUrn());
+ builder.is64Bit(true);//TODO: verify
+
+ List<String> pieces = ImmutableList.copyOf(Splitter.on(':').split(from.getUrn()));
+ if (pieces.get(2).indexOf('-') != -1) {
+ List<String> osFamVersion = ImmutableList.copyOf(Splitter.on('-').split(pieces.get(2)));
+ OsFamily family = OsFamily.fromValue(osFamVersion.get(0));
+ builder.family(family);
+ if (family != OsFamily.UNRECOGNIZED)
+ builder.version(ComputeServiceUtils.parseVersionOrReturnEmptyString(family, osFamVersion.get(1),
+ osVersionMap));
+ } else {
+ builder.family(OsFamily.fromValue(pieces.get(2)));
+ }
+ return builder.build();
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/MachineInDatacenterToNodeMetadata.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/MachineInDatacenterToNodeMetadata.java
new file mode 100644
index 0000000..d7aedde
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/MachineInDatacenterToNodeMetadata.java
@@ -0,0 +1,150 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.functions;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Predicates.not;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.tryFind;
+import static com.google.common.collect.Maps.filterKeys;
+import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
+import static org.jclouds.compute.util.ComputeServiceUtils.getSpace;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.ComputeMetadata;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
+import org.jclouds.joyent.sdc.v6_5.domain.Machine;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatacenterAndId;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatacenterAndName;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.MachineInDatacenter;
+import org.jclouds.joyent.sdc.v6_5.reference.MetadataKeys;
+import org.jclouds.logging.Logger;
+import org.jclouds.util.InetAddresses2;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+
+/**
+ * A function for transforming a sdc-specific Machine into a generic
+ * NodeMetadata object.
+ *
+ * @author Adrian Cole
+ */
+public class MachineInDatacenterToNodeMetadata implements Function<MachineInDatacenter, NodeMetadata> {
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ protected Map<Machine.State, org.jclouds.compute.domain.NodeMetadata.Status> toPortableNodeStatus;
+ protected final Supplier<Map<String, Location>> locationIndex;
+ protected final Supplier<Set<? extends Image>> images;
+ protected final Supplier<Set<? extends Hardware>> hardwares;
+ protected final GroupNamingConvention nodeNamingConvention;
+
+ @Inject
+ public MachineInDatacenterToNodeMetadata(Map<Machine.State, NodeMetadata.Status> toPortableNodeStatus,
+ Supplier<Map<String, Location>> locationIndex, @Memoized Supplier<Set<? extends Image>> images,
+ @Memoized Supplier<Set<? extends Hardware>> hardwares, GroupNamingConvention.Factory namingConvention) {
+ this.toPortableNodeStatus = checkNotNull(toPortableNodeStatus, "toPortableNodeStatus");
+ this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
+ this.locationIndex = checkNotNull(locationIndex, "locationIndex");
+ this.images = checkNotNull(images, "images");
+ this.hardwares = checkNotNull(hardwares, "hardwares");
+ }
+
+ @Override
+ public NodeMetadata apply(MachineInDatacenter machineInDatacenter) {
+ Location zone = locationIndex.get().get(machineInDatacenter.getDatacenter());
+ checkState(zone != null, "location %s not in locationIndex: %s", machineInDatacenter.getDatacenter(),
+ locationIndex.get());
+ Machine from = machineInDatacenter.get();
+
+ NodeMetadataBuilder builder = new NodeMetadataBuilder();
+ builder.id(machineInDatacenter.slashEncode());
+ builder.providerId(from.getId());
+ builder.name(from.getName());
+ builder.hostname(from.getName());
+ builder.location(zone);
+ addMetadataAndParseTagsFromCommaDelimitedValue(builder, filterKeys(from.getMetadata(), new Predicate<String>() {
+
+ @Override
+ public boolean apply(String input) {
+ // TODO make this more efficient
+ for (MetadataKeys key : MetadataKeys.values())
+ if (key.key().equals(input))
+ return false;
+ return true;
+ }
+
+ }));
+ builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
+ builder.imageId(DatacenterAndName.fromDatacenterAndName(machineInDatacenter.getDatacenter(), from.get())
+ .slashEncode());
+ builder.operatingSystem(findOperatingSystemForMachineOrNull(machineInDatacenter));
+ builder.hardware(findHardwareForMachineOrNull(machineInDatacenter));
+ builder.status(toPortableNodeStatus.get(from.getState()));
+ builder.publicAddresses(filter(from.getIps(), not(InetAddresses2.IsPrivateIPAddress.INSTANCE)));
+ builder.privateAddresses(filter(from.getIps(), InetAddresses2.IsPrivateIPAddress.INSTANCE));
+ return builder.build();
+ }
+
+ protected Hardware findHardwareForMachineOrNull(final MachineInDatacenter machineInDatacenter) {
+ return tryFind(hardwares.get(), new Predicate<Hardware>() {
+ @Override
+ public boolean apply(Hardware input) {
+ return input.getRam() == machineInDatacenter.get().getMemorySizeMb()
+ && getSpace(input) == machineInDatacenter.get().getDiskSizeGb()
+ && input.getLocation().getId().equals(machineInDatacenter.getDatacenter());
+ }
+ }).orNull();
+ }
+
+ protected OperatingSystem findOperatingSystemForMachineOrNull(MachineInDatacenter machineInDatacenter) {
+ Image image = findObjectOfTypeForMachineOrNull(images.get(), "image", machineInDatacenter.get()
+ .get(), machineInDatacenter);
+ return (image != null) ? image.getOperatingSystem() : null;
+ }
+
+ public <T extends ComputeMetadata> T findObjectOfTypeForMachineOrNull(Set<? extends T> supply, String type,
+ final String objectId, final DatacenterAndId machineInDatacenter) {
+ return tryFind(supply, new Predicate<T>() {
+ @Override
+ public boolean apply(T input) {
+ return input.getId().equals(
+ DatacenterAndId.fromDatacenterAndId(machineInDatacenter.getDatacenter(), objectId).slashEncode());
+ }
+ }).orNull();
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/OrphanedGroupsByDatacenterId.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/OrphanedGroupsByDatacenterId.java
new file mode 100644
index 0000000..5e0bbfc
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/OrphanedGroupsByDatacenterId.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.predicates.NodePredicates;
+import org.jclouds.joyent.sdc.v6_5.compute.predicates.AllNodesInGroupTerminated;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatacenterAndName;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+public class OrphanedGroupsByDatacenterId implements Function<Set<? extends NodeMetadata>, Multimap<String, String>> {
+ private final Predicate<DatacenterAndName> allNodesInGroupTerminated;
+
+ @Inject
+ protected OrphanedGroupsByDatacenterId(ComputeService computeService) {
+ this(new AllNodesInGroupTerminated(checkNotNull(computeService, "computeService")));
+ }
+
+ @VisibleForTesting
+ OrphanedGroupsByDatacenterId(Predicate<DatacenterAndName> allNodesInGroupTerminated) {
+ this.allNodesInGroupTerminated = checkNotNull(allNodesInGroupTerminated, "allNodesInGroupTerminated");
+ }
+
+ public Multimap<String, String> apply(Set<? extends NodeMetadata> deadNodes) {
+ Iterable<? extends NodeMetadata> nodesWithGroup = filter(deadNodes, NodePredicates.hasGroup());
+ Set<DatacenterAndName> datacenterAndGroupNames = ImmutableSet.copyOf(filter(transform(nodesWithGroup,
+ new Function<NodeMetadata, DatacenterAndName>() {
+
+ @Override
+ public DatacenterAndName apply(NodeMetadata input) {
+ String datacenterId = input.getLocation().getId();
+ return DatacenterAndName.fromDatacenterAndName(datacenterId, input.getGroup());
+ }
+
+ }), allNodesInGroupTerminated));
+ Multimap<String, String> datacenterToDatacenterAndGroupNames = Multimaps.transformValues(Multimaps.index(datacenterAndGroupNames,
+ DatacenterAndName.DATACENTER_FUNCTION), DatacenterAndName.NAME_FUNCTION);
+ return datacenterToDatacenterAndGroupNames;
+ }
+
+}
\ No newline at end of file
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/PackageInDatacenterToHardware.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/PackageInDatacenterToHardware.java
new file mode 100644
index 0000000..2aa55db
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/functions/PackageInDatacenterToHardware.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.internal.VolumeImpl;
+import org.jclouds.domain.Location;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.PackageInDatacenter;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+
+/**
+ * A function for transforming the sdc specific PackageInDatacenter object to
+ * the generic Hardware object.
+ *
+ * @author Adrian Cole
+ */
+public class PackageInDatacenterToHardware implements Function<PackageInDatacenter, Hardware> {
+
+ private final Supplier<Map<String, Location>> locationIndex;
+
+ @Inject
+ public PackageInDatacenterToHardware(Supplier<Map<String, Location>> locationIndex) {
+ this.locationIndex = checkNotNull(locationIndex, "locationIndex");
+ }
+
+ @Override
+ public Hardware apply(PackageInDatacenter pkgInDatacenter) {
+ Location location = locationIndex.get().get(pkgInDatacenter.getDatacenter());
+ checkState(location != null, "location %s not in locationIndex: %s", pkgInDatacenter.getDatacenter(),
+ locationIndex.get());
+ org.jclouds.joyent.sdc.v6_5.domain.Package pkg = pkgInDatacenter.get();
+ return new HardwareBuilder().id(pkgInDatacenter.slashEncode()).providerId(pkg.getName()).name(pkg.getName())
+ .ram(pkg.getMemorySizeMb())
+ // TODO: no api call to get processors.. either hard-code or
+ // calculate
+ .processor(new Processor(1, 1.0)).volume(new VolumeImpl(Float.valueOf(pkg.getDiskSizeGb()), true, true))
+ .location(location).build();
+ }
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/internal/KeyAndPrivateKey.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/internal/KeyAndPrivateKey.java
new file mode 100644
index 0000000..04c75a5
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/internal/KeyAndPrivateKey.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+
+import com.google.common.base.Objects;
+
+/**
+ * @author Adrian Cole
+ */
+public class KeyAndPrivateKey {
+
+ public static KeyAndPrivateKey fromKeyAndPrivateKey(Key key, String privateKey) {
+ return new KeyAndPrivateKey(key, privateKey);
+ }
+
+ protected final Key key;
+ protected final String privateKey;
+
+ protected KeyAndPrivateKey(Key key, String privateKey) {
+ this.key = checkNotNull(key, "key");
+ this.privateKey = checkNotNull(privateKey, "privateKey");
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(key, privateKey);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ KeyAndPrivateKey other = (KeyAndPrivateKey) obj;
+ return Objects.equal(key, other.key) && Objects.equal(privateKey, other.privateKey);
+ }
+
+ public Key getKey() {
+ return key;
+ }
+
+ public String getPrivateKey() {
+ return privateKey;
+ }
+
+ @Override
+ public String toString() {
+ return "[key=" + key + ", privateKey=" + privateKey + "]";
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/loaders/CreateUniqueKey.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/loaders/CreateUniqueKey.java
new file mode 100644
index 0000000..ca19266
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/loaders/CreateUniqueKey.java
@@ -0,0 +1,90 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.loaders;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.security.SecureRandom;
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.crypto.Crypto;
+import org.jclouds.crypto.SshKeys;
+import org.jclouds.joyent.sdc.v6_5.SDCClient;
+import org.jclouds.joyent.sdc.v6_5.compute.internal.KeyAndPrivateKey;
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatacenterAndName;
+import org.jclouds.logging.Logger;
+
+import com.google.common.cache.CacheLoader;
+import com.google.inject.Inject;
+
+/**
+ * @author Adrian Cole
+ */
+@Singleton
+public class CreateUniqueKey extends CacheLoader<DatacenterAndName, KeyAndPrivateKey> {
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+ protected final SDCClient sdcClient;
+ protected final GroupNamingConvention.Factory namingConvention;
+ protected final Crypto crypto;
+ protected final Provider<SecureRandom> secureRandom;
+
+ @Inject
+ public CreateUniqueKey(SDCClient sdcClient, GroupNamingConvention.Factory namingConvention, Crypto crypto, Provider<SecureRandom> secureRandom) {
+ this.sdcClient = checkNotNull(sdcClient, "sdcClient");
+ this.namingConvention = checkNotNull(namingConvention, "namingConvention");
+ this.crypto = checkNotNull(crypto, "crypto");
+ this.secureRandom = checkNotNull(secureRandom, "secureRandom");
+ }
+
+ @Override
+ public KeyAndPrivateKey load(DatacenterAndName datacenterAndName) {
+ String datacenterId = checkNotNull(datacenterAndName, "datacenterAndName").getDatacenter();
+ String prefix = datacenterAndName.getName();
+
+ Map<String, String> keyPair = SshKeys.generate(crypto.rsaKeyPairGenerator(), secureRandom.get());
+ String publicKey = keyPair.get("public");
+ String privateKey = keyPair.get("private");
+
+ logger.debug(">> creating key datacenter(%s) prefix(%s)", datacenterId, prefix);
+
+ Key key = null;
+ while (key == null) {
+ String name = namingConvention.createWithoutPrefix().uniqueNameForGroup(prefix);
+ try {
+ key = sdcClient.getKeyClient().create(Key.builder().name(name).key(publicKey).build());
+ } catch (IllegalStateException e) {
+ logger.trace("error creating keypair named %s, %s", name, e.getMessage());
+ }
+ }
+
+ logger.debug("<< created key(%s)", key.getName());
+ return KeyAndPrivateKey.fromKeyAndPrivateKey(key, privateKey);
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/options/SDCTemplateOptions.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/options/SDCTemplateOptions.java
new file mode 100644
index 0000000..da6d02d
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/options/SDCTemplateOptions.java
@@ -0,0 +1,337 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.options;
+
+import static com.google.common.base.Objects.equal;
+
+import java.util.Map;
+
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.scriptbuilder.domain.Statement;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Contains options supported in the {@code ComputeService#runNode} operation on the
+ * "joyent-sdc" provider. <h2>Usage</h2> The recommended way to instantiate a
+ * SDCTemplateOptions object is to statically import SDCTemplateOptions.* and invoke a static
+ * creation method followed by an instance mutator (if needed):
+ * <p/>
+ * <code>
+ * import static org.jclouds.aws.ec2.compute.options.SDCTemplateOptions.Builder.*;
+ * <p/>
+ * ComputeService client = // get connection
+ * templateBuilder.options(inboundPorts(22, 80, 8080, 443));
+ * Set<? extends NodeMetadata> set = client.createNodesInGroup(tag, 2, templateBuilder.build());
+ * <code>
+ *
+ * @author Adrian Cole
+ */
+public class SDCTemplateOptions extends TemplateOptions implements Cloneable {
+ @Override
+ public SDCTemplateOptions clone() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ copyTo(options);
+ return options;
+ }
+
+ @Override
+ public void copyTo(TemplateOptions to) {
+ super.copyTo(to);
+ if (to instanceof SDCTemplateOptions) {
+ SDCTemplateOptions eTo = SDCTemplateOptions.class.cast(to);
+ eTo.generateKey(shouldGenerateKey());
+ }
+ }
+
+ protected boolean generateKey = false;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ SDCTemplateOptions that = SDCTemplateOptions.class.cast(o);
+ return super.equals(that) && equal(this.generateKey, that.generateKey);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), generateKey);
+ }
+
+ @Override
+ public ToStringHelper string() {
+ ToStringHelper toString = super.string();
+ if (generateKey)
+ toString.add("generateKey", generateKey);
+ return toString;
+ }
+
+ /**
+ * @see #shouldGenerateKey()
+ */
+ public SDCTemplateOptions generateKey(boolean enable) {
+ this.generateKey = enable;
+ return this;
+ }
+
+ /**
+ *
+ * @return true if auto generation of keys is enabled
+ */
+ public boolean shouldGenerateKey() {
+ return generateKey;
+ }
+
+ public static class Builder {
+
+ /**
+ * @see SDCTemplateOptions#shouldGenerateKey()
+ */
+ public static SDCTemplateOptions generateKey(boolean enable) {
+ return new SDCTemplateOptions().generateKey(enable);
+ }
+
+ // methods that only facilitate returning the correct object type
+
+ /**
+ * @see TemplateOptions#inboundPorts
+ */
+ public static SDCTemplateOptions inboundPorts(int... ports) {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ return SDCTemplateOptions.class.cast(options.inboundPorts(ports));
+ }
+
+ /**
+ * @see TemplateOptions#port
+ */
+ public static SDCTemplateOptions blockOnPort(int port, int seconds) {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ return SDCTemplateOptions.class.cast(options.blockOnPort(port, seconds));
+ }
+
+ /**
+ * @see TemplateOptions#installPrivateKey
+ */
+ public static SDCTemplateOptions installPrivateKey(String rsaKey) {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ return SDCTemplateOptions.class.cast(options.installPrivateKey(rsaKey));
+ }
+
+ /**
+ * @see TemplateOptions#authorizePublicKey
+ */
+ public static SDCTemplateOptions authorizePublicKey(String rsaKey) {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ return SDCTemplateOptions.class.cast(options.authorizePublicKey(rsaKey));
+ }
+
+ /**
+ * @see TemplateOptions#userMetadata
+ */
+ public static SDCTemplateOptions userMetadata(Map<String, String> userMetadata) {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ return SDCTemplateOptions.class.cast(options.userMetadata(userMetadata));
+ }
+
+ /**
+ * @see TemplateOptions#overrideLoginUser
+ */
+ public static SDCTemplateOptions overrideLoginUser(String user) {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ return options.overrideLoginUser(user);
+ }
+
+ /**
+ * @see TemplateOptions#overrideLoginPassword
+ */
+ public static SDCTemplateOptions overrideLoginPassword(String password) {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ return options.overrideLoginPassword(password);
+ }
+
+ /**
+ * @see TemplateOptions#overrideLoginPrivateKey
+ */
+ public static SDCTemplateOptions overrideLoginPrivateKey(String privateKey) {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ return options.overrideLoginPrivateKey(privateKey);
+ }
+
+ /**
+ * @see TemplateOptions#overrideAuthenticateSudo
+ */
+ public static SDCTemplateOptions overrideAuthenticateSudo(boolean authenticateSudo) {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ return options.overrideAuthenticateSudo(authenticateSudo);
+ }
+
+ /**
+ * @see TemplateOptions#overrideLoginCredentials
+ */
+ public static SDCTemplateOptions overrideLoginCredentials(LoginCredentials credentials) {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ return options.overrideLoginCredentials(credentials);
+ }
+
+ /**
+ * @see TemplateOptions#blockUntilRunning
+ */
+ public static SDCTemplateOptions blockUntilRunning(boolean blockUntilRunning) {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ return options.blockUntilRunning(blockUntilRunning);
+ }
+
+ }
+
+ // methods that only facilitate returning the correct object type
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions blockOnPort(int port, int seconds) {
+ return SDCTemplateOptions.class.cast(super.blockOnPort(port, seconds));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions inboundPorts(int... ports) {
+ return SDCTemplateOptions.class.cast(super.inboundPorts(ports));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions authorizePublicKey(String publicKey) {
+ return SDCTemplateOptions.class.cast(super.authorizePublicKey(publicKey));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions installPrivateKey(String privateKey) {
+ return SDCTemplateOptions.class.cast(super.installPrivateKey(privateKey));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions blockUntilRunning(boolean blockUntilRunning) {
+ return SDCTemplateOptions.class.cast(super.blockUntilRunning(blockUntilRunning));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions dontAuthorizePublicKey() {
+ return SDCTemplateOptions.class.cast(super.dontAuthorizePublicKey());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions nameTask(String name) {
+ return SDCTemplateOptions.class.cast(super.nameTask(name));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions runAsRoot(boolean runAsRoot) {
+ return SDCTemplateOptions.class.cast(super.runAsRoot(runAsRoot));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions runScript(Statement script) {
+ return SDCTemplateOptions.class.cast(super.runScript(script));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions overrideLoginCredentials(LoginCredentials overridingCredentials) {
+ return SDCTemplateOptions.class.cast(super.overrideLoginCredentials(overridingCredentials));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions overrideLoginPassword(String password) {
+ return SDCTemplateOptions.class.cast(super.overrideLoginPassword(password));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions overrideLoginPrivateKey(String privateKey) {
+ return SDCTemplateOptions.class.cast(super.overrideLoginPrivateKey(privateKey));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions overrideLoginUser(String loginUser) {
+ return SDCTemplateOptions.class.cast(super.overrideLoginUser(loginUser));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions overrideAuthenticateSudo(boolean authenticateSudo) {
+ return SDCTemplateOptions.class.cast(super.overrideAuthenticateSudo(authenticateSudo));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions userMetadata(Map<String, String> userMetadata) {
+ return SDCTemplateOptions.class.cast(super.userMetadata(userMetadata));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SDCTemplateOptions userMetadata(String key, String value) {
+ return SDCTemplateOptions.class.cast(super.userMetadata(key, value));
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/predicates/AllNodesInGroupTerminated.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/predicates/AllNodesInGroupTerminated.java
new file mode 100644
index 0000000..ee20fdd
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/predicates/AllNodesInGroupTerminated.java
@@ -0,0 +1,52 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.predicates;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.and;
+import static com.google.common.collect.Iterables.all;
+import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
+import static org.jclouds.compute.predicates.NodePredicates.inGroup;
+import static org.jclouds.compute.predicates.NodePredicates.locationId;
+
+import javax.inject.Inject;
+
+import org.jclouds.compute.ComputeService;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatacenterAndName;
+
+import com.google.common.base.Predicate;
+
+/**
+ * @author Adrian Cole
+ */
+public class AllNodesInGroupTerminated implements Predicate<DatacenterAndName> {
+ private final ComputeService computeService;
+
+
+ //TODO: TESTME
+ @Inject
+ public AllNodesInGroupTerminated(ComputeService computeService) {
+ this.computeService = checkNotNull(computeService, "computeService");
+ }
+
+ @Override
+ public boolean apply(DatacenterAndName input) {
+ return all(computeService.listNodesDetailsMatching(locationId(input.getDatacenter())), and(inGroup(input.getName()), TERMINATED));
+ }
+}
\ No newline at end of file
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/strategy/ApplySDCTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/strategy/ApplySDCTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
new file mode 100644
index 0000000..0644756
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/compute/strategy/ApplySDCTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
@@ -0,0 +1,95 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.strategy;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.Constants;
+import org.jclouds.compute.config.CustomizationResponse;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
+import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
+import org.jclouds.compute.strategy.ListNodesStrategy;
+import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
+import org.jclouds.joyent.sdc.v6_5.compute.internal.KeyAndPrivateKey;
+import org.jclouds.joyent.sdc.v6_5.compute.options.SDCTemplateOptions;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatacenterAndName;
+
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.Multimap;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+@Singleton
+public class ApplySDCTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet extends
+ CreateNodesWithGroupEncodedIntoNameThenAddToSet {
+
+ private final LoadingCache<DatacenterAndName, KeyAndPrivateKey> keyCache;
+
+ @Inject
+ protected ApplySDCTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet(
+ CreateNodeWithGroupEncodedIntoName addNodeWithTagStrategy,
+ ListNodesStrategy listNodesStrategy,
+ GroupNamingConvention.Factory namingConvention,
+ CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
+ @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
+ LoadingCache<DatacenterAndName, KeyAndPrivateKey> keyCache) {
+ super(addNodeWithTagStrategy, listNodesStrategy, namingConvention, executor,
+ customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
+ this.keyCache = checkNotNull(keyCache, "keyCache");
+ }
+
+ @Override
+ public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
+ Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
+
+ Template mutableTemplate = template.clone();
+
+ SDCTemplateOptions templateOptions = SDCTemplateOptions.class.cast(mutableTemplate.getOptions());
+
+ assert template.getOptions().equals(templateOptions) : "options didn't clone properly";
+
+ String datacenter = mutableTemplate.getLocation().getId();
+
+ if (templateOptions.shouldGenerateKey()) {
+ KeyAndPrivateKey keyPair = keyCache.getUnchecked(DatacenterAndName.fromDatacenterAndName(datacenter, namingConvention.create()
+ .sharedNameForGroup(group)));
+ // in order to delete the key later
+ keyCache.asMap().put(DatacenterAndName.fromDatacenterAndName(datacenter, keyPair.getKey().getName()), keyPair);
+ templateOptions.overrideLoginPrivateKey(keyPair.getPrivateKey());
+ }
+ checkArgument(templateOptions.getRunScript() == null || templateOptions.getLoginPrivateKey() != null,
+ "when specifying runScript, you must either set overrideLoginPrivateKey, or generateKey(true)");
+ return super.execute(group, count, mutableTemplate, goodNodes, badNodes, customizationResponses);
+ }
+}
\ No newline at end of file
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/DatacentersAreZonesModule.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/DatacentersAreZonesModule.java
new file mode 100644
index 0000000..48b2c51
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/DatacentersAreZonesModule.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.config;
+
+import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient;
+
+import org.jclouds.joyent.sdc.v6_5.features.DatacenterAsyncClient;
+import org.jclouds.joyent.sdc.v6_5.features.DatacenterClient;
+import org.jclouds.joyent.sdc.v6_5.suppliers.ZoneIdToURIFromDatacentersClient;
+import org.jclouds.location.suppliers.ImplicitLocationSupplier;
+import org.jclouds.location.suppliers.ZoneIdToURISupplier;
+import org.jclouds.location.suppliers.ZoneIdsSupplier;
+import org.jclouds.location.suppliers.derived.ZoneIdsFromZoneIdToURIKeySet;
+import org.jclouds.location.suppliers.implicit.OnlyLocationOrFirstZone;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Scopes;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+public class DatacentersAreZonesModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ // datacenter client is needed for obtaining zone ids
+ bindClientAndAsyncClient(binder(), DatacenterClient.class, DatacenterAsyncClient.class);
+ bind(ImplicitLocationSupplier.class).to(OnlyLocationOrFirstZone.class).in(Scopes.SINGLETON);
+ bind(ZoneIdToURISupplier.class).to(ZoneIdToURIFromDatacentersClient.class).in(Scopes.SINGLETON);
+ bind(ZoneIdsSupplier.class).to(ZoneIdsFromZoneIdToURIKeySet.class).in(Scopes.SINGLETON);
+ }
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCParserModule.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCParserModule.java
index cc2e3f1..ae0974e 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCParserModule.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCParserModule.java
@@ -38,7 +38,7 @@
@Provides
@Singleton
public Map<Type, Object> provideCustomAdapterBindings() {
- return ImmutableMap.<Type, Object> of(Machine.State.class, new SDCTypeAdapters.ServerStateAdapter(), Type.class,
+ return ImmutableMap.<Type, Object> of(Machine.State.class, new SDCTypeAdapters.MachineStateAdapter(), Type.class,
new SDCTypeAdapters.SDCTypeAdapter());
}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCProperties.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCProperties.java
index 71eaaea..e408831 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCProperties.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCProperties.java
@@ -25,4 +25,10 @@
*/
public class SDCProperties {
+ /**
+ * Whenever a node is created, automatically generate keys for groups, as needed, also
+ * delete the key(s) when the last node in the group is destroyed.
+ */
+ public static final String AUTOGENERATE_KEYS = "jclouds.joyent-sdc.autogenerate-keys";
+
}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCRestClientModule.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCRestClientModule.java
index 922dac6..5b27bdc 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCRestClientModule.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCRestClientModule.java
@@ -30,6 +30,8 @@
import org.jclouds.joyent.sdc.v6_5.features.DatacenterClient;
import org.jclouds.joyent.sdc.v6_5.features.DatasetAsyncClient;
import org.jclouds.joyent.sdc.v6_5.features.DatasetClient;
+import org.jclouds.joyent.sdc.v6_5.features.KeyAsyncClient;
+import org.jclouds.joyent.sdc.v6_5.features.KeyClient;
import org.jclouds.joyent.sdc.v6_5.features.MachineAsyncClient;
import org.jclouds.joyent.sdc.v6_5.features.MachineClient;
import org.jclouds.joyent.sdc.v6_5.features.PackageAsyncClient;
@@ -50,8 +52,11 @@
@ConfiguresRestClient
public class SDCRestClientModule extends RestClientModule<SDCClient, SDCAsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
- .put(DatacenterClient.class, DatacenterAsyncClient.class).put(MachineClient.class, MachineAsyncClient.class)
- .put(DatasetClient.class, DatasetAsyncClient.class).put(PackageClient.class, PackageAsyncClient.class).build();
+ .put(DatacenterClient.class, DatacenterAsyncClient.class)
+ .put(KeyClient.class, KeyAsyncClient.class)
+ .put(MachineClient.class, MachineAsyncClient.class)
+ .put(DatasetClient.class, DatasetAsyncClient.class)
+ .put(PackageClient.class, PackageAsyncClient.class).build();
public SDCRestClientModule() {
super(DELEGATE_MAP);
@@ -70,4 +75,5 @@
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(SDCErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(SDCErrorHandler.class);
}
+
}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/Key.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/Key.java
new file mode 100644
index 0000000..1933691
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/Key.java
@@ -0,0 +1,109 @@
+package org.jclouds.joyent.sdc.v6_5.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Date;
+
+import com.google.common.base.Objects;
+
+/**
+ * Keys are the means by which you operate on your SSH/signing keys. Currently
+ * CloudAPI supports uploads of public keys in the OpenSSH format.
+ *
+ * @author Adrian Cole
+ * @see <a href="http://apidocs.joyent.com/sdcapidoc/cloudapi/#keys" >docs</a>
+ */
+public class Key implements Comparable<Key> {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return builder().fromKey(this);
+ }
+
+ public static class Builder {
+ private String name;
+ private String key;
+ private Date created;
+
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder key(String key) {
+ this.key = key;
+ return this;
+ }
+
+ public Builder created(Date created) {
+ this.created = created;
+ return this;
+ }
+
+ public Key build() {
+ return new Key(name, key, created);
+ }
+
+ public Builder fromKey(Key in) {
+ return name(in.getName()).key(in.get()).created(in.getCreated());
+ }
+ }
+
+ protected final String name;
+ protected final String key;
+ protected final Date created;
+
+ public Key(String name, String key, Date created) {
+ this.name = checkNotNull(name, "name");
+ this.key = checkNotNull(key, "key: OpenSSH formatted public key");
+ this.created = created;
+ }
+
+ /**
+ * Name for this key
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * OpenSSH formatted public key
+ */
+ public String get() {
+ return key;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+
+ @Override
+ public int compareTo(Key other) {
+ return name.compareTo(other.getName());
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object instanceof Key) {
+ return Objects.equal(name, ((Key) object).name);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("[name=%s, key=%s, created=%s]", name, key, created);
+ }
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/Machine.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/Machine.java
index 7a4df0c..5bbe326 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/Machine.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/Machine.java
@@ -24,10 +24,18 @@
import java.util.Map;
import java.util.Set;
+import org.jclouds.domain.JsonBall;
+import org.jclouds.joyent.sdc.v6_5.reference.MetadataKeys;
+import org.jclouds.json.Json;
+
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CaseFormat;
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
import com.google.gson.annotations.SerializedName;
/**
@@ -39,7 +47,7 @@
public class Machine implements Comparable<Machine> {
public static enum State {
- PUBLISHING, RUNNING, STOPPED, UNRECOGNIZED;
+ PROVISIONING, RUNNING, STOPPING, STOPPED, OFFLINE, DELETED, UNRECOGNIZED;
public static State fromValue(String state) {
try {
@@ -62,6 +70,10 @@
public static Builder builder() {
return new Builder();
}
+
+ public Builder toBuilder() {
+ return new Builder().fromMachine(this);
+ }
public static class Builder {
private String id;
@@ -74,7 +86,7 @@
private Set<String> ips;
private Date created;
private Date updated;
- private Map<String, String> metadata = ImmutableMap.of();
+ private Map<String, JsonBall> metadata = ImmutableMap.of();
public Builder id(String id) {
this.id = id;
@@ -129,7 +141,7 @@
/**
* @see Machine#getMetadata()
*/
- public Builder metadata(Map<String, String> metadata) {
+ public Builder metadata(Map<String, JsonBall> metadata) {
this.metadata = metadata;
return this;
}
@@ -139,9 +151,9 @@
}
public Builder fromMachine(Machine in) {
- return id(in.getId()).name(in.getName()).type(in.getType()).state(in.getState()).dataset(in.getDataset())
+ return id(in.getId()).name(in.getName()).type(in.getType()).state(in.getState()).dataset(in.get())
.memorySizeMb(in.getMemorySizeMb()).diskSizeGb(in.getDiskSizeGb()).ips(in.getIps())
- .metadata(in.getMetadata()).created(in.getCreated()).updated(in.getUpdated());
+ .metadata(in.metadata).created(in.getCreated()).updated(in.getUpdated());
}
}
@@ -169,7 +181,7 @@
protected final Date updated;
// metadata Object[String => String] Any "extra" metadata this machine has
- private final Map<String, String> metadata;
+ private final Map<String, JsonBall> metadata;
@Override
public int compareTo(Machine other) {
@@ -177,7 +189,7 @@
}
public Machine(String id, String name, Type type, State state, String dataset, int memorySizeMb, int diskSizeGb,
- Set<String> ips, Date created, Date updated, final Map<String, String> metadata) {
+ Set<String> ips, Date created, Date updated, final Map<String, JsonBall> metadata) {
super();
this.id = id;
this.name = name;
@@ -208,7 +220,7 @@
return state;
}
- public String getDataset() {
+ public String get() {
return dataset;
}
@@ -232,10 +244,39 @@
return updated;
}
- public Map<String, String> getMetadata() {
- return metadata;
+ /**
+ * If the value is a string, it will be quoted, as that's how json strings are represented.
+ *
+ * @return key to a json literal of the value
+ * @see MetadataKeys#valueType
+ * @see Json#fromJson
+ */
+ public Map<String, String> getMetadataAsJsonLiterals() {
+ return Maps.transformValues(metadata, Functions.toStringFunction());
}
+ /**
+ * Note!! metadata can contain arbitrarily complex values. If the value has structure, you should use {@link #getMetadataAsJsonLiterals}
+ *
+ * @return metadata
+ */
+ public Map<String, String> getMetadata() {
+ return Maps.transformValues(metadata, Functions.compose(Functions.toStringFunction(), unquoteString));
+ }
+
+ @VisibleForTesting
+ static final Function<JsonBall, String> unquoteString = new Function<JsonBall, String>() {
+
+ @Override
+ public String apply(JsonBall input) {
+ String value = input.toString();
+ if (value.length() >= 2 && value.charAt(0) == '"' && value.charAt(input.length() - 1) == '"')
+ return value.substring(1, input.length() - 1);
+ return value;
+ }
+
+ };
+
@Override
public boolean equals(Object object) {
if (this == object) {
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/DatacenterAndId.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/DatacenterAndId.java
new file mode 100644
index 0000000..df04e1d
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/DatacenterAndId.java
@@ -0,0 +1,88 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.domain.datacenterscoped;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+
+/**
+ * @author Adrian Cole
+ */
+public class DatacenterAndId {
+ public static DatacenterAndId fromSlashEncoded(String id) {
+ Iterable<String> parts = Splitter.on('/').split(checkNotNull(id, "id"));
+ checkArgument(Iterables.size(parts) == 2, "id must be in format datacenterId/id");
+ return new DatacenterAndId(Iterables.get(parts, 0), Iterables.get(parts, 1));
+ }
+
+ public static DatacenterAndId fromDatacenterAndId(String datacenterId, String id) {
+ return new DatacenterAndId(datacenterId, id);
+ }
+
+ private static String slashEncodeDatacenterAndId(String datacenterId, String id) {
+ return checkNotNull(datacenterId, "datacenterId") + "/" + checkNotNull(id, "id");
+ }
+
+ public String slashEncode() {
+ return slashEncodeDatacenterAndId(datacenterId, id);
+ }
+
+ protected final String datacenterId;
+ protected final String id;
+
+ protected DatacenterAndId(String datacenterId, String id) {
+ this.datacenterId = checkNotNull(datacenterId, "datacenterId");
+ this.id = checkNotNull(id, "id");
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(datacenterId, id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ DatacenterAndId other = (DatacenterAndId) obj;
+ return Objects.equal(datacenterId, other.datacenterId) && Objects.equal(id, other.id);
+ }
+
+ public String getDatacenter() {
+ return datacenterId;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return "[datacenterId=" + datacenterId + ", id=" + id + "]";
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/DatacenterAndName.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/DatacenterAndName.java
new file mode 100644
index 0000000..158c384
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/DatacenterAndName.java
@@ -0,0 +1,113 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.domain.datacenterscoped;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Splitter;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.Iterables;
+
+/**
+ * Helpful when looking for resources by datacenter and name
+ *
+ * @author Adrian Cole
+ */
+public class DatacenterAndName {
+
+ public final static Function<DatacenterAndName, String> NAME_FUNCTION = new Function<DatacenterAndName, String>(){
+
+ @Override
+ public String apply(DatacenterAndName input) {
+ return input.getName();
+ }
+
+ };
+
+ public final static Function<DatacenterAndName, String> DATACENTER_FUNCTION = new Function<DatacenterAndName, String>(){
+
+ @Override
+ public String apply(DatacenterAndName input) {
+ return input.getDatacenter();
+ }
+
+ };
+
+ public static DatacenterAndName fromSlashEncoded(String name) {
+ Iterable<String> parts = Splitter.on('/').split(checkNotNull(name, "name"));
+ checkArgument(Iterables.size(parts) == 2, "name must be in format datacenterId/name");
+ return new DatacenterAndName(Iterables.get(parts, 0), Iterables.get(parts, 1));
+ }
+
+ public static DatacenterAndName fromDatacenterAndName(String datacenterId, String name) {
+ return new DatacenterAndName(datacenterId, name);
+ }
+
+ private static String slashEncodeDatacenterAndName(String datacenterId, String name) {
+ return checkNotNull(datacenterId, "datacenterId") + "/" + checkNotNull(name, "name");
+ }
+
+ public String slashEncode() {
+ return slashEncodeDatacenterAndName(datacenterId, name);
+ }
+
+ protected final String datacenterId;
+ protected final String name;
+
+ protected DatacenterAndName(String datacenterId, String name) {
+ this.datacenterId = checkNotNull(datacenterId, "datacenterId");
+ this.name = checkNotNull(name, "name");
+ }
+
+ public String getDatacenter() {
+ return datacenterId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ DatacenterAndName that = DatacenterAndName.class.cast(o);
+ return equal(this.datacenterId, that.datacenterId) && equal(this.name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(datacenterId, name);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper("").add("datacenterId", datacenterId).add("name", name);
+ }
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/DatasetInDatacenter.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/DatasetInDatacenter.java
new file mode 100644
index 0000000..4e3e0e6
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/DatasetInDatacenter.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.domain.datacenterscoped;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.joyent.sdc.v6_5.domain.Dataset;
+
+/**
+ * @author Adrian Cole
+ */
+public class DatasetInDatacenter extends DatacenterAndId {
+ protected final Dataset dataset;
+
+ public DatasetInDatacenter(Dataset dataset, String datacenterId) {
+ super(datacenterId, checkNotNull(dataset, "dataset").getId());
+ this.dataset = dataset;
+ }
+
+ public Dataset get() {
+ return dataset;
+ }
+
+ // superclass hashCode/equals are good enough, and help us use DatacenterAndId and DatasetInDatacenter
+ // interchangeably as Map keys
+
+ @Override
+ public String toString() {
+ return "[dataset=" + dataset + ", datacenterId=" + datacenterId + "]";
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/KeyInDatacenter.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/KeyInDatacenter.java
new file mode 100644
index 0000000..42a80a0
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/KeyInDatacenter.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.domain.datacenterscoped;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+
+/**
+ * @author Adrian Cole
+ */
+public class KeyInDatacenter extends DatacenterAndName {
+ protected final Key key;
+
+ public KeyInDatacenter(Key key, String datacenterId) {
+ super(datacenterId, checkNotNull(key, "key").getName());
+ this.key = key;
+ }
+
+ public Key get() {
+ return key;
+ }
+
+ // superclass hashCode/equals are good enough, and help us use DatacenterAndId and PackageInDatacenter
+ // interchangeably as Map keys
+
+ @Override
+ public String toString() {
+ return "[key=" + key + ", datacenterId=" + datacenterId + "]";
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/MachineInDatacenter.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/MachineInDatacenter.java
new file mode 100644
index 0000000..1f0fb23
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/MachineInDatacenter.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.domain.datacenterscoped;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.joyent.sdc.v6_5.domain.Machine;
+
+/**
+ * @author Adrian Cole
+ */
+public class MachineInDatacenter extends DatacenterAndId {
+ protected final Machine machine;
+
+ public MachineInDatacenter(Machine machine, String datacenterId) {
+ super(datacenterId, checkNotNull(machine, "machine").getId());
+ this.machine = machine;
+ }
+
+ public Machine get() {
+ return machine;
+ }
+
+ // superclass hashCode/equals are good enough, and help us use DatacenterAndId and MachineInDatacenter
+ // interchangeably as Map keys
+
+ @Override
+ public String toString() {
+ return "[machine=" + machine + ", datacenterId=" + datacenterId + "]";
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/PackageInDatacenter.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/PackageInDatacenter.java
new file mode 100644
index 0000000..3a155c1
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/domain/datacenterscoped/PackageInDatacenter.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.domain.datacenterscoped;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * @author Adrian Cole
+ */
+public class PackageInDatacenter extends DatacenterAndName {
+ protected final org.jclouds.joyent.sdc.v6_5.domain.Package pkg;
+
+ public PackageInDatacenter(org.jclouds.joyent.sdc.v6_5.domain.Package pkg, String datacenterId) {
+ super(datacenterId, checkNotNull(pkg, "pkg").getName());
+ this.pkg = pkg;
+ }
+
+ public org.jclouds.joyent.sdc.v6_5.domain.Package get() {
+ return pkg;
+ }
+
+ // superclass hashCode/equals are good enough, and help us use DatacenterAndId and PackageInDatacenter
+ // interchangeably as Map keys
+
+ @Override
+ public String toString() {
+ return "[pkg=" + pkg + ", datacenterId=" + datacenterId + "]";
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatasetAsyncClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatasetAsyncClient.java
index 80eff51..c76ce88 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatasetAsyncClient.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatasetAsyncClient.java
@@ -32,20 +32,20 @@
@RequestFilters(BasicAuthentication.class)
public interface DatasetAsyncClient {
/**
- * @see DatasetClient#listMachines
+ * @see DatasetClient#list
*/
@GET
@Path("/my/datasets")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
- ListenableFuture<Set<Dataset>> listDatasets();
+ ListenableFuture<Set<Dataset>> list();
/**
- * @see DatasetClient#getMachineDetails
+ * @see DatasetClient#get
*/
@GET
@Path("/my/datasets/{id}")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
- ListenableFuture<Dataset> getDataset(@PathParam("id") String id);
+ ListenableFuture<Dataset> get(@PathParam("id") String id);
}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClient.java
index c33fd80..eaf99d5 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClient.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClient.java
@@ -22,7 +22,7 @@
*
* @return
*/
- Set<Dataset> listDatasets();
+ Set<Dataset> list();
/**
* Gets an individual dataset by id.
@@ -31,5 +31,5 @@
* the id of the dataset
* @return
*/
- Dataset getDataset(String id);
+ Dataset get(String id);
}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/KeyAsyncClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/KeyAsyncClient.java
new file mode 100644
index 0000000..975347b
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/KeyAsyncClient.java
@@ -0,0 +1,69 @@
+package org.jclouds.joyent.sdc.v6_5.features;
+
+import java.util.Set;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.http.filters.BasicAuthentication;
+import org.jclouds.joyent.sdc.v6_5.binders.BindKeyToJsonPayload;
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.ExceptionParser;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
+import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * @author Adrian Cole
+ * @see KeyClient
+ * @see <a href="http://apidocs.joyent.com/sdcapidoc/cloudapi/#keys">api doc</a>
+ */
+@SkipEncoding({ '/', '=' })
+@Headers(keys = "X-Api-Version", values = "{jclouds.api-version}")
+@RequestFilters(BasicAuthentication.class)
+public interface KeyAsyncClient {
+ /**
+ * @see KeyClient#list
+ */
+ @GET
+ @Path("/my/keys")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
+ ListenableFuture<Set<Key>> list();
+
+ /**
+ * @see KeyClient#get
+ */
+ @GET
+ @Path("/my/keys/{name}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+ ListenableFuture<Key> get(@PathParam("name") String name);
+
+ /**
+ * @see KeyClient#create
+ */
+ @POST
+ @Path("/my/keys")
+ @Consumes(MediaType.APPLICATION_JSON)
+ ListenableFuture<Key> create(@BinderParam(BindKeyToJsonPayload.class) Key key);
+
+ /**
+ * @see KeyClient#delete
+ */
+ @DELETE
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/my/keys/{name}")
+ ListenableFuture<Void> delete(@PathParam("name") String name);
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/KeyClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/KeyClient.java
new file mode 100644
index 0000000..ad540b6
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/KeyClient.java
@@ -0,0 +1,40 @@
+package org.jclouds.joyent.sdc.v6_5.features;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+
+/**
+ * Keys are the means by which you operate on your SSH/signing keys. Currently
+ * CloudAPI supports uploads of public keys in the OpenSSH format.
+ *
+ * @author Adrian Cole
+ * @see KeyAsyncClient
+ * @see <a href="http://apidocs.joyent.com/sdcapidoc/cloudapi/#keys">api doc</a>
+ */
+@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
+public interface KeyClient {
+
+ /**
+ * Lists all public keys we have on record for the specified account.
+ */
+ Set<Key> list();
+
+ /**
+ * Retrieves an individual key record.
+ */
+ Key get(String name);
+
+ /**
+ * Uploads a new OpenSSH key to SmartDataCenter for use in SSH and HTTP
+ * signing.
+ */
+ Key create(Key key);
+
+ /**
+ * Deletes an SSH key by name.
+ */
+ void delete(String name);
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/MachineAsyncClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/MachineAsyncClient.java
index b32ab43..67281e1 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/MachineAsyncClient.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/MachineAsyncClient.java
@@ -27,14 +27,14 @@
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.joyent.sdc.v6_5.domain.Machine;
-import org.jclouds.joyent.sdc.v6_5.options.CreateServerOptions;
+import org.jclouds.joyent.sdc.v6_5.options.CreateMachineOptions;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Headers;
-import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
@@ -58,81 +58,86 @@
public interface MachineAsyncClient {
/**
- * @see MachineClient#listMachines
+ * @see MachineClient#list
*/
@GET
@Path("/my/machines")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
- ListenableFuture<Set<Machine>> listMachines();
+ ListenableFuture<Set<Machine>> list();
/**
- * @see MachineClient#getMachineDetails
+ * @see MachineClient#get
*/
@GET
@Path("/my/machines/{id}")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
- ListenableFuture<Machine> getMachine(@PathParam("id") String id);
-
+ ListenableFuture<Machine> get(@PathParam("id") String id);
+
+ /**
+ * @see MachineClient#createWithDataset(String)
+ */
+ @POST
+ @Path("/my/machines")
+ @Consumes(MediaType.APPLICATION_JSON)
+ ListenableFuture<Machine> createWithDataset(@QueryParam("dataset") String datasetURN);
+
/**
- * @see MachineClient#createMachine
+ * @see MachineClient#createWithDataset(String, CreateMachineOptions)
*/
@POST
- @Path("/my/machines")
- @Consumes(MediaType.APPLICATION_JSON)
- @MapBinder(CreateServerOptions.class)
- ListenableFuture<Machine> createMachine(@PayloadParam("name") String name,
- @PayloadParam("package") String packageSDC,
- @PayloadParam("dataset") String dataset,CreateServerOptions... options);
+ @Path("/my/machines")
+ @Consumes(MediaType.APPLICATION_JSON)
+ ListenableFuture<Machine> createWithDataset(@QueryParam("dataset") String datasetURN, CreateMachineOptions options);
/**
- * @see MachineClient#stopMachine
+ * @see MachineClient#stop
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/my/machines/{id}")
@Payload("action=stop")
- ListenableFuture<Void> stopMachine(@PathParam("id") String id);
+ ListenableFuture<Void> stop(@PathParam("id") String id);
/**
- * @see MachineClient#startMachine
+ * @see MachineClient#start
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/my/machines/{id}")
@Payload("action=start")
- ListenableFuture<Void> startMachine(@PathParam("id") String id);
+ ListenableFuture<Void> start(@PathParam("id") String id);
/**
- * @see MachineClient#rebootMachine
+ * @see MachineClient#reboot
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/my/machines/{id}")
@Payload("action=reboot")
- ListenableFuture<Void> rebootMachine(@PathParam("id") String id);
+ ListenableFuture<Void> reboot(@PathParam("id") String id);
/**
- * @see MachineClient#resizeMachine
+ * @see MachineClient#resize
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/my/machines/{id}")
@Payload("action=resize&package={package}")
- ListenableFuture<Void> resizeMachine(@PathParam("id") String id,@PayloadParam("package") String packageSDC);
+ ListenableFuture<Void> resize(@PathParam("id") String id,@PayloadParam("package") String packageSDC);
/**
- * @see MachineClient#deleteMachine
+ * @see MachineClient#delete
*/
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Path("/my/machines/{id}")
- ListenableFuture<Void> deleteMachine(@PathParam("id") String id);
+ ListenableFuture<Void> delete(@PathParam("id") String id);
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/MachineClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/MachineClient.java
index 5cec1ed..64ccc6d 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/MachineClient.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/MachineClient.java
@@ -23,7 +23,7 @@
import org.jclouds.concurrent.Timeout;
import org.jclouds.joyent.sdc.v6_5.domain.Machine;
-import org.jclouds.joyent.sdc.v6_5.options.CreateServerOptions;
+import org.jclouds.joyent.sdc.v6_5.options.CreateMachineOptions;
/**
* Provides synchronous access to Machine.
@@ -39,9 +39,9 @@
/**
* Lists all machines we have on record for your account.
*
- * @return an account's associated server objects.
+ * @return an account's associated machine objects.
*/
- Set<Machine> listMachines();
+ Set<Machine> list();
/**
* Gets the details for an individual machine.
@@ -50,21 +50,47 @@
* the id of the machine
* @return
*/
- Machine getMachine(String id);
+ Machine get(String id);
/**
+ * Allows you to provision a machine. Note that if you do not specify a
+ * package, you'll get the datacenter defaults for it. If
+ * you do not specify a name, CloudAPI will generate a random one for you.
+ * Your machine will initially be not available for login (SmartDataCenter
+ * must provision and boot it). You can poll {@link #get} for status. When the
+ * state field is equal to running, you can login.
*
- * @param name
- * friendly name for this machine; default is a randomly generated name
- * @param packageSDC
- * Name of the package to use on provisioning; default is indicated in ListPackages
- * @param dataset
- * dataset URN; default is indicated in ListDatasets
- * @param options
- * optional parameters to be passed into the machine creation request
+ * <p/>
+ * With regards to login, if the machine is of type smartmachine, you can use
+ * any of the SSH keys managed under the keys section of CloudAPI to login,
+ * as any POSIX user on the OS. You can add/remove them over time, and the
+ * machine will automatically work with that set.
+ *
+ * <p/>
+ * If the the machine is a virtualmachine, and of a UNIX-derived OS (e.g.
+ * Linux), you must have keys uploaded before provisioning; that entire set
+ * of keys will be written out to /root/.ssh/authorized_keys, and you can ssh
+ * in using one of those. Changing the keys over time under your account will
+ * not affect the running virtual machine in any way; those keys are
+ * statically written at provisioning-time only, and you will need to
+ * manually manage them.
+ *
+ * <p/>
+ * If the dataset you create a machine from is set to generate passwords for
+ * you, the username/password pairs will be returned in the metadata response
+ * as a nested object, like:
+ *
+ * @param datasetURN urn of the dataset to install
+ *
* @return the newly created machine
*/
- Machine createMachine(String name, String packageSDC, String dataset, CreateServerOptions... options);
+ Machine createWithDataset(String datasetURN, CreateMachineOptions options);
+
+ /**
+ *
+ * @see #createWithDataset(CreateMachineOptions)
+ */
+ Machine createWithDataset(String datasetURN);
/**
* Allows you to shut down a machine.
@@ -72,7 +98,7 @@
* @param id
* the id of the machine to stop
*/
- void stopMachine(String id);
+ void stop(String id);
/**
* Allows you to boot up a machine.
@@ -80,7 +106,7 @@
* @param id
* the id of the machine to start
*/
- void startMachine(String id);
+ void start(String id);
/**
* Allows you to reboot a machine.
@@ -88,7 +114,7 @@
* @param id
* the id of the machine to reboot
*/
- void rebootMachine(String id);
+ void reboot(String id);
/**
* Allows you to resize a machine. (Works only for smart machines)
@@ -98,14 +124,15 @@
* @param packageSDC
* the package to use for the machine
*/
- void resizeMachine(String id, String packageSDC);
+ void resize(String id, String packageSDC);
/**
- * Allows you to delete a machine (the machine must be stopped before it can be deleted).
+ * Allows you to delete a machine (the machine must be stopped before it can
+ * be deleted).
*
* @param id
* the id of the machine to delete
*/
- void deleteMachine(String id);
+ void delete(String id);
}
\ No newline at end of file
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/PackageAsyncClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/PackageAsyncClient.java
index 7a316da..eab42d6 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/PackageAsyncClient.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/PackageAsyncClient.java
@@ -31,20 +31,20 @@
@RequestFilters(BasicAuthentication.class)
public interface PackageAsyncClient {
/**
- * @see PackageClient#listPackages
+ * @see PackageClient#list
*/
@GET
@Path("/my/packages")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
- ListenableFuture<Set<org.jclouds.joyent.sdc.v6_5.domain.Package>> listPackages();
+ ListenableFuture<Set<org.jclouds.joyent.sdc.v6_5.domain.Package>> list();
/**
- * @see PackageClient#getPackageDetails
+ * @see PackageClient#get
*/
@GET
@Path("/my/packages/{name}")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
- ListenableFuture<org.jclouds.joyent.sdc.v6_5.domain.Package> getPackage(@PathParam("name") String name);
+ ListenableFuture<org.jclouds.joyent.sdc.v6_5.domain.Package> get(@PathParam("name") String name);
}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/PackageClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/PackageClient.java
index 4f58da8..4b02b8f 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/PackageClient.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/PackageClient.java
@@ -21,7 +21,7 @@
*
* @return
*/
- Set<org.jclouds.joyent.sdc.v6_5.domain.Package> listPackages();
+ Set<org.jclouds.joyent.sdc.v6_5.domain.Package> list();
/**
* Gets an individual package by id.
@@ -30,5 +30,5 @@
* the name of the package
* @return
*/
- org.jclouds.joyent.sdc.v6_5.domain.Package getPackage(String name);
+ org.jclouds.joyent.sdc.v6_5.domain.Package get(String name);
}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/functions/internal/SDCTypeAdapters.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/functions/internal/SDCTypeAdapters.java
index ecfe62e..78c6066 100644
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/functions/internal/SDCTypeAdapters.java
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/functions/internal/SDCTypeAdapters.java
@@ -28,11 +28,11 @@
import com.google.gson.stream.JsonWriter;
/**
- * @author Adam Lowe
+ * @author Adrian Cole
*/
public class SDCTypeAdapters {
- public static class ServerStateAdapter extends TypeAdapter<Machine.State> {
+ public static class MachineStateAdapter extends TypeAdapter<Machine.State> {
@Override
public void write(JsonWriter writer, Machine.State value) throws IOException {
writer.value(value.value());
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/options/CreateMachineOptions.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/options/CreateMachineOptions.java
new file mode 100644
index 0000000..e0f5292
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/options/CreateMachineOptions.java
@@ -0,0 +1,146 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.options;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+import org.jclouds.joyent.sdc.v6_5.features.PackageClient;
+import org.jclouds.util.Maps2;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+
+/**
+ *
+ * @author Adrian Cole
+ *
+ */
+public class CreateMachineOptions extends BaseHttpRequestOptions {
+ private String name;
+ private String pkg;
+ private Map<String, String> metadata = ImmutableMap.of();
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object instanceof CreateMachineOptions) {
+ final CreateMachineOptions other = CreateMachineOptions.class.cast(object);
+ return equal(name, other.name) && equal(pkg, other.pkg) && equal(metadata, other.metadata);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name, pkg, metadata);
+ }
+
+ @Override
+ public String toString() {
+ ToStringHelper toString = Objects.toStringHelper("").omitNullValues();
+ toString.add("name", name).add("package", name);
+ if (metadata.size() > 0)
+ toString.add("metadata", metadata);
+ return toString.toString();
+ }
+
+ @Override
+ public Multimap<String, String> buildQueryParameters() {
+ Multimap<String, String> params = super.buildQueryParameters();
+ if (name != null)
+ params.put("name", name);
+ if (pkg != null)
+ params.put("package", pkg);
+ params.putAll(Multimaps.forMap(Maps2.transformKeys(metadata, new Function<String, String>() {
+
+ @Override
+ public String apply(String input) {
+ return "metadata." + input;
+ }
+
+ })));
+ return params;
+ }
+
+ /**
+ * friendly name for this machine; default is a randomly generated name
+ */
+ public CreateMachineOptions name(String name) {
+ this.name = checkNotNull(name, "name");
+ return this;
+ }
+
+ /**
+ * Name of the package to use on provisioning; default is indicated in
+ * {@link PackageClient#list}
+ */
+ public CreateMachineOptions packageName(String packageName) {
+ this.pkg = checkNotNull(packageName, "packageName");
+ return this;
+ }
+
+ /**
+ * An arbitrary set of metadata key/value pairs.
+ */
+ public CreateMachineOptions metadata(Map<String, String> metadata) {
+ checkNotNull(metadata, "metadata");
+ this.metadata = ImmutableMap.copyOf(metadata);
+ return this;
+ }
+
+ public static class Builder {
+
+ /**
+ * @see CreateMachineOptions#name
+ */
+ public static CreateMachineOptions name(String name) {
+ CreateMachineOptions options = new CreateMachineOptions();
+ return options.name(name);
+ }
+
+ /**
+ * @see CreateMachineOptions#packageName
+ */
+ public static CreateMachineOptions packageName(String packageName) {
+ CreateMachineOptions options = new CreateMachineOptions();
+ return options.packageName(packageName);
+ }
+
+ /**
+ * @see CreateMachineOptions#metadata(Map<String, String>)
+ */
+ public static CreateMachineOptions metadata(Map<String, String> metadata) {
+ CreateMachineOptions options = new CreateMachineOptions();
+ return options.metadata(metadata);
+ }
+
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/options/CreateServerOptions.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/options/CreateServerOptions.java
deleted file mode 100644
index 631b69f..0000000
--- a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/options/CreateServerOptions.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.options;
-
-import static com.google.common.base.Objects.equal;
-import static com.google.common.base.Objects.toStringHelper;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Map;
-
-import javax.inject.Inject;
-
-import org.jclouds.http.HttpRequest;
-import org.jclouds.rest.MapBinder;
-import org.jclouds.rest.binders.BindToJsonPayload;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Objects.ToStringHelper;
-import com.google.common.collect.ImmutableMap;
-import com.google.gson.annotations.SerializedName;
-
-/**
- *
- * @author Gerald Pereira
- *
- */
-public class CreateServerOptions implements MapBinder {
- @Inject
- private BindToJsonPayload jsonBinder;
-
- private Map<String, String> metadata = ImmutableMap.of();
- private Map<String, String> tag = ImmutableMap.of();
-
- @Override
- public boolean equals(Object object) {
- if (this == object) {
- return true;
- }
- if (object instanceof CreateServerOptions) {
- final CreateServerOptions other = CreateServerOptions.class.cast(object);
- return equal(tag, tag) && equal(metadata, other.metadata);
- } else {
- return false;
- }
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(tag, metadata);
- }
-
- protected ToStringHelper string() {
- return toStringHelper("").add("metadata", metadata).add("tag", tag);
- }
-
- @Override
- public String toString() {
- return string().toString();
- }
-
- @Override
- public <R extends HttpRequest> R bindToRequest(R request, Object input) {
- return jsonBinder.bindToRequest(request, input);
- }
-
- @Override
- public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
- MachineRequest machine = new MachineRequest(checkNotNull(postParams.get("name"), "name parameter not present")
- .toString(), checkNotNull(postParams.get("package"), "package parameter not present").toString(),
- checkNotNull(postParams.get("dataset"), "dataset parameter not present").toString());
-
- if (metadata.size() > 0)
- machine.metadata = metadata;
- if (tag.size() > 0)
- machine.tag = tag;
-
- return bindToRequest(request, machine);
- }
-
- /**
- * An arbitrary set of metadata key/value pairs can be set at provision time, but they must be
- * prefixed with "metadata."
- */
- public CreateServerOptions metadata(Map<String, String> metadata) {
- checkNotNull(metadata, "metadata");
- this.metadata = ImmutableMap.copyOf(metadata);
- return this;
- }
-
- /**
- * An arbitrary set of tags can be set at provision time, but they must be prefixed with "tag."
- */
- public CreateServerOptions tag(Map<String, String> tag) {
- checkNotNull(tag, "tag");
- this.tag = ImmutableMap.copyOf(tag);
- return this;
- }
-
- @SuppressWarnings("unused")
- private class MachineRequest {
- final String name;
- @SerializedName("package")
- final String packageSDC;
- final String dataset;
- Map<String, String> metadata;
- Map<String, String> tag;
-
- private MachineRequest(String name, String packageSDC, String dataset) {
- this.name = name;
- this.packageSDC = packageSDC;
- this.dataset = dataset;
- }
-
- }
-
- public static class Builder {
-
- /**
- * @see CreateServerOptions#metadata(Map<String, String>)
- */
- public static CreateServerOptions metadata(Map<String, String> metadata) {
- CreateServerOptions options = new CreateServerOptions();
- return options.metadata(metadata);
- }
-
- /**
- * @see CreateServerOptions#tag(Map<String, String>)
- */
- public static CreateServerOptions tag(Map<String, String> tag) {
- CreateServerOptions options = new CreateServerOptions();
- return options.tag(tag);
- }
- }
-
-}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/predicates/KeyPredicates.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/predicates/KeyPredicates.java
new file mode 100644
index 0000000..c5963b1
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/predicates/KeyPredicates.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.predicates;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+
+import com.google.common.base.Predicate;
+
+/**
+ * Predicates handy when working with Keys
+ *
+ * @author Adrian Cole
+ */
+
+public class KeyPredicates {
+
+
+ /**
+ * matches name of the given key pair
+ *
+ * @param name
+ * @return predicate that matches name
+ */
+ public static Predicate<Key> nameMatches(final Predicate<String> name) {
+ checkNotNull(name, "name must be defined");
+
+ return new Predicate<Key>() {
+ @Override
+ public boolean apply(Key ext) {
+ return name.apply(ext.getName());
+ }
+
+ @Override
+ public String toString() {
+ return "nameMatches(" + name + ")";
+ }
+ };
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/reference/MetadataKeys.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/reference/MetadataKeys.java
new file mode 100644
index 0000000..1d3a657
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/reference/MetadataKeys.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.reference;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * Known keys for metadata
+ *
+ * @author Adrian Cole
+ */
+public enum MetadataKeys {
+ ROOT_AUTHORIZED_KEYS(TypeToken.of(String.class).getType()),
+ /**
+ * If the dataset you create a machine from is set to generate passwords for
+ * you, the username/password pairs will be returned in the metadata response
+ * as a nested object, like:
+ *
+ * <pre>
+ * "credentials": {
+ * "root": "s8v9kuht5e",
+ * "admin": "mf4bteqhpy"
+ * }
+ * </pre>
+ */
+ CREDENTIALS(new TypeToken<Map<String, String>>() {
+ private static final long serialVersionUID = -433136967305618708L;
+ }.getType());
+
+ private final Type valueType;
+
+ MetadataKeys(Type valueType) {
+ this.valueType = valueType;
+ }
+
+ public String key() {
+ return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_UNDERSCORE, name());
+ }
+
+ /**
+ * type of the value;
+ */
+ public Type type() {
+ return valueType;
+ }
+
+}
diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/suppliers/ZoneIdToURIFromDatacentersClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/suppliers/ZoneIdToURIFromDatacentersClient.java
new file mode 100644
index 0000000..06d14a1
--- /dev/null
+++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/suppliers/ZoneIdToURIFromDatacentersClient.java
@@ -0,0 +1,35 @@
+package org.jclouds.joyent.sdc.v6_5.suppliers;
+
+import java.net.URI;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.joyent.sdc.v6_5.features.DatacenterClient;
+import org.jclouds.location.suppliers.ZoneIdToURISupplier;
+import org.jclouds.util.Suppliers2;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.Maps;
+
+@Singleton
+public class ZoneIdToURIFromDatacentersClient implements ZoneIdToURISupplier {
+
+ private final DatacenterClient client;
+
+ @Inject
+ public ZoneIdToURIFromDatacentersClient(DatacenterClient client) {
+ this.client = client;
+ }
+
+ @Override
+ public Map<String, Supplier<URI>> get() {
+ return Maps.transformValues(client.getDatacenters(), Suppliers2.<URI> ofInstanceFunction());
+ }
+
+ @Override
+ public String toString() {
+ return "getDatacenters()";
+ }
+}
\ No newline at end of file
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/SDCClientExpectTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/SDCClientExpectTest.java
new file mode 100644
index 0000000..901f943
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/SDCClientExpectTest.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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
+ *
+ * Unles 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 expres or implied. See the License for the
+ * specific language governing permisions and limitations
+ * under the License.
+ */
+package org.jclouds.joyent.sdc.v6_5;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.joyent.sdc.v6_5.internal.BaseSDCClientExpectTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "SDCClientExpectTest")
+public class SDCClientExpectTest extends BaseSDCClientExpectTest {
+
+ public void testGetConfiguredDatacenters() {
+
+ SDCClient clientWhenDatacentersExists = requestSendsResponse(getDatacenters, getDatacentersResponse);
+
+ assertEquals(
+ clientWhenDatacentersExists.getConfiguredDatacenters(),
+ ImmutableSet.<String> builder()
+ .add("us-east-1")
+ .add("us-west-1")
+ .add("us-sw-1")
+ .add("eu-ams-1").build());
+ }
+
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/SDCClientLiveTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/SDCClientLiveTest.java
new file mode 100644
index 0000000..4060e79
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/SDCClientLiveTest.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Set;
+
+import org.jclouds.joyent.sdc.v6_5.internal.BaseSDCClientLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "SDCClientLiveTest")
+public class SDCClientLiveTest extends BaseSDCClientLiveTest {
+
+ public void testGetDatacenters() {
+ Set<String> dcs = sdcContext.getApi().getConfiguredDatacenters();
+ assertEquals(dcs, sdcContext.getApi().getDatacenterClient().getDatacenters().keySet());
+ }
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/SDCComputeServiceLiveTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/SDCComputeServiceLiveTest.java
new file mode 100644
index 0000000..dac1eef
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/SDCComputeServiceLiveTest.java
@@ -0,0 +1,26 @@
+package org.jclouds.joyent.sdc.v6_5.compute;
+
+import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
+import org.jclouds.sshj.config.SshjSshClientModule;
+import org.testng.annotations.Test;
+
+import com.google.inject.Module;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "SDCComputeServiceLiveTest")
+public class SDCComputeServiceLiveTest extends BaseComputeServiceLiveTest {
+
+ public SDCComputeServiceLiveTest() {
+ provider = "joyent-sdc";
+ }
+
+ @Override
+ protected Module getSshModule() {
+ return new SshjSshClientModule();
+ }
+
+
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetInDatacenterToImageTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetInDatacenterToImageTest.java
new file mode 100644
index 0000000..c517630
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetInDatacenterToImageTest.java
@@ -0,0 +1,94 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.functions;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Map;
+
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.joyent.sdc.v6_5.domain.Dataset;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatasetInDatacenter;
+import org.jclouds.joyent.sdc.v6_5.parse.ParseDatasetTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests the function that transforms sdc-specific images to generic images.
+ *
+ * @author Adrian Cole
+ */
+@Test(testName = "DatasetInDatacenterToHardwareTest")
+public class DatasetInDatacenterToImageTest {
+
+ Location provider = new LocationBuilder().scope(LocationScope.PROVIDER).id("joyent-sdc")
+ .description("joyent-sdc").build();
+ Location zone = new LocationBuilder().id("us-sw-1").description("us-sw-1").scope(LocationScope.ZONE)
+ .parent(provider).build();
+ Supplier<Map<String, Location>> locationIndex = Suppliers.<Map<String, Location>> ofInstance(ImmutableMap
+ .<String, Location> of("us-sw-1", zone));
+
+ Dataset datasetToConvert = new ParseDatasetTest().expected();
+
+ @Test
+ public void testConversionWhereLocationFound() {
+ OperatingSystem operatingSystem = new OperatingSystem(OsFamily.UBUNTU, "My Test OS", "My Test Version", "x86",
+ "My Test OS", true);
+ DatasetInDatacenterToImage converter = new DatasetInDatacenterToImage(constant(operatingSystem), locationIndex);
+
+ DatasetInDatacenter datasetInZoneToConvert = new DatasetInDatacenter(datasetToConvert, "us-sw-1");
+
+ org.jclouds.compute.domain.Image convertedImage = converter.apply(datasetInZoneToConvert);
+
+ assertEquals(convertedImage.getId(), datasetInZoneToConvert.slashEncode());
+ assertEquals(convertedImage.getProviderId(), datasetToConvert.getId());
+ assertEquals(convertedImage.getLocation(), locationIndex.get().get("us-sw-1"));
+
+ assertEquals(convertedImage.getName(), datasetToConvert.getName());
+ assertEquals(convertedImage.getStatus(), org.jclouds.compute.domain.Image.Status.AVAILABLE);
+ assertEquals(convertedImage.getOperatingSystem(), operatingSystem);
+ assertEquals(convertedImage.getDescription(), datasetToConvert.getUrn());
+ assertEquals(convertedImage.getVersion(), datasetToConvert.getVersion());
+ }
+
+ @Test(expectedExceptions = IllegalStateException.class)
+ public void testConversionWhereLocationNotFound() {
+ OperatingSystem operatingSystem = new OperatingSystem(OsFamily.UBUNTU, "My Test OS", "My Test Version", "x86",
+ "My Test OS", true);
+ DatasetInDatacenterToImage converter = new DatasetInDatacenterToImage(constant(operatingSystem), locationIndex);
+
+ DatasetInDatacenter datasetInZoneToConvert = new DatasetInDatacenter(datasetToConvert, "South");
+
+ converter.apply(datasetInZoneToConvert);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Function<Dataset, OperatingSystem> constant(OperatingSystem operatingSystem) {
+ return Function.class.cast(Functions.constant(operatingSystem));
+ }
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetToOperatingSystemTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetToOperatingSystemTest.java
new file mode 100644
index 0000000..8c014a3
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/DatasetToOperatingSystemTest.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.functions;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.joyent.sdc.v6_5.domain.Dataset;
+import org.jclouds.joyent.sdc.v6_5.parse.ParseDatasetTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests for the function for transforming a sdc specific Image into a generic
+ * OperatingSystem object.
+ *
+ * @author Adrian Cole
+ */
+@Test(testName = "DatasetToOperatingSystemTest")
+public class DatasetToOperatingSystemTest {
+
+ public void testCentos6() {
+
+ Dataset datasetToConvert = new ParseDatasetTest().expected();
+
+ OperatingSystem convertedOs = new DatasetToOperatingSystem(ImmutableMap.<OsFamily, Map<String, String>> of(
+ OsFamily.CENTOS, ImmutableMap.of("6", "6.0"))).apply(datasetToConvert);
+
+ assertEquals(convertedOs.getName(), datasetToConvert.getName());
+ assertEquals(convertedOs.getFamily(), OsFamily.CENTOS);
+ assertEquals(convertedOs.getDescription(), datasetToConvert.getUrn());
+ assertEquals(convertedOs.getVersion(), "6.0");
+ assertEquals(convertedOs.getArch(), null);
+ assertTrue(convertedOs.is64Bit());
+ }
+
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/MachineInDatacenterToNodeMetadataTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/MachineInDatacenterToNodeMetadataTest.java
new file mode 100644
index 0000000..2ff1ac0
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/MachineInDatacenterToNodeMetadataTest.java
@@ -0,0 +1,142 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.functions;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.internal.VolumeImpl;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.joyent.sdc.v6_5.compute.config.SDCComputeServiceContextModule;
+import org.jclouds.joyent.sdc.v6_5.domain.Machine;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.MachineInDatacenter;
+import org.jclouds.joyent.sdc.v6_5.parse.ParseCreatedMachineTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Guice;
+
+/**
+ * Tests for the function for transforming a sdc specific Machine into a generic
+ * NodeMetadata object.
+ *
+ * @author Adrian Cole
+ */
+@Test(testName = "MachineInDatacenterToNodeMetadataTest")
+public class MachineInDatacenterToNodeMetadataTest {
+
+ Location provider = new LocationBuilder().scope(LocationScope.PROVIDER).id("joyent-sdc")
+ .description("joyent-sdc").build();
+ Location zone = new LocationBuilder().id("us-sw-1").description("us-sw-1").scope(LocationScope.ZONE)
+ .parent(provider).build();
+ Supplier<Map<String, Location>> locationIndex = Suppliers.<Map<String, Location>> ofInstance(ImmutableMap
+ .<String, Location> of("us-sw-1", zone));
+
+ GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(
+ GroupNamingConvention.Factory.class);
+
+ @Test
+ public void testWhenNoHardwareOrImageMatchImageIdIsStillSet() {
+
+ Hardware existingHardware = new HardwareBuilder().id("us-sw-1/FOOOOOOOO").providerId("FOOOOOOOO").location(zone)
+ .build();
+ Image existingImage = new ImageBuilder().id("us-sw-1/FOOOOOOOO")
+ .operatingSystem(OperatingSystem.builder().family(OsFamily.LINUX).description("foobuntu").build())
+ .providerId("FOOOOOOOO").description("foobuntu").location(zone).status(Image.Status.AVAILABLE).build();
+
+ checkHardwareAndImageStatus(null, existingHardware, "us-sw-1/sdc:sdc:centos-5.7:1.2.1", null, existingImage);
+ }
+
+ @Test
+ public void testWhenHardwareAndImageMatchHardwareOperatingSystemAndImageIdAreSet() {
+
+ Hardware existingHardware = new HardwareBuilder().id("us-sw-1/Small 1GB").providerId("Small 1GB").ram(1024)
+ .volume(new VolumeImpl(Float.valueOf(61440), true, true)).location(zone).build();
+ Image existingImage = new ImageBuilder().id("us-sw-1/sdc:sdc:centos-5.7:1.2.1")
+ .operatingSystem(OperatingSystem.builder().family(OsFamily.LINUX).description("foobuntu").build())
+ .providerId("sdc:sdc:centos-5.7:1.2.1").description("foobuntu").status(Image.Status.AVAILABLE)
+ .location(zone).build();
+
+ checkHardwareAndImageStatus(existingHardware, existingHardware, existingImage.getId(),
+ existingImage.getOperatingSystem(), existingImage);
+ }
+
+ // TODO: clean up this syntax
+ private void checkHardwareAndImageStatus(Hardware expectedHardware, Hardware existingHardware,
+ String expectedImageId, OperatingSystem expectedOs, Image existingImage) {
+
+ Set<Image> images = existingImage == null ? ImmutableSet.<Image> of() : ImmutableSet.of(existingImage);
+ Set<Hardware> hardwares = existingHardware == null ? ImmutableSet.<Hardware> of() : ImmutableSet
+ .of(existingHardware);
+ Machine machineToConvert = new ParseCreatedMachineTest().expected();
+
+ MachineInDatacenter machineInDatacenterToConvert = new MachineInDatacenter(machineToConvert, "us-sw-1");
+
+ MachineInDatacenterToNodeMetadata converter = new MachineInDatacenterToNodeMetadata(
+ SDCComputeServiceContextModule.toPortableNodeStatus, locationIndex,
+ Suppliers.<Set<? extends Image>> ofInstance(images),
+ Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
+
+ NodeMetadata convertedNodeMetadata = converter.apply(machineInDatacenterToConvert);
+
+ assertEquals(machineInDatacenterToConvert.slashEncode(), convertedNodeMetadata.getId());
+ assertEquals(machineToConvert.getId(), convertedNodeMetadata.getProviderId());
+
+ assertEquals(convertedNodeMetadata.getLocation().getScope(), LocationScope.ZONE);
+ assertEquals(convertedNodeMetadata.getLocation().getId(), "us-sw-1");
+
+ assertEquals(machineToConvert.getName(), convertedNodeMetadata.getName());
+ assertEquals(convertedNodeMetadata.getGroup(), "sample");
+
+ assertEquals(convertedNodeMetadata.getImageId(), expectedImageId);
+ assertEquals(convertedNodeMetadata.getOperatingSystem(), expectedOs);
+
+ assertEquals(convertedNodeMetadata.getHardware(), expectedHardware);
+
+ assertEquals(SDCComputeServiceContextModule.toPortableNodeStatus.get(machineToConvert.getState()),
+ convertedNodeMetadata.getStatus());
+
+ assertNotNull(convertedNodeMetadata.getPrivateAddresses());
+ assertEquals(convertedNodeMetadata.getPrivateAddresses(), ImmutableSet.of("10.224.0.63"));
+
+ assertNotNull(convertedNodeMetadata.getPublicAddresses());
+ assertEquals(convertedNodeMetadata.getPublicAddresses(), ImmutableSet.of("37.153.96.62"));
+
+ assertNotNull(convertedNodeMetadata.getUserMetadata());
+ // ensure filtered out root_authorized_keys!
+ assertEquals(convertedNodeMetadata.getUserMetadata(), ImmutableMap.<String, String> of());
+ }
+
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/OrphanedGroupsByDatacenterIdTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/OrphanedGroupsByDatacenterIdTest.java
new file mode 100644
index 0000000..0d61775
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/OrphanedGroupsByDatacenterIdTest.java
@@ -0,0 +1,100 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.functions;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.joyent.sdc.v6_5.compute.config.SDCComputeServiceContextModule;
+import org.jclouds.joyent.sdc.v6_5.domain.Machine.State;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatacenterAndName;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.MachineInDatacenter;
+import org.jclouds.joyent.sdc.v6_5.parse.ParseMachineTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Guice;
+
+/**
+ *
+ *
+ * @author Adrian Cole
+ */
+@Test(testName = "OrphanedGroupsByDatacenterIdTest")
+public class OrphanedGroupsByDatacenterIdTest {
+
+ Location provider = new LocationBuilder().scope(LocationScope.PROVIDER).id("joyent-sdc").description(
+ "joyent-sdc").build();
+ Location datacenter = new LocationBuilder().id("us-east-1").description("us-east-1").scope(
+ LocationScope.ZONE).parent(provider).build();
+ Supplier<Map<String, Location>> locationIndex = Suppliers.<Map<String, Location>> ofInstance(ImmutableMap
+ .<String, Location> of("us-east-1", datacenter));
+
+ GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
+
+ MachineInDatacenter machine1 = new MachineInDatacenter(new ParseMachineTest().expected().toBuilder().name("test-fe2").state(State.DELETED).build(), "us-east-1");
+ MachineInDatacenter machine2 = new MachineInDatacenter(new ParseMachineTest().expected().toBuilder().name("sample-fe1").state(State.DELETED).build(), "us-east-1");
+
+ @Test
+ public void testWhenComputeServiceSaysAllNodesAreDeadBothGroupsAreReturned() {
+
+
+ MachineInDatacenterToNodeMetadata converter = new MachineInDatacenterToNodeMetadata(
+ SDCComputeServiceContextModule.toPortableNodeStatus, locationIndex, Suppliers
+ .<Set<? extends Image>> ofInstance(ImmutableSet.<Image> of()), Suppliers
+ .<Set<? extends Hardware>> ofInstance(ImmutableSet.<Hardware> of()), namingConvention);
+
+ Set<? extends NodeMetadata> set = ImmutableSet.of(converter.apply(machine2), converter.apply(machine1));
+
+ assertEquals(new OrphanedGroupsByDatacenterId(Predicates.<DatacenterAndName> alwaysTrue()).apply(set), ImmutableMultimap
+ .<String, String> builder().putAll("us-east-1", "sample", "test").build());
+ }
+
+ @Test
+ public void testWhenComputeServiceSaysAllNodesAreDeadNoGroupsAreReturned() {
+
+ MachineInDatacenter machine1 = new MachineInDatacenter(new ParseMachineTest().expected(), "us-east-1");
+ MachineInDatacenter machine2 = new MachineInDatacenter(new ParseMachineTest().expected(), "us-east-1");
+
+ MachineInDatacenterToNodeMetadata converter = new MachineInDatacenterToNodeMetadata(
+ SDCComputeServiceContextModule.toPortableNodeStatus, locationIndex, Suppliers
+ .<Set<? extends Image>> ofInstance(ImmutableSet.<Image> of()), Suppliers
+ .<Set<? extends Hardware>> ofInstance(ImmutableSet.<Hardware> of()), namingConvention);
+
+ Set<? extends NodeMetadata> set = ImmutableSet.of(converter.apply(machine2), converter.apply(machine1));
+
+ assertEquals(new OrphanedGroupsByDatacenterId(Predicates.<DatacenterAndName> alwaysFalse()).apply(set), ImmutableMultimap
+ .<String, String> of());
+
+ }
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/PackageInDatacenterToHardwareTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/PackageInDatacenterToHardwareTest.java
new file mode 100644
index 0000000..8a88530
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/functions/PackageInDatacenterToHardwareTest.java
@@ -0,0 +1,88 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.functions;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Map;
+
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.joyent.sdc.v6_5.domain.Package;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.PackageInDatacenter;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests the function used to transform Package objects into Hardware objects
+ *
+ * @author Adrian Cole
+ */
+@Test(testName = "PackageInDatacenterToHardwareTest")
+public class PackageInDatacenterToHardwareTest {
+ Location provider = new LocationBuilder().scope(LocationScope.PROVIDER).id("joyent-sdc").description(
+ "joyent-sdc").build();
+ Location zone = new LocationBuilder().id("us-sw-1").description("us-sw-1").scope(
+ LocationScope.ZONE).parent(provider).build();
+ Supplier<Map<String, Location>> locationIndex = Suppliers.<Map<String, Location>> ofInstance(ImmutableMap
+ .<String, Location> of("us-sw-1", zone));
+
+ Package packageToConvert = org.jclouds.joyent.sdc.v6_5.domain.Package.builder().name("Small 1GB").memorySizeMb(1024)
+ .diskSizeGb(30720).swapSizeMb(2048).isDefault(true).build();
+
+ @Test
+ public void testConversionWhereLocationFound() {
+
+ PackageInDatacenter packageInZoneToConvert = new PackageInDatacenter(packageToConvert, "us-sw-1");
+
+ Hardware converted = new PackageInDatacenterToHardware(locationIndex).apply(packageInZoneToConvert);
+
+ assertEquals(converted.getName(), packageToConvert.getName());
+ assertEquals(converted.getId(), packageInZoneToConvert.slashEncode());
+ assertEquals(converted.getProviderId(), packageToConvert.getName());
+ assertEquals(converted.getLocation(), locationIndex.get().get("us-sw-1"));
+
+ assertEquals(converted.getRam(), packageToConvert.getMemorySizeMb());
+
+//TODO!
+// assertNotNull(converted.getProcessors());
+// assertFalse(converted.getProcessors().isEmpty());
+// assertEquals(converted.getProcessors().iterator().next().getCores(), (double) packageToConvert.getVcpus());
+
+ assertNotNull(converted.getVolumes());
+ assertFalse(converted.getVolumes().isEmpty());
+ assertEquals(converted.getVolumes().iterator().next().getSize(), Float.valueOf(packageToConvert.getDiskSizeGb()));
+
+ }
+
+ @Test(expectedExceptions = IllegalStateException.class)
+ public void testConversionWhereLocationNotFound() {
+
+ PackageInDatacenter packageInZoneToConvert = new PackageInDatacenter(packageToConvert, "South");
+ new PackageInDatacenterToHardware(locationIndex).apply(packageInZoneToConvert);
+ }
+
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/loaders/CreateUniqueKeyTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/loaders/CreateUniqueKeyTest.java
new file mode 100644
index 0000000..9e2a4a2
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/loaders/CreateUniqueKeyTest.java
@@ -0,0 +1,118 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.loaders;
+
+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.crypto.PemsTest.PRIVATE_KEY;
+import static org.jclouds.crypto.PemsTest.PUBLIC_KEY;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.functions.GroupNamingConvention.Factory;
+import org.jclouds.crypto.Crypto;
+import org.jclouds.crypto.Pems;
+import org.jclouds.crypto.SshKeys;
+import org.jclouds.io.Payloads;
+import org.jclouds.joyent.sdc.v6_5.SDCClient;
+import org.jclouds.joyent.sdc.v6_5.compute.internal.KeyAndPrivateKey;
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+import org.jclouds.joyent.sdc.v6_5.domain.datacenterscoped.DatacenterAndName;
+import org.jclouds.joyent.sdc.v6_5.features.KeyClient;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.TypeLiteral;
+import com.google.inject.util.Providers;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "CreateUniqueKeyTest")
+public class CreateUniqueKeyTest {
+ private Factory namingConvention;
+ private KeyPair keyPair;
+ private String openSshKey;
+
+ @BeforeClass
+ public void setup() throws InvalidKeySpecException, NoSuchAlgorithmException, IOException {
+ namingConvention = Guice.createInjector(new AbstractModule() {
+
+ @Override
+ protected void configure() {
+ bind(new TypeLiteral<Supplier<String>>() {
+ }).toInstance(Suppliers.ofInstance("foo"));
+ }
+ }).getInstance(GroupNamingConvention.Factory.class);
+ KeyFactory keyfactory = KeyFactory.getInstance("RSA");
+ PrivateKey privateKey = keyfactory.generatePrivate(Pems.privateKeySpec(Payloads.newStringPayload(PRIVATE_KEY)));
+
+ PublicKey publicKey = keyfactory
+ .generatePublic(Pems.publicKeySpec(Payloads.newStringPayload(PUBLIC_KEY)));
+
+ keyPair = new KeyPair(publicKey, privateKey);
+ openSshKey = SshKeys.encodeAsOpenSSH(RSAPublicKey.class.cast(publicKey));
+ }
+
+ @Test
+ public void testApply() {
+ SDCClient sdcClient = createMock(SDCClient.class);
+ KeyClient keyClient = createMock(KeyClient.class);
+ Crypto crypto = createMock(Crypto.class);
+ KeyPairGenerator rsaKeyPairGenerator = createMock(KeyPairGenerator.class);
+ SecureRandom secureRandom = createMock(SecureRandom.class);
+
+ Key key = Key.builder().name("group-foo").key(openSshKey).build();
+
+ expect(crypto.rsaKeyPairGenerator()).andReturn(rsaKeyPairGenerator);
+ rsaKeyPairGenerator.initialize(2048, secureRandom);
+ expect(rsaKeyPairGenerator.genKeyPair()).andReturn(keyPair);
+
+ expect(sdcClient.getKeyClient()).andReturn(keyClient);
+
+ expect(keyClient.create(key)).andReturn(key);
+
+ replay(sdcClient, keyClient, crypto, rsaKeyPairGenerator, secureRandom);
+
+ CreateUniqueKey parser = new CreateUniqueKey(sdcClient, namingConvention, crypto, Providers.of(secureRandom));
+
+ assertEquals(parser.load(DatacenterAndName.fromDatacenterAndName("datacenter", "group")),
+ KeyAndPrivateKey.fromKeyAndPrivateKey(key, PRIVATE_KEY));
+
+ verify(sdcClient, keyClient, crypto, rsaKeyPairGenerator, secureRandom);
+ }
+
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/options/SDCTemplateOptionsTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/options/SDCTemplateOptionsTest.java
new file mode 100644
index 0000000..bf75a90
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/compute/options/SDCTemplateOptionsTest.java
@@ -0,0 +1,181 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.compute.options;
+
+import static org.jclouds.joyent.sdc.v6_5.compute.options.SDCTemplateOptions.Builder.authorizePublicKey;
+import static org.jclouds.joyent.sdc.v6_5.compute.options.SDCTemplateOptions.Builder.blockOnPort;
+import static org.jclouds.joyent.sdc.v6_5.compute.options.SDCTemplateOptions.Builder.generateKey;
+import static org.jclouds.joyent.sdc.v6_5.compute.options.SDCTemplateOptions.Builder.inboundPorts;
+import static org.jclouds.joyent.sdc.v6_5.compute.options.SDCTemplateOptions.Builder.installPrivateKey;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.jclouds.compute.options.TemplateOptions;
+import org.testng.annotations.Test;
+
+/**
+ * Tests possible uses of SDCTemplateOptions and SDCTemplateOptions.Builder.*
+ *
+ * @author Adrian Cole
+ */
+@Test(testName = "SDCTemplateOptionsTest")
+public class SDCTemplateOptionsTest {
+
+ public void testAs() {
+ TemplateOptions options = new SDCTemplateOptions();
+ assertEquals(options.as(SDCTemplateOptions.class), options);
+ }
+
+ @Test
+ public void testGenerateKeyDefault() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ assert !options.shouldGenerateKey();
+ }
+
+ @Test
+ public void testGenerateKey() {
+ SDCTemplateOptions options = new SDCTemplateOptions().generateKey(true);
+ assert options.shouldGenerateKey();
+ }
+
+ @Test
+ public void testGenerateKeyStatic() {
+ SDCTemplateOptions options = generateKey(true);
+ assert options.shouldGenerateKey();
+ }
+
+ // superclass tests
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testinstallPrivateKeyBadFormat() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ options.installPrivateKey("whompy");
+ }
+
+ @Test
+ public void testinstallPrivateKey() throws IOException {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ options.installPrivateKey("-----BEGIN RSA PRIVATE KEY-----");
+ assertEquals(options.getPrivateKey(), "-----BEGIN RSA PRIVATE KEY-----");
+ }
+
+ @Test
+ public void testNullinstallPrivateKey() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ assertEquals(options.getPrivateKey(), null);
+ }
+
+ @Test
+ public void testinstallPrivateKeyStatic() throws IOException {
+ SDCTemplateOptions options = installPrivateKey("-----BEGIN RSA PRIVATE KEY-----");
+ assertEquals(options.getPrivateKey(), "-----BEGIN RSA PRIVATE KEY-----");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testinstallPrivateKeyNPE() {
+ installPrivateKey(null);
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testauthorizePublicKeyBadFormat() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ options.authorizePublicKey("whompy");
+ }
+
+ @Test
+ public void testauthorizePublicKey() throws IOException {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ options.authorizePublicKey("ssh-rsa");
+ assertEquals(options.getPublicKey(), "ssh-rsa");
+ }
+
+ @Test
+ public void testNullauthorizePublicKey() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ assertEquals(options.getPublicKey(), null);
+ }
+
+ @Test
+ public void testauthorizePublicKeyStatic() throws IOException {
+ SDCTemplateOptions options = authorizePublicKey("ssh-rsa");
+ assertEquals(options.getPublicKey(), "ssh-rsa");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testauthorizePublicKeyNPE() {
+ authorizePublicKey(null);
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testblockOnPortBadFormat() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ options.blockOnPort(-1, -1);
+ }
+
+ @Test
+ public void testblockOnPort() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ options.blockOnPort(22, 30);
+ assertEquals(options.getPort(), 22);
+ assertEquals(options.getSeconds(), 30);
+
+ }
+
+ @Test
+ public void testNullblockOnPort() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ assertEquals(options.getPort(), -1);
+ assertEquals(options.getSeconds(), -1);
+ }
+
+ @Test
+ public void testblockOnPortStatic() {
+ SDCTemplateOptions options = blockOnPort(22, 30);
+ assertEquals(options.getPort(), 22);
+ assertEquals(options.getSeconds(), 30);
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testinboundPortsBadFormat() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ options.inboundPorts(-1, -1);
+ }
+
+ @Test
+ public void testinboundPorts() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ options.inboundPorts(22, 30);
+ assertEquals(options.getInboundPorts()[0], 22);
+ assertEquals(options.getInboundPorts()[1], 30);
+
+ }
+
+ @Test
+ public void testDefaultOpen22() {
+ SDCTemplateOptions options = new SDCTemplateOptions();
+ assertEquals(options.getInboundPorts()[0], 22);
+ }
+
+ @Test
+ public void testinboundPortsStatic() {
+ SDCTemplateOptions options = inboundPorts(22, 30);
+ assertEquals(options.getInboundPorts()[0], 22);
+ assertEquals(options.getInboundPorts()[1], 30);
+ }
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClientExpectTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClientExpectTest.java
index 07a6623..2dc69ab 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClientExpectTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClientExpectTest.java
@@ -22,32 +22,20 @@
import java.net.URI;
-import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.joyent.sdc.v6_5.SDCClient;
import org.jclouds.joyent.sdc.v6_5.internal.BaseSDCClientExpectTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "DatacenterClientExpectTest")
public class DatacenterClientExpectTest extends BaseSDCClientExpectTest {
- HttpRequest getDatacenters = HttpRequest
- .builder()
- .method("GET")
- .endpoint(URI.create("https://api.joyentcloud.com/my/datacenters"))
- .headers(
- ImmutableMultimap.<String, String> builder().put("X-Api-Version", "~6.5")
- .put("Accept", "application/json").put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==")
- .build()).build();
public void testGetDatacentersWhenResponseIs2xx() {
- HttpResponse getDatacentersResponse = HttpResponse.builder().statusCode(200)
- .payload(payloadFromResource("/datacenters.json")).build();
SDCClient clientWhenDatacentersExists = requestSendsResponse(getDatacenters, getDatacentersResponse);
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClientExpectTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClientExpectTest.java
index 20575f1..8e0e951 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClientExpectTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClientExpectTest.java
@@ -37,27 +37,27 @@
*/
@Test(groups = "unit", testName = "DatasetClientExpectTest")
public class DatasetClientExpectTest extends BaseSDCClientExpectTest {
- HttpRequest listDatasets = HttpRequest.builder().method("GET").endpoint(
- URI.create("https://api.joyentcloud.com/my/datasets")).headers(
+ HttpRequest list = HttpRequest.builder().method("GET").endpoint(
+ URI.create("https://us-sw-1.api.joyentcloud.com/my/datasets")).headers(
ImmutableMultimap.<String, String> builder().put("X-Api-Version", "~6.5").put("Accept", "application/json")
.put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build();
public void testListDatasetsWhenResponseIs2xx() {
- HttpResponse listDatasetsResponse = HttpResponse.builder().statusCode(200).payload(
+ HttpResponse listResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/dataset_list.json")).build();
- SDCClient clientWhenDatasetsExists = requestSendsResponse(listDatasets, listDatasetsResponse);
+ SDCClient clientWhenDatasetsExists = requestsSendResponses(getDatacenters, getDatacentersResponse, list, listResponse);
- assertEquals(clientWhenDatasetsExists.getDatasetClient().listDatasets().toString(), new ParseDatasetListTest()
+ assertEquals(clientWhenDatasetsExists.getDatasetClientForDatacenter("us-sw-1").list().toString(), new ParseDatasetListTest()
.expected().toString());
}
public void testListDatasetsWhenResponseIs404() {
- HttpResponse listDatasetsResponse = HttpResponse.builder().statusCode(404).build();
+ HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
- SDCClient listDatasetsWhenNone = requestSendsResponse(listDatasets, listDatasetsResponse);
+ SDCClient listWhenNone = requestsSendResponses(getDatacenters, getDatacentersResponse, list, listResponse);
- assertEquals(listDatasetsWhenNone.getDatasetClient().listDatasets(), ImmutableSet.of());
+ assertEquals(listWhenNone.getDatasetClientForDatacenter("us-sw-1").list(), ImmutableSet.of());
}
// [id=e4cd7b9e-4330-11e1-81cf-3bb50a972bda, name=centos-6, type=VIRTUALMACHINE, version=1.0.1,
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClientLiveTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClientLiveTest.java
index 31bf750..0d62c86 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClientLiveTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatasetClientLiveTest.java
@@ -18,9 +18,7 @@
*/
package org.jclouds.joyent.sdc.v6_5.features;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.Assert.assertEquals;
import java.util.Set;
@@ -34,16 +32,22 @@
@Test(groups = "live", testName = "DatasetClientLiveTest")
public class DatasetClientLiveTest extends BaseSDCClientLiveTest {
- public void testListDatasets() {
- Set<Dataset> datasets = sdcContext.getApi().getDatasetClient().listDatasets();
- assertNotNull(datasets);
- assertTrue(datasets.size() > 0);
- }
-
- public void testGetDataset() {
- final String id = "e4cd7b9e-4330-11e1-81cf-3bb50a972bda";
- Dataset dataset = sdcContext.getApi().getDatasetClient().getDataset(id);
- assertNotNull(dataset);
- assertEquals(dataset.getId(), id);
+ @Test
+ public void testListAndGetDatasets() throws Exception {
+ for (String datacenterId : sdcContext.getApi().getConfiguredDatacenters()) {
+ DatasetClient client = sdcContext.getApi().getDatasetClientForDatacenter(datacenterId);
+ Set<Dataset> response = client.list();
+ assert null != response;
+ for (Dataset dataset : response) {
+ Dataset newDetails = client.get(dataset.getId());
+ assertEquals(newDetails.getId(), dataset.getId());
+ assertEquals(newDetails.getName(), dataset.getName());
+ assertEquals(newDetails.getType(), dataset.getType());
+ assertEquals(newDetails.getVersion(), dataset.getVersion());
+ assertEquals(newDetails.getUrn(), dataset.getUrn());
+ assertEquals(newDetails.getCreated(), dataset.getCreated());
+ assertEquals(newDetails.isDefault(), dataset.isDefault());
+ }
+ }
}
}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/KeyClientExpectTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/KeyClientExpectTest.java
new file mode 100644
index 0000000..e8190c8
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/KeyClientExpectTest.java
@@ -0,0 +1,85 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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
+ *
+ * Unles 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 expres or implied. See the License for the
+ * specific language governing permisions and limitations
+ * under the License.
+ */
+package org.jclouds.joyent.sdc.v6_5.features;
+
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.joyent.sdc.v6_5.SDCClient;
+import org.jclouds.joyent.sdc.v6_5.internal.BaseSDCClientExpectTest;
+import org.jclouds.joyent.sdc.v6_5.parse.ParseKeyListTest;
+import org.jclouds.joyent.sdc.v6_5.parse.ParseKeyTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "KeyClientExpectTest")
+public class KeyClientExpectTest extends BaseSDCClientExpectTest {
+ HttpRequest list = HttpRequest.builder().method("GET").endpoint(
+ URI.create("https://api.joyentcloud.com/my/keys")).headers(
+ ImmutableMultimap.<String, String> builder().put("X-Api-Version", "~6.5").put("Accept", "application/json")
+ .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build();
+
+ public void testListKeysWhenResponseIs2xx() {
+ HttpResponse listResponse = HttpResponse.builder().statusCode(200).payload(
+ payloadFromResource("/key_list.json")).build();
+
+ SDCClient clientWhenKeysExists = requestsSendResponses(getDatacenters, getDatacentersResponse, list, listResponse);
+
+ assertEquals(clientWhenKeysExists.getKeyClient().list(), new ParseKeyListTest().expected());
+ }
+
+ public void testListKeysWhenResponseIs404() {
+ HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
+
+ SDCClient listWhenNone = requestsSendResponses(getDatacenters, getDatacentersResponse, list, listResponse);
+
+ assertEquals(listWhenNone.getKeyClient().list(), ImmutableSet.of());
+ }
+
+ public void testCreateKeyWhenResponseIs202() throws Exception {
+ HttpRequest create = HttpRequest
+ .builder()
+ .method("POST")
+ .endpoint(URI.create("https://api.joyentcloud.com/my/keys"))
+ .headers(
+ ImmutableMultimap.<String, String> builder().put("X-Api-Version", "~6.5").put("Accept",
+ "application/json").put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build())
+ .payload(
+ payloadFromStringWithContentType(
+ "{\"name\":\"rsa\",\"key\":\"ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0A5Pf5Cq...\"}",
+ "application/json")).build();
+
+ HttpResponse createResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
+ .payload(payloadFromResourceWithContentType("/key.json", "application/json; charset=UTF-8"))
+ .build();
+
+ SDCClient clientWithNewKey = requestsSendResponses(getDatacenters, getDatacentersResponse, create, createResponse);
+
+ assertEquals(clientWithNewKey.getKeyClient().create(new ParseKeyTest().expected())
+ .toString(), new ParseKeyTest().expected().toString());
+ }
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/KeyClientLiveTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/KeyClientLiveTest.java
new file mode 100644
index 0000000..072b1a5
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/KeyClientLiveTest.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.features;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Set;
+
+import org.jclouds.crypto.SshKeys;
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+import org.jclouds.joyent.sdc.v6_5.internal.BaseSDCClientLiveTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "KeyClientLiveTest")
+public class KeyClientLiveTest extends BaseSDCClientLiveTest {
+
+ @Test
+ public void testListAndGetKeys() throws Exception {
+ KeyClient client = sdcContext.getApi().getKeyClient();
+ Set<Key> response = client.list();
+ assert null != response;
+ for (Key key : response) {
+ Key newDetails = client.get(key.getName());
+ assertEquals(newDetails.getName(), key.getName());
+ assertEquals(newDetails.get(), key.get());
+ assertEquals(newDetails.getCreated(), key.getCreated());
+ }
+
+ }
+
+ private String keyText;
+ private String fingerprint;
+
+ @BeforeTest
+ public void initKeys() {
+ keyText = SshKeys.generate().get("public");
+ fingerprint = SshKeys.fingerprintPublicKey(keyText);
+ }
+
+ public void testCreateKey() {
+ KeyClient client = sdcContext.getApi().getKeyClient();
+
+ Key newKey = client.create(Key.builder().name(fingerprint).key(keyText).build());
+ assertEquals(newKey.getName(), fingerprint);
+ assertEquals(newKey.get(), keyText);
+
+ newKey = client.get(fingerprint);
+ assertEquals(newKey.getName(), fingerprint);
+ assertEquals(newKey.get(), keyText);
+ }
+
+ @Test(dependsOnMethods = "testCreateKey", expectedExceptions = IllegalStateException.class)
+ public void testDuplicateKey() {
+ KeyClient client = sdcContext.getApi().getKeyClient();
+ client.create(Key.builder().name(fingerprint).key(keyText).build());
+ }
+
+ @Test(dependsOnMethods = "testDuplicateKey")
+ public void testDestroyKey() {
+ final KeyClient client = sdcContext.getApi().getKeyClient();
+ client.delete(fingerprint);
+ // not that eventhough the key is destroyed it is visible via GET for at
+ // least 45 seconds. This may be a cache issue on the server
+ }
+
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/MachineClientExpectTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/MachineClientExpectTest.java
index ef7d79f..78b658c 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/MachineClientExpectTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/MachineClientExpectTest.java
@@ -26,6 +26,7 @@
import org.jclouds.http.HttpResponse;
import org.jclouds.joyent.sdc.v6_5.SDCClient;
import org.jclouds.joyent.sdc.v6_5.internal.BaseSDCClientExpectTest;
+import org.jclouds.joyent.sdc.v6_5.options.CreateMachineOptions;
import org.jclouds.joyent.sdc.v6_5.parse.ParseCreatedMachineTest;
import org.jclouds.joyent.sdc.v6_5.parse.ParseMachineListTest;
import org.testng.annotations.Test;
@@ -38,48 +39,50 @@
*/
@Test(groups = "unit", testName = "MachineClientExpectTest")
public class MachineClientExpectTest extends BaseSDCClientExpectTest {
- HttpRequest listMachines = HttpRequest.builder().method("GET").endpoint(
- URI.create("https://api.joyentcloud.com/my/machines")).headers(
+ HttpRequest list = HttpRequest.builder().method("GET").endpoint(
+ URI.create("https://us-sw-1.api.joyentcloud.com/my/machines")).headers(
ImmutableMultimap.<String, String> builder().put("X-Api-Version", "~6.5").put("Accept", "application/json")
.put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build();
public void testListMachinesWhenResponseIs2xx() {
- HttpResponse listMachinesResponse = HttpResponse.builder().statusCode(200).payload(
+ HttpResponse listResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/machine_list.json")).build();
- SDCClient clientWhenMachinesExists = requestSendsResponse(listMachines, listMachinesResponse);
+ SDCClient clientWhenMachinesExists = requestsSendResponses(getDatacenters, getDatacentersResponse, list, listResponse);
- assertEquals(clientWhenMachinesExists.getMachineClient().listMachines(), new ParseMachineListTest().expected());
+ assertEquals(clientWhenMachinesExists.getMachineClientForDatacenter("us-sw-1").list(), new ParseMachineListTest().expected());
}
public void testListMachinesWhenResponseIs404() {
- HttpResponse listMachinesResponse = HttpResponse.builder().statusCode(404).build();
+ HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
- SDCClient listMachinesWhenNone = requestSendsResponse(listMachines, listMachinesResponse);
+ SDCClient listWhenNone = requestsSendResponses(getDatacenters, getDatacentersResponse, list, listResponse);
- assertEquals(listMachinesWhenNone.getMachineClient().listMachines(), ImmutableSet.of());
+ assertEquals(listWhenNone.getMachineClientForDatacenter("us-sw-1").list(), ImmutableSet.of());
}
public void testCreateMachineWhenResponseIs202() throws Exception {
- HttpRequest createMachine = HttpRequest
+ HttpRequest createWithDataset = HttpRequest
.builder()
.method("POST")
- .endpoint(URI.create("https://api.joyentcloud.com/my/machines"))
- .headers(
- ImmutableMultimap.<String, String> builder().put("X-Api-Version", "~6.5").put("Accept",
- "application/json").put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build())
- .payload(
- payloadFromStringWithContentType(
- "{\"name\":\"testJClouds\",\"package\":\"Small 1GB\",\"dataset\":\"sdc:sdc:centos-5.7:1.2.1\"}",
- "application/json")).build();
+ .endpoint(URI.create("https://us-sw-1.api.joyentcloud.com/my/machines?dataset=sdc%3Asdc%3Acentos-5.7%3A1.2.1&name=sample-e92&package=Small%201GB"))
+ .headers(ImmutableMultimap.<String, String> builder()
+ .put("X-Api-Version", "~6.5")
+ .put("Accept", "application/json")
+ .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build())
+ .build();
- HttpResponse createMachineResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
+ HttpResponse createWithDatasetResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/new_machine.json", "application/json; charset=UTF-8"))
.build();
- SDCClient clientWithNewMachine = requestSendsResponse(createMachine, createMachineResponse);
+ SDCClient clientWithNewMachine = requestsSendResponses(getDatacenters, getDatacentersResponse, createWithDataset, createWithDatasetResponse);
- assertEquals(clientWithNewMachine.getMachineClient().createMachine("testJClouds", "Small 1GB",
- "sdc:sdc:centos-5.7:1.2.1").toString(), new ParseCreatedMachineTest().expected().toString());
+ assertEquals(
+ clientWithNewMachine
+ .getMachineClientForDatacenter("us-sw-1")
+ .createWithDataset("sdc:sdc:centos-5.7:1.2.1",
+ CreateMachineOptions.Builder.name("sample-e92").packageName("Small 1GB")).toString(),
+ new ParseCreatedMachineTest().expected().toString());
}
}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/MachineClientLiveTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/MachineClientLiveTest.java
index 7011ce5..25477e1 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/MachineClientLiveTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/MachineClientLiveTest.java
@@ -18,32 +18,158 @@
*/
package org.jclouds.joyent.sdc.v6_5.features;
+import static com.google.common.base.Predicates.not;
import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
+import java.util.Map;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import org.jclouds.compute.domain.ExecResponse;
+import org.jclouds.crypto.SshKeys;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
import org.jclouds.joyent.sdc.v6_5.domain.Machine;
import org.jclouds.joyent.sdc.v6_5.internal.BaseSDCClientLiveTest;
+import org.jclouds.joyent.sdc.v6_5.options.CreateMachineOptions;
+import org.jclouds.joyent.sdc.v6_5.reference.MetadataKeys;
+import org.jclouds.predicates.InetSocketAddressConnect;
+import org.jclouds.predicates.RetryablePredicate;
+import org.jclouds.ssh.SshClient;
+import org.jclouds.sshj.config.SshjSshClientModule;
+import org.jclouds.util.InetAddresses2;
+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.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.net.HostAndPort;
+import com.google.inject.Module;
+
/**
- * @author Gerald Pereira
+ * @author Adrian Cole
*/
@Test(groups = "live", testName = "MachineClientLiveTest")
public class MachineClientLiveTest extends BaseSDCClientLiveTest {
- public void testListMachines() {
- Set<Machine> machines = sdcContext.getApi().getMachineClient().listMachines();
- assertNotNull(machines);
- assertTrue(machines.size() > 0);
+ @Test
+ public void testListAndGetMachines() throws Exception {
+ for (String datacenterId : sdcContext.getApi().getConfiguredDatacenters()) {
+ MachineClient client = sdcContext.getApi().getMachineClientForDatacenter(datacenterId);
+ Set<Machine> response = client.list();
+ assert null != response;
+ for (Machine machine : response) {
+ Machine newDetails = client.get(machine.getId());
+ assertEquals(newDetails.getId(), machine.getId());
+ assertEquals(newDetails.getName(), machine.getName());
+ assertEquals(newDetails.getType(), machine.getType());
+ assertEquals(newDetails.getState(), machine.getState());
+ assertEquals(newDetails.get(), machine.get());
+ assertEquals(newDetails.getMemorySizeMb(), machine.getMemorySizeMb());
+ assertEquals(newDetails.getDiskSizeGb(), machine.getDiskSizeGb());
+ assertEquals(newDetails.getIps(), machine.getIps());
+ assertEquals(newDetails.getCreated(), machine.getCreated());
+ assertEquals(newDetails.getUpdated(), machine.getUpdated());
+ assertEquals(newDetails.getMetadata(), machine.getMetadata());
+ }
+ }
}
- public void testGetMachine() {
- final String id = "d73cb0b0-7d1f-44ef-8c40-e040eef0f726";
- Machine machine = sdcContext.getApi().getMachineClient().getMachine(id);
- assertNotNull(machine);
- assertEquals(machine.getId(), id);
+ private Map<String, String> key;
+ private String fingerprint;
+ private RetryablePredicate<HostAndPort> socketTester;
+ private Predicate<Machine> machineRunning;
+ private MachineClient client;
+ private Machine machine;
+ protected String datasetURN = System.getProperty("test." + provider + ".image-id", "sdc:sdc:ubuntu-10.04:1.0.1");
+ private String name;
+
+ @BeforeGroups(groups = { "integration", "live" })
+ @Override
+ public void setupContext() {
+ super.setupContext();
+ key = SshKeys.generate();
+ fingerprint = SshKeys.fingerprintPublicKey(key.get("public"));
+ sdcContext.getApi().getKeyClient().create(Key.builder().name(fingerprint).key(key.get("public")).build());
+ client = sdcContext.getApi().getMachineClientForDatacenter(
+ Iterables.get(sdcContext.getApi().getConfiguredDatacenters(), 0));
+ socketTester = new RetryablePredicate<HostAndPort>(new InetSocketAddressConnect(), 180, 1, 1, TimeUnit.SECONDS);
+ machineRunning = new RetryablePredicate<Machine>(new Predicate<Machine>() {
+
+ @Override
+ public boolean apply(Machine input) {
+ return client.get(input.getId()).getState() == Machine.State.RUNNING;
+ }
+
+ }, 600, 5, 5, TimeUnit.SECONDS);
+ machineRunning = new RetryablePredicate<Machine>(new Predicate<Machine>() {
+
+ @Override
+ public boolean apply(Machine input) {
+ return client.get(input.getId()).getState() == Machine.State.RUNNING;
+ }
+
+ }, 600, 5, 5, TimeUnit.SECONDS);
+ }
+
+ public void testCreateMachine() {
+ Machine newMachine = client.createWithDataset(datasetURN,
+ CreateMachineOptions.Builder.metadata(ImmutableMap.of("foo", "bar")));
+ machine = newMachine;
+ name = newMachine.getName();
+
+ assertEquals(newMachine.getMetadata().get("foo").toString(), "bar");
+ assertTrue(
+ newMachine.getMetadata().get(MetadataKeys.ROOT_AUTHORIZED_KEYS.key()).indexOf(key.get("public")) != -1,
+ newMachine + "; key: " + key.get("public"));
+
+ assertTrue(machineRunning.apply(newMachine), newMachine.toString());
+ machine = client.get(newMachine.getId());
+
+ }
+
+ @Test(dependsOnMethods = "testCreateMachine", expectedExceptions = IllegalStateException.class)
+ public void testDuplicateMachineThrowsIllegalStateException() {
+ client.createWithDataset(datasetURN, CreateMachineOptions.Builder.name(name));
+ }
+
+ @Test(dependsOnMethods = "testCreateMachine")
+ protected void testSsh() {
+ String publicAddress = Iterables.find(machine.getIps(), not(InetAddresses2.IsPrivateIPAddress.INSTANCE));
+ HostAndPort socket = HostAndPort.fromParts(publicAddress, 22);
+ assertTrue(socketTester.apply(socket), socket.toString());
+ SshClient client = context.utils().injector().getInstance(SshClient.Factory.class)
+ .create(socket, LoginCredentials.builder().user("root").privateKey(key.get("private")).build());
+ try {
+ client.connect();
+ ExecResponse exec = client.exec("echo hello");
+ System.out.println(exec);
+ assertEquals(exec.getOutput().trim(), "hello");
+ } finally {
+ if (client != null)
+ client.disconnect();
+ }
+ }
+
+ @Test(dependsOnMethods = "testSsh")
+ public void testDeleteMachine() {
+ client.delete(machine.getId());
+ }
+
+ @Override
+ @AfterGroups(groups = "live")
+ protected void tearDown() {
+ if (machine != null)
+ client.delete(machine.getId());
+ sdcContext.getApi().getKeyClient().delete(fingerprint);
+ super.tearDown();
+ }
+
+ @Override
+ protected Module getSshModule() {
+ return new SshjSshClientModule();
}
}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/PackageClientExpectTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/PackageClientExpectTest.java
index 9ecc673..86fbbd7 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/PackageClientExpectTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/PackageClientExpectTest.java
@@ -37,29 +37,29 @@
*/
@Test(groups = "unit", testName = "PackageClientExpectTest")
public class PackageClientExpectTest extends BaseSDCClientExpectTest {
- HttpRequest listPackages = HttpRequest
+ HttpRequest list = HttpRequest
.builder()
.method("GET")
- .endpoint(URI.create("https://api.joyentcloud.com/my/packages"))
+ .endpoint(URI.create("https://us-sw-1.api.joyentcloud.com/my/packages"))
.headers(
ImmutableMultimap.<String, String> builder().put("X-Api-Version", "~6.5")
.put("Accept", "application/json").put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==")
.build()).build();
public void testListPackagesWhenResponseIs2xx() {
- HttpResponse listPackagesResponse = HttpResponse.builder().statusCode(200)
+ HttpResponse listResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/package_list.json")).build();
- SDCClient clientWhenPackagesExists = requestSendsResponse(listPackages, listPackagesResponse);
+ SDCClient clientWhenPackagesExists = requestsSendResponses(getDatacenters, getDatacentersResponse, list, listResponse);
- assertEquals(clientWhenPackagesExists.getPackageClient().listPackages(), new ParsePackageListTest().expected());
+ assertEquals(clientWhenPackagesExists.getPackageClientForDatacenter("us-sw-1").list(), new ParsePackageListTest().expected());
}
public void testListPackagesWhenResponseIs404() {
- HttpResponse listPackagesResponse = HttpResponse.builder().statusCode(404).build();
+ HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
- SDCClient listPackagesWhenNone = requestSendsResponse(listPackages, listPackagesResponse);
+ SDCClient listWhenNone = requestsSendResponses(getDatacenters, getDatacentersResponse, list, listResponse);
- assertEquals(listPackagesWhenNone.getPackageClient().listPackages(), ImmutableSet.of());
+ assertEquals(listWhenNone.getPackageClientForDatacenter("us-sw-1").list(), ImmutableSet.of());
}
}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/PackageClientLiveTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/PackageClientLiveTest.java
index 55e1aaa..08fbd84 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/PackageClientLiveTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/PackageClientLiveTest.java
@@ -18,12 +18,11 @@
*/
package org.jclouds.joyent.sdc.v6_5.features;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.Assert.assertEquals;
import java.util.Set;
+import org.jclouds.joyent.sdc.v6_5.domain.Package;
import org.jclouds.joyent.sdc.v6_5.internal.BaseSDCClientLiveTest;
import org.testng.annotations.Test;
@@ -33,16 +32,20 @@
@Test(groups = "live", testName = "PackageClientLiveTest")
public class PackageClientLiveTest extends BaseSDCClientLiveTest {
- public void testListPackages() {
- Set<org.jclouds.joyent.sdc.v6_5.domain.Package> packages = sdcContext.getApi().getPackageClient().listPackages();
- assertNotNull(packages);
- assertTrue(packages.size() > 0);
- }
-
- public void testGetPackage() {
- final String name = "Small 1GB";
- org.jclouds.joyent.sdc.v6_5.domain.Package packageSDC = sdcContext.getApi().getPackageClient().getPackage(name);
- assertNotNull(packageSDC);
- assertEquals(packageSDC.getName(), name);
+ @Test
+ public void testListAndGetPackages() throws Exception {
+ for (String datacenterId : sdcContext.getApi().getConfiguredDatacenters()) {
+ PackageClient client = sdcContext.getApi().getPackageClientForDatacenter(datacenterId);
+ Set<Package> response = client.list();
+ assert null != response;
+ for (Package pkg : response) {
+ Package newDetails = client.get(pkg.getName());
+ assertEquals(newDetails.getName(), pkg.getName());
+ assertEquals(newDetails.getMemorySizeMb(), pkg.getMemorySizeMb());
+ assertEquals(newDetails.getDiskSizeGb(), pkg.getDiskSizeGb());
+ assertEquals(newDetails.getSwapSizeMb(), pkg.getSwapSizeMb());
+ assertEquals(newDetails.isDefault(), pkg.isDefault());
+ }
+ }
}
}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientExpectTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientExpectTest.java
index cd342ce..bc1d4e2 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientExpectTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientExpectTest.java
@@ -18,13 +18,31 @@
*/
package org.jclouds.joyent.sdc.v6_5.internal;
+import java.net.URI;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
import org.jclouds.joyent.sdc.v6_5.SDCClient;
+import com.google.common.collect.ImmutableMultimap;
+
/**
* Base class for writing KeyStone Rest Client Expect tests
*
* @author Adrian Cole
*/
public class BaseSDCClientExpectTest extends BaseSDCExpectTest<SDCClient> {
-
+ protected HttpRequest getDatacenters = HttpRequest
+ .builder()
+ .method("GET")
+ .endpoint(URI.create("https://api.joyentcloud.com/my/datacenters"))
+ .headers(
+ ImmutableMultimap.<String, String> builder()
+ .put("X-Api-Version", "~6.5")
+ .put("Accept", "application/json")
+ .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==")
+ .build()).build();
+
+ protected HttpResponse getDatacentersResponse = HttpResponse.builder().statusCode(200)
+ .payload(payloadFromResource("/datacenters.json")).build();
}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientLiveTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientLiveTest.java
index cbac274..51180b7 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientLiveTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientLiveTest.java
@@ -18,16 +18,16 @@
*/
package org.jclouds.joyent.sdc.v6_5.internal;
-import org.jclouds.apis.BaseContextLiveTest;
-import org.jclouds.joyent.sdc.v6_5.SDCApiMetadata;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.joyent.sdc.v6_5.SDCAsyncClient;
import org.jclouds.joyent.sdc.v6_5.SDCClient;
import org.jclouds.rest.RestContext;
+import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
-import com.google.common.reflect.TypeToken;
+import com.google.inject.Module;
/**
* Tests behavior of {@code SDCClient}
@@ -35,7 +35,7 @@
* @author Adrian Cole
*/
@Test(groups = "live")
-public class BaseSDCClientLiveTest extends BaseContextLiveTest<RestContext<SDCClient, SDCAsyncClient>> {
+public class BaseSDCClientLiveTest extends BaseComputeServiceContextLiveTest {
public BaseSDCClientLiveTest() {
provider = "joyent-sdc";
@@ -47,7 +47,7 @@
@Override
public void setupContext() {
super.setupContext();
- sdcContext = context;
+ sdcContext = view.unwrap();
}
@AfterGroups(groups = "live")
@@ -57,8 +57,7 @@
}
@Override
- protected TypeToken<RestContext<SDCClient, SDCAsyncClient>> contextType() {
- return SDCApiMetadata.CONTEXT_TOKEN;
+ protected Module getSshModule() {
+ return new SshjSshClientModule();
}
-
}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseCreatedMachineTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseCreatedMachineTest.java
index 8920680..10e73ff 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseCreatedMachineTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseCreatedMachineTest.java
@@ -22,6 +22,7 @@
import javax.ws.rs.core.MediaType;
import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.domain.JsonBall;
import org.jclouds.joyent.sdc.v6_5.config.SDCParserModule;
import org.jclouds.joyent.sdc.v6_5.domain.Machine;
import org.jclouds.joyent.sdc.v6_5.domain.Type;
@@ -37,7 +38,7 @@
/**
* @author Gerald Pereira
*/
-@Test(groups = "unit", testName = "ParseServerTest")
+@Test(groups = "unit", testName = "ParseMachineTest")
public class ParseCreatedMachineTest extends BaseItemParserTest<Machine> {
@Override
@@ -51,14 +52,16 @@
return Machine
.builder()
.id("94eba336-ecb7-49f5-8a27-52f5e4dd57a1")
- .name("testJClouds")
+ .name("sample-e92")
.type(Type.VIRTUALMACHINE)
.state(Machine.State.STOPPED)
.dataset("sdc:sdc:centos-5.7:1.2.1")
.ips(ImmutableSet. <String>builder().add("37.153.96.62").add("10.224.0.63").build())
.memorySizeMb(1024)
.diskSizeGb(61440)
- .metadata(ImmutableMap. <String,String>builder().put("root_authorized_keys","ssh-rsa XXXXXX== test@xxxx.ovh.net\n").build())
+ .metadata(
+ ImmutableMap.<String, JsonBall> builder()
+ .put("root_authorized_keys", new JsonBall("ssh-rsa XXXXXX== test@xxxx.ovh.net\n")).build())
.created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-09T13:32:46+00:00"))
.updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-11T08:44:53+00:00"))
.build();
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseKeyListTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseKeyListTest.java
new file mode 100644
index 0000000..edd8d17
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseKeyListTest.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.parse;
+
+import java.util.Set;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.joyent.sdc.v6_5.config.SDCParserModule;
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+import org.jclouds.json.BaseSetParserTest;
+import org.jclouds.json.config.GsonModule;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "ParseKeyListTest")
+public class ParseKeyListTest extends BaseSetParserTest<Key> {
+
+ @Override
+ public String resource() {
+ return "/key_list.json";
+ }
+
+ @Override
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Set<Key> expected() {
+ return ImmutableSet.of(
+ Key.builder()
+ .name("rsa")
+ .key("ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0A5Pf5Cq...")
+ .created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-04-13T22:14:46+00:00"))
+ .build()
+ );
+ }
+
+ protected Injector injector() {
+ return Guice.createInjector(new SDCParserModule(), new GsonModule() {
+
+ @Override
+ protected void configure() {
+ bind(DateAdapter.class).to(Iso8601DateAdapter.class);
+ super.configure();
+ }
+
+ });
+ }
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseKeyTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseKeyTest.java
new file mode 100644
index 0000000..c147693
--- /dev/null
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseKeyTest.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.sdc.v6_5.parse;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.joyent.sdc.v6_5.config.SDCParserModule;
+import org.jclouds.joyent.sdc.v6_5.domain.Key;
+import org.jclouds.json.BaseItemParserTest;
+import org.jclouds.json.config.GsonModule;
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "ParseKeyTest")
+public class ParseKeyTest extends BaseItemParserTest<Key> {
+
+ @Override
+ public String resource() {
+ return "/key.json";
+ }
+
+ @Override
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Key expected() {
+ return Key.builder()
+ .name("rsa")
+ .key("ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0A5Pf5Cq...")
+ .created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-04-13T22:14:46+00:00"))
+ .build();
+ }
+
+ protected Injector injector() {
+ return Guice.createInjector(new SDCParserModule(), new GsonModule() {
+
+ @Override
+ protected void configure() {
+ bind(DateAdapter.class).to(Iso8601DateAdapter.class);
+ super.configure();
+ }
+
+ });
+ }
+}
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseMachineListTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseMachineListTest.java
index 60d70bf..51979c7 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseMachineListTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseMachineListTest.java
@@ -24,6 +24,7 @@
import javax.ws.rs.core.MediaType;
import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.domain.JsonBall;
import org.jclouds.joyent.sdc.v6_5.config.SDCParserModule;
import org.jclouds.joyent.sdc.v6_5.domain.Machine;
import org.jclouds.joyent.sdc.v6_5.domain.Type;
@@ -54,7 +55,7 @@
Machine
.builder()
.id("94eba336-ecb7-49f5-8a27-52f5e4dd57a1")
- .name("testJClouds")
+ .name("sample-e92")
.type(Type.VIRTUALMACHINE)
.state(Machine.State.RUNNING)
.dataset("sdc:sdc:centos-5.7:1.2.1")
@@ -62,16 +63,16 @@
.memorySizeMb(1024)
.diskSizeGb(61440)
.metadata(
- ImmutableMap.<String, String> builder()
- .put("root_authorized_keys", "ssh-rsa XXXXXX== test@xxxx.ovh.net\n").build())
+ ImmutableMap.<String, JsonBall> builder()
+ .put("root_authorized_keys", new JsonBall("ssh-rsa XXXXXX== test@xxxx.ovh.net\n")).build())
.created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-09T13:32:46+00:00"))
.updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-11T09:00:33+00:00"))
.build(),
- Machine.builder().id("d73cb0b0-7d1f-44ef-8c40-e040eef0f726").name("testJClouds2").type(Type.SMARTMACHINE)
+ Machine.builder().id("d73cb0b0-7d1f-44ef-8c40-e040eef0f726").name("sample-e922").type(Type.SMARTMACHINE)
.state(Machine.State.RUNNING).dataset("sdc:sdc:smartosplus:3.1.0")
.ips(ImmutableSet.<String> builder().add("37.153.96.56").add("10.224.0.57").build())
- .memorySizeMb(1024).diskSizeGb(61440).metadata(ImmutableMap.<String, String> of())
+ .memorySizeMb(1024).diskSizeGb(61440).metadata(ImmutableMap.<String, JsonBall> of())
.created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-09T13:39:43+00:00"))
.updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-09T13:43:45+00:00"))
.build()
diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseMachineTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseMachineTest.java
index 02829a4..912d31f 100644
--- a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseMachineTest.java
+++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/parse/ParseMachineTest.java
@@ -22,6 +22,7 @@
import javax.ws.rs.core.MediaType;
import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.domain.JsonBall;
import org.jclouds.joyent.sdc.v6_5.config.SDCParserModule;
import org.jclouds.joyent.sdc.v6_5.domain.Machine;
import org.jclouds.joyent.sdc.v6_5.domain.Type;
@@ -51,7 +52,7 @@
return Machine
.builder()
.id("94eba336-ecb7-49f5-8a27-52f5e4dd57a1")
- .name("testJClouds")
+ .name("sample-e92")
.type(Type.VIRTUALMACHINE)
.state(Machine.State.STOPPED)
.dataset("sdc:sdc:centos-5.7:1.2.1")
@@ -59,8 +60,8 @@
.memorySizeMb(1024)
.diskSizeGb(61440)
.metadata(
- ImmutableMap.<String, String> builder()
- .put("root_authorized_keys", "ssh-rsa XXXXXX== test@xxxx.ovh.net\n").build())
+ ImmutableMap.<String, JsonBall> builder()
+ .put("root_authorized_keys", new JsonBall("ssh-rsa XXXXXX== test@xxxx.ovh.net\n")).build())
.created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-09T13:32:46+00:00"))
.updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-11T08:44:53+00:00")).build();
}
diff --git a/labs/joyent-sdc/src/test/resources/key.json b/labs/joyent-sdc/src/test/resources/key.json
new file mode 100644
index 0000000..5957f79
--- /dev/null
+++ b/labs/joyent-sdc/src/test/resources/key.json
@@ -0,0 +1,5 @@
+{
+ "name": "rsa",
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0A5Pf5Cq...",
+ "created": "2011-04-13T22:14:46+00:00"
+}
\ No newline at end of file
diff --git a/labs/joyent-sdc/src/test/resources/key_list.json b/labs/joyent-sdc/src/test/resources/key_list.json
new file mode 100644
index 0000000..503dd9c
--- /dev/null
+++ b/labs/joyent-sdc/src/test/resources/key_list.json
@@ -0,0 +1,7 @@
+[
+ {
+ "name": "rsa",
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0A5Pf5Cq...",
+ "created": "2011-04-13T22:14:46+00:00"
+ }
+]
\ No newline at end of file
diff --git a/labs/joyent-sdc/src/test/resources/logback.xml b/labs/joyent-sdc/src/test/resources/logback.xml
deleted file mode 100644
index b77c1b0..0000000
--- a/labs/joyent-sdc/src/test/resources/logback.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0"?>
-<configuration scan="false">
- <appender name="FILE" class="ch.qos.logback.core.FileAppender">
- <file>target/test-data/jclouds.log</file>
-
- <encoder>
- <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
- </encoder>
- </appender>
-
- <appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
- <file>target/test-data/jclouds-wire.log</file>
-
- <encoder>
- <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
- </encoder>
- </appender>
-
- <appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
- <file>target/test-data/jclouds-compute.log</file>
-
- <encoder>
- <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
- </encoder>
- </appender>
-
- <root>
- <level value="warn" />
- </root>
-
- <logger name="org.jclouds">
- <level value="DEBUG" />
- <appender-ref ref="FILE" />
- </logger>
-
- <logger name="jclouds.wire">
- <level value="DEBUG" />
- <appender-ref ref="WIREFILE" />
- </logger>
-
- <logger name="jclouds.headers">
- <level value="DEBUG" />
- <appender-ref ref="WIREFILE" />
- </logger>
-
- <logger name="jclouds.compute">
- <level value="DEBUG" />
- <appender-ref ref="COMPUTEFILE" />
- </logger>
-
-</configuration>
diff --git a/labs/joyent-sdc/src/test/resources/machine.json b/labs/joyent-sdc/src/test/resources/machine.json
index fd56f2f..4815124 100644
--- a/labs/joyent-sdc/src/test/resources/machine.json
+++ b/labs/joyent-sdc/src/test/resources/machine.json
@@ -1 +1 @@
-{"id":"94eba336-ecb7-49f5-8a27-52f5e4dd57a1","name":"testJClouds","type":"virtualmachine","state":"stopped","dataset":"sdc:sdc:centos-5.7:1.2.1","ips":["37.153.96.62","10.224.0.63"],"memory":1024,"disk":61440,"metadata":{"root_authorized_keys":"ssh-rsa XXXXXX== test@xxxx.ovh.net"},"created":"2012-05-09T13:32:46+00:00","updated":"2012-05-11T08:44:53+00:00"}
+{"id":"94eba336-ecb7-49f5-8a27-52f5e4dd57a1","name":"sample-e92","type":"virtualmachine","state":"stopped","dataset":"sdc:sdc:centos-5.7:1.2.1","ips":["37.153.96.62","10.224.0.63"],"memory":1024,"disk":61440,"metadata":{"root_authorized_keys":"ssh-rsa XXXXXX== test@xxxx.ovh.net"},"created":"2012-05-09T13:32:46+00:00","updated":"2012-05-11T08:44:53+00:00"}
diff --git a/labs/joyent-sdc/src/test/resources/machine_list.json b/labs/joyent-sdc/src/test/resources/machine_list.json
index 29ca4ca..51b82b7 100644
--- a/labs/joyent-sdc/src/test/resources/machine_list.json
+++ b/labs/joyent-sdc/src/test/resources/machine_list.json
@@ -1 +1 @@
-[{"id":"d73cb0b0-7d1f-44ef-8c40-e040eef0f726","name":"testJClouds2","type":"smartmachine","state":"running","dataset":"sdc:sdc:smartosplus:3.1.0","ips":["37.153.96.56","10.224.0.57"],"memory":1024,"disk":61440,"metadata":{},"created":"2012-05-09T13:39:43+00:00","updated":"2012-05-09T13:43:45+00:00"},{"id":"94eba336-ecb7-49f5-8a27-52f5e4dd57a1","name":"testJClouds","type":"virtualmachine","state":"running","dataset":"sdc:sdc:centos-5.7:1.2.1","ips":["37.153.96.62","10.224.0.63"],"memory":1024,"disk":61440,"metadata":{"root_authorized_keys":"ssh-rsa XXXXXX== test@xxxx.ovh.net\n"},"created":"2012-05-09T13:32:46+00:00","updated":"2012-05-11T09:00:33+00:00"}]
\ No newline at end of file
+[{"id":"d73cb0b0-7d1f-44ef-8c40-e040eef0f726","name":"sample-e922","type":"smartmachine","state":"running","dataset":"sdc:sdc:smartosplus:3.1.0","ips":["37.153.96.56","10.224.0.57"],"memory":1024,"disk":61440,"metadata":{},"created":"2012-05-09T13:39:43+00:00","updated":"2012-05-09T13:43:45+00:00"},{"id":"94eba336-ecb7-49f5-8a27-52f5e4dd57a1","name":"sample-e92","type":"virtualmachine","state":"running","dataset":"sdc:sdc:centos-5.7:1.2.1","ips":["37.153.96.62","10.224.0.63"],"memory":1024,"disk":61440,"metadata":{"root_authorized_keys":"ssh-rsa XXXXXX== test@xxxx.ovh.net\n"},"created":"2012-05-09T13:32:46+00:00","updated":"2012-05-11T09:00:33+00:00"}]
\ No newline at end of file
diff --git a/labs/joyent-sdc/src/test/resources/new_machine.json b/labs/joyent-sdc/src/test/resources/new_machine.json
index fd56f2f..4815124 100644
--- a/labs/joyent-sdc/src/test/resources/new_machine.json
+++ b/labs/joyent-sdc/src/test/resources/new_machine.json
@@ -1 +1 @@
-{"id":"94eba336-ecb7-49f5-8a27-52f5e4dd57a1","name":"testJClouds","type":"virtualmachine","state":"stopped","dataset":"sdc:sdc:centos-5.7:1.2.1","ips":["37.153.96.62","10.224.0.63"],"memory":1024,"disk":61440,"metadata":{"root_authorized_keys":"ssh-rsa XXXXXX== test@xxxx.ovh.net"},"created":"2012-05-09T13:32:46+00:00","updated":"2012-05-11T08:44:53+00:00"}
+{"id":"94eba336-ecb7-49f5-8a27-52f5e4dd57a1","name":"sample-e92","type":"virtualmachine","state":"stopped","dataset":"sdc:sdc:centos-5.7:1.2.1","ips":["37.153.96.62","10.224.0.63"],"memory":1024,"disk":61440,"metadata":{"root_authorized_keys":"ssh-rsa XXXXXX== test@xxxx.ovh.net"},"created":"2012-05-09T13:32:46+00:00","updated":"2012-05-11T08:44:53+00:00"}
diff --git a/labs/joyentcloud/pom.xml b/labs/joyentcloud/pom.xml
new file mode 100644
index 0000000..a0bdbab
--- /dev/null
+++ b/labs/joyentcloud/pom.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to jclouds, Inc. (jclouds) under one or more
+ contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. jclouds 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-project</artifactId>
+ <version>1.5.0-SNAPSHOT</version>
+ <relativePath>../../project/pom.xml</relativePath>
+ </parent>
+ <groupId>org.jclouds.labs</groupId>
+ <artifactId>joyentcloud</artifactId>
+ <name>jcloud joyentcloud api</name>
+ <description>jclouds components to access the Joyent Cloud</description>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <test.joyentcloud.endpoint>https://api.joyentcloud.com</test.joyentcloud.endpoint>
+ <test.joyentcloud.api-version>~6.5</test.joyentcloud.api-version>
+ <test.joyentcloud.build-version></test.joyentcloud.build-version>
+ <test.joyentcloud.identity>FIXME_IDENTITY</test.joyentcloud.identity>
+ <test.joyentcloud.credential>FIXME_CREDENTIALS</test.joyentcloud.credential>
+ <jclouds.osgi.export>org.jclouds.joyent.joyentcloud*;version="${project.version}"</jclouds.osgi.export>
+ <jclouds.osgi.import>
+ org.jclouds.rest.internal;version="${project.version}",
+ org.jclouds*;version="${project.version}",
+ *
+ </jclouds.osgi.import>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jclouds.labs</groupId>
+ <artifactId>joyent-sdc</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.labs</groupId>
+ <artifactId>joyent-sdc</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-compute</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.driver</groupId>
+ <artifactId>jclouds-slf4j</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.driver</groupId>
+ <artifactId>jclouds-sshj</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.0.0</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>live</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>integration</id>
+ <phase>integration-test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <systemPropertyVariables>
+ <test.joyentcloud.endpoint>${test.joyentcloud.endpoint}</test.joyentcloud.endpoint>
+ <test.joyentcloud.api-version>${test.joyentcloud.api-version}</test.joyentcloud.api-version>
+ <test.joyentcloud.build-version>${test.joyentcloud.build-version}</test.joyentcloud.build-version>
+ <test.joyentcloud.identity>${test.joyentcloud.identity}</test.joyentcloud.identity>
+ <test.joyentcloud.credential>${test.joyentcloud.credential}</test.joyentcloud.credential>
+ </systemPropertyVariables>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/labs/joyentcloud/src/main/java/org/jclouds/joyent/joyentcloud/JoyentCloudProviderMetadata.java b/labs/joyentcloud/src/main/java/org/jclouds/joyent/joyentcloud/JoyentCloudProviderMetadata.java
new file mode 100644
index 0000000..9b278a7
--- /dev/null
+++ b/labs/joyentcloud/src/main/java/org/jclouds/joyent/joyentcloud/JoyentCloudProviderMetadata.java
@@ -0,0 +1,93 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.joyentcloud;
+
+import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_ZONE;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_ZONES;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.joyent.sdc.v6_5.SDCApiMetadata;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadata;
+
+/**
+ * Implementation of {@link org.jclouds.types.ProviderMetadata} for SDC.
+ * @author Adrian Cole
+ */
+public class JoyentCloudProviderMetadata extends BaseProviderMetadata {
+
+ /** The serialVersionUID */
+ private static final long serialVersionUID = 2196535609684739834L;
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return builder().fromProviderMetadata(this);
+ }
+
+ public JoyentCloudProviderMetadata() {
+ super(builder());
+ }
+
+ public JoyentCloudProviderMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = new Properties();
+ properties.setProperty(PROPERTY_ZONES, "us-east-1,us-west-1,us-sw-1,eu-ams-1");
+ properties.setProperty(PROPERTY_ZONE + ".us-east-1." + ISO3166_CODES, "US-VA");
+ properties.setProperty(PROPERTY_ZONE + ".us-west-1." + ISO3166_CODES, "US-CA");
+ properties.setProperty(PROPERTY_ZONE + ".us-sw-1." + ISO3166_CODES, "US-NV");
+ properties.setProperty(PROPERTY_ZONE + ".eu-ams-1." + ISO3166_CODES, "NL-NH");
+ return properties;
+ }
+
+ public static class Builder extends BaseProviderMetadata.Builder {
+
+ protected Builder() {
+ id("joyentcloud")
+ .name("JoyentCloud")
+ .apiMetadata(new SDCApiMetadata())
+ .homepage(URI.create("http://www.joyent.com/products/smartdatacenter/"))
+ .console(URI.create("https://my.joyentcloud.com/login"))
+ .iso3166Codes("US-VA", "US-CA", "US-NV", "NL-NH")
+ .endpoint("https://api.joyentcloud.com")
+ .defaultProperties(JoyentCloudProviderMetadata.defaultProperties());
+ }
+
+ @Override
+ public JoyentCloudProviderMetadata build() {
+ return new JoyentCloudProviderMetadata(this);
+ }
+
+ @Override
+ public Builder fromProviderMetadata(ProviderMetadata in) {
+ super.fromProviderMetadata(in);
+ return this;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/labs/joyentcloud/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/labs/joyentcloud/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
new file mode 100644
index 0000000..73d417c
--- /dev/null
+++ b/labs/joyentcloud/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
@@ -0,0 +1 @@
+org.jclouds.joyent.joyentcloud.JoyentCloudProviderMetadata
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudComputeServiceLiveTest.java
similarity index 63%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudComputeServiceLiveTest.java
index 771a1be..9522c5d 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudComputeServiceLiveTest.java
@@ -16,13 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.joyent.joyentcloud;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.joyent.sdc.v6_5.compute.SDCComputeServiceLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
+/**
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "JoyentCloudComputeServiceLiveTest")
+public class JoyentCloudComputeServiceLiveTest extends SDCComputeServiceLiveTest {
- void startPool() throws RunNodesException;
-
+ public JoyentCloudComputeServiceLiveTest() {
+ provider = "joyentcloud";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudLiveTest.java
similarity index 68%
rename from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
rename to labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudLiveTest.java
index 771a1be..bc282ed 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudLiveTest.java
@@ -16,13 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.joyent.joyentcloud;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.joyent.sdc.v6_5.SDCClientLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
-
- void startPool() throws RunNodesException;
-
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "JoyentCloudLiveTest")
+public class JoyentCloudLiveTest extends SDCClientLiveTest {
+ public JoyentCloudLiveTest() {
+ provider = "joyentcloud";
+ }
}
diff --git a/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudProviderMetadataTest.java b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudProviderMetadataTest.java
new file mode 100644
index 0000000..9d99158
--- /dev/null
+++ b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudProviderMetadataTest.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not computee 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.joyent.joyentcloud;
+
+import org.jclouds.joyent.sdc.v6_5.SDCApiMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadataTest;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "JoyentCloudProviderMetadataTest")
+public class JoyentCloudProviderMetadataTest extends BaseProviderMetadataTest {
+
+ public JoyentCloudProviderMetadataTest() {
+ super(new JoyentCloudProviderMetadata(), new SDCApiMetadata());
+ }
+}
diff --git a/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudTemplateBuilderLiveTest.java b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudTemplateBuilderLiveTest.java
new file mode 100644
index 0000000..69ddb03
--- /dev/null
+++ b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/JoyentCloudTemplateBuilderLiveTest.java
@@ -0,0 +1,85 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.joyent.joyentcloud;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Set;
+
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.OsFamilyVersion64Bit;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "JoyentCloudTemplateBuilderLiveTest")
+public class JoyentCloudTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
+
+ public JoyentCloudTemplateBuilderLiveTest() {
+ provider = "joyentcloud";
+ }
+
+ @Override
+ protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
+ return Predicates.not(new Predicate<OsFamilyVersion64Bit>() {
+
+ @Override
+ public boolean apply(OsFamilyVersion64Bit input) {
+ switch (input.family) {
+ case UBUNTU:
+ return (input.version.equals("") || input.version.equals("10.04")) && input.is64Bit;
+ case DEBIAN:
+ return input.is64Bit && !input.version.equals("5.0");
+ case CENTOS:
+ return (input.version.equals("") || input.version.equals("5.7") || input.version.equals("6.0"))
+ && input.is64Bit;
+ default:
+ return false;
+ }
+ }
+
+ });
+ }
+
+ @Test
+ public void testTemplateBuilder() {
+ Template defaultTemplate = this.view.getComputeService().templateBuilder().build();
+ assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
+ assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04");
+ assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
+ assertEquals(defaultTemplate.getImage().getName(), "ubuntu-10.04");
+ assertEquals(defaultTemplate.getImage().getDefaultCredentials().getUser(), "root");
+ assertEquals(defaultTemplate.getLocation().getId(), "us-east-1");
+ assertEquals(defaultTemplate.getImage().getLocation().getId(), "us-east-1");
+ assertEquals(defaultTemplate.getHardware().getLocation().getId(), "us-east-1");
+ }
+
+ @Override
+ protected Set<String> getIso3166Codes() {
+ return ImmutableSet.<String> of("US-VA", "US-CA", "US-NV", "NL-NH");
+ }
+}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudDatacenterClientLiveTest.java
similarity index 64%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudDatacenterClientLiveTest.java
index 771a1be..c35790c 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudDatacenterClientLiveTest.java
@@ -16,13 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.joyent.joyentcloud.features;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.joyent.sdc.v6_5.features.DatacenterClientLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
-
- void startPool() throws RunNodesException;
-
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "JoyentCloudDatacenterClientLiveTest")
+public class JoyentCloudDatacenterClientLiveTest extends DatacenterClientLiveTest {
+ public JoyentCloudDatacenterClientLiveTest() {
+ provider = "joyentcloud";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudDatasetClientLiveTest.java
similarity index 65%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudDatasetClientLiveTest.java
index 771a1be..412ec8c 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudDatasetClientLiveTest.java
@@ -16,13 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.joyent.joyentcloud.features;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.joyent.sdc.v6_5.features.DatasetClientLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
-
- void startPool() throws RunNodesException;
-
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "JoyentCloudDatasetClientLiveTest")
+public class JoyentCloudDatasetClientLiveTest extends DatasetClientLiveTest {
+ public JoyentCloudDatasetClientLiveTest() {
+ provider = "joyentcloud";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudKeyClientLiveTest.java
similarity index 66%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudKeyClientLiveTest.java
index 771a1be..5db0864 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudKeyClientLiveTest.java
@@ -16,13 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.joyent.joyentcloud.features;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.joyent.sdc.v6_5.features.KeyClientLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
-
- void startPool() throws RunNodesException;
-
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "JoyentCloudKeyClientLiveTest")
+public class JoyentCloudKeyClientLiveTest extends KeyClientLiveTest {
+ public JoyentCloudKeyClientLiveTest() {
+ provider = "joyentcloud";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudMachineClientLiveTest.java
similarity index 65%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudMachineClientLiveTest.java
index 771a1be..6307226 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudMachineClientLiveTest.java
@@ -16,13 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.joyent.joyentcloud.features;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.joyent.sdc.v6_5.features.MachineClientLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
-
- void startPool() throws RunNodesException;
-
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "JoyentCloudMachineClientLiveTest")
+public class JoyentCloudMachineClientLiveTest extends MachineClientLiveTest {
+ public JoyentCloudMachineClientLiveTest() {
+ provider = "joyentcloud";
+ }
}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudPackageClientLiveTest.java
similarity index 65%
copy from labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
copy to labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudPackageClientLiveTest.java
index 771a1be..0e2f42c 100644
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/PooledComputeService.java
+++ b/labs/joyentcloud/src/test/java/org/jclouds/joyent/joyentcloud/features/JoyentCloudPackageClientLiveTest.java
@@ -16,13 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jclouds.nodepool;
+package org.jclouds.joyent.joyentcloud.features;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
+import org.jclouds.joyent.sdc.v6_5.features.PackageClientLiveTest;
+import org.testng.annotations.Test;
-public interface PooledComputeService extends ComputeService {
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "JoyentCloudPackageClientLiveTest")
+public class JoyentCloudPackageClientLiveTest extends PackageClientLiveTest {
- void startPool() throws RunNodesException;
-
+ public JoyentCloudPackageClientLiveTest(){
+ provider = "joyentcloud";
+ }
}
diff --git a/labs/nodepool/pom.xml b/labs/nodepool/pom.xml
index 1cccd6e..a60c8c7 100644
--- a/labs/nodepool/pom.xml
+++ b/labs/nodepool/pom.xml
@@ -1,12 +1,13 @@
<?xml version="1.0"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>jclouds-project</artifactId>
<groupId>org.jclouds</groupId>
<version>1.5.0-SNAPSHOT</version>
- <relativePath>../../project/pom.xml</relativePath>
+ <relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.labs</groupId>
<artifactId>nodepool</artifactId>
@@ -17,23 +18,22 @@
<jsch.version>0.1.46</jsch.version>
<test.aws-ec2.identity>${test.aws.identity}</test.aws-ec2.identity>
<test.aws-ec2.credential>${test.aws.credential}</test.aws-ec2.credential>
-
<jclouds.osgi.export>org.jclouds.nodepool*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
</properties>
<dependencies>
- <dependency>
- <groupId>org.jclouds</groupId>
- <artifactId>jclouds-compute</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-compute</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
- </dependency>
+ </dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
@@ -41,41 +41,46 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.jclouds.provider</groupId>
- <artifactId>aws-ec2</artifactId>
- <version>${project.version}</version>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.0.0</version>
<scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.jclouds.driver</groupId>
- <artifactId>jclouds-enterprise</artifactId>
- <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.provider</groupId>
+ <artifactId>aws-ec2</artifactId>
+ <version>${project.version}</version>
<scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.jclouds.driver</groupId>
- <artifactId>jclouds-sshj</artifactId>
- <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.driver</groupId>
+ <artifactId>jclouds-enterprise</artifactId>
+ <version>${project.version}</version>
<scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.jclouds</groupId>
- <artifactId>jclouds-scriptbuilder</artifactId>
- <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.driver</groupId>
+ <artifactId>jclouds-sshj</artifactId>
+ <version>${project.version}</version>
<scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.jclouds.driver</groupId>
- <artifactId>jclouds-jsch</artifactId>
- <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-scriptbuilder</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.driver</groupId>
+ <artifactId>jclouds-jsch</artifactId>
+ <version>${project.version}</version>
<scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.jcraft</groupId>
- <artifactId>jsch</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.jcraft</groupId>
+ <artifactId>jsch</artifactId>
<scope>test</scope>
- </dependency>
-</dependencies>
-
+ </dependency>
+ </dependencies>
+
</project>
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/NodePoolApiMetadata.java b/labs/nodepool/src/main/java/org/jclouds/nodepool/NodePoolApiMetadata.java
new file mode 100644
index 0000000..849349d
--- /dev/null
+++ b/labs/nodepool/src/main/java/org/jclouds/nodepool/NodePoolApiMetadata.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.nodepool;
+
+import static org.jclouds.nodepool.config.NodePoolComputeServiceProperties.BACKING_GROUP_PROPERTY;
+import static org.jclouds.nodepool.config.NodePoolComputeServiceProperties.MAX_SIZE_PROPERTY;
+import static org.jclouds.nodepool.config.NodePoolComputeServiceProperties.MIN_SIZE_PROPERTY;
+import static org.jclouds.nodepool.config.NodePoolComputeServiceProperties.REMOVE_DESTROYED_PROPERTY;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.apis.internal.BaseApiMetadata;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.rest.internal.BaseRestApiMetadata;
+
+public class NodePoolApiMetadata extends BaseApiMetadata {
+
+ /** The serialVersionUID */
+ private static final long serialVersionUID = -2778027403592717115L;
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return Builder.class.cast(builder().fromApiMetadata(this));
+ }
+
+ public NodePoolApiMetadata() {
+ super(builder());
+ }
+
+ protected NodePoolApiMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = BaseRestApiMetadata.defaultProperties();
+ properties.setProperty(BACKING_GROUP_PROPERTY, "nodepool");
+ properties.setProperty(MAX_SIZE_PROPERTY, 10 + "");
+ properties.setProperty(MIN_SIZE_PROPERTY, 5 + "");
+ properties.setProperty(REMOVE_DESTROYED_PROPERTY, "false");
+ return properties;
+ }
+
+ public static class Builder extends BaseApiMetadata.Builder {
+ protected Builder() {
+ id("nodepool").name("node pool provider wrapper").identityName("Unused").defaultIdentity("nodepool")
+ .defaultEndpoint("nodepool").documentation(
+ URI.create("http://www.jclouds.org/documentation/userguide/compute")).view(
+ ComputeServiceContext.class).defaultProperties(NodePoolApiMetadata.defaultProperties());
+ }
+
+ @Override
+ public NodePoolApiMetadata build() {
+ return new NodePoolApiMetadata(this);
+ }
+
+ }
+
+}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/NodePoolComputeService.java b/labs/nodepool/src/main/java/org/jclouds/nodepool/NodePoolComputeService.java
new file mode 100644
index 0000000..c656809
--- /dev/null
+++ b/labs/nodepool/src/main/java/org/jclouds/nodepool/NodePoolComputeService.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.nodepool;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.jclouds.compute.ComputeService;
+import org.jclouds.nodepool.config.NodePoolComputeServiceProperties;
+import org.jclouds.nodepool.internal.EagerNodePoolComputeService;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.inject.ImplementedBy;
+
+/**
+ * A {@link ComputeService} wrapper that uses a pool of pre-loaded nodes to speed up creation times.
+ *
+ * This interface extends the ComputeService with a backing pool of nodes, configured during
+ * construction. The {@link #startPool()} and {@link #close()} methods are used to create and
+ * destroy the pool and its associated nodes.
+ *
+ * @author Andrew Kennedy
+ * @author Gustavo Morozowski
+ * @author David Alves
+ *
+ * @see <a href="https://github.com/jclouds/jclouds/wiki/NodePool-Notes">NodePool Notes</a>
+ * @see NodePoolComputeServiceProperties
+ * @since 1.5.0
+ */
+@ImplementedBy(EagerNodePoolComputeService.class)
+public interface NodePoolComputeService extends ComputeService, Closeable {
+
+ /**
+ * Starts the pool, may or may not start the actual nodes, depending on the implementation, i.e.
+ * the returned Set may be empty.
+ */
+ ListenableFuture<Void> startPool();
+
+ /**
+ * Returns true of the pool has been started by calling the {@link #startPool()} method.
+ */
+ boolean isStarted();
+
+ /**
+ * Returns the number of ready (pre-allocated) nodes in the pool.
+ */
+ int ready();
+
+ /**
+ * Returns the current size of the pool (nodes allocated on the backing compute service)
+ */
+ int size();
+
+ /**
+ * Returns the maximum amout of node the pool will allocate in the backing compute service.
+ */
+ int maxSize();
+
+ /**
+ * Close the pool and destroy all associated nodes.
+ */
+ void close() throws IOException;
+
+}
\ No newline at end of file
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/config/NodePoolComputeServiceProperties.java b/labs/nodepool/src/main/java/org/jclouds/nodepool/config/NodePoolComputeServiceProperties.java
new file mode 100644
index 0000000..96fae93
--- /dev/null
+++ b/labs/nodepool/src/main/java/org/jclouds/nodepool/config/NodePoolComputeServiceProperties.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds 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.nodepool.config;
+
+/**
+ * Constants for the {@link org.jclouds.nodepool.NodePoolComputeService}.
+ */
+public interface NodePoolComputeServiceProperties {
+
+ /**
+ * Property to set the name of the backing group used for pooled nodes.
+ */
+ public static final String BACKING_GROUP_PROPERTY = "jclouds.nodepool.backing-group";
+
+ /**
+ * Property to set the template that will be used to create the nodes in the pool.
+ */
+ public static final String BACKING_TEMPLATE_PROPERTY = "jclouds.nodepool.backing-template";
+
+ /**
+ * Property to set the maximum size of the pool. Set this to {@literal -1} to have an unlimited
+ * pool size.
+ */
+ public static final String MAX_SIZE_PROPERTY = "jclouds.nodepool.max-size";
+
+ /**
+ * Property to set the minimum (initial) size of the pool.
+ */
+ public static final String MIN_SIZE_PROPERTY = "jclouds.nodepool.min-size";
+
+ /**
+ * Property to set the pool behaviour to remove destroyed nodes rather than returning them to the
+ * pool for re-use.
+ */
+ public static final String REMOVE_DESTROYED_PROPERTY = "jclouds.nodepool.remove-destroyed";
+
+}
\ No newline at end of file
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/internal/BaseNodePoolComputeService.java b/labs/nodepool/src/main/java/org/jclouds/nodepool/internal/BaseNodePoolComputeService.java
new file mode 100644
index 0000000..554cd46
--- /dev/null
+++ b/labs/nodepool/src/main/java/org/jclouds/nodepool/internal/BaseNodePoolComputeService.java
@@ -0,0 +1,335 @@
+package org.jclouds.nodepool.internal;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.find;
+
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.RunScriptOnNodesException;
+import org.jclouds.compute.domain.ComputeMetadata;
+import org.jclouds.compute.domain.ExecResponse;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.extensions.ImageExtension;
+import org.jclouds.compute.options.RunScriptOptions;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.Location;
+import org.jclouds.nodepool.NodePoolComputeService;
+import org.jclouds.scriptbuilder.domain.Statement;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * A base class for {@link NodePoolComputeService}, takes care of keeping (not changing assignments)
+ * and of everything that does not change the pool.
+ *
+ * @author David Alves
+ *
+ */
+public abstract class BaseNodePoolComputeService implements NodePoolComputeService {
+
+ protected final ComputeService backingComputeService;
+ protected final String poolGroupName;
+ protected final Template template;
+ protected final Image image;
+ protected final Hardware hardware;
+ protected final Location location;
+
+ // assignments of nodes to group names
+ protected final Multimap<String, NodeMetadata> assignments = HashMultimap.create();
+
+ protected final AtomicBoolean started = new AtomicBoolean(false);
+
+ public BaseNodePoolComputeService(ComputeServiceContext backingComputeServiceContext, String poolGroupNamePrefix,
+ Template backingTemplate) {
+ this.backingComputeService = backingComputeServiceContext.getComputeService();
+ this.poolGroupName = poolGroupNamePrefix;
+ this.template = backingTemplate == null ? this.backingComputeService.templateBuilder().build() : backingTemplate;
+ this.image = this.template.getImage();
+ this.hardware = this.template.getHardware();
+ this.location = this.template.getLocation();
+ }
+
+ /**
+ * Checks which nodes match the users predicate and builds a predicate that returns true to their
+ * specific ids.
+ *
+ * @param filter
+ * @return
+ */
+ private Predicate<NodeMetadata> transformUserPredicateSpecificIdPredicate(Predicate<NodeMetadata> filter) {
+ Iterable<Map.Entry<String, NodeMetadata>> relevantAssginemnts = filterAssignmentsBasedOnUserPredicate(filter);
+ final Set<String> ids = Sets.newHashSet();
+ for (Map.Entry<String, NodeMetadata> assignment : relevantAssginemnts) {
+ ids.add(assignment.getValue().getId());
+ }
+ return new Predicate<NodeMetadata>() {
+ @Override
+ public boolean apply(NodeMetadata input) {
+ return ids.contains(input.getId());
+ }
+ };
+
+ }
+
+ @Override
+ public boolean isStarted() {
+ return started.get();
+ }
+
+ // TODO this is n^2 expensive. s
+ private Map<? extends NodeMetadata, ExecResponse> transformBackendExecutionMapIntoFrontend(
+ Map<? extends NodeMetadata, ExecResponse> backendMap) {
+ Map<NodeMetadata, ExecResponse> frontendMap = Maps.newHashMapWithExpectedSize(backendMap.size());
+ for (Map.Entry<? extends NodeMetadata, ExecResponse> entry : backendMap.entrySet()) {
+ Map.Entry<String, NodeMetadata> assignmentEntry = findAssigmentEntry(entry.getKey().getId());
+ frontendMap
+ .put(toFrontendNodemetadata(assignmentEntry.getValue(), assignmentEntry.getKey()), entry.getValue());
+ }
+ return frontendMap;
+ }
+
+ protected Map.Entry<String, NodeMetadata> findAssigmentEntry(final String id) {
+ // TODO reverse lookup data structure would be faster but will pools be that big ?
+ return find(assignments.entries(), new Predicate<Map.Entry<String, NodeMetadata>>() {
+ @Override
+ public boolean apply(Entry<String, NodeMetadata> entry) {
+ return entry.getValue().getId().equals(id);
+ }
+ });
+ }
+
+ protected NodeMetadata toFrontendNodemetadata(NodeMetadata backendNodeMetadata, String group) {
+ return NodeMetadataBuilder.fromNodeMetadata(backendNodeMetadata).group(group).build();
+ }
+
+ /**
+ * Because a lot of predicates are based on group info we need that to check wether the predicate
+ * matches.
+ */
+ protected Iterable<Map.Entry<String, NodeMetadata>> filterAssignmentsBasedOnUserPredicate(
+ final Predicate<NodeMetadata> userFilter) {
+ return filter(assignments.entries(), new Predicate<Map.Entry<String, NodeMetadata>>() {
+ @Override
+ public boolean apply(Entry<String, NodeMetadata> input) {
+ return userFilter.apply(toFrontendNodemetadata(input.getValue(), input.getKey()));
+ }
+ });
+ }
+
+ @Override
+ public NodeMetadata getNodeMetadata(String id) {
+ checkState(started.get(), "pool is not started");
+ Map.Entry<String, NodeMetadata> assigmentEntry = findAssigmentEntry(id);
+ return toFrontendNodemetadata(assigmentEntry.getValue(), assigmentEntry.getKey());
+ }
+
+ @Override
+ public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
+ String runScript) throws RunScriptOnNodesException {
+ return runScriptOnNodesMatching(filter, runScript, new RunScriptOptions());
+ }
+
+ @Override
+ public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
+ Statement runScript) throws RunScriptOnNodesException {
+ return runScriptOnNodesMatching(filter, runScript, new RunScriptOptions());
+ }
+
+ @Override
+ public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
+ String runScript, RunScriptOptions options) throws RunScriptOnNodesException {
+ checkState(started.get(), "pool is not started");
+ return transformBackendExecutionMapIntoFrontend(backingComputeService.runScriptOnNodesMatching(
+ transformUserPredicateSpecificIdPredicate(filter), runScript, options));
+ }
+
+ @Override
+ public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
+ Statement runScript, RunScriptOptions options) throws RunScriptOnNodesException {
+ checkState(started.get(), "pool is not started");
+ return transformBackendExecutionMapIntoFrontend(backingComputeService.runScriptOnNodesMatching(
+ transformUserPredicateSpecificIdPredicate(filter), runScript, options));
+ }
+
+ @Override
+ public Set<? extends ComputeMetadata> listNodes() {
+ checkState(started.get(), "pool is not started");
+ return listNodesDetailsMatching(Predicates.alwaysTrue());
+ }
+
+ @SuppressWarnings( { "rawtypes", "unchecked" })
+ @Override
+ public Set<? extends NodeMetadata> listNodesDetailsMatching(Predicate filter) {
+ checkState(started.get(), "pool is not started");
+ return FluentIterable.from(filterAssignmentsBasedOnUserPredicate(filter)).transform(
+ new Function<Map.Entry<String, NodeMetadata>, NodeMetadata>() {
+ @Override
+ public NodeMetadata apply(Entry<String, NodeMetadata> input) {
+ return toFrontendNodemetadata(input.getValue(), input.getKey());
+ }
+ }).toImmutableSet();
+ }
+
+ @Override
+ public void rebootNodesMatching(final Predicate<NodeMetadata> filter) {
+ checkState(started.get(), "pool is not started");
+ backingComputeService.rebootNodesMatching(transformUserPredicateSpecificIdPredicate(filter));
+ }
+
+ @Override
+ public void resumeNodesMatching(Predicate<NodeMetadata> filter) {
+ checkState(started.get(), "pool is not started");
+ backingComputeService.resumeNodesMatching(transformUserPredicateSpecificIdPredicate(filter));
+ }
+
+ @Override
+ public void suspendNodesMatching(Predicate<NodeMetadata> filter) {
+ checkState(started.get(), "pool is not started");
+ backingComputeService.suspendNodesMatching(transformUserPredicateSpecificIdPredicate(filter));
+ }
+
+ @Override
+ public ComputeServiceContext getContext() {
+ // not sure this is enough, should we have our own?
+ return backingComputeService.getContext();
+ }
+
+ // we ignore user provided templates and options
+
+ @Override
+ public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template)
+ throws RunNodesException {
+ return createNodesInGroup(group, count);
+ }
+
+ @Override
+ public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions)
+ throws RunNodesException {
+ return createNodesInGroup(group, count);
+ }
+
+ @Override
+ public TemplateBuilder templateBuilder() {
+ return backingComputeService.templateBuilder().fromTemplate(template);
+ }
+
+ @Override
+ public TemplateOptions templateOptions() {
+ return backingComputeService.templateOptions();
+ }
+
+ @Override
+ public Set<? extends Hardware> listHardwareProfiles() {
+ return ImmutableSet.of(hardware);
+ }
+
+ @Override
+ public Set<? extends Image> listImages() {
+ return ImmutableSet.of(image);
+
+ }
+
+ @Override
+ public Image getImage(String id) {
+ return image.getId().equals(id) ? image : null;
+ }
+
+ @Override
+ public Set<? extends Location> listAssignableLocations() {
+ return ImmutableSet.of(location);
+ }
+
+ @Override
+ public void suspendNode(String id) {
+ if (findAssigmentEntry(id) != null) {
+ backingComputeService.suspendNode(id);
+ }
+ throw new NoSuchElementException(id);
+ }
+
+ @Override
+ public void resumeNode(String id) {
+ if (findAssigmentEntry(id) != null) {
+ backingComputeService.resumeNode(id);
+ }
+ throw new NoSuchElementException(id);
+ }
+
+ @Override
+ public void rebootNode(String id) {
+ if (findAssigmentEntry(id) != null) {
+ backingComputeService.rebootNode(id);
+ }
+ throw new NoSuchElementException(id);
+ }
+
+ @Override
+ public ExecResponse runScriptOnNode(String id, Statement runScript) {
+ if (findAssigmentEntry(id) != null) {
+ return runScriptOnNode(id, runScript, new RunScriptOptions());
+ }
+ throw new NoSuchElementException(id);
+ }
+
+ @Override
+ public ExecResponse runScriptOnNode(String id, String runScript) {
+ if (findAssigmentEntry(id) != null) {
+ return runScriptOnNode(id, runScript, new RunScriptOptions());
+ }
+ throw new NoSuchElementException(id);
+
+ }
+
+ @Override
+ public ExecResponse runScriptOnNode(String id, Statement runScript, RunScriptOptions options) {
+ if (findAssigmentEntry(id) != null) {
+ return backingComputeService.runScriptOnNode(id, runScript, options);
+ }
+ throw new NoSuchElementException(id);
+ }
+
+ @Override
+ public ListenableFuture<ExecResponse> submitScriptOnNode(String id, Statement runScript, RunScriptOptions options) {
+ if (findAssigmentEntry(id) != null) {
+ return backingComputeService.submitScriptOnNode(id, runScript, options);
+ }
+ throw new NoSuchElementException(id);
+ }
+
+ @Override
+ public ExecResponse runScriptOnNode(String id, String runScript, RunScriptOptions options) {
+ if (findAssigmentEntry(id) != null) {
+ return backingComputeService.runScriptOnNode(id, runScript, options);
+ }
+ throw new NoSuchElementException(id);
+ }
+
+ @Override
+ public Optional<ImageExtension> getImageExtension() {
+ return Optional.absent();
+ }
+
+}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/internal/BasePooledComputeService.java b/labs/nodepool/src/main/java/org/jclouds/nodepool/internal/BasePooledComputeService.java
deleted file mode 100644
index 725be05..0000000
--- a/labs/nodepool/src/main/java/org/jclouds/nodepool/internal/BasePooledComputeService.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. jclouds 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.nodepool.internal;
-
-import java.util.Map;
-import java.util.Set;
-
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.ComputeServiceContext;
-import org.jclouds.compute.ImageExtension;
-import org.jclouds.compute.RunNodesException;
-import org.jclouds.compute.RunScriptOnNodesException;
-import org.jclouds.compute.domain.ComputeMetadata;
-import org.jclouds.compute.domain.ExecResponse;
-import org.jclouds.compute.domain.Hardware;
-import org.jclouds.compute.domain.Image;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.NodeMetadataBuilder;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.domain.TemplateBuilder;
-import org.jclouds.compute.options.RunScriptOptions;
-import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.domain.Location;
-import org.jclouds.nodepool.PooledComputeService;
-import org.jclouds.scriptbuilder.domain.Statement;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.ListenableFuture;
-
-public class BasePooledComputeService implements PooledComputeService {
-
- private final ComputeService backingComputeService;
- private final String backingGroup;
- private final Template backingTemplate;
- private final int minPoolSize;
- private Map<NodeMetadata, String> groupMapping;
-
- public BasePooledComputeService(ComputeService backingComputeService, String backingGroup, Template backingTemplate, int minPoolSize) {
- this.backingComputeService = backingComputeService;
- this.backingGroup = backingGroup;
- this.backingTemplate = backingTemplate;
- this.minPoolSize = minPoolSize;
- }
-
- @Override
- public void startPool() throws RunNodesException {
- Set<? extends NodeMetadata> backingNodes =
- backingComputeService.createNodesInGroup(backingGroup, minPoolSize, backingTemplate);
- groupMapping = Maps.newHashMap();
- for (NodeMetadata node : backingNodes) {
- groupMapping.put(node, "unassigned");
- }
- }
-
- @Override
- public ComputeServiceContext getContext() {
- return backingComputeService.getContext();
- }
-
- @Override
- public TemplateBuilder templateBuilder() {
- return backingComputeService.templateBuilder();
- }
-
- @Override
- public TemplateOptions templateOptions() {
- return backingComputeService.templateOptions();
- }
-
- @Override
- public Set<? extends Hardware> listHardwareProfiles() {
- return ImmutableSet.<Hardware>of(backingTemplate.getHardware());
- }
-
- @Override
- public Set<? extends Image> listImages() {
- return ImmutableSet.<Image>of(backingTemplate.getImage());
- }
-
- @Override
- public Set<? extends ComputeMetadata> listNodes() {
- Set<NodeMetadata> allocatedNodes = Sets.newLinkedHashSet();
- for (ComputeMetadata node : backingComputeService.listNodes()) {
- NodeMetadata metadata = backingComputeService.getNodeMetadata(node.getId());
- String group = groupMapping.get(node);
- if ("unassigned".equals(group))
- continue;
- NodeMetadata nodeWithUpdatedGroup =
- NodeMetadataBuilder.fromNodeMetadata(metadata).group(group).build();
- allocatedNodes.add(nodeWithUpdatedGroup);
- }
- return allocatedNodes;
- }
-
- @Override
- public Set<? extends Location> listAssignableLocations() {
- return ImmutableSet.<Location>of(backingTemplate.getLocation());
- }
-
- @Override
- public Set<? extends NodeMetadata> createNodesInGroup(String group,
- int count, Template template) throws RunNodesException {
- throw new RuntimeException("not implemented");
- }
-
- @Override
- public Set<? extends NodeMetadata> createNodesInGroup(String group,
- int count, TemplateOptions templateOptions)
- throws RunNodesException {
- throw new RuntimeException("not implemented");
- }
-
- @Override
- public Set<? extends NodeMetadata> createNodesInGroup(String group,
- int count) throws RunNodesException {
- int allocatedCount = 0;
- Set<NodeMetadata> allocatedNodes = Sets.newLinkedHashSet();
- for (NodeMetadata metadata : groupMapping.keySet()) {
- if (groupMapping.get(metadata).equals("unassigned")) {
- groupMapping.put(metadata, "group");
- NodeMetadata nodeWithUpdatedGroup =
- NodeMetadataBuilder.fromNodeMetadata(metadata).group(group).build();
- allocatedNodes.add(nodeWithUpdatedGroup);
- allocatedCount += 1;
- if (allocatedCount == count) break;
- }
- }
- return allocatedNodes;
- }
-
- @Override
- public void resumeNode(String id) {
- backingComputeService.resumeNode(id);
-
- }
-
- @Override
- public void resumeNodesMatching(Predicate<NodeMetadata> filter) {
- backingComputeService.resumeNodesMatching(filter);
-
- }
-
- @Override
- public void suspendNode(String id) {
- backingComputeService.suspendNode(id);
- }
-
- @Override
- public void suspendNodesMatching(Predicate<NodeMetadata> filter) {
- backingComputeService.suspendNodesMatching(filter);
- }
-
- @Override
- public void destroyNode(String id) {
-
- backingComputeService.destroyNode(id);
- }
-
- @Override
- public Set<? extends NodeMetadata> destroyNodesMatching(
- Predicate<NodeMetadata> filter) {
- return backingComputeService.destroyNodesMatching(filter);
- }
-
- @Override
- public void rebootNode(String id) {
- backingComputeService.rebootNode(id);
-
- }
-
- @Override
- public void rebootNodesMatching(Predicate<NodeMetadata> filter) {
- backingComputeService.rebootNodesMatching(filter);
-
- }
-
- @Override
- public NodeMetadata getNodeMetadata(String id) {
- return backingComputeService.getNodeMetadata(id);
- }
-
- @Override
- public Set<? extends NodeMetadata> listNodesDetailsMatching(
- Predicate<ComputeMetadata> filter) {
- return backingComputeService.listNodesDetailsMatching(filter);
- }
-
- @Override
- public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(
- Predicate<NodeMetadata> filter, String runScript)
- throws RunScriptOnNodesException {
- // TODO Auto-generated method stub
- return backingComputeService.runScriptOnNodesMatching(filter, runScript);
- }
-
- @Override
- public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(
- Predicate<NodeMetadata> filter, Statement runScript)
- throws RunScriptOnNodesException {
- return backingComputeService.runScriptOnNodesMatching(filter, runScript);
- }
-
- @Override
- public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(
- Predicate<NodeMetadata> filter, String runScript,
- RunScriptOptions options) throws RunScriptOnNodesException {
- return backingComputeService.runScriptOnNodesMatching(filter, runScript, options);
- }
-
- @Override
- public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(
- Predicate<NodeMetadata> filter, Statement runScript,
- RunScriptOptions options) throws RunScriptOnNodesException {
- return backingComputeService.runScriptOnNodesMatching(filter, runScript, options);
- }
-
- @Override
- public ExecResponse runScriptOnNode(String id, Statement runScript,
- RunScriptOptions options) {
- return backingComputeService.runScriptOnNode(id, runScript, options);
- }
-
- @Override
- public ListenableFuture<ExecResponse> submitScriptOnNode(String id,
- Statement runScript, RunScriptOptions options) {
- return backingComputeService.submitScriptOnNode(id, runScript, options);
- }
-
- @Override
- public ExecResponse runScriptOnNode(String id, Statement runScript) {
- return backingComputeService.runScriptOnNode(id, runScript);
- }
-
- @Override
- public ExecResponse runScriptOnNode(String id, String runScript,
- RunScriptOptions options) {
- return backingComputeService.runScriptOnNode(id, runScript, options);
- }
-
- @Override
- public ExecResponse runScriptOnNode(String id, String runScript) {
- return backingComputeService.runScriptOnNode(id, runScript);
- }
-
- @Override
- public Optional<ImageExtension> getImageExtension() {
- return Optional.absent();
- }
-
-}
diff --git a/labs/nodepool/src/main/java/org/jclouds/nodepool/internal/EagerNodePoolComputeService.java b/labs/nodepool/src/main/java/org/jclouds/nodepool/internal/EagerNodePoolComputeService.java
new file mode 100644
index 0000000..f3d0481d
--- /dev/null
+++ b/labs/nodepool/src/main/java/org/jclouds/nodepool/internal/EagerNodePoolComputeService.java
@@ -0,0 +1,250 @@
+package org.jclouds.nodepool.internal;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.removeIf;
+import static com.google.common.collect.Iterables.transform;
+import static org.jclouds.nodepool.config.NodePoolComputeServiceProperties.BACKING_GROUP_PROPERTY;
+import static org.jclouds.nodepool.config.NodePoolComputeServiceProperties.BACKING_TEMPLATE_PROPERTY;
+import static org.jclouds.nodepool.config.NodePoolComputeServiceProperties.MAX_SIZE_PROPERTY;
+import static org.jclouds.nodepool.config.NodePoolComputeServiceProperties.MIN_SIZE_PROPERTY;
+import static org.jclouds.nodepool.config.NodePoolComputeServiceProperties.REMOVE_DESTROYED_PROPERTY;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.annotation.Nullable;
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.Constants;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.NodeMetadata.Status;
+import org.jclouds.compute.predicates.NodePredicates;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.concurrent.Futures;
+import org.jclouds.logging.Logger;
+import org.jclouds.nodepool.NodePoolComputeService;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * An eager {@link NodePoolComputeService}. Eagerly builds and maintains a pool of nodes. It's only
+ * "started" after min nodes are allocated and available.
+ *
+ * @author David Alves
+ *
+ */
+public class EagerNodePoolComputeService extends BaseNodePoolComputeService {
+
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ private final int maxSize;
+ private final boolean reuseDestroyed;
+ private final int minSize;
+ private final ExecutorService executor;
+
+ // set of available nodes
+ private Set<NodeMetadata> available = Sets.newHashSet();
+
+ // lock associated with changes to the pool since they happen asynchronously
+ private final Lock lock = new ReentrantLock();
+
+ // all the nodes in the pool (associated or not)
+ private final Set<NodeMetadata> poolNodes = Sets.newLinkedHashSet();
+
+ @Inject
+ public EagerNodePoolComputeService(ComputeServiceContext backingComputeServiceContext,
+ @Named(BACKING_GROUP_PROPERTY) String poolGroupPrefix,
+ @Named(MAX_SIZE_PROPERTY) int maxSize, @Named(MIN_SIZE_PROPERTY) int minSize,
+ @Named(REMOVE_DESTROYED_PROPERTY) boolean readdDestroyed,
+ @Nullable @Named(BACKING_TEMPLATE_PROPERTY) Template backingTemplate,
+ @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
+ super(backingComputeServiceContext, poolGroupPrefix, backingTemplate);
+ this.maxSize = maxSize;
+ this.minSize = minSize;
+ this.reuseDestroyed = readdDestroyed;
+ this.executor = executor;
+ }
+
+ @Override
+ public synchronized Set<? extends NodeMetadata> createNodesInGroup(String group, int count) throws RunNodesException {
+ checkState(started.get(), "pool is not started");
+ try {
+ return assignPoolNodes(group, count);
+ } catch (Exception e) {
+ Set<NodeMetadata> nodes = Collections.emptySet();
+ Map<String, Exception> executionExceptions = ImmutableMap.of("poolnode", e);
+ Map<NodeMetadata, Exception> failedNodes = ImmutableMap.of(new NodeMetadataBuilder().id("poolnode").status(
+ Status.ERROR).build(), e);
+ throw new RunNodesException(group, count, template, nodes, executionExceptions, failedNodes);
+ }
+ }
+
+ @Override
+ public synchronized void destroyNode(String id) {
+ checkState(started.get(), "pool is not started");
+ unassignNode(id);
+ }
+
+ @Override
+ public synchronized Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
+ checkState(started.get(), "pool is not started");
+ // copy the set of nodes to unassign because we'll be altering the assignments map.
+ Set<Map.Entry<String, NodeMetadata>> poolNodesToUnassign = Sets
+ .newHashSet(filterAssignmentsBasedOnUserPredicate(filter));
+ // TODO this should be done in parallel since it can take quite a while, moreover the contract
+ // for any destroy node action should probably be that the pool has at least minSize nodes
+ // before it returns. need to think it through a bit better.
+ for (Map.Entry<String, NodeMetadata> poolNode : poolNodesToUnassign) {
+ unassignNode(poolNode.getValue().getId());
+ }
+ return Sets.newHashSet(transform(poolNodesToUnassign,
+ new Function<Map.Entry<String, NodeMetadata>, NodeMetadata>() {
+ @Override
+ public NodeMetadata apply(final Map.Entry<String, NodeMetadata> input) {
+ assignments.remove(input.getKey(), input.getValue());
+ return toFrontendNodemetadata(input.getValue(), input.getKey());
+ }
+ }));
+
+ }
+
+ /**
+ * Adds nodes to the pool, using the pool's group name. Lock the pool so that no-one tries to
+ * increase/decrease until we're finished but we'll return from the method well before the pool
+ * as enough nodes.
+ */
+ private ListenableFuture<Void> increasePoolSize(final int size) {
+ lock.lock();
+ logger.debug(">> increasing pool size, available: %s total: %s min; %s max: %s increasing to: %s", available
+ .size(), poolNodes.size(), minSize, maxSize, size);
+ return Futures.makeListenable(executor.submit(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ try {
+ Set<? extends NodeMetadata> original = backingComputeService.createNodesInGroup(poolGroupName, size,
+ template);
+ poolNodes.addAll(original);
+ available.addAll(original);
+ logger.debug("<< pool size increased, available: %s total: %s min; %s max: %s increasing to: %s",
+ available.size(), poolNodes.size(), minSize, maxSize, size);
+ if (started.compareAndSet(false, true)) {
+ logger.info("pool started, status: %s min; %s max: %s", available.size(), minSize, maxSize);
+ }
+ return null;
+ } finally {
+ lock.unlock();
+ }
+ }
+ }), executor);
+ }
+
+ /**
+ * Unassigns the node with the provided id. If the we're set to reuse the nodes it adds it to the
+ * available pool, if not is destroys the backing node, removes if from the poll and increases
+ * the pool size by one.
+ */
+ private NodeMetadata unassignNode(final String nodeId) {
+ Map.Entry<String, NodeMetadata> entry = findAssigmentEntry(nodeId);
+ assignments.remove(entry.getKey(), entry.getValue());
+ // if we're reusing destroyed simply add to the available nodes
+ if (reuseDestroyed) {
+ available.add(entry.getValue());
+ return entry.getValue();
+ }
+ // if not we need to destroy the backing node
+ lock.lock();
+ try {
+ backingComputeService.destroyNode(nodeId);
+ removeIf(poolNodes, new Predicate<NodeMetadata>() {
+ @Override
+ public boolean apply(NodeMetadata input) {
+ return input.getId().equals(nodeId);
+ }
+ });
+ if (poolNodes.size() < minSize) {
+ increasePoolSize(1);
+ }
+ } finally {
+ lock.unlock();
+ }
+ return entry.getValue();
+ }
+
+ /**
+ * Used to assign size pool nodes to a group. If not enough nodes are available we check if we
+ * can increase the pool if that is enough, otherwise we complain.
+ */
+ private Set<? extends NodeMetadata> assignPoolNodes(String groupName, int size) throws InterruptedException,
+ ExecutionException {
+ if (available.size() < size) {
+ if (poolNodes.size() + size > maxSize) {
+ // TODO think of a better exception
+ throw new IllegalStateException(
+ "not enough nodes available and cannot add enough nodes to pool [available: " + available.size()
+ + " total: " + poolNodes.size() + " min: " + minSize + " max: " + maxSize
+ + " requested: " + size + "]");
+ }
+ increasePoolSize(size - available.size()).get();
+ }
+ Set<NodeMetadata> groupNodes = Sets.newHashSet();
+ Iterator<NodeMetadata> iter = available.iterator();
+ for (int i = 0; i < size && iter.hasNext(); i++) {
+ NodeMetadata node = iter.next();
+ assignments.put(groupName, node);
+ iter.remove();
+ groupNodes.add(toFrontendNodemetadata(node, groupName));
+ }
+ return groupNodes;
+ }
+
+ @Override
+ public ListenableFuture<Void> startPool() {
+ return increasePoolSize(minSize);
+ }
+
+ @Override
+ public void close() {
+ // lock just to make sure we have the correct pool size
+ if (started.compareAndSet(true, false)) {
+ logger.info("Closing pooled compute service with {} nodes", size());
+ available.clear();
+ assignments.clear();
+ backingComputeService.destroyNodesMatching(NodePredicates.inGroup(poolGroupName));
+ }
+ }
+
+ @Override
+ public int ready() {
+ return available.size();
+ }
+
+ @Override
+ public int size() {
+ return poolNodes.size();
+ }
+
+ @Override
+ public int maxSize() {
+ return maxSize;
+ }
+
+}
diff --git a/labs/nodepool/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/labs/nodepool/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
new file mode 100644
index 0000000..64dfe90
--- /dev/null
+++ b/labs/nodepool/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
@@ -0,0 +1 @@
+org.jclouds.nodepool.NodePoolApiMetadata
\ No newline at end of file
diff --git a/labs/nodepool/src/test/java/org/jclouds/nodepool/AppTest.java b/labs/nodepool/src/test/java/org/jclouds/nodepool/AppTest.java
deleted file mode 100644
index d198d7d..0000000
--- a/labs/nodepool/src/test/java/org/jclouds/nodepool/AppTest.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. jclouds 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.nodepool;
-
-import static com.google.common.base.Throwables.propagate;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Properties;
-import java.util.logging.Logger;
-
-import junit.framework.TestCase;
-
-import org.jclouds.Constants;
-import org.jclouds.ContextBuilder;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.ComputeServiceContext;
-import org.jclouds.compute.RunNodesException;
-import org.jclouds.compute.domain.ComputeMetadata;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.NodeState;
-import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.domain.TemplateBuilder;
-import org.jclouds.enterprise.config.EnterpriseConfigurationModule;
-import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
-import org.jclouds.nodepool.internal.BasePooledComputeService;
-import org.jclouds.scriptbuilder.domain.Statement;
-import org.jclouds.scriptbuilder.domain.Statements;
-import org.jclouds.scriptbuilder.statements.java.InstallJDK;
-import org.jclouds.scriptbuilder.statements.login.AdminAccess;
-import org.jclouds.sshj.config.SshjSshClientModule;
-
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.inject.Module;
-
-/**
- * Unit test for simple App.
- */
-public class AppTest extends TestCase {
- private String identity;
- private String credential;
- private String providerName;
- private File privateKey;
- private File publicKey;
- private String endPointUrl;
- public String profile;
- private int retentionTime;
- public int instanceCap;
-
- private String imageId;
- private String osFamily;
- private String osVersion;
- private String hardwareId;
- private int ram;
- private int cores;
- private String initScript;
- private String name;
- private boolean stopOnTerminate;
- private ComputeService compute;
- private PooledComputeService pooledCompute;
- private Collection<NodeMetadata> nodes = new LinkedList<NodeMetadata>();
- private static Logger LOGGER = Logger.getLogger("AppTest");
-
- private long time;
-
- @Override
- protected void setUp() throws Exception {
- // setup JCloudsCloud
- identity = "insert-your-identity-here";
- credential = "insert-your-credential-here";
- providerName = "aws-ec2";
- privateKey = new File("private-key");
- publicKey = new File("public-key");
- endPointUrl = "";
- profile = "aws-slave-profile";
- retentionTime = -1;
- instanceCap = 3;
-
- // cloud instance template
- name = "aws-jenkins-slave";
- // numExecutors = 1;
- // description = ""
- imageId = "us-east-1/ami-4dad7424";
- osFamily = "";
- osVersion = "";
- hardwareId = "t1.micro";
- ram = -1;
- cores = -1;
- // labels = "whii";
- initScript = "touch /tmp/hellothere";
- stopOnTerminate = true;
- }
-
- /**
- * Rigourous Test :-)
- */
- public void testApp() {
- createCompute();
- assertNotNull(compute);
- createAndStartPool();
- assertNotNull(pooledCompute);
- for (int i = 0; i < 3; i++) {
- startCounter();
- provision("pool-1");
- stopCounter();
- }
- for (int i = 0; i < 3; i++) {
- startCounter();
- provision("pool-2");
- stopCounter();
- }
- for (int i = 0; i < 3; i++) {
- startCounter();
- provision("pool-3");
- stopCounter();
- }
- assertEquals(9, getRunningNodesCount());
- for (NodeMetadata slave : nodes) {
- assertNotNull(slave);
- LOGGER.info(slave.getId() + "-" + slave.getGroup());
- terminate(slave);
- }
- assertEquals(0, getRunningNodesCount());
- }
-
- private void stopCounter() {
- LOGGER.info("Elapsed time: " + (System.currentTimeMillis() - time));
- }
-
- private void startCounter() {
- time = System.currentTimeMillis();
- }
-
- public AppTest getCloud() {
- return this;
- }
-
- public ComputeService getCompute() {
- return pooledCompute;
- }
-
- public NodeMetadata provision(String groupName) {
- LOGGER.info("Provisioning new node");
- NodeMetadata nodeMetadata = createNodeWithJdk(groupName);
- nodes.add(nodeMetadata);
- return nodeMetadata;
- }
-
- public int getRunningNodesCount() {
- int nodeCount = 0;
-
- for (ComputeMetadata cm : pooledCompute.listNodes()) {
- if (NodeMetadata.class.isInstance(cm)) {
- String nodeGroup = ((NodeMetadata) cm).getGroup();
-
- if (!((NodeMetadata) cm).getState().equals(Status.SUSPENDED)
- && !((NodeMetadata) cm).getState().equals(Status.TERMINATED)) {
- nodeCount++;
- }
- }
- }
- return nodeCount;
- }
-
- private void createCompute() {
- Properties overrides = new Properties();
- if (!Strings.isNullOrEmpty(this.endPointUrl)) {
- overrides.setProperty(Constants.PROPERTY_ENDPOINT, this.endPointUrl);
- }
- Iterable<Module> modules = ImmutableSet.<Module> of(new SshjSshClientModule(), new SLF4JLoggingModule(),
- new EnterpriseConfigurationModule());
- this.compute = ContextBuilder.newBuilder(providerName)
- .credentials(identity, credential)
- .modules(modules)
- .overrides(overrides).buildView(ComputeServiceContext.class).getComputeService();
- }
-
- private void createAndStartPool() {
- LOGGER.info("creating jclouds nodepool");
- ImmutableMap<String, String> userMetadata = ImmutableMap.of("Name", name);
- TemplateBuilder templateBuilder = compute.templateBuilder();
- if (!Strings.isNullOrEmpty(imageId)) {
- LOGGER.info("Setting image id to " + imageId);
- templateBuilder.imageId(imageId);
- } else {
- if (!Strings.isNullOrEmpty(osFamily)) {
- LOGGER.info("Setting osFamily to " + osFamily);
- templateBuilder.osFamily(OsFamily.valueOf(osFamily));
- }
- if (!Strings.isNullOrEmpty(osVersion)) {
- LOGGER.info("Setting osVersion to " + osVersion);
- templateBuilder.osVersionMatches(osVersion);
- }
- }
- if (!Strings.isNullOrEmpty((hardwareId))) {
- LOGGER.info("Setting hardware Id to " + hardwareId);
- } else {
- LOGGER.info("Setting minRam " + ram + " and minCores " + cores);
- templateBuilder.minCores(cores).minRam(ram);
- }
-
- Template template = templateBuilder.build();
-
- // setup the jcloudTemplate to customize the nodeMetadata with jdk, etc.
- // also opening ports
- AdminAccess adminAccess = AdminAccess.builder().adminUsername("jenkins").installAdminPrivateKey(false) // no
- // need
- .grantSudoToAdminUser(false) // no need
- .adminPrivateKey(getCloud().privateKey) // temporary due to jclouds
- // bug
- .authorizeAdminPublicKey(true).adminPublicKey(getCloud().publicKey).build();
-
- // Jenkins needs /jenkins dir.
- Statement jenkinsDirStatement = Statements.newStatementList(Statements.exec("mkdir /jenkins"),
- Statements.exec("chown jenkins /jenkins"));
-
- Statement bootstrap = newStatementList(adminAccess, jenkinsDirStatement, Statements.exec(this.initScript),
- InstallJDK.fromOpenJDK());
-
- template.getOptions().inboundPorts(22).userMetadata(userMetadata).runScript(bootstrap);
-
- pooledCompute = new BasePooledComputeService(compute, "jenkins-pool", template, 10);
-
- try {
- pooledCompute.startPool();
- } catch (RunNodesException e) {
- destroyBadNodesAndPropagate(e);
- }
- }
-
- private NodeMetadata createNodeWithJdk(String groupName) {
- LOGGER.info("creating jclouds node");
-
- NodeMetadata nodeMetadata = null;
-
- try {
- nodeMetadata = getOnlyElement(pooledCompute.createNodesInGroup(groupName, 1));
- } catch (RunNodesException e) {
- throw destroyBadNodesAndPropagate(e);
- }
-
- // Check if nodeMetadata is null and throw
- return nodeMetadata;
- }
-
- private RuntimeException destroyBadNodesAndPropagate(RunNodesException e) {
- for (Map.Entry<? extends NodeMetadata, ? extends Throwable> nodeError : e.getNodeErrors().entrySet())
- getCloud().getCompute().destroyNode(nodeError.getKey().getId());
- throw propagate(e);
- }
-
- public void terminate(NodeMetadata nodeMetaData) {
- if (stopOnTerminate) {
- LOGGER.info("Suspending the Slave : " + nodeMetaData.getName());
- final ComputeService compute = getCloud().getCompute();
- compute.suspendNode(nodeMetaData.getId());
- } else {
- LOGGER.info("Terminating the Slave : " + nodeMetaData.getName());
- final ComputeService compute = getCloud().getCompute();
- compute.destroyNode(nodeMetaData.getId());
- }
- }
-
-}
diff --git a/labs/nodepool/src/test/java/org/jclouds/nodepool/NodePoolComputeServiceTest.java b/labs/nodepool/src/test/java/org/jclouds/nodepool/NodePoolComputeServiceTest.java
new file mode 100644
index 0000000..2ac202a
--- /dev/null
+++ b/labs/nodepool/src/test/java/org/jclouds/nodepool/NodePoolComputeServiceTest.java
@@ -0,0 +1,72 @@
+package org.jclouds.nodepool;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+
+import org.jclouds.ContextBuilder;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.predicates.NodePredicates;
+import org.jclouds.nodepool.internal.EagerNodePoolComputeService;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+@Test(groups = "unit", testName = "NodePoolComputeServiceTest")
+public class NodePoolComputeServiceTest {
+
+ private EagerNodePoolComputeService pooledComputeService;
+
+ @BeforeClass
+ public void setUp() {
+ ComputeServiceContext stubCtx = ContextBuilder.newBuilder("stub").buildView(ComputeServiceContext.class);
+ this.pooledComputeService = new EagerNodePoolComputeService(stubCtx, "pool", 10, 5, true, stubCtx
+ .getComputeService().templateBuilder().build(), stubCtx.utils().getUserExecutor());
+ }
+
+ public void testStartPool() throws InterruptedException, ExecutionException {
+ ListenableFuture<Void> future = this.pooledComputeService.startPool();
+ future.get();
+ assertEquals(pooledComputeService.ready(), 5);
+ assertEquals(pooledComputeService.size(), 5);
+ assertEquals(pooledComputeService.maxSize(), 10);
+ }
+
+ @Test(dependsOnMethods = "testStartPool", groups = { "unit", "poolStarted" })
+ public void testAllocateMinNodes() throws RunNodesException {
+ this.pooledComputeService.createNodesInGroup("1", 5);
+ // this pool is not supposed to add nodes past min until we request them
+ assertEquals(pooledComputeService.ready(), 0);
+ assertEquals(pooledComputeService.size(), 5);
+ }
+
+ @Test(dependsOnMethods = "testAllocateMinNodes", groups = { "unit", "poolStarted" })
+ public void testAllocateUpToMaxNodes() throws RunNodesException {
+ this.pooledComputeService.createNodesInGroup("2", 5);
+ assertEquals(pooledComputeService.ready(), 0);
+ assertEquals(pooledComputeService.size(), 10);
+ }
+
+ @Test(dependsOnMethods = "testAllocateUpToMaxNodes", groups = { "unit", "poolStarted" }, expectedExceptions = RunNodesException.class)
+ public void testAllocateMoreNodesFails() throws RunNodesException {
+ this.pooledComputeService.createNodesInGroup("3", 5);
+ System.out.println(this.pooledComputeService.size());
+ }
+
+ @Test(dependsOnMethods = "testAllocateUpToMaxNodes", groups = { "unit", "poolStarted" })
+ public void testDeallocatingNodesAndReallocating() throws RunNodesException {
+ this.pooledComputeService.destroyNodesMatching(NodePredicates.inGroup("2"));
+ assertEquals(pooledComputeService.ready(), 5);
+ this.pooledComputeService.createNodesInGroup("2", 5);
+ }
+
+ @Test(dependsOnGroups = "poolStarted")
+ public void testClose() throws IOException {
+ this.pooledComputeService.close();
+ assertEquals(0, pooledComputeService.ready());
+ }
+
+}
diff --git a/labs/nodepool/src/test/resources/logback.xml b/labs/nodepool/src/test/resources/logback.xml
new file mode 100644
index 0000000..fc22c87
--- /dev/null
+++ b/labs/nodepool/src/test/resources/logback.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<configuration scan="false">
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <file>target/test-data/jclouds.log</file>
+
+ <encoder>
+ <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+ </encoder>
+ </appender>
+
+ <appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
+ <file>target/test-data/jclouds-wire.log</file>
+
+ <encoder>
+ <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+ </encoder>
+ </appender>
+
+ <appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
+ <file>target/test-data/jclouds-compute.log</file>
+
+ <encoder>
+ <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+ </encoder>
+ </appender>
+
+ <appender name="SSHFILE" class="ch.qos.logback.core.FileAppender">
+ <file>target/test-data/jclouds-ssh.log</file>
+
+ <encoder>
+ <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+ </encoder>
+ </appender>
+
+ <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <Pattern>%-4r [%thread] %-5level - %msg%n</Pattern>
+ </encoder>
+ </appender>
+
+ <root>
+ <level value="DEBUG" />
+ <appender-ref ref="CONSOLE" />
+ </root>
+
+ <logger name="org.jclouds">
+ <level value="DEBUG" />
+ <appender-ref ref="FILE" />
+ </logger>
+
+ <logger name="jclouds.wire">
+ <level value="DEBUG" />
+ <appender-ref ref="WIREFILE" />
+ </logger>
+
+ <logger name="jclouds.headers">
+ <level value="DEBUG" />
+ <appender-ref ref="WIREFILE" />
+ </logger>
+
+ <logger name="jclouds.compute">
+ <level value="DEBUG" />
+ <appender-ref ref="COMPUTEFILE" />
+ </logger>
+
+ <logger name="jclouds.ssh">
+ <level value="DEBUG" />
+ <appender-ref ref="SSHFILE" />
+ </logger>
+
+</configuration>
diff --git a/labs/opsource-servers/pom.xml b/labs/opsource-servers/pom.xml
index 2f02745..71011b0 100644
--- a/labs/opsource-servers/pom.xml
+++ b/labs/opsource-servers/pom.xml
@@ -36,12 +36,10 @@
<properties>
<test.opsource-servers.endpoint>https://api.opsourcecloud.net/oec/${jclouds.api-version}</test.opsource-servers.endpoint>
<test.opsource-servers.api-version>0.9</test.opsource-servers.api-version>
- <test.opsource-servers.build-version />
+ <test.opsource-servers.build-version></test.opsource-servers.build-version>
<test.opsource-servers.identity>FIXME_USERNAME</test.opsource-servers.identity>
<test.opsource-servers.credential>FIXME_PASSWORD</test.opsource-servers.credential>
- <test.opsource-servers.image-id />
- <test.opsource-servers.image.login-user />
- <test.opsource-servers.image.authenticate-sudo />
+ <test.opsource-servers.template></test.opsource-servers.template>
<jclouds.osgi.export>org.jclouds.vcloud.director.v1_5*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -107,9 +105,7 @@
<test.opsource-servers.build-version>${test.opsource-servers.build-version}</test.opsource-servers.build-version>
<test.opsource-servers.identity>${test.opsource-servers.identity}</test.opsource-servers.identity>
<test.opsource-servers.credential>${test.opsource-servers.credential}</test.opsource-servers.credential>
- <test.opsource-servers.image-id>${test.opsource-servers.image-id}</test.opsource-servers.image-id>
- <test.opsource-servers.image.login-user>${test.opsource-servers.image.login-user}</test.opsource-servers.image.login-user>
- <test.opsource-servers.image.authenticate-sudo>${test.opsource-servers.image.authenticate-sudo}</test.opsource-servers.image.authenticate-sudo>
+ <test.opsource-servers.template>${test.opsource-servers.template}</test.opsource-servers.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/labs/pom.xml b/labs/pom.xml
index 2c45d37..b223764 100644
--- a/labs/pom.xml
+++ b/labs/pom.xml
@@ -46,8 +46,11 @@
<module>cdmi</module>
<module>openstack-glance</module>
<module>joyent-sdc</module>
+ <module>joyentcloud</module>
<module>openstack-quantum</module>
<module>rackspace-cloudidentity</module>
<module>rackspace-cloudservers-us</module>
+ <module>greenqloud-compute</module>
+ <module>greenqloud-storage</module>
</modules>
</project>
diff --git a/labs/rackspace-cloudservers-us/pom.xml b/labs/rackspace-cloudservers-us/pom.xml
index ccb4c21..cea349d 100644
--- a/labs/rackspace-cloudservers-us/pom.xml
+++ b/labs/rackspace-cloudservers-us/pom.xml
@@ -36,13 +36,10 @@
<properties>
<test.rackspace-cloudservers-us.endpoint>https://identity.api.rackspacecloud.com</test.rackspace-cloudservers-us.endpoint>
<test.rackspace-cloudservers-us.api-version>2</test.rackspace-cloudservers-us.api-version>
- <test.rackspace-cloudservers-us.build-version />
+ <test.rackspace-cloudservers-us.build-version></test.rackspace-cloudservers-us.build-version>
<test.rackspace-cloudservers-us.identity>${test.rackspace-us.identity}</test.rackspace-cloudservers-us.identity>
<test.rackspace-cloudservers-us.credential>${test.rackspace-us.credential}</test.rackspace-cloudservers-us.credential>
- <test.rackspace-cloudservers-us.image-id />
- <test.rackspace-cloudservers-us.image.login-user />
- <test.rackspace-cloudservers-us.image.authenticate-sudo />
-
+ <test.rackspace-cloudservers-us.template></test.rackspace-cloudservers-us.template>
<jclouds.osgi.export>org.jclouds.rackspace.cloudservers.us*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -134,9 +131,7 @@
<test.rackspace-cloudservers-us.build-version>${test.rackspace-cloudservers-us.build-version}</test.rackspace-cloudservers-us.build-version>
<test.rackspace-cloudservers-us.identity>${test.rackspace-cloudservers-us.identity}</test.rackspace-cloudservers-us.identity>
<test.rackspace-cloudservers-us.credential>${test.rackspace-cloudservers-us.credential}</test.rackspace-cloudservers-us.credential>
- <test.rackspace-cloudservers-us.image-id>${test.rackspace-cloudservers-us.image-id}</test.rackspace-cloudservers-us.image-id>
- <test.rackspace-cloudservers-us.image.login-user>${test.rackspace-cloudservers-us.image.login-user}</test.rackspace-cloudservers-us.image.login-user>
- <test.rackspace-cloudservers-us.image.authenticate-sudo>${test.rackspace-cloudservers-us.image.authenticate-sudo}</test.rackspace-cloudservers-us.image.authenticate-sudo>
+ <test.rackspace-cloudservers-us.template>${test.rackspace-cloudservers-us.template}</test.rackspace-cloudservers-us.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/labs/savvis-symphonyvpdc/pom.xml b/labs/savvis-symphonyvpdc/pom.xml
index a7013fd..c69a761 100644
--- a/labs/savvis-symphonyvpdc/pom.xml
+++ b/labs/savvis-symphonyvpdc/pom.xml
@@ -39,7 +39,7 @@
<test.savvis-symphonyvpdc.build-version>2.3</test.savvis-symphonyvpdc.build-version>
<test.savvis-symphonyvpdc.identity>FIXME</test.savvis-symphonyvpdc.identity>
<test.savvis-symphonyvpdc.credential>FIXME</test.savvis-symphonyvpdc.credential>
- <test.savvis-symphonyvpdc.image-id />
+ <test.savvis-symphonyvpdc.template></test.savvis-symphonyvpdc.template>
<test.savvis-symphonyvpdc.vdc-email>FIXME</test.savvis-symphonyvpdc.vdc-email>
<test.savvis-symphonyvpdc.loginUser>FIXME</test.savvis-symphonyvpdc.loginUser>
<test.savvis-symphonyvpdc.loginPassword>FIXME</test.savvis-symphonyvpdc.loginPassword>
@@ -112,7 +112,7 @@
<test.savvis-symphonyvpdc.build-version>${test.savvis-symphonyvpdc.build-version}</test.savvis-symphonyvpdc.build-version>
<test.savvis-symphonyvpdc.identity>${test.savvis-symphonyvpdc.identity}</test.savvis-symphonyvpdc.identity>
<test.savvis-symphonyvpdc.credential>${test.savvis-symphonyvpdc.credential}</test.savvis-symphonyvpdc.credential>
- <test.savvis-symphonyvpdc.image-id>${test.savvis-symphonyvpdc.image-id}</test.savvis-symphonyvpdc.image-id>
+ <test.savvis-symphonyvpdc.template>${test.savvis-symphonyvpdc.template}</test.savvis-symphonyvpdc.template>
<test.savvis-symphonyvpdc.vdc-email>${test.savvis-symphonyvpdc.vdc-email}</test.savvis-symphonyvpdc.vdc-email>
<test.savvis-symphonyvpdc.loginUser>${test.savvis-symphonyvpdc.loginUser}</test.savvis-symphonyvpdc.loginUser>
<test.savvis-symphonyvpdc.loginPassword>${test.savvis-symphonyvpdc.loginPassword}</test.savvis-symphonyvpdc.loginPassword>
diff --git a/labs/vcloud-director/pom.xml b/labs/vcloud-director/pom.xml
index e2bad9b..27a8807 100644
--- a/labs/vcloud-director/pom.xml
+++ b/labs/vcloud-director/pom.xml
@@ -39,15 +39,13 @@
<test.vcloud-director.build-version>1.5.0.464915</test.vcloud-director.build-version>
<test.vcloud-director.identity>FIXME_USERNAME_WHICH_MIGHT_BE_EMAIL@JClouds</test.vcloud-director.identity>
<test.vcloud-director.credential>FIXME_PASSWORD</test.vcloud-director.credential>
- <test.vcloud-director.image-id />
- <test.vcloud-director.image.login-user />
- <test.vcloud-director.image.authenticate-sudo />
- <test.vcloud-director.catalog-id />
- <test.vcloud-director.media-id />
- <test.vcloud-director.vapptemplate-id />
- <test.vcloud-director.network-id />
- <test.vcloud-director.vdc-id />
- <test.vcloud-director.user-id />
+ <test.vcloud-director.template></test.vcloud-director.template>
+ <test.vcloud-director.catalog-id></test.vcloud-director.catalog-id>
+ <test.vcloud-director.media-id></test.vcloud-director.media-id>
+ <test.vcloud-director.vapptemplate-id></test.vcloud-director.vapptemplate-id>
+ <test.vcloud-director.network-id></test.vcloud-director.network-id>
+ <test.vcloud-director.vdc-id></test.vcloud-director.vdc-id>
+ <test.vcloud-director.user-id></test.vcloud-director.user-id>
<jclouds.osgi.export>org.jclouds.vcloud.director.v1_5*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -125,9 +123,7 @@
<test.vcloud-director.build-version>${test.vcloud-director.build-version}</test.vcloud-director.build-version>
<test.vcloud-director.identity>${test.vcloud-director.identity}</test.vcloud-director.identity>
<test.vcloud-director.credential>${test.vcloud-director.credential}</test.vcloud-director.credential>
- <test.vcloud-director.image-id>${test.vcloud-director.image-id}</test.vcloud-director.image-id>
- <test.vcloud-director.image.login-user>${test.vcloud-director.image.login-user}</test.vcloud-director.image.login-user>
- <test.vcloud-director.image.authenticate-sudo>${test.vcloud-director.image.authenticate-sudo}</test.vcloud-director.image.authenticate-sudo>
+ <test.vcloud-director.template>${test.vcloud-director.template}</test.vcloud-director.template>
<test.vcloud-director.catalog-id>${test.vcloud-director.catalog-id}</test.vcloud-director.catalog-id>
<test.vcloud-director.media-id>${test.vcloud-director.media-id}</test.vcloud-director.media-id>
<test.vcloud-director.vapptemplate-id>${test.vcloud-director.vapptemplate-id}</test.vcloud-director.vapptemplate-id>
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/AdminOrgClientLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/AdminOrgClientLiveTest.java
index 53e8512..accbef2 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/AdminOrgClientLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/AdminOrgClientLiveTest.java
@@ -408,7 +408,7 @@
orgRef.getHref(), restorableSettings);
} catch (Exception e) {
if (exception != null) {
- logger.warn(e, "Error reseting settings; rethrowing origina test exception...");
+ logger.warn(e, "Error resetting settings; rethrowing original test exception...");
throw exception;
} else {
throw e;
diff --git a/labs/virtualbox/pom.xml b/labs/virtualbox/pom.xml
index 01e75cb..4355f52 100644
--- a/labs/virtualbox/pom.xml
+++ b/labs/virtualbox/pom.xml
@@ -39,10 +39,7 @@
<test.virtualbox.build-version>4.1.8r75467</test.virtualbox.build-version>
<test.virtualbox.identity>administrator</test.virtualbox.identity>
<test.virtualbox.credential>12345</test.virtualbox.credential>
- <test.virtualbox.image-id>test-ubuntu-11.10-i386</test.virtualbox.image-id>
- <test.virtualbox.image.login-user>toor:password</test.virtualbox.image.login-user>
- <test.virtualbox.image.authenticate-sudo>true</test.virtualbox.image.authenticate-sudo>
-
+ <test.virtualbox.template>imageId=test-ubuntu-11.10-i386,loginUser=toor:password,authenticateSudo=true</test.virtualbox.template>
<jclouds.osgi.export>org.jclouds.virtualbox*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
</properties>
@@ -144,9 +141,7 @@
<test.virtualbox.build-version>${test.virtualbox.build-version}</test.virtualbox.build-version>
<test.virtualbox.identity>${test.virtualbox.identity}</test.virtualbox.identity>
<test.virtualbox.credential>${test.virtualbox.credential}</test.virtualbox.credential>
- <test.virtualbox.image-id>${test.virtualbox.image-id}</test.virtualbox.image-id>
- <test.virtualbox.image.login-user>${test.virtualbox.image.login-user}</test.virtualbox.image.login-user>
- <test.virtualbox.image.authenticate-sudo>${test.virtualbox.image.authenticate-sudo}</test.virtualbox.image.authenticate-sudo>
+ <test.virtualbox.template>${test.virtualbox.template}</test.virtualbox.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java
index 1f7915f..b2c2c45 100644
--- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java
+++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java
@@ -139,8 +139,7 @@
Template template = view.getComputeService().templateBuilder().build();
checkNotNull(mastersCache.apply(template.getImage()));
- imageId = template.getImage().getId();
- masterVmName = VIRTUALBOX_IMAGE_PREFIX + imageId;
+ masterVmName = VIRTUALBOX_IMAGE_PREFIX + template.getImage().getId();
isosDir = workingDir + File.separator + "isos";
hostVersion = Iterables.get(Splitter.on('r').split(view.utils().injector().getInstance(Key.get(String.class, BuildVersion.class))), 0);
@@ -174,7 +173,7 @@
}
public MasterSpec getMasterSpecForTest() {
- String masterName = "jclouds-image-0x0-" + imageId;
+ String masterName = "jclouds-image-0x0-" + template.getImageId();
StorageController ideController = StorageController
.builder()
diff --git a/providers/aws-ec2/pom.xml b/providers/aws-ec2/pom.xml
index 1ffffde..3ea8981 100644
--- a/providers/aws-ec2/pom.xml
+++ b/providers/aws-ec2/pom.xml
@@ -36,13 +36,11 @@
<properties>
<test.aws-ec2.endpoint>https://ec2.us-east-1.amazonaws.com</test.aws-ec2.endpoint>
<test.aws-ec2.api-version>2011-05-15</test.aws-ec2.api-version>
- <test.aws-ec2.build-version />
+ <test.aws-ec2.build-version></test.aws-ec2.build-version>
<test.aws-ec2.identity>${test.aws.identity}</test.aws-ec2.identity>
<test.aws-ec2.credential>${test.aws.credential}</test.aws-ec2.credential>
- <test.aws-ec2.image-id />
- <test.aws-ec2.image.login-user />
- <test.aws-ec2.image.authenticate-sudo />
-
+ <test.aws-ec2.template></test.aws-ec2.template>
+ <test.aws-ec2.ebs-template>hardwareId=m1.small,imageId=us-west-2/ami-38c64a08</test.aws-ec2.ebs-template>
<jclouds.osgi.export>org.jclouds.aws.ec2*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -137,9 +135,8 @@
<test.aws-ec2.build-version>${test.aws-ec2.build-version}</test.aws-ec2.build-version>
<test.aws-ec2.identity>${test.aws-ec2.identity}</test.aws-ec2.identity>
<test.aws-ec2.credential>${test.aws-ec2.credential}</test.aws-ec2.credential>
- <test.aws-ec2.image-id>${test.aws-ec2.image-id}</test.aws-ec2.image-id>
- <test.aws-ec2.image.login-user>${test.aws-ec2.image.login-user}</test.aws-ec2.image.login-user>
- <test.aws-ec2.image.authenticate-sudo>${test.aws-ec2.image.authenticate-sudo}</test.aws-ec2.image.authenticate-sudo>
+ <test.aws-ec2.template>${test.aws-ec2.template}</test.aws-ec2.template>
+ <test.aws-ec2.ebs-template>${test.aws-ec2.ebs-template}</test.aws-ec2.ebs-template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AMIClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AMIClientLiveTest.java
deleted file mode 100644
index 9cf363c..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AMIClientLiveTest.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. jclouds 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.aws.ec2.services;
-
-import static org.jclouds.aws.ec2.options.AWSDescribeImagesOptions.Builder.filters;
-import static org.jclouds.aws.ec2.options.AWSDescribeImagesOptions.Builder.imageIds;
-import static org.jclouds.ec2.options.RegisterImageBackedByEbsOptions.Builder.addNewBlockDevice;
-import static org.jclouds.ec2.options.RegisterImageOptions.Builder.withDescription;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.util.Iterator;
-import java.util.Set;
-
-import org.jclouds.aws.domain.Region;
-import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.compute.predicates.ImagePredicates;
-import org.jclouds.ec2.domain.BlockDevice;
-import org.jclouds.ec2.domain.Image;
-import org.jclouds.ec2.domain.Reservation;
-import org.jclouds.ec2.domain.RootDeviceType;
-import org.jclouds.ec2.domain.RunningInstance;
-import org.jclouds.ec2.domain.Snapshot;
-import org.jclouds.ec2.domain.Image.ImageType;
-import org.jclouds.ec2.services.AMIClient;
-import org.testng.annotations.AfterTest;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-
-/**
- * Tests behavior of {@code AMIClient}
- *
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true)
-public class AMIClientLiveTest extends BaseComputeServiceContextLiveTest {
- public AMIClientLiveTest() {
- provider = "aws-ec2";
- // TODO: parameterize this.
- imageId = "ami-cdf819a4";
- }
-
- private AMIClient client;
- private static final String DEFAULT_MANIFEST = "adrianimages/image.manifest.xml";
- private static final String DEFAULT_SNAPSHOT = "TODO";
-
- private Set<String> imagesToDeregister = Sets.newHashSet();
- private Set<String> snapshotsToDelete = Sets.newHashSet();
-
- @Override
- @BeforeClass(groups = { "integration", "live" })
- public void setupContext() {
- super.setupContext();
- client = view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getAMIServices();
- }
-
- public void testDescribeImageNotExists() {
- assertEquals(client.describeImagesInRegion(null, imageIds("ami-cdf819a3")).size(), 0);
- }
-
- @Test(expectedExceptions = IllegalArgumentException.class)
- public void testDescribeImageBadId() {
- client.describeImagesInRegion(null, imageIds("asdaasdsa"));
- }
-
- public void testDescribeImages() {
- for (String region : view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getAvailabilityZoneAndRegionServices().describeRegions().keySet()) {
- Set<? extends Image> allResults = client.describeImagesInRegion(region);
- assertNotNull(allResults);
- assert allResults.size() >= 2 : allResults.size();
- Iterator<? extends Image> iterator = allResults.iterator();
- String id1 = iterator.next().getId();
- String id2 = iterator.next().getId();
- Set<? extends Image> twoResults = client.describeImagesInRegion(region, imageIds(id1, id2));
- assertNotNull(twoResults);
- assertEquals(twoResults.size(), 2);
- iterator = twoResults.iterator();
- assertEquals(iterator.next().getId(), id1);
- assertEquals(iterator.next().getId(), id2);
- }
- }
-
- public void testDescribeImagesCC() {
- Set<? extends Image> ccResults = client.describeImagesInRegion(Region.US_EAST_1, filters(
- ImmutableMultimap.<String, String> builder()//
- .put("virtualization-type", "hvm")//
- .put("architecture", "x86_64")//
- .putAll("owner-id", ImmutableSet.<String> of("137112412989", "099720109477"))//
- .put("hypervisor", "xen")//
- .put("state", "available")//
- .put("image-type", "machine")//
- .put("root-device-type", "ebs")//
- .build()).ownedBy("137112412989", "099720109477"));
- assertNotNull(ccResults);
- assert (ccResults.size() >= 34) : ccResults;
- }
-
- @Test(enabled = false)
- public void testRegisterImageFromManifest() {
- String imageRegisteredId = client.registerImageFromManifestInRegion(null, "jcloudstest1", DEFAULT_MANIFEST);
- imagesToDeregister.add(imageRegisteredId);
- Image imageRegisteredFromManifest = Iterables.getOnlyElement(client.describeImagesInRegion(null,
- imageIds(imageRegisteredId)));
- assertEquals(imageRegisteredFromManifest.getName(), "jcloudstest1");
- assertEquals(imageRegisteredFromManifest.getImageLocation(), DEFAULT_MANIFEST);
- assertEquals(imageRegisteredFromManifest.getImageType(), ImageType.MACHINE);
- assertEquals(imageRegisteredFromManifest.getRootDeviceType(), RootDeviceType.INSTANCE_STORE);
- assertEquals(imageRegisteredFromManifest.getRootDeviceName(), "/dev/sda1");
- }
-
- @Test(enabled = false)
- public void testRegisterImageFromManifestOptions() {
- String imageRegisteredWithOptionsId = client.registerImageFromManifestInRegion(null, "jcloudstest2",
- DEFAULT_MANIFEST, withDescription("adrian"));
- imagesToDeregister.add(imageRegisteredWithOptionsId);
- Image imageRegisteredFromManifestWithOptions = Iterables.getOnlyElement(client.describeImagesInRegion(null,
- imageIds(imageRegisteredWithOptionsId)));
- assertEquals(imageRegisteredFromManifestWithOptions.getName(), "jcloudstest2");
- assertEquals(imageRegisteredFromManifestWithOptions.getImageLocation(), DEFAULT_MANIFEST);
- assertEquals(imageRegisteredFromManifestWithOptions.getImageType(), ImageType.MACHINE);
- assertEquals(imageRegisteredFromManifestWithOptions.getRootDeviceType(), RootDeviceType.INSTANCE_STORE);
- assertEquals(imageRegisteredFromManifestWithOptions.getRootDeviceName(), "/dev/sda1");
- assertEquals(imageRegisteredFromManifestWithOptions.getDescription(), "adrian");
- }
-
- @Test
- public void testNewlyRegisteredImageCanBeListed() throws Exception {
- ComputeService computeService = view.getComputeService();
- Snapshot snapshot = createSnapshot(computeService);
-
- // List of images before...
- int sizeBefore = computeService.listImages().size();
-
- // Register a new image...
- final String imageRegisteredId = client.registerUnixImageBackedByEbsInRegion(null, "jcloudstest1", snapshot.getId());
- imagesToDeregister.add(imageRegisteredId);
- final Image imageRegistered = Iterables.getOnlyElement(client.describeImagesInRegion(null, imageIds(imageRegisteredId)));
-
- // This is the suggested method to ensure the new image ID is inserted into the cache
- // (suggested by adriancole_ on #jclouds)
- computeService.templateBuilder().imageId(imageRegistered.getRegion() + "/" + imageRegisteredId).build();
-
- // List of images after - should be one larger than before
- Set<? extends org.jclouds.compute.domain.Image> after = computeService.listImages();
- assertEquals(after.size(), sizeBefore + 1);
-
- // Detailed check: filter for the AMI ID
- Iterable<? extends org.jclouds.compute.domain.Image> filtered = Iterables.filter(after,
- ImagePredicates.idEquals(imageRegistered.getRegion() + "/" + imageRegisteredId));
- assertEquals(Iterables.size(filtered), 1);
- }
-
- // Fires up an instance, finds its root volume ID, takes a snapshot, then terminates the instance.
- private Snapshot createSnapshot(ComputeService computeService) throws RunNodesException {
- Template options = computeService.templateBuilder().smallest().build();
- Set<? extends NodeMetadata> nodes = computeService.createNodesInGroup("jcloudstest", 1, options);
- try {
- String instanceId = Iterables.getOnlyElement(nodes).getProviderId();
- Reservation<? extends RunningInstance> reservation = Iterables.getOnlyElement(view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getInstanceServices().describeInstancesInRegion(null, instanceId));
- RunningInstance instance = Iterables.getOnlyElement(reservation);
- BlockDevice device = instance.getEbsBlockDevices().get("/dev/sda1");
- Snapshot snapshot = view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getElasticBlockStoreServices().createSnapshotInRegion(null, device.getVolumeId());
- snapshotsToDelete.add(snapshot.getId());
- return snapshot;
- } finally {
- computeService.destroyNodesMatching(Predicates.in(nodes));
- }
- }
-
- @Test(enabled = false)
- // awaiting EBS functionality to be added to jclouds
- public void testRegisterImageBackedByEBS() {
- String imageRegisteredId = client.registerUnixImageBackedByEbsInRegion(null, "jcloudstest1", DEFAULT_MANIFEST);
- imagesToDeregister.add(imageRegisteredId);
- Image imageRegistered = Iterables
- .getOnlyElement(client.describeImagesInRegion(null, imageIds(imageRegisteredId)));
- assertEquals(imageRegistered.getName(), "jcloudstest1");
- assertEquals(imageRegistered.getImageType(), ImageType.MACHINE);
- assertEquals(imageRegistered.getRootDeviceType(), RootDeviceType.EBS);
- assertEquals(imageRegistered.getRootDeviceName(), "/dev/sda1");
- }
-
- @Test(enabled = false)
- // awaiting EBS functionality to be added to jclouds
- public void testRegisterImageBackedByEBSOptions() {
- String imageRegisteredWithOptionsId = client.registerUnixImageBackedByEbsInRegion(null, "jcloudstest2",
- DEFAULT_SNAPSHOT, addNewBlockDevice("/dev/sda2", "myvirtual", 1).withDescription("adrian"));
- imagesToDeregister.add(imageRegisteredWithOptionsId);
- Image imageRegisteredWithOptions = Iterables.getOnlyElement(client.describeImagesInRegion(null,
- imageIds(imageRegisteredWithOptionsId)));
- assertEquals(imageRegisteredWithOptions.getName(), "jcloudstest2");
- assertEquals(imageRegisteredWithOptions.getImageType(), ImageType.MACHINE);
- assertEquals(imageRegisteredWithOptions.getRootDeviceType(), RootDeviceType.EBS);
- assertEquals(imageRegisteredWithOptions.getRootDeviceName(), "/dev/sda1");
- assertEquals(imageRegisteredWithOptions.getDescription(), "adrian");
- assertEquals(imageRegisteredWithOptions.getEbsBlockDevices().entrySet(), ImmutableMap.of("/dev/sda1",
- new Image.EbsBlockDevice("/dev/sda1", 30, true), "/dev/sda2",
- new Image.EbsBlockDevice("/dev/sda2", 1, true)).entrySet());
- }
-
- @Test(enabled = false)
- public void testCreateImage() {
- // TODO client.createImageInRegion(null, name, instanceId, options);
- }
-
- @Test(enabled = false)
- public void testAddProductCodesToImage() {
- // TODO client.addProductCodesToImageInRegion(null, productCodes, imageId);
- }
-
- @Test(enabled = false)
- public void testAddLaunchPermissionsToImage() {
- // TODO client.addLaunchPermissionsToImageInRegion(null, userIds, userGroups,
- // imageId);
- }
-
- @Test(enabled = false)
- public void testRemoveLaunchPermissionsFromImage() {
- // TODO client.removeLaunchPermissionsFromImageInRegion(null, userIds, userGroups,
- // imageId);
- }
-
- @Test(enabled = false)
- public void testResetLaunchPermissionsOnImage() {
- // TODO client.resetLaunchPermissionsOnImageInRegion(null, imageId);
- }
-
- @Test(enabled = false)
- public void testGetLaunchPermissionForImage() {
- System.out.println(client.getLaunchPermissionForImageInRegion(null, imageId));
- }
-
- @Test(enabled = false)
- // awaiting ebs support
- public void testGetBlockDeviceMappingsForImage() {
- System.out.println(client.getBlockDeviceMappingsForImageInRegion(null, imageId));
- }
-
- @AfterTest
- public void cleanUp() {
- for (String imageId : imagesToDeregister)
- client.deregisterImageInRegion(null, imageId);
- for (String snapshotId : snapshotsToDelete)
- view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getElasticBlockStoreServices().deleteSnapshotInRegion(null, snapshotId);
- }
-
-}
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIClientLiveTest.java
index 739e843..fdab925 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIClientLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIClientLiveTest.java
@@ -18,186 +18,43 @@
*/
package org.jclouds.aws.ec2.services;
-import static org.jclouds.aws.ec2.options.AWSDescribeImagesOptions.Builder.imageIds;
-import static org.jclouds.ec2.options.RegisterImageBackedByEbsOptions.Builder.addNewBlockDevice;
-import static org.jclouds.ec2.options.RegisterImageOptions.Builder.withDescription;
-import static org.testng.Assert.assertEquals;
+import static org.jclouds.aws.ec2.options.AWSDescribeImagesOptions.Builder.filters;
import static org.testng.Assert.assertNotNull;
-import java.util.Iterator;
import java.util.Set;
-import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.aws.domain.Region;
import org.jclouds.ec2.domain.Image;
-import org.jclouds.ec2.domain.RootDeviceType;
-import org.jclouds.ec2.domain.Image.ImageType;
-import org.testng.annotations.AfterTest;
-import org.testng.annotations.BeforeClass;
+import org.jclouds.ec2.services.AMIClientLiveTest;
import org.testng.annotations.Test;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
/**
- * Tests behavior of {@code AWSAMIClient}
+ * Tests behavior of {@code AMIClient}
*
* @author Adrian Cole
*/
-@Test(groups = "live", singleThreaded = true, testName = "AWSAMIClientLiveTest")
-public class AWSAMIClientLiveTest extends BaseComputeServiceContextLiveTest {
+@Test(groups = "live", singleThreaded = true)
+public class AWSAMIClientLiveTest extends AMIClientLiveTest {
+
public AWSAMIClientLiveTest() {
provider = "aws-ec2";
- // TODO: parameterize this.
- imageId = "ami-7ea24a17";
- }
-
- private AWSAMIClient client;
- private static final String DEFAULT_MANIFEST = "adrianimages/image.manifest.xml";
- private static final String DEFAULT_SNAPSHOT = "TODO";
-
- private Set<String> imagesToDeregister = Sets.newHashSet();
-
- @Override
- @BeforeClass(groups = { "integration", "live" })
- public void setupContext() {
- super.setupContext();
- client = view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getAMIServices();
}
- public void testDescribeImageNotExists() {
- assertEquals(client.describeImagesInRegion(null, imageIds("ami-cdf819a3")).size(), 0);
- }
-
- @Test(expectedExceptions = IllegalArgumentException.class)
- public void testDescribeImageBadId() {
- client.describeImagesInRegion(null, imageIds("asdaasdsa"));
- }
-
- public void testDescribeImages() {
- for (String region : view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getAvailabilityZoneAndRegionServices().describeRegions().keySet()) {
- Set<Image> allResults = Sets.newLinkedHashSet(client.describeImagesInRegion(region));
- assertNotNull(allResults);
- assert allResults.size() >= 2 : allResults.size();
- Iterator<Image> iterator = allResults.iterator();
- String id1 = iterator.next().getId();
- String id2 = iterator.next().getId();
- Set<Image> twoResults = Sets.newLinkedHashSet(client.describeImagesInRegion(region, imageIds(id1, id2)));
- assertNotNull(twoResults);
- assertEquals(twoResults.size(), 2);
- iterator = twoResults.iterator();
- assertEquals(iterator.next().getId(), id1);
- assertEquals(iterator.next().getId(), id2);
- }
- }
-
- @Test(enabled = false)
- public void testRegisterImageFromManifest() {
- String imageRegisteredId = client.registerImageFromManifestInRegion(null, "jcloudstest1", DEFAULT_MANIFEST);
- imagesToDeregister.add(imageRegisteredId);
- Image imageRegisteredFromManifest = Iterables.getOnlyElement(client.describeImagesInRegion(null,
- imageIds(imageRegisteredId)));
- assertEquals(imageRegisteredFromManifest.getName(), "jcloudstest1");
- assertEquals(imageRegisteredFromManifest.getImageLocation(), DEFAULT_MANIFEST);
- assertEquals(imageRegisteredFromManifest.getImageType(), ImageType.MACHINE);
- assertEquals(imageRegisteredFromManifest.getRootDeviceType(), RootDeviceType.INSTANCE_STORE);
- assertEquals(imageRegisteredFromManifest.getRootDeviceName(), "/dev/sda1");
- }
-
- @Test(enabled = false)
- public void testRegisterImageFromManifestOptions() {
- String imageRegisteredWithOptionsId = client.registerImageFromManifestInRegion(null, "jcloudstest2",
- DEFAULT_MANIFEST, withDescription("adrian"));
- imagesToDeregister.add(imageRegisteredWithOptionsId);
- Image imageRegisteredFromManifestWithOptions = Iterables.getOnlyElement(client.describeImagesInRegion(null,
- imageIds(imageRegisteredWithOptionsId)));
- assertEquals(imageRegisteredFromManifestWithOptions.getName(), "jcloudstest2");
- assertEquals(imageRegisteredFromManifestWithOptions.getImageLocation(), DEFAULT_MANIFEST);
- assertEquals(imageRegisteredFromManifestWithOptions.getImageType(), ImageType.MACHINE);
- assertEquals(imageRegisteredFromManifestWithOptions.getRootDeviceType(), RootDeviceType.INSTANCE_STORE);
- assertEquals(imageRegisteredFromManifestWithOptions.getRootDeviceName(), "/dev/sda1");
- assertEquals(imageRegisteredFromManifestWithOptions.getDescription(), "adrian");
- }
-
- @Test(enabled = false)
- // awaiting EBS functionality to be added to jclouds
- public void testRegisterImageBackedByEBS() {
- String imageRegisteredId = client.registerUnixImageBackedByEbsInRegion(null, "jcloudstest1", DEFAULT_MANIFEST);
- imagesToDeregister.add(imageRegisteredId);
- Image imageRegistered = Iterables
- .getOnlyElement(client.describeImagesInRegion(null, imageIds(imageRegisteredId)));
- assertEquals(imageRegistered.getName(), "jcloudstest1");
- assertEquals(imageRegistered.getImageType(), ImageType.MACHINE);
- assertEquals(imageRegistered.getRootDeviceType(), RootDeviceType.EBS);
- assertEquals(imageRegistered.getRootDeviceName(), "/dev/sda1");
- }
-
- @Test(enabled = false)
- // awaiting EBS functionality to be added to jclouds
- public void testRegisterImageBackedByEBSOptions() {
- String imageRegisteredWithOptionsId = client.registerUnixImageBackedByEbsInRegion(null, "jcloudstest2",
- DEFAULT_SNAPSHOT, addNewBlockDevice("/dev/sda2", "myvirtual", 1).withDescription("adrian"));
- imagesToDeregister.add(imageRegisteredWithOptionsId);
- Image imageRegisteredWithOptions = Iterables.getOnlyElement(client.describeImagesInRegion(null,
- imageIds(imageRegisteredWithOptionsId)));
- assertEquals(imageRegisteredWithOptions.getName(), "jcloudstest2");
- assertEquals(imageRegisteredWithOptions.getImageType(), ImageType.MACHINE);
- assertEquals(imageRegisteredWithOptions.getRootDeviceType(), RootDeviceType.EBS);
- assertEquals(imageRegisteredWithOptions.getRootDeviceName(), "/dev/sda1");
- assertEquals(imageRegisteredWithOptions.getDescription(), "adrian");
- assertEquals(
- imageRegisteredWithOptions.getEbsBlockDevices().entrySet(),
- ImmutableMap.of("/dev/sda1", new Image.EbsBlockDevice("/dev/sda1", 30, true), "/dev/sda2",
- new Image.EbsBlockDevice("/dev/sda2", 1, true)).entrySet());
- }
-
- @Test(enabled = false)
- public void testCreateImage() {
- // TODO client.createImageInRegion(null, name, instanceId, options);
- }
-
- @Test(enabled = false)
- public void testAddProductCodesToImage() {
- // TODO client.addProductCodesToImageInRegion(null, productCodes, imageId);
- }
-
- @Test(enabled = false)
- public void testAddLaunchPermissionsToImage() {
- // TODO client.addLaunchPermissionsToImageInRegion(null, userIds, userGroups,
- // imageId);
- }
-
- @Test(enabled = false)
- public void testRemoveLaunchPermissionsFromImage() {
- // TODO client.removeLaunchPermissionsFromImageInRegion(null, userIds, userGroups,
- // imageId);
- }
-
- @Test(enabled = false)
- public void testResetLaunchPermissionsOnImage() {
- // TODO client.resetLaunchPermissionsOnImageInRegion(null, imageId);
- }
-
- @Test(enabled = false)
- public void testGetLaunchPermissionForImage() {
- // TODO System.out.println(client.getLaunchPermissionForImageInRegion(null, imageId));
- }
-
- @Test(enabled = false)
- public void testGetProductCodesForImage() {
- // TODO System.out.println(client.getProductCodesForImageInRegion(null, imageId));
- }
-
- @Test(enabled = false)
- // awaiting ebs support
- public void testGetBlockDeviceMappingsForImage() {
- System.out.println(client.getBlockDeviceMappingsForImageInRegion(null, imageId));
- }
-
- @AfterTest
- public void deregisterImages() {
- for (String imageId : imagesToDeregister)
- client.deregisterImageInRegion(null, imageId);
+ public void testDescribeImagesCC() {
+ Set<? extends Image> ccResults = client.describeImagesInRegion(Region.US_EAST_1,
+ filters(ImmutableMultimap.<String, String> builder()//
+ .put("virtualization-type", "hvm")//
+ .put("architecture", "x86_64")//
+ .putAll("owner-id", ImmutableSet.<String> of("137112412989", "099720109477"))//
+ .put("hypervisor", "xen")//
+ .put("state", "available")//
+ .put("image-type", "machine")//
+ .put("root-device-type", "ebs")//
+ .build()).ownedBy("137112412989", "099720109477"));
+ assertNotNull(ccResults);
+ assert (ccResults.size() >= 34) : ccResults;
}
}
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClientTest.java
index dd0f9cd..8945da2 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClientTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClientTest.java
@@ -100,7 +100,7 @@
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
- assertExceptionParserClassEquals(method, null);
+ assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(request);
}
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/BaseAWSEC2AsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/BaseAWSEC2AsyncClientTest.java
index add38e4..b555713 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/BaseAWSEC2AsyncClientTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/BaseAWSEC2AsyncClientTest.java
@@ -64,7 +64,7 @@
protected static class StubAWSEC2RestClientModule extends AWSEC2RestClientModule {
@Override
- protected String provideTimeStamp(DateService dateService, int expiration) {
+ protected String provideTimeStamp(DateService dateService) {
return "2009-11-08T15:54:08.897Z";
}
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java
index 74b2be2..63939d1 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java
@@ -47,7 +47,7 @@
import org.jclouds.scriptbuilder.statements.java.InstallJDK;
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
import org.jclouds.sshj.config.SshjSshClientModule;
-import org.testng.annotations.AfterTest;
+import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -163,12 +163,14 @@
public static final String PREFIX = System.getProperty("user.name") + "ec2";
- @AfterTest
- public void shutdown() {
+ @Override
+ @AfterClass(groups = { "integration", "live" })
+ protected void tearDownContext() {
if (group != null) {
client.getPlacementGroupServices().deletePlacementGroupInRegion(group.getRegion(), group.getName());
assert deletedTester.apply(group) : group;
}
+ super.tearDownContext();
}
@Override
diff --git a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/strategy/internal/ParallelMultipartUploadStrategy.java b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/strategy/internal/ParallelMultipartUploadStrategy.java
index bee6d98..e946df6 100644
--- a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/strategy/internal/ParallelMultipartUploadStrategy.java
+++ b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/strategy/internal/ParallelMultipartUploadStrategy.java
@@ -225,7 +225,7 @@
}
String eTag = client.completeMultipartUpload(container, key, uploadId, etags);
logger.debug(String.format("multipart upload of %s to container %s with uploadId %s" +
- " succeffully finished with %s retries", key, container, uploadId, errors.get()));
+ " successfully finished with %s retries", key, container, uploadId, errors.get()));
return eTag;
} catch (Exception ex) {
RuntimeException rtex = Throwables2.getFirstThrowableOfType(ex, RuntimeException.class);
diff --git a/providers/bluelock-vcloud-zone01/pom.xml b/providers/bluelock-vcloud-zone01/pom.xml
index 354294d..68786b0 100644
--- a/providers/bluelock-vcloud-zone01/pom.xml
+++ b/providers/bluelock-vcloud-zone01/pom.xml
@@ -39,10 +39,7 @@
<test.bluelock-vcloud-zone01.build-version>1.5.0.464915</test.bluelock-vcloud-zone01.build-version>
<test.bluelock-vcloud-zone01.identity>FIXME_IDENTITY</test.bluelock-vcloud-zone01.identity>
<test.bluelock-vcloud-zone01.credential>FIXME_CREDENTIAL</test.bluelock-vcloud-zone01.credential>
- <test.bluelock-vcloud-zone01.image-id />
- <test.bluelock-vcloud-zone01.image.login-user />
- <test.bluelock-vcloud-zone01.image.authenticate-sudo />
-
+ <test.bluelock-vcloud-zone01.template></test.bluelock-vcloud-zone01.template>
<jclouds.osgi.export>org.jclouds.bluelock.vcloud.zone01*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -115,9 +112,7 @@
<test.bluelock-vcloud-zone01.build-version>${test.bluelock-vcloud-zone01.build-version}</test.bluelock-vcloud-zone01.build-version>
<test.bluelock-vcloud-zone01.identity>${test.bluelock-vcloud-zone01.identity}</test.bluelock-vcloud-zone01.identity>
<test.bluelock-vcloud-zone01.credential>${test.bluelock-vcloud-zone01.credential}</test.bluelock-vcloud-zone01.credential>
- <test.bluelock-vcloud-zone01.image-id>${test.bluelock-vcloud-zone01.image-id}</test.bluelock-vcloud-zone01.image-id>
- <test.bluelock-vcloud-zone01.image.login-user>${test.bluelock-vcloud-zone01.image.login-user}</test.bluelock-vcloud-zone01.image.login-user>
- <test.bluelock-vcloud-zone01.image.authenticate-sudo>${test.bluelock-vcloud-zone01.image.authenticate-sudo}</test.bluelock-vcloud-zone01.image.authenticate-sudo>
+ <test.bluelock-vcloud-zone01.template>${test.bluelock-vcloud-zone01.template}</test.bluelock-vcloud-zone01.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/cloudservers-uk/pom.xml b/providers/cloudservers-uk/pom.xml
index dd0f694..771662c 100644
--- a/providers/cloudservers-uk/pom.xml
+++ b/providers/cloudservers-uk/pom.xml
@@ -36,13 +36,10 @@
<properties>
<test.cloudservers-uk.endpoint>https://lon.auth.api.rackspacecloud.com</test.cloudservers-uk.endpoint>
<test.cloudservers-uk.api-version>1.0</test.cloudservers-uk.api-version>
- <test.cloudservers-uk.build-version />
+ <test.cloudservers-uk.build-version></test.cloudservers-uk.build-version>
<test.cloudservers-uk.identity>${test.rackspace-uk.identity}</test.cloudservers-uk.identity>
<test.cloudservers-uk.credential>${test.rackspace-uk.credential}</test.cloudservers-uk.credential>
- <test.cloudservers-uk.image-id />
- <test.cloudservers-uk.image.login-user />
- <test.cloudservers-uk.image.authenticate-sudo />
-
+ <test.cloudservers-uk.template></test.cloudservers-uk.template>
<jclouds.osgi.export>org.jclouds.rackspace.cloudservers*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -120,9 +117,7 @@
<test.cloudservers-uk.build-version>${test.cloudservers-uk.build-version}</test.cloudservers-uk.build-version>
<test.cloudservers-uk.identity>${test.cloudservers-uk.identity}</test.cloudservers-uk.identity>
<test.cloudservers-uk.credential>${test.cloudservers-uk.credential}</test.cloudservers-uk.credential>
- <test.cloudservers-uk.image-id>${test.cloudservers-uk.image-id}</test.cloudservers-uk.image-id>
- <test.cloudservers-uk.image.login-user>${test.cloudservers-uk.image.login-user}</test.cloudservers-uk.image.login-user>
- <test.cloudservers-uk.image.authenticate-sudo>${test.cloudservers-uk.image.authenticate-sudo}</test.cloudservers-uk.image.authenticate-sudo>
+ <test.cloudservers-uk.template>${test.cloudservers-uk.template}</test.cloudservers-uk.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/cloudservers-us/pom.xml b/providers/cloudservers-us/pom.xml
index 7574d3f..70a3140 100644
--- a/providers/cloudservers-us/pom.xml
+++ b/providers/cloudservers-us/pom.xml
@@ -36,13 +36,10 @@
<properties>
<test.cloudservers-us.endpoint>https://auth.api.rackspacecloud.com</test.cloudservers-us.endpoint>
<test.cloudservers-us.api-version>1.0</test.cloudservers-us.api-version>
- <test.cloudservers-us.build-version />
+ <test.cloudservers-us.build-version></test.cloudservers-us.build-version>
<test.cloudservers-us.identity>${test.rackspace-us.identity}</test.cloudservers-us.identity>
<test.cloudservers-us.credential>${test.rackspace-us.credential}</test.cloudservers-us.credential>
- <test.cloudservers-us.image-id />
- <test.cloudservers-us.image.login-user />
- <test.cloudservers-us.image.authenticate-sudo />
-
+ <test.cloudservers-us.template></test.cloudservers-us.template>
<jclouds.osgi.export>org.jclouds.rackspace.cloudservers*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -121,9 +118,7 @@
<test.cloudservers-us.build-version>${test.cloudservers-us.build-version}</test.cloudservers-us.build-version>
<test.cloudservers-us.identity>${test.cloudservers-us.identity}</test.cloudservers-us.identity>
<test.cloudservers-us.credential>${test.cloudservers-us.credential}</test.cloudservers-us.credential>
- <test.cloudservers-us.image-id>${test.cloudservers-us.image-id}</test.cloudservers-us.image-id>
- <test.cloudservers-us.image.login-user>${test.cloudservers-us.image.login-user}</test.cloudservers-us.image.login-user>
- <test.cloudservers-us.image.authenticate-sudo>${test.cloudservers-us.image.authenticate-sudo}</test.cloudservers-us.image.authenticate-sudo>
+ <test.cloudservers-us.template>${test.cloudservers-us.template}</test.cloudservers-us.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/cloudsigma-lvs/pom.xml b/providers/cloudsigma-lvs/pom.xml
index ea087a9..46b4ff1 100644
--- a/providers/cloudsigma-lvs/pom.xml
+++ b/providers/cloudsigma-lvs/pom.xml
@@ -36,12 +36,10 @@
<properties>
<test.cloudsigma-lvs.endpoint>https://api.lvs.cloudsigma.com</test.cloudsigma-lvs.endpoint>
<test.cloudsigma-lvs.api-version>1.0</test.cloudsigma-lvs.api-version>
- <test.cloudsigma-lvs.build-version />
+ <test.cloudsigma-lvs.build-version></test.cloudsigma-lvs.build-version>
<test.cloudsigma-lvs.identity>FIXME</test.cloudsigma-lvs.identity>
<test.cloudsigma-lvs.credential>FIXME</test.cloudsigma-lvs.credential>
- <test.cloudsigma-lvs.image-id />
- <test.cloudsigma-lvs.image.login-user />
- <test.cloudsigma-lvs.image.authenticate-sudo />
+ <test.cloudsigma-lvs.template></test.cloudsigma-lvs.template>
<jclouds.osgi.export>org.jclouds.cloudsigma*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -114,9 +112,7 @@
<test.cloudsigma-lvs.build-version>${test.cloudsigma-lvs.build-version}</test.cloudsigma-lvs.build-version>
<test.cloudsigma-lvs.identity>${test.cloudsigma-lvs.identity}</test.cloudsigma-lvs.identity>
<test.cloudsigma-lvs.credential>${test.cloudsigma-lvs.credential}</test.cloudsigma-lvs.credential>
- <test.cloudsigma-lvs.image-id>${test.cloudsigma-lvs.image-id}</test.cloudsigma-lvs.image-id>
- <test.cloudsigma-lvs.image.login-user>${test.cloudsigma-lvs.image.login-user}</test.cloudsigma-lvs.image.login-user>
- <test.cloudsigma-lvs.image.authenticate-sudo>${test.cloudsigma-lvs.image.authenticate-sudo}</test.cloudsigma-lvs.image.authenticate-sudo>
+ <test.cloudsigma-lvs.template>${test.cloudsigma-lvs.template}</test.cloudsigma-lvs.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/cloudsigma-zrh/pom.xml b/providers/cloudsigma-zrh/pom.xml
index 1972503..a8d9b8d 100644
--- a/providers/cloudsigma-zrh/pom.xml
+++ b/providers/cloudsigma-zrh/pom.xml
@@ -36,13 +36,10 @@
<properties>
<test.cloudsigma-zrh.endpoint>https://api.zrh.cloudsigma.com</test.cloudsigma-zrh.endpoint>
<test.cloudsigma-zrh.api-version>1.0</test.cloudsigma-zrh.api-version>
- <test.cloudsigma-zrh.build-version />
+ <test.cloudsigma-zrh.build-version></test.cloudsigma-zrh.build-version>
<test.cloudsigma-zrh.identity>FIXME</test.cloudsigma-zrh.identity>
<test.cloudsigma-zrh.credential>FIXME</test.cloudsigma-zrh.credential>
- <test.cloudsigma-zrh.image-id />
- <test.cloudsigma-zrh.image.login-user />
- <test.cloudsigma-zrh.image.authenticate-sudo />
-
+ <test.cloudsigma-zrh.template></test.cloudsigma-zrh.template>
<jclouds.osgi.export>org.jclouds.cloudsigma*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -115,9 +112,7 @@
<test.cloudsigma-zrh.build-version>${test.cloudsigma-zrh.build-version}</test.cloudsigma-zrh.build-version>
<test.cloudsigma-zrh.identity>${test.cloudsigma-zrh.identity}</test.cloudsigma-zrh.identity>
<test.cloudsigma-zrh.credential>${test.cloudsigma-zrh.credential}</test.cloudsigma-zrh.credential>
- <test.cloudsigma-zrh.image-id>${test.cloudsigma-zrh.image-id}</test.cloudsigma-zrh.image-id>
- <test.cloudsigma-zrh.image.login-user>${test.cloudsigma-zrh.image.login-user}</test.cloudsigma-zrh.image.login-user>
- <test.cloudsigma-zrh.image.authenticate-sudo>${test.cloudsigma-zrh.image.authenticate-sudo}</test.cloudsigma-zrh.image.authenticate-sudo>
+ <test.cloudsigma-zrh.template>${test.cloudsigma-zrh.template}</test.cloudsigma-zrh.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/elastichosts-lax-p/pom.xml b/providers/elastichosts-lax-p/pom.xml
index f92bf52..ca0e7f5 100644
--- a/providers/elastichosts-lax-p/pom.xml
+++ b/providers/elastichosts-lax-p/pom.xml
@@ -36,10 +36,10 @@
<properties>
<test.elastichosts-lax-p.endpoint>https://api.lax-p.elastichosts.com</test.elastichosts-lax-p.endpoint>
<test.elastichosts-lax-p.api-version>2.0</test.elastichosts-lax-p.api-version>
- <test.elastichosts-lax-p.build-version />
+ <test.elastichosts-lax-p.build-version></test.elastichosts-lax-p.build-version>
<test.elastichosts-lax-p.identity>FIXME_IDENTITY</test.elastichosts-lax-p.identity>
<test.elastichosts-lax-p.credential>FIXME_CREDENTIAL</test.elastichosts-lax-p.credential>
- <test.elastichosts-lax-p.image-id />
+ <test.elastichosts-lax-p.template></test.elastichosts-lax-p.template>
<jclouds.osgi.export>org.jclouds.elastichosts*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -113,7 +113,7 @@
<test.elastichosts-lax-p.build-version>${test.elastichosts-lax-p.build-version}</test.elastichosts-lax-p.build-version>
<test.elastichosts-lax-p.identity>${test.elastichosts-lax-p.identity}</test.elastichosts-lax-p.identity>
<test.elastichosts-lax-p.credential>${test.elastichosts-lax-p.credential}</test.elastichosts-lax-p.credential>
- <test.elastichosts-lax-p.image-id>${test.elastichosts-lax-p.image-id}</test.elastichosts-lax-p.image-id>
+ <test.elastichosts-lax-p.template>${test.elastichosts-lax-p.template}</test.elastichosts-lax-p.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/elastichosts-lon-b/pom.xml b/providers/elastichosts-lon-b/pom.xml
index c925e54..6acef22 100644
--- a/providers/elastichosts-lon-b/pom.xml
+++ b/providers/elastichosts-lon-b/pom.xml
@@ -36,10 +36,10 @@
<properties>
<test.elastichosts-lon-b.endpoint>https://api.lon-b.elastichosts.com</test.elastichosts-lon-b.endpoint>
<test.elastichosts-lon-b.api-version>2.0</test.elastichosts-lon-b.api-version>
- <test.elastichosts-lon-b.build-version />
+ <test.elastichosts-lon-b.build-version></test.elastichosts-lon-b.build-version>
<test.elastichosts-lon-b.identity>FIXME_IDENTITY</test.elastichosts-lon-b.identity>
<test.elastichosts-lon-b.credential>FIXME_CREDENTIAL</test.elastichosts-lon-b.credential>
- <test.elastichosts-lon-b.image-id />
+ <test.elastichosts-lon-b.template></test.elastichosts-lon-b.template>
<jclouds.osgi.export>org.jclouds.elastichosts*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -113,7 +113,7 @@
<test.elastichosts-lon-b.build-version>${test.elastichosts-lon-b.build-version}</test.elastichosts-lon-b.build-version>
<test.elastichosts-lon-b.identity>${test.elastichosts-lon-b.identity}</test.elastichosts-lon-b.identity>
<test.elastichosts-lon-b.credential>${test.elastichosts-lon-b.credential}</test.elastichosts-lon-b.credential>
- <test.elastichosts-lon-b.image-id>${test.elastichosts-lon-b.image-id}</test.elastichosts-lon-b.image-id>
+ <test.elastichosts-lon-b.template>${test.elastichosts-lon-b.template}</test.elastichosts-lon-b.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/elastichosts-lon-p/pom.xml b/providers/elastichosts-lon-p/pom.xml
index 618a00b..4bc74dd 100644
--- a/providers/elastichosts-lon-p/pom.xml
+++ b/providers/elastichosts-lon-p/pom.xml
@@ -36,10 +36,10 @@
<properties>
<test.elastichosts-lon-p.endpoint>https://api.lon-p.elastichosts.com</test.elastichosts-lon-p.endpoint>
<test.elastichosts-lon-p.api-version>2.0</test.elastichosts-lon-p.api-version>
- <test.elastichosts-lon-p.build-version />
+ <test.elastichosts-lon-p.build-version></test.elastichosts-lon-p.build-version>
<test.elastichosts-lon-p.identity>FIXME_IDENTITY</test.elastichosts-lon-p.identity>
<test.elastichosts-lon-p.credential>FIXME_CREDENTIAL</test.elastichosts-lon-p.credential>
- <test.elastichosts-lon-p.image-id />
+ <test.elastichosts-lon-p.template></test.elastichosts-lon-p.template>
<jclouds.osgi.export>org.jclouds.elastichosts*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -113,7 +113,7 @@
<test.elastichosts-lon-p.build-version>${test.elastichosts-lon-p.build-version}</test.elastichosts-lon-p.build-version>
<test.elastichosts-lon-p.identity>${test.elastichosts-lon-p.identity}</test.elastichosts-lon-p.identity>
<test.elastichosts-lon-p.credential>${test.elastichosts-lon-p.credential}</test.elastichosts-lon-p.credential>
- <test.elastichosts-lon-p.image-id>${test.elastichosts-lon-p.image-id}</test.elastichosts-lon-p.image-id>
+ <test.elastichosts-lon-p.template>${test.elastichosts-lon-p.template}</test.elastichosts-lon-p.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/elastichosts-sat-p/pom.xml b/providers/elastichosts-sat-p/pom.xml
index f918362..6061d89 100644
--- a/providers/elastichosts-sat-p/pom.xml
+++ b/providers/elastichosts-sat-p/pom.xml
@@ -36,10 +36,10 @@
<properties>
<test.elastichosts-sat-p.endpoint>https://api.sat-p.elastichosts.com</test.elastichosts-sat-p.endpoint>
<test.elastichosts-sat-p.api-version>2.0</test.elastichosts-sat-p.api-version>
- <test.elastichosts-sat-p.build-version />
+ <test.elastichosts-sat-p.build-version></test.elastichosts-sat-p.build-version>
<test.elastichosts-sat-p.identity>FIXME_IDENTITY</test.elastichosts-sat-p.identity>
<test.elastichosts-sat-p.credential>FIXME_CREDENTIAL</test.elastichosts-sat-p.credential>
- <test.elastichosts-sat-p.image-id />
+ <test.elastichosts-sat-p.template></test.elastichosts-sat-p.template>
<jclouds.osgi.export>org.jclouds.elastichosts*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -113,7 +113,7 @@
<test.elastichosts-sat-p.build-version>${test.elastichosts-sat-p.build-version}</test.elastichosts-sat-p.build-version>
<test.elastichosts-sat-p.identity>${test.elastichosts-sat-p.identity}</test.elastichosts-sat-p.identity>
<test.elastichosts-sat-p.credential>${test.elastichosts-sat-p.credential}</test.elastichosts-sat-p.credential>
- <test.elastichosts-sat-p.image-id>${test.elastichosts-sat-p.image-id}</test.elastichosts-sat-p.image-id>
+ <test.elastichosts-sat-p.template>${test.elastichosts-sat-p.template}</test.elastichosts-sat-p.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/elastichosts-tor-p/pom.xml b/providers/elastichosts-tor-p/pom.xml
index 2fad95b..29e566c 100644
--- a/providers/elastichosts-tor-p/pom.xml
+++ b/providers/elastichosts-tor-p/pom.xml
@@ -36,10 +36,10 @@
<properties>
<test.elastichosts-tor-p.endpoint>https://api.tor-p.elastichosts.com</test.elastichosts-tor-p.endpoint>
<test.elastichosts-tor-p.api-version>2.0</test.elastichosts-tor-p.api-version>
- <test.elastichosts-tor-p.build-version />
+ <test.elastichosts-tor-p.build-version></test.elastichosts-tor-p.build-version>
<test.elastichosts-tor-p.identity>FIXME_IDENTITY</test.elastichosts-tor-p.identity>
<test.elastichosts-tor-p.credential>FIXME_CREDENTIAL</test.elastichosts-tor-p.credential>
- <test.elastichosts-tor-p.image-id />
+ <test.elastichosts-tor-p.template></test.elastichosts-tor-p.template>
<jclouds.osgi.export>org.jclouds.elastichosts*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -113,7 +113,7 @@
<test.elastichosts-tor-p.build-version>${test.elastichosts-tor-p.build-version}</test.elastichosts-tor-p.build-version>
<test.elastichosts-tor-p.identity>${test.elastichosts-tor-p.identity}</test.elastichosts-tor-p.identity>
<test.elastichosts-tor-p.credential>${test.elastichosts-tor-p.credential}</test.elastichosts-tor-p.credential>
- <test.elastichosts-tor-p.image-id>${test.elastichosts-tor-p.image-id}</test.elastichosts-tor-p.image-id>
+ <test.elastichosts-tor-p.template>${test.elastichosts-tor-p.template}</test.elastichosts-tor-p.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/eucalyptus-partnercloud-ec2/pom.xml b/providers/eucalyptus-partnercloud-ec2/pom.xml
index b75965e..bd9374e 100644
--- a/providers/eucalyptus-partnercloud-ec2/pom.xml
+++ b/providers/eucalyptus-partnercloud-ec2/pom.xml
@@ -36,12 +36,11 @@
<properties>
<test.eucalyptus-partnercloud-ec2.endpoint>http://partnercloud.eucalyptus.com:8773/services/Eucalyptus</test.eucalyptus-partnercloud-ec2.endpoint>
<test.eucalyptus-partnercloud-ec2.api-version>2010-06-15</test.eucalyptus-partnercloud-ec2.api-version>
- <test.eucalyptus-partnercloud-ec2.build-version />
+ <test.eucalyptus-partnercloud-ec2.build-version></test.eucalyptus-partnercloud-ec2.build-version>
<test.eucalyptus-partnercloud-ec2.identity>FIXME_IDENTITY</test.eucalyptus-partnercloud-ec2.identity>
<test.eucalyptus-partnercloud-ec2.credential>FIXME_CREDENTIAL</test.eucalyptus-partnercloud-ec2.credential>
- <test.eucalyptus-partnercloud-ec2.image-id />
- <!-- corresponds to image manifest and also virt + "-cluster" zone -->
- <test.eucalyptus-partnercloud-ec2.virtualization-type>kvm</test.eucalyptus-partnercloud-ec2.virtualization-type>
+ <test.eucalyptus-partnercloud-ec2.template></test.eucalyptus-partnercloud-ec2.template>
+ <test.eucalyptus-partnercloud-ec2.ebs-template></test.eucalyptus-partnercloud-ec2.ebs-template>
<jclouds.osgi.export>org.jclouds.epc*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -128,8 +127,8 @@
<test.eucalyptus-partnercloud-ec2.build-version>${test.eucalyptus-partnercloud-ec2.build-version}</test.eucalyptus-partnercloud-ec2.build-version>
<test.eucalyptus-partnercloud-ec2.identity>${test.eucalyptus-partnercloud-ec2.identity}</test.eucalyptus-partnercloud-ec2.identity>
<test.eucalyptus-partnercloud-ec2.credential>${test.eucalyptus-partnercloud-ec2.credential}</test.eucalyptus-partnercloud-ec2.credential>
- <test.eucalyptus-partnercloud-ec2.image-id>${test.eucalyptus-partnercloud-ec2.image-id}</test.eucalyptus-partnercloud-ec2.image-id>
- <test.eucalyptus-partnercloud-ec2.virtualization-type>${test.eucalyptus-partnercloud-ec2.virtualization-type}</test.eucalyptus-partnercloud-ec2.virtualization-type>
+ <test.eucalyptus-partnercloud-ec2.template>${test.eucalyptus-partnercloud-ec2.template}</test.eucalyptus-partnercloud-ec2.template>
+ <test.eucalyptus-partnercloud-ec2.ebs-template>${test.eucalyptus-partnercloud-ec2.ebs-template}</test.eucalyptus-partnercloud-ec2.ebs-template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/eucalyptus-partnercloud-ec2/src/main/java/org/jclouds/epc/EucalyptusPartnerCloudEC2ProviderMetadata.java b/providers/eucalyptus-partnercloud-ec2/src/main/java/org/jclouds/epc/EucalyptusPartnerCloudEC2ProviderMetadata.java
index 0ff2825..7687626 100644
--- a/providers/eucalyptus-partnercloud-ec2/src/main/java/org/jclouds/epc/EucalyptusPartnerCloudEC2ProviderMetadata.java
+++ b/providers/eucalyptus-partnercloud-ec2/src/main/java/org/jclouds/epc/EucalyptusPartnerCloudEC2ProviderMetadata.java
@@ -18,7 +18,6 @@
*/
package org.jclouds.epc;
-import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
@@ -65,10 +64,8 @@
public static Properties defaultProperties() {
Properties properties = new Properties();
- properties.setProperty(PROPERTY_REGIONS, "Eucalyptus");
- properties.setProperty(PROPERTY_REGION + ".Eucalyptus." + ISO3166_CODES, "US-CA");
- properties.setProperty("eucalyptus-partnercloud-ec2.virtualization-type", "kvm");
- properties.setProperty(TEMPLATE, "osFamily=UBUNTU,locationId=${eucalyptus-partnercloud-ec2.virtualization-type}-cluster");
+ properties.setProperty(PROPERTY_REGIONS, "eucalyptus");
+ properties.setProperty(PROPERTY_REGION + ".eucalyptus." + ISO3166_CODES, "US-CA");
return properties;
}
@@ -82,7 +79,7 @@
.defaultModules(ImmutableSet.<Class<? extends Module>>of(EC2RestClientModule.class, EC2ResolveImagesModule.class, EucalyptusPartnerCloudComputeServiceContextModule.class))
.build())
.homepage(URI.create("http://www.eucalyptus.com/partners"))
- .console(URI.create("https://partnercloud.eucalyptus.com:8443"))
+ .console(URI.create("https://eucalyptus.partner.eucalyptus.com"))
.linkedServices("eucalyptus-partnercloud-ec2", "eucalyptus-partnercloud-s3")
.iso3166Codes("US-CA")
.endpoint("http://partnercloud.eucalyptus.com:8773/services/Eucalyptus")
diff --git a/providers/eucalyptus-partnercloud-ec2/src/test/java/org/jclouds/epc/compute/EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest.java b/providers/eucalyptus-partnercloud-ec2/src/test/java/org/jclouds/epc/compute/EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest.java
index 80607c2..242b9e4 100644
--- a/providers/eucalyptus-partnercloud-ec2/src/test/java/org/jclouds/epc/compute/EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest.java
+++ b/providers/eucalyptus-partnercloud-ec2/src/test/java/org/jclouds/epc/compute/EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest.java
@@ -18,8 +18,6 @@
*/
package org.jclouds.epc.compute;
-import java.util.Properties;
-
import org.jclouds.eucalyptus.compute.EucalyptusComputeServiceLiveTest;
import org.testng.annotations.Test;
@@ -35,14 +33,4 @@
// security groups must be <30 characters
group = "eu";
}
-
- @Override
- protected Properties setupProperties() {
- Properties overrides = super.setupProperties();
- if (System.getProperties().containsKey("test.eucalyptus-partnercloud-ec2.virtualization-type"))
- overrides.setProperty("eucalyptus-partnercloud-ec2.virtualization-type", System
- .getProperty("test.eucalyptus-partnercloud-ec2.virtualization-type"));
- return overrides;
- }
-
}
diff --git a/providers/eucalyptus-partnercloud-s3/pom.xml b/providers/eucalyptus-partnercloud-s3/pom.xml
index da8bb6b..00c0e2c 100644
--- a/providers/eucalyptus-partnercloud-s3/pom.xml
+++ b/providers/eucalyptus-partnercloud-s3/pom.xml
@@ -34,7 +34,7 @@
<packaging>bundle</packaging>
<properties>
- <test.eucalyptus-partnercloud-s3.endpoint>http://partnercloud.eucalyptus.com:8773/services/Walrus</test.eucalyptus-partnercloud-s3.endpoint>
+ <test.eucalyptus-partnercloud-s3.endpoint>http://walrus.partner.eucalyptus.com:8773/services/Walrus</test.eucalyptus-partnercloud-s3.endpoint>
<test.eucalyptus-partnercloud-s3.api-version>2006-03-01</test.eucalyptus-partnercloud-s3.api-version>
<test.eucalyptus-partnercloud-s3.build-version />
<test.eucalyptus-partnercloud-s3.identity>FIXME_IDENTITY</test.eucalyptus-partnercloud-s3.identity>
diff --git a/providers/eucalyptus-partnercloud-s3/src/main/java/org/jclouds/epc/EucalyptusPartnerCloudS3ProviderMetadata.java b/providers/eucalyptus-partnercloud-s3/src/main/java/org/jclouds/epc/EucalyptusPartnerCloudS3ProviderMetadata.java
index 7be125d..f28e71f 100644
--- a/providers/eucalyptus-partnercloud-s3/src/main/java/org/jclouds/epc/EucalyptusPartnerCloudS3ProviderMetadata.java
+++ b/providers/eucalyptus-partnercloud-s3/src/main/java/org/jclouds/epc/EucalyptusPartnerCloudS3ProviderMetadata.java
@@ -60,10 +60,10 @@
public static Properties defaultProperties() {
Properties properties = new Properties();
- properties.setProperty(PROPERTY_REGIONS, "Walrus");
+ properties.setProperty(PROPERTY_REGIONS, "walrus");
properties.setProperty(PROPERTY_ISO3166_CODES, "US-CA");
- properties.setProperty(PROPERTY_REGION + ".Walrus." + ISO3166_CODES, "US-CA");
- properties.setProperty(PROPERTY_REGION + "." + "Walrus" + "." + ENDPOINT, "http://partnercloud.eucalyptus.com:8773/services/Walrus");
+ properties.setProperty(PROPERTY_REGION + ".walrus." + ISO3166_CODES, "US-CA");
+ properties.setProperty(PROPERTY_REGION + "." + "walrus" + "." + ENDPOINT, "http://walrus.partner.eucalyptus.com:8773/services/Walrus");
return properties;
}
@@ -74,10 +74,10 @@
.name("Eucalyptus Partner Cloud (S3)")
.apiMetadata(new WalrusApiMetadata())
.homepage(URI.create("http://www.eucalyptus.com/partners"))
- .console(URI.create("https://partnercloud.eucalyptus.com:8443"))
+ .console(URI.create("https://walrus.partner.eucalyptus.com"))
.linkedServices("eucalyptus-partnercloud-ec2", "eucalyptus-partnercloud-s3")
.iso3166Codes("US-CA")
- .endpoint("http://partnercloud.eucalyptus.com:8773/services/Walrus")
+ .endpoint("http://walrus.partner.eucalyptus.com:8773/services/Walrus")
.defaultProperties(EucalyptusPartnerCloudS3ProviderMetadata.defaultProperties());
}
diff --git a/providers/eucalyptus-partnercloud-s3/src/test/java/org/jclouds/epc/EucalyptusPartnerCloudWalrusClientLiveTest.java b/providers/eucalyptus-partnercloud-s3/src/test/java/org/jclouds/epc/EucalyptusPartnerCloudWalrusClientLiveTest.java
index 812d259..442e4a9 100644
--- a/providers/eucalyptus-partnercloud-s3/src/test/java/org/jclouds/epc/EucalyptusPartnerCloudWalrusClientLiveTest.java
+++ b/providers/eucalyptus-partnercloud-s3/src/test/java/org/jclouds/epc/EucalyptusPartnerCloudWalrusClientLiveTest.java
@@ -26,7 +26,9 @@
*
* @author Adrian Cole
*/
-@Test(groups = "live", sequential = true, testName = "EucalyptusPartnerCloudWalrusClientLiveTest")
+@Test(groups = "live", singleThreaded = true, testName = "EucalyptusPartnerCloudWalrusClientLiveTest")
public class EucalyptusPartnerCloudWalrusClientLiveTest extends WalrusClientLiveTest {
-
+ public EucalyptusPartnerCloudWalrusClientLiveTest() {
+ provider = "eucalyptus-partnercloud-s3";
+ }
}
diff --git a/providers/go2cloud-jhb1/pom.xml b/providers/go2cloud-jhb1/pom.xml
index 76e3b4c..81e9026 100644
--- a/providers/go2cloud-jhb1/pom.xml
+++ b/providers/go2cloud-jhb1/pom.xml
@@ -36,10 +36,10 @@
<properties>
<test.go2cloud-jhb1.endpoint>http://api.jhb1.go2cloud.co.za</test.go2cloud-jhb1.endpoint>
<test.go2cloud-jhb1.api-version>2.0</test.go2cloud-jhb1.api-version>
- <test.go2cloud-jhb1.build-version />
+ <test.go2cloud-jhb1.build-version></test.go2cloud-jhb1.build-version>
<test.go2cloud-jhb1.identity>FIXME_IDENTITY</test.go2cloud-jhb1.identity>
<test.go2cloud-jhb1.credential>FIXME_CREDENTIAL</test.go2cloud-jhb1.credential>
- <test.go2cloud-jhb1.image-id />
+ <test.go2cloud-jhb1.template></test.go2cloud-jhb1.template>
<jclouds.osgi.export>org.jclouds.go2cloud*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -113,7 +113,7 @@
<test.go2cloud-jhb1.build-version>${test.go2cloud-jhb1.build-version}</test.go2cloud-jhb1.build-version>
<test.go2cloud-jhb1.identity>${test.go2cloud-jhb1.identity}</test.go2cloud-jhb1.identity>
<test.go2cloud-jhb1.credential>${test.go2cloud-jhb1.credential}</test.go2cloud-jhb1.credential>
- <test.go2cloud-jhb1.image-id>${test.go2cloud-jhb1.image-id}</test.go2cloud-jhb1.image-id>
+ <test.go2cloud-jhb1.template>${test.go2cloud-jhb1.template}</test.go2cloud-jhb1.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/gogrid/pom.xml b/providers/gogrid/pom.xml
index b92f143..b42e13c 100644
--- a/providers/gogrid/pom.xml
+++ b/providers/gogrid/pom.xml
@@ -36,10 +36,10 @@
<properties>
<test.gogrid.endpoint>https://api.gogrid.com/api</test.gogrid.endpoint>
<test.gogrid.api-version>1.5</test.gogrid.api-version>
- <test.gogrid.build-version />
+ <test.gogrid.build-version></test.gogrid.build-version>
<test.gogrid.identity>FIXME</test.gogrid.identity>
<test.gogrid.credential>FIXME</test.gogrid.credential>
- <test.gogrid.image-id />
+ <test.gogrid.template></test.gogrid.template>
<jclouds.osgi.export>org.jclouds.gogrid*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -106,7 +106,7 @@
<test.gogrid.build-version>${test.gogrid.build-version}</test.gogrid.build-version>
<test.gogrid.identity>${test.gogrid.identity}</test.gogrid.identity>
<test.gogrid.credential>${test.gogrid.credential}</test.gogrid.credential>
- <test.gogrid.image-id>${test.gogrid.image-id}</test.gogrid.image-id>
+ <test.gogrid.template>${test.gogrid.template}</test.gogrid.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java b/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java
index 8db55df..39f0d2d 100644
--- a/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java
+++ b/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java
@@ -211,7 +211,7 @@
Job latestJobFetched = Iterables.getOnlyElement(client.getJobServices().getJobsById(latestJobId));
- assert latestJob.equals(latestJobFetched) : "Job and its reprentation found by ID don't match";
+ assert latestJob.equals(latestJobFetched) : "Job and its representation found by ID don't match";
long[] idsOfAllJobs = new long[jobs.size()];
int i = 0;
diff --git a/providers/greenhousedata-element-vcloud/pom.xml b/providers/greenhousedata-element-vcloud/pom.xml
index 25ef92a..640bcf0 100644
--- a/providers/greenhousedata-element-vcloud/pom.xml
+++ b/providers/greenhousedata-element-vcloud/pom.xml
@@ -39,10 +39,7 @@
<test.greenhousedata-element-vcloud.build-version>1.5.0.464915</test.greenhousedata-element-vcloud.build-version>
<test.greenhousedata-element-vcloud.identity>FIXME_IDENTITY</test.greenhousedata-element-vcloud.identity>
<test.greenhousedata-element-vcloud.credential>FIXME_CREDENTIAL</test.greenhousedata-element-vcloud.credential>
- <test.greenhousedata-element-vcloud.image-id />
- <test.greenhousedata-element-vcloud.image.login-user />
- <test.greenhousedata-element-vcloud.image.authenticate-sudo />
-
+ <test.greenhousedata-element-vcloud.template></test.greenhousedata-element-vcloud.template>
<jclouds.osgi.export>org.jclouds.greenhousedata.element.vcloud*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -115,9 +112,7 @@
<test.greenhousedata-element-vcloud.build-version>${test.greenhousedata-element-vcloud.build-version}</test.greenhousedata-element-vcloud.build-version>
<test.greenhousedata-element-vcloud.identity>${test.greenhousedata-element-vcloud.identity}</test.greenhousedata-element-vcloud.identity>
<test.greenhousedata-element-vcloud.credential>${test.greenhousedata-element-vcloud.credential}</test.greenhousedata-element-vcloud.credential>
- <test.greenhousedata-element-vcloud.image-id>${test.greenhousedata-element-vcloud.image-id}</test.greenhousedata-element-vcloud.image-id>
- <test.greenhousedata-element-vcloud.image.login-user>${test.greenhousedata-element-vcloud.image.login-user}</test.greenhousedata-element-vcloud.image.login-user>
- <test.greenhousedata-element-vcloud.image.authenticate-sudo>${test.greenhousedata-element-vcloud.image.authenticate-sudo}</test.greenhousedata-element-vcloud.image.authenticate-sudo>
+ <test.greenhousedata-element-vcloud.template>${test.greenhousedata-element-vcloud.template}</test.greenhousedata-element-vcloud.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/hpcloud-compute/pom.xml b/providers/hpcloud-compute/pom.xml
index 68e0127..aaa4bfd 100644
--- a/providers/hpcloud-compute/pom.xml
+++ b/providers/hpcloud-compute/pom.xml
@@ -36,13 +36,10 @@
<properties>
<test.hpcloud-compute.endpoint>https://region-a.geo-1.identity.hpcloudsvc.com:35357</test.hpcloud-compute.endpoint>
<test.hpcloud-compute.api-version>1.1</test.hpcloud-compute.api-version>
- <test.hpcloud-compute.build-version />
+ <test.hpcloud-compute.build-version></test.hpcloud-compute.build-version>
<test.hpcloud-compute.identity>FIXME_IDENTITY</test.hpcloud-compute.identity>
<test.hpcloud-compute.credential>FIXME_CREDENTIAL</test.hpcloud-compute.credential>
- <test.hpcloud-compute.image-id />
- <test.hpcloud-compute.image.login-user />
- <test.hpcloud-compute.image.authenticate-sudo />
-
+ <test.hpcloud-compute.template></test.hpcloud-compute.template>
<jclouds.osgi.export>org.jclouds.hpcloud.compute*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -122,9 +119,7 @@
<test.hpcloud-compute.build-version>${test.hpcloud-compute.build-version}</test.hpcloud-compute.build-version>
<test.hpcloud-compute.identity>${test.hpcloud-compute.identity}</test.hpcloud-compute.identity>
<test.hpcloud-compute.credential>${test.hpcloud-compute.credential}</test.hpcloud-compute.credential>
- <test.hpcloud-compute.image-id>${test.hpcloud-compute.image-id}</test.hpcloud-compute.image-id>
- <test.hpcloud-compute.image.login-user>${test.hpcloud-compute.image.login-user}</test.hpcloud-compute.image.login-user>
- <test.hpcloud-compute.image.authenticate-sudo>${test.hpcloud-compute.image.authenticate-sudo}</test.hpcloud-compute.image.authenticate-sudo>
+ <test.hpcloud-compute.template>${test.hpcloud-compute.template}</test.hpcloud-compute.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/ninefold-compute/pom.xml b/providers/ninefold-compute/pom.xml
index 7874950..17ab38c 100644
--- a/providers/ninefold-compute/pom.xml
+++ b/providers/ninefold-compute/pom.xml
@@ -39,10 +39,7 @@
<test.ninefold-compute.build-version />
<test.ninefold-compute.identity>FIXME_IDENTITY</test.ninefold-compute.identity>
<test.ninefold-compute.credential>FIXME_CREDENTIAL</test.ninefold-compute.credential>
- <test.ninefold-compute.image-id>1215</test.ninefold-compute.image-id>
- <test.ninefold-compute.image.login-user>user:Password01</test.ninefold-compute.image.login-user>
- <test.ninefold-compute.image.authenticate-sudo>true</test.ninefold-compute.image.authenticate-sudo>
-
+ <test.ninefold-compute.template>imageId=1215,loginUser=user:Password01,authenticateSudo=true</test.ninefold-compute.template>
<jclouds.osgi.export>org.jclouds.ninefold.compute*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -116,9 +113,7 @@
<test.ninefold-compute.build-version>${test.ninefold-compute.build-version}</test.ninefold-compute.build-version>
<test.ninefold-compute.identity>${test.ninefold-compute.identity}</test.ninefold-compute.identity>
<test.ninefold-compute.credential>${test.ninefold-compute.credential}</test.ninefold-compute.credential>
- <test.ninefold-compute.image-id>${test.ninefold-compute.image-id}</test.ninefold-compute.image-id>
- <test.ninefold-compute.image.login-user>${test.ninefold-compute.image.login-user}</test.ninefold-compute.image.login-user>
- <test.ninefold-compute.image.authenticate-sudo>${test.ninefold-compute.image.authenticate-sudo}</test.ninefold-compute.image.authenticate-sudo>
+ <test.ninefold-compute.template>${test.ninefold-compute.template}</test.ninefold-compute.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/ninefold-compute/src/test/java/org/jclouds/ninefold/compute/compute/NinefoldComputeTemplateBuilderLiveTest.java b/providers/ninefold-compute/src/test/java/org/jclouds/ninefold/compute/compute/NinefoldComputeTemplateBuilderLiveTest.java
index fcdb275..912727f 100644
--- a/providers/ninefold-compute/src/test/java/org/jclouds/ninefold/compute/compute/NinefoldComputeTemplateBuilderLiveTest.java
+++ b/providers/ninefold-compute/src/test/java/org/jclouds/ninefold/compute/compute/NinefoldComputeTemplateBuilderLiveTest.java
@@ -71,14 +71,14 @@
@Test
public void testDefaultTemplateBuilder() throws IOException {
Template defaultTemplate = this.view.getComputeService().templateBuilder().build();
- if (imageId == null) {
+ if (template == null) {
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getLocation().getId(), "1");
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
} else {
- assertEquals(defaultTemplate.getImage(), this.view.getComputeService().templateBuilder().imageId(imageId)
+ assertEquals(defaultTemplate.getImage(), this.view.getComputeService().templateBuilder().from(template)
.build().getImage());
}
}
diff --git a/providers/openhosting-east1/pom.xml b/providers/openhosting-east1/pom.xml
index bc6e40a..7e87b05 100644
--- a/providers/openhosting-east1/pom.xml
+++ b/providers/openhosting-east1/pom.xml
@@ -36,10 +36,10 @@
<properties>
<test.openhosting-east1.endpoint>https://api.east1.openhosting.com</test.openhosting-east1.endpoint>
<test.openhosting-east1.api-version>2.0</test.openhosting-east1.api-version>
- <test.openhosting-east1.build-version />
+ <test.openhosting-east1.build-version></test.openhosting-east1.build-version>
<test.openhosting-east1.identity>FIXME_IDENTITY</test.openhosting-east1.identity>
<test.openhosting-east1.credential>FIXME_CREDENTIAL</test.openhosting-east1.credential>
- <test.openhosting-east1.image-id />
+ <test.openhosting-east1.template></test.openhosting-east1.template>
<jclouds.osgi.export>org.jclouds.openhosting*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -113,7 +113,7 @@
<test.openhosting-east1.build-version>${test.openhosting-east1.build-version}</test.openhosting-east1.build-version>
<test.openhosting-east1.identity>${test.openhosting-east1.identity}</test.openhosting-east1.identity>
<test.openhosting-east1.credential>${test.openhosting-east1.credential}</test.openhosting-east1.credential>
- <test.openhosting-east1.image-id>${test.openhosting-east1.image-id}</test.openhosting-east1.image-id>
+ <test.openhosting-east1.template>${test.openhosting-east1.template}</test.openhosting-east1.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/rimuhosting/pom.xml b/providers/rimuhosting/pom.xml
index c3ca7c2..7ecbb09 100644
--- a/providers/rimuhosting/pom.xml
+++ b/providers/rimuhosting/pom.xml
@@ -36,9 +36,9 @@
<properties>
<test.rimuhosting.endpoint>https://api.rimuhosting.com/r</test.rimuhosting.endpoint>
<test.rimuhosting.api-version>1.0</test.rimuhosting.api-version>
- <test.rimuhosting.build-version />
+ <test.rimuhosting.build-version></test.rimuhosting.build-version>
<test.rimuhosting.identity>FIXME</test.rimuhosting.identity>
- <test.rimuhosting.image-id />
+ <test.rimuhosting.template></test.rimuhosting.template>
<jclouds.osgi.export>org.jclouds.rimuhosting.miro*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -113,7 +113,7 @@
<test.rimuhosting.api-version>${test.rimuhosting.api-version}</test.rimuhosting.api-version>
<test.rimuhosting.build-version>${test.rimuhosting.build-version}</test.rimuhosting.build-version>
<test.rimuhosting.identity>${test.rimuhosting.identity}</test.rimuhosting.identity>
- <test.rimuhosting.image-id>${test.rimuhosting.image-id}</test.rimuhosting.image-id>
+ <test.rimuhosting.template>${test.rimuhosting.template}</test.rimuhosting.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/data/NewServerData.java b/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/data/NewServerData.java
index 762cdb8..0d8a155 100644
--- a/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/data/NewServerData.java
+++ b/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/data/NewServerData.java
@@ -107,7 +107,7 @@
* stops them all fitting in 'neatly' (that's not a problem on the bigger-, non-low
* contention-plans.
*/
- @SerializedName("vps_paramters")
+ @SerializedName("vps_parameters")
private ServerParameters serverParameters;
@SerializedName("meta_data")
diff --git a/providers/serverlove-z1-man/pom.xml b/providers/serverlove-z1-man/pom.xml
index 3bd52cd..4b0ef8a 100644
--- a/providers/serverlove-z1-man/pom.xml
+++ b/providers/serverlove-z1-man/pom.xml
@@ -36,10 +36,10 @@
<properties>
<test.serverlove-z1-man.endpoint>https://api.z1-man.serverlove.com</test.serverlove-z1-man.endpoint>
<test.serverlove-z1-man.api-version>1.0</test.serverlove-z1-man.api-version>
- <test.serverlove-z1-man.build-version />
+ <test.serverlove-z1-man.build-version></test.serverlove-z1-man.build-version>
<test.serverlove-z1-man.identity>FIXME_IDENTITY</test.serverlove-z1-man.identity>
<test.serverlove-z1-man.credential>FIXME_CREDENTIAL</test.serverlove-z1-man.credential>
- <test.serverlove-z1-man.image-id />
+ <test.serverlove-z1-man.template></test.serverlove-z1-man.template>
<jclouds.osgi.export>org.jclouds.serverlove*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -112,7 +112,7 @@
<test.serverlove-z1-man.build-version>${test.serverlove-z1-man.build-version}</test.serverlove-z1-man.build-version>
<test.serverlove-z1-man.identity>${test.serverlove-z1-man.identity}</test.serverlove-z1-man.identity>
<test.serverlove-z1-man.credential>${test.serverlove-z1-man.credential}</test.serverlove-z1-man.credential>
- <test.serverlove-z1-man.image-id>${test.serverlove-z1-man.image-id}</test.serverlove-z1-man.image-id>
+ <test.serverlove-z1-man.template>${test.serverlove-z1-man.template}</test.serverlove-z1-man.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/skalicloud-sdg-my/pom.xml b/providers/skalicloud-sdg-my/pom.xml
index d0aa2af..e1b38fa 100644
--- a/providers/skalicloud-sdg-my/pom.xml
+++ b/providers/skalicloud-sdg-my/pom.xml
@@ -36,10 +36,10 @@
<properties>
<test.skalicloud-sdg-my.endpoint>https://api.sdg-my.skalicloud.com</test.skalicloud-sdg-my.endpoint>
<test.skalicloud-sdg-my.api-version>1.0</test.skalicloud-sdg-my.api-version>
- <test.skalicloud-sdg-my.build-version />
+ <test.skalicloud-sdg-my.build-version></test.skalicloud-sdg-my.build-version>
<test.skalicloud-sdg-my.identity>FIXME_IDENTITY</test.skalicloud-sdg-my.identity>
<test.skalicloud-sdg-my.credential>FIXME_CREDENTIAL</test.skalicloud-sdg-my.credential>
- <test.skalicloud-sdg-my.image-id />
+ <test.skalicloud-sdg-my.template></test.skalicloud-sdg-my.template>
<jclouds.osgi.export>org.jclouds.skalicloud*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -113,7 +113,7 @@
<test.skalicloud-sdg-my.build-version>${test.skalicloud-sdg-my.build-version}</test.skalicloud-sdg-my.build-version>
<test.skalicloud-sdg-my.identity>${test.skalicloud-sdg-my.identity}</test.skalicloud-sdg-my.identity>
<test.skalicloud-sdg-my.credential>${test.skalicloud-sdg-my.credential}</test.skalicloud-sdg-my.credential>
- <test.skalicloud-sdg-my.image-id>${test.skalicloud-sdg-my.image-id}</test.skalicloud-sdg-my.image-id>
+ <test.skalicloud-sdg-my.template>${test.skalicloud-sdg-my.template}</test.skalicloud-sdg-my.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/slicehost/pom.xml b/providers/slicehost/pom.xml
index dc8167e..80f8a67 100644
--- a/providers/slicehost/pom.xml
+++ b/providers/slicehost/pom.xml
@@ -36,9 +36,9 @@
<properties>
<test.slicehost.endpoint>https://api.slicehost.com</test.slicehost.endpoint>
<test.slicehost.api-version>1.4.1.1</test.slicehost.api-version>
- <test.slicehost.build-version />
+ <test.slicehost.build-version></test.slicehost.build-version>
<test.slicehost.identity>FIXME</test.slicehost.identity>
- <test.slicehost.image-id />
+ <test.slicehost.template></test.slicehost.template>
<jclouds.osgi.export>org.jclouds.slicehost*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -105,7 +105,7 @@
<test.slicehost.api-version>${test.slicehost.api-version}</test.slicehost.api-version>
<test.slicehost.build-version>${test.slicehost.build-version}</test.slicehost.build-version>
<test.slicehost.identity>${test.slicehost.identity}</test.slicehost.identity>
- <test.slicehost.image-id>${test.slicehost.image-id}</test.slicehost.image-id>
+ <test.slicehost.template>${test.slicehost.template}</test.slicehost.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/softlayer/pom.xml b/providers/softlayer/pom.xml
index 0836c5e..9ddb6e2 100644
--- a/providers/softlayer/pom.xml
+++ b/providers/softlayer/pom.xml
@@ -50,13 +50,10 @@
<properties>
<test.softlayer.endpoint>https://api.softlayer.com/rest</test.softlayer.endpoint>
<test.softlayer.api-version>3</test.softlayer.api-version>
- <test.softlayer.build-version />
+ <test.softlayer.build-version></test.softlayer.build-version>
<test.softlayer.identity>FIXME</test.softlayer.identity>
<test.softlayer.credential>FIXME</test.softlayer.credential>
- <test.softlayer.image-id />
- <test.softlayer.image.login-user />
- <test.softlayer.image.authenticate-sudo />
-
+ <test.softlayer.template></test.softlayer.template>
<jclouds.osgi.export>org.jclouds.softlayer*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -120,9 +117,7 @@
<test.softlayer.build-version>${test.softlayer.build-version}</test.softlayer.build-version>
<test.softlayer.identity>${test.softlayer.identity}</test.softlayer.identity>
<test.softlayer.credential>${test.softlayer.credential}</test.softlayer.credential>
- <test.softlayer.image-id>${test.softlayer.image-id}</test.softlayer.image-id>
- <test.softlayer.image.login-user>${test.softlayer.image.login-user}</test.softlayer.image.login-user>
- <test.softlayer.image.authenticate-sudo>${test.softlayer.image.authenticate-sudo}</test.softlayer.image.authenticate-sudo>
+ <test.softlayer.template>${test.softlayer.template}</test.softlayer.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/stratogen-vcloud-mycloud/pom.xml b/providers/stratogen-vcloud-mycloud/pom.xml
index cfa68f8..5f80ed3 100644
--- a/providers/stratogen-vcloud-mycloud/pom.xml
+++ b/providers/stratogen-vcloud-mycloud/pom.xml
@@ -39,10 +39,7 @@
<test.stratogen-vcloud-mycloud.build-version>1.5.0.464915</test.stratogen-vcloud-mycloud.build-version>
<test.stratogen-vcloud-mycloud.identity>FIXME_IDENTITY</test.stratogen-vcloud-mycloud.identity>
<test.stratogen-vcloud-mycloud.credential>FIXME_CREDENTIAL</test.stratogen-vcloud-mycloud.credential>
- <test.stratogen-vcloud-mycloud.image-id />
- <test.stratogen-vcloud-mycloud.image.login-user />
- <test.stratogen-vcloud-mycloud.image.authenticate-sudo />
-
+ <test.stratogen-vcloud-mycloud.template></test.stratogen-vcloud-mycloud.template>
<jclouds.osgi.export>org.jclouds.stratogen.vcloud.mycloud*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -115,9 +112,7 @@
<test.stratogen-vcloud-mycloud.build-version>${test.stratogen-vcloud-mycloud.build-version}</test.stratogen-vcloud-mycloud.build-version>
<test.stratogen-vcloud-mycloud.identity>${test.stratogen-vcloud-mycloud.identity}</test.stratogen-vcloud-mycloud.identity>
<test.stratogen-vcloud-mycloud.credential>${test.stratogen-vcloud-mycloud.credential}</test.stratogen-vcloud-mycloud.credential>
- <test.stratogen-vcloud-mycloud.image-id>${test.stratogen-vcloud-mycloud.image-id}</test.stratogen-vcloud-mycloud.image-id>
- <test.stratogen-vcloud-mycloud.image.login-user>${test.stratogen-vcloud-mycloud.image.login-user}</test.stratogen-vcloud-mycloud.image.login-user>
- <test.stratogen-vcloud-mycloud.image.authenticate-sudo>${test.stratogen-vcloud-mycloud.image.authenticate-sudo}</test.stratogen-vcloud-mycloud.image.authenticate-sudo>
+ <test.stratogen-vcloud-mycloud.template>${test.stratogen-vcloud-mycloud.template}</test.stratogen-vcloud-mycloud.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/trmk-ecloud/pom.xml b/providers/trmk-ecloud/pom.xml
index 3eb59ff..f38b244 100644
--- a/providers/trmk-ecloud/pom.xml
+++ b/providers/trmk-ecloud/pom.xml
@@ -37,10 +37,10 @@
<test.trmk-ecloud.endpoint>https://services.enterprisecloud.terremark.com/api</test.trmk-ecloud.endpoint>
<test.trmk-ecloud.datacenter>MIA</test.trmk-ecloud.datacenter>
<test.trmk-ecloud.api-version>0.8b-ext2.8</test.trmk-ecloud.api-version>
- <test.trmk-ecloud.build-version />
+ <test.trmk-ecloud.build-version></test.trmk-ecloud.build-version>
<test.trmk-ecloud.identity>FIXME</test.trmk-ecloud.identity>
<test.trmk-ecloud.credential>FIXME</test.trmk-ecloud.credential>
- <test.trmk-ecloud.image-id />
+ <test.trmk-ecloud.template></test.trmk-ecloud.template>
<jclouds.osgi.export>org.jclouds.trmk.ecloud*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -116,7 +116,7 @@
<test.trmk-ecloud.identity>${test.trmk-ecloud.identity}</test.trmk-ecloud.identity>
<test.trmk-ecloud.credential>${test.trmk-ecloud.credential}</test.trmk-ecloud.credential>
<test.trmk-ecloud.datacenter>${test.trmk-ecloud.datacenter}</test.trmk-ecloud.datacenter>
- <test.trmk-ecloud.image-id>${test.trmk-ecloud.image-id}</test.trmk-ecloud.image-id>
+ <test.trmk-ecloud.template>${test.trmk-ecloud.template}</test.trmk-ecloud.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/trmk-vcloudexpress/pom.xml b/providers/trmk-vcloudexpress/pom.xml
index e80faed..df454c2 100644
--- a/providers/trmk-vcloudexpress/pom.xml
+++ b/providers/trmk-vcloudexpress/pom.xml
@@ -36,10 +36,10 @@
<properties>
<test.trmk-vcloudexpress.endpoint>https://services.vcloudexpress.terremark.com/api</test.trmk-vcloudexpress.endpoint>
<test.trmk-vcloudexpress.api-version>0.8a-ext1.6</test.trmk-vcloudexpress.api-version>
- <test.trmk-vcloudexpress.build-version />
+ <test.trmk-vcloudexpress.build-version></test.trmk-vcloudexpress.build-version>
<test.trmk-vcloudexpress.identity>FIXME</test.trmk-vcloudexpress.identity>
<test.trmk-vcloudexpress.credential>FIXME</test.trmk-vcloudexpress.credential>
- <test.trmk-vcloudexpress.image-id />
+ <test.trmk-vcloudexpress.template></test.trmk-vcloudexpress.template>
<jclouds.osgi.export>org.jclouds.trmk.ecloud*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
@@ -114,7 +114,7 @@
<test.trmk-vcloudexpress.build-version>${test.trmk-vcloudexpress.build-version}</test.trmk-vcloudexpress.build-version>
<test.trmk-vcloudexpress.identity>${test.trmk-vcloudexpress.identity}</test.trmk-vcloudexpress.identity>
<test.trmk-vcloudexpress.credential>${test.trmk-vcloudexpress.credential}</test.trmk-vcloudexpress.credential>
- <test.trmk-vcloudexpress.image-id>${test.trmk-vcloudexpress.image-id}</test.trmk-vcloudexpress.image-id>
+ <test.trmk-vcloudexpress.template>${test.trmk-vcloudexpress.template}</test.trmk-vcloudexpress.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/providers/trystack-nova/pom.xml b/providers/trystack-nova/pom.xml
index 5f85e5c..ba50265 100644
--- a/providers/trystack-nova/pom.xml
+++ b/providers/trystack-nova/pom.xml
@@ -36,13 +36,10 @@
<properties>
<test.trystack-nova.endpoint>https://nova-api.trystack.org:5443</test.trystack-nova.endpoint>
<test.trystack-nova.api-version>1.1</test.trystack-nova.api-version>
- <test.trystack-nova.build-version />
+ <test.trystack-nova.build-version></test.trystack-nova.build-version>
<test.trystack-nova.identity>FIXME_IDENTITY</test.trystack-nova.identity>
<test.trystack-nova.credential>FIXME_CREDENTIAL</test.trystack-nova.credential>
- <test.trystack-nova.image-id />
- <test.trystack-nova.image.login-user />
- <test.trystack-nova.image.authenticate-sudo />
-
+ <test.trystack-nova.template></test.trystack-nova.template>
<jclouds.osgi.export>org.jclouds.trystack.nova*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
@@ -122,9 +119,7 @@
<test.trystack-nova.build-version>${test.trystack-nova.build-version}</test.trystack-nova.build-version>
<test.trystack-nova.identity>${test.trystack-nova.identity}</test.trystack-nova.identity>
<test.trystack-nova.credential>${test.trystack-nova.credential}</test.trystack-nova.credential>
- <test.trystack-nova.image-id>${test.trystack-nova.image-id}</test.trystack-nova.image-id>
- <test.trystack-nova.image.login-user>${test.trystack-nova.image.login-user}</test.trystack-nova.image.login-user>
- <test.trystack-nova.image.authenticate-sudo>${test.trystack-nova.image.authenticate-sudo}</test.trystack-nova.image.authenticate-sudo>
+ <test.trystack-nova.template>${test.trystack-nova.template}</test.trystack-nova.template>
</systemPropertyVariables>
</configuration>
</execution>
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/EnvBuilder.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/EnvBuilder.java
index ad65abc..6851bb4 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/EnvBuilder.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/EnvBuilder.java
@@ -42,6 +42,8 @@
/**
* Exports a variable inside the script
+ *
+ * @param name name of the variable in UPPER_UNDERSCORE case format
*/
public EnvBuilder export(String name, String value) {
variables.put(checkNotNull(name, "name"), checkNotNull(value, "value"));
@@ -66,7 +68,7 @@
builder.append(Utils.writeComment(" Example usage to set a variable", osFamily));
builder.append(Utils.writeComment("", osFamily));
builder.append(Utils.writeComment(" "
- + Utils.writeVariableExporters(ImmutableMap.of("mavenOpts", "-Xms64m -Xmx128m"),
+ + Utils.writeVariableExporters(ImmutableMap.of("MAVEN_OPTS", "-Xms64m -Xmx128m"),
osFamily), osFamily));
builder.append(Utils.writeVariableExporters(variables, osFamily));
builder.append(ShellToken.LF.to(osFamily));
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitBuilder.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitBuilder.java
index 3b0f3e7..c92c078 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitBuilder.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitBuilder.java
@@ -67,10 +67,13 @@
this(instanceName, instanceHome, logDir, variables, ImmutableSet.<Statement> of(), statements);
}
+ /**
+ * @param variables keys are the variables to export in UPPER_UNDERSCORE case format
+ */
public InitBuilder(String instanceName, String instanceHome, String logDir, Map<String, String> variables,
Iterable<Statement> initStatements, Iterable<Statement> statements) {
- Map<String, String> defaultVariables = ImmutableMap.of("instanceName", instanceName, "instanceHome",
- instanceHome, "logDir", logDir);
+ Map<String, String> defaultVariables = ImmutableMap.of("INSTANCE_NAME", instanceName, "INSTANCE_HOME",
+ instanceHome, "LOG_DIR", logDir);
this.initStatement = new StatementList(initStatements);
this.createRunScript = createRunScript(instanceName,// TODO: convert
// so
@@ -79,9 +82,9 @@
// can take from a
// variable
Iterables.concat(variables.keySet(), defaultVariables.keySet()), "{varl}INSTANCE_HOME{varr}", statements);
- this.instanceName = checkNotNull(instanceName, "instanceName");
- this.instanceHome = checkNotNull(instanceHome, "instanceHome");
- this.logDir = checkNotNull(logDir, "logDir");
+ this.instanceName = checkNotNull(instanceName, "INSTANCE_NAME");
+ this.instanceHome = checkNotNull(instanceHome, "INSTANCE_HOME");
+ this.logDir = checkNotNull(logDir, "LOG_DIR");
addEnvironmentVariableScope("default", defaultVariables)
.addEnvironmentVariableScope(instanceName, variables)
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitScript.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitScript.java
index 651cc60..38134dc 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitScript.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitScript.java
@@ -70,7 +70,7 @@
* @see InitScript#getInstanceName()
*/
public Builder name(String instanceName) {
- this.instanceName = checkNotNull(instanceName, "instanceName");
+ this.instanceName = checkNotNull(instanceName, "INSTANCE_NAME");
return this;
}
@@ -78,7 +78,7 @@
* @see InitScript#getInstanceHome()
*/
public Builder home(String instanceHome) {
- this.instanceHome = checkNotNull(instanceHome, "instanceHome");
+ this.instanceHome = checkNotNull(instanceHome, "INSTANCE_HOME");
return this;
}
@@ -86,11 +86,12 @@
* @see InitScript#getLogDir()
*/
public Builder logDir(String logDir) {
- this.logDir = checkNotNull(logDir, "logDir");
+ this.logDir = checkNotNull(logDir, "LOG_DIR");
return this;
}
/**
+ * @param exports keys are the variables to export in UPPER_UNDERSCORE case format
* @see InitScript#getExportedVariables()
*/
public Builder exportVariables(Map<String, String> exports) {
@@ -176,11 +177,14 @@
protected final StatementList run;
protected final ScriptBuilder delegate;
+ /**
+ * @param exports keys are the variables to export in UPPER_UNDERSCORE case format
+ */
protected InitScript(String instanceName, String instanceHome, String logDir, Map<String, String> exports,
StatementList init, StatementList run) {
- this.instanceName = checkNotNull(instanceName, "instanceName");
- this.instanceHome = checkNotNull(instanceHome, "instanceHome");
- this.logDir = checkNotNull(logDir, "logDir");
+ this.instanceName = checkNotNull(instanceName, "INSTANCE_NAME");
+ this.instanceHome = checkNotNull(instanceHome, "INSTANCE_HOME");
+ this.logDir = checkNotNull(logDir, "LOG_DIR");
this.exports = ImmutableMap.<String, String> copyOf(checkNotNull(exports, "exports"));
this.init = checkNotNull(init, "init");
this.run = checkNotNull(run, "run");
@@ -188,10 +192,14 @@
this.delegate = makeInitScriptStatement(instanceName, instanceHome, logDir, exports, init, run);
}
+ /**
+ *
+ * @param exports keys are the variables to export in UPPER_UNDERSCORE case format
+ */
public static ScriptBuilder makeInitScriptStatement(String instanceName, String instanceHome, String logDir,
Map<String, String> exports, StatementList init, StatementList run) {
- Map<String, String> defaultExports = ImmutableMap.of("instanceName", instanceName, "instanceHome", instanceHome,
- "logDir", logDir);
+ Map<String, String> defaultExports = ImmutableMap.of("INSTANCE_NAME", instanceName, "INSTANCE_HOME", instanceHome,
+ "LOG_DIR", logDir);
String exitStatusFile = format("%s/rc", logDir);
run = new StatementList(ImmutableList.<Statement> builder().add(interpret("rm -f " + exitStatusFile))
.add(interpret(format("trap 'echo $?>%s' 0 1 2 3 15", exitStatusFile))).addAll(run.delegate()).build());
@@ -303,7 +311,7 @@
@Override
public String toString() {
- return toStringHelper(this).add("instanceName", instanceName).toString();
+ return toStringHelper(this).add("INSTANCE_NAME", instanceName).toString();
}
@Override
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/ScriptBuilder.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/ScriptBuilder.java
index 7c71ce8..5df74dd 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/ScriptBuilder.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/ScriptBuilder.java
@@ -57,7 +57,7 @@
Map<String, Map<String, String>> variableScopes = Maps.newLinkedHashMap();
@VisibleForTesting
- List<String> variablesToUnset = Lists.newArrayList("path", "javaHome", "libraryPath");
+ List<String> variablesToUnset = Lists.newArrayList("PATH", "JAVA_HOME", "LIBRARY_PATH");
public ScriptBuilder addStatement(Statement statement) {
statements.add(checkNotNull(statement, "statement"));
@@ -66,6 +66,7 @@
/**
* Unsets a variable to ensure it is set within the script.
+ * @param variable name in UPPER_UNDERSCORE case format
*/
public ScriptBuilder unsetEnvironmentVariable(String name) {
variablesToUnset.add(checkNotNull(name, "name"));
@@ -74,6 +75,8 @@
/**
* Exports a variable inside the script
+ * @param scopeName
+ * @param variables keys are the variables to export in UPPER_UNDERSCORE case format
*/
public ScriptBuilder addEnvironmentVariableScope(String scopeName, Map<String, String> variables) {
variableScopes.put(checkNotNull(scopeName, "scopeName"), checkNotNull(variables, "variables"));
@@ -112,22 +115,12 @@
functions.put("abort", Utils.writeFunctionFromResource("abort", osFamily));
for (Entry<String, Map<String, String>> entry : variableScopes.entrySet()) {
- functions.put(entry.getKey(),
- Utils.writeFunction(entry.getKey(), Utils.writeVariableExporters(entry.getValue())));
+ functions.put(entry.getKey(), Utils.writeFunction(entry.getKey(), Utils.writeVariableExporters(entry
+ .getValue(), osFamily)));
}
- final Map<String, String> tokenValueMap = ShellToken.tokenValueMap(osFamily);
StringBuilder builder = new StringBuilder();
builder.append(ShellToken.BEGIN_SCRIPT.to(osFamily));
- builder.append(Utils.writeUnsetVariables(
- Lists.newArrayList(Iterables.transform(variablesToUnset, new Function<String, String>() {
- @Override
- public String apply(String from) {
- if (tokenValueMap.containsKey(from + "Variable"))
- return Utils.FUNCTION_UPPER_UNDERSCORE_TO_LOWER_CAMEL.apply(tokenValueMap.get(from + "Variable"));
- return from;
- }
-
- })), osFamily));
+ builder.append(Utils.writeUnsetVariables(variablesToUnset, osFamily));
Map<String, String> functionsToWrite = resolveFunctionDependenciesForStatements(functions, statements, osFamily);
writeFunctions(functionsToWrite, osFamily, builder);
builder.append(Utils.writeZeroPath(osFamily));
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/AppendFile.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/AppendFile.java
index 4f674cf..8fd534c 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/AppendFile.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/AppendFile.java
@@ -37,7 +37,7 @@
* @author Adrian Cole
*/
public class AppendFile implements Statement {
- public static final String DELIMETER = "END_OF_JCLOUDS_FILE";
+ public static final String DELIMITER = "END_OF_JCLOUDS_FILE";
public static Builder builder() {
return new Builder();
@@ -46,7 +46,7 @@
public static class Builder {
protected String path;
protected Iterable<String> lines = ImmutableSet.of();
- protected String delimeter = DELIMETER;
+ protected String delimiter = DELIMITER;
protected boolean expandVariables;
/**
@@ -66,10 +66,10 @@
}
/**
- * @see AppendFile#getDelimeter()
+ * @see AppendFile#getDelimiter()
*/
- public Builder delimeter(String delimeter) {
- this.delimeter = delimeter;
+ public Builder delimiter(String delimiter) {
+ this.delimiter = delimiter;
return this;
}
@@ -82,19 +82,19 @@
}
public AppendFile build() {
- return new AppendFile(path, lines, delimeter, expandVariables);
+ return new AppendFile(path, lines, delimiter, expandVariables);
}
}
protected final String path;
protected final Iterable<String> lines;
- protected final String delimeter;
+ protected final String delimiter;
protected final boolean expandVariables;
- protected AppendFile(String path, Iterable<String> lines, String delimeter, boolean expandVariables) {
- this.path = checkNotNull(path, "path");
+ protected AppendFile(String path, Iterable<String> lines, String delimiter, boolean expandVariables) {
+ this.path = checkNotNull(path, "PATH");
this.lines = checkNotNull(lines, "lines");
- this.delimeter = checkNotNull(delimeter, "delimeter");
+ this.delimiter = checkNotNull(delimiter, "delimiter");
checkState(Iterables.size(lines) > 0, "you must pass something to execute");
this.expandVariables = expandVariables;
}
@@ -140,15 +140,15 @@
for (String line : lines) {
hereFile.append('\t').append(line).append("\n");
}
- hereFile.append(delimeter).append("\n");
+ hereFile.append(delimiter).append("\n");
return hereFile.toString();
}
public StringBuilder startHereFile() {
StringBuilder hereFile = new StringBuilder().append("cat >> ").append(path);
if (expandVariables)
- return hereFile.append(" <<-").append(delimeter).append("\n");
- return hereFile.append(" <<-'").append(delimeter).append("'\n");
+ return hereFile.append(" <<-").append(delimiter).append("\n");
+ return hereFile.append(" <<-'").append(delimiter).append("'\n");
}
protected String appendLineToWindowsFile(String line, String path) {
@@ -161,4 +161,4 @@
return String.format("echo %s%s%s >>%s{lf}", quote, line, quote, path);
}
-}
\ No newline at end of file
+}
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/CreateOrOverwriteFile.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/CreateOrOverwriteFile.java
index 04bb3ab..f0eb424 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/CreateOrOverwriteFile.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/CreateOrOverwriteFile.java
@@ -42,8 +42,8 @@
}
@Override
- public Builder delimeter(String delimeter) {
- return Builder.class.cast(super.delimeter(delimeter));
+ public Builder delimiter(String delimiter) {
+ return Builder.class.cast(super.delimiter(delimiter));
}
@Override
@@ -53,13 +53,13 @@
@Override
public CreateOrOverwriteFile build() {
- return new CreateOrOverwriteFile(path, lines, delimeter, expandVariables);
+ return new CreateOrOverwriteFile(path, lines, delimiter, expandVariables);
}
}
- protected CreateOrOverwriteFile(String path, Iterable<String> lines, String delimeter, boolean expandVariables) {
- super(path, lines, delimeter, expandVariables);
+ protected CreateOrOverwriteFile(String path, Iterable<String> lines, String delimiter, boolean expandVariables) {
+ super(path, lines, delimiter, expandVariables);
}
@Override
@@ -71,8 +71,8 @@
public StringBuilder startHereFile() {
StringBuilder hereFile = new StringBuilder().append("cat > ").append(path);
if (expandVariables)
- return hereFile.append(" <<-").append(delimeter).append("\n");
- return hereFile.append(" <<-'").append(delimeter).append("'\n");
+ return hereFile.append(" <<-").append(delimiter).append("\n");
+ return hereFile.append(" <<-'").append(delimiter).append("'\n");
}
-}
\ No newline at end of file
+}
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/CreateRunScript.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/CreateRunScript.java
index 0678107..50ef817 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/CreateRunScript.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/CreateRunScript.java
@@ -36,13 +36,12 @@
import org.jclouds.scriptbuilder.ScriptBuilder;
import org.jclouds.scriptbuilder.util.Utils;
-import com.google.common.base.CaseFormat;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
+import com.google.common.collect.ImmutableList.Builder;
/**
* Creates a run script
@@ -50,14 +49,18 @@
* @author Adrian Cole
*/
public class CreateRunScript extends StatementList {
- public final static String DELIMETER = "END_OF_JCLOUDS_SCRIPT";
+ public final static String DELIMITER = "END_OF_JCLOUDS_SCRIPT";
final String instanceName;
final Iterable<String> exports;
final String pwd;
-
+
+ /**
+ * @param exports
+ * variable names to export in UPPER_UNDERSCORE case format
+ */
public CreateRunScript(String instanceName, Iterable<String> exports, String pwd, Iterable<Statement> statements) {
super(statements);
- this.instanceName = checkNotNull(instanceName, "instanceName");
+ this.instanceName = checkNotNull(instanceName, "INSTANCE_NAME");
this.exports = checkNotNull(exports, "exports");
this.pwd = checkNotNull(pwd, "pwd").replaceAll("[/\\\\]", "{fs}");
}
@@ -65,9 +68,13 @@
public static class AddExport implements Statement {
final String export;
final String value;
-
+
+ /**
+ * @param export
+ * variable name in UPPER_UNDERSCORE case format
+ */
public AddExport(String export, String value) {
- this.export = checkNotNull(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export), "export");
+ this.export = checkNotNull(export, "export");
this.value = checkNotNull(value, "value");
}
@@ -116,7 +123,7 @@
builder.append("# add runscript footer\n");
Iterable<String> endScript = Splitter.on(ShellToken.LF.to(OsFamily.UNIX)).split(
ShellToken.END_SCRIPT.to(OsFamily.UNIX));
- builder.append(appendFile(runScript, endScript, DELIMETER).render(OsFamily.UNIX));
+ builder.append(appendFile(runScript, endScript, DELIMITER).render(OsFamily.UNIX));
}
private void addUnixRunScript(String runScript, StringBuilder builder) {
@@ -131,7 +138,7 @@
}
userCommands.addAll(Splitter.on('\n').split(statement.render(OsFamily.UNIX)));
}
- builder.append(appendFile(runScript, userCommands.build(), DELIMETER).render(OsFamily.UNIX));
+ builder.append(appendFile(runScript, userCommands.build(), DELIMITER).render(OsFamily.UNIX));
}
private void addUnixRunScriptHeader(String runScript, StringBuilder builder) {
@@ -143,17 +150,16 @@
beginningOfFile.add(format("PROMPT_COMMAND='echo -ne \\\"\\033]0;%s\\007\\\"'", instanceName));
beginningOfFile.add(Utils.writeZeroPath(OsFamily.UNIX));
beginningOfFile.add(format("export INSTANCE_NAME='%s'", instanceName));
- builder.append(createOrOverwriteFile(runScript, beginningOfFile.build(), DELIMETER).render(OsFamily.UNIX));
+ builder.append(createOrOverwriteFile(runScript, beginningOfFile.build(), DELIMITER).render(OsFamily.UNIX));
// expanding variables here.
- builder.append(AppendFile.builder().path(runScript).delimeter(DELIMETER).expandVariables(true)
+ builder.append(AppendFile.builder().path(runScript).delimiter(DELIMITER).expandVariables(true)
.lines(Iterables.transform(exports, new Function<String, String>() {
@Override
public String apply(String export) {
- String variableNameInUpper = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export);
- return new StringBuilder().append("export ").append(variableNameInUpper).append("='$")
- .append(variableNameInUpper).append("'").toString();
+ return new StringBuilder().append("export ").append(export).append("='$")
+ .append(export).append("'").toString();
}
})).build().render(OsFamily.UNIX));
@@ -165,7 +171,7 @@
if (functionsToWrite.size() > 1) {
StringBuilder functions = new StringBuilder();
ScriptBuilder.writeFunctions(functionsToWrite, OsFamily.UNIX, functions);
- builder.append(appendFile(runScript, functions.toString(), DELIMETER).render(OsFamily.UNIX));
+ builder.append(appendFile(runScript, functions.toString(), DELIMITER).render(OsFamily.UNIX));
}
}
-}
\ No newline at end of file
+}
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InitMetadata.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InitMetadata.java
index 7c0f265..b933d10 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InitMetadata.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InitMetadata.java
@@ -49,7 +49,7 @@
this.stopDir = checkNotNull(stopDir, "stopDir");
this.configDir = checkNotNull(configDir, "configDir");
this.dataDir = checkNotNull(dataDir, "dataDir");
- this.logDir = checkNotNull(logDir, "logDir");
+ this.logDir = checkNotNull(logDir, "LOG_DIR");
this.goldDir = checkNotNull(goldDir, "goldDir");
}
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/JavaInitMetadata.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/JavaInitMetadata.java
index 999147f..765245c 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/JavaInitMetadata.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/JavaInitMetadata.java
@@ -40,7 +40,7 @@
String stopDir, String configDir, String dataDir, String logDir, String goldDir,
String javaHome, String[] classpath, String mainClass, String[] opts, String[] args) {
super(name, platformHome, endPoint, startDir, stopDir, configDir, dataDir, logDir, goldDir);
- this.javaHome = checkNotNull(javaHome, "javaHome");
+ this.javaHome = checkNotNull(javaHome, "JAVA_HOME");
this.classpath = checkNotNull(classpath, "classpath");
this.mainClass = checkNotNull(mainClass, "mainClass");
this.opts = checkNotNull(opts, "opts");
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statements.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statements.java
index 76c6bf6..bfc6df4 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statements.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statements.java
@@ -65,26 +65,30 @@
return new Call(function, args);
}
- public static Statement appendFile(String path, String line, String delimeter) {
- return AppendFile.builder().path(path).lines(ImmutableSet.of(line)).delimeter(delimeter).build();
+ public static Statement appendFile(String path, String line, String delimiter) {
+ return AppendFile.builder().path(path).lines(ImmutableSet.of(line)).delimiter(delimiter).build();
}
public static Statement appendFile(String path, Iterable<String> lines) {
return AppendFile.builder().path(path).lines(lines).build();
}
- public static Statement appendFile(String path, Iterable<String> lines, String delimeter) {
- return AppendFile.builder().path(path).lines(lines).delimeter(delimeter).build();
+ public static Statement appendFile(String path, Iterable<String> lines, String delimiter) {
+ return AppendFile.builder().path(path).lines(lines).delimiter(delimiter).build();
}
public static Statement createOrOverwriteFile(String path, Iterable<String> lines) {
return CreateOrOverwriteFile.builder().path(path).lines(lines).build();
}
- public static Statement createOrOverwriteFile(String path, Iterable<String> lines, String delimeter) {
- return CreateOrOverwriteFile.builder().path(path).lines(lines).delimeter(delimeter).build();
+ public static Statement createOrOverwriteFile(String path, Iterable<String> lines, String delimiter) {
+ return CreateOrOverwriteFile.builder().path(path).lines(lines).delimiter(delimiter).build();
}
+ /**
+ * @param exports
+ * variable names to export in UPPER_UNDERSCORE case format
+ */
public static CreateRunScript createRunScript(String instanceName, Iterable<String> exports, String pwd,
Iterable<Statement> statements) {// TODO: convert so
// that
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/SwitchArg.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/SwitchArg.java
index 289ecc7..17841ba 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/SwitchArg.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/SwitchArg.java
@@ -94,11 +94,11 @@
if (shouldIndent)
actionBuilder.append(INDENT);
actionBuilder.append(line).append(ShellToken.LF.to(family));
- if (line.indexOf(CreateRunScript.DELIMETER) != -1) {
+ if (line.indexOf(CreateRunScript.DELIMITER) != -1) {
inRunScript = inRunScript ? false : true;
}
- if (line.indexOf(AppendFile.DELIMETER) != -1) {
+ if (line.indexOf(AppendFile.DELIMITER) != -1) {
inCreateFile = inCreateFile ? false : true;
}
shouldIndent = !inCreateFile && !inRunScript;
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/functionloader/FunctionNotFoundException.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/functionloader/FunctionNotFoundException.java
index f6ba30f..9c58412 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/functionloader/FunctionNotFoundException.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/functionloader/FunctionNotFoundException.java
@@ -27,10 +27,10 @@
private static final long serialVersionUID = 1L;
public FunctionNotFoundException(String functionName, OsFamily family) {
- super("function: " + functionName + " not found for famiy: " + family);
+ super("function: " + functionName + " not found for family: " + family);
}
public FunctionNotFoundException(String functionName, OsFamily family, Throwable cause) {
- super("function: " + functionName + " not found for famiy: " + family, cause);
+ super("function: " + functionName + " not found for family: " + family, cause);
}
}
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/util/Utils.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/util/Utils.java
index e22e5a6..b8f2f8d 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/util/Utils.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/util/Utils.java
@@ -18,7 +18,6 @@
*/
package org.jclouds.scriptbuilder.util;
-import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
@@ -27,6 +26,7 @@
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.ShellToken;
import org.jclouds.scriptbuilder.functionloader.CurrentFunctionLoader;
+import org.jclouds.util.Maps2;
import com.google.common.base.CaseFormat;
import com.google.common.base.Function;
@@ -41,28 +41,35 @@
*/
public class Utils {
- public static final LowerCamelToUpperUnderscore FUNCTION_LOWER_CAMEL_TO_UPPER_UNDERSCORE = new LowerCamelToUpperUnderscore();
+ /**
+ *
+ * In {@link ShellToken}, the values whose names end in {@code _VARIABLE} designate variable
+ * names we know how to translate from one platform to another. For example
+ * {@link ShellToken#LIBRARY_PATH_VARIABLE} means that we can translate the variable named
+ * {@code LIBRARY_PATH} to the proper platform-specific name.
+ */
+ public static final class VariableNameForOsFamily implements Function<String, String> {
+ private final OsFamily family;
- public static final class LowerCamelToUpperUnderscore implements Function<String, String> {
+ public VariableNameForOsFamily(OsFamily family) {
+ this.family = family;
+ }
+
@Override
- public String apply(String from) {
- return CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, from);
+ public String apply(String input) {
+ String variableNameKey = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, input) + "Variable";
+ if (ShellToken.tokenValueMap(family).containsKey(variableNameKey))
+ return ShellToken.tokenValueMap(family).get(variableNameKey);
+ return input;
}
}
- public static final UpperUnderscoreToLowerCamel FUNCTION_UPPER_UNDERSCORE_TO_LOWER_CAMEL = new UpperUnderscoreToLowerCamel();
-
- public static final class UpperUnderscoreToLowerCamel implements Function<String, String> {
- @Override
- public String apply(String from) {
- return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, from);
- }
- }
-
- /** matches any expression inside curly braces (where the expression does not including an open curly brace) */
+ /**
+ * matches any expression inside curly braces (where the expression does not including an open
+ * curly brace)
+ */
private static final Pattern pattern = Pattern.compile("\\{([^\\{]+?)\\}");
-
/**
* replaces tokens that are expressed as <code>{token}</code>
*
@@ -96,32 +103,31 @@
/**
* converts a map into variable exports relevant to the specified platform.
* <p/>
- * ex. if variablesInLowerCamelCase is "mavenOpts" -> "-Xms64m -Xmx256m" <br/>
+ * ex. if {@code keys} is the map: "MAVEN_OPTS" -> "-Xms64m -Xmx256m" <br/>
* and family is UNIX<br/>
* then writeVariableExporters returns literally {@code export MAVEN_OPTS="-Xms64m -Xmx256m"\n}
*
- * @param variablesInLowerCamelCase
- * lower camel keys to values
+ * @param exports
+ * keys are the variables to export in UPPER_UNDERSCORE case format
* @param family
* operating system for formatting
+ * @see VariableNameForOsFamily
*/
- public static String writeVariableExporters(Map<String, String> variablesInLowerCamelCase,
- OsFamily family) {
- return replaceTokens(writeVariableExporters(variablesInLowerCamelCase), ShellToken
- .tokenValueMap(family));
+ public static String writeVariableExporters(Map<String, String> exports, final OsFamily family) {
+ exports = Maps2.transformKeys(exports, new VariableNameForOsFamily(family));
+ return replaceTokens(writeVariableExporters(exports), ShellToken.tokenValueMap(family));
}
/**
* converts a map into variable exporters in shell intermediate language.
*
- * @param variablesInLowerCamelCase
- * lower camel keys to values
+ * @param exports
+ * keys are the variables to export in UPPER_UNDERSCORE case format
*/
- public static String writeVariableExporters(Map<String, String> variablesInLowerCamelCase) {
+ public static String writeVariableExporters(Map<String, String> exports) {
StringBuilder initializers = new StringBuilder();
- for (Entry<String, String> entry : variablesInLowerCamelCase.entrySet()) {
- String key = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, entry.getKey());
- initializers.append(String.format("{export} %s={vq}%s{vq}{lf}", key, entry.getValue()));
+ for (Entry<String, String> entry : exports.entrySet()) {
+ initializers.append(String.format("{export} %s={vq}%s{vq}{lf}", entry.getKey(), entry.getValue()));
}
return initializers.toString();
}
@@ -131,36 +137,34 @@
}
public static String writeFunctionFromResource(String function, OsFamily family) {
- String toReturn = CurrentFunctionLoader.get().loadFunction(function,family);
- String lf = ShellToken.LF.to(family);
- return toReturn.endsWith(lf) ? toReturn : new StringBuilder(toReturn).append(lf).toString();
+ String toReturn = CurrentFunctionLoader.get().loadFunction(function, family);
+ String lf = ShellToken.LF.to(family);
+ return toReturn.endsWith(lf) ? toReturn : new StringBuilder(toReturn).append(lf).toString();
}
- public static String writeFunction(String function, String source) {
+ public static String writeFunction(String function, String source) {
return String.format("{fncl}%s{fncr}%s{fnce}", function, source.replaceAll("^", " "));
}
- public static final Map<OsFamily, String> OS_TO_POSITIONAL_VAR_PATTERN = ImmutableMap.of(
- OsFamily.UNIX, "set {key}=$1\nshift\n", OsFamily.WINDOWS, "set {key}=%1\r\nshift\r\n");
+ public static final Map<OsFamily, String> OS_TO_POSITIONAL_VAR_PATTERN = ImmutableMap.of(OsFamily.UNIX,
+ "set {key}=$1\nshift\n", OsFamily.WINDOWS, "set {key}=%1\r\nshift\r\n");
- public static final Map<OsFamily, String> OS_TO_LOCAL_VAR_PATTERN = ImmutableMap.of(
- OsFamily.UNIX, "set {key}=\"{value}\"\n", OsFamily.WINDOWS, "set {key}={value}\r\n");
+ public static final Map<OsFamily, String> OS_TO_LOCAL_VAR_PATTERN = ImmutableMap.of(OsFamily.UNIX,
+ "set {key}=\"{value}\"\n", OsFamily.WINDOWS, "set {key}={value}\r\n");
/**
* Writes an initialization statement for use inside a script or a function.
*
- * @param positionalVariablesInLowerCamelCase
+ * @param positionalVariables
* - transfer the value of args into these statements. Note that there is no check to
* ensure that all source args are indeed present.
+ *
*/
- public static String writePositionalVars(List<String> positionalVariablesInLowerCamelCase,
- OsFamily family) {
+ public static String writePositionalVars(Iterable<String> positionalVariables, OsFamily family) {
StringBuilder initializers = new StringBuilder();
- for (String variableInLowerCamelCase : positionalVariablesInLowerCamelCase) {
- String key = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE,
- variableInLowerCamelCase);
- initializers.append(replaceTokens(OS_TO_POSITIONAL_VAR_PATTERN.get(family), ImmutableMap
- .of("key", key)));
+ for (String positionalVariable : positionalVariables) {
+ initializers.append(replaceTokens(OS_TO_POSITIONAL_VAR_PATTERN.get(family), ImmutableMap.of("key",
+ positionalVariable)));
}
return initializers.toString();
}
@@ -168,22 +172,20 @@
/**
* Ensures that variables come from a known source instead of bleeding in from a profile
*
- * @param variablesInLowerCamelCase
+ * @param variablesToUnset
* - System variables to unset
+ * @see VariableNameForOsFamily
*/
- public static String writeUnsetVariables(List<String> variablesInLowerCamelCase, OsFamily family) {
+ public static String writeUnsetVariables(Iterable<String> variablesToUnset, OsFamily family) {
+ variablesToUnset = Iterables.transform(variablesToUnset, new VariableNameForOsFamily(family));
switch (family) {
case UNIX:
- return String.format("unset %s\n", Joiner.on(' ').join(
- Iterables.transform(variablesInLowerCamelCase,
- FUNCTION_LOWER_CAMEL_TO_UPPER_UNDERSCORE)));
+ return String.format("unset %s\n", Joiner.on(' ').join(variablesToUnset));
case WINDOWS:
StringBuilder initializers = new StringBuilder();
- for (String variableInLowerCamelCase : variablesInLowerCamelCase) {
- String key = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE,
- variableInLowerCamelCase);
- initializers.append(replaceTokens(OS_TO_LOCAL_VAR_PATTERN.get(family), ImmutableMap
- .of("key", key, "value", "")));
+ for (String variableToUnset : variablesToUnset) {
+ initializers.append(replaceTokens(OS_TO_LOCAL_VAR_PATTERN.get(family), ImmutableMap.of("key",
+ variableToUnset, "value", "")));
}
return initializers.toString();
default:
@@ -193,8 +195,8 @@
}
public static final Map<OsFamily, String> OS_TO_ZERO_PATH = ImmutableMap.of(OsFamily.WINDOWS,
- "set PATH=c:\\windows\\;C:\\windows\\system32;c:\\windows\\system32\\wbem\r\n",
- OsFamily.UNIX, "export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin\n");
+ "set PATH=c:\\windows\\;C:\\windows\\system32;c:\\windows\\system32\\wbem\r\n", OsFamily.UNIX,
+ "export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin\n");
/**
* @return line used to zero out the path of the script such that basic commands such as unix ps
diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/EnvBuilderTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/EnvBuilderTest.java
index 9b3b9bb..b574989 100644
--- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/EnvBuilderTest.java
+++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/EnvBuilderTest.java
@@ -39,7 +39,7 @@
*/
public class EnvBuilderTest {
- EnvBuilder testScriptBuilder = new EnvBuilder().export("javaHome",
+ EnvBuilder testScriptBuilder = new EnvBuilder().export("JAVA_HOME",
"/apps/jdk1.6");
@Test
@@ -59,8 +59,8 @@
@Test
public void testExport() {
EnvBuilder builder = new EnvBuilder();
- builder.export("javaHome", "/apps/jdk1.6");
- assertEquals(builder.variables, ImmutableMap.of("javaHome", "/apps/jdk1.6"));
+ builder.export("JAVA_HOME", "/apps/jdk1.6");
+ assertEquals(builder.variables, ImmutableMap.of("JAVA_HOME", "/apps/jdk1.6"));
}
@Test
diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/InitBuilderTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/InitBuilderTest.java
index 60a2000..d2274eb 100644
--- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/InitBuilderTest.java
+++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/InitBuilderTest.java
@@ -45,7 +45,7 @@
@Deprecated
public class InitBuilderTest {
- InitBuilder testInitBuilder = new InitBuilder("mkebsboot", "/mnt/tmp", "/mnt/tmp", ImmutableMap.of("tmpDir",
+ InitBuilder testInitBuilder = new InitBuilder("mkebsboot", "/mnt/tmp", "/mnt/tmp", ImmutableMap.of("TMP_DIR",
"/mnt/tmp"), ImmutableList.<Statement> of(
appendFile("{tmp}{fs}{uid}{fs}scripttest{fs}temp.txt", ImmutableList.<String> of("hello world")),
exec("find /")));
@@ -69,7 +69,7 @@
new InitBuilder("mkebsboot",// name of the script
"/tmp",// working directory
"/tmp/logs",// location of stdout.log and stderr.log
- ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh", "ebsMountPoint", "/mnt/ebs"),// variables
+ ImmutableMap.of("IMAGE_DIR", "/mnt/tmp", "EBS_DEVICE", "/dev/sdh", "EBS_MOUNT_POINT", "/mnt/ebs"),// variables
// used
// inside
// of
diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/ScriptBuilderTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/ScriptBuilderTest.java
index 2710927..aa7409a 100644
--- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/ScriptBuilderTest.java
+++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/ScriptBuilderTest.java
@@ -49,8 +49,8 @@
public class ScriptBuilderTest {
ScriptBuilder testScriptBuilder = new ScriptBuilder()
- .unsetEnvironmentVariable("runtime")
- .addEnvironmentVariableScope("default", ImmutableMap.of("runtime", "Moo"))
+ .unsetEnvironmentVariable("RUNTIME")
+ .addEnvironmentVariableScope("default", ImmutableMap.of("RUNTIME", "Moo"))
.addStatement(
switchArg(1, ImmutableMap.of(
"start",
@@ -132,8 +132,8 @@
@Test
public void testExport() {
ScriptBuilder builder = new ScriptBuilder();
- builder.addEnvironmentVariableScope("default", ImmutableMap.of("javaHome", "/apps/jdk1.6"));
- assertEquals(builder.variableScopes, ImmutableMap.of("default", ImmutableMap.of("javaHome", "/apps/jdk1.6")));
+ builder.addEnvironmentVariableScope("default", ImmutableMap.of("JAVA_HOME", "/apps/jdk1.6"));
+ assertEquals(builder.variableScopes, ImmutableMap.of("default", ImmutableMap.of("JAVA_HOME", "/apps/jdk1.6")));
}
@Test
diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/CreateRunScriptTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/CreateRunScriptTest.java
index 46050e8..c265bc1 100644
--- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/CreateRunScriptTest.java
+++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/CreateRunScriptTest.java
@@ -39,7 +39,7 @@
public class CreateRunScriptTest {
Statement statement = createRunScript(
"yahooprod",
- ImmutableList.<String> of("javaHome"),
+ ImmutableList.<String> of("JAVA_HOME"),
"{tmp}{fs}{uid}{fs}scripttest",
ImmutableList
.<Statement> of(
diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/util/UtilsTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/util/UtilsTest.java
index a1a53ac..022bcd7 100644
--- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/util/UtilsTest.java
+++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/util/UtilsTest.java
@@ -48,36 +48,57 @@
}
public void testWriteVariableExportersUNIX() {
- assertEquals(Utils.writeVariableExporters(ImmutableMap.of("mavenOpts",
+ assertEquals(Utils.writeVariableExporters(ImmutableMap.of("MAVEN_OPTS",
"-Xms128m -Xmx256m -XX:+HeapDumpOnOutOfMemoryError"), OsFamily.UNIX),
"export MAVEN_OPTS=\"-Xms128m -Xmx256m -XX:+HeapDumpOnOutOfMemoryError\"\n");
}
public void testWriteVariableExportersWindows() {
- assertEquals(Utils.writeVariableExporters(ImmutableMap.of("mavenOpts",
+ assertEquals(Utils.writeVariableExporters(ImmutableMap.of("MAVEN_OPTS",
"-Xms128m -Xmx256m -XX:+HeapDumpOnOutOfMemoryError"), OsFamily.WINDOWS),
"set MAVEN_OPTS=-Xms128m -Xmx256m -XX:+HeapDumpOnOutOfMemoryError\r\n");
}
+
+ public void testWriteVariableExportersNameReplaceUNIX() {
+ assertEquals(Utils.writeVariableExporters(ImmutableMap.of("LIBRARY_PATH", "{tmp}"), OsFamily.UNIX),
+ "export LD_LIBRARY_PATH=\"/tmp\"\n");
+ }
+
+ public void testWriteVariableExportersNameReplaceWindows() {
+ assertEquals(Utils.writeVariableExporters(ImmutableMap.of("LIBRARY_PATH", "{tmp}"), OsFamily.WINDOWS),
+ "set PATH=%TEMP%\r\n");
+ }
public void testWritePositionalVarsUNIX() {
- assertEquals(Utils.writePositionalVars(ImmutableList.of("host", "port"), OsFamily.UNIX),
+ assertEquals(Utils.writePositionalVars(ImmutableList.of("HOST", "PORT"), OsFamily.UNIX),
"set HOST=$1\nshift\nset PORT=$1\nshift\n");
}
public void testWritePositionalVarsWindows() {
- assertEquals(Utils.writePositionalVars(ImmutableList.of("host", "port"), OsFamily.WINDOWS),
+ assertEquals(Utils.writePositionalVars(ImmutableList.of("HOST", "PORT"), OsFamily.WINDOWS),
"set HOST=%1\r\nshift\r\nset PORT=%1\r\nshift\r\n");
}
public void testWriteUnsetVariablesUNIX() {
- assertEquals(Utils.writeUnsetVariables(ImmutableList.of("host", "port"), OsFamily.UNIX),
+ assertEquals(Utils.writeUnsetVariables(ImmutableList.of("HOST", "PORT"), OsFamily.UNIX),
"unset HOST PORT\n");
}
public void testWriteUnsetVariablesWindows() {
- assertEquals(Utils.writeUnsetVariables(ImmutableList.of("host", "port"), OsFamily.WINDOWS),
+ assertEquals(Utils.writeUnsetVariables(ImmutableList.of("HOST", "PORT"), OsFamily.WINDOWS),
"set HOST=\r\nset PORT=\r\n");
}
+
+
+ public void testWriteUnsetVariablesNameReplaceUNIX() {
+ assertEquals(Utils.writeUnsetVariables(ImmutableList.of("LIBRARY_PATH"), OsFamily.UNIX),
+ "unset LD_LIBRARY_PATH\n");
+ }
+
+ public void testWriteUnsetVariablesNameReplaceWindows() {
+ assertEquals(Utils.writeUnsetVariables(ImmutableList.of("LIBRARY_PATH"), OsFamily.WINDOWS),
+ "set PATH=\r\n");
+ }
public void testSingleCurlyBraceDoesntBreakLfTokenReplacement() {
assertEquals(Utils.replaceTokens("{{lf}", ShellToken.tokenValueMap(OsFamily.UNIX)),