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/06/02 22:36:18 UTC

[1/2] jclouds-labs git commit: JCLOUDS-664 Azurecompute-arm DeploymentApi OSImageApi VMSizeApi

Repository: jclouds-labs
Updated Branches:
  refs/heads/master 17a12fc1c -> fca7addf0


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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
new file mode 100644
index 0000000..0e2baef
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
@@ -0,0 +1,226 @@
+/*
+ * 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 com.google.common.base.Predicate;
+import com.google.common.net.UrlEscapers;
+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.functions.ParseJobStatus;
+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.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.net.URI;
+import java.util.List;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+@Test(groups = "live", testName = "DeploymentApiLiveTest", singleThreaded = true)
+public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
+   private int maxTestDuration = 190;
+
+   private String resourceName;
+   private String deploymentName;
+   private String rawtemplate;
+   private String rawparameters;
+   private String rawbadParameters;
+   private String properties;
+   private String badProperties;
+
+   @BeforeClass
+   @Override
+   public void setup() {
+      super.setup();
+      resourceName = getResourceGroupName();
+      Long now = System.currentTimeMillis();
+      deploymentName = "jc" + now;
+
+      rawtemplate = "{\"$schema\":\"https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#\",\"contentVersion\":\"1.0.0.0\",\"parameters\":{\"newStorageAccountName\":{\"type\":\"string\",\"metadata\":{\"description\":\"Name of the Storage Account\"}},\"storageAccountType\":{\"type\":\"string\",\"defaultValue\":\"Standard_LRS\",\"allowedValues\":[\"Standard_LRS\",\"Standard_GRS\",\"Standard_ZRS\"],\"metadata\":{\"description\":\"Storage Account type\"}},\"location\":{\"type\":\"string\",\"allowedValues\":[\"East US\",\"West US\",\"West Europe\",\"East Asia\",\"Southeast Asia\"],\"metadata\":{\"description\":\"Location of storage account\"}}},\"resources\":[{\"type\":\"Microsoft.Storage/storageAccounts\",\"name\":\"[parameters('newStorageAccountName')]\",\"apiVersion\":\"2015-05-01-preview\",\"location\":\"[parameters('location')]\",\"properties\":{\"accountType\":\"[parameters('storageAccountType')]\"}}]}";
+      rawparameters = "{\"newStorageAccountName\":{\"value\":\"" + resourceName + "\"},\"storageAccountType\":{\"value\":\"Standard_LRS\"},\"location\":{\"value\":\"West US\"}}";
+      rawbadParameters = "{\"newStorageAccountName\":{\"value\":\"" + resourceName + "\"},\"storageAccountType\":{\"value\":\"Standard_LRS\"},\"location\":{\"value\":\"West\"}}";
+
+      properties = getPutBody(rawtemplate, "Incremental", rawparameters);
+      badProperties = getPutBody(rawtemplate, "Incremental", rawbadParameters);
+   }
+
+   private String getPutBody(String template, String mode, String parameters) {
+      String body = "{ " +
+              "\"properties\" : " +
+              "  { " +
+              "    \"template\" : " + template + ", " +
+              "    \"mode\" : \"" + mode + "\", " +
+              "    \"parameters\" : " + parameters + " " +
+              "  } " +
+              "}";
+      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("northeurope").description("North 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(resourceName, deploymentName, template);
+      return templateBuilder;
+   }
+
+   @Test(groups = "live")
+   public void testValidate(){
+      Deployment deploymentInvalid = null;
+      try {
+         deploymentInvalid = api().validate(deploymentName + "invalid", badProperties);
+      } catch (Exception ex) {
+         assertTrue(ex.getClass() == java.lang.IllegalArgumentException.class);
+      }
+      assertNull(deploymentInvalid);
+
+      Deployment deploymentValid = null;
+      try {
+         deploymentValid = api().validate(deploymentName + "valid", properties);
+      } catch (Exception ex) {
+         assertTrue(ex.getClass() == java.lang.IllegalArgumentException.class);
+      }
+      assertNotNull(deploymentValid);
+   }
+   @Test(groups = "live")
+   public void testCreate() {
+      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 TemplateOptions();
+      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 deploymentValid = api().validate(deploymentName, deploymentTemplate);
+      assertNotNull(deploymentValid);
+
+      Deployment deployment = api().create(deploymentName, deploymentTemplate);
+      assertNotNull(deployment);
+
+      //Poll until resource is ready to be used
+      boolean jobDone = Predicates2.retry(new Predicate<String>() {
+         @Override
+         public boolean apply(String name) {
+            Deployment dp = api().get(deploymentName);
+            ProvisioningState state = ProvisioningState.fromValue(dp.properties().provisioningState());
+            return state == ProvisioningState.SUCCEEDED;
+         }
+      }, 60 * maxTestDuration * 1000).apply(deploymentName);
+      assertTrue(jobDone, "create operation did not complete in the configured timeout");
+
+      Deployment dp = api().get(deploymentName);
+      ProvisioningState state = ProvisioningState.fromValue(dp.properties().provisioningState());
+      assertTrue(state == ProvisioningState.SUCCEEDED);
+   }
+
+
+   @Test(groups = "live", dependsOnMethods = "testCreate")
+   public void testGetDeployment() {
+      Deployment deployment = api().get(deploymentName);
+      assertNotNull(deployment);
+      ProvisioningState state = ProvisioningState.fromValue(deployment.properties().provisioningState());
+      assertTrue(state == ProvisioningState.SUCCEEDED);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testCreate")
+   public void testListDeployments() {
+      List<Deployment> deployments = api().list();
+      assertTrue(deployments.size() > 0);
+      boolean deploymentFound = false;
+      for (Deployment d : deployments) {
+
+         if (d.name().equals(deploymentName)) {
+            deploymentFound = true;
+            break;
+         }
+      }
+      assertTrue(deploymentFound);
+
+   }
+
+   @Test(groups = "live", dependsOnMethods = {"testGetDeployment", "testListDeployments"}, alwaysRun = true)
+   public void testDelete() throws Exception {
+      List<Deployment> deployments = api().list();
+      for (Deployment d : deployments) {
+         if (d.name().contains("jc")) {
+            URI uri = api().delete(d.name());
+            assertNotNull(uri);
+            assertTrue(uri.toString().contains("api-version"));
+            assertTrue(uri.toString().contains("operationresults"));
+
+            boolean jobDone = Predicates2.retry(new Predicate<URI>() {
+               @Override
+               public boolean apply(URI uri) {
+                  return ParseJobStatus.JobStatus.NO_CONTENT == api.getJobApi().jobStatus(uri);
+               }
+            }, 60 * maxTestDuration * 1000).apply(uri);
+            assertTrue(jobDone, "delete operation did not complete in the configured timeout");
+         }
+      }
+   }
+
+   private DeploymentApi api() {
+      return api.getDeploymentApi(resourceName);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiMockTest.java
new file mode 100644
index 0000000..89d6aca
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiMockTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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 org.jclouds.azurecompute.arm.domain.Deployment;
+import org.jclouds.azurecompute.arm.domain.Deployment.ProvisioningState;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.testng.annotations.Test;
+
+import java.net.URI;
+import java.util.List;
+
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertEquals;
+
+@Test(groups = "unit", testName = "DeploymentApiMockTest", singleThreaded = true)
+public class DeploymentApiMockTest extends BaseAzureComputeApiMockTest {
+
+   private String subscriptionId = "SUBSCRIPTIONID";
+   private String resourceGroup = "resourceGroup";
+   private String deploymentName = "jcdep1458344383064";
+   private String resourceName = "jcres1458344383064";
+
+   private String getPutBody(String template, String mode, String parameters) {
+      String body = "{ " +
+              "\"properties\" : " +
+              "  { " +
+              "    \"template\" : " + template + ", " +
+              "    \"mode\" : \"" + mode + "\", " +
+              "    \"parameters\" : " + parameters + " " +
+              "  } " +
+              "}";
+      return body;
+   }
+
+   @Test
+   public void testCreateDeployment() throws Exception {
+      final DeploymentApi deploymentApi = api.getDeploymentApi(resourceGroup);
+
+      // check if deployment accepted
+      server.enqueue(jsonResponse("/createdeploymentaccepted.json"));
+      String template = "{\"$schema\":\"https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#\",\"contentVersion\":\"1.0.0.0\",\"parameters\":{\"newStorageAccountName\":{\"type\":\"string\",\"metadata\":{\"description\":\"Name of the Storage Account\"}},\"storageAccountType\":{\"type\":\"string\",\"defaultValue\":\"Standard_LRS\",\"allowedValues\":[\"Standard_LRS\",\"Standard_GRS\",\"Standard_ZRS\"],\"metadata\":{\"description\":\"Storage Account type\"}},\"location\":{\"type\":\"string\",\"allowedValues\":[\"East US\",\"West US\",\"West Europe\",\"East Asia\",\"Southeast Asia\"],\"metadata\":{\"description\":\"Location of storage account\"}}},\"resources\":[{\"type\":\"Microsoft.Storage/storageAccounts\",\"name\":\"[parameters('newStorageAccountName')]\",\"apiVersion\":\"2015-05-01-preview\",\"location\":\"[parameters('location')]\",\"properties\":{\"accountType\":\"[parameters('storageAccountType')]\"}}]}";
+      String parameters = "{\"newStorageAccountName\":{\"value\":\"" + resourceName + "\"},\"storageAccountType\":{\"value\":\"Standard_LRS\"},\"location\":{\"value\":\"West US\"}}";
+      String properties = getPutBody(template, "Incremental", parameters);
+      Deployment deployment = deploymentApi.create(deploymentName, properties);
+      assertTrue(deployment != null);
+      assertEquals(ProvisioningState.fromValue(deployment.properties().provisioningState()), ProvisioningState.ACCEPTED);
+
+      // check if deployment succeeded
+      server.enqueue(jsonResponse("/createdeploymentsucceeded.json"));
+      deployment = deploymentApi.create(deploymentName, properties);
+      assertTrue(deployment != null);
+      assertEquals(ProvisioningState.fromValue(deployment.properties().provisioningState()), ProvisioningState.SUCCEEDED);
+      assertSent(server, "PUT", "/subscriptions/" + subscriptionId + "/resourcegroups/" + resourceGroup +
+              "/providers/microsoft.resources/deployments/" + deploymentName + "?api-version=2016-02-01", properties);
+   }
+
+   @Test
+   public void testGetDeployment() throws Exception {
+      final DeploymentApi deploymentApi = api.getDeploymentApi(resourceGroup);
+
+      // check if deployment succeeded
+      server.enqueue(jsonResponse("/createdeploymentsucceeded.json"));
+      Deployment deployment = deploymentApi.get(deploymentName);
+      assertTrue(deployment != null);
+      assertEquals(ProvisioningState.fromValue(deployment.properties().provisioningState()), ProvisioningState.SUCCEEDED);
+      assertSent(server, "GET", "/subscriptions/" + subscriptionId + "/resourcegroups/" + resourceGroup +
+              "/providers/microsoft.resources/deployments/" + deploymentName + "?api-version=2016-02-01");
+   }
+
+   @Test
+   public void testGetDeploymentEmpty() throws Exception {
+      final DeploymentApi deploymentApi = api.getDeploymentApi(resourceGroup);
+
+      server.enqueue(new MockResponse().setResponseCode(404));
+
+      Deployment deployment = deploymentApi.get(deploymentName);
+      assertNull(deployment);
+
+      assertSent(server, "GET", "/subscriptions/" + subscriptionId + "/resourcegroups/" + resourceGroup +
+              "/providers/microsoft.resources/deployments/" + deploymentName + "?api-version=2016-02-01");
+   }
+
+   @Test
+   public void testListDeployment() throws Exception {
+      final DeploymentApi deploymentApi = api.getDeploymentApi(resourceGroup);
+
+      // check if deployment succeeded
+      server.enqueue(jsonResponse("/listdeployments.json"));
+      List<Deployment> deployments = deploymentApi.list();
+      assertTrue(deployments.size() > 0);
+
+      assertSent(server, "GET", "/subscriptions/" + subscriptionId + "/resourcegroups/" + resourceGroup +
+              "/providers/microsoft.resources/deployments?api-version=2016-02-01");
+
+   }
+
+   @Test
+   public void testListDeploymentEmpty() throws Exception {
+      final DeploymentApi deploymentApi = api.getDeploymentApi(resourceGroup);
+
+      server.enqueue(new MockResponse().setResponseCode(404));
+
+      List<Deployment> deployments = deploymentApi.list();
+      assertTrue(deployments.size() == 0);
+
+      assertSent(server, "GET", "/subscriptions/" + subscriptionId + "/resourcegroups/" + resourceGroup +
+              "/providers/microsoft.resources/deployments?api-version=2016-02-01");
+
+   }
+
+   @Test
+   public void testDeleteDeployment() throws InterruptedException {
+      final DeploymentApi deploymentApi = api.getDeploymentApi(resourceGroup);
+
+      server.enqueue(response202WithHeader());
+
+      URI uri = deploymentApi.delete(deploymentName);
+      assertNotNull(uri);
+
+      assertSent(server, "DELETE", "/subscriptions/" + subscriptionId + "/resourcegroups/" + resourceGroup +
+              "/providers/microsoft.resources/deployments/" + deploymentName + "?api-version=2016-02-01");
+   }
+
+   @Test
+   public void testDeleteDeploymentReturns404() throws InterruptedException {
+      final DeploymentApi deploymentApi = api.getDeploymentApi(resourceGroup);
+
+      server.enqueue(response404());
+
+      URI uri = deploymentApi.delete(deploymentName);
+      assertNull(uri);
+
+      assertSent(server, "DELETE", "/subscriptions/" + subscriptionId + "/resourcegroups/" + resourceGroup +
+              "/providers/microsoft.resources/deployments/" + deploymentName + "?api-version=2016-02-01");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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
new file mode 100644
index 0000000..bc505e7
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentTemplateBuilderTest.java
@@ -0,0 +1,224 @@
+/*
+ * 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 org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.jclouds.compute.options.TemplateOptions;
+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.OSProfile;
+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.domain.VirtualNetwork.VirtualNetworkProperties;
+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.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.testng.annotations.Test;
+
+import java.util.Map;
+import java.util.List;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+
+@Test(groups = "unit", testName = "DeploymentTemplateBuilderTest", singleThreaded = true)
+public class DeploymentTemplateBuilderTest extends BaseAzureComputeApiMockTest {
+
+   final String group = "jcgroup";
+
+   @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 testVirtualNetwork() {
+      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/virtualNetworks");
+
+      VirtualNetworkProperties properties = (VirtualNetworkProperties) resource.properties();
+      assertTrue(properties.addressSpace().addressPrefixes().size() > 0);
+      assertTrue(properties.subnets().size() > 0);
+
+      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 testVirtualMachineWithSSH() {
+
+      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 TemplateOptions();
+      options.authorizePublicKey(rsakey);
+
+      DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithOptions(options);
+      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");
+
+      // Check that ssh key is in place
+      OSProfile.LinuxConfiguration osConfig = properties.osProfile().linuxConfiguration();
+      assertEquals(osConfig.disablePasswordAuthentication(), "true");
+      assertTrue(osConfig.ssh().publicKeys().size() > 0);
+      assertEquals(osConfig.ssh().publicKeys().get(0).keyData(), rsakey);
+
+      assertTrue(variables.containsKey(parseVariableName(resource.name())));
+   }
+
+   private Template getMockTemplate(TemplateOptions options) {
+      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() {
+      TemplateOptions options = new TemplateOptions();
+      Template template = getMockTemplate(options);
+      DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(group, "mydeployment", template);
+      return templateBuilder;
+   }
+
+   private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
+      Template template = getMockTemplate(options);
+      DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(group, "mydeployment", template);
+      return templateBuilder;
+   }
+
+   private ResourceDefinition getResourceByType(List<ResourceDefinition> resources, String type) {
+      for (ResourceDefinition r : resources) {
+         if (r.type().equals(type)) {
+            return r;
+         }
+      }
+      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/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/JobApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/JobApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/JobApiMockTest.java
index ba87ca5..3e55df1 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/JobApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/JobApiMockTest.java
@@ -18,6 +18,7 @@ package org.jclouds.azurecompute.arm.features;
 
 import java.io.IOException;
 import java.net.URI;
+
 import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
 import org.testng.annotations.Test;
@@ -49,11 +50,21 @@ public class JobApiMockTest extends BaseAzureComputeApiMockTest {
       assertSent(server, "GET", requestUrl);
    }
 
-   public void testGetJobStatusFailed() throws InterruptedException {
+   public void testGetJobStatusNoContent() throws InterruptedException {
       server.enqueue(jsonResponse("/resourcegroup.json").setStatus("HTTP/1.1 204 No Content"));
 
       JobStatus status = api.getJobApi().jobStatus(URI.create(requestUrl));
 
+      assertEquals(status, JobStatus.NO_CONTENT);
+
+      assertSent(server, "GET", requestUrl);
+   }
+
+   public void testGetJobStatusFailed() throws InterruptedException {
+      server.enqueue(jsonResponse("/resourcegroup.json").setStatus("HTTP/1.1 208 Error"));
+
+      JobStatus status = api.getJobApi().jobStatus(URI.create(requestUrl));
+
       assertEquals(status, JobStatus.FAILED);
 
       assertSent(server, "GET", requestUrl);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiLiveTest.java
index c1e77a2..34917ac 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiLiveTest.java
@@ -17,6 +17,7 @@
 package org.jclouds.azurecompute.arm.features;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.base.Predicate;
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.IpConfiguration;
 import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
@@ -24,18 +25,22 @@ import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
 import org.jclouds.azurecompute.arm.domain.Subnet;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
+import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
+import org.jclouds.util.Predicates2;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import java.net.URI;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
+
+import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
 
 @Test(groups = "live", singleThreaded = true)
 public class NetworkInterfaceCardApiLiveTest extends BaseAzureComputeApiLiveTest {
@@ -66,8 +71,8 @@ public class NetworkInterfaceCardApiLiveTest extends BaseAzureComputeApiLiveTest
    public void deleteNetworkInterfaceCardResourceDoesNotExist() {
 
       final NetworkInterfaceCardApi nicApi = api.getNetworkInterfaceCardApi(resourcegroup);
-      boolean status = nicApi.delete(NETWORKINTERFACECARD_NAME);
-      assertFalse(status);
+      URI uri = nicApi.delete(NETWORKINTERFACECARD_NAME);
+      assertNull(uri);
    }
 
    @Test(groups = "live", dependsOnMethods = "deleteNetworkInterfaceCardResourceDoesNotExist")
@@ -85,8 +90,8 @@ public class NetworkInterfaceCardApiLiveTest extends BaseAzureComputeApiLiveTest
                               .properties(IpConfigurationProperties.builder()
                                       .privateIPAllocationMethod("Dynamic")
                                       .subnet(IdReference.create(subnetID)).build()
-                      ).build()
-              )).build();
+                              ).build()
+                      )).build();
 
       final Map<String, String> tags = ImmutableMap.of("jclouds", "livetest");
       NetworkInterfaceCard nic = nicApi.createOrUpdate(NETWORKINTERFACECARD_NAME, LOCATION, networkInterfaceCardProperties, tags);
@@ -131,9 +136,19 @@ public class NetworkInterfaceCardApiLiveTest extends BaseAzureComputeApiLiveTest
    public void deleteNetworkInterfaceCard() {
 
       final NetworkInterfaceCardApi nicApi = api.getNetworkInterfaceCardApi(resourcegroup);
-
-      boolean status = nicApi.delete(NETWORKINTERFACECARD_NAME);
-      assertTrue(status);
+      URI uri = nicApi.delete(NETWORKINTERFACECARD_NAME);
+      if (uri != null) {
+         assertTrue(uri.toString().contains("api-version"));
+         assertTrue(uri.toString().contains("operationresults"));
+
+         boolean jobDone = Predicates2.retry(new Predicate<URI>() {
+            @Override
+            public boolean apply(URI uri) {
+               return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri);
+            }
+         }, 60 * 2 * 1000 /* 2 minute timeout */).apply(uri);
+         assertTrue(jobDone, "delete operation did not complete in the configured timeout");
+      }
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiMockTest.java
index 179a4ab..12ad073 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiMockTest.java
@@ -34,7 +34,6 @@ import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
 
 @Test(groups = "unit", testName = "NetworkInterfaceCardApiMockTest", singleThreaded = true)
 public class NetworkInterfaceCardApiMockTest extends BaseAzureComputeApiMockTest {
@@ -123,12 +122,11 @@ public class NetworkInterfaceCardApiMockTest extends BaseAzureComputeApiMockTest
 
    public void deleteNetworkInterfaceCard() throws InterruptedException {
 
-      server.enqueue(response202());
+      server.enqueue(response202WithHeader());
 
       final NetworkInterfaceCardApi nicApi = api.getNetworkInterfaceCardApi(resourcegroup);
 
-      boolean status = nicApi.delete(nicName);
-      assertTrue(status);
+      nicApi.delete(nicName);
 
       String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Network/networkInterfaces/%s?%s", subscriptionid, resourcegroup, nicName, apiVersion);
       assertSent(server, "DELETE", path);
@@ -137,12 +135,11 @@ public class NetworkInterfaceCardApiMockTest extends BaseAzureComputeApiMockTest
 
    public void deleteNetworkInterfaceCardResourceDoesNotExist() throws InterruptedException {
 
-      server.enqueue(response204());
+      server.enqueue(response404());
 
       final NetworkInterfaceCardApi nicApi = api.getNetworkInterfaceCardApi(resourcegroup);
 
-      boolean status = nicApi.delete(nicName);
-      assertFalse(status);
+      nicApi.delete(nicName);
 
       String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Network/networkInterfaces/%s?%s", subscriptionid, resourcegroup, nicName, apiVersion);
       assertSent(server, "DELETE", path);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/OSImageApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/OSImageApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/OSImageApiLiveTest.java
new file mode 100644
index 0000000..6ceb0d4
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/OSImageApiLiveTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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 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.internal.AbstractAzureComputeApiLiveTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+
+@Test(groups = "live", testName = "OSImageApiLiveTest")
+public class OSImageApiLiveTest extends AbstractAzureComputeApiLiveTest {
+
+   @Test
+   public void testPublisher() {
+      List<Publisher> publishers = api().listPublishers();
+      assertTrue(publishers.size() > 0);
+   }
+
+   @Test
+   public void testList() {
+      List<Offer> offerList = api().listOffers("MicrosoftWindowsServer");
+      assertTrue(offerList.size() > 0);
+
+      List<SKU> skuList = api().listSKUs("MicrosoftWindowsServer", offerList.get(0).name());
+      assertTrue(skuList.size() > 0);
+
+      List<Version> versionList = api().listVersions("MicrosoftWindowsServer", offerList.get(0).name(), skuList.get(0).name());
+
+      assertTrue(versionList.size() > 0);
+   }
+
+   @Test
+   public void testListCanonicalUbuntu() {
+      Iterable<Offer> offerList = api().listOffers("canonical");
+      int total = 0;
+
+      for (Offer offer : offerList) {
+         Iterable<SKU> skuList = api().listSKUs("canonical", offer.name());
+         for (SKU sku : skuList) {
+            List<Version> versionList = api().listVersions("canonical", offer.name(), sku.name());
+            total += versionList.size();
+         }
+      }
+      assertTrue(total > 0);
+   }
+
+   private OSImageApi api() {
+      return api.getOSImageApi("eastus");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/OSImageApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/OSImageApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/OSImageApiMockTest.java
new file mode 100644
index 0000000..d7dbc92
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/OSImageApiMockTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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 static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+
+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.internal.BaseAzureComputeApiMockTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "OSImageApiMockTest", singleThreaded = true)
+public class OSImageApiMockTest extends BaseAzureComputeApiMockTest {
+
+   private final String subscriptionid = "SUBSCRIPTIONID";
+   private final String apiversion = "?api-version=2015-06-15";
+   private final String location = "eastus";
+   private final String publisher = "MicrosoftWindowsServer";
+   private final String offer = "WindowsServer";
+   private final String sku = "2008-R2-SP1";
+
+   final String requestUrl = "/subscriptions/" + subscriptionid + "/providers/Microsoft.Compute/locations/" + location + "/publishers";
+
+   public void testPublishers() throws InterruptedException {
+      server.enqueue(jsonResponse("/publishers.json"));
+
+      List<Publisher> publishers = api.getOSImageApi(location).listPublishers();
+
+      assertEquals(size(publishers), 2);
+
+      assertSent(server, "GET", requestUrl + apiversion);
+   }
+   public void testPublishersEmtpy() throws InterruptedException {
+      server.enqueue(response404());
+
+      List<Publisher> publishers = api.getOSImageApi(location).listPublishers();
+
+      assertTrue(isEmpty(publishers));
+
+      assertSent(server, "GET", requestUrl + apiversion);
+   }
+
+   public void testOffers() throws InterruptedException {
+      server.enqueue(jsonResponse("/offers.json"));
+
+      List<Offer> offers = api.getOSImageApi(location).listOffers(publisher);
+
+      assertEquals(size(offers), 1);
+
+      assertSent(server, "GET", requestUrl + "/" + publisher + "/artifacttypes/vmimage/offers" + apiversion);
+   }
+   public void testOffersEmtpy() throws InterruptedException {
+      server.enqueue(response404());
+
+      List<Offer> offers = api.getOSImageApi(location).listOffers(publisher);
+
+      assertTrue(isEmpty(offers));
+
+      assertSent(server, "GET", requestUrl + "/" + publisher + "/artifacttypes/vmimage/offers" + apiversion);
+   }
+
+   public void testSkus() throws InterruptedException {
+      server.enqueue(jsonResponse("/skus.json"));
+
+      List<SKU> skus = api.getOSImageApi(location).listSKUs(publisher, offer);
+
+      assertEquals(size(skus), 2);
+
+      assertSent(server, "GET", requestUrl + "/" + publisher + "/artifacttypes/vmimage/offers/" + offer + "/skus" + apiversion);
+   }
+
+   public void testSkusEmtpy() throws InterruptedException {
+      server.enqueue(response404());
+
+      List<SKU> skus = api.getOSImageApi(location).listSKUs(publisher, offer);
+
+      assertTrue(isEmpty(skus));
+
+      assertSent(server, "GET", requestUrl + "/" + publisher + "/artifacttypes/vmimage/offers/" + offer + "/skus" + apiversion);
+   }
+
+   public void testVersions() throws InterruptedException {
+      server.enqueue(jsonResponse("/versions.json"));
+
+      List<Version> versions = api.getOSImageApi(location).listVersions(publisher, offer, sku);
+
+      assertEquals(size(versions), 2);
+
+      assertSent(server, "GET", requestUrl + "/" + publisher + "/artifacttypes/vmimage/offers/" + offer + "/skus/" + sku + "/versions" + apiversion);
+   }
+   public void testVersionsEmtpy() throws InterruptedException {
+      server.enqueue(response404());
+
+      List<Version> versions = api.getOSImageApi(location).listVersions(publisher, offer, sku);
+
+      assertTrue(isEmpty(versions));
+
+      assertSent(server, "GET", requestUrl + "/" + publisher + "/artifacttypes/vmimage/offers/" + offer + "/skus/" + sku + "/versions" + apiversion);
+   }
+
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiLiveTest.java
index 1ad8bf3..f9ad6cc 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiLiveTest.java
@@ -32,6 +32,7 @@ import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.assertEquals;
 import org.jclouds.util.Predicates2;
@@ -80,7 +81,7 @@ public class ResourceGroupApiLiveTest extends BaseAzureComputeApiLiveTest {
       final ResourceGroup resourceGroup = api().create("jcloudstest", LOCATION, null);
       assertEquals(resourceGroup.name(), "jcloudstest");
       assertEquals(resourceGroup.location(), LOCATION);
-      assertEquals(resourceGroup.tags().size(), 0);
+      assertNull(resourceGroup.tags());
       assertTrue(resourceGroup.id().contains("jcloudstest"));
       assertEquals(resourceGroup.properties().provisioningState(), "Succeeded");
    }
@@ -107,7 +108,7 @@ public class ResourceGroupApiLiveTest extends BaseAzureComputeApiLiveTest {
 
    @AfterClass(alwaysRun = true)
    public void testDelete() throws Exception {
-      URI uri =  api().delete(resourcegroup);
+      URI uri =  api().delete("jcloudstest");
 
       if (uri != null){
          assertTrue(uri.toString().contains("api-version"));
@@ -117,7 +118,7 @@ public class ResourceGroupApiLiveTest extends BaseAzureComputeApiLiveTest {
             @Override public boolean apply(URI uri) {
                return JobStatus.DONE == api.getJobApi().jobStatus(uri);
             }
-         }, 60 * 1 * 1000 /* 1 minute timeout */).apply(uri);
+         }, 60 * 2 * 1000 /* 1 minute timeout */).apply(uri);
          assertTrue(jobDone, "delete operation did not complete in the configured timeout");
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiLiveTest.java
index 9a13d77..6eb13dd 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiLiveTest.java
@@ -117,13 +117,13 @@ public class StorageAccountApiLiveTest extends BaseAzureComputeApiLiveTest {
       assertTrue(params.tags().containsKey("another_property_name"));
       assertNull(params.storageServiceProperties().accountType());
    }
-   @Test(dependsOnMethods = "testCreate")
+   @Test(dependsOnMethods = {"testCreate", "testGet"})
    public void testUpdateAccountType() {
       StorageServiceUpdateParams.StorageServiceUpdateProperties props =
               StorageServiceUpdateParams.StorageServiceUpdateProperties.create(StorageService.AccountType.Standard_GRS);
       final StorageServiceUpdateParams params = api().update(NAME,
               null, props);
-      assertTrue(params.tags().isEmpty());
+      assertNull(params.tags());
       assertEquals(params.storageServiceProperties().accountType(), StorageService.AccountType.Standard_GRS);
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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
new file mode 100644
index 0000000..be2eb3e
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/TemplateToDeploymentTemplateLiveTest.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import com.google.common.net.UrlEscapers;
+import org.jclouds.compute.options.TemplateOptions;
+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.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.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+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 resourceGroup;
+   private String deploymentName;
+
+   @BeforeClass
+   @Override
+   public void setup() {
+      super.setup();
+      resourceGroup = getResourceGroupName();
+   }
+
+   @Test(groups = "live")
+   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(groups = "live")
+   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");
+
+      TemplateOptions options = new TemplateOptions();
+      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(groups = "live")
+   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");
+
+      TemplateOptions options = new TemplateOptions();
+      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);
+
+      //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("northeurope").description("North 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 getDeploymentTemplateBuilderWithEmptyOptions() {
+      TemplateOptions options = new TemplateOptions();
+      Template template = getTemplate(options);
+      DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroup, deploymentName, template);
+      return templateBuilder;
+   }
+
+   private DeploymentTemplateBuilder getDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
+      Template template = getTemplate(options);
+      DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroup, deploymentName, template);
+      return templateBuilder;
+   }
+
+   private DeploymentApi api() {
+      return api.getDeploymentApi(resourceGroup);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VMSizeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VMSizeApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VMSizeApiLiveTest.java
new file mode 100644
index 0000000..fdd6ce9
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VMSizeApiLiveTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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 org.jclouds.azurecompute.arm.domain.VMSize;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+@Test(groups = "live", testName = "VMSizeApiLiveTest")
+public class VMSizeApiLiveTest extends BaseAzureComputeApiLiveTest {
+
+   @Test
+   public void testList() {
+      for (VMSize vmSize : api().list()) {
+         assertNotNull(vmSize.name());
+      }
+      assertTrue(api().list().size() > 0);
+   }
+
+   private VMSizeApi api() {
+      return api.getVMSizeApi(getLocation());
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VMSizeApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VMSizeApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VMSizeApiMockTest.java
new file mode 100644
index 0000000..6717e8b
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VMSizeApiMockTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.squareup.okhttp.mockwebserver.MockResponse;
+import org.jclouds.azurecompute.arm.domain.VMSize;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+
+@Test(groups = "unit", testName = "VMSizeApiMockTest", singleThreaded = true)
+public class VMSizeApiMockTest extends BaseAzureComputeApiMockTest {
+
+   public void testList() throws Exception {
+      server.enqueue(jsonResponse("/vmsizes.json"));
+      final VMSizeApi vmSizeAPI = api.getVMSizeApi("westeurope");
+      List<VMSize> vmSizes = vmSizeAPI.list();
+
+      assertNotNull(vmSizes);
+      assertEquals(vmSizes.size(), 3);
+      assertEquals(
+              vmSizes.get(0),
+              VMSize.create("Standard_A0", 1, 1047552, 20480, 768, 1));
+
+
+      assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/westeurope/vmSizes?api-version=2015-06-15");
+   }
+
+   public void testEmptyList() throws Exception {
+      server.enqueue(new MockResponse().setResponseCode(404));
+
+      final VMSizeApi vmSizeAPI = api.getVMSizeApi("location");
+
+      assertTrue(vmSizeAPI.list().isEmpty());
+
+      assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/location/vmSizes?api-version=2015-06-15");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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 87b84d8..f117f1c 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
@@ -69,7 +69,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
    }
 
    @Test
-   public void testCreate(){
+   public void testCreate() {
 
       StorageAccountApi storageApi = api.getStorageAccountApi(getResourceGroupName());
       StorageService storageAccount = storageApi.get(getStorageServiceName());
@@ -80,7 +80,8 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
 
       //Poll until resource is ready to be used
       boolean jobDone = Predicates2.retry(new Predicate<String>() {
-         @Override public boolean apply(String name) {
+         @Override
+         public boolean apply(String name) {
             return !api().get(name).properties().provisioningState().equals("Creating");
          }
       }, 60 * 20 * 1000).apply(getName());
@@ -109,7 +110,8 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
       api().stop(getName());
       //Poll until resource is ready to be used
       boolean jobDone = Predicates2.retry(new Predicate<String>() {
-         @Override public boolean apply(String name) {
+         @Override
+         public boolean apply(String name) {
             String status = "";
             List<VirtualMachineInstance.VirtualMachineStatus> statuses = api().getInstanceDetails(name).statuses();
             for (int c = 0; c < statuses.size(); c++) {
@@ -131,7 +133,8 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
 
       //Poll until resource is ready to be used
       boolean jobDone = Predicates2.retry(new Predicate<String>() {
-         @Override public boolean apply(String name) {
+         @Override
+         public boolean apply(String name) {
             String status = "";
             List<VirtualMachineInstance.VirtualMachineStatus> statuses = api().getInstanceDetails(name).statuses();
             for (int c = 0; c < statuses.size(); c++) {
@@ -153,7 +156,8 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
 
       //Poll until resource is ready to be used
       boolean jobDone = Predicates2.retry(new Predicate<String>() {
-         @Override public boolean apply(String name) {
+         @Override
+         public boolean apply(String name) {
             String status = "";
             List<VirtualMachineInstance.VirtualMachineStatus> statuses = api().getInstanceDetails(name).statuses();
             for (int c = 0; c < statuses.size(); c++) {
@@ -171,7 +175,8 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
 
       //Poll until resource is ready to be used
       jobDone = Predicates2.retry(new Predicate<String>() {
-         @Override public boolean apply(String name) {
+         @Override
+         public boolean apply(String name) {
             String status = "";
             List<VirtualMachineInstance.VirtualMachineStatus> statuses = api().getInstanceDetails(name).statuses();
             for (int c = 0; c < statuses.size(); c++) {
@@ -193,7 +198,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
       assertTrue(list.contains(vm));
    }
 
-   @Test(dependsOnMethods = {"testRestart", "testList", "testGet"},  alwaysRun = true)
+   @Test(dependsOnMethods = {"testRestart", "testList", "testGet"}, alwaysRun = true)
    public void testDelete() throws Exception {
       URI uri = api().delete(getName());
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/functions/URIParserTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/functions/URIParserTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/functions/URIParserTest.java
index f7b234d..cd0eb02 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/functions/URIParserTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/functions/URIParserTest.java
@@ -31,14 +31,14 @@ public class URIParserTest {
 
    public void testApply() {
       URIParser parser = new URIParser();
-      Multimap<String, String> headers = LinkedHashMultimap.<String, String> create();
+      Multimap<String, String> headers = LinkedHashMultimap.<String, String>create();
 
       URI uri = parser.apply(HttpResponse.builder().statusCode(200).build());
       assertNull(uri);
 
       try {
          uri = parser.apply(HttpResponse.builder().statusCode(202).build());
-      } catch (IllegalStateException ex){
+      } catch (IllegalStateException ex) {
          assertNotNull(ex);
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
index 0768dab..900d3e0 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
@@ -66,6 +66,24 @@ public class BaseAzureComputeApiLiveTest extends AbstractAzureComputeApiLiveTest
    private String storageServiceName = null;
 
 
+   protected String getCredential() {
+      String credential = null;
+      if (System.getProperty("test.azurecompute-arm.credential") != null) {
+         credential = System.getProperty("test.azurecompute-arm.credential");
+      }
+      assertNotNull(credential);
+      return credential;
+   }
+
+   protected String getIdentity() {
+      String identity = null;
+      if (System.getProperty("test.azurecompute-arm.identity") != null) {
+         identity = System.getProperty("test.azurecompute-arm.identity");
+      }
+      assertNotNull(identity);
+      return identity;
+   }
+
    protected String getStorageServiceName() {
       if (storageServiceName == null) {
          storageServiceName = String.format("%3.24s",
@@ -74,6 +92,10 @@ public class BaseAzureComputeApiLiveTest extends AbstractAzureComputeApiLiveTest
       return storageServiceName;
    }
 
+   protected String getLocation() {
+      return LOCATION;
+   }
+
    protected String getEndpoint() {
       String endpoint = null;
       if (System.getProperty("test.azurecompute-arm.endpoint") != null) {
@@ -114,7 +136,6 @@ public class BaseAzureComputeApiLiveTest extends AbstractAzureComputeApiLiveTest
       api.getResourceGroupApi().delete(name);
    }
 
-
    @BeforeClass
    @Override
    public void setup() {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/resources/createdeploymentaccepted.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/createdeploymentaccepted.json b/azurecompute-arm/src/test/resources/createdeploymentaccepted.json
new file mode 100644
index 0000000..8ae5a59
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/createdeploymentaccepted.json
@@ -0,0 +1,33 @@
+{
+  "id": "/subscriptions/04f7ec88-8e28-41ed-8537-5e17766001f5/resourceGroups/jims216group/providers/Microsoft.Resources/deployments/jcdep1458344383064",
+  "name": "jcdep1458344383064",
+  "properties": {
+    "parameters": {
+      "newStorageAccountName": {
+        "type": "String",
+        "value": "jcres1458344383064"
+      },
+      "storageAccountType": {
+        "type": "String",
+        "value": "Standard_LRS"
+      },
+      "location": {
+        "type": "String",
+        "value": "West US"
+      }
+    },
+    "mode": "Incremental",
+    "provisioningState": "Accepted",
+    "timestamp": "2016-03-18T23:39:47.3048037Z",
+    "duration": "PT2.4433028S",
+    "correlationId": "8dee9711-8632-4948-9fe6-368bb75e6438",
+    "providers": [{
+      "namespace": "Microsoft.Storage",
+      "resourceTypes": [{
+        "resourceType": "storageAccounts",
+        "locations": ["westus"]
+      }]
+    }],
+    "dependencies": []
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/resources/createdeploymentsucceeded.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/createdeploymentsucceeded.json b/azurecompute-arm/src/test/resources/createdeploymentsucceeded.json
new file mode 100644
index 0000000..e992204
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/createdeploymentsucceeded.json
@@ -0,0 +1,36 @@
+{
+  "id": "/subscriptions/04f7ec88-8e28-41ed-8537-5e17766001f5/resourceGroups/jims216group/providers/Microsoft.Resources/deployments/jcdep1458344383064",
+  "name": "jcdep1458344383064",
+  "properties": {
+    "parameters": {
+      "newStorageAccountName": {
+        "type": "String",
+        "value": "jcres1458344383064"
+      },
+      "storageAccountType": {
+        "type": "String",
+        "value": "Standard_LRS"
+      },
+      "location": {
+        "type": "String",
+        "value": "West US"
+      }
+    },
+    "mode": "Incremental",
+    "provisioningState": "Succeeded",
+    "timestamp": "2016-03-18T23:40:25.1856907Z",
+    "duration": "PT40.3241898S",
+    "correlationId": "8dee9711-8632-4948-9fe6-368bb75e6438",
+    "providers": [{
+      "namespace": "Microsoft.Storage",
+      "resourceTypes": [{
+        "resourceType": "storageAccounts",
+        "locations": ["westus"]
+      }]
+    }],
+    "dependencies": [],
+    "outputResources": [{
+      "id": "Microsoft.Storage/storageAccounts/jcres1458344383064"
+    }]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/resources/listdeployments.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/listdeployments.json b/azurecompute-arm/src/test/resources/listdeployments.json
new file mode 100644
index 0000000..122500f
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/listdeployments.json
@@ -0,0 +1,99 @@
+{
+  "value": [
+    {
+      "id": "/subscriptions/123abc12-1234-1234-1234-12345345234/resourceGroups/resourceGroup/providers/Microsoft.Resources/deployments/jcdep1458344383064",
+      "name": "jcdep1458344383064",
+      "properties": {
+        "parameters": {},
+        "mode": "Incremental",
+        "provisioningState": "Running",
+        "timestamp": "2016-04-26T11:48:11.1807222Z",
+        "duration": "PT0.950828S",
+        "correlationId": "f7876e0f-22ec-413c-a79e-0a718b4789a2",
+        "providers": [
+          {
+            "namespace": "Microsoft.Storage",
+            "resourceTypes": [
+              {
+                "resourceType": "storageAccounts",
+                "locations": [
+                  "northeurope"
+                ]
+              }
+            ]
+          },
+          {
+            "namespace": "Microsoft.Network",
+            "resourceTypes": [
+              {
+                "resourceType": "virtualNetworks",
+                "locations": [
+                  "northeurope"
+                ]
+              },
+              {
+                "resourceType": "publicIPAddresses",
+                "locations": [
+                  "northeurope"
+                ]
+              },
+              {
+                "resourceType": "networkInterfaces",
+                "locations": [
+                  "northeurope"
+                ]
+              }
+            ]
+          },
+          {
+            "namespace": "Microsoft.Compute",
+            "resourceTypes": [
+              {
+                "resourceType": "virtualMachines",
+                "locations": [
+                  "northeurope"
+                ]
+              }
+            ]
+          }
+        ],
+        "dependencies": [
+          {
+            "dependsOn": [
+              {
+                "id": "/subscriptions/123abc12-1234-1234-1234-12345345234/resourceGroups/resourceGroup/providers/Microsoft.Network/publicIPAddresses/jc1461584629971publicip",
+                "resourceType": "Microsoft.Network/publicIPAddresses",
+                "resourceName": "jc1461584629971publicip"
+              },
+              {
+                "id": "/subscriptions/123abc12-1234-1234-1234-12345345234/resourceGroups/resourceGroup/providers/Microsoft.Network/virtualNetworks/jc1461584629971virtualnetwork",
+                "resourceType": "Microsoft.Network/virtualNetworks",
+                "resourceName": "jc1461584629971virtualnetwork"
+              }
+            ],
+            "id": "/subscriptions/123abc12-1234-1234-1234-12345345234/resourceGroups/resourceGroup/providers/Microsoft.Network/networkInterfaces/jc1461584629971nic",
+            "resourceType": "Microsoft.Network/networkInterfaces",
+            "resourceName": "jc1461584629971nic"
+          },
+          {
+            "dependsOn": [
+              {
+                "id": "/subscriptions/123abc12-1234-1234-1234-12345345234/resourceGroups/resourceGroup/providers/Microsoft.Storage/storageAccounts/jc1461584629971storage",
+                "resourceType": "Microsoft.Storage/storageAccounts",
+                "resourceName": "jc1461584629971storage"
+              },
+              {
+                "id": "/subscriptions/123abc12-1234-1234-1234-12345345234/resourceGroups/resourceGroup/providers/Microsoft.Network/networkInterfaces/jc1461584629971nic",
+                "resourceType": "Microsoft.Network/networkInterfaces",
+                "resourceName": "jc1461584629971nic"
+              }
+            ],
+            "id": "/subscriptions/123abc12-1234-1234-1234-12345345234/resourceGroups/resourceGroup/providers/Microsoft.Compute/virtualMachines/jc1461584629971VirtualMachine",
+            "resourceType": "Microsoft.Compute/virtualMachines",
+            "resourceName": "jc1461584629971VirtualMachine"
+          }
+        ]
+      }
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/resources/offers.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/offers.json b/azurecompute-arm/src/test/resources/offers.json
new file mode 100644
index 0000000..473c748
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/offers.json
@@ -0,0 +1,7 @@
+[
+  {
+    "location": "eastus",
+    "name": "WindowsServer",
+    "id": "/Subscriptions/c36d97d3-3fea-4561-aa2d-e61168908c5b/Providers/Microsoft.Compute/Locations/eastus/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer"
+  }
+]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/resources/publishers.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/publishers.json b/azurecompute-arm/src/test/resources/publishers.json
new file mode 100644
index 0000000..32d3e84
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/publishers.json
@@ -0,0 +1,12 @@
+[
+  {
+    "location": "eastus",
+    "name": "MicrosoftVisualStudio",
+    "id": "/Subscriptions/c36d97d3-3fea-4561-aa2d-e61168908c5b/Providers/Microsoft.Compute/Locations/eastus/Publishers/MicrosoftVisualStudio"
+  },
+  {
+    "location": "eastus",
+    "name": "MicrosoftWindowsServer",
+    "id": "/Subscriptions/c36d97d3-3fea-4561-aa2d-e61168908c5b/Providers/Microsoft.Compute/Locations/eastus/Publishers/MicrosoftWindowsServer"
+  }
+]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/resources/skus.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/skus.json b/azurecompute-arm/src/test/resources/skus.json
new file mode 100644
index 0000000..68c5a81
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/skus.json
@@ -0,0 +1,12 @@
+[
+  {
+    "location": "eastus",
+    "name": "2008-R2-SP1",
+    "id": "/Subscriptions/c36d97d3-3fea-4561-aa2d-e61168908c5b/Providers/Microsoft.Compute/Locations/eastus/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2008-R2-SP1"
+  },
+  {
+    "location": "eastus",
+    "name": "2012-Datacenter",
+    "id": "/Subscriptions/c36d97d3-3fea-4561-aa2d-e61168908c5b/Providers/Microsoft.Compute/Locations/eastus/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2012-Datacenter"
+  }
+]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/resources/versions.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/versions.json b/azurecompute-arm/src/test/resources/versions.json
new file mode 100644
index 0000000..48659ed
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/versions.json
@@ -0,0 +1,12 @@
+[
+  {
+    "location": "eastus",
+    "name": "2.0.20151120",
+    "id": "/Subscriptions/c36d97d3-3fea-4561-aa2d-e61168908c5b/Providers/Microsoft.Compute/Locations/eastus/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2008-R2-SP1/Versions/2.0.20151120"
+  },
+  {
+    "location": "eastus",
+    "name": "2.0.20151214",
+    "id": "/Subscriptions/c36d97d3-3fea-4561-aa2d-e61168908c5b/Providers/Microsoft.Compute/Locations/eastus/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2008-R2-SP1/Versions/2.0.20151214"
+  }
+]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/test/resources/vmsizes.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vmsizes.json b/azurecompute-arm/src/test/resources/vmsizes.json
new file mode 100644
index 0000000..19ec780
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vmsizes.json
@@ -0,0 +1,28 @@
+{
+  "value": [
+    {
+      "name": "Standard_A0",
+      "numberOfCores": 1,
+      "osDiskSizeInMB": 1047552,
+      "resourceDiskSizeInMB": 20480,
+      "memoryInMB": 768,
+      "maxDataDiskCount": 1
+    },
+    {
+      "name": "Standard_A1",
+      "numberOfCores": 1,
+      "osDiskSizeInMB": 1047552,
+      "resourceDiskSizeInMB": 71680,
+      "memoryInMB": 1792,
+      "maxDataDiskCount": 2
+    },
+    {
+      "name": "Standard_A2",
+      "numberOfCores": 2,
+      "osDiskSizeInMB": 1047552,
+      "resourceDiskSizeInMB": 138240,
+      "memoryInMB": 3584,
+      "maxDataDiskCount": 4
+    }
+  ]
+}
\ No newline at end of file


[2/2] jclouds-labs git commit: JCLOUDS-664 Azurecompute-arm DeploymentApi OSImageApi VMSizeApi

Posted by na...@apache.org.
JCLOUDS-664 Azurecompute-arm DeploymentApi OSImageApi VMSizeApi


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

Branch: refs/heads/master
Commit: fca7addf03239f59706c765d6011df41414ae676
Parents: 17a12fc
Author: Rita Zhang <ri...@gmail.com>
Authored: Mon May 16 18:55:01 2016 -0700
Committer: Ignasi Barrera <na...@apache.org>
Committed: Fri Jun 3 00:25:57 2016 +0200

----------------------------------------------------------------------
 .../azurecompute/arm/AzureComputeApi.java       |  32 ++
 .../arm/config/AzureComputeHttpApiModule.java   |   4 +
 .../arm/config/AzureComputeProperties.java      |   2 +
 .../azurecompute/arm/domain/ComputeNode.java    |  31 ++
 .../azurecompute/arm/domain/Deployment.java     | 254 +++++++++++++
 .../azurecompute/arm/domain/DeploymentBody.java |  42 +++
 .../arm/domain/DeploymentProperties.java        |  31 ++
 .../arm/domain/DeploymentTemplate.java          | 105 ++++++
 .../jclouds/azurecompute/arm/domain/Offer.java  |  51 +++
 .../azurecompute/arm/domain/Publisher.java      |  52 +++
 .../arm/domain/ResourceDefinition.java          | 103 +++++
 .../jclouds/azurecompute/arm/domain/SKU.java    |  51 +++
 .../azurecompute/arm/domain/StorageService.java |  48 ++-
 .../azurecompute/arm/domain/VMDeployment.java   |  29 ++
 .../jclouds/azurecompute/arm/domain/VMSize.java |  67 ++++
 .../azurecompute/arm/domain/Version.java        |  49 +++
 .../arm/features/DeploymentApi.java             | 109 ++++++
 .../arm/features/NetworkInterfaceCardApi.java   |   8 +-
 .../azurecompute/arm/features/OSImageApi.java   |  84 +++++
 .../arm/features/StorageAccountApi.java         |   4 +-
 .../azurecompute/arm/features/VMSizeApi.java    |  45 +++
 .../arm/functions/ParseJobStatus.java           |   3 +
 .../arm/util/DeploymentTemplateBuilder.java     | 375 +++++++++++++++++++
 .../arm/features/DeploymentApiLiveTest.java     | 226 +++++++++++
 .../arm/features/DeploymentApiMockTest.java     | 154 ++++++++
 .../features/DeploymentTemplateBuilderTest.java | 224 +++++++++++
 .../arm/features/JobApiMockTest.java            |  13 +-
 .../NetworkInterfaceCardApiLiveTest.java        |  31 +-
 .../NetworkInterfaceCardApiMockTest.java        |  11 +-
 .../arm/features/OSImageApiLiveTest.java        |  69 ++++
 .../arm/features/OSImageApiMockTest.java        | 123 ++++++
 .../arm/features/ResourceGroupApiLiveTest.java  |   7 +-
 .../arm/features/StorageAccountApiLiveTest.java |   4 +-
 .../TemplateToDeploymentTemplateLiveTest.java   | 186 +++++++++
 .../arm/features/VMSizeApiLiveTest.java         |  40 ++
 .../arm/features/VMSizeApiMockTest.java         |  57 +++
 .../arm/features/VirtualMachineApiLiveTest.java |  19 +-
 .../arm/functions/URIParserTest.java            |   4 +-
 .../internal/BaseAzureComputeApiLiveTest.java   |  23 +-
 .../resources/createdeploymentaccepted.json     |  33 ++
 .../resources/createdeploymentsucceeded.json    |  36 ++
 .../src/test/resources/listdeployments.json     |  99 +++++
 azurecompute-arm/src/test/resources/offers.json |   7 +
 .../src/test/resources/publishers.json          |  12 +
 azurecompute-arm/src/test/resources/skus.json   |  12 +
 .../src/test/resources/versions.json            |  12 +
 .../src/test/resources/vmsizes.json             |  28 ++
 47 files changed, 2970 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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 f8ac6e9..4e10089 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,17 +16,22 @@
  */
 package org.jclouds.azurecompute.arm;
 
+import org.jclouds.azurecompute.arm.features.DeploymentApi;
 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.OSImageApi;
 import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
 import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
 import org.jclouds.azurecompute.arm.features.StorageAccountApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
 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.util.DeploymentTemplateBuilder;
 import org.jclouds.rest.annotations.Delegate;
 
+import com.google.inject.Provides;
 import javax.ws.rs.PathParam;
 import java.io.Closeable;
 
@@ -108,4 +113,31 @@ public interface AzureComputeApi extends Closeable {
    @Delegate
    VirtualMachineApi getVirtualMachineApi(@PathParam("resourceGroup") String resourceGroup);
 
+   /**
+    * This Azure Resource Manager API lists all available virtual machine sizes for a subscription in a given region
+    *
+    * @see <a href="https://msdn.microsoft.com/en-us/library/azure/mt269440.aspx">docs</a>
+    */
+   @Delegate
+   VMSizeApi getVMSizeApi(@PathParam("location") String location);
+
+   /**
+    * The Azure Resource Manager API gets all the OS images in your subscription.
+    *
+    * @see <a href="http://msdn.microsoft.com/en-us/library/jj157175">docs</a>
+    */
+   @Delegate
+   OSImageApi getOSImageApi(@PathParam("location") String location);
+
+   /**
+    * The Deployment API allows for the management of Azure Resource Manager resources through the use of templates.
+    *
+    * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn790549.aspx">docs</a>
+    */
+   @Delegate
+   DeploymentApi getDeploymentApi(@PathParam("resourcegroup") String resourceGroup);
+
+   @Provides
+   DeploymentTemplateBuilder.Factory deploymentTemplateFactory();
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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 eb6a6d6..30cbc1e 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
@@ -17,6 +17,8 @@
 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;
@@ -28,6 +30,7 @@ import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.config.HttpApiModule;
 import org.jclouds.oauth.v2.config.OAuthScopes;
 
+import com.google.inject.assistedinject.FactoryModuleBuilder;
 import com.google.inject.Scopes;
 
 @ConfiguresHttpApi
@@ -51,6 +54,7 @@ public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
    @Override
    protected void configure() {
       install(new AzureComputeParserModule());
+      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/fca7addf/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 e16b5da..48188c4 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
@@ -31,4 +31,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";
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ComputeNode.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ComputeNode.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ComputeNode.java
new file mode 100644
index 0000000..516bbf6
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ComputeNode.java
@@ -0,0 +1,31 @@
+/*
+ * 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.domain;
+
+import org.jclouds.azurecompute.arm.util.GetEnumValue;
+
+public class ComputeNode {
+   public enum Status {
+      GOOD,
+      BAD,
+      UNRECOGNIZED;
+
+      public static Status fromValue(final String text) {
+         return (Status) GetEnumValue.fromValueOrDefault(text, Status.UNRECOGNIZED);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Deployment.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Deployment.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Deployment.java
new file mode 100644
index 0000000..2fc85bc
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Deployment.java
@@ -0,0 +1,254 @@
+/*
+ * 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.domain;
+
+import static com.google.common.collect.ImmutableList.copyOf;
+
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.azurecompute.arm.util.GetEnumValue;
+import org.jclouds.domain.JsonBall;
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class Deployment {
+
+   public enum ProvisioningState {
+      ACCEPTED,
+      READY,
+      CANCELED,
+      FAILED,
+      DELETED,
+      SUCCEEDED,
+      RUNNING,
+      UNRECOGNIZED;
+
+      public static ProvisioningState fromValue(final String text) {
+         return (ProvisioningState) GetEnumValue.fromValueOrDefault(text, ProvisioningState.UNRECOGNIZED);
+      }
+   }
+
+   public enum DeploymentMode {
+      INCREMENTAL,
+      COMPLETE,
+      UNRECOGNIZED;
+
+      public static DeploymentMode fromValue(final String text) {
+         return (DeploymentMode) GetEnumValue.fromValueOrDefault(text, DeploymentMode.UNRECOGNIZED);
+      }
+   }
+
+   @AutoValue
+   public abstract static class TypeValue {
+      public abstract String type();
+
+      public abstract String value();
+
+      @SerializedNames({"type", "value"})
+      public static TypeValue create(final String type, final String value) {
+         return new AutoValue_Deployment_TypeValue(type, value);
+      }
+   }
+
+   @AutoValue
+   public abstract static class ProviderResourceType {
+      @Nullable
+      public abstract String resourceType();
+
+      @Nullable
+      public abstract List<String> locations();
+
+      @Nullable
+      public abstract List<String> apiVersions();
+
+      @Nullable
+      public abstract Map<String, JsonBall> properties();
+
+      @SerializedNames({"resourceType", "locations", "apiVersions", "properties"})
+      public static ProviderResourceType create(final String resourceType,
+                                                final List<String> locations,
+                                                final List<String> apiVersions,
+                                                @Nullable final Map<String, JsonBall> properties) {
+         return new AutoValue_Deployment_ProviderResourceType(resourceType,
+                 locations == null ? null : copyOf(locations),
+                 apiVersions == null ? null : copyOf(apiVersions),
+                 properties == null ? ImmutableMap.<String, JsonBall>builder().build() : ImmutableMap.copyOf(properties));
+      }
+   }
+
+   @AutoValue
+   public abstract static class Provider {
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String namespace();
+
+      @Nullable
+      public abstract String registrationState();
+
+      @Nullable
+      public abstract List<ProviderResourceType> resourceTypes();
+
+      @SerializedNames({"id", "namespace", "registrationState", "resourceTypes"})
+      public static Provider create(final String id,
+                                    final String namespace,
+                                    final String registrationState,
+                                    final List<ProviderResourceType> resourceTypes) {
+         return new AutoValue_Deployment_Provider(id, namespace, registrationState, resourceTypes == null ? null : copyOf(resourceTypes));
+      }
+   }
+
+   @AutoValue
+   public abstract static class Dependency {
+      @Nullable
+      public abstract List<Dependency> dependencies();
+
+      @Nullable
+      public abstract List<Dependency> dependsOn();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String resourceType();
+
+      @Nullable
+      public abstract String resourceName();
+
+      @SerializedNames({"dependencies", "dependsOn", "id", "resourceType", "resourceName"})
+      public static Dependency create(final List<Dependency> dependencies,
+                                      final List<Dependency> dependsOn,
+                                      final String id,
+                                      final String resourceType,
+                                      final String resourceName) {
+         return new AutoValue_Deployment_Dependency(dependencies == null ? null : copyOf(dependencies),
+               dependsOn == null ? null : copyOf(dependsOn), id, resourceType, resourceName);
+      }
+   }
+
+   @AutoValue
+   public abstract static class ContentLink {
+      public abstract String uri();
+
+      @Nullable
+      public abstract String contentVersion();
+
+      @SerializedNames({"uri", "contentVersion"})
+      public static ContentLink create(final String uri, final String contentVersion) {
+         return new AutoValue_Deployment_ContentLink(uri, contentVersion);
+      }
+   }
+
+   @AutoValue
+   public abstract static class DeploymentProperties {
+      @Nullable
+      public abstract String provisioningState();
+
+      @Nullable
+      public abstract String correlationId();
+
+      @Nullable
+      public abstract String timestamp();
+
+      @Nullable
+      public abstract Map<String, JsonBall> outputs();
+
+      @Nullable
+      public abstract List<Provider> providers();
+
+      @Nullable
+      public abstract List<Dependency> dependencies();
+
+      @Nullable
+      public abstract Map<String, JsonBall> template();
+
+      @Nullable
+      public abstract ContentLink templateLink();
+
+      @Nullable
+      public abstract Map<String, JsonBall> parameters();
+
+      @Nullable
+      public abstract ContentLink parametersLink();
+
+      public abstract String mode();
+
+      // The entries below seem to be dynamic/not documented in the specification
+      @Nullable
+      public abstract String duration();
+
+      @Nullable
+      public abstract List<Map<String, String>> outputResources();
+
+      @SerializedNames({"provisioningState", "correlationId", "timestamp", "outputs", "providers", "dependencies", "template", "templateLink", "parameters", "parametersLink", "mode", "duration", "outputResources"})
+      public static DeploymentProperties create(final String provisioningState,
+                                                final String correlationId,
+                                                final String timestamp,
+                                                @Nullable final Map<String, JsonBall> outputs,
+                                                final List<Provider> providers,
+                                                final List<Dependency> dependencies,
+                                                final Map<String, JsonBall> template,
+                                                final ContentLink templateLink,
+                                                final Map<String, JsonBall> parameters,
+                                                final ContentLink parametersLink,
+                                                final String mode,
+                                                final String duration,
+                                                final List<Map<String, String>> outputResources) {
+         return new AutoValue_Deployment_DeploymentProperties(provisioningState,
+                                                              correlationId,
+                                                              timestamp,
+                                                              outputs == null ? ImmutableMap.<String, JsonBall>builder().build() : ImmutableMap.copyOf(outputs),
+                                                              providers == null ? null : copyOf(providers),
+                                                              dependencies == null ? null : copyOf(dependencies),
+                                                              template == null ? ImmutableMap.<String, JsonBall>builder().build() : ImmutableMap.copyOf(template),
+                                                              templateLink,
+                                                              parameters == null ? ImmutableMap.<String, JsonBall>builder().build() : ImmutableMap.copyOf(parameters),
+                                                              parametersLink,
+                                                              mode,
+                                                              duration,
+                                                              outputResources == null ? null : copyOf(outputResources));
+      }
+   }
+
+   /**
+    * The ID associated with the template deployment.
+    */
+   @Nullable
+   public abstract String id();
+
+   /**
+    * The name associated with the template deployment.
+    */
+   public abstract String name();
+
+   /**
+    * Properties of the deployment.
+    */
+   @Nullable
+   public abstract DeploymentProperties properties();
+
+   @SerializedNames({"id", "name", "properties"})
+   public static Deployment create(final String id, final String name, final DeploymentProperties properties) {
+      return new AutoValue_Deployment(id, name, properties);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentBody.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentBody.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentBody.java
new file mode 100644
index 0000000..0f91360
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentBody.java
@@ -0,0 +1,42 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.azurecompute.arm.domain.DeploymentTemplate.Parameters;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class DeploymentBody {
+
+   @Nullable
+   public abstract DeploymentTemplate template();
+
+   @Nullable
+   public abstract String mode();
+
+   @Nullable
+   public abstract Parameters parameters();
+
+   @SerializedNames({"template", "mode", "parameters"})
+   public static DeploymentBody create(final DeploymentTemplate template,
+                                       final String mode,
+                                       final Parameters parameters) {
+      return new AutoValue_DeploymentBody(template, mode, parameters);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentProperties.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentProperties.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentProperties.java
new file mode 100644
index 0000000..94b53c5
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentProperties.java
@@ -0,0 +1,31 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class DeploymentProperties {
+
+   public abstract DeploymentBody properties();
+
+   @SerializedNames({"properties"})
+   public static DeploymentProperties create(final DeploymentBody properties) {
+      return new AutoValue_DeploymentProperties(properties);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentTemplate.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentTemplate.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentTemplate.java
new file mode 100644
index 0000000..848000d
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentTemplate.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+
+import java.util.List;
+import java.util.Map;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class DeploymentTemplate {
+
+   //Empty placeholders as we want to generate the empty JSON object
+   @AutoValue
+   public abstract static class Parameters {
+      public static Parameters create() {
+         return new AutoValue_DeploymentTemplate_Parameters();
+      }
+   }
+
+   public abstract String schema();
+
+   public abstract String contentVersion();
+
+   public abstract Parameters parameters();
+
+   public abstract Map<String, String> variables();
+
+   public abstract List<ResourceDefinition> resources();
+
+   @Nullable
+   public abstract List<?> outputs();
+
+   @SerializedNames({"$schema", "contentVersion", "parameters", "variables", "resources" , "outputs"})
+   public static DeploymentTemplate create(final String schema,
+                                           final String contentVersion,
+                                           final Parameters parameters,
+                                           final Map<String, String> variables,
+                                           final List<ResourceDefinition> resources,
+                                           final List<?> outputs) {
+
+      DeploymentTemplate.Builder builder = DeploymentTemplate.builder()
+              .schema(schema)
+              .contentVersion(contentVersion)
+              .parameters(parameters);
+
+      if (variables != null)
+         builder.variables(variables);
+
+      if (resources != null)
+         builder.resources(resources);
+
+      builder.outputs(outputs == null ? null : ImmutableList.copyOf(outputs));
+
+      return builder.build();
+   }
+
+   public static Builder builder() {
+      return new AutoValue_DeploymentTemplate.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder schema(String schema);
+
+      public abstract Builder contentVersion(String type);
+
+      public abstract Builder parameters(Parameters parameters);
+
+      public abstract Builder variables(Map<String, String> variables);
+
+      public abstract Builder resources(List<ResourceDefinition> resources);
+
+      public abstract Builder outputs(List<?> outputs);
+
+      abstract Map<String, String> variables();
+      abstract List<ResourceDefinition> resources();
+
+      abstract DeploymentTemplate autoBuild();
+
+      public DeploymentTemplate build() {
+         variables(variables() != null ? ImmutableMap.copyOf(variables()) : null);
+         resources(resources() != null ? ImmutableList.copyOf(resources()) : null);
+         return autoBuild();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Offer.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Offer.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Offer.java
new file mode 100644
index 0000000..d44c8f8
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Offer.java
@@ -0,0 +1,51 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+/**
+ * Offer
+ */
+@AutoValue
+public abstract class Offer {
+   /**
+    * The location of the Offer
+    */
+   @Nullable
+   public abstract String location();
+
+   /**
+    * The name of the Offer
+    */
+   @Nullable
+   public abstract String name();
+
+   /**
+    * The id of the Offer
+    */
+   @Nullable
+   public abstract String id();
+
+   @SerializedNames({"location", "name", "id"})
+   public static Offer create(final String location, final String name, final String id) {
+
+      return new AutoValue_Offer(location, name, id);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Publisher.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Publisher.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Publisher.java
new file mode 100644
index 0000000..4f5c53f
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Publisher.java
@@ -0,0 +1,52 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+/**
+ * Publisher
+ */
+@AutoValue
+public abstract class Publisher {
+
+   /**
+    * The location of the publisher
+    */
+   @Nullable
+   public abstract String location();
+
+   /**
+    * The name of the publisher
+    */
+   @Nullable
+   public abstract String name();
+
+   /**
+    * The id of the publisher
+    */
+   @Nullable
+   public abstract String id();
+
+   @SerializedNames({"location", "name", "id"})
+   public static Publisher create(final String location, final String name, final String id) {
+
+      return new AutoValue_Publisher(location, name, id);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ResourceDefinition.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ResourceDefinition.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ResourceDefinition.java
new file mode 100644
index 0000000..7c68e80
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ResourceDefinition.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.azurecompute.arm.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import java.util.List;
+import java.util.Map;
+
+@AutoValue
+public abstract class ResourceDefinition {
+
+    public abstract String name();
+
+    public abstract String type();
+
+    public abstract String location();
+
+    public abstract String apiVersion();
+
+    @Nullable
+    public abstract List<String> dependsOn();
+
+    @Nullable
+    public abstract Map<String, String> tags();
+
+    @Nullable
+    public abstract Object properties();
+
+    @SerializedNames({"name", "type", "location", "apiVersion", "dependsOn", "tags", "properties"})
+    public static ResourceDefinition create(final String name,
+                                            final String type,
+                                            final String location,
+                                            final String apiVersion,
+                                            final List<String> dependsOn,
+                                            final Map<String, String> tags,
+                                            final Object properties) {
+        ResourceDefinition.Builder builder = ResourceDefinition.builder()
+                .name(name)
+                .type(type)
+                .location(location)
+                .apiVersion(apiVersion)
+                .properties(properties);
+
+        builder.dependsOn(dependsOn == null ? null : ImmutableList.copyOf(dependsOn));
+
+        builder.tags(tags == null ? null : ImmutableMap.copyOf(tags));
+
+        return  builder.build();
+    }
+
+    public static Builder builder() {
+        return new AutoValue_ResourceDefinition.Builder();
+    }
+
+    @AutoValue.Builder
+    public abstract static class Builder {
+        public abstract Builder name(String name);
+
+        public abstract Builder type(String type);
+
+        public abstract Builder location(String location);
+
+        public abstract Builder apiVersion(String apiVersion);
+
+        public abstract Builder dependsOn(List<String> dependencies);
+
+        public abstract Builder tags(Map<String, String> tags);
+
+        public abstract Builder properties(Object properties);
+
+        abstract List<String>  dependsOn();
+        abstract Map<String, String>  tags();
+
+        abstract ResourceDefinition autoBuild();
+
+        public ResourceDefinition build() {
+            dependsOn(dependsOn() != null ? ImmutableList.copyOf(dependsOn()) : null);
+            tags(tags() != null ? ImmutableMap.copyOf(tags()) : null);
+            return autoBuild();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java
new file mode 100644
index 0000000..4c414e5
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java
@@ -0,0 +1,51 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+/**
+ * SKU
+ */
+@AutoValue
+public abstract class SKU {
+   /**
+    * The location of the SKU
+    */
+   @Nullable
+   public abstract String location();
+
+   /**
+    * The name of the SKU
+    */
+   @Nullable
+   public abstract String name();
+
+   /**
+    * The id of the SKU
+    */
+   @Nullable
+   public abstract String id();
+
+   @SerializedNames({"location", "name", "id"})
+   public static SKU create(final String location, final String name, final String id) {
+
+      return new AutoValue_SKU(location, name, id);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageService.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageService.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageService.java
index a151aec..a97117f 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageService.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageService.java
@@ -19,7 +19,6 @@ package org.jclouds.azurecompute.arm.domain;
 import com.google.auto.value.AutoValue;
 import java.util.Date;
 import java.util.Map;
-
 import com.google.common.collect.ImmutableMap;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
@@ -83,11 +82,13 @@ public abstract class StorageService {
        /**
         * Specifies the time that the storage account was created.
         */
+       @Nullable
        public abstract Date creationTime();
 
        /**
         * Specifies the endpoints of the storage account.
         */
+       @Nullable
        public abstract Map<String, String> primaryEndpoints();
 
        /**
@@ -105,6 +106,7 @@ public abstract class StorageService {
        /**
         * Specifies the secondary endpoints of the storage account.
         */
+       @Nullable
        public abstract Map<String, String> secondaryEndpoints();
 
       /**
@@ -133,9 +135,47 @@ public abstract class StorageService {
               final Map<String, String> secondaryEndpoints, final String secondaryLocation,
               final RegionStatus statusOfPrimary, final RegionStatus statusOfSecondary) {
 
-         return new AutoValue_StorageService_StorageServiceProperties(accountType, creationTime,
-                 primaryEndpoints == null ? ImmutableMap.<String, String>builder().build() : ImmutableMap.copyOf(primaryEndpoints), primaryLocation, provisioningState,
-                 secondaryEndpoints == null ? ImmutableMap.<String, String>builder().build() : ImmutableMap.copyOf(secondaryEndpoints), secondaryLocation, statusOfPrimary, statusOfSecondary);
+         StorageServiceProperties.Builder builder = StorageServiceProperties.builder()
+                 .accountType(accountType)
+                 .creationTime(creationTime)
+                 .primaryLocation(primaryLocation)
+                 .provisioningState(provisioningState)
+                 .secondaryLocation(secondaryLocation)
+                 .statusOfPrimary(statusOfPrimary)
+                 .statusOfSecondary(statusOfSecondary);
+
+
+         builder.primaryEndpoints(primaryEndpoints != null ? ImmutableMap.copyOf(primaryEndpoints) : null);
+         builder.secondaryEndpoints(secondaryEndpoints != null ? ImmutableMap.copyOf(secondaryEndpoints) : null);
+
+         return  builder.build();
+      }
+      public static Builder builder() {
+         return new AutoValue_StorageService_StorageServiceProperties.Builder();
+      }
+
+      @AutoValue.Builder
+      public abstract static class Builder {
+         public abstract Builder accountType(AccountType accountType);
+         public abstract Builder creationTime(Date creationTime);
+         public abstract Builder primaryEndpoints(Map<String, String> primaryEndpoints);
+         public abstract Builder primaryLocation(String primaryLocation);
+         public abstract Builder provisioningState(Status provisioningState);
+         public abstract Builder secondaryEndpoints(Map<String, String> secondaryEndpoints);
+         public abstract Builder secondaryLocation(String secondaryLocation);
+         public abstract Builder statusOfPrimary(RegionStatus statusOfPrimary);
+         public abstract Builder statusOfSecondary(RegionStatus statusOfSecondary);
+
+         abstract Map<String, String>  primaryEndpoints();
+         abstract Map<String, String>  secondaryEndpoints();
+
+         abstract StorageServiceProperties autoBuild();
+
+         public StorageServiceProperties build() {
+            primaryEndpoints(primaryEndpoints() != null ? ImmutableMap.copyOf(primaryEndpoints()) : null);
+            secondaryEndpoints(secondaryEndpoints() != null ? ImmutableMap.copyOf(secondaryEndpoints()) : null);
+            return autoBuild();
+         }
       }
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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
new file mode 100644
index 0000000..2504409
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMDeployment.java
@@ -0,0 +1,29 @@
+/*
+ * 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.domain;
+
+
+import java.util.List;
+
+public class VMDeployment {
+
+   public Deployment deployment;
+
+   public List<PublicIPAddress> ipAddressList;
+
+   public VirtualMachineInstance vm;
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMSize.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMSize.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMSize.java
new file mode 100644
index 0000000..6794735
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMSize.java
@@ -0,0 +1,67 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+/**
+ * A VM Size that is available in a region for a given subscription.
+ *
+ * @see <a href="https://msdn.microsoft.com/en-us/library/azure/mt269440.aspx" >api</a>
+ */
+@AutoValue
+public abstract class VMSize {
+
+   /**
+    * The name of the VM size.
+    */
+   public abstract String name();
+
+   /**
+    * The number of cores that are available in the VM size.
+    */
+   public abstract Integer numberOfCores();
+
+   /**
+    * Specifies the size in MB of the OS Disk.
+    */
+   public abstract Integer osDiskSizeInMB();
+
+   /**
+    * The size of the resource disk.
+    */
+   public abstract Integer resourceDiskSizeInMB();
+
+   /**
+    * Specifies the available RAM in MB.
+    */
+   public abstract Integer memoryInMB();
+
+   /**
+    * Specifies the maximum number of data disks that can be attached to the VM size.
+    */
+   public abstract Integer maxDataDiskCount();
+
+   @SerializedNames({ "name", "numberOfCores", "osDiskSizeInMB", "resourceDiskSizeInMB", "memoryInMB", "maxDataDiskCount"})
+   public static VMSize create(final String name, final Integer numberOfCores, final Integer osDiskSizeInMB,
+           final Integer resourceDiskSizeInMB, final Integer memoryInMB, final Integer maxDataDiskCount) {
+
+      return new AutoValue_VMSize(name, numberOfCores, osDiskSizeInMB, resourceDiskSizeInMB, memoryInMB, maxDataDiskCount);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Version.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Version.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Version.java
new file mode 100644
index 0000000..63d7e11
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Version.java
@@ -0,0 +1,49 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+/**
+ * Version
+ */
+@AutoValue
+public abstract class Version {
+
+   /**
+    * The location of the Version
+    */
+   public abstract String location();
+
+   /**
+    * The name of the Version
+    */
+   public abstract String name();
+
+   /**
+    * The id of the Version
+    */
+   public abstract String id();
+
+   @SerializedNames({"location", "name", "id"})
+   public static Version create(final String location, final String name, final String id) {
+
+      return new AutoValue_Version(location, name, id);
+   }
+}
+

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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
new file mode 100644
index 0000000..550f8ea
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
@@ -0,0 +1,109 @@
+/*
+ * 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 javax.inject.Named;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+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.functions.URIParser;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+
+import java.net.URI;
+import java.util.List;
+
+/**
+ * - create deployment
+ * - delete deployment
+ * - get information about deployment
+ */
+@Path("/resourcegroups/{resourcegroup}/providers/microsoft.resources/deployments")
+@QueryParams(keys = "api-version", values = "2016-02-01")
+@RequestFilters(OAuthFilter.class)
+@Consumes(MediaType.APPLICATION_JSON)
+public interface DeploymentApi {
+
+   /**
+    * The Create Template Deployment operation starts the process of an ARM Template deployment.
+    * It then returns a Deployment object.
+    */
+   @Named("deployment:create")
+   @Path("/{deploymentname}")
+   @Payload("{properties}")
+   @PUT
+   @Produces(MediaType.APPLICATION_JSON)
+   Deployment create(@PathParam("deploymentname") String deploymentname,
+                               @PayloadParam("properties") String properties);
+
+   /**
+    * Get Deployment Information returns information about the specified deployment.
+    */
+   @Named("deployment:get")
+   @Path("/{deploymentname}")
+   @GET
+   @Fallback(NullOnNotFoundOr404.class)
+   Deployment get(@PathParam("deploymentname") String deploymentname);
+
+   /**
+    * Validate Deployment validates deployment template before deployment
+    */
+   @Named("deployment:validate")
+   @Path("/{deploymentname}/validate")
+   @Payload("{properties}")
+   @POST
+   @Produces(MediaType.APPLICATION_JSON)
+   Deployment validate(@PathParam("deploymentname") String deploymentname,
+                                 @PayloadParam("properties") String properties);
+
+   /**
+    * List all deployments in a resource group
+    */
+   @Named("deployment:list")
+   @GET
+   @SelectJson("value")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Deployment> list();
+
+   /**
+    * The Delete Template Deployment operation starts the process of an ARM Template removal.
+    */
+   @Named("deployment:delete")
+   @DELETE
+   @ResponseParser(URIParser.class)
+   @Path("/{deploymentname}")
+   @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   URI delete(@PathParam("deploymentname") String deploymentname);
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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 c7c665d..2f19996 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
@@ -20,7 +20,7 @@ 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.functions.FalseOn204;
+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;
@@ -41,6 +41,7 @@ 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")
@@ -73,6 +74,7 @@ public interface NetworkInterfaceCardApi {
    @Named("networkinterfacecard:delete")
    @Path("/{networkinterfacecardname}")
    @DELETE
-   @ResponseParser(FalseOn204.class)
-   boolean delete(@PathParam("networkinterfacecardname") String networkinterfacecardname);
+   @ResponseParser(URIParser.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   URI delete(@PathParam("networkinterfacecardname") String networkinterfacecardname);
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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
new file mode 100644
index 0000000..96dce6b
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/OSImageApi.java
@@ -0,0 +1,84 @@
+/*
+ * 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 static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
+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.PathParam;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+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.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")
+@Consumes(APPLICATION_JSON)
+public interface OSImageApi {
+
+   /**
+    * List Publishers in location
+    */
+   @Named("publisher:list")
+   @GET
+   @Path("/publishers")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Publisher> listPublishers();
+
+   /**
+    * List Offers in publisher
+    */
+   @Named("offer:list")
+   @GET
+   @Path("/publishers/{publisher}/artifacttypes/vmimage/offers")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Offer> listOffers(@PathParam("publisher") String publisher);
+
+   /**
+    * List SKUs in offer
+    */
+   @Named("sku:list")
+   @GET
+   @Path("/publishers/{publisher}/artifacttypes/vmimage/offers/{offer}/skus")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<SKU> listSKUs(@PathParam("publisher") String publisher, @PathParam("offer") String offer);
+
+   /**
+    * List Versions in SKU
+    */
+   @Named("version:list")
+   @GET
+   @Path("/publishers/{publisher}/artifacttypes/vmimage/offers/{offer}/skus/{sku}/versions")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Version> listVersions(@PathParam("publisher") String publisher, @PathParam("offer") String offer,
+                          @PathParam("sku") String sku);
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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 8ebfc82..fd75fca 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
@@ -51,6 +51,8 @@ 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.
  *
@@ -58,7 +60,7 @@ import java.net.URI;
  */
 @Path("/")
 @RequestFilters(OAuthFilter.class)
-@QueryParams(keys = "api-version", values = "2015-06-15")
+@QueryParams(keys = "api-version", values = STORAGE_API_VERSION)
 @Consumes(MediaType.APPLICATION_JSON)
 public interface StorageAccountApi {
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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
new file mode 100644
index 0000000..345e08c
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VMSizeApi.java
@@ -0,0 +1,45 @@
+/*
+ * 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 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 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;
+
+@Path("/providers/Microsoft.Compute/locations/{location}/vmSizes")
+@QueryParams(keys = "api-version", values = "2015-06-15")
+@RequestFilters(OAuthFilter.class)
+@Consumes(MediaType.APPLICATION_JSON)
+public interface VMSizeApi {
+
+   @Named("vmSizes:list")
+   @GET
+   @SelectJson("value")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<VMSize> list();
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/ParseJobStatus.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/ParseJobStatus.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/ParseJobStatus.java
index 5770582..045431c 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/ParseJobStatus.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/ParseJobStatus.java
@@ -30,6 +30,7 @@ public class ParseJobStatus implements Function<HttpResponse, ParseJobStatus.Job
       DONE,
       IN_PROGRESS,
       FAILED,
+      NO_CONTENT,
       UNRECOGNIZED;
 
       public static JobStatus fromValue(final String text) {
@@ -39,6 +40,8 @@ public class ParseJobStatus implements Function<HttpResponse, ParseJobStatus.Job
    public JobStatus apply(final HttpResponse from) {
       if (from.getStatusCode() == 202 ){
          return JobStatus.IN_PROGRESS;
+      } else if (from.getStatusCode() == 204) {
+         return JobStatus.NO_CONTENT;
       } else if (from.getStatusCode() == 200 ){
          return JobStatus.DONE;
       } else {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fca7addf/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
new file mode 100644
index 0000000..ffa533e
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java
@@ -0,0 +1,375 @@
+/*
+ * 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 com.google.common.collect.ImmutableMap;
+import com.google.inject.assistedinject.Assisted;
+
+import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.azurecompute.arm.domain.DataDisk;
+import org.jclouds.azurecompute.arm.domain.DeploymentBody;
+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.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.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.Subnet;
+import org.jclouds.azurecompute.arm.domain.Subnet.SubnetProperties;
+import org.jclouds.azurecompute.arm.domain.VHD;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
+import org.jclouds.azurecompute.arm.domain.VirtualNetwork.VirtualNetworkProperties;
+import org.jclouds.azurecompute.arm.domain.VirtualNetwork.AddressSpace;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.json.Json;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.inject.Inject;
+
+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 group;
+   private final Template template;
+   private final Json json;
+
+   private TemplateOptions options;
+   private List<ResourceDefinition> resources;
+   private Map<String, String> variables;
+   private String loginUser;
+   private String loginPassword;
+   private String location;
+
+   public static final String DEFAULT_LOGIN_USER = "jclouds";
+   public static final String DEFAULT_LOGIN_PASSWORD = "Password1!";
+   private static final String DEPLOYMENT_MODE = "Incremental";
+   private static final String DEFAULT_DATA_DISK_SIZE = "1023";
+
+   private static final String DEFAULT_vnAddresSpacePrefix = "10.0.0.0/16";
+   private static final String DEFAULT_subnetAddressPrefix = "10.0.0.0/24";
+
+   @Inject
+   DeploymentTemplateBuilder(Json json, @Assisted("group") String group, @Assisted("name") String name, @Assisted Template template) {
+      this.name = name;
+      this.group = group;
+      this.template = template;
+      this.options = template.getOptions().as(TemplateOptions.class);
+      this.variables = new HashMap<String, String>();
+      this.resources = new ArrayList<ResourceDefinition>();
+      this.loginUser = options.getLoginUser() == null ? DEFAULT_LOGIN_USER : options.getLoginUser();
+      this.loginPassword = options.getLoginPassword() == null ? DEFAULT_LOGIN_PASSWORD : options.getLoginPassword();
+      this.location = template.getLocation().getId();
+      this.json = json;
+   }
+
+   public String getLoginUserUsername() {
+      return loginUser;
+   }
+
+   public String getLoginPassword() {
+      return loginPassword;
+   }
+
+   public Template getTemplate() {
+      return template;
+   }
+
+   public DeploymentBody getDeploymentTemplate() {
+
+      addStorageResource();
+      addVirtualNetworkResource();
+      addPublicIpAddress();
+      addNetworkInterfaceCard();
+      addVirtualMachine();
+
+      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(DeploymentTemplate.Parameters.create())
+              .build();
+
+      DeploymentBody body = DeploymentBody.create(template, DEPLOYMENT_MODE, DeploymentTemplate.Parameters.create());
+
+      return body;
+   }
+
+   public String getDeploymentTemplateJson(DeploymentProperties properties){
+      return json.toJson(properties);
+   }
+
+   private void addStorageResource() {
+      String storageAccountName = name.replaceAll("[^A-Za-z0-9 ]", "") + "storage";
+
+      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 addVirtualNetworkResource() {
+      String virtualNetworkName = group + "virtualnetwork";
+
+      String subnetName = group + "subnet";
+      variables.put("virtualNetworkName", virtualNetworkName);
+      variables.put("virtualNetworkReference", "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]");
+      variables.put("subnetName", subnetName);
+      variables.put("subnetReference", "[concat(variables('virtualNetworkReference'),'/subnets/',variables('subnetName'))]");
+
+      VirtualNetworkProperties properties = VirtualNetworkProperties.builder()
+              .addressSpace(
+                      AddressSpace.create(Arrays.asList(DEFAULT_vnAddresSpacePrefix))
+              )
+              .subnets(
+                      Arrays.asList(
+                              Subnet.create("[variables('subnetName')]", null, null,
+                                      SubnetProperties.builder()
+                                              .addressPrefix(DEFAULT_subnetAddressPrefix).build()
+                              ))
+              )
+              .build();
+
+
+      ResourceDefinition virtualNetwork = ResourceDefinition.builder()
+              .name("[variables('virtualNetworkName')]")
+              .type("Microsoft.Network/virtualNetworks")
+              .location(location)
+              .apiVersion(STORAGE_API_VERSION)
+              .properties(properties)
+              .build();
+
+      resources.add(virtualNetwork);
+   }
+
+   private void addPublicIpAddress() {
+      String publicIPAddressName = name + "publicip";
+      String dnsLabelPrefix = name; //TODO: read from Azure template properties
+
+      PublicIPAddressProperties.Builder properties = PublicIPAddressProperties.builder();
+
+      if (!dnsLabelPrefix.isEmpty()) {
+         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";
+      variables.put("ipConfigurationName", ipConfigurationName);
+
+      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);
+
+      NetworkInterfaceCardProperties networkInterfaceCardProperties = NetworkInterfaceCardProperties.builder()
+              .ipConfigurations(ipConfigurations)
+              .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(Arrays.asList("[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
+                      "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"))
+              .properties(networkInterfaceCardProperties)
+              .build();
+
+      resources.add(networkInterfaceCard);
+   }
+
+   private void addVirtualMachine() {
+
+      //Build OS Profile
+      final String computerName = name + "pc";
+
+      variables.put("loginUser", loginUser);
+      OSProfile.Builder profileBuilder = OSProfile.builder()
+              .adminUsername(loginUser)
+              .computerName(computerName);
+
+      boolean usePublicKey = options.getPublicKey() != null;
+
+      if (usePublicKey) {
+         OSProfile.LinuxConfiguration configuration = OSProfile.LinuxConfiguration.create("true",
+                 OSProfile.LinuxConfiguration.SSH.create(Arrays.asList(
+                         OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create(
+                                 "[concat('/home/',variables('loginUser'),'/.ssh/authorized_keys')]",
+                                 options.getPublicKey())
+                 ))
+         );
+         profileBuilder.linuxConfiguration(configuration);
+      } else {
+         profileBuilder.adminPassword(loginPassword);
+      }
+
+      OSProfile osProfile = profileBuilder.build();
+
+      //Build Image Reference
+      final String imagePublisher = template.getImage().getProviderId();
+      final String imageOffer = template.getImage().getName();
+      final String imageSku = template.getImage().getVersion();
+
+      ImageReference imageReference = ImageReference.builder()
+              .publisher(imagePublisher)
+              .offer(imageOffer)
+              .sku(imageSku)
+              .version("latest")
+              .build();
+
+      //Build OsDisk
+      final String storageAccountContainerName = "vhds";
+      variables.put("storageAccountContainerName", storageAccountContainerName);
+
+      final String osDiskName = name + "osdisk";
+      variables.put("osDiskName", osDiskName);
+
+      OSDisk osDisk = OSDisk.builder()
+              .name("[variables('osDiskName')]")
+              .vhd(
+                      VHD.create("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net/',variables('storageAccountContainerName'),'/',variables('osDiskName'),'.vhd')]")
+              )
+              .caching("ReadWrite")
+              .createOption("FromImage")
+              .build();
+
+
+      //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(DEFAULT_DATA_DISK_SIZE)
+              .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 storageProfile = StorageProfile.builder()
+              .imageReference(imageReference)
+              .osDisk(osDisk)
+              .dataDisks(dataDisks)
+              .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();
+
+      variables.put("virtualMachineName", name);
+      ResourceDefinition virtualMachine = ResourceDefinition.builder()
+              .name("[variables('virtualMachineName')]")
+              .type("Microsoft.Compute/virtualMachines")
+              .location(location)
+              .apiVersion(STORAGE_API_VERSION)
+              .dependsOn(Arrays.asList("[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
+                      "[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceCardName'))]"))
+              .tags(ImmutableMap.of("displayName", "VirtualMachine"))
+              .properties(properties)
+              .build();
+
+      resources.add(virtualMachine);
+   }
+
+}