http://git-wip-us.apache.org/repos/asf/stratos/blob/397d9926/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest.java
 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest.java
new file mode 100644
index 0000000..527123a
--- /dev/null
+++ 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest.java
@@ -0,0 +1,575 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.ec2.compute.strategy;
+
+import static com.google.common.io.BaseEncoding.base64;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.testng.Assert.assertEquals;
+
+import javax.inject.Provider;
+import java.lang.reflect.Method;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+
+import com.google.common.base.Function;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.aws.domain.Region;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.ec2.compute.domain.EC2HardwareBuilder;
+import org.jclouds.ec2.compute.domain.RegionAndName;
+import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
+import org.jclouds.ec2.compute.options.EC2TemplateOptions;
+import org.jclouds.ec2.domain.BlockDeviceMapping;
+import org.jclouds.ec2.domain.KeyPair;
+import org.jclouds.ec2.options.RunInstancesOptions;
+import org.jclouds.scriptbuilder.domain.Statements;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", singleThreaded = true, testName = 
"CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest")
+public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
+
+   public static final LoginCredentials CREDENTIALS = LoginCredentials
+         .builder()
+         .privateKey(
+               "-----BEGIN RSA PRIVATE KEY-----\n"
+                     + 
"MIIEowIBAAKCAQEA0CbFlhSdbMdad2ux2BVqk6Ut5fLKb0CdbqubGcEBfwsSz9Rp4Ile76P90MpV\n"
+                     + 
"W1BGKL5V4MO+flG6dZnRWPVmgrNVyDTmEsALiMGjfEwbACEZ1A8C6mPa36wWO7MlxuyMjg8OczTB\n"
+                     + 
"EXnHNDpxE5a6KowJtzFlmgjHk2Y+Q42UIqPx47lQUv5bdMDCnfNNomSzTVRjOZLUkDja+ybCKdux\n"
+                     + 
"gqTsuInhuBRMx+wxff8Z43ECdJV6UPoXK3der1dlZunxGCFkCeYq0kCX7FZ7PV35X744jqhD8P+7\n"
+                     + 
"y5prO4W+M3DWgChUx0OlbDbSHtDVlcfdbj/+4AKYKU6rQOqh+4DPDQIDAQABAoIBAHjQuEiXKJSV\n"
+                     + 
"1U2RZcVtENInws9AL/2I/Jfa5Qh6vTqXG9EjklywfzkK72x7tDVvD3ngmAoAs5WwLFDL+fXvYhOk\n"
+                     + 
"sbql8ZCahVdYRWME7XsSu2IZYHDZipXe1XzLS7b9X8uos5Ns4E8bZuNKtI1RJDdD1vPMqRNR2z0T\n"
+                     + 
"0Dn3eC7t+t+t7PWaK5AXu2ot7DoOeG1QhqJbwd5pMkIn2ydBILytgmDk/2P3EtJGePIJIeQBicmw\n"
+                     + 
"Z0KrJFa/K2cC8AtmMJUoZMo+mh1yemDbDLCZW30PjFHbZtcszS2cydAgq/HDFkZynvZG0zhbx/To\n"
+                     + 
"jzcNza1AyypYwOwb2/9/ulXZp0UCgYEA+QFgWDfYLH2zwjU5b6e0UbIyd/X/yRZ+L8lOEBd0Bbu8\n"
+                     + 
"qO3txaDbwi7o2mG7pJENHJ3u62CHjgTGDNW9V9Q8eNoGtj3uHvMvi7FdDEK8B6izdZyR7hmZmQ/5\n"
+                     + 
"MIldelyiGZlz1KBSoy4FsCpA7hV7cI6H6x+Im24NxG90/wd/EgMCgYEA1f+cUyUisIO3yKOCf0hQ\n"
+                     + 
"aL289q2//F2cbvBxtki6I8JzTg1H3oTO2WVrXQeCA3a/yiuRUatgGH4mxrpCF6byVJyqrEWAj4kU\n"
+                     + 
"uTbhMgIYhLGoaF1e+vMirCRXUXox0i5X976ASzHn64V9JSd1B+UbKfpcFTYYnChmrRDzmhKN1a8C\n"
+                     + 
"gYBTvIHAyO7ab18/BRUOllAOVSWhr8lXv0eqHEEzKh/rOaoFCRY3qpOcZpgJsGogumK1Z+sLnoeX\n"
+                     + 
"W8WaVVp6KbY4UeGF8aedItyvVnLbB6ohzTqkZ4Wvk05S6cs75kXYO0SL5U3NiCiiFXz2NA9nwTOk\n"
+                     + 
"s1nD2PPgiQ76Kx0mEkhKLwKBgFhHEJqv+AZu37Kx2NRe5WS/2KK9/DPD/hM5tv7mM3sq7Nvm2J3v\n"
+                     + 
"lVDS6J5AyZ5aLzXcER9qncKcz6wtC7SsFs1Wr4VPSoBroRPikrVJbgnXK8yZr+O/xq7Scv7WdJTq\n"
+                     + 
"rzkw6cWbObvLnltkUn/GQBVqBPBvF2nbtLdyBbuqKb5bAoGBAI1+aoJnvXEXxT4UHrMkQcY0eXRz\n"
+                     + 
"3UdbzJmtjMW9CR6l9s11mV6PcZP4qnODp3nd6a+lPeL3wVYQ47DsTJ/Bx5dI17zA5mU57n6mV0a3\n"
+                     + 
"DbSoPKSdaKTQdo2THnVE9P9sPKZWueAcsE4Yw/qcTjoxrtUnAH/AXN250v0tkKIOvMhu\n"
+                     + "-----END RSA PRIVATE KEY-----").build();
+
+   public static final KeyPair KEYPAIR = 
KeyPair.builder().region(Region.AP_SOUTHEAST_1).keyName("myKeyPair")
+         
.sha1OfPrivateKey("13:36:74:b9:56:bb:07:96:c0:19:ab:00:7f:9f:06:d2:16:a0:45:32")
+         
.fingerprint("60:15:d1:f1:d9:e2:3c:e2:ee:a9:64:6a:42:a7:34:0c").keyMaterial(CREDENTIALS.credential).build();
+
+   private static final Provider<RunInstancesOptions> OPTIONS_PROVIDER = new 
javax.inject.Provider<RunInstancesOptions>() {
+
+      @Override
+      public RunInstancesOptions get() {
+         return new RunInstancesOptions();
+      }
+
+   };
+
+   public void testExecuteWithDefaultOptionsEC2() throws SecurityException, 
NoSuchMethodException {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      Hardware size = EC2HardwareBuilder.m1_small().build();
+      String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
+      String generatedGroup = "group";
+      Set<String> generatedGroups = ImmutableSet.of(generatedGroup);
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
createMock(
+            CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class,
+            new Method[] {
+                  
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
+                        .getDeclaredMethod("getOptionsProvider"),
+                  
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
+                        "createNewKeyPairUnlessUserSpecifiedOtherwise", 
String.class, String.class,
+                        TemplateOptions.class),
+                  
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
+                        "getSecurityGroupsForTagAndOptions", String.class, 
String.class, TemplateOptions.class) });
+
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+      Template template = createMock(Template.class);
+
+      // setup expectations
+      expect(strategy.getOptionsProvider()).andReturn(OPTIONS_PROVIDER);
+      expect(template.getHardware()).andReturn(size).atLeastOnce();
+      expect(template.getOptions()).andReturn(options).atLeastOnce();
+      
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping>
 of()).atLeastOnce();
