You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2016/10/14 09:43:45 UTC

[1/4] jclouds-labs git commit: Refactored Azure ARM to not use Deployments

Repository: jclouds-labs
Updated Branches:
  refs/heads/azure-rebased [created] 2f1103873


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentTemplateBuilderTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentTemplateBuilderTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentTemplateBuilderTest.java
deleted file mode 100644
index 1657899..0000000
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentTemplateBuilderTest.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * 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.azurecompute.arm.features;
-
-import java.util.List;
-import java.util.Map;
-
-import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
-import org.jclouds.azurecompute.arm.domain.DeploymentBody;
-import org.jclouds.azurecompute.arm.domain.ImageReference;
-import org.jclouds.azurecompute.arm.domain.IpConfiguration;
-import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
-import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
-import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
-import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
-import org.jclouds.azurecompute.arm.domain.StorageService;
-import org.jclouds.azurecompute.arm.domain.StorageService.StorageServiceProperties;
-import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
-import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
-import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
-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.OperatingSystem;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.domain.internal.TemplateImpl;
-import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.domain.Location;
-import org.jclouds.domain.LocationBuilder;
-import org.jclouds.domain.LocationScope;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Iterables;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-@Test(groups = "unit", testName = "DeploymentTemplateBuilderTest", singleThreaded = true)
-public class DeploymentTemplateBuilderTest extends BaseAzureComputeApiMockTest {
-
-   final String group = "jcgroup";
-   final String vnetName = group + "virtualnetwork";
-   final String subnetId = "";
-
-   @Test
-   public void testResourceGroup() {
-      DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
-      DeploymentBody deploymentBody = builder.getDeploymentTemplate();
-      List<ResourceDefinition> resources = deploymentBody.template().resources();
-      Map<String, String> variables = deploymentBody.template().variables();
-
-      ResourceDefinition resource = getResourceByType(resources, "Microsoft.Storage/storageAccounts");
-
-      StorageServiceProperties properties = (StorageServiceProperties) resource.properties();
-      assertEquals(properties.accountType(), StorageService.AccountType.Standard_LRS);
-      assertTrue(variables.containsKey(parseVariableName(resource.name())));
-   }
-
-   @Test
-   void testPublicIpAddress() {
-      DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
-      DeploymentBody deploymentBody = builder.getDeploymentTemplate();
-      List<ResourceDefinition> resources = deploymentBody.template().resources();
-      Map<String, String> variables = deploymentBody.template().variables();
-
-      ResourceDefinition resource = getResourceByType(resources, "Microsoft.Network/publicIPAddresses");
-
-      PublicIPAddressProperties properties = (PublicIPAddressProperties) resource.properties();
-      assertEquals(properties.publicIPAllocationMethod(), "Dynamic");
-      assertTrue(variables.containsKey(parseVariableName(resource.name())));
-   }
-
-   @Test
-   void testNetworkInterfaceCard() {
-      DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
-      DeploymentBody deploymentBody = builder.getDeploymentTemplate();
-      List<ResourceDefinition> resources = deploymentBody.template().resources();
-      Map<String, String> variables = deploymentBody.template().variables();
-
-      ResourceDefinition resource = getResourceByType(resources, "Microsoft.Network/networkInterfaces");
-
-      NetworkInterfaceCardProperties properties = (NetworkInterfaceCardProperties) resource.properties();
-      List<IpConfiguration> ipConfigs = properties.ipConfigurations();
-      assertTrue(ipConfigs.size() > 0);
-      IpConfigurationProperties ipProperties = ipConfigs.get(0).properties();
-      assertEquals(ipProperties.privateIPAllocationMethod(), "Dynamic");
-      assertNotNull(ipProperties.publicIPAddress());
-      assertNotNull(ipProperties.subnet());
-
-      assertTrue(variables.containsKey(parseVariableName(resource.name())));
-   }
-
-   @Test
-   void testVirtualMachine() {
-      DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
-      Template template = builder.getTemplate();
-
-      DeploymentBody deploymentBody = builder.getDeploymentTemplate();
-      List<ResourceDefinition> resources = deploymentBody.template().resources();
-      Map<String, String> variables = deploymentBody.template().variables();
-
-      ResourceDefinition resource = getResourceByType(resources, "Microsoft.Compute/virtualMachines");
-      assertNotNull(resource);
-
-      VirtualMachineProperties properties = (VirtualMachineProperties) resource.properties();
-      assertEquals(properties.hardwareProfile().vmSize(), template.getHardware().getId());
-
-      ImageReference image = properties.storageProfile().imageReference();
-      assertEquals(image.publisher(), template.getImage().getProviderId());
-      assertEquals(image.offer(), template.getImage().getName());
-      assertEquals(image.sku(), template.getImage().getVersion());
-      assertEquals(image.version(), "latest");
-
-      assertTrue(variables.containsKey(parseVariableName(resource.name())));
-   }
-
-   @Test
-   void testAddStorageResourceWhenNameIsLongerThan24Chars() {
-      String name = "thishasmorethan24characters";
-      DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions(name);
-
-      DeploymentBody deploymentBody = builder.getDeploymentTemplate();
-      assertTrue(Iterables.contains(deploymentBody.template().variables().keySet(), "storageAccountName"));
-      String storageAccountName = deploymentBody.template().variables().get("storageAccountName");
-      assertEquals(storageAccountName.length(), 24);
-      assertEquals(storageAccountName.substring(0, 10), "thishasmor");
-      assertEquals(storageAccountName.substring(storageAccountName.length() - 10, storageAccountName.length()), "characters");
-   }
-
-   @Test
-   void testAddStorageResourceWhenNameIsExactly24Chars() {
-      String name = "ithasexactly24characters";
-      DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions(name);
-
-      DeploymentBody deploymentBody = builder.getDeploymentTemplate();
-      assertTrue(Iterables.contains(deploymentBody.template().variables().keySet(), "storageAccountName"));
-      assertEquals(deploymentBody.template().variables().get("storageAccountName").length(), 24);
-      assertEquals(deploymentBody.template().variables().get("storageAccountName"), name);
-   }
-
-   @Test
-   void testAddStorageResourceWhenNameIsLessThan3Chars() {
-      String name = "3c";
-      DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions(name);
-
-      DeploymentBody deploymentBody = builder.getDeploymentTemplate();
-      assertTrue(Iterables.contains(deploymentBody.template().variables().keySet(), "storageAccountName"));
-      assertEquals(deploymentBody.template().variables().get("storageAccountName").length(), 6);
-      assertEquals(deploymentBody.template().variables().get("storageAccountName").substring(0, 2), name);
-   }
-
-   @Test
-   void testCustomOptions(){
-      final String dnsLabelPrefix = "mydnslabel";
-      final String customData = "echo customData";
-      final String customData64 = "ZWNobyBjdXN0b21EYXRh";
-      final String keyvaultString = "/url/to/vault/:publickeysecret";
-
-      AzureTemplateOptions options = new AzureTemplateOptions()
-            .customData(customData)
-            .DNSLabelPrefix(dnsLabelPrefix)
-            .keyVaultIdAndSecret(keyvaultString);
-
-      options.virtualNetworkName(vnetName);
-      options.subnetId(subnetId);
-
-      assertEquals(options.as(AzureTemplateOptions.class).getCustomData(), customData);
-      assertEquals(options.getDNSLabelPrefix(), dnsLabelPrefix);
-      assertEquals(options.as(AzureTemplateOptions.class).getKeyVaultIdAndSecret(), keyvaultString);
-
-      DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithOptions(options);
-
-      DeploymentBody deploymentBody = builder.getDeploymentTemplate();
-
-      List<ResourceDefinition> resources = deploymentBody.template().resources();
-      ResourceDefinition publicIpResource = getResourceByType(resources, "Microsoft.Network/publicIPAddresses");
-      assertNotNull(publicIpResource);
-
-      PublicIPAddressProperties ipProperties = (PublicIPAddressProperties) publicIpResource.properties();
-      assertEquals(ipProperties.dnsSettings().domainNameLabel(), dnsLabelPrefix);
-
-      ResourceDefinition vmResource = getResourceByType(resources, "Microsoft.Compute/virtualMachines");
-      assertNotNull(vmResource);
-
-      VirtualMachineProperties virtualMachineProperties = (VirtualMachineProperties) vmResource.properties();
-      assertEquals(virtualMachineProperties.osProfile().customData(), customData64);
-
-      //populated when keyvault is used to get public key.
-      assertNotNull(virtualMachineProperties.osProfile().linuxConfiguration().ssh().publicKeys());
-   }
-
-   @Test(expectedExceptions = IllegalArgumentException.class)
-   void testSimplifyPortsWithPortsNull() {
-      int[] ports = null;
-      DeploymentTemplateBuilder.simplifyPorts(ports);
-   }
-
-   @Test(expectedExceptions = IllegalArgumentException.class)
-   void testSimplifyPortsWithPortsEmpty() {
-      int[] ports = new int[0];
-      DeploymentTemplateBuilder.simplifyPorts(ports);
-   }
-
-   @Test
-   void testSimplifyPorts() {
-      int[] ports = {8084, 22, 8081, 8080, 8082};
-      List<String> ranges = DeploymentTemplateBuilder.simplifyPorts(ports);
-      assertEquals(ranges.size(), 3);
-      assertEquals(ranges.get(0), "22");
-      assertEquals(ranges.get(1), "8080-8082");
-      assertEquals(ranges.get(2), "8084");
-   }
-
-   private Template getMockTemplate(TemplateOptions options) {
-      ((AzureTemplateOptions)options).virtualNetworkName(vnetName);
-      ((AzureTemplateOptions)options).subnetId(subnetId);
-
-      Location provider = (new LocationBuilder()).scope(LocationScope.PROVIDER).id("azurecompute-arm").description("azurecompute-arm").build();
-      Location region = (new LocationBuilder()).scope(LocationScope.REGION).id("northeurope").description("North Europe").parent(provider).build();
-      OperatingSystem os = OperatingSystem.builder().name("osName").version("osVersion").description("osDescription").arch("X86_32").build();
-      //Note that version is set to "latest"
-      Image image = (new ImageBuilder()).id("imageId").providerId("imageId").name("imageName").description("imageDescription").version("sku").operatingSystem(os).status(Image.Status.AVAILABLE).location(region).build();
-      Hardware hardware = (new HardwareBuilder()).id("Standard_A0").build();
-      return new TemplateImpl(image, hardware, region, options);
-   }
-
-   private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithEmptyOptions() {
-      return getMockDeploymentTemplateBuilderWithEmptyOptions("mydeployment");
-   }
-
-   private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithEmptyOptions(String name) {
-      AzureTemplateOptions options = new AzureTemplateOptions();
-      options.virtualNetworkName(vnetName);
-      options.subnetId(subnetId);
-
-      Template template = getMockTemplate(options);
-      DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(group, name, template);
-      return templateBuilder;
-   }
-
-   private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
-      return getMockDeploymentTemplateBuilderWithOptions("mydeployment", options);
-   }
-
-   private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithOptions(String name, TemplateOptions options) {
-      ((AzureTemplateOptions)options).virtualNetworkName(vnetName);
-      ((AzureTemplateOptions)options).subnetId(subnetId);
-
-      Template template = getMockTemplate(options);
-      DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(group, name, template);
-      return templateBuilder;
-   }
-
-   private ResourceDefinition getResourceByType(List<ResourceDefinition> resources, String type) {
-      for (ResourceDefinition r : resources) {
-         if (r.type().equals(type)) {
-            return r;
-         }
-      }
-      Assert.fail("Resource with type: " + type + " not found");
-      return null;
-   }
-
-   private String parseVariableName(String variable) {
-      String[] parts = variable.split("\'");
-      assertTrue(parts.length == 3);
-      return parts[1];
-   }
-}
-

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApiMockTest.java
index adefd95..2d43694 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApiMockTest.java
@@ -83,8 +83,6 @@ public class NetworkSecurityGroupApiMockTest extends BaseAzureComputeApiMockTest
    }
 
    public void getNetworkSecurityGroup() throws InterruptedException {
-      NetworkSecurityGroup nsg = createGroup();
-
       server.enqueue(jsonResponse("/networksecuritygroupget.json").setResponseCode(200));
 
       final NetworkSecurityGroupApi nsgApi = api.getNetworkSecurityGroupApi(resourcegroup);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApiMockTest.java
index 436cb91..b510580 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApiMockTest.java
@@ -147,8 +147,7 @@ public class PublicIPAddressApiMockTest extends BaseAzureComputeApiMockTest {
       PublicIPAddressProperties properties = PublicIPAddressProperties.create(null, null, "Static", 4, null,
               DnsSettings.create("foobar", "foobar.northeurope.cloudapp.azure.com", null));
 
-      PublicIPAddress ip = ipApi.createOrUpdate(publicIpName, location, tags, properties);
-
+      ipApi.createOrUpdate(publicIpName, location, tags, properties);
    }
 
    public void deletePublicIPAddress() throws InterruptedException {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceProviderAPIMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceProviderAPIMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceProviderAPIMockTest.java
index 70f2ad6..3c90d42 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceProviderAPIMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceProviderAPIMockTest.java
@@ -31,7 +31,6 @@ public class ResourceProviderAPIMockTest extends BaseAzureComputeApiMockTest {
 
    final String apiVersion = "2015-01-01";
    final String resource = "Microsoft.Compute";
-   private final String vm_resource = "virtualMachines";
 
    public void getPublicIPAddressInfo() throws InterruptedException {
       server.enqueue(jsonResponse("/getresourceprovidermetadata.json"));

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiMockTest.java
index 39ecd2b..e3fdf6d 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiMockTest.java
@@ -235,41 +235,6 @@ public class StorageAccountApiMockTest extends BaseAzureComputeApiMockTest {
               "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE?api-version=2015-06-15");
    }
 
-   private StorageService getStrorageAccount() {
-      DateService DATE_SERVICE = new SimpleDateFormatDateService();
-      Map<String, String> endpoints = new HashMap<String, String>();
-      endpoints.put("blob", "https://TESTSTORAGE.blob.core.windows.net/");
-      endpoints.put("file", "https://TESTSTORAGE.file.core.windows.net/");
-      endpoints.put("queue", "https://TESTSTORAGE.queue.core.windows.net/");
-      endpoints.put("table", "https://TESTSTORAGE.table.core.windows.net/");
-      Map<String, String> secondaryEndpoints = new HashMap<String, String>();
-      secondaryEndpoints.put("blob", "https://TESTSTORAGE-secondary.blob.core.windows.net/");
-      secondaryEndpoints.put("queue", "https://TESTSTORAGE-secondary.queue.core.windows.net/");
-      secondaryEndpoints.put("table", "https://TESTSTORAGE-secondary.table.core.windows.net/");
-
-
-      String location = "westus";
-      String secondaryLocation = "eastus";
-      final StorageService.StorageServiceProperties props = StorageService.StorageServiceProperties.create(
-              StorageService.AccountType.Standard_RAGRS,
-              DATE_SERVICE.iso8601DateOrSecondsDateParse("2016-02-24T13:04:45.0890883Z"),
-              endpoints,
-              location,
-              StorageService.Status.Succeeded,
-              secondaryEndpoints, secondaryLocation,
-              StorageService.RegionStatus.Available,
-              StorageService.RegionStatus.Available);
-
-      final Map<String, String> tags = ImmutableMap.of(
-              "key1", "value1",
-              "key2", "value2");
-
-      return StorageService.create(
-              "/subscriptions/SUBSCRIPTIONID/resourceGroups/resourceGroup" +
-                      "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE",
-              "TESTSTORAGE", location, tags, null, props);
-   }
-
    private List<StorageService> expected() throws MalformedURLException {
       DateService DATE_SERVICE = new SimpleDateFormatDateService();
       Map<String, String> endpoints = new HashMap<String, String>();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/SubnetApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/SubnetApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/SubnetApiMockTest.java
index bfcf188..0113201 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/SubnetApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/SubnetApiMockTest.java
@@ -16,18 +16,17 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-import com.squareup.okhttp.mockwebserver.RecordedRequest;
-import org.jclouds.azurecompute.arm.domain.Subnet;
-import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
-import org.testng.annotations.Test;
-
-import java.util.List;
-
 import static com.google.common.collect.Iterables.isEmpty;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+
+import org.jclouds.azurecompute.arm.domain.Subnet;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.testng.annotations.Test;
 
 
 @Test(groups = "unit", testName = "SubnetApiMockTest", singleThreaded = true)
@@ -135,6 +134,6 @@ public class SubnetApiMockTest extends BaseAzureComputeApiMockTest {
       assertFalse(status);
 
       String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Network/virtualNetworks/%s/subnets/%s?%s", subscriptionid, resourcegroup, virtualNetwork, subnetName, apiVersion);
-      RecordedRequest rr = assertSent(server, "DELETE", path);
+      assertSent(server, "DELETE", path);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/TemplateToDeploymentTemplateLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/TemplateToDeploymentTemplateLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/TemplateToDeploymentTemplateLiveTest.java
deleted file mode 100644
index 3b87663..0000000
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/TemplateToDeploymentTemplateLiveTest.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * 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.azurecompute.arm.features;
-
-import java.net.URI;
-
-import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
-import org.jclouds.azurecompute.arm.domain.Deployment;
-import org.jclouds.azurecompute.arm.domain.DeploymentBody;
-import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
-import org.jclouds.azurecompute.arm.domain.Subnet;
-import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
-import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
-import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
-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.OperatingSystem;
-import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.domain.internal.TemplateImpl;
-import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.domain.Location;
-import org.jclouds.domain.LocationBuilder;
-import org.jclouds.domain.LocationScope;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.net.UrlEscapers;
-
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-@Test(groups = "live", testName = "TemplateToDeploymentTemplateLiveTest", singleThreaded = true)
-public class TemplateToDeploymentTemplateLiveTest extends BaseAzureComputeApiLiveTest {
-
-   private int maxTestDuration = 400;
-   private int pollingInterval = 3; // how frequently to poll for create status
-   private String resourceGroupName;
-   private String deploymentName;
-   private String vnetName;
-   private String subnetId;
-   private String virtualNetworkName;
-
-   @BeforeClass
-   @Override
-   public void setup() {
-      super.setup();
-      resourceGroupName = String.format("rg-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
-      assertNotNull(createResourceGroup(resourceGroupName));
-      virtualNetworkName = String.format("vn-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
-
-      //Subnets belong to a virtual network so that needs to be created first
-      VirtualNetwork vn = createDefaultVirtualNetwork(resourceGroupName, virtualNetworkName, "10.2.0.0/16", LOCATION);
-      assertNotNull(vn);
-      vnetName = vn.name();
-
-      //Subnet needs to be up & running before NIC can be created
-      String subnetName = String.format("s-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
-      Subnet subnet = createDefaultSubnet(resourceGroupName, subnetName, virtualNetworkName, "10.2.0.0/23");
-      assertNotNull(subnet);
-      assertNotNull(subnet.id());
-      subnetId = subnet.id();
-   }
-
-   @AfterClass
-   @Override
-   protected void tearDown() {
-      super.tearDown();
-      URI uri = deleteResourceGroup(resourceGroupName);
-      assertResourceDeleted(uri);
-   }
-
-   @Test
-   public void testValidateDeploymentTemplateLinuxNodeWithOptions() {
-      Long now = System.currentTimeMillis();
-      deploymentName = "jc" + now;
-
-      AzureTemplateOptions options = new AzureTemplateOptions();
-      options.virtualNetworkName(vnetName);
-      options.subnetId(subnetId);
-
-      options.inboundPorts(22, 8080);
-
-      DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
-
-      DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
-
-      DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
-
-      String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
-      deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
-
-      //Validates that template is syntactically correct
-      Deployment deployment = api().validate(deploymentName, deploymentTemplate);
-      assertNotNull(deployment);
-   }
-
-   @Test
-   public void testValidateDeploymentTemplateLinuxNode() {
-      Long now = System.currentTimeMillis();
-      deploymentName = "jc" + now;
-
-      DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithEmptyOptions();
-
-      DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
-
-      DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
-
-      String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
-      deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
-
-      //Validates that template is syntactically correct
-      Deployment deployment = api().validate(deploymentName, deploymentTemplate);
-      assertNotNull(deployment);
-   }
-
-   @Test
-   public void testValidateDeploymentTemplateWithCustomOptions() {
-      Long now = System.currentTimeMillis();
-      deploymentName = "jc" + now;
-
-      String rsakey = new String("ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmfk/QSF0pvnrpdz+Ah2KulGruKU+8FFBdlw938MpOysRdmp7uwpH6Z7+5VNGNdxFIAyc/W3UaZXF9hTsU8+78TlwkZpsr2mzU+ycu37XLAQ8Uv7hjsAN0DkKKPrZ9lgUUfZVKV/8E/JIAs03gIbL6zO3y7eYJQ5fNeZb+nji7tQT+YLpGq/FDegvraPKVMQbCSCZhsHyWhdPLyFlu9/30npZ0ahYOPI/KyZxFDtM/pHp88+ZAk9Icq5owaLRWcJQqrBGWqjbZnHtjdDqvHZ+C0wPhdJZPyfkHOrSYTwSQBXfX4JLRRCz3J1jf62MbQWT1o6Y4JEs1ZP1Skxu6zR96Q== mocktest");
-      TemplateOptions options = new AzureTemplateOptions()
-              .DNSLabelPrefix("mydnslabel")
-              .virtualNetworkAddressPrefix("10.0.0.0/20")
-              .subnetAddressPrefix("10.0.0.0/25")
-              .authorizePublicKey(rsakey);
-
-      ((AzureTemplateOptions)options).virtualNetworkName(vnetName);
-      ((AzureTemplateOptions)options).subnetId(subnetId);
-
-      DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
-
-      DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
-
-      DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
-
-      String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
-      deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
-
-      Deployment deployment = api().validate(deploymentName, deploymentTemplate);
-      assertNotNull(deployment);
-   }
-
-   @Test
-   public void testValidateDeploymentTemplateLinuxNodeWithSSH() {
-      Long now = System.currentTimeMillis();
-      deploymentName = "jc" + now;
-
-      String rsakey = new String("ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmfk/QSF0pvnrpdz+Ah2KulGruKU+8FFBdlw938MpOysRdmp7uwpH6Z7+5VNGNdxFIAyc/W3UaZXF9hTsU8+78TlwkZpsr2mzU+ycu37XLAQ8Uv7hjsAN0DkKKPrZ9lgUUfZVKV/8E/JIAs03gIbL6zO3y7eYJQ5fNeZb+nji7tQT+YLpGq/FDegvraPKVMQbCSCZhsHyWhdPLyFlu9/30npZ0ahYOPI/KyZxFDtM/pHp88+ZAk9Icq5owaLRWcJQqrBGWqjbZnHtjdDqvHZ+C0wPhdJZPyfkHOrSYTwSQBXfX4JLRRCz3J1jf62MbQWT1o6Y4JEs1ZP1Skxu6zR96Q== mocktest");
-
-      AzureTemplateOptions options = new AzureTemplateOptions();
-      options.virtualNetworkName(vnetName);
-      options.subnetId(subnetId);
-
-      options.authorizePublicKey(rsakey);
-      DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
-
-      DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
-
-      DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
-
-      String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
-      deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
-
-      Deployment deployment = api().validate(deploymentName, deploymentTemplate);
-      assertNotNull(deployment);
-   }
-
-   @Test
-   public void testCreateDeploymentTemplateLinuxNode() {
-      Long now = System.currentTimeMillis();
-      deploymentName = "jc" + now;
-
-      String rsakey = new String("ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmfk/QSF0pvnrpdz+Ah2KulGruKU+8FFBdlw938MpOysRdmp7uwpH6Z7+5VNGNdxFIAyc/W3UaZXF9hTsU8+78TlwkZpsr2mzU+ycu37XLAQ8Uv7hjsAN0DkKKPrZ9lgUUfZVKV/8E/JIAs03gIbL6zO3y7eYJQ5fNeZb+nji7tQT+YLpGq/FDegvraPKVMQbCSCZhsHyWhdPLyFlu9/30npZ0ahYOPI/KyZxFDtM/pHp88+ZAk9Icq5owaLRWcJQqrBGWqjbZnHtjdDqvHZ+C0wPhdJZPyfkHOrSYTwSQBXfX4JLRRCz3J1jf62MbQWT1o6Y4JEs1ZP1Skxu6zR96Q== mocktest");
-
-      AzureTemplateOptions options = new AzureTemplateOptions();
-      options.virtualNetworkName(vnetName);
-      options.subnetId(subnetId);
-
-      options.authorizePublicKey(rsakey);
-      options.inboundPorts(22, 8080);
-      DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
-
-      DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
-      DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
-
-      String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
-      deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
-
-      //creates an actual VM using deployment template
-      Deployment deployment = api().create(deploymentName, deploymentTemplate);
-
-      Deployment.ProvisioningState state = Deployment.ProvisioningState.fromValue(deployment.properties().provisioningState());
-      int testTime = 0;
-      while (testTime < maxTestDuration) {
-         if ((state == Deployment.ProvisioningState.SUCCEEDED) ||
-                 (state == Deployment.ProvisioningState.CANCELED) ||
-                 (state == Deployment.ProvisioningState.DELETED) ||
-                 (state == Deployment.ProvisioningState.FAILED)) {
-            break;
-         }
-
-         // sleep a little bit before polling, timeout after a fixed time
-         try {
-            Thread.sleep(pollingInterval * 1000);
-         } catch (InterruptedException e) {
-            e.printStackTrace();
-         }
-         testTime += pollingInterval;
-
-         deployment = api().get(deploymentName);
-         assertNotNull(deployment);
-         state = Deployment.ProvisioningState.fromValue(deployment.properties().provisioningState());
-      }
-      assertTrue(state == Deployment.ProvisioningState.SUCCEEDED);
-      assertNotNull(deployment);
-   }
-
-   private Template getTemplate(TemplateOptions options) {
-      Location provider = (new LocationBuilder()).scope(LocationScope.PROVIDER).id("azurecompute-arm").description("azurecompute-arm").build();
-      Location region = (new LocationBuilder()).scope(LocationScope.REGION).id(LOCATION).description(LOCATIONDESCRIPTION).parent(provider).build();
-
-      OperatingSystem os = OperatingSystem.builder()
-              .family(OsFamily.UBUNTU)
-              .description("14.04.3-LTS")
-              .is64Bit(true)
-              .build();
-
-      Image image = (new ImageBuilder())
-              .id("UbuntuServer14.04.3-LTS")
-              .providerId("Canonical")
-              .name("UbuntuServer")
-              .description("14.04.3-LTS")
-              .version("14.04.3-LTS")
-              .operatingSystem(os)
-              .status(Image.Status.AVAILABLE)
-              .location(region)
-              .build();
-
-      Hardware hardware = (new HardwareBuilder()).id("Standard_A0").build();
-      return new TemplateImpl(image, hardware, region, options);
-   }
-
-   private DeploymentTemplateBuilder getDeploymentTemplateBuilderWithEmptyOptions() {
-      AzureTemplateOptions options = new AzureTemplateOptions();
-      options.virtualNetworkName(vnetName);
-      options.subnetId(subnetId);
-
-      Template template = getTemplate(options);
-      DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroupName, deploymentName, template);
-      return templateBuilder;
-   }
-
-   private DeploymentTemplateBuilder getDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
-      Template template = getTemplate(options);
-      DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroupName, deploymentName, template);
-      return templateBuilder;
-   }
-
-   private DeploymentApi api() {
-      return api.getDeploymentApi(resourceGroupName);
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
index 2702370..0973693 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
@@ -16,6 +16,10 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -41,6 +45,7 @@ import org.jclouds.azurecompute.arm.domain.Subnet;
 import org.jclouds.azurecompute.arm.domain.VHD;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
 import org.testng.Assert;
@@ -48,16 +53,9 @@ import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-import com.google.common.base.Function;
 import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
-import com.google.gson.internal.LinkedTreeMap;
-
-import static org.jclouds.util.Predicates2.retry;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
 
 @Test(groups = "live", testName = "VirtualMachineApiLiveTest")
 public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
@@ -125,7 +123,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
       }, 60 * 20 * 1000).apply(vmName);
       assertTrue(jobDone, "create operation did not complete in the configured timeout");
 
-      String status = api().get(vmName).properties().provisioningState();
+      VirtualMachineProperties.ProvisioningState status = api().get(vmName).properties().provisioningState();
       // Cannot be creating anymore. Should be succeeded or running but not failed.
       assertTrue(!status.equals("Creating"));
       assertTrue(!status.equals("Failed"));
@@ -146,21 +144,21 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
    @Test(dependsOnMethods = "testStart")
    public void testStop() {
       api().stop(vmName);
-      assertTrue(stateReached("PowerState", "VM stopped"), "stop operation did not complete in the configured timeout");
+      assertTrue(stateReached(PowerState.STOPPED), "stop operation did not complete in the configured timeout");
    }
 
    @Test(dependsOnMethods = "testGet")
    public void testStart() {
       api().start(vmName);
-      assertTrue(stateReached("PowerState", "VM running"), "start operation did not complete in the configured timeout");
+      assertTrue(stateReached(PowerState.RUNNING), "start operation did not complete in the configured timeout");
    }
 
    @Test(dependsOnMethods = "testStop")
    public void testRestart() {
       api().start(vmName);
-      assertTrue(stateReached("PowerState", "VM running"), "start operation did not complete in the configured timeout");
+      assertTrue(stateReached(PowerState.RUNNING), "start operation did not complete in the configured timeout");
       api().restart(vmName);
-      assertTrue(stateReached("PowerState", "VM running"), "restart operation did not complete in the configured timeout");
+      assertTrue(stateReached(PowerState.RUNNING), "restart operation did not complete in the configured timeout");
    }
 
    @Test(dependsOnMethods = "testCreate")
@@ -180,10 +178,11 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
    @Test(dependsOnMethods = "testRestart")
    public void testGeneralize() throws IllegalStateException {
       api().stop(vmName);
-      assertTrue(stateReached("PowerState", "VM stopped"), "restart operation did not complete in the configured timeout");
+      assertTrue(stateReached(PowerState.STOPPED), "restart operation did not complete in the configured timeout");
       api().generalize(vmName);
    }
 
+   @SuppressWarnings("unchecked")
    @Test(dependsOnMethods = "testGeneralize")
    public void testCapture() throws IllegalStateException {
       URI uri = api().capture(vmName, vmName, vmName);
@@ -192,17 +191,17 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
          List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
          if (definitions != null) {
             for (ResourceDefinition definition : definitions) {
-               LinkedTreeMap<String, String> properties = (LinkedTreeMap<String, String>) definition.properties();
+               Map<String, String> properties = (Map<String, String>) definition.properties();
                Object storageObject = properties.get("storageProfile");
-               LinkedTreeMap<String, String> properties2 = (LinkedTreeMap<String, String>) storageObject;
+               Map<String, String> properties2 = (Map<String, String>) storageObject;
                Object osDiskObject = properties2.get("osDisk");
-               LinkedTreeMap<String, String> osProperties = (LinkedTreeMap<String, String>) osDiskObject;
+               Map<String, String> osProperties = (Map<String, String>) osDiskObject;
                Object dataDisksObject = properties2.get("dataDisks");
-               ArrayList<Object> dataProperties = (ArrayList<Object>) dataDisksObject;
-               LinkedTreeMap<String, String> datadiskObject = (LinkedTreeMap<String, String>) dataProperties.get(0);
+               List<Object> dataProperties = (List<Object>) dataDisksObject;
+               Map<String, String> datadiskObject = (Map<String, String>) dataProperties.get(0);
 
-               Assert.assertNotNull(osProperties.get("name"));
-               Assert.assertNotNull(datadiskObject.get("name"));
+               assertNotNull(osProperties.get("name"));
+               assertNotNull(datadiskObject.get("name"));
             }
          }
       }
@@ -245,7 +244,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
               DiagnosticsProfile.BootDiagnostics.create(true, blob);
       DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics);
       VirtualMachineProperties properties = VirtualMachineProperties.create(null,
-              null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, "Creating");
+              null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, VirtualMachineProperties.ProvisioningState.CREATING);
       return properties;
    }
 
@@ -261,37 +260,15 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
       return api.getNetworkInterfaceCardApi(resourceGroupName).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, tags);
    }
 
-   private boolean deleteStorageService(String resourceGroupName, String storageServiceName) {
-      return api.getStorageAccountApi(resourceGroupName).delete(storageServiceName);
-   }
-
-   private boolean waitForState(String name, final String state, final String displayStatus) {
-      return FluentIterable.from(api().getInstanceDetails(name).statuses())
-              .filter(new Predicate<VirtualMachineInstance.VirtualMachineStatus>() {
-                 @Override
-                 public boolean apply(VirtualMachineInstance.VirtualMachineStatus input) {
-                    return input.code().substring(0, 10).equals(state);
-                 }
-              })
-              .transform(new Function<VirtualMachineInstance.VirtualMachineStatus, String>() {
-                 @Override
-                 public String apply(VirtualMachineInstance.VirtualMachineStatus input) {
-                    return input.displayStatus();
-                 }
-              })
-              .anyMatch(new Predicate<String>() {
-                 @Override
-                 public boolean apply(String input) {
-                    return input.equals(displayStatus);
-                 }
-              });
+   private boolean waitForState(String name, final PowerState state) {
+      return api().getInstanceDetails(name).powerState().equals(state);
    }
 
-   private boolean stateReached(final String state, final String displayStatus) {
+   private boolean stateReached(final PowerState state) {
       return retry(new Predicate<String>() {
          @Override
          public boolean apply(String name) {
-            return waitForState(name, state, displayStatus);
+            return waitForState(name, state);
          }
       }, 60 * 4 * 1000).apply(vmName);
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
index f6583c8..bb36dc5 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
@@ -16,35 +16,36 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-import com.google.common.collect.ImmutableList;
-import com.squareup.okhttp.mockwebserver.MockResponse;
+import java.net.URI;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.jclouds.azurecompute.arm.domain.DataDisk;
+import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
 import org.jclouds.azurecompute.arm.domain.HardwareProfile;
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.ImageReference;
-import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import org.jclouds.azurecompute.arm.domain.VHD;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile;
 import org.jclouds.azurecompute.arm.domain.OSDisk;
 import org.jclouds.azurecompute.arm.domain.OSProfile;
-import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
-import org.jclouds.azurecompute.arm.domain.NetworkProfile;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
-import org.jclouds.azurecompute.arm.domain.DataDisk;
+import org.jclouds.azurecompute.arm.domain.VHD;
+import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
 import org.testng.annotations.Test;
 
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Date;
-import java.text.SimpleDateFormat;
-import java.text.DateFormat;
+import com.google.common.collect.ImmutableList;
+import com.squareup.okhttp.mockwebserver.MockResponse;
 
 import static com.google.common.collect.Iterables.isEmpty;
 import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
 @Test(groups = "unit", testName = "VirtualMachineApiMockTest", singleThreaded = true)
@@ -55,14 +56,14 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
       assertEquals(vmAPI.get("windowsmachine"), getVM());
       assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
-              "/virtualMachines/windowsmachine?api-version=2015-06-15");
+              "/virtualMachines/windowsmachine?api-version=2016-03-30");
    }
    public void testGetEmpty() throws Exception {
       server.enqueue(new MockResponse().setResponseCode(404));
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
       assertNull(vmAPI.get("windowsmachine"));
       assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
-              "/virtualMachines/windowsmachine?api-version=2015-06-15");
+              "/virtualMachines/windowsmachine?api-version=2016-03-30");
    }
 
    public void testGetInstanceDetails() throws Exception {
@@ -76,7 +77,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       assertEquals(actual.statuses().get(0).level(), expected.statuses().get(0).level());
       //assertEquals(actual.statuses().get(0).time().toString(), expected.statuses().get(0).time().toString());
       assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
-              "/virtualMachines/windowsmachine/instanceView?api-version=2015-06-15");
+              "/virtualMachines/windowsmachine/instanceView?api-version=2016-03-30");
    }
 
    public void testGetInstanceDetailsEmpty() throws Exception {
@@ -84,7 +85,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
       assertNull(vmAPI.getInstanceDetails("windowsmachine"));
       assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
-              "/virtualMachines/windowsmachine/instanceView?api-version=2015-06-15");
+              "/virtualMachines/windowsmachine/instanceView?api-version=2016-03-30");
    }
 
    public void testList() throws Exception {
@@ -109,7 +110,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       VirtualMachine vm = vmAPI.create("windowsmachine", "westus", getProperties());
       assertEquals(vm, getVM());
       assertSent(server, "PUT", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
-              "/virtualMachines/windowsmachine?api-version=2015-06-15&validating=false",
+              "/virtualMachines/windowsmachine?validating=false&api-version=2016-03-30",
               "{\"location\":\"westus\",\"properties\":" +
                       "{\"vmId\":\"27ee085b-d707-xxxx-yyyy-2370e2eb1cc1\"," +
                       "\"hardwareProfile\":{\"vmSize\":\"Standard_D1\"}," +
@@ -118,7 +119,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
                       "\"vhd\":{\"uri\":\"https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd\"},\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\"},\"dataDisks\":[]}," +
                       "\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"windowsConfiguration\":{\"provisionVMAgent\":false,\"enableAutomaticUpdates\":true}}," +
                       "\"networkProfile\":{\"networkInterfaces\":[{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167\"}]}," +
-                      "\"diagnosticsProfile\":{\"bootDiagnostics\":{\"enabled\":true,\"storageUri\":\"https://groupname2760.blob.core.windows.net/\"}},\"provisioningState\":\"Creating\"}}");
+                      "\"diagnosticsProfile\":{\"bootDiagnostics\":{\"enabled\":true,\"storageUri\":\"https://groupname2760.blob.core.windows.net/\"}},\"provisioningState\":\"CREATING\"}}");
 
    }
 
@@ -133,7 +134,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       assertNull(uri);
 
       assertSent(server, "DELETE", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
-              "/virtualMachines/windowsmachine?api-version=2015-06-15");
+              "/virtualMachines/windowsmachine?api-version=2016-03-30");
    }
    public void testDelete() throws Exception {
       server.enqueue(response202WithHeader());
@@ -146,7 +147,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       assertNotNull(uri);
 
       assertSent(server, "DELETE", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
-              "/virtualMachines/windowsmachine?api-version=2015-06-15");
+              "/virtualMachines/windowsmachine?api-version=2016-03-30");
    }
 
    public void testStart() throws Exception {
@@ -231,7 +232,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
               "https://groupname2760.blob.core.windows.net/");
       DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics);
       VirtualMachineProperties properties = VirtualMachineProperties.create("27ee085b-d707-xxxx-yyyy-2370e2eb1cc1",
-              null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, "Creating");
+              null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, VirtualMachineProperties.ProvisioningState.CREATING);
       return properties;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApiMockTest.java
index 99b0b57..79b48ef 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApiMockTest.java
@@ -101,7 +101,7 @@ public class VirtualNetworkApiMockTest extends BaseAzureComputeApiMockTest {
                       VirtualNetwork.AddressSpace.create(Arrays.asList("10.2.0.0/16")), null);
 
 