+      expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, 
group, options)).andReturn(
+            systemGeneratedKeyPairName);
+      expect(strategy.getSecurityGroupsForTagAndOptions(region, group, 
options)).andReturn(generatedGroups);
+      expect(options.getUserData()).andReturn(null);
+      expect(options.getClientToken()).andReturn(null);
+
+      // replay mocks
+      replay(options);
+      replay(template);
+      replay(strategy);
+
+      // run
+      RunInstancesOptions customize = strategy.execute(region, group, 
template);
+      assertEquals(customize.buildQueryParameters(), 
ImmutableMultimap.<String, String> of());
+      assertEquals(
+            customize.buildFormParameters().entries(),
+            ImmutableMultimap.<String, String> of("InstanceType", 
size.getProviderId(), "SecurityGroup.1",
+                  generatedGroup, "KeyName", 
systemGeneratedKeyPairName).entries());
+      assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, 
String> of());
+      assertEquals(customize.buildStringPayload(), null);
+
+      // verify mocks
+      verify(options);
+      verify(template);
+      verify(strategy);
+   }
+
+   public void testExecuteWithUserData() throws SecurityException, 
NoSuchMethodException {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      Hardware size = EC2HardwareBuilder.m1_small().build();
+      String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
+      String generatedGroup = "group";
+      Set<String> generatedGroups = ImmutableSet.of(generatedGroup);
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
createMock(
+            CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class,
+            new Method[] {
+                  
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
+                        .getDeclaredMethod("getOptionsProvider"),
+                  
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
+                        "createNewKeyPairUnlessUserSpecifiedOtherwise", 
String.class, String.class,
+                        TemplateOptions.class),
+                  
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
+                        "getSecurityGroupsForTagAndOptions", String.class, 
String.class, TemplateOptions.class) });
+
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+      Template template = createMock(Template.class);
+
+      // setup expectations
+      expect(strategy.getOptionsProvider()).andReturn(OPTIONS_PROVIDER);
+      expect(template.getHardware()).andReturn(size).atLeastOnce();
+      expect(template.getOptions()).andReturn(options).atLeastOnce();
+      
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping>
 of()).atLeastOnce();