-      VirtualNetwork vn = vnApi.createOrUpdate(virtualNetwork, location, virtualNetworkProperties);
+      vnApi.createOrUpdate(virtualNetwork, location, virtualNetworkProperties);
 
       String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Network/virtualNetworks/%s?%s", subscriptionid, resourcegroup, virtualNetwork, apiVersion);
       String json = String.format("{\"location\":\"%s\",\"properties\":{\"addressSpace\":{\"addressPrefixes\":[\"%s\"]}}}", location, "10.2.0.0/16");

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/filters/ApiVersionFilterTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/filters/ApiVersionFilterTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/filters/ApiVersionFilterTest.java
new file mode 100644
index 0000000..f3b15ce
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/filters/ApiVersionFilterTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.azurecompute.arm.filters;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
+import static org.jclouds.reflect.Reflection2.method;
+import static org.testng.Assert.assertEquals;
+
+import java.util.Properties;
+
+import javax.inject.Named;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.internal.FilterStringsBoundToInjectorByName;
+import org.jclouds.reflect.Invocation;
+import org.jclouds.rest.config.InvocationConfig;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.name.Names;
+
+@Test(groups = "unit", testName = "ApiVersionFilterTest", singleThreaded = true)
+public class ApiVersionFilterTest {
+
+   public interface VersionedApi {
+      HttpResponse noName();
+
+      @Named("named:get")
+      HttpResponse named();
+   }
+
+   private Invocation noName;
+   private Invocation named;
+   private InvocationConfig config;
+
+   @BeforeMethod
+   public void setup() {
+      noName = Invocation.create(method(VersionedApi.class, "noName"), ImmutableList.of());
+      named = Invocation.create(method(VersionedApi.class, "named"), ImmutableList.of());
+
+      config = createMock(InvocationConfig.class);
+      expect(config.getCommandName(noName)).andReturn("VersionedApi.noName");
+      expect(config.getCommandName(named)).andReturn("named:get");
+      replay(config);
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testFailIfNoGeneratedHttpRequest() {
+      ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(new Properties()));
+      filter.filter(HttpRequest.builder().method("GET").endpoint("http://localhost").build());
+   }
+
+   @Test
+   public void testOverrideMethodVersion() {
+      Properties props = new Properties();
+      props.setProperty(API_VERSION_PREFIX + "named:get", "namedversion");
+      props.setProperty(API_VERSION_PREFIX + "VersionedApi.noName", "noNameversion");
+      ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(props));
+
+      HttpRequest request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost")
+            .invocation(noName).addQueryParam("api-version", "original", "original2").build();
+      HttpRequest filtered = filter.filter(request);
+      assertEquals(filtered.getEndpoint().getQuery(), "api-version=noNameversion");
+
+      request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost").invocation(named)
+            .addQueryParam("api-version", "original", "original2").build();
+      filtered = filter.filter(request);
+      assertEquals(filtered.getEndpoint().getQuery(), "api-version=namedversion");
+   }
+
+   @Test
+   public void testFallbackToClassName() {
+      Properties props = new Properties();
+      props.setProperty(API_VERSION_PREFIX + "VersionedApi", "classversion");
+      ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(props));
+
+      HttpRequest request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost")
+            .invocation(noName).addQueryParam("api-version", "original", "original2").build();
+      HttpRequest filtered = filter.filter(request);
+      assertEquals(filtered.getEndpoint().getQuery(), "api-version=classversion");
+
+      request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost").invocation(named)
+            .addQueryParam("api-version", "original", "original2").build();
+      filtered = filter.filter(request);
+      assertEquals(filtered.getEndpoint().getQuery(), "api-version=classversion");
+   }
+
+   @Test
+   public void testNothingChangesIfNoCustomVersion() {
+      ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(new Properties()));
+
+      HttpRequest request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost").invocation(named)
+            .addQueryParam("api-version", "foo").build();
+      HttpRequest filtered = filter.filter(request);
+      assertEquals(filtered.getEndpoint().getQuery(), "api-version=foo");
+   }
+
+   private FilterStringsBoundToInjectorByName filterStringsBoundToInjectorByName(final Properties props) {
+      Injector injector = Guice.createInjector(new AbstractModule() {
+         protected void configure() {
+            Names.bindProperties(binder(), props);
+         }
+      });
+      return new FilterStringsBoundToInjectorByName(injector);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
index 82af978..dc4ad28 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
@@ -28,6 +28,7 @@ import org.jclouds.ContextBuilder;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
 import org.jclouds.concurrent.config.ExecutorServiceModule;
+import org.jclouds.rest.ApiContext;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 
@@ -50,6 +51,7 @@ public class BaseAzureComputeApiMockTest {
 
    protected MockWebServer server;
    protected AzureComputeApi api;
+   protected ApiContext<AzureComputeApi> context;
 
    // So that we can ignore formatting.
    private final JsonParser parser = new JsonParser();
@@ -58,16 +60,21 @@ public class BaseAzureComputeApiMockTest {
    public void start() throws IOException {
       server = new MockWebServer();
       server.play();
-      Properties properties = new Properties();
-      properties.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString());
-      properties.put("oauth.endpoint", "https://login.microsoftonline.com/tenant-id/oauth2/token");
       AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
-      api = ContextBuilder.newBuilder(pm)
+      context = ContextBuilder.newBuilder(pm)
               .credentials("", MOCK_BEARER_TOKEN)
               .endpoint(server.getUrl("/").toString() + "subscriptions/SUBSCRIPTIONID")
               .modules(modules)
-              .overrides(properties)
-              .buildApi(AzureComputeApi.class);
+              .overrides(setupProperties())
+              .build();
+      api = context.getApi();
+   }
+   
+   protected Properties setupProperties() {
+      Properties properties = new Properties();
+      properties.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString());
+      properties.put("oauth.endpoint", "https://login.microsoftonline.com/tenant-id/oauth2/token");
+      return properties;
    }
 
    @AfterMethod(alwaysRun = true)


[3/4] jclouds-labs git commit: Refactored Azure ARM to not use Deployments

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
new file mode 100644
index 0000000..cce6b50
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
@@ -0,0 +1,78 @@
+/*
+ * 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.azurecompute.arm.compute.functions;
+
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
+import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
+import org.jclouds.azurecompute.arm.domain.VMImage;
+import org.jclouds.azurecompute.arm.domain.VirtualMachine;
+import org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName;
+import org.jclouds.compute.domain.Image;
+
+import com.google.common.base.Function;
+import com.google.inject.assistedinject.Assisted;
+
+public class ResourceDefinitionToCustomImage implements Function<ResourceDefinition, Image> {
+
+   public interface Factory {
+      ResourceDefinitionToCustomImage create(@Assisted("nodeId") String nodeId, @Assisted("imageName") String imageName);
+   }
+
+   private final String resourceGroup;
+   private final Function<VMImage, Image> vmImageToImage;
+   private final String imageName;
+   private final String storageAccountName;
+   private final VirtualMachine vm;
+
+   @Inject
+   ResourceDefinitionToCustomImage(AzureComputeApi api, AzureComputeConstants azureComputeConstants,
+         StorageProfileToStorageAccountName storageProfileToStorageAccountName,
+         Function<VMImage, Image> vmImageToImage, @Assisted("nodeId") String nodeId,
+         @Assisted("imageName") String imageName) {
+      this.vmImageToImage = vmImageToImage;
+      this.resourceGroup = azureComputeConstants.azureResourceGroup();
+      this.imageName = imageName;
+      this.vm = api.getVirtualMachineApi(resourceGroup).get(nodeId);
+      this.storageAccountName = storageProfileToStorageAccountName.apply(vm.properties().storageProfile());
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public Image apply(ResourceDefinition input) {
+      VMImage.Builder builder = VMImage.customImage().group(resourceGroup).storage(storageAccountName).name(imageName)
+            .offer(CUSTOM_IMAGE_OFFER).location(vm.location());
+
+      Map<String, String> properties = (Map<String, String>) input.properties();
+
+      Object storageObject = properties.get("storageProfile");
+      Map<String, String> storageProperties = (Map<String, String>) storageObject;
+
+      Object osDiskObject = storageProperties.get("osDisk");
+      Map<String, String> osProperties = (Map<String, String>) osDiskObject;
+      builder.vhd1(osProperties.get("name"));
+
+      return vmImageToImage.apply(builder.build());
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
index f784842..9d9eceb 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
@@ -16,58 +16,50 @@
  */
 package org.jclouds.azurecompute.arm.compute.functions;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_PASSWORD;
-import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_USERNAME;
+import java.util.Set;
 
-import com.google.common.base.Supplier;
-import com.google.common.collect.FluentIterable;
+import org.jclouds.azurecompute.arm.domain.ImageReference;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.collect.Memoized;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.ImageBuilder;
 import org.jclouds.compute.domain.OperatingSystem;
 import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.domain.Location;
+import org.jclouds.location.predicates.LocationPredicates;
 
 import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.FluentIterable;
 import com.google.inject.Inject;
-import org.jclouds.domain.Credentials;
-import org.jclouds.domain.Location;
-import org.jclouds.domain.LoginCredentials;
-import org.jclouds.location.predicates.LocationPredicates;
 
-import java.util.Set;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 public class VMImageToImage implements Function<VMImage, Image> {
 
-   private static final String UNRECOGNIZED = "UNRECOGNIZED";
-
    private static final String UBUNTU = "Ubuntu";
-
    private static final String WINDOWS = "Windows";
-
    private static final String OPENLOGIC = "openLogic";
-
    private static final String CENTOS = "CentOS";
-
    private static final String COREOS = "CoreOS";
-
    private static final String OPENSUSE = "openSUSE";
-
    private static final String SUSE = "SUSE";
-
-   private static final String SQL_SERVER = "SQL Server";
-
-   private static final String ORACLE_lINUX = "Oracle Linux";
+   private static final String SLES = "SLES";
+   private static final String ORACLE_lINUX = "Oracle-Linux";
+   private static final String RHEL = "RHEL";
 
    private final Supplier<Set<? extends org.jclouds.domain.Location>> locations;
 
+   public static String encodeFieldsToUniqueId(boolean globallyAvailable, String locatioName, ImageReference imageReference){
+      return (globallyAvailable ? "global" : locatioName) + "/" + imageReference.publisher() + "/" + imageReference.offer() + "/" + imageReference.sku();
+   }
+   
    public static String encodeFieldsToUniqueId(VMImage imageReference){
       return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.publisher() + "/" + imageReference.offer() + "/" + imageReference.sku();
    }
 
    public static String encodeFieldsToUniqueIdCustom(VMImage imageReference){
-      return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.group() + "/" + imageReference.storage() + "/" + imageReference.vhd1() + "/" + imageReference.offer();
+      return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.group() + "/" + imageReference.storage() + "/" + imageReference.offer() + "/" + imageReference.name();
    }
 
    public static VMImage decodeFieldsFromUniqueId(final String id) {
@@ -79,10 +71,10 @@ public class VMImageToImage implements Function<VMImage, Image> {
          0: imageReference.location) + "/" +
          1: imageReference.group + "/" +
          2: imageReference.storage + "/" +
-         3: imageReference.vhd1 + "/" +
-         4: imageReference.offer
+         3: imageReference.offer + "/" +
+         4: imageReference.name
          */
-         vmImage = VMImage.create(fields[1], fields[2], fields[3], null, null, fields[4], fields[0]);
+         vmImage = VMImage.customImage().location(fields[0]).group(fields[1]).storage(fields[2]).vhd1(fields[3]).offer(fields[4]).build();
       } else {
          /* id fields indexes
          0: imageReference.location) + "/" +
@@ -90,7 +82,7 @@ public class VMImageToImage implements Function<VMImage, Image> {
          2: imageReference.offer + "/" +
          3: imageReference.sku + "/" +
          */
-         vmImage = VMImage.create(fields[1], fields[2], fields[3], null, fields[0]);
+         vmImage = VMImage.azureImage().location(fields[0]).publisher(fields[1]).offer(fields[2]).sku(fields[3]).build();
       }
       return vmImage;
    }
@@ -102,26 +94,21 @@ public class VMImageToImage implements Function<VMImage, Image> {
 
    @Override
    public Image apply(final VMImage image) {
-
-      Credentials credentials = new Credentials(AZURE_LOGIN_USERNAME, AZURE_LOGIN_PASSWORD);
       if (image.custom()) {
-
          final ImageBuilder builder = new ImageBuilder()
                .location(FluentIterable.from(locations.get())
                      .firstMatch(LocationPredicates.idEquals(image.location()))
                      .get())
                .name(image.name())
-               .description("#" + image.group())
+               .description(image.group())
                .status(Image.Status.AVAILABLE)
-               .version(image.storage())
+               .version("latest")
                .providerId(image.vhd1())
-               .id(encodeFieldsToUniqueIdCustom(image))
-               .defaultCredentials(LoginCredentials.fromCredentials(credentials));
+               .id(encodeFieldsToUniqueIdCustom(image));
 
          final OperatingSystem.Builder osBuilder = osFamily().apply(image);
          Image retimage = builder.operatingSystem(osBuilder.build()).build();
          return retimage;
-
       }
       else {
          final ImageBuilder builder = new ImageBuilder()
@@ -130,7 +117,6 @@ public class VMImageToImage implements Function<VMImage, Image> {
                .status(Image.Status.AVAILABLE)
                .version(image.sku())
                .id(encodeFieldsToUniqueId(image))
-               .defaultCredentials(LoginCredentials.fromCredentials(credentials))
                .providerId(image.publisher())
                .location(image.globallyAvailable() ? null : FluentIterable.from(locations.get())
                      .firstMatch(LocationPredicates.idEquals(image.location()))
@@ -149,11 +135,11 @@ public class VMImageToImage implements Function<VMImage, Image> {
             final String label = image.offer();
 
             OsFamily family = OsFamily.UNRECOGNIZED;
-            if (label.contains(CENTOS)) {
-               family = OsFamily.CENTOS;
-            } else if (label.contains(OPENLOGIC)) {
+            if (label.contains(CENTOS) || label.contains(OPENLOGIC)) {
                family = OsFamily.CENTOS;
-            } else if (label.contains(SUSE)) {
+            } else if (label.contains(COREOS)) {
+               family = OsFamily.COREOS;
+            } else if (label.contains(SUSE) || label.contains(SLES) || label.contains(OPENSUSE)) {
                family = OsFamily.SUSE;
             } else if (label.contains(UBUNTU)) {
                family = OsFamily.UBUNTU;
@@ -161,18 +147,16 @@ public class VMImageToImage implements Function<VMImage, Image> {
                family = OsFamily.WINDOWS;
             } else if (label.contains(ORACLE_lINUX)) {
                family = OsFamily.OEL;
+            } else if (label.contains(RHEL)) {
+               family = OsFamily.RHEL;
             }
 
-            String sku = image.sku();
-            if (image.custom())
-               sku = image.vhd1();
-
             // only 64bit OS images are supported by Azure ARM
             return OperatingSystem.builder().
                   family(family).
                   is64Bit(true).
-                  description(sku).
-                  version(sku);
+                  description(image.custom() ? image.vhd1() : image.sku()).
+                  version(image.custom() ? "latest" : image.sku());
          }
       };
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
new file mode 100644
index 0000000..e151a4a
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
@@ -0,0 +1,279 @@
+/*
+ * 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.azurecompute.arm.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.find;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Iterables.tryFind;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
+import static org.jclouds.util.Closeables2.closeQuietly;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
+import org.jclouds.azurecompute.arm.domain.IdReference;
+import org.jclouds.azurecompute.arm.domain.IpConfiguration;
+import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
+import org.jclouds.azurecompute.arm.domain.StorageProfile;
+import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
+import org.jclouds.azurecompute.arm.domain.VMImage;
+import org.jclouds.azurecompute.arm.domain.VirtualMachine;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties.ProvisioningState;
+import org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName;
+import org.jclouds.azurecompute.arm.util.BlobHelper;
+import org.jclouds.collect.Memoized;
+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.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Credentials;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> {
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   // When using the Deployment API to deploy an ARM template, the deployment
+   // goes through
+   // stages. Accepted -> Running -> Succeeded. Only when the deployment has
+   // SUCCEEDED is
+   // the resource deployed using the template actually ready.
+   //
+   // To get details about the resource(s) deployed via template, one needs to
+   // query the
+   // various resources after the deployment has "SUCCEEDED".
+   private static final Function<VirtualMachineProperties.ProvisioningState, NodeMetadata.Status> PROVISIONINGSTATE_TO_NODESTATUS = Functions
+         .forMap(
+               ImmutableMap.<VirtualMachineProperties.ProvisioningState, NodeMetadata.Status> builder()
+                     .put(VirtualMachineProperties.ProvisioningState.ACCEPTED, NodeMetadata.Status.PENDING)
+                     .put(VirtualMachineProperties.ProvisioningState.READY, NodeMetadata.Status.PENDING)
+                     .put(VirtualMachineProperties.ProvisioningState.CREATING, NodeMetadata.Status.PENDING)
+                     .put(VirtualMachineProperties.ProvisioningState.RUNNING, NodeMetadata.Status.PENDING)
+                     .put(VirtualMachineProperties.ProvisioningState.UPDATING, NodeMetadata.Status.PENDING)
+                     .put(VirtualMachineProperties.ProvisioningState.SUCCEEDED, NodeMetadata.Status.RUNNING)
+                     .put(VirtualMachineProperties.ProvisioningState.DELETED, NodeMetadata.Status.TERMINATED)
+                     .put(VirtualMachineProperties.ProvisioningState.CANCELED, NodeMetadata.Status.TERMINATED)
+                     .put(VirtualMachineProperties.ProvisioningState.FAILED, NodeMetadata.Status.ERROR)
+                     .put(VirtualMachineProperties.ProvisioningState.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED)
+                     .build(), NodeMetadata.Status.UNRECOGNIZED);
+
+   private static final Function<VirtualMachineStatus.PowerState, NodeMetadata.Status> POWERSTATE_TO_NODESTATUS = Functions
+         .forMap(
+               ImmutableMap.<PowerState, NodeMetadata.Status> builder()
+                     .put(PowerState.RUNNING, NodeMetadata.Status.RUNNING)
+                     .put(PowerState.STOPPED, NodeMetadata.Status.SUSPENDED)
+                     .put(PowerState.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).build(),
+               NodeMetadata.Status.UNRECOGNIZED);
+
+   private final String azureGroup;
+   private final AzureComputeApi api;
+   private final GroupNamingConvention nodeNamingConvention;
+   private final Supplier<Map<String, ? extends Image>> images;
+   private final Supplier<Set<? extends Location>> locations;
+   private final Supplier<Map<String, ? extends Hardware>> hardwares;
+   private final Map<String, Credentials> credentialStore;
+   private final Function<VMImage, Image> vmImageToImge;
+   private final StorageProfileToStorageAccountName storageProfileToStorageAccountName;
+
+   @Inject
+   VirtualMachineToNodeMetadata(AzureComputeApi api, GroupNamingConvention.Factory namingConvention,
+         Supplier<Map<String, ? extends Image>> images, Supplier<Map<String, ? extends Hardware>> hardwares,
+         @Memoized Supplier<Set<? extends Location>> locations, Map<String, Credentials> credentialStore,
+         final AzureComputeConstants azureComputeConstants, Function<VMImage, Image> vmImageToImge,
+         StorageProfileToStorageAccountName storageProfileToStorageAccountName) {
+      this.api = api;
+      this.nodeNamingConvention = namingConvention.createWithoutPrefix();
+      this.images = checkNotNull(images, "images cannot be null");
+      this.locations = checkNotNull(locations, "locations cannot be null");
+      this.hardwares = checkNotNull(hardwares, "hardwares cannot be null");
+      this.credentialStore = credentialStore;
+      this.azureGroup = azureComputeConstants.azureResourceGroup();
+      this.vmImageToImge = vmImageToImge;
+      this.storageProfileToStorageAccountName = storageProfileToStorageAccountName;
+   }
+
+   @Override
+   public NodeMetadata apply(VirtualMachine virtualMachine) {
+      NodeMetadataBuilder builder = new NodeMetadataBuilder();
+      builder.id(virtualMachine.name());
+      builder.providerId(virtualMachine.id());
+      builder.name(virtualMachine.name());
+      builder.hostname(virtualMachine.name());
+      String group = this.nodeNamingConvention.extractGroup(virtualMachine.name());
+      builder.group(group);
+
+      ProvisioningState provisioningState = virtualMachine.properties().provisioningState();
+      if (ProvisioningState.SUCCEEDED.equals(provisioningState)) {
+         // If the provisioning succeeded, we need to query the *real* status of
+         // the VM
+         VirtualMachineInstance instanceDetails = api.getVirtualMachineApi(azureGroup).getInstanceDetails(
+               virtualMachine.name());
+         builder.status(POWERSTATE_TO_NODESTATUS.apply(instanceDetails.powerState()));
+         builder.backendStatus(Joiner.on(',').join(
+               transform(instanceDetails.statuses(), new Function<VirtualMachineStatus, String>() {
+                  @Override
+                  public String apply(VirtualMachineStatus input) {
+                     return input.code();
+                  }
+               })));
+      } else {
+         builder.status(PROVISIONINGSTATE_TO_NODESTATUS.apply(provisioningState));
+         builder.backendStatus(provisioningState.name());
+      }
+
+      Credentials credentials = credentialStore.get("node#" + virtualMachine.name());
+      builder.credentials(LoginCredentials.fromCredentials(credentials));
+
+      builder.publicAddresses(getPublicIpAddresses(virtualMachine.properties().networkProfile().networkInterfaces()));
+      builder.privateAddresses(getPrivateIpAddresses(virtualMachine.properties().networkProfile().networkInterfaces()));
+
+      if (virtualMachine.tags() != null) {
+         Map<String, String> userMetaData = virtualMachine.tags();
+         builder.userMetadata(userMetaData);
+         builder.tags(Splitter.on(",").split(userMetaData.get("tags")));
+      }
+      String locationName = virtualMachine.location();
+      builder.location(getLocation(locationName));
+
+      Optional<? extends Image> image = findImage(virtualMachine.properties().storageProfile(), locationName);
+      if (image.isPresent()) {
+         builder.imageId(image.get().getId());
+         builder.operatingSystem(image.get().getOperatingSystem());
+      } else {
+         logger.info(">> image with id %s for virtualmachine %s was not found. "
+               + "This might be because the image that was used to create the virtualmachine has a new id.",
+               virtualMachine.id(), virtualMachine.id());
+      }
+
+      builder.hardware(getHardware(virtualMachine.properties().hardwareProfile().vmSize()));
+
+      return builder.build();
+   }
+
+   private Iterable<String> getPrivateIpAddresses(List<IdReference> idReferences) {
+      List<String> privateIpAddresses = Lists.newArrayList();
+      for (IdReference networkInterfaceCardIdReference : idReferences) {
+         NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference);
+         for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) {
+            privateIpAddresses.add(ipConfiguration.properties().privateIPAddress());
+         }
+      }
+      return privateIpAddresses;
+   }
+
+   private NetworkInterfaceCard getNetworkInterfaceCard(IdReference networkInterfaceCardIdReference) {
+      Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 2);
+      String resourceGroup = Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 4);
+      String nicName = Iterables.getLast(Splitter.on("/").split(networkInterfaceCardIdReference.id()));
+      return api.getNetworkInterfaceCardApi(resourceGroup).get(nicName);
+
+   }
+
+   private Iterable<String> getPublicIpAddresses(List<IdReference> idReferences) {
+      List<String> publicIpAddresses = Lists.newArrayList();
+      for (IdReference networkInterfaceCardIdReference : idReferences) {
+         NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference);
+         String resourceGroup = Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 4);
+         for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) {
+            if (ipConfiguration.properties().publicIPAddress() != null) {
+               String publicIpId = ipConfiguration.properties().publicIPAddress().id();
+               publicIpAddresses.add(api.getPublicIPAddressApi(resourceGroup)
+                     .get(Iterables.getLast(Splitter.on("/").split(publicIpId))).properties().ipAddress());
+            }
+         }
+      }
+      return publicIpAddresses;
+   }
+
+   protected Location getLocation(final String locationName) {
+      return find(locations.get(), new Predicate<Location>() {
+         @Override
+         public boolean apply(Location location) {
+            return locationName != null && locationName.equals(location.getId());
+         }
+      }, null);
+   }
+
+   protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName) {
+      if (storageProfile.imageReference() != null) {
+         return Optional.fromNullable(images.get().get(
+               encodeFieldsToUniqueId(false, locatioName, storageProfile.imageReference())));
+      } else {
+         String storageAccountName = storageProfileToStorageAccountName.apply(storageProfile);
+         StorageServiceKeys keys = api.getStorageAccountApi(azureGroup).getKeys(storageAccountName);
+         BlobHelper blobHelper = new BlobHelper(storageAccountName, keys.key1());
+
+         try {
+            // Custom image. Let's find it by uri
+            List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER,
+                  locatioName);
+            Optional<VMImage> customImage = tryFind(customImagesInStorage, new Predicate<VMImage>() {
+               @Override
+               public boolean apply(VMImage input) {
+                  return input.vhd1().equals(storageProfile.osDisk().image().uri());
+               }
+            });
+
+            return customImage.isPresent() ? Optional.of(vmImageToImge.apply(customImage.get())) : Optional
+                  .<Image> absent();
+         } finally {
+            closeQuietly(blobHelper);
+         }
+      }
+   }
+
+   protected Hardware getHardware(final String vmSize) {
+      return Iterables.find(hardwares.get().values(), new Predicate<Hardware>() {
+         @Override
+         public boolean apply(Hardware input) {
+            return input.getId().equals(vmSize);
+         }
+      });
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
index c5267b1..c71a7da 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
@@ -16,10 +16,12 @@
  */
 package org.jclouds.azurecompute.arm.compute.options;
 
-import static com.google.common.base.Objects.equal;
 import org.jclouds.compute.options.TemplateOptions;
+
 import com.google.common.base.Objects;
 
+import static com.google.common.base.Objects.equal;
+
 /**
  * Azure ARM custom options
  */
@@ -31,7 +33,9 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
    private String subnetAddressPrefix;
    private String DNSLabelPrefix;
    private String keyVaultIdAndSecret;
-
+   private String virtualNetworkName;
+   private String subnetId;
+   private String blob;
 
    /**
     * Custom options for the Azure ARM API
@@ -40,9 +44,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       this.customData = customData;
       return this;
    }
-   private String virtualNetworkName;
-   private String subnetId;
-
+   
    /**
     * Sets the CIDR block for virtual network
     */
@@ -75,15 +77,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       return this;
    }
 
-   public String getCustomData() { return customData; }
-   public String getVirtualNetworkAddressPrefix() { return virtualNetworkAddressPrefix; }
-   public String getSubnetAddressPrefix() { return subnetAddressPrefix; }
-   public String getDNSLabelPrefix() { return DNSLabelPrefix; }
-   public String getKeyVaultIdAndSecret() { return keyVaultIdAndSecret; }
-   public String getVirtualNetworkName() { return virtualNetworkName; }
-   public String getSubnetId() { return subnetId; }
-
-
    /**
     * Sets the virtual network name
     */
@@ -100,6 +93,24 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       return this;
    }
 
+   /**
+    * Sets the blob name
+    */
+   public  AzureTemplateOptions blob(String blob) {
+      this.blob = blob;
+      return this;
+   }
+
+   public String getCustomData() { return customData; }
+   public String getVirtualNetworkAddressPrefix() { return virtualNetworkAddressPrefix; }
+   public String getSubnetAddressPrefix() { return subnetAddressPrefix; }
+   public String getDNSLabelPrefix() { return DNSLabelPrefix; }
+   public String getKeyVaultIdAndSecret() { return keyVaultIdAndSecret; }
+   public String getVirtualNetworkName() { return virtualNetworkName; }
+   public String getSubnetId() { return subnetId; }
+   public String getBlob() { return blob; }
+
+
    @Override
    public AzureTemplateOptions clone() {
       AzureTemplateOptions options = new AzureTemplateOptions();
@@ -119,12 +130,13 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          eTo.keyVaultIdAndSecret(keyVaultIdAndSecret);
          eTo.virtualNetworkName(virtualNetworkName);
          eTo.subnetId(subnetId);
+         eTo.blob(blob);
       }
    }
 
    @Override
    public int hashCode() {
-      return Objects.hashCode(super.hashCode(), virtualNetworkAddressPrefix, subnetAddressPrefix, DNSLabelPrefix, customData, keyVaultIdAndSecret, virtualNetworkName, subnetId);
+      return Objects.hashCode(super.hashCode(), virtualNetworkAddressPrefix, subnetAddressPrefix, DNSLabelPrefix, customData, keyVaultIdAndSecret, virtualNetworkName, subnetId, blob);
    }
 
    @Override
@@ -146,7 +158,8 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
             && equal(this.DNSLabelPrefix, other.DNSLabelPrefix)
             && equal(this.keyVaultIdAndSecret, other.keyVaultIdAndSecret)
             && equal(this.virtualNetworkName, other.virtualNetworkName)
-            && equal(this.subnetId, other.subnetId);
+            && equal(this.subnetId, other.subnetId)
+            && equal(this.blob, other.blob);
    }
 
    @Override
@@ -159,6 +172,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       toString.add("keyVaultIdAndSecret", keyVaultIdAndSecret);
       toString.add("virtualNetworkName", virtualNetworkName);
       toString.add("subnetId", subnetId);
+      toString.add("blob", blob);
       return toString;
    }
 
@@ -219,5 +233,13 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          AzureTemplateOptions options = new AzureTemplateOptions();
          return options.subnetId(subnetId);
       }
+
+      /**
+       * @see AzureTemplateOptions#blob
+       */
+      public static AzureTemplateOptions blob(String blob) {
+         AzureTemplateOptions options = new AzureTemplateOptions();
+         return options.blob(blob);
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/predicates/IsDeploymentInRegions.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/predicates/IsDeploymentInRegions.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/predicates/IsDeploymentInRegions.java
index 57a0678..66590e1 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/predicates/IsDeploymentInRegions.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/predicates/IsDeploymentInRegions.java
@@ -40,6 +40,7 @@ public class IsDeploymentInRegions implements Predicate<Deployment> {
 
    @Override
    public boolean apply(Deployment deployment) {
+      if (deployment.properties() == null || deployment.properties().parameters() == null || deployment.properties().parameters().get("location") == null) return false;
       Value locationValue = deployment.properties().parameters().get("location");
       return regionIds.get().contains(locationValue.value());
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/AzurePopulateDefaultLoginCredentialsForImageStrategy.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/AzurePopulateDefaultLoginCredentialsForImageStrategy.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/AzurePopulateDefaultLoginCredentialsForImageStrategy.java
deleted file mode 100644
index 55d1a3c..0000000
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/AzurePopulateDefaultLoginCredentialsForImageStrategy.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.azurecompute.arm.compute.strategy;
-
-import org.jclouds.compute.domain.internal.ImageImpl;
-import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
-import org.jclouds.domain.Credentials;
-import org.jclouds.domain.LoginCredentials;
-
-import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_PASSWORD;
-import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_USERNAME;
-
-public class AzurePopulateDefaultLoginCredentialsForImageStrategy implements PopulateDefaultLoginCredentialsForImageStrategy {
-   @Override
-   public LoginCredentials apply(Object o) {
-      ImageImpl node = (ImageImpl)o;
-      String username = AZURE_LOGIN_USERNAME;
-      String password = AZURE_LOGIN_PASSWORD;
-      if (username == null) {
-         username = "jclouds";
-      }
-      if (password == null) {
-         password = "Password1!";
-      }
-      Credentials creds = new Credentials(username, password);
-      LoginCredentials credentials = LoginCredentials.fromCredentials(creds);
-      return credentials;
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
index 468b87c..99528fd 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
@@ -17,26 +17,36 @@
 package org.jclouds.azurecompute.arm.compute.strategy;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
+import static org.jclouds.util.Predicates2.retry;
 
+import java.net.URI;
 import java.util.Arrays;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 
 import javax.annotation.Resource;
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
-import com.google.common.collect.ImmutableMap;
 import org.jclouds.Constants;
+import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
+import org.jclouds.azurecompute.arm.domain.StorageService;
 import org.jclouds.azurecompute.arm.domain.Subnet;
+import org.jclouds.azurecompute.arm.domain.VMImage;
+import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
 import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
 import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
+import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
 import org.jclouds.compute.config.CustomizationResponse;
+import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.functions.GroupNamingConvention;
@@ -45,9 +55,11 @@ 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.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
 import org.jclouds.logging.Logger;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Multimap;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
@@ -81,7 +93,13 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
    public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template,
                                                  Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
                                                  Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
-
+      // If there is a script to be run on the node and public key
+      // authentication has been configured, warn users if the private key
+      // is not present
+      if (hasRunScriptWithKeyAuthAndNoPrivateKey(template)) {
+         logger.warn(">> a runScript was configured but no SSH key has been provided. " +
+                 "Authentication will delegate to the ssh-agent");
+      }
       String azureGroupName = this.azureComputeConstants.azureResourceGroup();
 
       AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class);
@@ -91,7 +109,7 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
       final String location = template.getLocation().getId();
 
       if (resourceGroup == null){
-         final Map<String, String> tags = ImmutableMap.of("description", "jClouds managed VMs");
+         final Map<String, String> tags = ImmutableMap.of("description", "jclouds managed VMs");
          resourceGroupApi.create(azureGroupName, location, tags).name();
       }
 
@@ -104,7 +122,10 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
 
       this.getOrCreateVirtualNetworkWithSubnet(vnetName, subnetName, location, options, azureGroupName);
 
-
+      StorageService storageService = getOrCreateStorageService(group, azureGroupName, location, template.getImage());
+      String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
+      options.blob(blob);
+      
       Map<?, ListenableFuture<Void>> responses = super.execute(group, count, template, goodNodes, badNodes,
               customizationResponses);
 
@@ -135,6 +156,70 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
 
       options.virtualNetworkName(virtualNetworkName);
       options.subnetId(subnet.id());
+   }
+
+   private static boolean hasRunScriptWithKeyAuthAndNoPrivateKey(Template template) {
+      return template.getOptions().getRunScript() != null && template.getOptions().getPublicKey() != null
+              && !template.getOptions().hasLoginPrivateKeyOption();
+   }
+
+   public StorageService getOrCreateStorageService(String name, String resourceGroupName, String locationName, Image image) {
+      String storageAccountName = null;
+      VMImage imageRef = decodeFieldsFromUniqueId(image.getId());
+      if (imageRef.custom()) {
+         storageAccountName = imageRef.storage();
+      }
+
+      if (Strings.isNullOrEmpty(storageAccountName)) {
+         storageAccountName = generateStorageAccountName(name);
+      }
+
+      StorageService storageService = api.getStorageAccountApi(resourceGroupName).get(storageAccountName);
+      if (storageService != null) return storageService;
+
+      URI uri = api.getStorageAccountApi(resourceGroupName).create(storageAccountName, locationName, ImmutableMap.of("jclouds",
+              name), ImmutableMap.of("accountType", StorageService.AccountType.Standard_LRS.toString()));
+      boolean starageAccountCreated = retry(new Predicate<URI>() {
+         @Override
+         public boolean apply(URI uri) {
+            return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri);
+         }
+      }, 60 * 2 * 1000 /* 2 minutes timeout */).apply(uri);
+      // TODO check provisioning state of the primary
+      checkState(starageAccountCreated, "Storage account %s was not created in the configured timeout",
+            storageAccountName);
+      return api.getStorageAccountApi(resourceGroupName).get(storageAccountName);
+   }
+
+   /**
+    * Generates a valid storage account
+    *
+    * Storage account names must be between 3 and 24 characters in length and may contain numbers and lowercase letters only.
+    *
+    * @param name the node name
+    * @return the storage account name starting from a sanitized name (with only numbers and lowercase letters only ).
+    * If sanitized name is between 3 and 24 characters, storage account name is equals to sanitized name.
+    * If sanitized name is less than 3 characters, storage account is sanitized name plus 4 random chars.
+    * If sanitized name is more than 24 characters, storage account is first 10 chars of sanitized name plus 4 random chars plus last 10 chars of sanitized name.
+    */
+   public static String generateStorageAccountName(String name) {
+      String random = UUID.randomUUID().toString().substring(0, 4);
+      String storageAccountName = new StringBuilder().append(name).append(random).toString();
+      String sanitizedStorageAccountName = storageAccountName.replaceAll("[^a-z0-9]", "");
+      int nameLength = sanitizedStorageAccountName.length();
+      if (nameLength >= 3 && nameLength <= 24) {
+         return sanitizedStorageAccountName;
+      }
+
+      if (nameLength > 24) {
+         sanitizedStorageAccountName = shorten(storageAccountName, random);
+      }
+      return sanitizedStorageAccountName;
+   }
 
+   private static String shorten(String storageAccountName, String random) {
+      String prefix = storageAccountName.substring(0, 10);
+      String suffix = storageAccountName.substring(storageAccountName.length() - 10, storageAccountName.length());
+      return String.format("%s%s%s", prefix, random, suffix);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
index bd1750f..991c738 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
@@ -18,7 +18,6 @@ package org.jclouds.azurecompute.arm.config;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.handlers.AzureComputeErrorHandler;
-import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
 import org.jclouds.http.HttpErrorHandler;
 import org.jclouds.http.annotation.ClientError;
 import org.jclouds.http.annotation.Redirection;
@@ -30,7 +29,6 @@ import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.config.HttpApiModule;
 
 import com.google.inject.Scopes;
-import com.google.inject.assistedinject.FactoryModuleBuilder;
 
 @ConfiguresHttpApi
 public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
@@ -51,7 +49,6 @@ public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
 
    @Override
    protected void configure() {
-      install(new FactoryModuleBuilder().build(DeploymentTemplateBuilder.Factory.class));
       super.configure();
       bind(OAuthScopes.class).toInstance(OAuthScopes.NoScopes.create());
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
index e5ef5cd..8f945d9 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
@@ -17,10 +17,13 @@
 package org.jclouds.azurecompute.arm.config;
 
 /**
- * Configuration properties and constants used in Azure Resource Manager connections.
+ * Configuration properties and constants used in Azure Resource Manager
+ * connections.
  */
 public class AzureComputeProperties {
 
+   public static final String STORAGE_API_VERSION = "2015-06-15";
+
    public static final String OPERATION_TIMEOUT = "jclouds.azurecompute.arm.operation.timeout";
 
    public static final String OPERATION_POLL_INITIAL_PERIOD = "jclouds.azurecompute.arm.operation.poll.initial.period";
@@ -31,8 +34,6 @@ public class AzureComputeProperties {
 
    public static final String TCP_RULE_REGEXP = "jclouds.azurecompute.arm.tcp.rule.regexp";
 
-   public static final String STORAGE_API_VERSION = "2015-06-15";
-
    public static final String RESOURCE_GROUP_NAME = "jclouds.azurecompute.arm.operation.resourcegroup";
 
    public static final String IMAGE_PUBLISHERS = "jclouds.azurecompute.arm.publishers";
@@ -47,4 +48,6 @@ public class AzureComputeProperties {
 
    public static final String DEFAULT_DATADISKSIZE = "jclouds.azurecompute.arm.datadisksize";
 
+   public static final String API_VERSION_PREFIX = "jclouds.azurecompute.arm.apiversion.";
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMDeployment.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMDeployment.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMDeployment.java
index 948e69b..99edc5c 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMDeployment.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMDeployment.java
@@ -16,43 +16,29 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
+import java.util.List;
+
 import org.jclouds.javax.annotation.Nullable;
 
-import java.util.List;
-import java.util.Map;
+import com.google.auto.value.AutoValue;
 
 @AutoValue
 public abstract class VMDeployment {
 
-   public abstract Deployment deployment();
-
-   @Nullable
-   public abstract List<PublicIPAddress> ipAddressList();
-
-   @Nullable
-   public abstract VirtualMachineInstance vm();
-
+   public abstract String deploymentId();
+   
    @Nullable
    public abstract VirtualMachine virtualMachine();
-
-   @Nullable
-   public abstract List<NetworkInterfaceCard> networkInterfaceCards();
-
+   
    @Nullable
-   public abstract Map<String, String> userMetaData();
+   public abstract List<PublicIPAddress> ipAddressList();
 
    @Nullable
-   public abstract Iterable<String> tags();
-
-   public static VMDeployment create(Deployment deployment) {
-      return create(deployment, null, null, null, null, null, null);
-   }
+   public abstract List<NetworkInterfaceCard> networkInterfaceCards();
 
-   public static VMDeployment create(Deployment deployment, List<PublicIPAddress> ipAddressList,
-                                     VirtualMachineInstance vm, VirtualMachine virtualMachine,
-                                     List<NetworkInterfaceCard> networkInterfaceCards, Map<String, String> userMetaData,
-                                     Iterable<String> tags) {
-      return new AutoValue_VMDeployment(deployment, ipAddressList, vm, virtualMachine, networkInterfaceCards, userMetaData, tags);
+   public static VMDeployment create(String deploymentId, VirtualMachine virtualMachine,
+                                     List<PublicIPAddress> ipAddressList,
+                                     List<NetworkInterfaceCard> networkInterfaceCards) {
+      return new AutoValue_VMDeployment(deploymentId, virtualMachine, ipAddressList, networkInterfaceCards);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
index c83eafe..e4f2301 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
@@ -16,9 +16,9 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
 import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
 
 @AutoValue
 public abstract class VMImage {
@@ -91,16 +91,35 @@ public abstract class VMImage {
     * True if custom image
     */
    public abstract boolean custom();
-
-   @SerializedNames({ "publisher", "offer", "sku", "version", "location"})
-   public static VMImage create(String publisher, String offer, String sku, String version, String location) {
-
-      return new AutoValue_VMImage(publisher, offer, sku, version, location, false, null, null, null, null, null, false);
+   
+   public static Builder builder() {
+      return new AutoValue_VMImage.Builder();
    }
-
-   @SerializedNames({ "group", "storage", "vhd1", "vhd2", "name", "offer", "location"})
-   public static VMImage create(String group, String storage, String vhd1, String vhd2, String name, String offer, String location) {
-
-      return new AutoValue_VMImage(null, offer, null, null, location, false, group, storage, vhd1, vhd2, name, true);
+   
+   public static Builder azureImage() {
+      return new AutoValue_VMImage.Builder().globallyAvailable(false).custom(false);
+   }
+   
+   public static Builder customImage() {
+      return new AutoValue_VMImage.Builder().globallyAvailable(false).custom(true);
+   }
+   
+   @AutoValue.Builder
+   public abstract static class Builder {
+      
+      public abstract Builder publisher(String published);
+      public abstract Builder offer(String offer);
+      public abstract Builder sku(String sku);
+      public abstract Builder version(String version);
+      public abstract Builder location(String location);
+      public abstract Builder globallyAvailable(boolean globallyAvailable);
+      public abstract Builder group(String group);
+      public abstract Builder storage(String storage);
+      public abstract Builder vhd1(String vhd1);
+      public abstract Builder vhd2(String vhd2);
+      public abstract Builder name(String name);
+      public abstract Builder custom(boolean custom);
+      
+      public abstract VMImage build();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java
index 3013543..10fa231 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java
@@ -16,12 +16,13 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
-import java.util.Map;
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
 
 /**
  * A virtual machine  that is valid for your subscription.

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineInstance.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineInstance.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineInstance.java
index b0ed6d5..1c11e4d 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineInstance.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineInstance.java
@@ -16,13 +16,23 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableList;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.getFirst;
+import static com.google.common.collect.Iterables.transform;
+import static org.jclouds.util.Predicates2.startsWith;
+
+import java.util.Date;
 import java.util.List;
+
+import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties.ProvisioningState;
+import org.jclouds.azurecompute.arm.util.GetEnumValue;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
-import java.util.Date;
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
 
 /**
  * A virtual machine instance view that is valid for your subscription.
@@ -30,8 +40,21 @@ import java.util.Date;
 @AutoValue
 public abstract class VirtualMachineInstance {
 
-   @AutoValue
+   @com.google.auto.value.AutoValue
    public abstract static class VirtualMachineStatus {
+      
+      public static final String PROVISIONING_STATE_PREFIX = "ProvisioningState/";
+      public static final String POWER_STATE_PREFIX = "PowerState/";
+      
+      public enum PowerState {
+         RUNNING,
+         STOPPED,
+         UNRECOGNIZED;
+
+         public static PowerState fromValue(final String text) {
+            return (PowerState) GetEnumValue.fromValueOrDefault(text, PowerState.UNRECOGNIZED);
+         }
+      }
 
       @Nullable
       public abstract String code();
@@ -61,6 +84,26 @@ public abstract class VirtualMachineInstance {
 
    @Nullable
    public abstract List<VirtualMachineStatus> statuses();
+   
+   public ProvisioningState provisioningState() {
+      return ProvisioningState.fromValue(firstStatus(VirtualMachineStatus.PROVISIONING_STATE_PREFIX));
+   }
+   
+   public PowerState powerState() {
+      return PowerState.fromValue(firstStatus(VirtualMachineStatus.POWER_STATE_PREFIX));
+   }
+   
+   private String firstStatus(final String type) {
+      return getFirst(transform(filter(transform(statuses(), new Function<VirtualMachineStatus, String>() {
+         @Override public String apply(VirtualMachineStatus input) {
+            return input.code();
+         }
+      }), startsWith(type)), new Function<String, String>() {
+         @Override public String apply(String input) {
+            return input.substring(type.length());
+         }
+      }), null);
+   }
 
 
    @SerializedNames({"platformUpdateDomain", "platformFaultDomain", "statuses"})

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineProperties.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineProperties.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineProperties.java
index 73afd14..eb9520a 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineProperties.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineProperties.java
@@ -16,16 +16,35 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
+import org.jclouds.azurecompute.arm.util.GetEnumValue;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
+import com.google.auto.value.AutoValue;
+
 /**
  * A virtual machine properties for the virtual machine.
  */
 @AutoValue
 public abstract class VirtualMachineProperties {
 
+   public enum ProvisioningState {
+      ACCEPTED,
+      CREATING,
+      READY,
+      CANCELED,
+      FAILED,
+      DELETED,
+      SUCCEEDED,
+      RUNNING,
+      UPDATING,
+      UNRECOGNIZED;
+
+      public static ProvisioningState fromValue(final String text) {
+         return (ProvisioningState) GetEnumValue.fromValueOrDefault(text, ProvisioningState.UNRECOGNIZED);
+      }
+   }
+
    /**
     * The id of the virtual machine.
     */
@@ -78,7 +97,7 @@ public abstract class VirtualMachineProperties {
     * The provisioning state of the VM
     */
    @Nullable
-   public abstract String provisioningState();
+   public abstract ProvisioningState provisioningState();
 
    @SerializedNames({"vmId", "licenseType", "availabilitySet", "hardwareProfile", "storageProfile", "osProfile",
            "networkProfile", "diagnosticsProfile", "provisioningState"})
@@ -90,7 +109,7 @@ public abstract class VirtualMachineProperties {
                                                  final OSProfile osProfile,
                                                  final NetworkProfile networkProfile,
                                                  final DiagnosticsProfile diagnosticsProfile,
-                                                 final String provisioningState) {
+                                                 final ProvisioningState provisioningState) {
       return builder()
               .vmId(vmId)
               .licenseType(licenseType)
@@ -126,7 +145,7 @@ public abstract class VirtualMachineProperties {
 
       public abstract Builder diagnosticsProfile(DiagnosticsProfile diagnosticsProfile);
 
-      public abstract Builder provisioningState(String provisioningState);
+      public abstract Builder provisioningState(ProvisioningState provisioningState);
 
       public abstract VirtualMachineProperties build();
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
index 33c929a..8d446a5 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
@@ -34,12 +34,12 @@ import org.jclouds.Fallbacks;
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.azurecompute.arm.domain.Deployment;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.functions.URIParser;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.Payload;
 import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.QueryParams;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
 import org.jclouds.rest.annotations.SelectJson;
@@ -50,8 +50,7 @@ import org.jclouds.rest.annotations.SelectJson;
  * - get information about deployment
  */
 @Path("/resourcegroups/{resourcegroup}/providers/microsoft.resources/deployments")
-@QueryParams(keys = "api-version", values = "2016-02-01")
-@RequestFilters(OAuthFilter.class)
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface DeploymentApi {
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
index f2858d9..3c3bab9 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
@@ -18,19 +18,20 @@ package org.jclouds.azurecompute.arm.features;
 import java.io.Closeable;
 import java.net.URI;
 import java.util.List;
+
 import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
 import javax.ws.rs.GET;
+import javax.ws.rs.core.MediaType;
 
 import org.jclouds.Fallbacks;
 import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
+import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
+import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.EndpointParam;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
-import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus;
 import org.jclouds.rest.annotations.SelectJson;
 
 /**

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LocationApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LocationApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LocationApi.java
index 8f31d31..257293c 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LocationApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LocationApi.java
@@ -27,11 +27,11 @@ import javax.ws.rs.core.MediaType;
 
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
 import org.jclouds.azurecompute.arm.domain.Location;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
-import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.Fallback;
 
 /**
  * This Azure Resource Manager API provides all of the locations that are available for resource providers
@@ -40,8 +40,7 @@ import org.jclouds.rest.annotations.Fallback;
  * @see <a href="https://msdn.microsoft.com/en-US/library/azure/dn790540.aspx">docs</a>
  */
 @Path("/locations")
-@RequestFilters(OAuthFilter.class)
-@QueryParams(keys = "api-version", values = "2015-11-01")
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Produces(MediaType.APPLICATION_JSON)
 @Consumes(MediaType.APPLICATION_JSON)
 public interface LocationApi {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApi.java
index 2f19996..c135e9e 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApi.java
@@ -16,38 +16,37 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Named;
+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.core.MediaType;
+
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.functions.URIParser;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.MapBinder;
 import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.QueryParams;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
 import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.binders.BindToJsonPayload;
 
-import javax.inject.Named;
-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.core.MediaType;
-import java.util.List;
-import java.util.Map;
-import java.net.URI;
-
 @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkInterfaces")
-@QueryParams(keys = "api-version", values = "2015-06-15")
-@RequestFilters(OAuthFilter.class)
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
-
 public interface NetworkInterfaceCardApi {
 
    @Named("networkinterfacecard:list")

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java
index e6b310d..ba4c2cd 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java
@@ -16,40 +16,38 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Named;
+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.Fallbacks.EmptyListOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.functions.URIParser;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
-
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
 import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.binders.BindToJsonPayload;
 
-import javax.inject.Named;
-import javax.ws.rs.Produces;
-import javax.ws.rs.Path;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.PUT;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-
 @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkSecurityGroups")
-
-@QueryParams(keys = "api-version", values = "2016-03-30")
-@RequestFilters(OAuthFilter.class)
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface NetworkSecurityGroupApi {
 
@@ -72,9 +70,8 @@ public interface NetworkSecurityGroupApi {
    @MapBinder(BindToJsonPayload.class)
    @Produces(MediaType.APPLICATION_JSON)
    NetworkSecurityGroup createOrUpdate(@PathParam("networksecuritygroupname") String nsgName,
-                                       @PayloadParam("location") String location,
-                                       @Nullable @PayloadParam("tags") Map<String, String> tags,
-                                       @PayloadParam("properties")NetworkSecurityGroupProperties properties);
+         @PayloadParam("location") String location, @Nullable @PayloadParam("tags") Map<String, String> tags,
+         @PayloadParam("properties") NetworkSecurityGroupProperties properties);
 
    @Named("networksecuritygroup:get")
    @Path("/{networksecuritygroupname}")
@@ -82,4 +79,3 @@ public interface NetworkSecurityGroupApi {
    @Fallback(NullOnNotFoundOr404.class)
    NetworkSecurityGroup get(@PathParam("networksecuritygroupname") String nsgName);
 }
-

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java
index 2edd3df..8def4e3 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java
@@ -16,38 +16,36 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import java.net.URI;
+import java.util.List;
+
+import javax.inject.Named;
+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.Fallbacks.EmptyListOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.functions.URIParser;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
-
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
 import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.binders.BindToJsonPayload;
 
-import javax.inject.Named;
-import javax.ws.rs.Produces;
-import javax.ws.rs.Path;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.PUT;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.core.MediaType;
-import java.util.List;
-import java.net.URI;
-
 @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkSecurityGroups/{networksecuritygroup}")
-
-@QueryParams(keys = "api-version", values = "2016-03-30")
-@RequestFilters(OAuthFilter.class)
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface NetworkSecurityRuleApi {
    @Named("networksecurityrule:createOrUpdate")

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/OSImageApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/OSImageApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/OSImageApi.java
index 96dce6b..c8fb3f3 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/OSImageApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/OSImageApi.java
@@ -31,17 +31,16 @@ import org.jclouds.azurecompute.arm.domain.Offer;
 import org.jclouds.azurecompute.arm.domain.Publisher;
 import org.jclouds.azurecompute.arm.domain.SKU;
 import org.jclouds.azurecompute.arm.domain.Version;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.QueryParams;
 import org.jclouds.rest.annotations.RequestFilters;
 
 /**
  * The Azure Resource Management API includes operations for managing the OS images in your subscription.
  */
 @Path("/providers/Microsoft.Compute/locations/{location}")
-@RequestFilters(OAuthFilter.class)
-@QueryParams(keys = "api-version", values = "2015-06-15")
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(APPLICATION_JSON)
 public interface OSImageApi {
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApi.java
index 2e19fe2..2693753 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApi.java
@@ -16,37 +16,36 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Named;
+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.core.MediaType;
+
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.functions.FalseOn204;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.MapBinder;
 import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.QueryParams;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
 import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.binders.BindToJsonPayload;
 
-import javax.inject.Named;
-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.core.MediaType;
-import java.util.List;
-import java.util.Map;
-
 @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/publicIPAddresses")
-@QueryParams(keys = "api-version", values = "2015-06-15")
-@RequestFilters(OAuthFilter.class)
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
-
 public interface PublicIPAddressApi {
 
    @Named("publicipaddress:list")

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java
index 1ad47d9..6f718a5 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java
@@ -19,32 +19,31 @@ import java.io.Closeable;
 import java.net.URI;
 import java.util.List;
 import java.util.Map;
+
 import javax.inject.Named;
 import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
 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.Fallbacks.EmptyListOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.azurecompute.arm.functions.URIParser;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.MapBinder;
-import org.jclouds.rest.annotations.PayloadParam;
 import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.azurecompute.arm.functions.URIParser;
-
-
+import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.binders.BindToJsonPayload;
 
 /**
@@ -53,9 +52,7 @@ import org.jclouds.rest.binders.BindToJsonPayload;
  * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn790546.aspx">docs</a>
  */
 @Path("/resourcegroups")
-
-@QueryParams(keys = "api-version", values = "2015-01-01")
-@RequestFilters(OAuthFilter.class)
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface ResourceGroupApi extends Closeable{
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java
index e3d38b8..a25e2a5 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java
@@ -17,14 +17,8 @@
 package org.jclouds.azurecompute.arm.features;
 
 
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.oauth.v2.filters.OAuthFilter;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
+import java.io.Closeable;
+import java.util.List;
 
 import javax.inject.Named;
 import javax.ws.rs.Consumes;
@@ -32,8 +26,15 @@ import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.core.MediaType;
-import java.io.Closeable;
-import java.util.List;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
 
 /**
  * The Azure Resource Provider API provides information about a resource provider and its supported resource types.
@@ -42,8 +43,7 @@ import java.util.List;
  */
 @Path("/providers")
 
-@QueryParams(keys = "api-version", values = "2015-01-01")
-@RequestFilters(OAuthFilter.class)
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface ResourceProviderApi extends Closeable {
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
index fd75fca..5d2e06c 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
@@ -16,15 +16,19 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
 import javax.inject.Named;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
 import javax.ws.rs.Consumes;
-import javax.ws.rs.PUT;
-import javax.ws.rs.POST;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+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.Fallbacks;
@@ -32,35 +36,28 @@ import org.jclouds.azurecompute.arm.domain.Availability;
 import org.jclouds.azurecompute.arm.domain.StorageService;
 import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.StorageServiceUpdateParams;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.functions.FalseOn204;
 import org.jclouds.azurecompute.arm.functions.URIParser;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.MapBinder;
 import org.jclouds.rest.annotations.PATCH;
-import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.Payload;
 import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.binders.BindToJsonPayload;
 
-import java.util.List;
-import java.util.Map;
-import java.net.URI;
-
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION;
-
 /**
  * The Azure Resource Management API includes operations for managing the storage accounts in your subscription.
  *
  * @see <a href="https://msdn.microsoft.com/en-us/library/mt163683.aspx">docs</a>
  */
 @Path("/")
-@RequestFilters(OAuthFilter.class)
-@QueryParams(keys = "api-version", values = STORAGE_API_VERSION)
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface StorageAccountApi {
 


[4/4] jclouds-labs git commit: Refactored Azure ARM to not use Deployments

Posted by na...@apache.org.
Refactored Azure ARM to not use Deployments

* Simplified ImageExtension
* Fixed access to deployed VMS
* Made api-version configurable for all apis"
* Fixed all feature live tests
* Fixed the AzureComputeServiceLiveTest
* Fixed the AzureTemplateBuilderLiveTest
* Fixed the AzureComputeImageExtensionLiveTest


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/2f110387
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/2f110387
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/2f110387

Branch: refs/heads/azure-rebased
Commit: 2f110387381c4778c68c2287f616193d6474bd5f
Parents: 5742745
Author: Andrea Turli <an...@gmail.com>
Authored: Wed Sep 28 18:20:26 2016 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Fri Oct 14 11:43:00 2016 +0200

----------------------------------------------------------------------
 azurecompute-arm/README.md                      |   6 +-
 azurecompute-arm/pom.xml                        |   7 +-
 .../azurecompute/arm/AzureComputeApi.java       |  17 +-
 .../arm/AzureComputeProviderMetadata.java       |  68 ++-
 .../arm/compute/AzureComputeServiceAdapter.java | 348 ++++++-----
 .../AzureComputeServiceContextModule.java       | 143 +++--
 .../extensions/AzureComputeImageExtension.java  | 178 +++---
 .../functions/DeploymentToNodeMetadata.java     | 244 --------
 .../functions/DeploymentToVMDeployment.java     | 121 ----
 .../ResourceDefinitionToCustomImage.java        |  78 +++
 .../arm/compute/functions/VMImageToImage.java   |  76 +--
 .../functions/VirtualMachineToNodeMetadata.java | 279 +++++++++
 .../compute/options/AzureTemplateOptions.java   |  54 +-
 .../predicates/IsDeploymentInRegions.java       |   1 +
 ...DefaultLoginCredentialsForImageStrategy.java |  43 --
 .../CreateResourceGroupThenCreateNodes.java     |  97 +++-
 .../arm/config/AzureComputeHttpApiModule.java   |   3 -
 .../arm/config/AzureComputeProperties.java      |   9 +-
 .../azurecompute/arm/domain/VMDeployment.java   |  38 +-
 .../azurecompute/arm/domain/VMImage.java        |  43 +-
 .../azurecompute/arm/domain/VirtualMachine.java |   7 +-
 .../arm/domain/VirtualMachineInstance.java      |  51 +-
 .../arm/domain/VirtualMachineProperties.java    |  27 +-
 .../arm/features/DeploymentApi.java             |   5 +-
 .../azurecompute/arm/features/JobApi.java       |   7 +-
 .../azurecompute/arm/features/LocationApi.java  |   7 +-
 .../arm/features/NetworkInterfaceCardApi.java   |  31 +-
 .../arm/features/NetworkSecurityGroupApi.java   |  46 +-
 .../arm/features/NetworkSecurityRuleApi.java    |  38 +-
 .../azurecompute/arm/features/OSImageApi.java   |   5 +-
 .../arm/features/PublicIPAddressApi.java        |  29 +-
 .../arm/features/ResourceGroupApi.java          |  19 +-
 .../arm/features/ResourceProviderApi.java       |  24 +-
 .../arm/features/StorageAccountApi.java         |  35 +-
 .../azurecompute/arm/features/SubnetApi.java    |  33 +-
 .../azurecompute/arm/features/VMSizeApi.java    |  20 +-
 .../arm/features/VirtualMachineApi.java         |  35 +-
 .../arm/features/VirtualNetworkApi.java         |  35 +-
 .../arm/filters/ApiVersionFilter.java           |  90 +++
 .../arm/functions/CleanupResources.java         | 210 ++++---
 .../StorageProfileToStorageAccountName.java     |  38 ++
 .../azurecompute/arm/util/BlobHelper.java       |  86 ++-
 .../arm/util/DeploymentTemplateBuilder.java     | 573 -------------------
 .../azurecompute/arm/util/GetEnumValue.java     |   1 -
 .../compute/AzureComputeServiceLiveTest.java    |  76 ++-
 .../compute/AzureTemplateBuilderLiveTest.java   |  49 +-
 .../AzureComputeImageExtensionLiveTest.java     |  69 +--
 .../arm/features/DeploymentApiLiveTest.java     |  92 ++-
 .../features/DeploymentTemplateBuilderTest.java | 287 ----------
 .../NetworkSecurityGroupApiMockTest.java        |   2 -
 .../features/PublicIPAddressApiMockTest.java    |   3 +-
 .../features/ResourceProviderAPIMockTest.java   |   1 -
 .../arm/features/StorageAccountApiMockTest.java |  35 --
 .../arm/features/SubnetApiMockTest.java         |  17 +-
 .../TemplateToDeploymentTemplateLiveTest.java   | 281 ---------
 .../arm/features/VirtualMachineApiLiveTest.java |  71 +--
 .../arm/features/VirtualMachineApiMockTest.java |  47 +-
 .../arm/features/VirtualNetworkApiMockTest.java |   2 +-
 .../arm/filters/ApiVersionFilterTest.java       | 129 +++++
 .../internal/BaseAzureComputeApiMockTest.java   |  19 +-
 60 files changed, 1881 insertions(+), 2604 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/README.md
----------------------------------------------------------------------
diff --git a/azurecompute-arm/README.md b/azurecompute-arm/README.md
index b1c0916..a5a9956 100644
--- a/azurecompute-arm/README.md
+++ b/azurecompute-arm/README.md
@@ -32,8 +32,7 @@ azure ad app create --name <name> --password <password> --home-page <home-page>
 # Create a Service Principal
 azure ad sp create <Application-id>
 
-# Output will include a value for `Object Id`
-
+# Output will include a value for `Object Id`, to be used in the next step 
 ```
 
 Run the following commands to assign roles to the service principal
@@ -58,7 +57,8 @@ mvn -Dtest=<name of the live test> \
     -Dtest.azurecompute-arm.identity="<Application-id>" \
     -Dtest.azurecompute-arm.credential="<password>" \
     -Dtest.azurecompute-arm.endpoint="https://management.azure.com/subscriptions/<Subscription-id>" \
-    -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test
+    -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token"
+    integration-test -Plive
 
 ```
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/pom.xml
----------------------------------------------------------------------
diff --git a/azurecompute-arm/pom.xml b/azurecompute-arm/pom.xml
index df5b835..824e552 100644
--- a/azurecompute-arm/pom.xml
+++ b/azurecompute-arm/pom.xml
@@ -46,7 +46,7 @@
     <dependency>
       <groupId>org.apache.jclouds</groupId>
       <artifactId>jclouds-compute</artifactId>
-      <version>${project.parent.version}</version>
+      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>com.google.auto.service</groupId>
@@ -80,11 +80,6 @@
       <groupId>org.apache.jclouds</groupId>
       <artifactId>jclouds-compute</artifactId>
       <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-compute</artifactId>
-      <version>${project.version}</version>
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index 42749cf..c0c0994 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -16,28 +16,27 @@
  */
 package org.jclouds.azurecompute.arm;
 
+import java.io.Closeable;
+
+import javax.ws.rs.PathParam;
+
 import org.jclouds.azurecompute.arm.features.DeploymentApi;
-import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
 import org.jclouds.azurecompute.arm.features.JobApi;
 import org.jclouds.azurecompute.arm.features.LocationApi;
 import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
+import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
+import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
 import org.jclouds.azurecompute.arm.features.OSImageApi;
 import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
 import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
 import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
 import org.jclouds.azurecompute.arm.features.StorageAccountApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
+import org.jclouds.azurecompute.arm.features.VMSizeApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
 import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
-import org.jclouds.azurecompute.arm.features.VMSizeApi;
-import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
-import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
 import org.jclouds.rest.annotations.Delegate;
 
-import com.google.inject.Provides;
-import javax.ws.rs.PathParam;
-import java.io.Closeable;
-
 /**
  * The Azure Resource Manager API is a REST API for managing your services and deployments.
  * <p>
@@ -165,6 +164,4 @@ public interface AzureComputeApi extends Closeable {
    @Delegate
    ResourceProviderApi getResourceProviderApi();
 
-   @Provides
-   DeploymentTemplateBuilder.Factory deploymentTemplateFactory();
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index 460df67..a434079 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -17,31 +17,47 @@
 package org.jclouds.azurecompute.arm;
 
 
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE;
-
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN;
-
+import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_AUTHENTICATE_SUDO;
+import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER;
+import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
 import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
-import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
 import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
+import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
 
 import java.net.URI;
 import java.util.Properties;
+
 import org.jclouds.azurecompute.arm.domain.Region;
+import org.jclouds.azurecompute.arm.features.DeploymentApi;
+import org.jclouds.azurecompute.arm.features.LocationApi;
+import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
+import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
+import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
+import org.jclouds.azurecompute.arm.features.OSImageApi;
+import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
+import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
+import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
+import org.jclouds.azurecompute.arm.features.StorageAccountApi;
+import org.jclouds.azurecompute.arm.features.SubnetApi;
+import org.jclouds.azurecompute.arm.features.VMSizeApi;
+import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
+import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
+import org.jclouds.compute.config.ComputeServiceProperties;
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.providers.internal.BaseProviderMetadata;
-import org.jclouds.compute.config.ComputeServiceProperties;
-
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
 
 import com.google.auto.service.AutoService;
 
@@ -72,13 +88,37 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.setProperty(TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
       properties.put(RESOURCE, "https://management.azure.com/");
       properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
-      properties.put(RESOURCE_GROUP_NAME, "jcloudsgroup");
+      properties.put(RESOURCE_GROUP_NAME, "jclouds");
       properties.put(DEFAULT_VNET_ADDRESS_SPACE_PREFIX, "10.0.0.0/16");
       properties.put(DEFAULT_SUBNET_ADDRESS_PREFIX, "10.0.0.0/24");
       properties.put(DEFAULT_DATADISKSIZE, "100");
       properties.put(IMAGE_PUBLISHERS, "Canonical,RedHat");
-      properties.put(DEFAULT_IMAGE_LOGIN, "jclouds:Password1!");
+      // Default credentials for all images
+      properties.put(IMAGE_LOGIN_USER, "jclouds:Password12345!");
+      properties.put(IMAGE_AUTHENTICATE_SUDO, "true");
+      properties.put(TEMPLATE, "imageNameMatches=UbuntuServer,osVersionMatches=1[45]\\.[01][04]\\.[0-9]-LTS");
       properties.put(TIMEOUT_NODE_TERMINATED, 60 * 10 * 1000);
+      // Api versions used in each API
+      properties.put(API_VERSION_PREFIX + DeploymentApi.class.getSimpleName(), "2016-02-01");
+      properties.put(API_VERSION_PREFIX + LocationApi.class.getSimpleName(), "2015-11-01");
+      properties.put(API_VERSION_PREFIX + NetworkInterfaceCardApi.class.getSimpleName(), "2015-06-15");
+      properties.put(API_VERSION_PREFIX + NetworkSecurityGroupApi.class.getSimpleName(), "2016-03-30");
+      properties.put(API_VERSION_PREFIX + NetworkSecurityRuleApi.class.getSimpleName(), "2016-03-30");
+      properties.put(API_VERSION_PREFIX + OSImageApi.class.getSimpleName(), "2015-06-15");
+      properties.put(API_VERSION_PREFIX + PublicIPAddressApi.class.getSimpleName(), "2015-06-15");
+      properties.put(API_VERSION_PREFIX + ResourceGroupApi.class.getSimpleName(), "2015-01-01");
+      properties.put(API_VERSION_PREFIX + ResourceProviderApi.class.getSimpleName(), "2015-01-01");
+      properties.put(API_VERSION_PREFIX + StorageAccountApi.class.getSimpleName(), STORAGE_API_VERSION);
+      properties.put(API_VERSION_PREFIX + SubnetApi.class.getSimpleName(), "2015-06-15");
+      properties.put(API_VERSION_PREFIX + VirtualNetworkApi.class.getSimpleName(), "2015-06-15");
+      properties.put(API_VERSION_PREFIX + VMSizeApi.class.getSimpleName(), "2015-06-15");
+      properties.put(API_VERSION_PREFIX + VirtualMachineApi.class.getSimpleName(), "2015-06-15");
+      properties.put(API_VERSION_PREFIX + "GetVirtualMachine", "2016-03-30");
+      properties.put(API_VERSION_PREFIX + "GetVirtualMachineInstance", "2016-03-30");
+      properties.put(API_VERSION_PREFIX + "CreateVirtualMachine", "2016-03-30");
+      properties.put(API_VERSION_PREFIX + "ListVirtualMachines", "2015-06-15");
+      properties.put(API_VERSION_PREFIX + "DeleteVirtualMachine", "2016-03-30");
+      
       return properties;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 61807a9..0e2ed64 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -17,164 +17,139 @@
 package org.jclouds.azurecompute.arm.compute;
 
 import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.jclouds.util.Predicates2.retry;
+import static com.google.common.collect.Iterables.contains;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.find;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
+import static org.jclouds.util.Closeables2.closeQuietly;
 
-import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
-import javax.annotation.Resource;
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
-import org.jclouds.azurecompute.arm.compute.functions.DeploymentToVMDeployment;
-import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
-import org.jclouds.azurecompute.arm.compute.predicates.IsDeploymentInRegions;
-import org.jclouds.azurecompute.arm.domain.Deployment;
-import org.jclouds.azurecompute.arm.domain.DeploymentBody;
-import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
+import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
+import org.jclouds.azurecompute.arm.domain.DataDisk;
+import org.jclouds.azurecompute.arm.domain.HardwareProfile;
+import org.jclouds.azurecompute.arm.domain.IdReference;
+import org.jclouds.azurecompute.arm.domain.ImageReference;
+import org.jclouds.azurecompute.arm.domain.IpConfiguration;
+import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
 import org.jclouds.azurecompute.arm.domain.Location;
+import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
+import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile;
+import org.jclouds.azurecompute.arm.domain.OSDisk;
+import org.jclouds.azurecompute.arm.domain.OSProfile;
 import org.jclouds.azurecompute.arm.domain.Offer;
+import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
+import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
 import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
 import org.jclouds.azurecompute.arm.domain.SKU;
+import org.jclouds.azurecompute.arm.domain.StorageProfile;
 import org.jclouds.azurecompute.arm.domain.StorageService;
-import org.jclouds.azurecompute.arm.domain.VMDeployment;
+import org.jclouds.azurecompute.arm.domain.StorageService.Status;
+import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
+import org.jclouds.azurecompute.arm.domain.VHD;
 import org.jclouds.azurecompute.arm.domain.VMHardware;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VMSize;
-import org.jclouds.azurecompute.arm.domain.Value;
 import org.jclouds.azurecompute.arm.domain.Version;
-import org.jclouds.azurecompute.arm.features.DeploymentApi;
+import org.jclouds.azurecompute.arm.domain.VirtualMachine;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
 import org.jclouds.azurecompute.arm.features.OSImageApi;
+import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
 import org.jclouds.azurecompute.arm.functions.CleanupResources;
 import org.jclouds.azurecompute.arm.util.BlobHelper;
-import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
 import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.OsFamily;
 import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.reference.ComputeServiceConstants;
-import org.jclouds.domain.LoginCredentials;
 import org.jclouds.location.Region;
-import org.jclouds.logging.Logger;
 
 import com.google.common.base.Function;
+import com.google.common.base.Objects;
 import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
 import com.google.common.base.Supplier;
-import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
-import com.google.common.net.UrlEscapers;
 
 /**
  * Defines the connection between the {@link AzureComputeApi} implementation and the jclouds
  * {@link org.jclouds.compute.ComputeService}.
  */
 @Singleton
-public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeployment, VMHardware, VMImage, Location> {
+public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location> {
 
-   private String azureGroup;
-   protected final CleanupResources cleanupResources;
-
-   @Resource
-   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
-   private Logger logger = Logger.NULL;
+   private final String azureGroup;
+   private final CleanupResources cleanupResources;
    private final AzureComputeApi api;
    private final AzureComputeConstants azureComputeConstants;
    private final Supplier<Set<String>> regionIds;
-   private final IsDeploymentInRegions isDeploymentInRegions;
-   private final DeploymentToVMDeployment deploymentToVMDeployment;
+   private final Predicate<String> publicIpAvailable;
 
    @Inject
    AzureComputeServiceAdapter(final AzureComputeApi api, final AzureComputeConstants azureComputeConstants,
          CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
-         IsDeploymentInRegions isDeploymentInRegions, DeploymentToVMDeployment deploymentToVMDeployment) {
+         @Named("PublicIpAvailable") Predicate<String> publicIpAvailable) {
       this.api = api;
       this.azureComputeConstants = azureComputeConstants;
       this.azureGroup = azureComputeConstants.azureResourceGroup();
-
-      logger.debug("AzureComputeServiceAdapter set azuregroup to: " + azureGroup);
-
       this.cleanupResources = cleanupResources;
       this.regionIds = regionIds;
-      this.isDeploymentInRegions = isDeploymentInRegions;
-      this.deploymentToVMDeployment = deploymentToVMDeployment;
+      this.publicIpAvailable = publicIpAvailable;
    }
 
    @Override
-   public NodeAndInitialCredentials<VMDeployment> createNodeWithGroupEncodedIntoName(
+   public NodeAndInitialCredentials<VirtualMachine> createNodeWithGroupEncodedIntoName(
            final String group, final String name, final Template template) {
 
-      DeploymentTemplateBuilder deploymentTemplateBuilder = api.deploymentTemplateFactory().create(group, name, template);
-
-      final String loginUser = DeploymentTemplateBuilder.getLoginUserUsername();
-      final String loginPassword = DeploymentTemplateBuilder.getLoginPassword();
-
-      DeploymentBody deploymentTemplateBody =  deploymentTemplateBuilder.getDeploymentTemplate();
-
-      DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
-
-      final String deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplateBuilder.getDeploymentTemplateJson(properties));
-
-      logger.debug("Deployment created with name: %s group: %s", name, group);
-
-
-      final Set<VMDeployment> deployments = Sets.newHashSet();
-
-      final DeploymentApi deploymentApi = api.getDeploymentApi(azureGroup);
-
-      if (!retry(new Predicate<String>() {
-         @Override
-         public boolean apply(final String name) {
-            Deployment deployment = deploymentApi.create(name, deploymentTemplate);
-
-            if (deployment != null) {
-               VMDeployment vmDeployment = VMDeployment.create(deployment);
-               deployments.add(vmDeployment);
-            } else {
-               logger.debug("Failed to create deployment!");
-            }
-            return !deployments.isEmpty();
-         }
-      }, azureComputeConstants.operationTimeout(), 1, SECONDS).apply(name)) {
-         final String illegalStateExceptionMessage = format("Deployment %s was not created within %sms so it will be destroyed.",
-                 name, azureComputeConstants.operationTimeout());
-         logger.warn(illegalStateExceptionMessage);
-         destroyNode(name);
-         throw new IllegalStateException(illegalStateExceptionMessage);
-      }
-      final VMDeployment deployment = deployments.iterator().next();
-      NodeAndInitialCredentials<VMDeployment> credential;
-      if (template.getOptions().getPublicKey() != null){
-         String privateKey = template.getOptions().getPrivateKey();
-         credential = new NodeAndInitialCredentials<VMDeployment>(deployment, name,
-                 LoginCredentials.builder().user(loginUser).privateKey(privateKey).authenticateSudo(true).build());
-      } else {
-         credential = new NodeAndInitialCredentials<VMDeployment>(deployment, name,
-                 LoginCredentials.builder().user(loginUser).password(loginPassword).authenticateSudo(true).build());
-      }
-      return credential;
+      AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class);
+
+      // TODO Store group apart from the name to be able to identify nodes with custom names in the configured group
+      // TODO ARM specific options
+      // TODO user metadata and tags
+      // TODO network ids => create one nic in each network
+      // TODO inbound ports
+      
+      String locationName = template.getLocation().getId();
+      String subnetId = templateOptions.getSubnetId();
+      NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName); 
+      StorageProfile storageProfile = createStorageProfile(name, template.getImage(), templateOptions.getBlob());
+      HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(template.getHardware().getId()).build();
+      OSProfile osProfile = createOsProfile(name, template);
+      NetworkProfile networkProfile = NetworkProfile.builder().networkInterfaces(ImmutableList.of(IdReference.create(nic.id()))).build();
+      VirtualMachineProperties virtualMachineProperties = VirtualMachineProperties.builder()
+              .licenseType(null) // TODO
+              .availabilitySet(null) // TODO
+              .hardwareProfile(hardwareProfile)
+              .storageProfile(storageProfile)
+              .osProfile(osProfile)
+              .networkProfile(networkProfile)
+              .build();
+
+      VirtualMachine virtualMachine = api.getVirtualMachineApi(azureGroup).create(name, template.getLocation().getId(), virtualMachineProperties);
+
+      // Safe to pass null credentials here, as jclouds will default populate the node with the default credentials from the image, or the ones in the options, if provided.
+      return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, name, null);
    }
 
    @Override
    public Iterable<VMHardware> listHardwareProfiles() {
-
       final List<VMHardware> hwProfiles = Lists.newArrayList();
-      final List<String> locationIds = Lists.newArrayList();
-
-      Iterable<Location> locations = listLocations();
-      for (Location location : locations){
-         locationIds.add(location.name());
-
+      for (Location location : listLocations()) {
          Iterable<VMSize> vmSizes = api.getVMSizeApi(location.name()).list();
-
          for (VMSize vmSize : vmSizes){
             VMHardware hwProfile = VMHardware.create(
                     vmSize.name(),
@@ -188,22 +163,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
             hwProfiles.add(hwProfile);
          }
       }
-
-      checkAndSetHwAvailability(hwProfiles, Sets.newHashSet(locationIds));
-
       return hwProfiles;
    }
-   private void checkAndSetHwAvailability(List<VMHardware> hwProfiles, Collection<String> locations) {
-      Multimap<String, String> hwMap = ArrayListMultimap.create();
-      for (VMHardware hw : hwProfiles) {
-         hwMap.put(hw.name(), hw.location());
-      }
-
-      /// TODO
-      //      for (VMHardware hw : hwProfiles) {
-      //         hw.globallyAvailable() = hwMap.get(hw.name()).containsAll(locations);
-      //      }
-   }
 
    private List<VMImage> getImagesFromPublisher(String publisherName, String location) {
       List<VMImage> osImagesRef = Lists.newArrayList();
@@ -216,7 +177,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
          for (SKU sku : skuList) {
             Iterable<Version> versionList = osImageApi.listVersions(publisherName, offer.name(), sku.name());
             for (Version version : versionList) {
-               VMImage vmImage = VMImage.create(publisherName, offer.name(), sku.name(), version.name(), location);
+               VMImage vmImage = VMImage.azureImage().publisher(publisherName).offer(offer.name()).sku(sku.name())
+                     .version(version.name()).location(location).build();
                osImagesRef.add(vmImage);
             }
          }
@@ -235,7 +197,6 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
 
    @Override
    public Iterable<VMImage> listImages() {
-
       final List<VMImage> osImages = Lists.newArrayList();
 
       for (Location location : listLocations()){
@@ -245,24 +206,51 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
       List<StorageService> storages = api.getStorageAccountApi(azureGroup).list();
       for (StorageService storage : storages) {
          String name = storage.name();
-         String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1();
-            List<VMImage> images = BlobHelper.getImages("jclouds", azureGroup, storage.name(), key,
-                  "custom", storage.location());
-            osImages.addAll(images);
+         StorageService storageService = api.getStorageAccountApi(azureGroup).get(name);
+         if (storageService != null
+               && Status.Succeeded == storageService.storageServiceProperties().provisioningState()) {
+            String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1();
+            BlobHelper blobHelper = new BlobHelper(storage.name(), key);
+            try {
+               List<VMImage> images = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER,
+                     storage.location());
+               osImages.addAll(images);
+            } finally {
+               closeQuietly(blobHelper);
+            }
+         }
       }
+      
       return osImages;
    }
 
    @Override
    public VMImage getImage(final String id) {
-      VMImage image = VMImageToImage.decodeFieldsFromUniqueId(id);
+      VMImage image = decodeFieldsFromUniqueId(id);
       if (image.custom()) {
-         String key = api.getStorageAccountApi(azureGroup).getKeys(image.storage()).key1();
-         if (BlobHelper.customImageExists(image.storage(), key))
-            return image;
-         else
+         VMImage customImage = null;
+         StorageServiceKeys keys = api.getStorageAccountApi(azureGroup).getKeys(image.storage());
+         if (keys == null) {
+            // If the storage account for the image does not exist, it means the image was deleted
             return null;
-
+         }
+         
+         BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1());
+         try {
+            if (blobHelper.customImageExists()) {
+               List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, azureGroup,
+                     CUSTOM_IMAGE_OFFER, image.location());
+               customImage = find(customImagesInStorage, new Predicate<VMImage>() {
+                  @Override
+                  public boolean apply(VMImage input) {
+                     return id.equals(encodeFieldsToUniqueIdCustom(input));
+                  }
+               }, null);
+            }
+         } finally {
+            closeQuietly(blobHelper);
+         }
+         return customImage;
       }
 
       String location = image.location();
@@ -273,7 +261,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
       OSImageApi osImageApi = api.getOSImageApi(location);
       List<Version> versions = osImageApi.listVersions(publisher, offer, sku);
       if (!versions.isEmpty()) {
-         return VMImage.create(publisher, offer, sku, versions.get(0).name(), location);
+         return VMImage.azureImage().publisher(publisher).offer(offer).sku(sku).version(versions.get(0).name())
+               .location(location).build();
       }
       return null;
    }
@@ -313,13 +302,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
    }
 
    @Override
-   public VMDeployment getNode(final String id) {
-      Deployment deployment = api.getDeploymentApi(azureGroup).get(id);
-      if (deployment == null) return null;
-      if (isDeploymentInRegions.apply(deployment)) {
-         return deploymentToVMDeployment.apply(deployment);
-      }
-      return null;
+   public VirtualMachine getNode(final String id) {
+      return api.getVirtualMachineApi(azureGroup).get(id);
    }
 
    @Override
@@ -343,29 +327,99 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
    }
 
    @Override
-   public Iterable<VMDeployment> listNodes() {
-      return FluentIterable.from(api.getDeploymentApi(azureGroup).list())
-              .filter(isDeploymentInRegions)
-              .filter(new Predicate<Deployment>() {
-                 @Override
-                 public boolean apply(Deployment deployment) {
-                    Value storageAccountNameValue = deployment.properties().parameters().get("storageAccountName");
-                    String storageAccountName = storageAccountNameValue.value();
-                    String key = api.getStorageAccountApi(azureGroup).getKeys(storageAccountName).key1();
-                    return !BlobHelper.customImageExists(storageAccountName, key);
-                 }
-              })
-              .transform(deploymentToVMDeployment)
-              .toList();
+   public Iterable<VirtualMachine> listNodes() {
+      return api.getVirtualMachineApi(azureGroup).list();
    }
 
    @Override
-   public Iterable<VMDeployment> listNodesByIds(final Iterable<String> ids) {
-      return Iterables.filter(listNodes(), new Predicate<VMDeployment>() {
+   public Iterable<VirtualMachine> listNodesByIds(final Iterable<String> ids) {
+      return filter(listNodes(), new Predicate<VirtualMachine>() {
          @Override
-         public boolean apply(final VMDeployment input) {
-            return Iterables.contains(ids, input.deployment().name());
+         public boolean apply(VirtualMachine virtualMachine) {
+            return contains(ids, virtualMachine.id());
          }
       });
    }
+
+
+   private OSProfile createOsProfile(String computerName, Template template) {
+      String defaultLoginUser = template.getImage().getDefaultCredentials().getUser();
+      String defaultLoginPassword = template.getImage().getDefaultCredentials().getOptionalPassword().get();
+      String adminUsername = Objects.firstNonNull(template.getOptions().getLoginUser(), defaultLoginUser);
+      String adminPassword = Objects.firstNonNull(template.getOptions().getLoginPassword(), defaultLoginPassword);
+      OSProfile.Builder builder = OSProfile.builder().adminUsername(adminUsername).computerName(computerName);
+      // prefer public key over password
+      if (template.getOptions().getPublicKey() != null) {
+         OSProfile.LinuxConfiguration linuxConfiguration = OSProfile.LinuxConfiguration.create("true",
+                 OSProfile.LinuxConfiguration.SSH.create(ImmutableList.of(
+                         OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create(
+                                 String.format("/home/%s/.ssh/authorized_keys", adminUsername),
+                                 template.getOptions().getPublicKey())
+                 ))
+         );
+         builder.linuxConfiguration(linuxConfiguration);
+      } else {
+         builder.adminPassword(adminPassword);
+      }
+      return builder.build();
+   }
+
+   private NetworkInterfaceCard createNetworkInterfaceCard(String subnetId, String name, String locationName) {
+      final PublicIPAddressApi ipApi = api.getPublicIPAddressApi(azureGroup);
+
+      PublicIPAddressProperties properties =
+              PublicIPAddressProperties.builder()
+                      .publicIPAllocationMethod("Static")
+                      .idleTimeoutInMinutes(4)
+                      .build();
+
+      String publicIpAddressName = "public-address-" + name;
+      PublicIPAddress ip = ipApi.createOrUpdate(publicIpAddressName, locationName, ImmutableMap.of("jclouds", name), properties);
+      
+      checkState(publicIpAvailable.apply(publicIpAddressName),
+            "Public IP was not provisioned in the configured timeout");
+
+      final NetworkInterfaceCardProperties networkInterfaceCardProperties =
+              NetworkInterfaceCardProperties.builder()
+                      .ipConfigurations(ImmutableList.of(
+                              IpConfiguration.builder()
+                                      .name("ipConfig-" + name)
+                                      .properties(IpConfigurationProperties.builder()
+                                              .privateIPAllocationMethod("Dynamic")
+                                              .publicIPAddress(IdReference.create(ip.id()))
+                                              .subnet(IdReference.create(subnetId))
+                                              .build())
+                                      .build()))
+                      .build();
+
+      String networkInterfaceCardName = "jc-nic-" + name;
+      return api.getNetworkInterfaceCardApi(azureGroup).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, ImmutableMap.of("jclouds", name));
+   }
+
+   private StorageProfile createStorageProfile(String name, Image image, String blob) {
+      VMImage imageRef = decodeFieldsFromUniqueId(image.getId());
+      ImageReference imageReference = null;
+      VHD sourceImage = null;
+      String osType = null;
+      
+      if (!imageRef.custom()) {
+         imageReference = ImageReference.builder()
+               .publisher(image.getProviderId())
+               .offer(image.getName())
+               .sku(image.getVersion())
+               .version("latest")
+               .build();
+      } else {
+         sourceImage = VHD.create(image.getProviderId());
+
+         // TODO: read the ostype from the image blob
+         OsFamily osFamily = image.getOperatingSystem().getFamily();
+         osType = osFamily == OsFamily.WINDOWS ? "Windows" : "Linux";
+      }
+      
+      VHD vhd = VHD.create(blob + "vhds/" + name + ".vhd");
+      OSDisk osDisk = OSDisk.create(osType, name, vhd, "ReadWrite", "FromImage", sourceImage);
+      
+      return StorageProfile.create(imageReference, osDisk, ImmutableList.<DataDisk>of());
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
index 6033f42..24f02ea 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
@@ -16,10 +16,27 @@
  */
 package org.jclouds.azurecompute.arm.compute.config;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
+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 static org.jclouds.util.Predicates2.retry;
+
 import java.net.URI;
 import java.util.List;
 
-import javax.annotation.Resource;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
@@ -27,19 +44,21 @@ import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.AzureComputeService;
 import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter;
 import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
-import org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata;
 import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation;
+import org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage;
 import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware;
 import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
+import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
-import org.jclouds.azurecompute.arm.compute.strategy.AzurePopulateDefaultLoginCredentialsForImageStrategy;
 import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes;
 import org.jclouds.azurecompute.arm.domain.Location;
+import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
-import org.jclouds.azurecompute.arm.domain.VMDeployment;
 import org.jclouds.azurecompute.arm.domain.VMHardware;
 import org.jclouds.azurecompute.arm.domain.VMImage;
+import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
 import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
 import org.jclouds.compute.ComputeService;
 import org.jclouds.compute.ComputeServiceAdapter;
@@ -47,13 +66,12 @@ import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
 import org.jclouds.compute.domain.Hardware;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.extensions.ImageExtension;
+import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement;
+import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatementWithoutPublicKey;
 import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
 import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
 import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
-import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
-import org.jclouds.logging.Logger;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
@@ -61,53 +79,37 @@ import com.google.common.base.Predicate;
 import com.google.inject.Inject;
 import com.google.inject.Provides;
 import com.google.inject.TypeLiteral;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
-import static org.jclouds.util.Predicates2.retry;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
 
 public class AzureComputeServiceContextModule
-        extends ComputeServiceAdapterContextModule<VMDeployment, VMHardware, VMImage, Location> {
-
-   @Resource
-   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
-   protected Logger logger = Logger.NULL;
+        extends ComputeServiceAdapterContextModule<VirtualMachine, VMHardware, VMImage, Location> {
 
    @Override
    protected void configure() {
       super.configure();
-      bind(new TypeLiteral<ComputeServiceAdapter<VMDeployment, VMHardware, VMImage, Location>>() {
+      
+      bind(new TypeLiteral<ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location>>() {
       }).to(AzureComputeServiceAdapter.class);
+      
       bind(new TypeLiteral<Function<VMImage, org.jclouds.compute.domain.Image>>() {
       }).to(VMImageToImage.class);
       bind(new TypeLiteral<Function<VMHardware, Hardware>>() {
       }).to(VMHardwareToHardware.class);
-      bind(new TypeLiteral<Function<VMDeployment, NodeMetadata>>() {
-      }).to(DeploymentToNodeMetadata.class);
+      bind(new TypeLiteral<Function<VirtualMachine, NodeMetadata>>() {
+      }).to(VirtualMachineToNodeMetadata.class);
       bind(new TypeLiteral<Function<Location, org.jclouds.domain.Location>>() {
       }).to(LocationToLocation.class);
       bind(ComputeService.class).to(AzureComputeService.class);
-      install(new LocationsFromComputeServiceAdapterModule<VMDeployment, VMHardware, VMImage, Location>() {
+      
+      install(new LocationsFromComputeServiceAdapterModule<VirtualMachine, VMHardware, VMImage, Location>() {
       });
+      
+      install(new FactoryModuleBuilder().build(ResourceDefinitionToCustomImage.Factory.class));
 
       bind(TemplateOptions.class).to(AzureTemplateOptions.class);
-      bind(PopulateDefaultLoginCredentialsForImageStrategy.class).to(AzurePopulateDefaultLoginCredentialsForImageStrategy.class);
-      //bind(TemplateOptionsToStatement.class).to(TemplateOptionsToStatementWithoutPublicKey.class);
+      bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class);
       bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class);
+      
       bind(new TypeLiteral<ImageExtension>() {
       }).to(AzureComputeImageExtension.class);
    }
@@ -143,10 +145,6 @@ public class AzureComputeServiceContextModule
       @Inject
       private String azureImagePublishersProperty;
 
-      @Named(DEFAULT_IMAGE_LOGIN)
-      @Inject
-      private String azureDefaultImageLoginProperty;
-
       @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX)
       @Inject
       private String azureDefaultVnetAddressPrefixProperty;
@@ -171,10 +169,6 @@ public class AzureComputeServiceContextModule
          return azureImagePublishersProperty;
       }
 
-      public String azureDefaultImageLogin() {
-         return azureDefaultImageLoginProperty;
-      }
-
       public String azureDefaultVnetAddressPrefixProperty() {
          return azureDefaultVnetAddressPrefixProperty;
       }
@@ -205,6 +199,14 @@ public class AzureComputeServiceContextModule
    }
 
    @Provides
+   @com.google.inject.name.Named(TIMEOUT_NODE_RUNNING)
+   protected Predicate<String> provideVirtualMachineRunningPredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, Timeouts timeouts, PollPeriod pollPeriod) {
+      String azureGroup = azureComputeConstants.azureResourceGroup();
+      return retry(new VirtualMachineInStatePredicate(api, azureGroup, PowerState.RUNNING), timeouts.nodeRunning,
+              pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+   }
+   
+   @Provides
    @Named(TIMEOUT_NODE_TERMINATED)
    protected Predicate<URI> provideNodeTerminatedPredicate(final AzureComputeApi api, Timeouts timeouts, PollPeriod pollPeriod) {
       return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod,
@@ -230,7 +232,17 @@ public class AzureComputeServiceContextModule
    protected Predicate<String> provideNodeSuspendedPredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
                                                              Timeouts timeouts, PollPeriod pollPeriod) {
       String azureGroup = azureComputeConstants.azureResourceGroup();
-      return retry(new NodeSuspendedPredicate(api, azureGroup), timeouts.nodeSuspended, pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+      return retry(new VirtualMachineInStatePredicate(api, azureGroup, PowerState.STOPPED), timeouts.nodeTerminated,
+              pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+   }
+   
+   @Provides
+   @Named("PublicIpAvailable")
+   protected Predicate<String> providePublicIpAvailablePredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
+                                                             Timeouts timeouts, PollPeriod pollPeriod) {
+      String azureGroup = azureComputeConstants.azureResourceGroup();
+      return retry(new PublicIpAvailablePredicate(api, azureGroup), azureComputeConstants.operationTimeout(),
+            azureComputeConstants.operationPollInitialPeriod(), azureComputeConstants.operationPollMaxPeriod());
    }
 
    @VisibleForTesting
@@ -269,30 +281,45 @@ public class AzureComputeServiceContextModule
    }
 
    @VisibleForTesting
-   static class NodeSuspendedPredicate implements Predicate<String> {
+   static class VirtualMachineInStatePredicate implements Predicate<String> {
 
       private final AzureComputeApi api;
       private final String azureGroup;
+      private final PowerState powerState;
 
-      public NodeSuspendedPredicate(AzureComputeApi api, String azureGroup) {
+      public VirtualMachineInStatePredicate(AzureComputeApi api, String azureGroup, PowerState powerState) {
          this.api = checkNotNull(api, "api must not be null");
          this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be null");
+         this.powerState = checkNotNull(powerState, "powerState must not be null");
       }
 
       @Override
       public boolean apply(String name) {
          checkNotNull(name, "name cannot be null");
-         String status = "";
-         VirtualMachineInstance virtualMachineInstance = api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name);
-         if (virtualMachineInstance == null) return false;
-         List<VirtualMachineInstance.VirtualMachineStatus> statuses = virtualMachineInstance.statuses();
-         for (int c = 0; c < statuses.size(); c++) {
-            if (statuses.get(c).code().substring(0, 10).equals("PowerState")) {
-               status = statuses.get(c).displayStatus();
-               break;
-            }
-         }
-         return status.equals("VM stopped");
+         VirtualMachineInstance vmInstance = api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name);
+         if (vmInstance == null) return false;
+         return powerState == vmInstance.powerState();
       }
    }
+   
+   @VisibleForTesting
+   static class PublicIpAvailablePredicate implements Predicate<String> {
+
+      private final AzureComputeApi api;
+      private final String azureGroup;
+
+      public PublicIpAvailablePredicate(AzureComputeApi api, String azureGroup) {
+         this.api = checkNotNull(api, "api must not be null");
+         this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be null");
+      }
+
+      @Override
+      public boolean apply(String name) {
+         checkNotNull(name, "name cannot be null");
+         PublicIPAddress publicIp = api.getPublicIPAddressApi(azureGroup).get(name);
+         if (publicIp == null) return false;
+         return publicIp.properties().provisioningState().equalsIgnoreCase("Succeeded");
+      }
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
index 786c17a..99c9c6c 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
@@ -16,141 +16,137 @@
  */
 package org.jclouds.azurecompute.arm.compute.extensions;
 
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.UncheckedTimeoutException;
-import com.google.gson.internal.LinkedTreeMap;
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static org.jclouds.util.Closeables2.closeQuietly;
+
+import java.net.URI;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import javax.annotation.Resource;
+
 import org.jclouds.Constants;
-import org.jclouds.View;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
-import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
+import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
+import org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage;
 import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
 import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VMImage;
-import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import static java.lang.String.format;
+import org.jclouds.azurecompute.arm.functions.CleanupResources;
 import org.jclouds.azurecompute.arm.util.BlobHelper;
 import org.jclouds.compute.domain.CloneImageTemplate;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.ImageTemplate;
 import org.jclouds.compute.domain.ImageTemplateBuilder;
 import org.jclouds.compute.extensions.ImageExtension;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
 
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
+import com.google.common.base.Predicate;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
 
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+public class AzureComputeImageExtension implements ImageExtension {
+   public static final String CONTAINER_NAME = "jclouds";
+   public static final String CUSTOM_IMAGE_OFFER = "custom";
 
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
 
-public class AzureComputeImageExtension implements ImageExtension {
    private final AzureComputeApi api;
-   private final ListeningExecutorService userExecutor;
-   private final Supplier<View> blobstore = null;
    private final String group;
+   private final ListeningExecutorService userExecutor;
    private final Predicate<URI> imageAvailablePredicate;
    private final Predicate<String> nodeSuspendedPredicate;
-   private final AzureComputeConstants azureComputeConstants;
-   private final VMImageToImage imageReferenceToImage;
-   public static final String CONTAINER_NAME = "jclouds";
-   public static final String CUSTOM_IMAGE_PREFIX = "#";
+   private final ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage;
+   private final CleanupResources cleanupResources;
 
    @Inject
    AzureComputeImageExtension(AzureComputeApi api,
-                              @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> imageAvailablePredicate,
-                              @Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> nodeSuspendedPredicate,
-                              final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
-                              @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
-                              VMImageToImage imageReferenceToImage) {
-      this.userExecutor = userExecutor;
-      this.group = azureComputeConstants.azureResourceGroup();
-      this.imageReferenceToImage = imageReferenceToImage;
+         @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> imageAvailablePredicate,
+         @Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> nodeSuspendedPredicate,
+         AzureComputeConstants azureComputeConstants,
+         @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
+         ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage, CleanupResources cleanupResources) {
+      this.api = api;
       this.imageAvailablePredicate = imageAvailablePredicate;
       this.nodeSuspendedPredicate = nodeSuspendedPredicate;
-      this.azureComputeConstants = azureComputeConstants;
-      this.api = api;
+      this.group = azureComputeConstants.azureResourceGroup();
+      this.userExecutor = userExecutor;
+      this.resourceDefinitionToImage = resourceDefinitionToImage;
+      this.cleanupResources = cleanupResources;
    }
 
    @Override
    public ImageTemplate buildImageTemplateFromNode(String name, String id) {
-      String nameLowerCase = name.toLowerCase();
-      return new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(nameLowerCase).build();
+      return new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(name.toLowerCase()).build();
    }
 
    @Override
    public ListenableFuture<Image> createImage(ImageTemplate template) {
-
-
       final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
       final String id = cloneTemplate.getSourceNodeId();
       final String name = cloneTemplate.getName();
-      final String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + "stor";
 
+      logger.debug(">> stopping node %s...", id);
       api.getVirtualMachineApi(group).stop(id);
-      if (nodeSuspendedPredicate.apply(id)) {
-         return userExecutor.submit(new Callable<Image>() {
-            @Override
-            public Image call() throws Exception {
-               api.getVirtualMachineApi(group).generalize(id);
-
-               final String[] disks = new String[2];
-               URI uri = api.getVirtualMachineApi(group).capture(id, cloneTemplate.getName(), CONTAINER_NAME);
-               if (uri != null) {
-                  if (imageAvailablePredicate.apply(uri)) {
-                     List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
-                     if (definitions != null) {
-                        for (ResourceDefinition definition : definitions) {
-                           LinkedTreeMap<String, String> properties = (LinkedTreeMap<String, String>) definition.properties();
-                           Object storageObject = properties.get("storageProfile");
-                           LinkedTreeMap<String, String> properties2 = (LinkedTreeMap<String, String>) storageObject;
-                           Object osDiskObject = properties2.get("osDisk");
-                           LinkedTreeMap<String, String> osProperties = (LinkedTreeMap<String, String>) osDiskObject;
-                           Object dataDisksObject = properties2.get("dataDisks");
-                           ArrayList<Object> dataProperties = (ArrayList<Object>) dataDisksObject;
-                           LinkedTreeMap<String, String> datadiskObject = (LinkedTreeMap<String, String>) dataProperties.get(0);
-
-                           disks[0] = osProperties.get("name");
-                           disks[1] = datadiskObject.get("name");
-
-                           VirtualMachine vm = api.getVirtualMachineApi(group).get(id);
-                           final VMImage ref = VMImage.create(group, storageAccountName, disks[0], disks[1], name, "custom", vm.location());
-                           return imageReferenceToImage.apply(ref);
-                        }
-                     }
-                  }
-               }
-               throw new UncheckedTimeoutException("Image was not created within the time limit: "
-                     + cloneTemplate.getName());
-            }
-         });
-      } else {
-         final String illegalStateExceptionMessage = format("Node %s was not suspended within %sms.",
-               id, azureComputeConstants.operationTimeout());
-         throw new IllegalStateException(illegalStateExceptionMessage);
-      }
+      checkState(nodeSuspendedPredicate.apply(id), "Node %s was not suspended within the configured time limit", id);
+
+      return userExecutor.submit(new Callable<Image>() {
+         @Override
+         public Image call() throws Exception {
+            logger.debug(">> generalizing virtal machine %s...", id);
+            api.getVirtualMachineApi(group).generalize(id);
+
+            logger.debug(">> capturing virtual machine %s to container %s...", id, CONTAINER_NAME);
+            URI uri = api.getVirtualMachineApi(group).capture(id, cloneTemplate.getName(), CONTAINER_NAME);
+            checkState(uri != null && imageAvailablePredicate.apply(uri),
+                  "Image %s was not created within the configured time limit", cloneTemplate.getName());
+
+            List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
+            checkState(definitions.size() == 1,
+                  "Expected one resource definition after creating the image but %s were returned", definitions.size());
+
+            Image image = resourceDefinitionToImage.create(id, name).apply(definitions.get(0));
+            logger.debug(">> created %s", image);
+            return image;
+         }
+      });
    }
 
    @Override
    public boolean deleteImage(String id) {
+      VMImage image = decodeFieldsFromUniqueId(id);
+      checkArgument(image.custom(), "Only custom images can be deleted");
 
-      VMImage image = VMImageToImage.decodeFieldsFromUniqueId(id);
-      if (image.custom()) {
-         StorageServiceKeys keys = api.getStorageAccountApi(image.group()).getKeys(image.storage());
+      logger.debug(">> deleting image %s", id);
 
-         // This removes now all the images in this storage. At least in theory, there should be just one and if there is
+      StorageServiceKeys keys = api.getStorageAccountApi(image.group()).getKeys(image.storage());
+      BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1());
+      
+      try {
+         // This removes now all the images in this storage. At least in theory,
+         // there should be just one and if there is
          // more, they should be copies of each other.
-         BlobHelper.deleteContainerIfExists(image.storage(), keys.key1(), "system");
-         return !BlobHelper.customImageExists(image.storage(), keys.key1());
+         blobHelper.deleteContainerIfExists("system");
+         boolean result = !blobHelper.customImageExists();
+
+         if (!blobHelper.hasContainers()) {
+            logger.debug(">> storage account is empty after deleting the custom image. Deleting the storage account...");
+            api.getStorageAccountApi(image.group()).delete(image.storage());
+            cleanupResources.deleteResourceGroupIfEmpty(image.group());
+         }
+
+         return result;
+      } finally {
+         closeQuietly(blobHelper);
       }
-
-      return false;
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java
deleted file mode 100644
index 532e786..0000000
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * 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.azurecompute.arm.compute.functions;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.inject.Inject;
-
-import com.google.common.collect.Sets;
-import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.domain.ComputeNode;
-import org.jclouds.azurecompute.arm.domain.Deployment;
-import org.jclouds.azurecompute.arm.domain.ImageReference;
-import org.jclouds.azurecompute.arm.domain.IpConfiguration;
-import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
-import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
-import org.jclouds.azurecompute.arm.domain.VMDeployment;
-import org.jclouds.azurecompute.arm.domain.VMHardware;
-import org.jclouds.azurecompute.arm.domain.VMImage;
-import org.jclouds.azurecompute.arm.domain.VMSize;
-import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
-import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
-import org.jclouds.azurecompute.arm.util.GetEnumValue;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.NodeMetadataBuilder;
-import org.jclouds.compute.functions.GroupNamingConvention;
-import org.jclouds.domain.Credentials;
-import org.jclouds.domain.Location;
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableMap;
-import org.jclouds.domain.LoginCredentials;
-import org.jclouds.compute.domain.Image;
-import org.jclouds.compute.domain.Hardware;
-
-public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMetadata> {
-
-   public static final String JCLOUDS_DEFAULT_USERNAME = "root";
-   public static final String AZURE_LOGIN_USERNAME = DeploymentTemplateBuilder.getLoginUserUsername();
-   public static final String AZURE_LOGIN_PASSWORD = DeploymentTemplateBuilder.getLoginPassword();
-
-   private static final Map<ComputeNode.Status, NodeMetadata.Status> INSTANCESTATUS_TO_NODESTATUS =
-           ImmutableMap.<ComputeNode.Status, NodeMetadata.Status>builder().
-                   put(ComputeNode.Status.GOOD, NodeMetadata.Status.RUNNING).
-                   put(ComputeNode.Status.BAD, NodeMetadata.Status.ERROR).
-                   put(ComputeNode.Status.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).
-                   build();
-
-   // When using the Deployment API to deploy an ARM template, the deployment goes through
-   // stages.  Accepted -> Running -> Succeeded.  Only when the deployment has SUCCEEDED is
-   // the resource deployed using the template actually ready.
-   //
-   // To get details about the resource(s) deployed via template, one needs to query the
-   // various resources after the deployment has "SUCCEEDED".
-   private static final Map<Deployment.ProvisioningState, NodeMetadata.Status> STATUS_TO_NODESTATUS =
-           ImmutableMap.<Deployment.ProvisioningState, NodeMetadata.Status>builder().
-                   put(Deployment.ProvisioningState.ACCEPTED, NodeMetadata.Status.PENDING).
-                   put(Deployment.ProvisioningState.READY, NodeMetadata.Status.PENDING).
-                   put(Deployment.ProvisioningState.RUNNING, NodeMetadata.Status.PENDING).
-                   put(Deployment.ProvisioningState.CANCELED, NodeMetadata.Status.TERMINATED).
-                   put(Deployment.ProvisioningState.FAILED, NodeMetadata.Status.ERROR).
-                   put(Deployment.ProvisioningState.DELETED, NodeMetadata.Status.TERMINATED).
-                   put(Deployment.ProvisioningState.SUCCEEDED, NodeMetadata.Status.RUNNING).
-                   put(Deployment.ProvisioningState.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).
-                   build();
-
-   public static Deployment.ProvisioningState provisioningStateFromString(final String text) {
-      return (Deployment.ProvisioningState) GetEnumValue.fromValueOrDefault(text, Deployment.ProvisioningState.UNRECOGNIZED);
-   }
-
-   private final AzureComputeApi api;
-
-   private final LocationToLocation locationToLocation;
-
-   private final GroupNamingConvention nodeNamingConvention;
-
-   private final VMImageToImage vmImageToImage;
-
-   private final VMHardwareToHardware vmHardwareToHardware;
-
-   private final Map<String, Credentials> credentialStore;
-
-   @Inject
-   DeploymentToNodeMetadata(
-           AzureComputeApi api,
-           LocationToLocation locationToLocation,
-           GroupNamingConvention.Factory namingConvention, VMImageToImage vmImageToImage,
-           VMHardwareToHardware vmHardwareToHardware, Map<String, Credentials> credentialStore) {
-
-      this.nodeNamingConvention = namingConvention.createWithoutPrefix();
-      this.locationToLocation = locationToLocation;
-      this.vmImageToImage = vmImageToImage;
-      this.vmHardwareToHardware = vmHardwareToHardware;
-      this.credentialStore = credentialStore;
-      this.api = api;
-   }
-
-   @Override
-   public NodeMetadata apply(final VMDeployment from) {
-      final NodeMetadataBuilder builder = new NodeMetadataBuilder();
-      final Deployment deployment = from.deployment();
-      builder.id(deployment.name());
-      builder.providerId(deployment.name());
-      builder.name(deployment.name());
-      String group =  this.nodeNamingConvention.extractGroup(deployment.name());
-      builder.group(group);
-      if (from.tags() != null)
-         builder.tags(from.tags());
-      if (from.userMetaData() != null)
-         builder.userMetadata(from.userMetaData());
-
-      NodeMetadata.Status status = STATUS_TO_NODESTATUS.get(provisioningStateFromString(deployment.properties().provisioningState()));
-      if (status == NodeMetadata.Status.RUNNING && from.vm() != null && from.vm().statuses() != null) {
-         List<VirtualMachineInstance.VirtualMachineStatus> statuses = from.vm().statuses();
-         for (int c = 0; c < statuses.size(); c++) {
-            if (statuses.get(c).code().substring(0, 10).equals("PowerState")) {
-               if (statuses.get(c).displayStatus().equals("VM running")) {
-                  status = NodeMetadata.Status.RUNNING;
-               } else if (statuses.get(c).displayStatus().equals("VM stopped")) {
-                  status = NodeMetadata.Status.SUSPENDED;
-               }
-               break;
-            }
-         }
-      }
-
-      builder.status(status);
-
-      if (from.vm() != null) {
-         builder.hostname(deployment.name() + "pc");
-      }
-
-      Credentials credentials = credentialStore.get("node#" + from.deployment().name());
-      if (credentials != null && credentials.identity.equals(JCLOUDS_DEFAULT_USERNAME)) {
-         credentials = new Credentials(AZURE_LOGIN_USERNAME, credentials.credential);
-      }
-      else if (credentials == null) {
-         String username = AZURE_LOGIN_USERNAME;
-         String password = AZURE_LOGIN_PASSWORD;
-         if (username == null) {
-            username = "jclouds";
-         }
-         if (password == null) {
-            password = "Password1!";
-         }
-
-         credentials = new Credentials(username, password);
-      }
-      builder.credentials(LoginCredentials.fromCredentials(credentials));
-
-      final Set<String> publicIpAddresses = Sets.newLinkedHashSet();
-      if (from.ipAddressList() != null) {
-         for (int c = 0; c < from.ipAddressList().size(); c++) {
-            PublicIPAddress ip = from.ipAddressList().get(c);
-            if (ip != null && ip.properties() != null && ip.properties().ipAddress() != null)
-            {
-               publicIpAddresses.add(ip.properties().ipAddress());
-               break;
-            }
-         }
-         if (publicIpAddresses.size() > 0)
-            builder.publicAddresses(publicIpAddresses);
-      }
-      final Set<String> privateIpAddresses = Sets.newLinkedHashSet();
-      if (from.networkInterfaceCards() != null) {
-         for (NetworkInterfaceCard nic : from.networkInterfaceCards()) {
-            if (nic != null && nic.properties() != null && nic.properties().ipConfigurations() != null) {
-               for (IpConfiguration ip : nic.properties().ipConfigurations()) {
-                  if (ip != null && ip.properties() != null && ip.properties().privateIPAddress() != null) {
-                     privateIpAddresses.add(ip.properties().privateIPAddress());
-                  }
-               }
-            }
-         }
-         if (!privateIpAddresses.isEmpty()) {
-            builder.privateAddresses(privateIpAddresses);
-         }
-      }
-
-      org.jclouds.azurecompute.arm.domain.Location myLocation = null;
-      if (from.virtualMachine() != null) {
-         String locationName = from.virtualMachine().location();
-         List<org.jclouds.azurecompute.arm.domain.Location> locations = api.getLocationApi().list();
-
-         for (org.jclouds.azurecompute.arm.domain.Location location : locations) {
-            if (location.name().equals(locationName)) {
-               myLocation = location;
-               break;
-            }
-         }
-         Location jLocation = this.locationToLocation.apply(myLocation);
-         builder.location(jLocation);
-
-         ImageReference imageReference = from.virtualMachine().properties().storageProfile().imageReference();
-
-         if (imageReference != null) {
-            VMImage vmImage = VMImage.create(imageReference.publisher(), imageReference.offer(), imageReference.sku(),
-                    imageReference.version(), locationName);
-            Image image = vmImageToImage.apply(vmImage);
-            builder.imageId(image.getId());
-         }
-
-         VMSize myVMSize = null;
-         String vmSizeName = from.virtualMachine().properties().hardwareProfile().vmSize();
-         List<VMSize> vmSizes = api.getVMSizeApi(locationName).list();
-         for (VMSize vmSize : vmSizes) {
-            if (vmSize.name().equals(vmSizeName)) {
-               myVMSize = vmSize;
-               break;
-            }
-         }
-
-         VMHardware hwProfile = VMHardware.create(
-                 myVMSize.name(),
-                 myVMSize.numberOfCores(),
-                 myVMSize.osDiskSizeInMB(),
-                 myVMSize.resourceDiskSizeInMB(),
-                 myVMSize.memoryInMB(),
-                 myVMSize.maxDataDiskCount(),
-                 locationName,
-                 false);
-
-         Hardware hardware = vmHardwareToHardware.apply(hwProfile);
-         builder.hardware(hardware);
-      }
-
-      return builder.build();
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToVMDeployment.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToVMDeployment.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToVMDeployment.java
deleted file mode 100644
index 31f1a58..0000000
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToVMDeployment.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.azurecompute.arm.compute.functions;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
-import org.jclouds.azurecompute.arm.domain.Deployment;
-import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
-import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
-import org.jclouds.azurecompute.arm.domain.VMDeployment;
-import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
-
-import com.google.common.base.Function;
-
-/**
- * Converts an Deployment into a VMDeployment.
- */
-@Singleton
-public class DeploymentToVMDeployment implements Function<Deployment, VMDeployment> {
-
-   private final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
-
-   private final AzureComputeApi api;
-
-   @Inject
-   DeploymentToVMDeployment(AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants) {
-      this.api = api;
-      this.azureComputeConstants = azureComputeConstants;
-   }
-
-   @Override
-   public VMDeployment apply(final Deployment deployment) {
-      String id = deployment.id();
-      List<PublicIPAddress> ipAddressList = getIPAddresses(deployment);
-      List<NetworkInterfaceCard> networkInterfaceCards = getNetworkInterfaceCards(deployment);
-      VirtualMachine vm = api.getVirtualMachineApi(azureComputeConstants.azureResourceGroup()).get(id);
-      VirtualMachineInstance vmInstanceDetails = api.getVirtualMachineApi(azureComputeConstants.azureResourceGroup()).getInstanceDetails(id);
-      Map<String, String> userMetaData = null;
-      Iterable<String> tags = null;
-      if (vm != null && vm.tags() != null) {
-         userMetaData = vm.tags();
-         String tagString = userMetaData.get("tags");
-         tags = Arrays.asList(tagString.split(","));
-      }
-      return VMDeployment.create(deployment, ipAddressList, vmInstanceDetails, vm, networkInterfaceCards, userMetaData, tags);
-   }
-
-   private List<PublicIPAddress> getIPAddresses(Deployment deployment) {
-      List<PublicIPAddress> list = new ArrayList<PublicIPAddress>();
-      String resourceGroup = getResourceGroupFromId(deployment.id());
-
-      if (deployment.properties() != null && deployment.properties().dependencies() != null) {
-         List<Deployment.Dependency> dependencies = deployment.properties().dependencies();
-         for (int d = 0; d < dependencies.size(); d++) {
-            if (dependencies.get(d).resourceType().equals("Microsoft.Network/networkInterfaces")) {
-               List<Deployment.Dependency> dependsOn = dependencies.get(d).dependsOn();
-               for (int e = 0; e < dependsOn.size(); e++) {
-                  if (dependsOn.get(e).resourceType().equals("Microsoft.Network/publicIPAddresses")) {
-                     String resourceName = dependsOn.get(e).resourceName();
-                     PublicIPAddress ip = api.getPublicIPAddressApi(resourceGroup).get(resourceName);
-                     list.add(ip);
-                     break;
-                  }
-               }
-            }
-         }
-      }
-      return list;
-   }
-
-   private String getResourceGroupFromId(String id) {
-      String searchStr = "/resourceGroups/";
-      int indexStart = id.lastIndexOf(searchStr) + searchStr.length();
-      searchStr = "/providers/";
-      int indexEnd = id.lastIndexOf(searchStr);
-
-      String resourceGroup = id.substring(indexStart, indexEnd);
-      return resourceGroup;
-   }
-
-   private List<NetworkInterfaceCard> getNetworkInterfaceCards(Deployment deployment) {
-      List<NetworkInterfaceCard> result = new ArrayList<NetworkInterfaceCard>();
-
-      String resourceGroup = getResourceGroupFromId(deployment.id());
-
-      if (deployment.properties() != null && deployment.properties().dependencies() != null) {
-         for (Deployment.Dependency dependency : deployment.properties().dependencies()) {
-            if (dependency.resourceType().equals("Microsoft.Network/networkInterfaces")) {
-               String resourceName = dependency.resourceName();
-               NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(resourceGroup).get(resourceName);
-               result.add(nic);
-            }
-         }
-      }
-      return result;
-   }
-
-}


[2/4] jclouds-labs git commit: Refactored Azure ARM to not use Deployments

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/SubnetApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/SubnetApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/SubnetApi.java
index 1ac38d8..8f30d6c 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/SubnetApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/SubnetApi.java
@@ -16,20 +16,7 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.azurecompute.arm.domain.Subnet;
-import org.jclouds.azurecompute.arm.functions.FalseOn204;
-import org.jclouds.oauth.v2.filters.OAuthFilter;
-import org.jclouds.rest.binders.BindToJsonPayload;
-
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.MapBinder;
+import java.util.List;
 
 import javax.inject.Named;
 import javax.ws.rs.Consumes;
@@ -39,12 +26,24 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.core.MediaType;
-import java.util.List;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.azurecompute.arm.domain.Subnet;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.azurecompute.arm.functions.FalseOn204;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.binders.BindToJsonPayload;
 
 @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/virtualNetworks/{virtualnetwork}/subnets")
 
-@QueryParams(keys = "api-version", values = "2015-06-15")
-@RequestFilters(OAuthFilter.class)
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface SubnetApi {
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VMSizeApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VMSizeApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VMSizeApi.java
index 345e08c..b5917ce 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VMSizeApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VMSizeApi.java
@@ -16,24 +16,24 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
-import org.jclouds.azurecompute.arm.domain.VMSize;
-import org.jclouds.oauth.v2.filters.OAuthFilter;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
+import java.util.List;
 
 import javax.inject.Named;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.core.MediaType;
-import java.util.List;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.azurecompute.arm.domain.VMSize;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
 
 @Path("/providers/Microsoft.Compute/locations/{location}/vmSizes")
-@QueryParams(keys = "api-version", values = "2015-06-15")
-@RequestFilters(OAuthFilter.class)
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface VMSizeApi {
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
index 14f3c70..2dd6d34 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
@@ -16,10 +16,25 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import java.net.URI;
+import java.util.List;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+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.Fallbacks;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.functions.URIParser;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
@@ -32,27 +47,13 @@ import org.jclouds.rest.annotations.ResponseParser;
 import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.binders.BindToJsonPayload;
 
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-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 java.net.URI;
-import java.util.List;
-
 /**
  * The Virtual Machine API includes operations for managing the virtual machines in your subscription.
  *
  * @see <a href="https://msdn.microsoft.com/en-us/library/azure/mt163630.aspx">docs</a>
  */
 @Path("/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines")
-@RequestFilters(OAuthFilter.class)
-@QueryParams(keys = "api-version", values = "2015-06-15")
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface VirtualMachineApi {
 
@@ -66,14 +67,14 @@ public interface VirtualMachineApi {
    VirtualMachine get(@PathParam("name") String name);
 
    /**
-    * The Get Virtual Machine details
+    * Get information about the model view and instance view of a virtual machine:
     */
    @Named("GetVirtualMachineInstance")
    @GET
    @Path("/{name}/instanceView")
    @Fallback(Fallbacks.NullOnNotFoundOr404.class)
    VirtualMachineInstance getInstanceDetails(@PathParam("name") String name);
-
+   
    /**
     * The Create Virtual Machine
     */

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApi.java
index 0acbdee..1e657f3 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApi.java
@@ -15,22 +15,7 @@
  * limitations under the License.
  */
 package org.jclouds.azurecompute.arm.features;
-import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-
-import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
-
-import org.jclouds.azurecompute.arm.functions.FalseOn204;
-import org.jclouds.oauth.v2.filters.OAuthFilter;
-
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.MapBinder;
-import org.jclouds.rest.binders.BindToJsonPayload;
+import java.util.List;
 
 import javax.inject.Named;
 import javax.ws.rs.Consumes;
@@ -40,11 +25,23 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.core.MediaType;
-import java.util.List;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.azurecompute.arm.functions.FalseOn204;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.binders.BindToJsonPayload;
 
 @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/virtualNetworks")
-@QueryParams(keys = "api-version", values = "2015-06-15")
-@RequestFilters(OAuthFilter.class)
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface VirtualNetworkApi {
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/filters/ApiVersionFilter.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/filters/ApiVersionFilter.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/filters/ApiVersionFilter.java
new file mode 100644
index 0000000..904c2e8
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/filters/ApiVersionFilter.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.filters;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
+import static org.jclouds.util.Maps2.transformKeys;
+import static org.jclouds.util.Predicates2.startsWith;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.jclouds.http.HttpException;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpRequestFilter;
+import org.jclouds.rest.config.InvocationConfig;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.reflect.Invokable;
+
+/**
+ * Allow users to customize the api versions for each method call.
+ * <p>
+ * In Azure ARM, each method may have its own api version. This filter allows to
+ * configure the versions of each method, so there is no need to change the code
+ * when Azure deprecates old versions.
+ */
+public class ApiVersionFilter implements HttpRequestFilter {
+
+   private final InvocationConfig config;
+   private final Map<String, String> versions;
+
+   @Inject
+   ApiVersionFilter(InvocationConfig config, Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) {
+      this.config = config;
+      this.versions = versions(filterStringsBoundByName);
+   }
+
+   @Override
+   public HttpRequest filter(HttpRequest request) throws HttpException {
+      checkArgument(request instanceof GeneratedHttpRequest,
+            "This filter can only be applied to GeneratedHttpRequest objects");
+      GeneratedHttpRequest generatedRequest = (GeneratedHttpRequest) request;
+
+      // Look if there is a custom api version for the current method
+      String commandName = config.getCommandName(generatedRequest.getInvocation());
+      String customApiVersion = versions.get(commandName);
+
+      if (customApiVersion == null) {
+         // No custom config for the specific method. Let's look for custom
+         // config for the class
+         Invokable<?, ?> invoked = generatedRequest.getInvocation().getInvokable();
+         String className = invoked.getOwnerType().getRawType().getSimpleName();
+         customApiVersion = versions.get(className);
+      }
+
+      if (customApiVersion != null) {
+         return request.toBuilder().replaceQueryParam("api-version", customApiVersion).build();
+      }
+
+      return request;
+   }
+
+   private static Map<String, String> versions(Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) {
+      Map<String, String> stringBoundWithApiVersionPrefix = filterStringsBoundByName
+            .apply(startsWith(API_VERSION_PREFIX));
+      return transformKeys(stringBoundWithApiVersionPrefix, new Function<String, String>() {
+         public String apply(String input) {
+            return input.replaceFirst(API_VERSION_PREFIX, "");
+         }
+      });
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java
index 6970887..39cc32c 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java
@@ -14,127 +14,163 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package  org.jclouds.azurecompute.arm.functions;
+package org.jclouds.azurecompute.arm.functions;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.notNull;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static org.jclouds.util.Closeables2.closeQuietly;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
 
 import javax.annotation.Resource;
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
-import com.google.common.base.Predicate;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
-import org.jclouds.azurecompute.arm.domain.Deployment;
+import org.jclouds.azurecompute.arm.domain.IdReference;
+import org.jclouds.azurecompute.arm.domain.IpConfiguration;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
-import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
-import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
+import org.jclouds.azurecompute.arm.domain.ResourceGroup;
+import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
+import org.jclouds.azurecompute.arm.util.BlobHelper;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.logging.Logger;
 
 import com.google.common.base.Function;
-
-import java.net.URI;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 
 @Singleton
 public class CleanupResources implements Function<String, Boolean> {
 
-   private final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
 
    protected final AzureComputeApi api;
-   private Predicate<URI> nodeTerminated;
-   private Predicate<URI> resourceDeleted;
+   private final Predicate<URI> resourceDeleted;
+   private final StorageProfileToStorageAccountName storageProfileToStorageAccountName;
 
    @Inject
-   public CleanupResources(AzureComputeApi azureComputeApi,
-                           AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
-                           @Named(TIMEOUT_NODE_TERMINATED) Predicate<URI> nodeTerminated,
-                           @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted) {
-      this.azureComputeConstants = azureComputeConstants;
+   CleanupResources(AzureComputeApi azureComputeApi, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
+         StorageProfileToStorageAccountName storageProfileToStorageAccountName) {
       this.api = azureComputeApi;
-      this.nodeTerminated = nodeTerminated;
       this.resourceDeleted = resourceDeleted;
+      this.storageProfileToStorageAccountName = storageProfileToStorageAccountName;
    }
 
    @Override
-   public Boolean apply(String id) {
-
-      logger.debug("Destroying %s ...", id);
-      String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + "stor";
-      String group = azureComputeConstants.azureResourceGroup();
-
-      VirtualMachine vm = api.getVirtualMachineApi(group).get(id);
-      if (vm != null) {
-         URI uri = api.getVirtualMachineApi(group).delete(id);
-         if (uri != null) {
-            boolean jobDone = nodeTerminated.apply(uri);
-            boolean storageAcctDeleteStatus = false;
-            boolean deploymentDeleteStatus = false;
-
-            if (jobDone) {
-               Deployment deployment = api.getDeploymentApi(group).get(id);
-               if (deployment != null) {
-                  uri = api.getDeploymentApi(group).delete(id);
-                  jobDone = resourceDeleted.apply(uri);
-                  if (jobDone) {
-                     deploymentDeleteStatus = true;
-                  }
-               } else {
-                  deploymentDeleteStatus = true;
+   public Boolean apply(final String id) {
+      logger.debug(">> destroying %s ...", id);
+
+      Map<String, VirtualMachine> resourceGroupNamesAndVirtualMachines = getResourceGroupNamesAndVirtualMachines(id);
+      if (resourceGroupNamesAndVirtualMachines.isEmpty())
+         return true;
+
+      String group = checkNotNull(resourceGroupNamesAndVirtualMachines.entrySet().iterator().next().getKey(),
+            "resourceGroup name must not be null");
+      VirtualMachine virtualMachine = checkNotNull(resourceGroupNamesAndVirtualMachines.get(group),
+            "virtualMachine must not be null");
+
+      boolean vmDeleted = deleteVirtualMachine(group, virtualMachine);
+      
+      // We don't delete the network here, as it is global to the resource
+      // group. It will be deleted when the resource group is deleted
+
+      for (String nicName : getNetworkCardInterfaceNames(virtualMachine)) {
+         NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(group).get(nicName);
+         Iterable<String> publicIps = getPublicIps(group, nic);
+
+         logger.debug(">> destroying nic %s...", nicName);
+         URI nicDeletionURI = api.getNetworkInterfaceCardApi(group).delete(nicName);
+         resourceDeleted.apply(nicDeletionURI);
+
+         for (String publicIp : publicIps) {
+            logger.debug(">> deleting public ip nic %s...", publicIp);
+            api.getPublicIPAddressApi(group).delete(publicIp);
+         }
+      }
+
+      String storageAccountName = storageProfileToStorageAccountName.apply(virtualMachine.properties().storageProfile());
+      StorageServiceKeys keys = api.getStorageAccountApi(group).getKeys(storageAccountName);
+
+      // Remove the virtual machine files
+      logger.debug(">> deleting virtual machine disk storage...");
+      BlobHelper blobHelper = new BlobHelper(storageAccountName, keys.key1());
+      try {
+         blobHelper.deleteContainerIfExists("vhds");
+
+         if (!blobHelper.customImageExists()) {
+            logger.debug(">> deleting storage account %s...", storageAccountName);
+            api.getStorageAccountApi(group).delete(storageAccountName);
+         } else {
+            logger.debug(">> the storage account contains custom images. Will not delete it!");
+         }
+      } finally {
+         closeQuietly(blobHelper);
+      }
+
+      deleteResourceGroupIfEmpty(group);
+
+      return vmDeleted;
+   }
+
+   public void deleteResourceGroupIfEmpty(String group) {
+      if (api.getVirtualMachineApi(group).list().isEmpty() 
+            && api.getStorageAccountApi(group).list().isEmpty()
+            && api.getNetworkInterfaceCardApi(group).list().isEmpty()
+            && api.getPublicIPAddressApi(group).list().isEmpty()) {
+         logger.debug(">> the resource group %s is empty. Deleting...", group);
+         resourceDeleted.apply(api.getResourceGroupApi().delete(group));
+      }
+   }
+
+   private Iterable<String> getPublicIps(String group, NetworkInterfaceCard nic) {
+      return transform(
+            filter(transform(nic.properties().ipConfigurations(), new Function<IpConfiguration, IdReference>() {
+               @Override
+               public IdReference apply(IpConfiguration input) {
+                  return input.properties().publicIPAddress();
                }
-               NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(group).get(id + "nic");
-               if (nic != null) {
-                  uri = api.getNetworkInterfaceCardApi(group).delete(id + "nic");
-                  if (uri != null) {
-                     jobDone = resourceDeleted.apply(uri);
-                     if (jobDone) {
-                        boolean ipDeleteStatus = false;
-                        PublicIPAddress ip = api.getPublicIPAddressApi(group).get(id + "publicip");
-                        if (ip != null) {
-                           ipDeleteStatus = api.getPublicIPAddressApi(group).delete(id + "publicip");
-                        } else {
-                           ipDeleteStatus = true;
-                        }
-
-                        // Get NSG
-                        boolean nsgDeleteStatus = false;
-                        NetworkSecurityGroup nsg = api.getNetworkSecurityGroupApi(group).get(id + "nsg");
-                        if (nsg != null) {
-                           uri = api.getNetworkSecurityGroupApi(group).delete(id + "nsg");
-                           jobDone = resourceDeleted.apply(uri);
-                           if (jobDone) {
-                              nsgDeleteStatus = true;
-
-                           }
-                        }
-                        else {
-                           nsgDeleteStatus = true;
-                        }
-
-                        return deploymentDeleteStatus && storageAcctDeleteStatus && ipDeleteStatus && nsgDeleteStatus;
-                     } else {
-                        return false;
-                     }
-                  } else {
-                     return false;
-                  }
-               } else {
-                  return false;
+            }), notNull()), new Function<IdReference, String>() {
+               @Override
+               public String apply(IdReference input) {
+                  return Iterables.getLast(Splitter.on("/").split(input.id()));
                }
-            } else {
-               return false;
-            }
-         } else {
-            return false;
+            });
+   }
+
+   private List<String> getNetworkCardInterfaceNames(VirtualMachine virtualMachine) {
+      List<String> nics = Lists.newArrayList();
+      for (IdReference idReference : virtualMachine.properties().networkProfile().networkInterfaces()) {
+         nics.add(Iterables.getLast(Splitter.on("/").split(idReference.id())));
+      }
+      return nics;
+   }
+
+   private boolean deleteVirtualMachine(String group, VirtualMachine virtualMachine) {
+      return resourceDeleted.apply(api.getVirtualMachineApi(group).delete(virtualMachine.name()));
+   }
+
+   private Map<String, VirtualMachine> getResourceGroupNamesAndVirtualMachines(String id) {
+      for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
+         String group = resourceGroup.name();
+         VirtualMachine virtualMachine = api.getVirtualMachineApi(group).get(id);
+         if (virtualMachine != null) {
+            return ImmutableMap.of(group, virtualMachine);
          }
-      } else {
-         return false;
       }
+      return Maps.newHashMap();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/StorageProfileToStorageAccountName.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/StorageProfileToStorageAccountName.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/StorageProfileToStorageAccountName.java
new file mode 100644
index 0000000..f624886
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/StorageProfileToStorageAccountName.java
@@ -0,0 +1,38 @@
+/*
+ * 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.azurecompute.arm.functions;
+
+import java.net.URI;
+
+import org.jclouds.azurecompute.arm.domain.StorageProfile;
+
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+
+/**
+ * Returns the storage account name for a given storage profile.
+ */
+public class StorageProfileToStorageAccountName implements Function<StorageProfile, String> {
+
+   @Override
+   public String apply(StorageProfile input) {
+      String storageAccountNameURI = input.osDisk().vhd().uri();
+      return Iterables.get(Splitter.on(".").split(URI.create(storageAccountNameURI).getHost()), 0);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
index f5bfc75..b42ea5e 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
@@ -16,76 +16,68 @@
  */
 package org.jclouds.azurecompute.arm.util;
 
+import static org.jclouds.util.Closeables2.closeQuietly;
+
+import java.io.Closeable;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.jclouds.ContextBuilder;
-import org.jclouds.azure.storage.domain.BoundedSet;
 import org.jclouds.azureblob.AzureBlobClient;
 import org.jclouds.azureblob.domain.BlobProperties;
 import org.jclouds.azureblob.domain.ContainerProperties;
 import org.jclouds.azureblob.domain.ListBlobsResponse;
 import org.jclouds.azurecompute.arm.domain.VMImage;
-import org.jclouds.util.Closeables2;
 
-public class BlobHelper {
+public class BlobHelper implements Closeable {
 
-   public static void deleteContainerIfExists(String storage, String key, String containerName) {
-      final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob")
-              .credentials(storage, key)
-              .buildApi(AzureBlobClient.class);
+   private final String storageAccount;
+   private final AzureBlobClient azureBlob;
 
-      try {
-         azureBlob.deleteContainer(containerName);
-      }
-      finally {
-         Closeables2.closeQuietly(azureBlob);
-      }
+   public BlobHelper(String storageAccount, String key) {
+      this.storageAccount = storageAccount;
+      this.azureBlob = ContextBuilder.newBuilder("azureblob").credentials(storageAccount, key)
+            .buildApi(AzureBlobClient.class);
    }
 
-   public static boolean customImageExists(String storage, String key) {
-      final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob")
-              .credentials(storage, key)
-              .buildApi(AzureBlobClient.class);
+   @Override
+   public void close() throws IOException {
+      closeQuietly(azureBlob);
+   }
 
-      try {
-         return azureBlob.containerExists("system");
-      }
-      finally {
-         Closeables2.closeQuietly(azureBlob);
-      }
+   public void deleteContainerIfExists(String containerName) {
+      azureBlob.deleteContainer(containerName);
    }
 
-   public static List<VMImage> getImages(String containerName, String group,
-                                         String storageAccountName, String key, String offer, String location) {
-      final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob")
-              .credentials(storageAccountName, key)
-              .buildApi(AzureBlobClient.class);
+   public boolean hasContainers() {
+      return !azureBlob.listContainers().isEmpty();
+   }
 
+   public boolean customImageExists() {
+      return azureBlob.containerExists("system");
+   }
 
+   public List<VMImage> getImages(String containerName, String group, String offer, String location) {
       List<VMImage> list = new ArrayList<VMImage>();
-      try {
-         BoundedSet<ContainerProperties> containerList = azureBlob.listContainers();
-         for (ContainerProperties props : containerList) {
-            if (props.getName().equals("system")) {
-               ListBlobsResponse blobList = azureBlob.listBlobs("system");
-               String osDisk = "";
-               String dataDisk = "";
-
-               for (BlobProperties blob : blobList) {
-                  String name = blob.getName();
-
-                  if (dataDisk.length() == 0) dataDisk = name.substring(1 + name.lastIndexOf('/'));
-                  else if (osDisk.length() == 0) osDisk = name.substring(1 + name.lastIndexOf('/'));
-               }
-               final VMImage ref = VMImage.create(group, storageAccountName, osDisk, dataDisk, "test-create-image", "custom", location);
-               list.add(ref);
+
+      ContainerProperties systemContainer = azureBlob.getContainerProperties("system");
+      if (systemContainer != null) {
+         ListBlobsResponse blobList = azureBlob.listBlobs(systemContainer.getName());
+         for (BlobProperties blob : blobList) {
+            String name = blob.getName();
+
+            if (name.contains("-osDisk")) {
+               String imageName = name.substring(name.lastIndexOf('/') + 1, name.indexOf("-osDisk"));
+               String imageUrl = blob.getUrl().toString();
+
+               list.add(VMImage.customImage().group(group).storage(storageAccount).vhd1(imageUrl).name(imageName)
+                     .offer(offer).location(location).build());
             }
          }
       }
-      finally {
-         Closeables2.closeQuietly(azureBlob);
-      }
+
       return list;
    }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java
deleted file mode 100644
index e5b0a43..0000000
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
- * 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.azurecompute.arm.util;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
-import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
-import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
-import org.jclouds.azurecompute.arm.domain.DataDisk;
-import org.jclouds.azurecompute.arm.domain.DeploymentBody;
-import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
-import org.jclouds.azurecompute.arm.domain.DeploymentTemplate;
-import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
-import org.jclouds.azurecompute.arm.domain.DnsSettings;
-import org.jclouds.azurecompute.arm.domain.HardwareProfile;
-import org.jclouds.azurecompute.arm.domain.IdReference;
-import org.jclouds.azurecompute.arm.domain.ImageReference;
-import org.jclouds.azurecompute.arm.domain.IpConfiguration;
-import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
-import org.jclouds.azurecompute.arm.domain.KeyVaultReference;
-import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
-import org.jclouds.azurecompute.arm.domain.NetworkProfile;
-import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
-import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
-import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
-import org.jclouds.azurecompute.arm.domain.OSDisk;
-import org.jclouds.azurecompute.arm.domain.OSProfile;
-import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
-import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
-import org.jclouds.azurecompute.arm.domain.StorageProfile;
-import org.jclouds.azurecompute.arm.domain.StorageService;
-import org.jclouds.azurecompute.arm.domain.StorageService.StorageServiceProperties;
-import org.jclouds.azurecompute.arm.domain.TemplateParameterType;
-import org.jclouds.azurecompute.arm.domain.VHD;
-import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.json.Json;
-import org.jclouds.predicates.Validator;
-import org.jclouds.predicates.validators.DnsNameValidator;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-import com.google.inject.Inject;
-import com.google.inject.assistedinject.Assisted;
-
-import static com.google.common.io.BaseEncoding.base64;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION;
-
-public class DeploymentTemplateBuilder {
-   public interface Factory {
-      DeploymentTemplateBuilder create(@Assisted("group") String group, @Assisted("name") String name, Template template);
-   }
-
-   private final String name;
-   private final String azureGroup;
-   private final String group;
-   private final Template template;
-   private final Json json;
-
-   private AzureTemplateOptions options;
-   private Iterable<String> tags;
-   private Map<String, String> userMetaData;
-   private List<ResourceDefinition> resources;
-   private Map<String, String> variables;
-   private static String loginUser;
-   private static String loginPassword;
-   private String location;
-   private AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
-
-   private static final String DEPLOYMENT_MODE = "Incremental";
-
-   @Inject
-   DeploymentTemplateBuilder(Json json, @Assisted("group") String group, @Assisted("name") String name, @Assisted Template template,
-                             final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants) {
-      this.name = name;
-      this.group = group;
-      this.template = template;
-      this.options = template.getOptions().as(AzureTemplateOptions.class);
-      this.tags = template.getOptions().getTags();
-      this.userMetaData = template.getOptions().getUserMetadata();
-      this.variables = new HashMap<String, String>();
-      this.resources = new ArrayList<ResourceDefinition>();
-      this.location = template.getLocation().getId();
-      this.json = json;
-
-      this.azureComputeConstants = azureComputeConstants;
-      this.azureGroup = this.azureComputeConstants.azureResourceGroup();
-
-      String[] defaultLogin = this.azureComputeConstants.azureDefaultImageLogin().split(":");
-      String defaultUser = null;
-      String defaultPassword = null;
-
-      if (defaultLogin.length == 2) {
-         defaultUser = defaultLogin[0].trim();
-         defaultPassword = defaultLogin[1].trim();
-      }
-
-      loginUser = options.getLoginUser() == null ? defaultUser : options.getLoginUser();
-      loginPassword = options.getLoginPassword() == null ? defaultPassword : options.getLoginPassword();
-   }
-
-   public static String getLoginUserUsername() {
-      return loginUser;
-   }
-
-   public static String getLoginPassword() {
-      return loginPassword;
-   }
-
-   public Template getTemplate() {
-      return template;
-   }
-
-   public DeploymentBody getDeploymentTemplate() {
-
-      addStorageResource();
-      addPublicIpAddress();
-      addNetworkSecurityGroup();
-      addNetworkInterfaceCard();
-      addVirtualMachine();
-
-
-      DeploymentTemplate.TemplateParameters templateParameters = null;
-      DeploymentTemplate.Parameters parameters = null;
-
-      if (keyVaultInUse()){
-         String[] keyVaultInfo = options.getKeyVaultIdAndSecret().split(":");
-         Preconditions.checkArgument(keyVaultInfo.length == 2);
-         String vaultId = keyVaultInfo[0].trim();
-         String secretName = keyVaultInfo[1].trim();
-
-         templateParameters = DeploymentTemplate.TemplateParameters.create(TemplateParameterType.create("securestring"));
-         parameters = DeploymentTemplate.Parameters.create(KeyVaultReference.create(KeyVaultReference.Reference.create(IdReference.create(vaultId), secretName)));
-      } else {
-         templateParameters = DeploymentTemplate.TemplateParameters.create(null);
-         parameters = DeploymentTemplate.Parameters.create(null);
-      }
-
-
-      DeploymentTemplate template = DeploymentTemplate.builder()
-              .schema("https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#")
-              .contentVersion("1.0.0.0")
-              .resources(resources)
-              .variables(variables)
-              .parameters(templateParameters)
-              .build();
-
-      DeploymentBody body = DeploymentBody.create(template, DEPLOYMENT_MODE, parameters);
-
-      return body;
-   }
-
-   public String getDeploymentTemplateJson(DeploymentProperties properties) {
-      return json.toJson(properties);
-   }
-
-   private void addStorageResource() {
-      String storageAccountName = null;
-
-      String imageName = template.getImage().getName();
-      if (imageName.startsWith(CUSTOM_IMAGE_PREFIX)) {
-         storageAccountName = template.getImage().getVersion();
-      }
-
-      if (Strings.isNullOrEmpty(storageAccountName)) {
-         storageAccountName = generateStorageAccountName(name);
-      }
-
-      Validator<String> validator = new DnsNameValidator(3, 24);
-      validator.validate(storageAccountName);
-
-      variables.put("storageAccountName", storageAccountName);
-
-      ResourceDefinition storageAccount = ResourceDefinition.builder()
-              .name("[variables('storageAccountName')]")
-              .type("Microsoft.Storage/storageAccounts")
-              .location(location)
-              .apiVersion(STORAGE_API_VERSION)
-              .properties(
-                      StorageServiceProperties.builder()
-                              .accountType(StorageService.AccountType.Standard_LRS)
-                              .build()
-              )
-              .build();
-
-      resources.add(storageAccount);
-   }
-
-   private void addPublicIpAddress() {
-      String publicIPAddressName = name + "publicip";
-      String dnsLabelPrefix = options.getDNSLabelPrefix();
-
-      PublicIPAddressProperties.Builder properties = PublicIPAddressProperties.builder();
-
-      if (!Strings.isNullOrEmpty(dnsLabelPrefix)) {
-         properties.dnsSettings(DnsSettings.builder().domainNameLabel(dnsLabelPrefix).build());
-         variables.put("dnsLabelPrefix", dnsLabelPrefix);
-      }
-
-      properties.publicIPAllocationMethod("Dynamic");
-      variables.put("publicIPAddressName", publicIPAddressName);
-      variables.put("publicIPAddressReference", "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]");
-
-      ResourceDefinition publicIpAddress = ResourceDefinition.builder()
-              .name("[variables('publicIPAddressName')]")
-              .type("Microsoft.Network/publicIPAddresses")
-              .location(location)
-              .apiVersion(STORAGE_API_VERSION)
-              .properties(properties.build())
-              .build();
-
-      resources.add(publicIpAddress);
-   }
-
-   private void addNetworkInterfaceCard() {
-
-      List<IpConfiguration> ipConfigurations = new ArrayList<IpConfiguration>();
-
-      String ipConfigurationName = name + "ipconfig";
-      String subnetId = options.getSubnetId();
-      String vnetName = options.getVirtualNetworkName();
-
-      variables.put("ipConfigurationName", ipConfigurationName);
-      variables.put("subnetReference", subnetId);
-
-      IpConfiguration ipConfig = IpConfiguration.create(ipConfigurationName, null, null, null,
-              IpConfigurationProperties.builder()
-                      .privateIPAllocationMethod("Dynamic")
-                      .publicIPAddress(IdReference.create("[variables('publicIPAddressReference')]"))
-                      .subnet(IdReference.create("[variables('subnetReference')]"))
-                      .build());
-
-      ipConfigurations.add(ipConfig);
-
-      // Check to see if we have defined a network security group
-      IdReference networkSecurityGroup = null;
-      int ports[] = options.getInboundPorts();
-      if ((ports != null) && (ports.length > 0)) {
-         networkSecurityGroup = IdReference.create("[variables('networkSecurityGroupNameReference')]");
-      }
-
-      ArrayList<String> depends = new ArrayList<String>(Arrays.asList("[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]"));
-
-      NetworkInterfaceCardProperties.Builder networkInterfaceCardPropertiesBuilder = NetworkInterfaceCardProperties.builder();
-      networkInterfaceCardPropertiesBuilder.ipConfigurations(ipConfigurations);
-      if (networkSecurityGroup != null) {
-         networkInterfaceCardPropertiesBuilder.networkSecurityGroup(networkSecurityGroup);
-         depends.add("[concat('Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]");
-      }
-      NetworkInterfaceCardProperties networkInterfaceCardProperties = networkInterfaceCardPropertiesBuilder.build();
-
-      String networkInterfaceCardName = name + "nic";
-      variables.put("networkInterfaceCardName", networkInterfaceCardName);
-      variables.put("networkInterfaceCardReference", "[resourceId('Microsoft.Network/networkInterfaces',variables('networkInterfaceCardName'))]");
-
-      ResourceDefinition networkInterfaceCard = ResourceDefinition.builder()
-              .name("[variables('networkInterfaceCardName')]")
-              .type("Microsoft.Network/networkInterfaces")
-              .location(location)
-              .apiVersion(STORAGE_API_VERSION)
-              .dependsOn(depends)
-              .properties(networkInterfaceCardProperties)
-              .build();
-
-      resources.add(networkInterfaceCard);
-   }
-
-   private void addNetworkSecurityGroup() {
-      int inboundPorts[] = options.getInboundPorts();
-      if ((inboundPorts != null) && (inboundPorts.length > 0)) {
-         variables.put("networkSecurityGroupName", name + "nsg");
-         variables.put("networkSecurityGroupNameReference", "[resourceId('Microsoft.Network/networkSecurityGroups',variables('networkSecurityGroupName'))]");
-
-         List<String> portRanges = simplifyPorts(inboundPorts);
-
-         List<NetworkSecurityRule> rules = new ArrayList<NetworkSecurityRule>();
-         int priority = 1234;
-         for (String portRange : portRanges) {
-            NetworkSecurityRuleProperties ruleProperties = NetworkSecurityRuleProperties.builder()
-                    .description("default-allow-port-" + portRange)
-                    .protocol(NetworkSecurityRuleProperties.Protocol.All)
-                    .access(NetworkSecurityRuleProperties.Access.Allow)
-                    .sourcePortRange("*")
-                    .destinationPortRange(portRange)
-                    .sourceAddressPrefix("*")
-                    .destinationAddressPrefix("*")
-                    .priority(priority)
-                    .direction(NetworkSecurityRuleProperties.Direction.Inbound)
-                    .build();
-
-            NetworkSecurityRule networkSecurityRule = NetworkSecurityRule.create(
-                    "default-allow-port-" + portRange,
-                    null,
-                    null,
-                    ruleProperties);
-
-            rules.add(networkSecurityRule);
-            priority++;
-         }
-
-         NetworkSecurityGroupProperties networkSecurityGroupProperties = NetworkSecurityGroupProperties.builder()
-                 .securityRules(rules)
-                 .build();
-
-         ResourceDefinition networkSecurityGroup = ResourceDefinition.builder()
-                 .name("[variables('networkSecurityGroupName')]")
-                 .type("Microsoft.Network/networkSecurityGroups").location(location)
-                 .apiVersion(STORAGE_API_VERSION)
-                 .properties(networkSecurityGroupProperties)
-                 .build();
-         resources.add(networkSecurityGroup);
-      }
-
-   }
-
-   /**
-    * Helper function for simplifying an array of ports to a list of ranges as list of strings
-    * @param ports array of int
-    * @return list of strings representing ranges
-    */
-   public static List<String> simplifyPorts(int[] ports) {
-      Preconditions.checkArgument(ports != null && ports.length != 0);
-      ArrayList<String> output = new ArrayList<String>();
-      Arrays.sort(ports);
-
-      int range_start = ports[0];
-      int range_end = ports[0];
-      for (int i = 1; i < ports.length; i++) {
-         if ((ports[i - 1] == ports[i] - 1) || (ports[i - 1] == ports[i])){
-            // Range continues.
-            range_end = ports[i];
-         }
-         else {
-            // Range ends.
-            output.add(formatRange(range_start, range_end));
-            range_start = ports[i];
-            range_end = ports[i];
-         }
-      }
-      // Make sure we get the last range.
-      output.add(formatRange(range_start, range_end));
-      return output;
-   }
-
-   private static String formatRange(int start, int finish) {
-      if (start == finish){
-         return Integer.toString(start);
-      }
-      else {
-         return String.format("%s-%s", Integer.toString(start), Integer.toString(finish));
-      }
-   }
-
-   private void addVirtualMachine() {
-      //Build OS Profile
-      final String computerName = name + "pc";
-
-      variables.put("loginUser", loginUser);
-      OSProfile.Builder profileBuilder = OSProfile.builder()
-              .adminUsername(loginUser)
-              .computerName(computerName);
-
-      profileBuilder.adminPassword(loginPassword);
-      //boolean usePublicKey = options.getPublicKey() != null;
-
-      if (keyVaultInUse()) {
-         OSProfile.LinuxConfiguration configuration = OSProfile.LinuxConfiguration.create("false",
-                 OSProfile.LinuxConfiguration.SSH.create(Arrays.asList(
-                         OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create(
-                                 "[concat('/home/',variables('loginUser'),'/.ssh/authorized_keys')]",
-                                 "[parameters('publicKeyFromAzureKeyVault')]"
-                         ))
-                 ));
-         profileBuilder.linuxConfiguration(configuration);
-      }
-
-      if (!Strings.isNullOrEmpty(options.getCustomData())){
-         String encodedCustomData = base64().encode(options.getCustomData().getBytes());
-         profileBuilder.customData(encodedCustomData);
-      }
-
-      OSProfile osProfile = profileBuilder.build();
-
-      //Build OsDisk
-      final String storageAccountContainerName = name + "vhds";
-      variables.put("storageAccountContainerName", storageAccountContainerName);
-
-      final String osDiskName = name + "osdisk";
-      variables.put("osDiskName", osDiskName);
-
-      boolean usingMarketplaceImage = true;
-      String cusotomImageUri = "";
-
-      // Handle custom image case if description starts with CUSTOM_IMAGE_PREFIX
-      String vhd1 = template.getImage().getProviderId();
-      String description = template.getImage().getDescription();
-      if (description.substring(0, CUSTOM_IMAGE_PREFIX.length()).equals(CUSTOM_IMAGE_PREFIX)) {
-         String storageName = template.getImage().getVersion();
-         cusotomImageUri = vhd1;
-         cusotomImageUri = "https://" + storageName + ".blob.core.windows.net/system/Microsoft.Compute/Images/" + AzureComputeImageExtension.CONTAINER_NAME + "/" + cusotomImageUri;
-      }
-
-      if (!cusotomImageUri.isEmpty()) {
-         usingMarketplaceImage = false;
-      }
-
-      OSDisk osDisk = getOsDisk("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net/',variables('storageAccountContainerName'),'/',variables('osDiskName'),'.vhd')]", cusotomImageUri);
-
-      //Create Data Disk(s) and add to list
-      final String dataDiskName = name + "datadisk";
-      variables.put("dataDiskName", dataDiskName);
-
-      List<DataDisk> dataDisks = new ArrayList<DataDisk>();
-      DataDisk dataDisk = DataDisk.builder()
-              .name("[variables('dataDiskName')]")
-              .diskSizeGB(azureComputeConstants.azureDefaultDataDiskSizeProperty())
-              .lun(0)
-              .vhd(
-                      VHD.create("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net/',variables('storageAccountContainerName'),'/',variables('dataDiskName'),'.vhd')]")
-              )
-              .createOption("Empty")
-              .build();
-
-      dataDisks.add(dataDisk);
-
-      //Create Storage Profile
-      StorageProfile.Builder storageProfileBuilder = StorageProfile.builder()
-              .osDisk(osDisk)
-              .dataDisks(dataDisks);
-
-      if (usingMarketplaceImage) {
-         //Build Image Reference if marketplace image is used
-         ImageReference imageReference = getImageReference(template.getImage().getProviderId(),
-                 template.getImage().getName(),
-                 template.getImage().getVersion());
-
-         storageProfileBuilder.imageReference(imageReference);
-      }
-      StorageProfile storageProfile = storageProfileBuilder.build();
-
-
-      //Create Network Profile for this VM (links to network interface cards)
-      NetworkProfile networkProfile = NetworkProfile.create(
-              Arrays.asList(
-                      IdReference.create("[variables('networkInterfaceCardReference')]")
-              ));
-
-      //Boot Diagnostics
-      DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(
-              DiagnosticsProfile.BootDiagnostics.builder()
-                      .enabled(true)
-                      .storageUri("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net')]")
-                      .build());
-
-      //Build VirtualMachine properties based on above properties.
-      final String vmSize = template.getHardware().getId();
-      HardwareProfile hw = HardwareProfile.create(vmSize);
-
-      VirtualMachineProperties properties = VirtualMachineProperties.builder()
-              .hardwareProfile(hw)
-              .osProfile(osProfile)
-              .storageProfile(storageProfile)
-              .networkProfile(networkProfile)
-              .diagnosticsProfile(diagnosticsProfile)
-              .build();
-
-
-      String tagString = Joiner.on(",").join(Lists.newArrayList(tags));
-      if (tagString.isEmpty())
-         tagString = "jclouds";
-      userMetaData.put("tags", tagString);
-
-      variables.put("virtualMachineName", name);
-      ResourceDefinition virtualMachine = ResourceDefinition.builder()
-              .name("[variables('virtualMachineName')]")
-              .type("Microsoft.Compute/virtualMachines")
-              .location(location)
-              .apiVersion("2015-06-15")
-              .dependsOn(Arrays.asList("[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
-                      "[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceCardName'))]"))
-              .tags(userMetaData)
-              .properties(properties)
-              .build();
-
-      resources.add(virtualMachine);
-   }
-
-
-   private ImageReference getImageReference(String publisher, String offer, String sku) {
-      return ImageReference.builder()
-              .publisher(publisher)
-              .offer(offer)
-              .sku(sku)
-              .version("latest")
-              .build();
-
-   }
-
-   private OSDisk getOsDisk(String vhdUri, String imageUri) {
-      OSDisk.Builder builder = OSDisk.builder();
-      builder.name("[variables('osDiskName')]");
-      builder.caching("ReadWrite");
-      builder.createOption("FromImage");
-      builder.vhd(VHD.create(vhdUri));
-
-      if (!imageUri.isEmpty()) {
-         builder.osType("Linux");
-         builder.image(VHD.create(imageUri));
-      }
-      return builder.build();
-   }
-
-   private boolean keyVaultInUse(){
-      return !Strings.isNullOrEmpty(options.getKeyVaultIdAndSecret());
-   }
-
-   /**
-    * Generates a valid storage account
-    *
-    * Storage account names must be between 3 and 24 characters in length and may contain numbers and lowercase letters only.
-    *
-    * @param name the node name
-    * @return the storage account name starting from a sanitized name (with only numbers and lowercase letters only ).
-    * If sanitized name is between 3 and 24 characters, storage account name is equals to sanitized name.
-    * If sanitized name is less than 3 characters, storage account is sanitized name plus 4 random chars.
-    * If sanitized name is more than 24 characters, storage account is first 10 chars of sanitized name plus 4 random chars plus last 10 chars of sanitized name.
-    */
-   private static String generateStorageAccountName(String name) {
-      String storageAccountName = name.replaceAll("[^a-z0-9]", "");
-      int nameLength = storageAccountName.length();
-      if (nameLength >= 3 && nameLength <= 24) {
-         return storageAccountName;
-      }
-
-      String random = UUID.randomUUID().toString().replaceAll("[^a-z0-9]", "").substring(0, 4);
-      if (nameLength < 3) {
-         storageAccountName = new StringBuilder().append(storageAccountName).append(random).toString();
-      }
-      if (nameLength > 24) {
-         storageAccountName = shorten(storageAccountName, random);
-      }
-      return storageAccountName;
-   }
-
-   private static String shorten(String storageAccountName, String random) {
-      String prefix = storageAccountName.substring(0, 10);
-      String suffix = storageAccountName.substring(storageAccountName.length() - 10, storageAccountName.length());
-      return String.format("%s%s%s", prefix, random, suffix);
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/GetEnumValue.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/GetEnumValue.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/GetEnumValue.java
index 4a61613..f42bad3 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/GetEnumValue.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/GetEnumValue.java
@@ -20,7 +20,6 @@ import java.util.EnumSet;
 
 public class GetEnumValue {
 
-   @SuppressWarnings("unchecked")
    public static <T extends Enum<T>> Enum<T> fromValueOrDefault(String text, Enum<T> defaultValue) {
       if (text != null) {
          EnumSet<T> elements = EnumSet.allOf(defaultValue.getDeclaringClass());

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
index d6fdd3c..c338954 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
@@ -16,21 +16,26 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
-import java.util.Map;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
+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 static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
+import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
+
 import java.util.Properties;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 
 import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
 import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
-import org.jclouds.compute.RunScriptOnNodesException;
-import org.jclouds.compute.domain.ExecResponse;
 import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.OperatingSystem;
 import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.TemplateBuilder;
 import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
-import org.jclouds.compute.predicates.NodePredicates;
-import org.jclouds.domain.LoginCredentials;
 import org.jclouds.logging.config.LoggingModule;
 import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
 import org.jclouds.providers.ProviderMetadata;
@@ -41,29 +46,18 @@ import org.jclouds.scriptbuilder.statements.login.AdminAccess;
 import org.jclouds.sshj.config.SshjSshClientModule;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.inject.Module;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
-import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
-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 static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
-
 /**
  * Live tests for the {@link org.jclouds.compute.ComputeService} integration.
  */
 @Test(groups = "live", singleThreaded = true, testName = "AzureComputeServiceLiveTest")
 public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
-   protected int nonBlockDurationSeconds = 30;
-
+   
    public AzureComputeServiceLiveTest() {
       provider = "azurecompute-arm";
-      nonBlockDurationSeconds = 300;
-      group = "az-u";
    }
 
    @Override
@@ -78,21 +72,20 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
 
    @Override
    protected ProviderMetadata createProviderMetadata() {
-      AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
-      return pm;
+      return AzureComputeProviderMetadata.builder().build();
    }
 
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      long scriptTimeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES);
-      properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + "");
-      properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + "");
-      properties.setProperty(TIMEOUT_PORT_OPEN, scriptTimeout + "");
-      properties.setProperty(TIMEOUT_NODE_TERMINATED, scriptTimeout + "");
-      properties.setProperty(TIMEOUT_NODE_SUSPENDED, scriptTimeout + "");
-      properties.put(RESOURCE_GROUP_NAME, "a4");
-      properties.put(TEMPLATE, "locationId=westeurope");
+      String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
+      properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout);
+      properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout);
+      properties.put(RESOURCE_GROUP_NAME, "jc");
+      properties.put(PROPERTY_REGIONS, "eastus");
       properties.put(IMAGE_PUBLISHERS, "Canonical");
 
       AzureLiveTestUtils.defaultProperties(properties);
@@ -102,24 +95,27 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
    }
 
    @Override
-   protected Template refreshTemplate() {
-      return this.template = addRunScriptToTemplate(this.buildTemplate(this.client.templateBuilder()));
+   protected TemplateBuilder templateBuilder() {
+      return super.templateBuilder().options(
+            authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(keyPair.get("private")));
    }
 
    @Override
    protected Template addRunScriptToTemplate(Template template) {
-      template.getOptions().runScript(Statements.newStatementList(new Statement[]{AdminAccess.standard(), Statements.exec("sleep 50"), InstallJDK.fromOpenJDK()}));
+      template.getOptions().runScript(
+            Statements.newStatementList(new Statement[] { AdminAccess.standard(), Statements.exec("sleep 50"),
+                  InstallJDK.fromOpenJDK() }));
       return template;
    }
-
+   
    @Override
-   @Test( enabled = false)
-   protected void weCanCancelTasks(NodeMetadata node) throws InterruptedException, ExecutionException {
-      return;
+   protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
+      // User metadata not yet supported
    }
 
    @Override
-   protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(String group, OperatingSystem os, LoginCredentials creds) throws RunScriptOnNodesException {
-      return this.client.runScriptOnNodesMatching(NodePredicates.runningInGroup(group), Statements.newStatementList(Statements.exec("sleep 50"), InstallJDK.fromOpenJDK()), org.jclouds.compute.options.TemplateOptions.Builder.overrideLoginCredentials(creds).nameTask("runScriptWithCreds"));
+   protected void checkTagsInNodeEquals(NodeMetadata node, ImmutableSet<String> tags) {
+      // Tags not yet supported
    }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
index 8756240..c20655b 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
@@ -16,33 +16,30 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
+import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
 import java.util.Properties;
 import java.util.Set;
-import java.util.concurrent.TimeUnit;
 
 import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
+import org.jclouds.azurecompute.arm.domain.Region;
 import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest;
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.sshj.config.SshjSshClientModule;
 import org.testng.annotations.Test;
 
-import com.google.common.collect.ImmutableSet;
 import com.google.inject.Module;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
-
 @Test(groups = "live", testName = "AzureTemplateBuilderLiveTest")
 public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
-   public String azureGroup;
-
-   @Override
-   protected Set<String> getIso3166Codes() {
-      return ImmutableSet.of("US-IA", "US-VA", "US-IL", "US-TX", "US-CA", "IE", "NL", "HK", "SG", "JP-11", "JP-27", "BR", "AU-NSW", "AU-VIC", "IN-GA", "IN-TN", "IN-MH", "CN-SH", "CN-BJ", "CA-ON", "CA-QC");
-   }
 
    public AzureTemplateBuilderLiveTest() {
       provider = "azurecompute-arm";
@@ -55,23 +52,33 @@ public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
 
    @Override
    protected ProviderMetadata createProviderMetadata() {
-      AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
-      return pm;
+      return AzureComputeProviderMetadata.builder().build();
    }
 
    @Override
    protected Properties setupProperties() {
-      azureGroup = "jc" + System.getProperty("user.name").substring(0, 3);
       Properties properties = super.setupProperties();
-      long scriptTimeout = TimeUnit.MILLISECONDS.convert(20, TimeUnit.MINUTES);
-      properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + "");
-      properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + "");
-      properties.put(RESOURCE_GROUP_NAME, azureGroup);
+      properties.put(RESOURCE_GROUP_NAME, "jc");
 
       AzureLiveTestUtils.defaultProperties(properties);
       checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
 
       return properties;
-
+   }
+   
+   @Override
+   @Test
+   public void testDefaultTemplateBuilder() throws IOException {
+      Template defaultTemplate = view.getComputeService().templateBuilder().build();
+      assertTrue(defaultTemplate.getImage().getOperatingSystem().getVersion().matches("1[45]\\.[01][04]\\.[0-9]-LTS"),
+            "Version mismatch, expected dd.dd.d-LTS, found: " + defaultTemplate.getImage().getOperatingSystem().getVersion());
+      assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
+      assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
+      assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
+   }
+   
+   @Override
+   protected Set<String> getIso3166Codes() {
+      return Region.iso3166Codes();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
index 06f9ab7..de44668 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
@@ -16,29 +16,35 @@
  */
 package org.jclouds.azurecompute.arm.compute.extensions;
 
-import com.google.inject.Module;
-import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
-import org.jclouds.azurecompute.arm.config.AzureComputeProperties;
-import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
-import org.jclouds.compute.config.ComputeServiceProperties;
-import org.jclouds.compute.extensions.internal.BaseImageExtensionLiveTest;
-import org.jclouds.providers.ProviderMetadata;
-import org.jclouds.sshj.config.SshjSshClientModule;
-import org.testng.annotations.Test;
-
-import java.util.Properties;
-import java.util.concurrent.TimeUnit;
-
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
 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 static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
+import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
+
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
+import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
+import org.jclouds.compute.ComputeTestUtils;
+import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.extensions.internal.BaseImageExtensionLiveTest;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.sshj.config.SshjSshClientModule;
+import org.testng.annotations.Test;
+
+import com.google.inject.Module;
 
 /**
- * Live tests for the {@link org.jclouds.compute.extensions.ImageExtension} integration.
+ * Live tests for the {@link org.jclouds.compute.extensions.ImageExtension}
+ * integration.
  */
 @Test(groups = "live", singleThreaded = true, testName = "AzureComputeImageExtensionLiveTest")
 public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTest {
@@ -57,34 +63,33 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      long scriptTimeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES);
-      properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + "");
-      properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + "");
-      properties.setProperty(TIMEOUT_PORT_OPEN, scriptTimeout + "");
-      properties.setProperty(TIMEOUT_NODE_TERMINATED, scriptTimeout + "");
-      properties.setProperty(TIMEOUT_NODE_SUSPENDED, scriptTimeout + "");
-      properties.put(RESOURCE_GROUP_NAME, "jcloudsgroup");
-
-      properties.put(ComputeServiceProperties.POLL_INITIAL_PERIOD, 1000);
-      properties.put(ComputeServiceProperties.POLL_MAX_PERIOD, 10000);
-      properties.setProperty(AzureComputeProperties.OPERATION_TIMEOUT, "46000000");
-      properties.setProperty(AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD, "5");
-      properties.setProperty(AzureComputeProperties.OPERATION_POLL_MAX_PERIOD, "15");
-      properties.setProperty(AzureComputeProperties.TCP_RULE_FORMAT, "tcp_%s-%s");
-      properties.setProperty(AzureComputeProperties.TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
+      String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
+      properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout);
+      properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout);
+      properties.put(RESOURCE_GROUP_NAME, "jc");
+      properties.put(PROPERTY_REGIONS, "eastus");
+      properties.put(IMAGE_PUBLISHERS, "Canonical");
 
       AzureLiveTestUtils.defaultProperties(properties);
       checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
 
       return properties;
-
    }
 
    @Override
    protected ProviderMetadata createProviderMetadata() {
-      AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
-      return pm;
+      return AzureComputeProviderMetadata.builder().build();
    }
 
+   @Override
+   public TemplateBuilder getNodeTemplate() {
+      Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
+      return super.getNodeTemplate().options(
+            authorizePublicKey(keyPair.get("public"))
+            .overrideLoginPrivateKey(keyPair.get("private")));
+   }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
index 7476828..42116c2 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
@@ -16,30 +16,19 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
 import java.net.URI;
 import java.util.List;
 
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.domain.Deployment;
 import org.jclouds.azurecompute.arm.domain.Deployment.ProvisioningState;
-import org.jclouds.azurecompute.arm.domain.DeploymentBody;
-import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
 import org.jclouds.azurecompute.arm.domain.Subnet;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
-import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
-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.OperatingSystem;
-import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.domain.internal.TemplateImpl;
-import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.domain.Location;
-import org.jclouds.domain.LocationBuilder;
-import org.jclouds.domain.LocationScope;
 import org.jclouds.util.Predicates2;
 import org.testng.Assert;
 import org.testng.annotations.AfterClass;
@@ -49,10 +38,6 @@ import org.testng.annotations.Test;
 import com.google.common.base.Predicate;
 import com.google.common.net.UrlEscapers;
 
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
 @Test(testName = "DeploymentApiLiveTest", singleThreaded = true)
 public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
 
@@ -112,37 +97,6 @@ public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
       return body;
    }
 
-   private Template getTemplate(TemplateOptions options) {
-      Location provider = (new LocationBuilder()).scope(LocationScope.PROVIDER).id("azurecompute-arm").description("azurecompute-arm").build();
-      Location region = (new LocationBuilder()).scope(LocationScope.REGION).id(LOCATION).description("West Europe").parent(provider).build();
-
-      OperatingSystem os = OperatingSystem.builder()
-              .family(OsFamily.UBUNTU)
-              .description("14.04.3-LTS")
-              .is64Bit(true)
-              .build();
-
-      Image image = (new ImageBuilder())
-              .id("UbuntuServer14.04.3-LTS")
-              .providerId("Canonical")
-              .name("UbuntuServer")
-              .description("14.04.3-LTS")
-              .version("14.04.3-LTS")
-              .operatingSystem(os)
-              .status(Image.Status.AVAILABLE)
-              .location(region)
-              .build();
-
-      Hardware hardware = (new HardwareBuilder()).id("Standard_A0").build();
-      return new TemplateImpl(image, hardware, region, options);
-   }
-
-   private DeploymentTemplateBuilder getDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
-      Template template = getTemplate(options);
-      DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroupName, deploymentName, template);
-      return templateBuilder;
-   }
-
    @Test
    public void testValidate(){
       Deployment deploymentInvalid = null;
@@ -168,12 +122,40 @@ public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
       AzureTemplateOptions options = new AzureTemplateOptions();
       options.authorizePublicKey(rsakey);
       options.subnetId(subnetId);
-      DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
-      DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
-
-      DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
 
-      String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
+      String deploymentTemplate = "{\n" +
+              "  \"id\": \"/subscriptions/04f7ec88-8e28-41ed-8537-5e17766001f5/resourceGroups/jims216group/providers/Microsoft.Resources/deployments/jcdep1458344383064\",\n" +
+              "  \"name\": \"jcdep1458344383064\",\n" +
+              "  \"properties\": {\n" +
+              "    \"parameters\": {\n" +
+              "      \"newStorageAccountName\": {\n" +
+              "        \"type\": \"String\",\n" +
+              "        \"value\": \"jcres1458344383064\"\n" +
+              "      },\n" +
+              "      \"storageAccountType\": {\n" +
+              "        \"type\": \"String\",\n" +
+              "        \"value\": \"Standard_LRS\"\n" +
+              "      },\n" +
+              "      \"location\": {\n" +
+              "        \"type\": \"String\",\n" +
+              "        \"value\": \"West US\"\n" +
+              "      }\n" +
+              "    },\n" +
+              "    \"mode\": \"Incremental\",\n" +
+              "    \"provisioningState\": \"Accepted\",\n" +
+              "    \"timestamp\": \"2016-03-18T23:39:47.3048037Z\",\n" +
+              "    \"duration\": \"PT2.4433028S\",\n" +
+              "    \"correlationId\": \"8dee9711-8632-4948-9fe6-368bb75e6438\",\n" +
+              "    \"providers\": [{\n" +
+              "      \"namespace\": \"Microsoft.Storage\",\n" +
+              "      \"resourceTypes\": [{\n" +
+              "        \"resourceType\": \"storageAccounts\",\n" +
+              "        \"locations\": [\"westus\"]\n" +
+              "      }]\n" +
+              "    }],\n" +
+              "    \"dependencies\": []\n" +
+              "  }\n" +
+              "}";
       deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
 
       Deployment deploymentValid = api().validate(deploymentName, deploymentTemplate);