+      expect(options.getClientToken()).andReturn("some-token");
+      expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, 
group, options)).andReturn(
+            systemGeneratedKeyPairName);
+      expect(strategy.getSecurityGroupsForTagAndOptions(region, group, 
options)).andReturn(generatedGroups);
+      expect(options.getUserData()).andReturn("hello".getBytes());
+
+      // replay mocks
+      replay(options);
+      replay(template);
+      replay(strategy);
+
+      // run
+      RunInstancesOptions customize = strategy.execute(region, group, 
template);
+      assertEquals(customize.buildQueryParameters(), 
ImmutableMultimap.<String, String> of());
+      assertEquals(
+            customize.buildFormParameters().entries(),
+            ImmutableMultimap.<String, String> of("InstanceType", 
size.getProviderId(), "SecurityGroup.1", "group",
+                  "KeyName", systemGeneratedKeyPairName, "UserData", 
base64().encode("hello".getBytes()),
+                    "ClientToken", "some-token").entries());
+
+      assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, 
String> of());
+      assertEquals(customize.buildStringPayload(), null);
+
+      // verify mocks
+      verify(options);
+      verify(template);
+      verify(strategy);
+   }
+
+   public void 
testCreateNewKeyPairUnlessUserSpecifiedOtherwise_reusesKeyWhenToldTo() {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      String userSuppliedKeyPair = "myKeyPair";
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
setupStrategy();
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+      KeyPair keyPair = createMock(KeyPair.class);
+
+      // setup expectations
+      expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
+      expect(options.getLoginPrivateKey()).andReturn(null);
+      expect(options.getRunScript()).andReturn(null);
+
+      // replay mocks
+      replay(options);
+      replay(keyPair);
+      replayStrategy(strategy);
+
+      // run
+      
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, 
group, options), userSuppliedKeyPair);
+
+      // verify mocks
+      verify(options);
+      verify(keyPair);
+      verifyStrategy(strategy);
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void 
testCreateNewKeyPairUnlessUserSpecifiedOtherwise_reusesKeyWhenToldToWithRunScriptButNoCredentials()
 {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      String userSuppliedKeyPair = "myKeyPair";
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
setupStrategy();
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+      KeyPair keyPair = createMock(KeyPair.class);
+
+      // setup expectations
+      expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
+      expect(options.getLoginUser()).andReturn(null);
+      expect(options.getLoginPassword()).andReturn(null);
+      expect(options.getLoginPrivateKey()).andReturn(null);
+      expect(options.shouldAuthenticateSudo()).andReturn(null);
+      expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
+
+      expect(strategy.credentialsMap.containsKey(new RegionAndName(region, 
userSuppliedKeyPair))).andReturn(false);
+
+      // replay mocks
+      replay(options);
+      replay(keyPair);
+      replayStrategy(strategy);
+
+      // run
+      
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, 
group, options), userSuppliedKeyPair);
+
+      // verify mocks
+      verify(options);
+      verify(keyPair);
+      verifyStrategy(strategy);
+   }
+
+   public void 
testCreateNewKeyPairUnlessUserSpecifiedOtherwise_reusesKeyWhenToldToWithRunScriptAndCredentialsAlreadyInMap()
 {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      String userSuppliedKeyPair = "myKeyPair";
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
setupStrategy();
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+      KeyPair keyPair = createMock(KeyPair.class);
+
+      // setup expectations
+      expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
+      expect(options.getLoginPrivateKey()).andReturn(null);
+      expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
+
+      expect(strategy.credentialsMap.containsKey(new RegionAndName(region, 
userSuppliedKeyPair))).andReturn(true);
+
+      // replay mocks
+      replay(options);
+      replay(keyPair);
+      replayStrategy(strategy);
+
+      // run
+      
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, 
group, options), userSuppliedKeyPair);
+
+      // verify mocks
+      verify(options);
+      verify(keyPair);
+      verifyStrategy(strategy);
+   }
+
+   public void 
testCreateNewKeyPairUnlessUserSpecifiedOtherwise_reusesKeyWhenToldToWithRunScriptAndCredentialsSpecified()
 {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      String userSuppliedKeyPair = "myKeyPair";
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
setupStrategy();
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+      KeyPair keyPair = createMock(KeyPair.class);
+
+      // setup expectations
+      expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
+      
expect(options.getLoginPrivateKey()).andReturn(CREDENTIALS.getOptionalPrivateKey().get()).atLeastOnce();
+
+      // Notice that the fingerprint and sha1 generated
+      expect(strategy.credentialsMap.put(new RegionAndName(region, 
userSuppliedKeyPair), KEYPAIR)).andReturn(null);
+      expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
+      expect(strategy.credentialsMap.containsKey(new RegionAndName(region, 
userSuppliedKeyPair))).andReturn(true);
+
+      // replay mocks
+      replay(options);
+      replay(keyPair);
+      replayStrategy(strategy);
+
+      // run
+      
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, 
group, options), userSuppliedKeyPair);
+
+      // verify mocks
+      verify(options);
+      verify(keyPair);
+      verifyStrategy(strategy);
+   }
+
+   public void 
testCreateNewKeyPairUnlessUserSpecifiedOtherwise_createsNewKeyPairAndReturnsItsNameByDefault()
+         throws ExecutionException {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      String userSuppliedKeyPair = null;
+      boolean shouldAutomaticallyCreateKeyPair = true;
+      String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
setupStrategy();
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+      KeyPair keyPair = createMock(KeyPair.class);
+
+      // setup expectations
+      expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
+      
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
+      
expect(keyPair.getKeyName()).andReturn(systemGeneratedKeyPairName).atLeastOnce();
+      expect(strategy.credentialsMap.containsKey(new RegionAndName(region, 
group))).andReturn(true);
+      expect(strategy.credentialsMap.get(new RegionAndName(region, 
group))).andReturn(keyPair);
+      expect(options.getRunScript()).andReturn(null);
+
+      // replay mocks
+      replay(options);
+      replay(keyPair);
+      replayStrategy(strategy);
+
+      // run
+      
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, 
group, options),
+            systemGeneratedKeyPairName);
+
+      // verify mocks
+      verify(options);
+      verify(keyPair);
+      verifyStrategy(strategy);
+   }
+
+   public void 
testCreateNewKeyPairUnlessUserSpecifiedOtherwise_doesntCreateAKeyPairAndReturnsNullWhenToldNotTo()
 {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      String userSuppliedKeyPair = null;
+      boolean shouldAutomaticallyCreateKeyPair = false; // here's the important
+      // part!
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
setupStrategy();
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+      KeyPair keyPair = createMock(KeyPair.class);
+
+      // setup expectations
+      expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
+      expect(options.getRunScript()).andReturn(null);
+      
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
+
+      // replay mocks
+      replay(options);
+      replay(keyPair);
+      replayStrategy(strategy);
+
+      // run
+      
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, 
group, options), null);
+
+      // verify mocks
+      verify(options);
+      verify(keyPair);
+      verifyStrategy(strategy);
+   }
+
+   public void 
testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesntExist()
+         throws ExecutionException {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      String generatedMarkerGroup = "jclouds#group";
+      Set<String> groupIds = ImmutableSet.<String> of();
+      int[] ports = {};
+      boolean shouldAuthorizeSelf = true;
+      Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
setupStrategy();
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+
+      // setup expectations
+      expect(options.getGroups()).andReturn(groupIds).atLeastOnce();
+      expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
+      RegionNameAndIngressRules regionNameAndIngressRules = new 
RegionNameAndIngressRules(region, generatedMarkerGroup,
+            ports, shouldAuthorizeSelf);
+      
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(group);
+
+      // replay mocks
+      replay(options);
+      replayStrategy(strategy);
+
+      // run
+      assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, 
options), returnVal);
+
+      // verify mocks
+      verify(options);
+      verifyStrategy(strategy);
+   }
+
+   public void 
testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenPortsAreSpecifiedWhenDoesntExist()
+         throws ExecutionException {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      String generatedMarkerGroup = "jclouds#group";
+      Set<String> groupIds = ImmutableSet.<String> of();
+      int[] ports = { 22, 80 };
+      boolean shouldAuthorizeSelf = true;
+      Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
setupStrategy();
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+
+      // setup expectations
+      expect(options.getGroups()).andReturn(groupIds).atLeastOnce();
+      expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
+      RegionNameAndIngressRules regionNameAndIngressRules = new 
RegionNameAndIngressRules(region, generatedMarkerGroup,
+            ports, shouldAuthorizeSelf);
+      
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
+
+      // replay mocks
+      replay(options);
+      replayStrategy(strategy);
+
+      // run
+      assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, 
options), returnVal);
+
+      // verify mocks
+      verify(options);
+      verifyStrategy(strategy);
+   }
+
+   public void 
testGetSecurityGroupsForTagAndOptions_reusesGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesExist()
+         throws ExecutionException {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      String generatedMarkerGroup = "jclouds#group";
+      Set<String> groupIds = ImmutableSet.<String> of();
+      int[] ports = {};
+      boolean shouldAuthorizeSelf = true;
+      Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
setupStrategy();
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+
+      // setup expectations
+      expect(options.getGroups()).andReturn(groupIds).atLeastOnce();
+      expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
+      RegionNameAndIngressRules regionNameAndIngressRules = new 
RegionNameAndIngressRules(region, generatedMarkerGroup,
+            ports, shouldAuthorizeSelf);
+      
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
+
+      // replay mocks
+      replay(options);
+      replayStrategy(strategy);
+
+      // run
+      assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, 
options), returnVal);
+
+      // verify mocks
+      verify(options);
+      verifyStrategy(strategy);
+   }
+
+   public void 
testGetSecurityGroupsForTagAndOptions_reusesGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesExistAndAcceptsUserSuppliedGroups()
 {
+      // setup constants
+      String region = Region.AP_SOUTHEAST_1;
+      String group = "group";
+      String generatedMarkerGroup = "jclouds#group";
+      Set<String> groupIds = ImmutableSet.<String> of("group1", "group2");
+      int[] ports = {};
+      boolean shouldAuthorizeSelf = true;
+      boolean groupExisted = true;
+      Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup, 
"group1", "group2");
+
+      // create mocks
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy = 
setupStrategy();
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+
+      // setup expectations
+      expect(options.getGroups()).andReturn(groupIds).atLeastOnce();
+      RegionNameAndIngressRules regionNameAndIngressRules = new 
RegionNameAndIngressRules(region, generatedMarkerGroup,
+            ports, shouldAuthorizeSelf);
+
+      expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules))
+            .andReturn(groupExisted ? "group" : null);
+
+      // replay mocks
+      replay(options);
+      replayStrategy(strategy);
+
+      // run
+      assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, 
options), returnVal);
+
+      // verify mocks
+      verify(options);
+      verifyStrategy(strategy);
+   }
+
+   private void 
verifyStrategy(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions 
strategy) {
+      verify(strategy.makeKeyPair);
+      verify(strategy.credentialsMap);
+      verify(strategy.securityGroupMap);
+   }
+
+   @SuppressWarnings("unchecked")
+   private CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions 
setupStrategy() {
+      Function<RegionAndName, KeyPair> makeKeyPair = 
createMock(Function.class);
+      ConcurrentMap<RegionAndName, KeyPair> credentialsMap = 
createMock(ConcurrentMap.class);
+      LoadingCache<RegionAndName, String> securityGroupMap = 
createMock(LoadingCache.class);
+      GroupNamingConvention.Factory namingConventionFactory = 
createMock(GroupNamingConvention.Factory.class);
+      GroupNamingConvention namingConvention = 
createMock(GroupNamingConvention.class);
+      
expect(namingConventionFactory.create()).andReturn(namingConvention).anyTimes();
+      
expect(namingConvention.sharedNameForGroup("group")).andReturn("jclouds#group").anyTimes();
+      replay(namingConventionFactory);
+      replay(namingConvention);
+      
+      return new 
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(makeKeyPair, 
credentialsMap,
+            securityGroupMap, OPTIONS_PROVIDER, namingConventionFactory);
+   }
+
+   private void 
replayStrategy(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions 
strategy) {
+      replay(strategy.makeKeyPair);
+      replay(strategy.credentialsMap);
+      replay(strategy.securityGroupMap);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/397d9926/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSetTest.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSetTest.java
 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSetTest.java
new file mode 100644
index 0000000..86f39bc
--- /dev/null
+++ 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSetTest.java
@@ -0,0 +1,340 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.ec2.compute.strategy;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reportMatcher;
+import static org.easymock.EasyMock.verify;
+
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.base.Optional;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+import org.easymock.IArgumentMatcher;
+import org.jclouds.compute.config.CustomizationResponse;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadata.Status;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.predicates.AtomicNodeRunning;
+import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
+import org.jclouds.compute.util.ComputeUtils;
+import org.jclouds.domain.Credentials;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.compute.domain.RegionAndName;
+import org.jclouds.ec2.compute.functions.PresentInstances;
+import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
+import org.jclouds.ec2.compute.options.EC2TemplateOptions;
+import org.jclouds.ec2.domain.Reservation;
+import org.jclouds.ec2.domain.RunningInstance;
+import org.jclouds.ec2.features.ElasticIPAddressApi;
+import org.jclouds.ec2.features.InstanceApi;
+import org.jclouds.ec2.options.RunInstancesOptions;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", singleThreaded = true, testName = 
"EC2CreateNodesInGroupThenAddToSetTest")
+public class EC2CreateNodesInGroupThenAddToSetTest {
+
+   @SuppressWarnings("unchecked")
+   public void testIpAllocationThenAfterNodeRunningAssignThenUpdateCache() {
+      Location location = ZONE_AP_SOUTHEAST_1A;
+      String region = "ap-southeast-1";
+      String zone = "ap-southeast-1a";
+
+      String imageId = "ami1";
+      String instanceCreatedId = "instance1";
+      NodeMetadata nodeMetadata = new NodeMetadataBuilder().id(region + "/" + 
instanceCreatedId)
+            .providerId(instanceCreatedId).status(Status.RUNNING).build();
+      // setup mocks
+      EC2CreateNodesInGroupThenAddToSet strategy = setupStrategy(nodeMetadata);
+      InputParams input = new InputParams(location);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
+      ElasticIPAddressApi ipClient = createMock(ElasticIPAddressApi.class);
+      RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
+      RunningInstance instance = createMock(RunningInstance.class);
+      Reservation<? extends RunningInstance> reservation = new 
Reservation<RunningInstance>(region,
+            ImmutableSet.<String> of(), ImmutableSet.<RunningInstance> 
of(instance), "ownerId", "requesterId",
+            "reservationId");
+
+      // enable auto-allocation
+      strategy.autoAllocateElasticIps = true;
+
+      // setup expectations
+      expect(input.template.clone()).andReturn(input.template);
+      expect(strategy.client.getInstanceApi()).andReturn((Optional) 
Optional.of(instanceClient)).atLeastOnce();
+      expect(
+            strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize
+                  .execute(region, input.tag, 
input.template)).andReturn(ec2Options);
+      expect(strategy.client.getElasticIPAddressApi()).andReturn((Optional) 
Optional.of(ipClient)).atLeastOnce();
+
+      
expect(input.template.getLocation()).andReturn(input.location).atLeastOnce();
+      expect(input.template.getImage()).andReturn(input.image).atLeastOnce();
+      expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce();
+
+      // differences when ip allocation
+      expect(ipClient.allocateAddressInRegion(region)).andReturn("1.1.1.1");
+      
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata).atLeastOnce();
+      ipClient.associateAddressInRegion(region, "1.1.1.1", instanceCreatedId);
+      strategy.elasticIpCache.put(new RegionAndName(region, 
instanceCreatedId), "1.1.1.1");
+
+      expect(instanceClient.runInstancesInRegion(region, zone, imageId, 1, 
input.count, ec2Options)).andReturn(
+            Reservation.class.cast(reservation));
+      expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce();
+      // simulate a lazy credentials fetch
+      LoginCredentials creds = 
LoginCredentials.builder().user("foo").privateKey("bar").build();
+      
expect(strategy.instanceToCredentials.getUnchecked(instance)).andReturn(Optional.of(creds));
+      expect(instance.getRegion()).andReturn(region).atLeastOnce();
+      expect(strategy.credentialStore.put("node#" + region + "/" + 
instanceCreatedId, creds)).andReturn(null);
+
+      expect(strategy.presentInstances.apply(ImmutableSet.of(new 
RegionAndName(region, 
instanceCreatedId)))).andReturn(ImmutableSet.of(instance));
+      
expect(input.template.getOptions()).andReturn(input.options).atLeastOnce();
+      expect(input.options.getLoginUser()).andReturn(null);
+      expect(input.options.getLoginPassword()).andReturn(null);
+      expect(input.options.getLoginPrivateKey()).andReturn(null);
+      expect(input.options.shouldAuthenticateSudo()).andReturn(null);
+      expect(input.options.getMaxCount()).andReturn(0);
+
+      expect(
+            
strategy.utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(eq(input.options),
+                  containsNodeMetadata(nodeMetadata), eq(input.nodes), 
eq(input.badNodes), eq(input.customization)))
+            .andReturn(null);
+
+      // replay mocks
+      replay(instanceClient);
+      replay(ipClient);
+      replay(ec2Options);
+      replay(instance);
+      input.replayMe();
+      replayStrategy(strategy);
+
+      // run
+      strategy.execute(input.tag, input.count, input.template, input.nodes, 
input.badNodes, input.customization);
+
+      // verify mocks
+      verify(instanceClient);
+      verify(ipClient);
+      verify(ec2Options);
+      verify(instance);
+      input.verifyMe();
+      verifyStrategy(strategy);
+   }
+
+   @Test
+   public void testZoneAsALocation() {
+      assertRegionAndZoneForLocation(ZONE_AP_SOUTHEAST_1A, "ap-southeast-1", 
"ap-southeast-1a");
+   }
+
+   @Test
+   public void testRegionAsALocation() {
+      assertRegionAndZoneForLocation(REGION_AP_SOUTHEAST_1, "ap-southeast-1", 
null);
+   }
+
+   // // fixtures
+
+   public static Iterable<NodeMetadata> containsNodeMetadata(final 
NodeMetadata in) {
+      reportMatcher(new IArgumentMatcher() {
+
+         @Override
+         public void appendTo(StringBuffer buffer) {
+            buffer.append("contains(");
+            buffer.append(in);
+            buffer.append(")");
+         }
+
+         @Override
+         public boolean matches(Object arg) {
+            return Iterables.contains((Iterable<?>) arg, in);
+         }
+
+      });
+      return null;
+   }
+
+   @SuppressWarnings("unchecked")
+   private void assertRegionAndZoneForLocation(Location location, String 
region, String zone) {
+      String imageId = "ami1";
+      String instanceCreatedId = "instance1";
+      NodeMetadata nodeMetadata = new NodeMetadataBuilder().id(region + "/" + 
instanceCreatedId)
+            .providerId(instanceCreatedId).status(Status.RUNNING).build();
+
+      // setup mocks
+      EC2CreateNodesInGroupThenAddToSet strategy = setupStrategy(nodeMetadata);
+      InputParams input = new InputParams(location);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
+      RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
+      RunningInstance instance = createMock(RunningInstance.class);
+      Reservation<? extends RunningInstance> reservation = new 
Reservation<RunningInstance>(region,
+            ImmutableSet.<String> of(), ImmutableSet.<RunningInstance> 
of(instance), "ownerId", "requesterId",
+            "reservationId");
+
+      // setup expectations
+      expect(input.template.clone()).andReturn(input.template);
+      expect(strategy.client.getInstanceApi()).andReturn((Optional) 
Optional.of(instanceClient)).atLeastOnce();
+      expect(
+            strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize
+                  .execute(region, input.tag, 
input.template)).andReturn(ec2Options);
+      
expect(input.template.getLocation()).andReturn(input.location).atLeastOnce();
+      expect(input.template.getImage()).andReturn(input.image).atLeastOnce();
+      expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce();
+      expect(instanceClient.runInstancesInRegion(region, zone, imageId, 1, 
input.count, ec2Options)).andReturn(
+            Reservation.class.cast(reservation));
+      expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce();
+      // simulate a lazy credentials fetch
+      LoginCredentials creds = 
LoginCredentials.builder().user("foo").privateKey("bar").build();
+      
expect(strategy.instanceToCredentials.getUnchecked(instance)).andReturn(Optional.of(creds));
+      expect(instance.getRegion()).andReturn(region).atLeastOnce();
+      expect(strategy.credentialStore.put("node#" + region + "/" + 
instanceCreatedId, creds)).andReturn(null);
+
+      expect(strategy.presentInstances.apply(ImmutableSet.of(new 
RegionAndName(region, 
instanceCreatedId)))).andReturn(ImmutableSet.of(instance));
+      
expect(input.template.getOptions()).andReturn(input.options).atLeastOnce();
+      expect(input.options.getLoginUser()).andReturn(null);
+      expect(input.options.getLoginPassword()).andReturn(null);
+      expect(input.options.getLoginPrivateKey()).andReturn(null);
+      expect(input.options.shouldAuthenticateSudo()).andReturn(null);
+      expect(input.options.getMaxCount()).andReturn(0);
+
+      
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata);
+      expect(
+            
strategy.utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(eq(input.options),
+                  containsNodeMetadata(nodeMetadata), eq(input.nodes), 
eq(input.badNodes), eq(input.customization)))
+            .andReturn(null);
+
+      // replay mocks
+      replay(instanceClient);
+      replay(ec2Options);
+      replay(instance);
+      input.replayMe();
+      replayStrategy(strategy);
+
+      // run
+      strategy.execute(input.tag, input.count, input.template, input.nodes, 
input.badNodes, input.customization);
+
+      // verify mocks
+      verify(instanceClient);
+      verify(ec2Options);
+      verify(instance);
+      input.verifyMe();
+      verifyStrategy(strategy);
+   }
+
+   private static final Location REGION_AP_SOUTHEAST_1 = new 
LocationBuilder().scope(LocationScope.REGION)
+         .id("ap-southeast-1").description("ap-southeast-1")
+         .parent(new 
LocationBuilder().scope(LocationScope.PROVIDER).id("aws-ec2").description("aws-ec2").build())
+         .build();
+   private static final Location ZONE_AP_SOUTHEAST_1A = new 
LocationBuilder().scope(LocationScope.ZONE)
+         
.id("ap-southeast-1a").description("ap-southeast-1a").parent(REGION_AP_SOUTHEAST_1).build();
+
+   // /////////////////////////////////////////////////////////////////////
+   @SuppressWarnings("unchecked")
+   private static class InputParams {
+      String tag = "foo";
+      int count = 1;
+      Template template = createMock(Template.class);
+      Set<NodeMetadata> nodes = createMock(Set.class);
+      Map<NodeMetadata, Exception> badNodes = createMock(Map.class);
+      Multimap<NodeMetadata, CustomizationResponse> customization = 
createMock(Multimap.class);
+      Hardware hardware = createMock(Hardware.class);
+      Image image = createMock(Image.class);
+      final Location location;
+      EC2TemplateOptions options = createMock(EC2TemplateOptions.class);
+
+      public InputParams(Location location) {
+         this.location = location;
+      }
+
+      void replayMe() {
+         replay(template);
+         replay(hardware);
+         replay(image);
+         replay(nodes);
+         replay(badNodes);
+         replay(customization);
+         replay(options);
+      }
+
+      void verifyMe() {
+         verify(template);
+         verify(hardware);
+         verify(image);
+         verify(nodes);
+         verify(badNodes);
+         verify(customization);
+         verify(options);
+      }
+   }
+
+   private void verifyStrategy(EC2CreateNodesInGroupThenAddToSet strategy) {
+      
verify(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize);
+      verify(strategy.client);
+      verify(strategy.elasticIpCache);
+      verify(strategy.presentInstances);
+      verify(strategy.runningInstanceToNodeMetadata);
+      verify(strategy.instanceToCredentials);
+      verify(strategy.credentialStore);
+      verify(strategy.utils);
+   }
+
+   @SuppressWarnings("unchecked")
+   private EC2CreateNodesInGroupThenAddToSet setupStrategy(final NodeMetadata 
node) {
+      EC2Api client = createMock(EC2Api.class);
+      CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions 
createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = 
createMock(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class);
+      PresentInstances presentInstances = createMock(PresentInstances.class);
+      RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = 
createMock(RunningInstanceToNodeMetadata.class);
+      LoadingCache<RunningInstance, Optional<LoginCredentials>> 
instanceToCredentials = createMock(LoadingCache.class);
+      LoadingCache<RegionAndName, String> elasticIpCache = 
createMock(LoadingCache.class);
+      GetNodeMetadataStrategy nodeRunning = new GetNodeMetadataStrategy() {
+
+         @Override
+         public NodeMetadata getNode(String input) {
+            Assert.assertEquals(input, node.getId());
+            return node;
+         }
+         
+      };
+      Map<String, Credentials> credentialStore = createMock(Map.class);
+      ComputeUtils utils = createMock(ComputeUtils.class);
+      return new EC2CreateNodesInGroupThenAddToSet(client, elasticIpCache, new 
AtomicNodeRunning(nodeRunning),
+            createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, 
presentInstances, runningInstanceToNodeMetadata,
+            instanceToCredentials, credentialStore, utils);
+   }
+
+   private void replayStrategy(EC2CreateNodesInGroupThenAddToSet strategy) {
+      
replay(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize);
+      replay(strategy.client);
+      replay(strategy.elasticIpCache);
+      replay(strategy.presentInstances);
+      replay(strategy.runningInstanceToNodeMetadata);
+      replay(strategy.instanceToCredentials);
+      replay(strategy.credentialStore);
+      replay(strategy.utils);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/397d9926/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategyTest.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategyTest.java
 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategyTest.java
new file mode 100644
index 0000000..077f4c8
--- /dev/null
+++ 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategyTest.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.ec2.compute.strategy;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.testng.Assert.assertEquals;
+
+import java.util.concurrent.ExecutionException;
+
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.compute.domain.RegionAndName;
+import org.jclouds.ec2.features.ElasticIPAddressApi;
+import org.jclouds.ec2.features.InstanceApi;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Optional;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+
+@Test(groups = "unit", singleThreaded = true, testName = 
"EC2DestroyNodeStrategyTest")
+public class EC2DestroyNodeStrategyTest {
+
+   @SuppressWarnings("unchecked")
+   @Test
+   public void testDestroyNodeTerminatesInstanceAndReturnsRefreshedNode() 
throws Exception {
+      EC2Api client = createMock(EC2Api.class);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
+      GetNodeMetadataStrategy getNode = 
createMock(GetNodeMetadataStrategy.class);
+      LoadingCache<RegionAndName, String> elasticIpCache = 
createMock(LoadingCache.class);
+
+      NodeMetadata node = createMock(NodeMetadata.class);
+
+      expect(client.getInstanceApi()).andReturn((Optional) 
Optional.of(instanceClient)).atLeastOnce();
+      expect(instanceClient.terminateInstancesInRegion("region", 
"i-blah")).andReturn(null);
+      expect(getNode.getNode("region/i-blah")).andReturn(node);
+
+      replay(client);
+      replay(getNode);
+      replay(instanceClient);
+      replay(elasticIpCache);
+
+      EC2DestroyNodeStrategy destroyer = new EC2DestroyNodeStrategy(client, 
getNode, elasticIpCache);
+
+      assertEquals(destroyer.destroyNode("region/i-blah"), node);
+
+      verify(client);
+      verify(getNode);
+      verify(instanceClient);
+      verify(elasticIpCache);
+   }
+
+   @SuppressWarnings("unchecked")
+   @Test
+   public void 
testDestroyNodeDisassociatesAndReleasesIpThenTerminatesInstanceAndReturnsRefreshedNode()
+            throws Exception {
+      EC2Api client = createMock(EC2Api.class);
+      GetNodeMetadataStrategy getNode = 
createMock(GetNodeMetadataStrategy.class);
+      LoadingCache<RegionAndName, String> elasticIpCache = 
createMock(LoadingCache.class);
+      ElasticIPAddressApi ipClient = createMock(ElasticIPAddressApi.class);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
+
+      NodeMetadata node = createMock(NodeMetadata.class);
+
+      expect(elasticIpCache.get(new RegionAndName("region", 
"i-blah"))).andReturn("1.1.1.1");
+
+      expect(client.getElasticIPAddressApi()).andReturn((Optional) 
Optional.of(ipClient)).atLeastOnce();
+      ipClient.disassociateAddressInRegion("region", "1.1.1.1");
+      ipClient.releaseAddressInRegion("region", "1.1.1.1");
+      elasticIpCache.invalidate(new RegionAndName("region", "i-blah"));
+
+
+      expect(client.getInstanceApi()).andReturn((Optional) 
Optional.of(instanceClient)).atLeastOnce();
+      expect(instanceClient.terminateInstancesInRegion("region", 
"i-blah")).andReturn(null);
+      expect(getNode.getNode("region/i-blah")).andReturn(node);
+
+      replay(client);
+      replay(getNode);
+      replay(elasticIpCache);
+      replay(instanceClient);
+      replay(ipClient);
+
+      EC2DestroyNodeStrategy destroyer = new EC2DestroyNodeStrategy(client, 
getNode, elasticIpCache);
+      destroyer.autoAllocateElasticIps = true;
+
+      assertEquals(destroyer.destroyNode("region/i-blah"), node);
+
+      verify(client);
+      verify(getNode);
+      verify(elasticIpCache);
+      verify(instanceClient);
+      verify(ipClient);
+   }
+   
+
+   @SuppressWarnings("unchecked")
+   @Test
+   public void 
testDestroyNodeSafeOnCacheMissThenTerminatesInstanceAndReturnsRefreshedNode()
+            throws Exception {
+      EC2Api client = createMock(EC2Api.class);
+      GetNodeMetadataStrategy getNode = 
createMock(GetNodeMetadataStrategy.class);
+      LoadingCache<RegionAndName, String> elasticIpCache = 
createMock(LoadingCache.class);
+      ElasticIPAddressApi ipClient = createMock(ElasticIPAddressApi.class);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
+
+      NodeMetadata node = createMock(NodeMetadata.class);
+
+      expect(elasticIpCache.get(new RegionAndName("region", 
"i-blah"))).andThrow(new CacheLoader.InvalidCacheLoadException(null));
+
+      expect(client.getInstanceApi()).andReturn((Optional) 
Optional.of(instanceClient)).atLeastOnce();
+      expect(instanceClient.terminateInstancesInRegion("region", 
"i-blah")).andReturn(null);
+      expect(getNode.getNode("region/i-blah")).andReturn(node);
+
+      replay(client);
+      replay(getNode);
+      replay(elasticIpCache);
+      replay(instanceClient);
+      replay(ipClient);
+
+      EC2DestroyNodeStrategy destroyer = new EC2DestroyNodeStrategy(client, 
getNode, elasticIpCache);
+      destroyer.autoAllocateElasticIps = true;
+
+      assertEquals(destroyer.destroyNode("region/i-blah"), node);
+
+      verify(client);
+      verify(getNode);
+      verify(elasticIpCache);
+      verify(instanceClient);
+      verify(ipClient);
+   }
+   
+
+   @SuppressWarnings("unchecked")
+   @Test
+   public void 
testDestroyNodeSafeOnCacheExecutionExceptionThenTerminatesInstanceAndReturnsRefreshedNode()
+            throws Exception {
+      EC2Api client = createMock(EC2Api.class);
+      GetNodeMetadataStrategy getNode = 
createMock(GetNodeMetadataStrategy.class);
+      LoadingCache<RegionAndName, String> elasticIpCache = 
createMock(LoadingCache.class);
+      ElasticIPAddressApi ipClient = createMock(ElasticIPAddressApi.class);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
+
+      NodeMetadata node = createMock(NodeMetadata.class);
+
+      expect(elasticIpCache.get(new RegionAndName("region", 
"i-blah"))).andThrow(new ExecutionException(null));
+
+      expect(client.getInstanceApi()).andReturn((Optional) 
Optional.of(instanceClient)).atLeastOnce();
+      expect(instanceClient.terminateInstancesInRegion("region", 
"i-blah")).andReturn(null);
+      expect(getNode.getNode("region/i-blah")).andReturn(node);
+
+      replay(client);
+      replay(getNode);
+      replay(elasticIpCache);
+      replay(instanceClient);
+      replay(ipClient);
+
+      EC2DestroyNodeStrategy destroyer = new EC2DestroyNodeStrategy(client, 
getNode, elasticIpCache);
+      destroyer.autoAllocateElasticIps = true;
+
+      assertEquals(destroyer.destroyNode("region/i-blah"), node);
+
+      verify(client);
+      verify(getNode);
+      verify(elasticIpCache);
+      verify(instanceClient);
+      verify(ipClient);
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/397d9926/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/config/EC2HttpApiModuleExpectTest.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/config/EC2HttpApiModuleExpectTest.java
 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/config/EC2HttpApiModuleExpectTest.java
new file mode 100644
index 0000000..737f880
--- /dev/null
+++ 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/config/EC2HttpApiModuleExpectTest.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.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.BaseEC2ApiExpectTest;
+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.BeforeClass;
+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;
+
+@Test(groups = "unit", testName = "EC2HttpApiModuleExpectTest")
+public class EC2HttpApiModuleExpectTest extends BaseEC2ApiExpectTest<Injector> 
{
+   private Injector injector;
+
+   @BeforeClass
+   @Override
+   protected void setupDefaultRequests() {
+      super.setupDefaultRequests();
+      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);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/397d9926/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/features/AMIApiExpectTest.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/features/AMIApiExpectTest.java
 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/features/AMIApiExpectTest.java
new file mode 100644
index 0000000..e82d079
--- /dev/null
+++ 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/features/AMIApiExpectTest.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.ec2.features;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.domain.Image;
+import org.jclouds.ec2.internal.BaseEC2ApiExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+@Test(groups = "unit", testName = "AMIApiExpectTest")
+public class AMIApiExpectTest extends BaseEC2ApiExpectTest<EC2Api> {
+
+   HttpRequest filter = HttpRequest.builder().method("POST")
+           .endpoint("https://ec2.us-east-1.amazonaws.com/";)
+           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+           .addFormParam("Action", "DescribeImages")
+           .addFormParam("Filter.1.Name", "owner-id")
+           .addFormParam("Filter.1.Value.1", "206029621532")
+           .addFormParam("Signature", 
"BxOCrCYJujtaUqSPagRvv1ki76veVBiKK3yWHvRWgR0%3D")
+           .addFormParam("SignatureMethod", "HmacSHA256")
+           .addFormParam("SignatureVersion", "2")
+           .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z")
+           .addFormParam("Version", "2010-08-31")
+           .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testFilterWhenResponseIs2xx() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
+              
.payload(payloadFromResourceWithContentType("/describe_images.xml", 
"text/xml")).build();
+
+      EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, 
describeRegionsResponse, filter, filterResponse);
+
+      Image image = 
getOnlyElement(apiWhenExist.getAMIApi().get().describeImagesInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("owner-id", "206029621532")
+                      .build()));
+
+      assertEquals(image.getId(), "ami-be3adfd7");
+   }
+
+   public void testFilterWhenResponseIs404() {
+      HttpResponse filterResponse = 
HttpResponse.builder().statusCode(404).build();
+
+      EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, 
describeRegionsResponse, filter, filterResponse);
+
+      
assertEquals(apiWhenNotExist.getAMIApi().get().describeImagesInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("owner-id", "206029621532")
+                      .build()),
+              ImmutableSet.of());
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/397d9926/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
new file mode 100644
index 0000000..367de3f
--- /dev/null
+++ 
b/dependencies/jclouds/apis/ec2/1.8.0-stratos/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.ec2.features;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.concat;
+import static com.google.common.collect.Iterables.getFirst;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.collect.Sets.newHashSet;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.imageIds;
+import static 
org.jclouds.ec2.options.RegisterImageBackedByEbsOptions.Builder.addNewBlockDevice;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+import org.jclouds.aws.AWSResponseException;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.TemplateBuilderSpec;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.domain.BlockDevice;
+import org.jclouds.ec2.domain.Image;
+import org.jclouds.ec2.domain.Image.ImageType;
+import org.jclouds.ec2.domain.RootDeviceType;
+import org.jclouds.ec2.domain.RunningInstance;
+import org.jclouds.ec2.domain.Snapshot;
+import org.jclouds.ec2.options.RegisterImageBackedByEbsOptions;
+import org.jclouds.ec2.predicates.InstanceStateRunning;
+import org.jclouds.ec2.predicates.SnapshotCompleted;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+
+/**
+ * Tests behavior of {@code AMIApi}
+ */
+@Test(groups = "live", singleThreaded = true)
+public class AMIApiLiveTest extends BaseComputeServiceContextLiveTest {
+   private TemplateBuilderSpec ebsTemplate;
+
+   public AMIApiLiveTest() {
+      provider = "ec2";
+   }
+
+   @Override
+   protected Properties setupProperties() {
+      Properties overrides = super.setupProperties();
+      String ebsSpec = checkNotNull(setIfTestSystemPropertyPresent(overrides, 
provider + ".ebs-template"), provider
+            + ".ebs-template");
+      ebsTemplate = TemplateBuilderSpec.parse(ebsSpec);
+      return overrides;
+   }
+
+   protected EC2Api ec2Api;
+   protected AMIApi client;
+
+   protected Predicate<RunningInstance> runningTester;
+
+   protected Set<String> imagesToDeregister = newHashSet();
+   protected Set<String> snapshotsToDelete = newHashSet();
+   protected String regionId;
+   protected String ebsBackedImageId;
+   protected String ebsBackedImageName = "jcloudstest1";
+   protected String imageId;
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      ec2Api = view.unwrapApi(EC2Api.class);
+      runningTester = retry(new InstanceStateRunning(ec2Api), 600, 5, SECONDS);
+
+      client = ec2Api.getAMIApi().get();
+      if (ebsTemplate != null) {
+         Template template = 
view.getComputeService().templateBuilder().from(ebsTemplate).build();
+         regionId = template.getLocation().getId();
+         imageId = template.getImage().getProviderId();
+         for (Image image : client.describeImagesInRegionWithFilter(regionId,
+                 ImmutableMultimap.<String, String>builder()
+                         .put("name", ebsBackedImageName).build())) {
+            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() {
+      // Just run in the first region - no need to take the time on all of 
them.
+      String region = getFirst(ec2Api.getConfiguredRegions(), null);
+      assertNotNull(region, "region should not be null");
+      Set<? extends Image> allResults = client.describeImagesInRegion(region);
+      assertNotNull(allResults);
+      assertTrue(allResults.size() >= 2);
+      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 testDescribeImagesWithFilter() {
+      // Just run in the first region - no need to take the time on all of 
them.
+      String region = getFirst(ec2Api.getConfiguredRegions(), null);
+      assertNotNull(region, "region should not be null");
+      Set<? extends Image> allResults = client.describeImagesInRegion(region);
+      assertNotNull(allResults);
+      assertTrue(allResults.size() >= 2);
+      String id1 = allResults.iterator().next().getId();
+      Set<? extends Image> filterResult = 
client.describeImagesInRegionWithFilter(region,
+              ImmutableMultimap.<String, String>builder()
+                      .put("image-id", id1)
+                      .build());
+      assertNotNull(filterResult);
+      assertEquals(filterResult.size(), 1);
+      assertEquals(filterResult.iterator().next().getId(), id1);
+   }
+
+   @Test(expectedExceptions = AWSResponseException.class)
+   public void testDescribeImagesWithInvalidFilter() {
+      // Just run in the first region - no need to take the time on all of 
them.
+      String region = getFirst(ec2Api.getConfiguredRegions(), null);
+      assertNotNull(region, "region should not be null");
+
+      Set<? extends Image> allResults = client.describeImagesInRegion(region);
+      assertNotNull(allResults);
+      assertTrue(allResults.size() >= 2);
+      String id1 = allResults.iterator().next().getId();
+      Set<? extends Image> filterResult = 
client.describeImagesInRegionWithFilter(region,
+              ImmutableMultimap.<String, String>builder()
+                      .put("invalid-filter-id", id1)
+                      .build());
+      assertNotNull(filterResult);
+      assertEquals(filterResult.size(), 1);
+      assertEquals(filterResult.iterator().next().getId(), id1);
+   }
+
+   @Test
+   public void testCreateAndListEBSBackedImage() throws Exception {
+      Snapshot snapshot = createSnapshot();
+
+      // List of images before...
+      int sizeBefore = client.describeImagesInRegionWithFilter(regionId,
+              ImmutableMultimap.<String, String>builder()
+                      .put("name", ebsBackedImageName).build()).size();
+
+      // Register a new image...
+      ebsBackedImageId = client.registerUnixImageBackedByEbsInRegion(regionId, 
ebsBackedImageName, snapshot.getId(),
+              newBlockDeviceOption());
+      imagesToDeregister.add(ebsBackedImageId);
+      final Image ebsBackedImage = 
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, null, 
null, false),
+                  "/dev/sda2", newBlockDeviceInfo()).entrySet());
+
+      int describeCount = 0;
+      int after = 0;
+
+      // This loop is in here to deal with a lag between image creation and it 
showing up in filtered describeImage queries.
+      while (describeCount < 10 && after == 0) {
+         describeCount++;
+         Thread.sleep(30000);
+         // List of images after - should be one larger than before
+         after = client.describeImagesInRegionWithFilter(regionId,
+                 ImmutableMultimap.<String, String>builder()
+                         .put("name", ebsBackedImageName).build()).size();
+      }
+      assertEquals(after, sizeBefore + 1);
+   }
+
+   protected RegisterImageBackedByEbsOptions newBlockDeviceOption() {
+      return addNewBlockDevice("/dev/sda2", "myvirtual", 5, false, null, null, 
false).withDescription("adrian");
+   }
+
+   protected Image.EbsBlockDevice newBlockDeviceInfo() {
+      return new Image.EbsBlockDevice(null, 5, false, null, null, false);
+   }
+
+   // Fires up an instance, finds its root volume ID, takes a snapshot, then
+   // terminates the instance.
+   protected Snapshot createSnapshot() throws RunNodesException {
+
+      String instanceId = null;
+      try {
+         RunningInstance instance = 
getOnlyElement(concat(ec2Api.getInstanceApi().get().runInstancesInRegion(
+               regionId, null, imageId, 1, 1)));
+         instanceId = instance.getId();
+         
+         assertTrue(runningTester.apply(instance), instanceId + "didn't 
achieve the state running!");
+
+         instance = 
getOnlyElement(concat(ec2Api.getInstanceApi().get().describeInstancesInRegion(regionId,
+               instanceId)));
+         BlockDevice device = instance.getEbsBlockDevices().get("/dev/sda1");
+         assertNotNull(device, "device: /dev/sda1 not present on: " + 
instance);
+         Snapshot snapshot = 
ec2Api.getElasticBlockStoreApi().get().createSnapshotInRegion(regionId,
+               device.getVolumeId());
+         snapshotsToDelete.add(snapshot.getId());
+         Predicate<Snapshot> snapshotted = retry(new 
SnapshotCompleted(ec2Api.getElasticBlockStoreApi().get()), 600, 10, SECONDS);
+         assert snapshotted.apply(snapshot);
+         return snapshot;
+      } finally {
+         if (instanceId != null)
+            ec2Api.getInstanceApi().get().terminateInstancesInRegion(regionId, 
instanceId);
+      }
+   }
+
+   @Test(dependsOnMethods = "testCreateAndListEBSBackedImage")
+   public void testGetLaunchPermissionForImage() {
+      client.getLaunchPermissionForImageInRegion(regionId, ebsBackedImageId);
+   }
+
+   @Override
+   @AfterClass(groups = { "integration", "live" })
+   protected void tearDownContext() {
+      for (String imageId : imagesToDeregister)
+         client.deregisterImageInRegion(regionId, imageId);
+      for (String snapshotId : snapshotsToDelete)
+         
ec2Api.getElasticBlockStoreApi().get().deleteSnapshotInRegion(regionId, 
snapshotId);
+      super.tearDownContext();
+   }
+
+}

Reply via email to