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 2018/01/08 14:52:22 UTC

[01/50] [abbrv] jclouds git commit: edit VirtualMachineApi.create to createOrUpdate

Repository: jclouds
Updated Branches:
  refs/heads/master 9fef6ed06 -> 3877303ed


edit VirtualMachineApi.create to createOrUpdate

- add live test for update vm
- update virtual machine api docs
- fix VirtualMachineApiMockTest


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

Branch: refs/heads/master
Commit: 894be791ea6a64dc0402e275e04a73736ec87c35
Parents: cec7308
Author: Andrea Turli <an...@gmail.com>
Authored: Thu Mar 2 22:22:42 2017 +0100
Committer: Andrea Turli <an...@gmail.com>
Committed: Fri Mar 3 15:28:07 2017 +0100

----------------------------------------------------------------------
 .../arm/AzureComputeProviderMetadata.java       | 38 +++++++--------
 .../arm/compute/AzureComputeServiceAdapter.java | 32 ++++++-------
 .../functions/VirtualMachineToNodeMetadata.java | 24 +++++-----
 .../arm/features/VirtualMachineApi.java         | 40 ++++------------
 .../arm/features/VirtualMachineApiLiveTest.java | 50 +++++++++++++++-----
 .../arm/features/VirtualMachineApiMockTest.java |  4 +-
 6 files changed, 94 insertions(+), 94 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/894be791/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index a4c2bbe..08979b7 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -17,24 +17,6 @@
 package org.jclouds.azurecompute.arm;
 
 
-import static org.jclouds.Constants.PROPERTY_MAX_RATE_LIMIT_WAIT;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
-import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_AUTHENTICATE_SUDO;
-import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER;
-import static org.jclouds.compute.config.ComputeServiceProperties.POLL_INITIAL_PERIOD;
-import static org.jclouds.compute.config.ComputeServiceProperties.POLL_MAX_PERIOD;
-import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
-import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
-import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
-import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
-import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
-import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
-
 import java.net.URI;
 import java.util.Properties;
 
@@ -60,6 +42,24 @@ import org.jclouds.providers.internal.BaseProviderMetadata;
 
 import com.google.auto.service.AutoService;
 
+import static org.jclouds.Constants.PROPERTY_MAX_RATE_LIMIT_WAIT;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
+import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_AUTHENTICATE_SUDO;
+import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER;
+import static org.jclouds.compute.config.ComputeServiceProperties.POLL_INITIAL_PERIOD;
+import static org.jclouds.compute.config.ComputeServiceProperties.POLL_MAX_PERIOD;
+import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
+import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
+import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
+import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
+import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
+
 @AutoService(ProviderMetadata.class)
 public class AzureComputeProviderMetadata extends BaseProviderMetadata {
 
@@ -114,7 +114,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(API_VERSION_PREFIX + AvailabilitySetApi.class.getSimpleName(), "2016-03-30");
       properties.put(API_VERSION_PREFIX + "GetVirtualMachine", "2016-03-30");
       properties.put(API_VERSION_PREFIX + "GetVirtualMachineInstance", "2016-03-30");
-      properties.put(API_VERSION_PREFIX + "CreateVirtualMachine", "2016-03-30");
+      properties.put(API_VERSION_PREFIX + "CreateOrUpdateVirtualMachine", "2016-03-30");
       properties.put(API_VERSION_PREFIX + "ListVirtualMachines", "2015-06-15");
       properties.put(API_VERSION_PREFIX + "DeleteVirtualMachine", "2016-03-30");
       

http://git-wip-us.apache.org/repos/asf/jclouds/blob/894be791/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index a1204bf..f510109 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -16,20 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.contains;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.find;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
-import static org.jclouds.util.Closeables2.closeQuietly;
-
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -98,6 +84,20 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.contains;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.find;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
+import static org.jclouds.util.Closeables2.closeQuietly;
+
 /**
  * Defines the connection between the {@link AzureComputeApi} implementation and
  * the jclouds {@link org.jclouds.compute.ComputeService}.
@@ -138,7 +138,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(template.getLocation().getId());
 
       // TODO ARM specific options
-      // TODO network ids => create one nic in each network
+      // TODO network ids => createOrUpdate one nic in each network
       
       IdReference availabilitySet = null;
       if (templateOptions.getAvailabilitySet() != null) {
@@ -166,7 +166,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       Map<String, String> metadataAndTags = metadataAndTagsAsCommaDelimitedValue(template.getOptions());
       Plan plan = getMarketplacePlanFromImageMetadata(template.getImage());
 
-      VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroup.name()).create(name, template.getLocation().getId(),
+      VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroup.name()).createOrUpdate(name, template.getLocation().getId(),
             virtualMachineProperties, metadataAndTags, plan);
 
       // Safe to pass null credentials here, as jclouds will default populate

http://git-wip-us.apache.org/repos/asf/jclouds/blob/894be791/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
index 29a57e4..cb40a14 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
@@ -16,18 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.compute.functions;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Strings.nullToEmpty;
-import static com.google.common.collect.Iterables.find;
-import static com.google.common.collect.Iterables.tryFind;
-import static org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.GROUP_KEY;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
-import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
-import static org.jclouds.location.predicates.LocationPredicates.idEquals;
-import static org.jclouds.util.Closeables2.closeQuietly;
-
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -71,6 +59,18 @@ import com.google.common.cache.LoadingCache;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Strings.nullToEmpty;
+import static com.google.common.collect.Iterables.find;
+import static com.google.common.collect.Iterables.tryFind;
+import static org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.GROUP_KEY;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
+import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
+import static org.jclouds.location.predicates.LocationPredicates.idEquals;
+import static org.jclouds.util.Closeables2.closeQuietly;
+
 public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> {
 
    @Resource

http://git-wip-us.apache.org/repos/asf/jclouds/blob/894be791/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
index 805378b..c87390e 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
@@ -53,16 +53,13 @@ import org.jclouds.rest.binders.BindToJsonPayload;
 /**
  * The Virtual Machine API includes operations for managing the virtual machines in your subscription.
  *
- * @see <a href="https://msdn.microsoft.com/en-us/library/azure/mt163630.aspx">docs</a>
+ * @see <a href="https://docs.microsoft.com/en-us/rest/api/compute/virtualmachines/virtualmachines-rest-api">docs</a>
  */
 @Path("/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines")
 @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface VirtualMachineApi {
 
-   /**
-    * The Get Virtual Machine details
-    */
    @Named("GetVirtualMachine")
    @GET
    @Path("/{name}")
@@ -70,7 +67,7 @@ public interface VirtualMachineApi {
    VirtualMachine get(@PathParam("name") String name);
 
    /**
-    * Get information about the model view and instance view of a virtual machine:
+    * Get information about the model view and instance view of a virtual machine
     */
    @Named("GetVirtualMachineInstance")
    @GET
@@ -78,34 +75,25 @@ public interface VirtualMachineApi {
    @Fallback(Fallbacks.NullOnNotFoundOr404.class)
    VirtualMachineInstance getInstanceDetails(@PathParam("name") String name);
    
-   /**
-    * The Create Virtual Machine
-    */
-   @Named("CreateVirtualMachine")
+   @Named("CreateOrUpdateVirtualMachine")
    @PUT
    @Payload("%7B\"location\":\"{location}\",\"tags\":{tags},\"properties\":{properties},\"plan\":{plan}%7D")
    @MapBinder(BindToJsonPayload.class)
    @Path("/{vmname}")
    @QueryParams(keys = "validating", values = "false")
    @Produces(MediaType.APPLICATION_JSON)
-   VirtualMachine create(@PathParam("vmname") String vmname,
-                         @PayloadParam("location") String location,
-                         @PayloadParam("properties") VirtualMachineProperties properties,
-                         @PayloadParam("tags") Map<String, String> tags,
-                         @Nullable @PayloadParam("plan") Plan plan);
+   VirtualMachine createOrUpdate(@PathParam("vmname") String vmname,
+                                 @PayloadParam("location") String location,
+                                 @PayloadParam("properties") VirtualMachineProperties properties,
+                                 @PayloadParam("tags") Map<String, String> tags,
+                                 @Nullable @PayloadParam("plan") Plan plan);
 
-   /**
-    * The List Virtual Machines operation
-    */
    @Named("ListVirtualMachines")
    @GET
    @SelectJson("value")
    @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
    List<VirtualMachine> list();
 
-   /**
-    * The Delete Virtual Machine operation
-    */
    @Named("DeleteVirtualMachine")
    @DELETE
    @Path("/{name}")
@@ -113,33 +101,21 @@ public interface VirtualMachineApi {
    @Fallback(Fallbacks.NullOnNotFoundOr404.class)
    URI delete(@PathParam("name") String name);
 
-   /**
-    * The Restart Virtual Machine operation
-    */
    @Named("RestartVirtualMachine")
    @POST
    @Path("/{name}/restart")
    void restart(@PathParam("name") String name);
 
-   /**
-    * The start Virtual Machine operation
-    */
    @Named("StartVirtualMachine")
    @POST
    @Path("/{name}/start")
    void start(@PathParam("name") String name);
 
-   /**
-    * The stop Virtual Machine operation
-    */
    @Named("StopVirtualMachine")
    @POST
    @Path("/{name}/powerOff")
    void stop(@PathParam("name") String name);
 
-   /**
-    * Generalize the virtual machine
-    */
    @Named("generalize")
    @POST
    @Path("/{name}/generalize")

http://git-wip-us.apache.org/repos/asf/jclouds/blob/894be791/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
index 8bc25c2..6fe65e3 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
@@ -16,11 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.jclouds.util.Predicates2.retry;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -55,9 +50,16 @@ import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
 @Test(groups = "live", testName = "VirtualMachineApiLiveTest")
 public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
 
@@ -102,7 +104,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
    public void testCreate() {
       String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
 
-      VirtualMachine vm = api().create(vmName, LOCATION, getProperties(blob, nicName),
+      VirtualMachine vm = api().createOrUpdate(vmName, LOCATION, getProperties(blob, nicName),
             Collections.<String, String> emptyMap(), null);
       assertTrue(!vm.name().isEmpty());
 
@@ -113,7 +115,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
             return !api().get(name).properties().provisioningState().equals(VirtualMachineProperties.ProvisioningState.CREATING);
          }
       }, 60 * 20 * 1000).apply(vmName);
-      assertTrue(jobDone, "create operation did not complete in the configured timeout");
+      assertTrue(jobDone, "createOrUpdate operation did not complete in the configured timeout");
 
       VirtualMachineProperties.ProvisioningState status = api().get(vmName).properties().provisioningState();
       // Cannot be creating anymore. Should be succeeded or running but not failed.
@@ -133,18 +135,40 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
       assertTrue(!vmi.statuses().isEmpty());
    }
 
-   @Test(dependsOnMethods = "testStart")
-   public void testStop() {
-      api().stop(vmName);
-      assertTrue(stateReached(PowerState.STOPPED), "stop operation did not complete in the configured timeout");
-   }
-
    @Test(dependsOnMethods = "testGet")
    public void testStart() {
       api().start(vmName);
       assertTrue(stateReached(PowerState.RUNNING), "start operation did not complete in the configured timeout");
    }
 
+   @Test(dependsOnMethods = "testStart")
+   public void testUpdate() {
+      VirtualMachine vm = api().get(vmName);
+      VirtualMachineProperties oldProperties = vm.properties();
+      StorageProfile oldStorageProfile = oldProperties.storageProfile();
+
+      String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
+      VHD vhd = VHD.create(blob + "vhds/" + vmName + "new-data-disk.vhd");
+      DataDisk newDataDisk = DataDisk.create(vmName + "new-data-disk", "1", 1, vhd, "Empty");
+      List<DataDisk> oldDataDisks = oldStorageProfile.dataDisks();
+      assertEquals(oldDataDisks.size(), 1);
+
+      ImmutableList<DataDisk> newDataDisks = ImmutableList.<DataDisk> builder().addAll(oldDataDisks).add(newDataDisk).build();
+      StorageProfile newStorageProfile = oldStorageProfile.toBuilder().dataDisks(newDataDisks).build();
+      VirtualMachineProperties newProperties = oldProperties.toBuilder().storageProfile(newStorageProfile).build();
+
+      VirtualMachine newVm = vm.toBuilder().properties(newProperties).build();
+      vm = api().createOrUpdate(vmName, newVm.location(), newVm.properties(), newVm.tags(), newVm.plan());
+
+      assertEquals(vm.properties().storageProfile().dataDisks().size(), oldDataDisks.size() + 1);
+   }
+
+   @Test(dependsOnMethods = "testUpdate")
+   public void testStop() {
+      api().stop(vmName);
+      assertTrue(stateReached(PowerState.STOPPED), "stop operation did not complete in the configured timeout");
+   }
+
    @Test(dependsOnMethods = "testStop")
    public void testRestart() {
       api().start(vmName);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/894be791/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
index 65bdeb3..0c03fb1 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
@@ -115,7 +115,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       Plan plan = Plan.create("thinkboxsoftware", "deadline-slave-7-2", "deadline7-2");
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
       VirtualMachine vm = vmAPI
-            .create("windowsmachine", "westus", getProperties(), ImmutableMap.of("foo", "bar"), plan);
+            .createOrUpdate("windowsmachine", "westus", getProperties(), ImmutableMap.of("foo", "bar"), plan);
       assertEquals(vm, getVM(plan));
       assertSent(
             server,
@@ -138,7 +138,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       server.enqueue(jsonResponse("/createvirtualmachineresponse.json"));
 
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
-      VirtualMachine vm = vmAPI.create("windowsmachine", "westus", getProperties(), ImmutableMap.of("foo", "bar"), null);
+      VirtualMachine vm = vmAPI.createOrUpdate("windowsmachine", "westus", getProperties(), ImmutableMap.of("foo", "bar"), null);
       assertEquals(vm, getVM());
       assertSent(
             server,


[10/50] [abbrv] jclouds git commit: JCLOUDS-1273/JCLOUDS-1226: Support multiple resource groups in ARM

Posted by na...@apache.org.
JCLOUDS-1273/JCLOUDS-1226: Support multiple resource groups in ARM


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

Branch: refs/heads/master
Commit: 83c0a3c7b255ec744c6150ce76c40e8301280c79
Parents: cc13cfe
Author: Ignasi Barrera <na...@apache.org>
Authored: Mon Apr 24 14:49:57 2017 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Apr 26 00:12:53 2017 +0200

----------------------------------------------------------------------
 .../azurecompute/arm/AzureComputeApi.java       |   8 +-
 .../arm/compute/AzureComputeService.java        |  15 +-
 .../arm/compute/AzureComputeServiceAdapter.java |  88 ++++----
 .../AzureComputeServiceContextModule.java       |  18 +-
 .../arm/compute/domain/LocationAndName.java     |  50 +++++
 .../domain/RegionAndIdAndIngressRules.java      |  66 ------
 .../compute/domain/ResourceGroupAndName.java    |  50 +++++
 .../ResourceGroupAndNameAndIngressRules.java    |  71 +++++++
 .../extensions/AzureComputeImageExtension.java  |  39 ++--
 .../AzureComputeSecurityGroupExtension.java     | 100 +++++-----
 .../compute/functions/CustomImageToVMImage.java |   4 +-
 .../NetworkSecurityGroupToSecurityGroup.java    |   7 +-
 .../functions/TemplateToAvailabilitySet.java    |   8 +-
 .../compute/functions/VMHardwareToHardware.java |  20 +-
 .../arm/compute/functions/VMImageToImage.java   |  25 ++-
 .../functions/VirtualMachineToNodeMetadata.java |  50 ++---
 .../functions/VirtualMachineToStatus.java       |  11 +-
 .../loaders/CreateSecurityGroupIfNeeded.java    |  15 +-
 .../compute/loaders/DefaultResourceGroup.java   |  62 ++++++
 .../loaders/ResourceGroupForLocation.java       |  62 ------
 .../compute/options/AzureTemplateOptions.java   |  78 ++++----
 .../arm/compute/strategy/CleanupResources.java  |  79 +++-----
 .../CreateResourceGroupThenCreateNodes.java     | 193 ------------------
 .../CreateResourcesThenCreateNodes.java         | 199 +++++++++++++++++++
 .../azurecompute/arm/domain/IdReference.java    |  39 +++-
 .../azurecompute/arm/domain/RegionAndId.java    |  50 -----
 .../azurecompute/arm/domain/VMHardware.java     |  11 +-
 .../azurecompute/arm/domain/VMImage.java        |   8 +
 .../azurecompute/arm/features/JobApi.java       |   2 +-
 .../jclouds/azurecompute/arm/util/VMImages.java |   2 +-
 .../compute/AzureComputeServiceLiveTest.java    |  29 +--
 .../compute/AzureTemplateBuilderLiveTest.java   |   2 +-
 .../AzureComputeImageExtensionLiveTest.java     |  24 +--
 ...reComputeSecurityGroupExtensionLiveTest.java |  40 ++--
 .../arm/domain/IdReferenceTest.java             |  62 ++++++
 .../arm/features/ImageApiLiveTest.java          |  30 +--
 .../arm/features/LoadBalancerApiLiveTest.java   |  50 ++---
 .../arm/internal/AzureLiveTestUtils.java        |  10 +-
 .../internal/BaseAzureComputeApiLiveTest.java   |   2 +-
 39 files changed, 884 insertions(+), 795 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index 70814868..a25690f 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -17,15 +17,16 @@
 package org.jclouds.azurecompute.arm;
 
 import java.io.Closeable;
+
 import javax.ws.rs.PathParam;
 
 import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
 import org.jclouds.azurecompute.arm.features.DeploymentApi;
+import org.jclouds.azurecompute.arm.features.DiskApi;
 import org.jclouds.azurecompute.arm.features.ImageApi;
 import org.jclouds.azurecompute.arm.features.JobApi;
 import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
 import org.jclouds.azurecompute.arm.features.LocationApi;
-import org.jclouds.azurecompute.arm.features.DiskApi;
 import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
@@ -47,7 +48,7 @@ import org.jclouds.rest.annotations.Delegate;
  * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn790568.aspx" >doc</a>
  */
 public interface AzureComputeApi extends Closeable {
-
+   
    /**
     * The Azure Resource Manager API includes operations for managing resource groups in your subscription.
     *
@@ -56,6 +57,9 @@ public interface AzureComputeApi extends Closeable {
    @Delegate
    ResourceGroupApi getResourceGroupApi();
 
+   /**
+    * Provides access to the Job tracking API.
+    */
    @Delegate
    JobApi getJobApi();
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
index f566a69..dcb9c44 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
@@ -31,8 +31,8 @@ import javax.inject.Provider;
 import javax.inject.Singleton;
 
 import org.jclouds.Constants;
+import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.collect.Memoized;
 import org.jclouds.compute.ComputeServiceContext;
 import org.jclouds.compute.callables.RunScriptOnNode;
@@ -62,7 +62,6 @@ import org.jclouds.scriptbuilder.functions.InitAdminAccess;
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.base.Supplier;
-import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.ListeningExecutorService;
@@ -70,7 +69,6 @@ import com.google.common.util.concurrent.ListeningExecutorService;
 @Singleton
 public class AzureComputeService extends BaseComputeService {
    private final CleanupResources cleanupResources;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
 
    @Inject
    protected AzureComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@@ -89,14 +87,13 @@ public class AzureComputeService extends BaseComputeService {
          PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
          @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
          CleanupResources cleanupResources, Optional<ImageExtension> imageExtension,
-         Optional<SecurityGroupExtension> securityGroupExtension, LoadingCache<String, ResourceGroup> resourceGroupMap) {
+         Optional<SecurityGroupExtension> securityGroupExtension) {
       super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
             getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
             startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
             nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
             persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
       this.cleanupResources = cleanupResources;
-      this.resourceGroupMap = resourceGroupMap;
    }
 
    @Override
@@ -105,11 +102,11 @@ public class AzureComputeService extends BaseComputeService {
       ImmutableSet.Builder<String> resourceGroups = ImmutableSet.builder();
 
       for (NodeMetadata deadNode : deadNodes) {
-         ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(deadNode.getLocation().getId());
-
-         resourceGroups.add(resourceGroup.name());
+         String resourceGroupName = ResourceGroupAndName.fromSlashEncoded(deadNode.getId()).resourceGroup();
+         resourceGroups.add(resourceGroupName);
+         
          if (deadNode.getGroup() != null) {
-            regionGroups.put(resourceGroup.name(), deadNode.getGroup());
+            regionGroups.put(resourceGroupName, deadNode.getGroup());
          }
 
          try {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 8f9b67c..2e9e0f6 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -19,10 +19,12 @@ package org.jclouds.azurecompute.arm.compute;
 import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.ImmutableList.builder;
 import static com.google.common.collect.ImmutableList.of;
-import static com.google.common.collect.Iterables.contains;
 import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Lists.newArrayList;
+import static org.jclouds.azurecompute.arm.compute.domain.LocationAndName.fromSlashEncoded;
+import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
 import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
 import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
@@ -40,6 +42,7 @@ import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources;
@@ -62,7 +65,6 @@ import org.jclouds.azurecompute.arm.domain.Offer;
 import org.jclouds.azurecompute.arm.domain.Plan;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
-import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
 import org.jclouds.azurecompute.arm.domain.SKU;
@@ -90,7 +92,6 @@ import com.google.common.base.Objects;
 import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
 import com.google.common.base.Supplier;
-import com.google.common.cache.LoadingCache;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -115,20 +116,18 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    private final List<String> imagePublishers;
    private final Supplier<Set<String>> regionIds;
    private final PublicIpAvailablePredicateFactory publicIpAvailable;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
    private final CustomImageToVMImage customImagetoVmImage;
 
    @Inject
    AzureComputeServiceAdapter(final AzureComputeApi api, @Named(IMAGE_PUBLISHERS) String imagePublishers,
          CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
-         PublicIpAvailablePredicateFactory publicIpAvailable, LoadingCache<String, ResourceGroup> resourceGroupMap,
+         PublicIpAvailablePredicateFactory publicIpAvailable,
          CustomImageToVMImage customImagetoVmImage) {
       this.api = api;
       this.imagePublishers = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(imagePublishers);
       this.cleanupResources = cleanupResources;
       this.regionIds = regionIds;
       this.publicIpAvailable = publicIpAvailable;
-      this.resourceGroupMap = resourceGroupMap;
       this.customImagetoVmImage = customImagetoVmImage;
    }
 
@@ -138,15 +137,15 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
 
       String locationName = template.getLocation().getId();
       Image image = template.getImage();
-      String hardwareId = template.getHardware().getId();
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(locationName);
+      String hardwareId = fromSlashEncoded(template.getHardware().getId()).name();
       // TODO ARM specific options
       AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class);
       String subnetId = templateOptions.getSubnetId();
+      String resourceGroupName = templateOptions.getResourceGroup();
       
       IdReference availabilitySet = getAvailabilitySetIdReference(templateOptions.getAvailabilitySet());
       StorageProfile storageProfile = createStorageProfile(image, templateOptions.getDataDisks());
-      NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName, resourceGroup.name(), template.getOptions());
+      NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName, resourceGroupName, template.getOptions());
       HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(hardwareId).build();
       OSProfile osProfile = createOsProfile(name, template);
       NetworkProfile networkProfile = NetworkProfile.builder().networkInterfaces(of(IdReference.create(nic.id()))).build();
@@ -165,14 +164,14 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       Map<String, String> metadataAndTags = metadataAndTagsAsCommaDelimitedValue(template.getOptions());
       Plan plan = getMarketplacePlanFromImageMetadata(template.getImage());
 
-      VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroup.name()).createOrUpdate(name, template.getLocation().getId(),
+      VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).createOrUpdate(name, template.getLocation().getId(),
             virtualMachineProperties, metadataAndTags, plan);
 
       // Safe to pass null credentials here, as jclouds will default populate
       // the node with the default credentials from the image, or the ones in
       // the options, if provided.
-      RegionAndId regionAndId = RegionAndId.fromRegionAndId(locationName, name);
-      return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, regionAndId.slashEncode(), null);
+      ResourceGroupAndName resourceGroupAndName = fromResourceGroupAndName(resourceGroupName, name);
+      return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, resourceGroupAndName.slashEncode(), null);
    }
 
    @Override
@@ -183,8 +182,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
          for (VMSize vmSize : vmSizes) {
             VMHardware hwProfile = VMHardware
                     .create(vmSize.name(), vmSize.numberOfCores(), vmSize.osDiskSizeInMB(),
-                            vmSize.resourceDiskSizeInMB(), vmSize.memoryInMB(), vmSize.maxDataDiskCount(), location.name(),
-                            false);
+                            vmSize.resourceDiskSizeInMB(), vmSize.memoryInMB(), vmSize.maxDataDiskCount(), location.name());
             hwProfiles.add(hwProfile);
          }
       }
@@ -221,9 +219,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       return osImages;
    }
    
-   private List<VMImage> listCustomImagesByLocation(String location) {
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location);
-      List<org.jclouds.azurecompute.arm.domain.Image> customImages = api.getVirtualMachineImageApi(resourceGroup.name()).list();
+   private List<VMImage> listCustomImagesByResourceGroup(String resourceGroup) {
+      List<org.jclouds.azurecompute.arm.domain.Image> customImages = api.getVirtualMachineImageApi(resourceGroup).list();
       return Lists.transform(customImages, customImagetoVmImage);
    }
 
@@ -231,16 +228,29 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    public Iterable<VMImage> listImages() {
       final ImmutableList.Builder<VMImage> osImages = ImmutableList.builder();
       
-      Iterable<String> availableLocationNames = transform(listLocations(), new Function<Location, String>() {
-         @Override
-         public String apply(Location location) {
-            return location.name();
-         }
-      });
+      final List<String> availableLocationNames = newArrayList(transform(listLocations(),
+            new Function<Location, String>() {
+               @Override
+               public String apply(Location location) {
+                  return location.name();
+               }
+            }));
 
       for (String locationName : availableLocationNames) {
          osImages.addAll(listImagesByLocation(locationName));
-         osImages.addAll(listCustomImagesByLocation(locationName));
+      }
+
+      // We need to look for custom images in all resource groups
+      Iterable<ResourceGroup> resourceGroupsInLocation = filter(api.getResourceGroupApi().list(),
+            new Predicate<ResourceGroup>() {
+               @Override
+               public boolean apply(ResourceGroup input) {
+                  return availableLocationNames.contains(input.location());
+               }
+            });
+      
+      for (ResourceGroup resourceGroup : resourceGroupsInLocation) {
+         osImages.addAll(listCustomImagesByResourceGroup(resourceGroup.name()));
       }
 
       return osImages.build();
@@ -249,10 +259,10 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    @Override
    public VMImage getImage(final String id) {
       VMImage image = decodeFieldsFromUniqueId(id);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(image.location());
 
       if (image.custom()) {
-         org.jclouds.azurecompute.arm.domain.Image vmImage = api.getVirtualMachineImageApi(resourceGroup.name()).get(image.name());
+         org.jclouds.azurecompute.arm.domain.Image vmImage = api.getVirtualMachineImageApi(image.resourceGroup()).get(
+               image.name());
          return vmImage == null ? null : customImagetoVmImage.apply(vmImage);
       }
 
@@ -304,9 +314,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
 
    @Override
    public VirtualMachine getNode(final String id) {
-      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
-      return api.getVirtualMachineApi(resourceGroup.name()).get(regionAndId.id());
+      ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
+      return api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).get(resourceGroupAndName.name());
    }
 
    @Override
@@ -316,23 +325,20 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
 
    @Override
    public void rebootNode(final String id) {
-      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
-      api.getVirtualMachineApi(resourceGroup.name()).restart(regionAndId.id());
+      ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
+      api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).restart(resourceGroupAndName.name());
    }
 
    @Override
    public void resumeNode(final String id) {
-      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
-      api.getVirtualMachineApi(resourceGroup.name()).start(regionAndId.id());
+      ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
+      api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).start(resourceGroupAndName.name());
    }
 
    @Override
    public void suspendNode(final String id) {
-      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
-      api.getVirtualMachineApi(resourceGroup.name()).stop(regionAndId.id());
+      ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
+      api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).stop(resourceGroupAndName.name());
    }
 
    @Override
@@ -346,10 +352,10 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
 
    @Override
    public Iterable<VirtualMachine> listNodesByIds(final Iterable<String> ids) {
-      return filter(listNodes(), new Predicate<VirtualMachine>() {
+      return transform(ids, new Function<String, VirtualMachine>() {
          @Override
-         public boolean apply(VirtualMachine virtualMachine) {
-            return contains(ids, virtualMachine.id());
+         public VirtualMachine apply(String input) {
+            return getNode(input);
          }
       });
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
index cf3c90c..11d3ab1 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
@@ -34,7 +34,7 @@ import javax.inject.Singleton;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.AzureComputeService;
 import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter;
-import org.jclouds.azurecompute.arm.compute.domain.RegionAndIdAndIngressRules;
+import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
 import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
 import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeSecurityGroupExtension;
 import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation;
@@ -44,9 +44,9 @@ import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware;
 import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
 import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata;
 import org.jclouds.azurecompute.arm.compute.loaders.CreateSecurityGroupIfNeeded;
-import org.jclouds.azurecompute.arm.compute.loaders.ResourceGroupForLocation;
+import org.jclouds.azurecompute.arm.compute.loaders.DefaultResourceGroup;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
-import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes;
+import org.jclouds.azurecompute.arm.compute.strategy.CreateResourcesThenCreateNodes;
 import org.jclouds.azurecompute.arm.domain.Image;
 import org.jclouds.azurecompute.arm.domain.Location;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
@@ -116,12 +116,12 @@ public class AzureComputeServiceContextModule extends
 
       bind(TemplateOptions.class).to(AzureTemplateOptions.class);
       bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class);
-      bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class);
+      bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourcesThenCreateNodes.class);
 
-      bind(new TypeLiteral<CacheLoader<RegionAndIdAndIngressRules, String>>() {
+      bind(new TypeLiteral<CacheLoader<ResourceGroupAndNameAndIngressRules, String>>() {
       }).to(CreateSecurityGroupIfNeeded.class);
       bind(new TypeLiteral<CacheLoader<String, ResourceGroup>>() {
-      }).to(ResourceGroupForLocation.class);
+      }).to(DefaultResourceGroup.class);
 
       bind(new TypeLiteral<ImageExtension>() {
       }).to(AzureComputeImageExtension.class);
@@ -131,14 +131,14 @@ public class AzureComputeServiceContextModule extends
 
    @Provides
    @Singleton
-   protected final LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap(
-         CacheLoader<RegionAndIdAndIngressRules, String> in) {
+   protected final LoadingCache<ResourceGroupAndNameAndIngressRules, String> securityGroupMap(
+         CacheLoader<ResourceGroupAndNameAndIngressRules, String> in) {
       return CacheBuilder.newBuilder().build(in);
    }
 
    @Provides
    @Singleton
-   protected final LoadingCache<String, ResourceGroup> resourceGroupMap(CacheLoader<String, ResourceGroup> in) {
+   protected final LoadingCache<String, ResourceGroup> defaultResourceGroup(CacheLoader<String, ResourceGroup> in) {
       return CacheBuilder.newBuilder().build(in);
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/LocationAndName.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/LocationAndName.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/LocationAndName.java
new file mode 100644
index 0000000..0142448
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/LocationAndName.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.compute.domain;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+
+@AutoValue
+public abstract class LocationAndName {
+
+   public abstract String location();
+   public abstract String name();
+   
+   protected LocationAndName() {
+      
+   }
+   
+   public static LocationAndName fromSlashEncoded(String id) {
+      Iterable<String> parts = Splitter.on('/').split(checkNotNull(id, "id"));
+      checkArgument(Iterables.size(parts) == 2, "id must be in format location/name");
+      return new AutoValue_LocationAndName(Iterables.get(parts, 0), Iterables.get(parts, 1));
+   }
+
+   public static LocationAndName fromLocationAndName(String location, String name) {
+      return new AutoValue_LocationAndName(location, name);
+   }
+
+   public String slashEncode() {
+      return location() + "/" + name();
+   }
+   
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/RegionAndIdAndIngressRules.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/RegionAndIdAndIngressRules.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/RegionAndIdAndIngressRules.java
deleted file mode 100644
index fa9730d..0000000
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/RegionAndIdAndIngressRules.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azurecompute.arm.compute.domain;
-
-import org.jclouds.azurecompute.arm.domain.RegionAndId;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Objects;
-
-@AutoValue
-public abstract class RegionAndIdAndIngressRules {
-
-   abstract RegionAndId regionAndId(); // Intentionally hidden
-   public abstract int[] inboundPorts();
-
-   RegionAndIdAndIngressRules() {
-
-   }
-
-   public static RegionAndIdAndIngressRules create(String region, String id, int[] inboundPorts) {
-      return new AutoValue_RegionAndIdAndIngressRules(RegionAndId.fromRegionAndId(region, id), inboundPorts);
-   }
-
-   public String id() {
-      return regionAndId().id();
-   }
-
-   public String region() {
-      return regionAndId().region();
-   }
-
-   // Intentionally delegate equals and hashcode to the fields in the parent
-   // class so that we can search only by region/id in a map
-
-   @Override
-   public int hashCode() {
-      return Objects.hashCode(region(), id());
-   }
-
-   @Override
-   public boolean equals(Object obj) {
-      if (obj == this) {
-         return true;
-      }
-      if (!(obj instanceof RegionAndId)) {
-         return false;
-      }
-      RegionAndId that = (RegionAndId) obj;
-      return Objects.equal(region(), that.region()) && Objects.equal(id(), that.id());
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndName.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndName.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndName.java
new file mode 100644
index 0000000..c06056e
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndName.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.compute.domain;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+
+@AutoValue
+public abstract class ResourceGroupAndName {
+
+   public abstract String resourceGroup();
+   public abstract String name();
+   
+   protected ResourceGroupAndName() {
+      
+   }
+   
+   public static ResourceGroupAndName fromSlashEncoded(String id) {
+      Iterable<String> parts = Splitter.on('/').split(checkNotNull(id, "id"));
+      checkArgument(Iterables.size(parts) == 2, "id must be in format resourcegroup/name");
+      return new AutoValue_ResourceGroupAndName(Iterables.get(parts, 0), Iterables.get(parts, 1));
+   }
+
+   public static ResourceGroupAndName fromResourceGroupAndName(String resourceGroup, String name) {
+      return new AutoValue_ResourceGroupAndName(resourceGroup, name);
+   }
+
+   public String slashEncode() {
+      return resourceGroup() + "/" + name();
+   }
+   
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java
new file mode 100644
index 0000000..2b07406
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.compute.domain;
+
+import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Objects;
+
+@AutoValue
+public abstract class ResourceGroupAndNameAndIngressRules {
+
+   abstract ResourceGroupAndName resourceGroupAndName(); // Intentionally hidden
+   
+   public abstract String location();
+
+   public abstract int[] inboundPorts();
+
+   ResourceGroupAndNameAndIngressRules() {
+
+   }
+
+   public static ResourceGroupAndNameAndIngressRules create(String resourceGroup, String location, String name,
+         int[] inboundPorts) {
+      return new AutoValue_ResourceGroupAndNameAndIngressRules(fromResourceGroupAndName(resourceGroup, name), location,
+            inboundPorts);
+   }
+
+   public String name() {
+      return resourceGroupAndName().name();
+   }
+
+   public String resourceGroup() {
+      return resourceGroupAndName().resourceGroup();
+   }
+
+   // Intentionally delegate equals and hashcode to the fields in the parent
+   // class so that we can search only by region/id in a map
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(resourceGroup(), name());
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (obj == this) {
+         return true;
+      }
+      if (!(obj instanceof ResourceGroupAndName)) {
+         return false;
+      }
+      ResourceGroupAndName that = (ResourceGroupAndName) obj;
+      return Objects.equal(resourceGroup(), that.resourceGroup()) && Objects.equal(name(), that.name());
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
index 4bfa449..7d654d5 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
@@ -19,6 +19,7 @@ package org.jclouds.azurecompute.arm.compute.extensions;
 import static com.google.common.base.Functions.compose;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
+import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromSlashEncoded;
 import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
@@ -32,11 +33,10 @@ import org.jclouds.Constants;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.ImageAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.VirtualMachineInStatePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.ImageProperties;
-import org.jclouds.azurecompute.arm.domain.RegionAndId;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.compute.domain.CloneImageTemplate;
@@ -49,7 +49,6 @@ import org.jclouds.logging.Logger;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
-import com.google.common.cache.LoadingCache;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.inject.Inject;
@@ -66,25 +65,21 @@ public class AzureComputeImageExtension implements ImageExtension {
    private final ListeningExecutorService userExecutor;
    private final ImageAvailablePredicateFactory imageAvailablePredicate;
    private final VirtualMachineInStatePredicateFactory nodeSuspendedPredicate;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
    private final Function<VMImage, Image> vmImageToImage;
    private final Predicate<URI> resourceDeleted;
    private final CustomImageToVMImage customImagetoVmImage;
 
    @Inject
-   AzureComputeImageExtension(AzureComputeApi api,
-         ImageAvailablePredicateFactory imageAvailablePredicate,
+   AzureComputeImageExtension(AzureComputeApi api, ImageAvailablePredicateFactory imageAvailablePredicate,
          @Named(TIMEOUT_NODE_SUSPENDED) VirtualMachineInStatePredicateFactory nodeSuspendedPredicate,
          @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
-         Function<VMImage, Image> vmImageToImage, LoadingCache<String, ResourceGroup> resourceGroupMap,
-         @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
+         Function<VMImage, Image> vmImageToImage, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
          CustomImageToVMImage customImagetoVmImage) {
       this.api = api;
       this.imageAvailablePredicate = imageAvailablePredicate;
       this.nodeSuspendedPredicate = nodeSuspendedPredicate;
       this.userExecutor = userExecutor;
       this.vmImageToImage = vmImageToImage;
-      this.resourceGroupMap = resourceGroupMap;
       this.resourceDeleted = resourceDeleted;
       this.customImagetoVmImage = customImagetoVmImage;
    }
@@ -97,27 +92,27 @@ public class AzureComputeImageExtension implements ImageExtension {
    @Override
    public ListenableFuture<Image> createImage(ImageTemplate template) {
       final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
-      final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId());
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
-      final String resourceGroupName = resourceGroup.name();
+      final ResourceGroupAndName resourceGroupAndName = fromSlashEncoded(cloneTemplate.getSourceNodeId());
+      final String resourceGroupName = resourceGroupAndName.resourceGroup();
+      final String vmName = resourceGroupAndName.name();
 
-      final VirtualMachine vm = api.getVirtualMachineApi(resourceGroupName).get(regionAndId.id());
+      final VirtualMachine vm = api.getVirtualMachineApi(resourceGroupName).get(vmName);
       final IdReference vmIdRef = IdReference.create(vm.id());
 
-      logger.debug(">> stopping node %s...", regionAndId.slashEncode());
-      api.getVirtualMachineApi(resourceGroupName).stop(regionAndId.id());
-      checkState(nodeSuspendedPredicate.create(resourceGroupName).apply(regionAndId.id()),
-            "Node %s was not suspended within the configured time limit", regionAndId.slashEncode());
+      logger.debug(">> stopping node %s...", cloneTemplate.getSourceNodeId());
+      api.getVirtualMachineApi(resourceGroupName).stop(vmName);
+      checkState(nodeSuspendedPredicate.create(resourceGroupName).apply(vmName),
+            "Node %s was not suspended within the configured time limit", cloneTemplate.getSourceNodeId());
 
       return userExecutor.submit(new Callable<Image>() {
          @Override
          public Image call() throws Exception {
-            logger.debug(">> generalizing virtal machine %s...", regionAndId.id());
+            logger.debug(">> generalizing virtal machine %s...", vmName);
 
-            api.getVirtualMachineApi(resourceGroupName).generalize(regionAndId.id());
+            api.getVirtualMachineApi(resourceGroupName).generalize(vmName);
 
             org.jclouds.azurecompute.arm.domain.Image imageFromVM = api.getVirtualMachineImageApi(resourceGroupName)
-                  .createOrUpdate(cloneTemplate.getName(), regionAndId.region(),
+                  .createOrUpdate(cloneTemplate.getName(), vm.location(),
                         ImageProperties.builder().sourceVirtualMachine(vmIdRef).build());
 
             checkState(imageAvailablePredicate.create(resourceGroupName).apply(imageFromVM.name()),
@@ -134,9 +129,7 @@ public class AzureComputeImageExtension implements ImageExtension {
       checkArgument(image.custom(), "Only custom images can be deleted");
 
       logger.debug(">> deleting image %s", id);
-
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(image.location());
-      URI uri = api.getVirtualMachineImageApi(resourceGroup.name()).delete(image.name());
+      URI uri = api.getVirtualMachineImageApi(image.resourceGroup()).delete(image.name());
       return resourceDeleted.apply(uri);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
index f23cfd8..eafb4f1 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
@@ -20,10 +20,10 @@ import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.base.Predicates.equalTo;
 import static com.google.common.base.Predicates.notNull;
 import static com.google.common.collect.Iterables.any;
-import static com.google.common.collect.Iterables.concat;
 import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.transform;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.compute.predicates.NodePredicates.locationId;
 
 import java.net.URI;
 import java.util.ArrayList;
@@ -36,6 +36,7 @@ import javax.inject.Named;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.SecurityGroupAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
@@ -45,12 +46,10 @@ import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Access;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Direction;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Protocol;
-import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
-import org.jclouds.collect.Memoized;
 import org.jclouds.compute.domain.SecurityGroup;
 import org.jclouds.compute.domain.SecurityGroupBuilder;
 import org.jclouds.compute.extensions.SecurityGroupExtension;
@@ -63,11 +62,8 @@ import org.jclouds.net.domain.IpProtocol;
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
 import com.google.common.base.Predicate;
-import com.google.common.base.Splitter;
-import com.google.common.base.Supplier;
 import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Ordering;
 
@@ -78,64 +74,67 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
 
    private final AzureComputeApi api;
    private final Function<NetworkSecurityGroup, SecurityGroup> securityGroupConverter;
-   private final Supplier<Set<? extends Location>> locations;
    private final SecurityGroupAvailablePredicateFactory securityGroupAvailable;
    private final Predicate<URI> resourceDeleted;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private final LoadingCache<String, ResourceGroup> defaultResourceGroup;
 
    @Inject
-   AzureComputeSecurityGroupExtension(AzureComputeApi api, @Memoized Supplier<Set<? extends Location>> locations,
+   AzureComputeSecurityGroupExtension(AzureComputeApi api,
          Function<NetworkSecurityGroup, SecurityGroup> groupConverter,
          SecurityGroupAvailablePredicateFactory securityRuleAvailable,
          @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
-         LoadingCache<String, ResourceGroup> resourceGroupMap) {
+         LoadingCache<String, ResourceGroup> defaultResourceGroup) {
       this.api = api;
-      this.locations = locations;
       this.securityGroupConverter = groupConverter;
       this.securityGroupAvailable = securityRuleAvailable;
       this.resourceDeleted = resourceDeleted;
-      this.resourceGroupMap = resourceGroupMap;
+      this.defaultResourceGroup = defaultResourceGroup;
    }
 
    @Override
    public Set<SecurityGroup> listSecurityGroups() {
-      return ImmutableSet.copyOf(concat(transform(locations.get(), new Function<Location, Set<SecurityGroup>>() {
-         @Override
-         public Set<SecurityGroup> apply(Location input) {
-            return listSecurityGroupsInLocation(input);
-         }
-      })));
+      ImmutableSet.Builder<SecurityGroup> securityGroups = ImmutableSet.builder();
+      for (ResourceGroup rg : api.getResourceGroupApi().list()) {
+         securityGroups.addAll(securityGroupsInResourceGroup(rg.name()));
+      }
+      return securityGroups.build();
+   }
+   
+   private Set<SecurityGroup> securityGroupsInResourceGroup(String resourceGroup) {
+      List<NetworkSecurityGroup> networkGroups = api.getNetworkSecurityGroupApi(resourceGroup).list();
+      return ImmutableSet.copyOf(transform(filter(networkGroups, notNull()), securityGroupConverter));
    }
 
    @Override
    public Set<SecurityGroup> listSecurityGroupsInLocation(Location location) {
-      logger.debug(">> getting security groups for %s...", location);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location.getId());
-      List<NetworkSecurityGroup> networkGroups = api.getNetworkSecurityGroupApi(resourceGroup.name()).list();
-      return ImmutableSet.copyOf(transform(filter(networkGroups, notNull()), securityGroupConverter));
+      // Even though the resource groups are in a location, each security group
+      // can be in a different resource group, so we need to inspect all teh
+      // existing resource groups, and filter afterwards
+      return ImmutableSet.copyOf(filter(listSecurityGroups(), locationId(location.getId())));
    }
 
    @Override
    public Set<SecurityGroup> listSecurityGroupsForNode(String nodeId) {
       logger.debug(">> getting security groups for node %s...", nodeId);
 
-      final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(nodeId);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
+      final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(nodeId);
 
-      VirtualMachine vm = api.getVirtualMachineApi(resourceGroup.name()).get(regionAndId.id());
+      VirtualMachine vm = api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).get(
+            resourceGroupAndName.name());
       if (vm == null) {
-         throw new IllegalArgumentException("Node " + regionAndId.id() + " was not found");
+         throw new IllegalArgumentException("Node " + nodeId + " was not found");
       }
       List<IdReference> networkInterfacesIdReferences = vm.properties().networkProfile().networkInterfaces();
       List<NetworkSecurityGroup> networkGroups = new ArrayList<NetworkSecurityGroup>();
 
       for (IdReference networkInterfaceCardIdReference : networkInterfacesIdReferences) {
-         String nicName = Iterables.getLast(Splitter.on("/").split(networkInterfaceCardIdReference.id()));
-         NetworkInterfaceCard card = api.getNetworkInterfaceCardApi(resourceGroup.name()).get(nicName);
+         String nicName = networkInterfaceCardIdReference.name();
+         String nicResourceGroup = networkInterfaceCardIdReference.resourceGroup();
+         NetworkInterfaceCard card = api.getNetworkInterfaceCardApi(nicResourceGroup).get(nicName);
          if (card != null && card.properties().networkSecurityGroup() != null) {
-            String secGroupName = Iterables.getLast(Splitter.on("/").split(
-                  card.properties().networkSecurityGroup().id()));
-            NetworkSecurityGroup group = api.getNetworkSecurityGroupApi(resourceGroup.name()).get(secGroupName);
+            String secGroupName = card.properties().networkSecurityGroup().name();
+            String sgResourceGroup = card.properties().networkSecurityGroup().resourceGroup();
+            NetworkSecurityGroup group = api.getNetworkSecurityGroupApi(sgResourceGroup).get(secGroupName);
             networkGroups.add(group);
          }
       }
@@ -146,15 +145,15 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
    @Override
    public SecurityGroup getSecurityGroupById(String id) {
       logger.debug(">> getting security group %s...", id);
-      final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
-      NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(resourceGroup.name()).get(regionAndId.id());
+      final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
+      NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup()).get(
+            resourceGroupAndName.name());
       return securityGroup == null ? null : securityGroupConverter.apply(securityGroup);
    }
 
    @Override
    public SecurityGroup createSecurityGroup(String name, Location location) {
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location.getId());
+      ResourceGroup resourceGroup = defaultResourceGroup.getUnchecked(location.getId());
 
       logger.debug(">> creating security group %s in %s...", name, location);
 
@@ -170,9 +169,9 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
    public boolean removeSecurityGroup(String id) {
       logger.debug(">> deleting security group %s...", id);
 
-      final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
-      URI uri = api.getNetworkSecurityGroupApi(resourceGroup.name()).delete(regionAndId.id());
+      final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
+      URI uri = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup())
+            .delete(resourceGroupAndName.name());
       return resourceDeleted.apply(uri);
    }
 
@@ -199,17 +198,16 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
 
       // TODO: Support Azure network tags somehow?
 
-      final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(group.getId());
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
+      final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(group.getId());
 
-      NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroup.name());
-      NetworkSecurityGroup networkSecurityGroup = groupApi.get(regionAndId.id());
+      NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup());
+      NetworkSecurityGroup networkSecurityGroup = groupApi.get(resourceGroupAndName.name());
 
       if (networkSecurityGroup == null) {
          throw new IllegalArgumentException("Security group " + group.getName() + " was not found");
       }
 
-      NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroup.name(), networkSecurityGroup.name());
+      NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroupAndName.resourceGroup(), networkSecurityGroup.name());
       int nextPriority = getRuleStartingPriority(networkSecurityGroup);
 
       for (String ipRange : ipRanges) {
@@ -228,7 +226,8 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
 
          ruleApi.createOrUpdate(ruleName, properties);
 
-         checkState(securityGroupAvailable.create(resourceGroup.name()).apply(networkSecurityGroup.name()),
+         checkState(
+               securityGroupAvailable.create(resourceGroupAndName.resourceGroup()).apply(networkSecurityGroup.name()),
                "Security group was not updated in the configured timeout");
       }
 
@@ -244,17 +243,17 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
 
       logger.debug(">> deleting ip permissions matching [%s] from %s...", ruleName, group.getName());
 
-      final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(group.getId());
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
+      final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(group.getId());
 
-      NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroup.name());
-      NetworkSecurityGroup networkSecurityGroup = groupApi.get(regionAndId.id());
+      NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup());
+      NetworkSecurityGroup networkSecurityGroup = groupApi.get(resourceGroupAndName.name());
 
       if (networkSecurityGroup == null) {
          throw new IllegalArgumentException("Security group " + group.getName() + " was not found");
       }
 
-      NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroup.name(), networkSecurityGroup.name());
+      NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroupAndName.resourceGroup(),
+            networkSecurityGroup.name());
       Iterable<NetworkSecurityRule> rules = filter(ruleApi.list(), new Predicate<NetworkSecurityRule>() {
          @Override
          public boolean apply(NetworkSecurityRule input) {
@@ -270,7 +269,8 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
       for (NetworkSecurityRule matchingRule : rules) {
          logger.debug(">> deleting network security rule %s from %s...", matchingRule.name(), group.getName());
          ruleApi.delete(matchingRule.name());
-         checkState(securityGroupAvailable.create(resourceGroup.name()).apply(networkSecurityGroup.name()),
+         checkState(
+               securityGroupAvailable.create(resourceGroupAndName.resourceGroup()).apply(networkSecurityGroup.name()),
                "Security group was not updated in the configured timeout");
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java
index 9cb2188..2220535 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.azurecompute.arm.compute.functions;
 
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
+
 import org.jclouds.azurecompute.arm.domain.Image;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 
@@ -25,7 +27,7 @@ public class CustomImageToVMImage implements Function<Image, VMImage> {
 
    @Override
    public VMImage apply(Image input) {
-      return VMImage.customImage().customImageId(input.id()).location(input.location()).name(input.name())
+      return VMImage.customImage().resourceGroup(extractResourceGroup(input.id())).customImageId(input.id()).location(input.location()).name(input.name())
             .offer(input.properties().storageProfile().osDisk().osType()).build();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityGroupToSecurityGroup.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityGroupToSecurityGroup.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityGroupToSecurityGroup.java
index 65f5b0d..71d51aa 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityGroupToSecurityGroup.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityGroupToSecurityGroup.java
@@ -18,8 +18,10 @@ package org.jclouds.azurecompute.arm.compute.functions;
 
 import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.transform;
+import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
 import static org.jclouds.azurecompute.arm.compute.functions.NetworkSecurityRuleToIpPermission.InboundRule;
 import static org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata.getLocation;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
 
 import java.util.Set;
 
@@ -27,7 +29,6 @@ import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
-import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.collect.Memoized;
 import org.jclouds.compute.domain.SecurityGroup;
 import org.jclouds.compute.domain.SecurityGroupBuilder;
@@ -54,8 +55,8 @@ public class NetworkSecurityGroupToSecurityGroup implements Function<NetworkSecu
    public SecurityGroup apply(NetworkSecurityGroup input) {
       SecurityGroupBuilder builder = new SecurityGroupBuilder();
 
-      builder.id(RegionAndId.fromRegionAndId(input.location(), input.name()).slashEncode());
-      builder.providerId(input.properties().resourceGuid());
+      builder.id(fromResourceGroupAndName(extractResourceGroup(input.id()), input.name()).slashEncode());
+      builder.providerId(input.id());
       builder.name(input.name());
       builder.location(getLocation(locations, input.location()));
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
index 2732b6e..7359ace 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
@@ -29,14 +29,12 @@ import javax.inject.Singleton;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.logging.Logger;
 
 import com.google.common.base.Function;
-import com.google.common.cache.LoadingCache;
 
 @Singleton
 public class TemplateToAvailabilitySet implements Function<Template, AvailabilitySet> {
@@ -46,12 +44,10 @@ public class TemplateToAvailabilitySet implements Function<Template, Availabilit
    protected Logger logger = Logger.NULL;
 
    private final AzureComputeApi api;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
 
    @Inject
-   TemplateToAvailabilitySet(AzureComputeApi api, LoadingCache<String, ResourceGroup> resourceGroupMap) {
+   TemplateToAvailabilitySet(AzureComputeApi api) {
       this.api = api;
-      this.resourceGroupMap = resourceGroupMap;
    }
 
    @Nullable
@@ -62,7 +58,7 @@ public class TemplateToAvailabilitySet implements Function<Template, Availabilit
 
       AvailabilitySet availabilitySet = null;
       String location = input.getLocation().getId();
-      String resourceGroup = resourceGroupMap.getUnchecked(location).name();
+      String resourceGroup = options.getResourceGroup();
 
       if (options.getAvailabilitySetName() != null) {
          availabilitySet = api.getAvailabilitySetApi(resourceGroup).get(options.getAvailabilitySetName());

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMHardwareToHardware.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMHardwareToHardware.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMHardwareToHardware.java
index 5303e25..d877aba 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMHardwareToHardware.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMHardwareToHardware.java
@@ -16,9 +16,10 @@
  */
 package org.jclouds.azurecompute.arm.compute.functions;
 
-import com.google.common.base.Supplier;
-import com.google.common.collect.FluentIterable;
-import com.google.inject.Inject;
+import static org.jclouds.azurecompute.arm.compute.domain.LocationAndName.fromLocationAndName;
+
+import java.util.Set;
+
 import org.jclouds.azurecompute.arm.domain.VMHardware;
 import org.jclouds.collect.Memoized;
 import org.jclouds.compute.domain.Hardware;
@@ -26,14 +27,15 @@ import org.jclouds.compute.domain.HardwareBuilder;
 import org.jclouds.compute.domain.Processor;
 import org.jclouds.compute.domain.Volume;
 import org.jclouds.compute.domain.VolumeBuilder;
+import org.jclouds.domain.Location;
+import org.jclouds.location.predicates.LocationPredicates;
 
 import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import org.jclouds.domain.Location;
-import org.jclouds.location.predicates.LocationPredicates;
-
-import java.util.Set;
+import com.google.inject.Inject;
 
 public class VMHardwareToHardware implements Function<VMHardware, Hardware> {
 
@@ -49,10 +51,10 @@ public class VMHardwareToHardware implements Function<VMHardware, Hardware> {
       final HardwareBuilder builder = new HardwareBuilder()
               .name(from.name())
               .providerId(from.name())
-              .id(from.name())
+              .id(fromLocationAndName(from.location(), from.name()).slashEncode())
               .processors(ImmutableList.of(new Processor(from.numberOfCores(), 2)))
               .ram(from.memoryInMB())
-              .location(from.globallyAvailable() ? null : FluentIterable.from(locations.get())
+              .location(FluentIterable.from(locations.get())
                       .firstMatch(LocationPredicates.idEquals(from.location()))
                       .get());
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
index 4f02100..2a5075c 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
@@ -16,6 +16,12 @@
  */
 package org.jclouds.azurecompute.arm.compute.functions;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.tryFind;
+import static java.util.Arrays.asList;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
+import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
+
 import java.util.Map;
 import java.util.Set;
 
@@ -40,11 +46,6 @@ import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
 import com.google.inject.Inject;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.tryFind;
-import static java.util.Arrays.asList;
-import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
-
 public class VMImageToImage implements Function<VMImage, Image> {
 
    private static final Map<String, OsFamily> OTHER_OS_MAP = ImmutableMap.<String, OsFamily> builder()
@@ -64,8 +65,8 @@ public class VMImageToImage implements Function<VMImage, Image> {
 
    public static String encodeFieldsToUniqueIdCustom(boolean globallyAvailable, String locationName,
          ImageReference imageReference) {
-      return (globallyAvailable ? "global" : locationName) + "/" + imageReference.customImageId()
-            .substring(imageReference.customImageId().lastIndexOf("/") + 1);
+      return extractResourceGroup(imageReference.customImageId()) + "/" + (globallyAvailable ? "global" : locationName)
+            + "/" + imageReference.customImageId().substring(imageReference.customImageId().lastIndexOf("/") + 1);
    }
 
    public static String encodeFieldsToUniqueId(VMImage imageReference) {
@@ -74,7 +75,8 @@ public class VMImageToImage implements Function<VMImage, Image> {
    }
 
    public static String encodeFieldsToUniqueIdCustom(VMImage imageReference) {
-      return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.name();
+      return imageReference.resourceGroup() + "/"
+            + (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.name();
    }
 
    public static VMImage decodeFieldsFromUniqueId(final String id) {
@@ -82,10 +84,11 @@ public class VMImageToImage implements Function<VMImage, Image> {
       String[] fields = checkNotNull(id, "id").split("/");
       if (isCustom(id)) {
          /* id fields indexes
-         0: imageReference.location + "/" +
-         1: imageReference.name
+         0: imageReference.resourceGroup
+         1: imageReference.location + "/" +
+         2: imageReference.name
          */
-         vmImage = VMImage.customImage().location(fields[0]).name(fields[1]).build();
+         vmImage = VMImage.customImage().resourceGroup(fields[0]).location(fields[1]).name(fields[2]).build();
       } else {
          /* id fields indexes
          0: imageReference.location + "/" +

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
index 9bad6e5..bcfd4fe 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
@@ -20,8 +20,11 @@ import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Strings.nullToEmpty;
 import static com.google.common.collect.Iterables.find;
 import static org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.GROUP_KEY;
+import static org.jclouds.azurecompute.arm.compute.domain.LocationAndName.fromLocationAndName;
+import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
 import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
 import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
 import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
 import static org.jclouds.location.predicates.LocationPredicates.idEquals;
 
@@ -34,13 +37,12 @@ import javax.inject.Inject;
 import javax.inject.Named;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.compute.domain.LocationAndName;
 import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToStatus.StatusAndBackendStatus;
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.IpConfiguration;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
-import org.jclouds.azurecompute.arm.domain.RegionAndId;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.collect.Memoized;
@@ -58,10 +60,7 @@ import org.jclouds.logging.Logger;
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
-import com.google.common.base.Splitter;
 import com.google.common.base.Supplier;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
 public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> {
@@ -74,20 +73,18 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
    private final GroupNamingConvention nodeNamingConvention;
    private final Supplier<Set<? extends Location>> locations;
    private final Supplier<Map<String, ? extends Hardware>> hardwares;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
    private final ImageCacheSupplier imageCache;
    private final VirtualMachineToStatus virtualMachineToStatus;
 
    @Inject
    VirtualMachineToNodeMetadata(AzureComputeApi api, GroupNamingConvention.Factory namingConvention,
          Supplier<Map<String, ? extends Hardware>> hardwares, @Memoized Supplier<Set<? extends Location>> locations,
-         Map<String, Credentials> credentialStore, LoadingCache<String, ResourceGroup> resourceGroupMap,
-         @Memoized Supplier<Set<? extends Image>> imageCache, VirtualMachineToStatus virtualMachineToStatus) {
+         Map<String, Credentials> credentialStore, @Memoized Supplier<Set<? extends Image>> imageCache,
+         VirtualMachineToStatus virtualMachineToStatus) {
       this.api = api;
       this.nodeNamingConvention = namingConvention.createWithoutPrefix();
       this.locations = locations;
       this.hardwares = hardwares;
-      this.resourceGroupMap = resourceGroupMap;
       this.virtualMachineToStatus = virtualMachineToStatus;
       checkArgument(imageCache instanceof ImageCacheSupplier,
             "This provider needs an instance of the ImageCacheSupplier");
@@ -96,10 +93,9 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
 
    @Override
    public NodeMetadata apply(VirtualMachine virtualMachine) {
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(virtualMachine.location());
-
       NodeMetadataBuilder builder = new NodeMetadataBuilder();
-      builder.id(RegionAndId.fromRegionAndId(virtualMachine.location(), virtualMachine.name()).slashEncode());
+      builder.id(fromResourceGroupAndName(extractResourceGroup(virtualMachine.id()), virtualMachine.name())
+            .slashEncode());
       builder.providerId(virtualMachine.id());
       builder.name(virtualMachine.name());
       builder.hostname(virtualMachine.name());
@@ -125,8 +121,7 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
       String locationName = virtualMachine.location();
       builder.location(getLocation(locations, locationName));
 
-      Optional<? extends Image> image = findImage(virtualMachine.properties().storageProfile(), locationName,
-            resourceGroup.name());
+      Optional<? extends Image> image = findImage(virtualMachine.properties().storageProfile(), locationName);
       
       if (image.isPresent()) {
          builder.imageId(image.get().getId());
@@ -137,7 +132,8 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
                virtualMachine.id(), virtualMachine.id());
       }
 
-      builder.hardware(getHardware(virtualMachine.properties().hardwareProfile().vmSize()));
+      builder.hardware(getHardware(fromLocationAndName(virtualMachine.location(), virtualMachine.properties()
+            .hardwareProfile().vmSize())));
 
       return builder.build();
    }
@@ -158,12 +154,8 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
       return privateIpAddresses;
    }
 
-   private NetworkInterfaceCard getNetworkInterfaceCard(IdReference networkInterfaceCardIdReference) {
-      Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 2);
-      String resourceGroup = Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 4);
-      String nicName = Iterables.getLast(Splitter.on("/").split(networkInterfaceCardIdReference.id()));
-      return api.getNetworkInterfaceCardApi(resourceGroup).get(nicName);
-
+   private NetworkInterfaceCard getNetworkInterfaceCard(IdReference nic) {
+      return api.getNetworkInterfaceCardApi(nic.resourceGroup()).get(nic.name());
    }
 
    private Iterable<String> getPublicIpAddresses(List<IdReference> idReferences) {
@@ -172,11 +164,11 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
          NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference);
          if (networkInterfaceCard != null && networkInterfaceCard.properties() != null
                && networkInterfaceCard.properties().ipConfigurations() != null) {
-            String resourceGroup = Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 4);
+            String resourceGroup = networkInterfaceCardIdReference.resourceGroup();
             for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) {
                if (ipConfiguration.properties().publicIPAddress() != null) {
-                  String publicIpId = ipConfiguration.properties().publicIPAddress().id();
-                  PublicIPAddress publicIp = api.getPublicIPAddressApi(resourceGroup).get(Iterables.getLast(Splitter.on("/").split(publicIpId)));
+                  IdReference publicIpId = ipConfiguration.properties().publicIPAddress();
+                  PublicIPAddress publicIp = api.getPublicIPAddressApi(resourceGroup).get(publicIpId.name());
                   if (publicIp != null && publicIp.properties().ipAddress() != null) {
                      publicIpAddresses.add(publicIp.properties().ipAddress());
                   }
@@ -191,8 +183,7 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
       return find(locations.get(), idEquals(nullToEmpty(locationName)), null);
    }
 
-   protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName,
-         String azureGroup) {
+   protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName) {
       if (storageProfile.imageReference() != null) {
          // FIXME check this condition
          String imageId = storageProfile.imageReference().customImageId() != null ?
@@ -205,11 +196,12 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
       }
    }
 
-   protected Hardware getHardware(final String vmSize) {
-      return Iterables.find(hardwares.get().values(), new Predicate<Hardware>() {
+   protected Hardware getHardware(final LocationAndName hardwareId) {
+      final String slashEncoded = hardwareId.slashEncode();
+      return find(hardwares.get().values(), new Predicate<Hardware>() {
          @Override
          public boolean apply(Hardware input) {
-            return input.getId().equals(vmSize);
+            return input.getId().equals(slashEncoded);
          }
       });
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToStatus.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToStatus.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToStatus.java
index c0e333e..9669f50 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToStatus.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToStatus.java
@@ -17,13 +17,13 @@
 package org.jclouds.azurecompute.arm.compute.functions;
 
 import static com.google.common.collect.Iterables.transform;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToStatus.StatusAndBackendStatus;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.Status;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
@@ -36,7 +36,6 @@ import com.google.auto.value.AutoValue;
 import com.google.common.base.Function;
 import com.google.common.base.Functions;
 import com.google.common.base.Joiner;
-import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableMap;
 
 @Singleton
@@ -80,17 +79,15 @@ public class VirtualMachineToStatus implements Function<VirtualMachine, StatusAn
          NodeMetadata.Status.UNRECOGNIZED);
 
    private final AzureComputeApi api;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
 
    @Inject
-   VirtualMachineToStatus(AzureComputeApi api, LoadingCache<String, ResourceGroup> resourceGroupMap) {
+   VirtualMachineToStatus(AzureComputeApi api) {
       this.api = api;
-      this.resourceGroupMap = resourceGroupMap;
    }
 
    @Override
    public StatusAndBackendStatus apply(VirtualMachine virtualMachine) {
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(virtualMachine.location());
+      String resourceGroup = extractResourceGroup(virtualMachine.id());
       ProvisioningState provisioningState = virtualMachine.properties().provisioningState();
 
       NodeMetadata.Status status = PROVISIONINGSTATE_TO_NODESTATUS.apply(provisioningState);
@@ -99,7 +96,7 @@ public class VirtualMachineToStatus implements Function<VirtualMachine, StatusAn
       if (ProvisioningState.SUCCEEDED.equals(provisioningState)) {
          // If the provisioning succeeded, we need to query the *real* status of
          // the VM
-         VirtualMachineInstance instanceDetails = api.getVirtualMachineApi(resourceGroup.name()).getInstanceDetails(
+         VirtualMachineInstance instanceDetails = api.getVirtualMachineApi(resourceGroup).getInstanceDetails(
                virtualMachine.name());
          if (instanceDetails != null && instanceDetails.powerState() != null) {
             status = POWERSTATE_TO_NODESTATUS.apply(instanceDetails.powerState());


[21/50] [abbrv] jclouds git commit: Use the date service to parse dates

Posted by na...@apache.org.
Use the date service to parse dates


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

Branch: refs/heads/master
Commit: f086c050f9061fc0de62b3eafcf9df90fdcb9d8c
Parents: b2cc647
Author: Ignasi Barrera <na...@apache.org>
Authored: Wed Jun 28 09:29:52 2017 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Jun 28 09:29:52 2017 +0200

----------------------------------------------------------------------
 .../azurecompute/arm/features/MetricsApiMockTest.java    | 11 ++++-------
 .../arm/internal/BaseAzureComputeApiMockTest.java        |  3 +++
 2 files changed, 7 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/f086c050/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiMockTest.java
index c6e30c1..2001d19 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiMockTest.java
@@ -19,9 +19,7 @@ package org.jclouds.azurecompute.arm.features;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 
-import java.text.ParsePosition;
-import java.text.SimpleDateFormat;
-import java.util.Locale;
+import java.util.Date;
 
 import org.jclouds.azurecompute.arm.domain.Metric;
 import org.jclouds.azurecompute.arm.domain.MetricData;
@@ -41,11 +39,10 @@ public class MetricsApiMockTest extends BaseAzureComputeApiMockTest {
 
    public void testList() throws Exception {
       server.enqueue(jsonResponse("/metrics.json"));
-      final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);
       final MetricsApi metricsApi = api.getMetricsApi(resourceId);
-      assertEquals(metricsApi.list(filter), ImmutableList.of(Metric.create(ImmutableList.of(MetricData
-                .create(dateFormat.parse("2017-06-01T07:14:00", new ParsePosition(0)), null,
-                    Double.valueOf(0.295), null, null, null)),
+      Date timestamp = dateService.iso8601DateOrSecondsDateParse("2017-06-01T11:14:00Z");
+      assertEquals(metricsApi.list(filter), ImmutableList.of(Metric.create(
+            ImmutableList.of(MetricData.create(timestamp, null, Double.valueOf(0.295), null, null, null)),
             "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers"
                   + "/Microsoft.Compute/virtualMachines/myvm/providers/Microsoft.Insights/metrics/Percentage CPU",
             MetricName.create("Percentage CPU", "Percentage CPU"), "Microsoft.Insights/metrics", "Percent")));

http://git-wip-us.apache.org/repos/asf/jclouds/blob/f086c050/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
index dc4ad28..f704e5f 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
@@ -28,6 +28,7 @@ import org.jclouds.ContextBuilder;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
 import org.jclouds.concurrent.config.ExecutorServiceModule;
+import org.jclouds.date.DateService;
 import org.jclouds.rest.ApiContext;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
@@ -52,6 +53,7 @@ public class BaseAzureComputeApiMockTest {
    protected MockWebServer server;
    protected AzureComputeApi api;
    protected ApiContext<AzureComputeApi> context;
+   protected DateService dateService;
 
    // So that we can ignore formatting.
    private final JsonParser parser = new JsonParser();
@@ -68,6 +70,7 @@ public class BaseAzureComputeApiMockTest {
               .overrides(setupProperties())
               .build();
       api = context.getApi();
+      dateService = context.utils().injector().getInstance(DateService.class);
    }
    
    protected Properties setupProperties() {


[06/50] [abbrv] jclouds git commit: Update ImageExtension to work with Managed Disks

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApi.java
index 30456d4..cf5116c 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApi.java
@@ -28,13 +28,13 @@ import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetProperties;
+import org.jclouds.azurecompute.arm.domain.AvailabilitySet.SKU;
 import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.functions.URIParser;
 import org.jclouds.javax.annotation.Nullable;
@@ -65,12 +65,13 @@ public interface AvailabilitySetApi extends Closeable {
    AvailabilitySet get(@PathParam("name") String name);
 
    @Named("availabilityset:createOrUpdate")
+   @MapBinder(BindToJsonPayload.class)
    @Path("/{name}")
    @PUT
-   @MapBinder(BindToJsonPayload.class)
-   @Produces(MediaType.APPLICATION_JSON)
    AvailabilitySet createOrUpdate(@PathParam("name") String name,
-         @PayloadParam("location") String location, @Nullable @PayloadParam("tags") Map<String, String> tags,
+         @Nullable @PayloadParam("sku") SKU sku,
+         @PayloadParam("location") String location,
+         @Nullable @PayloadParam("tags") Map<String, String> tags,
          @PayloadParam("properties") AvailabilitySetProperties properties);
 
    @Named("availabilityset:delete")

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
index 8d446a5..1ff43de 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
@@ -60,11 +60,11 @@ public interface DeploymentApi {
     */
    @Named("deployment:create")
    @Path("/{deploymentname}")
-   @Payload("{properties}")
+   @Payload("{template}")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    Deployment create(@PathParam("deploymentname") String deploymentname,
-                               @PayloadParam("properties") String properties);
+                               @PayloadParam("template") String template);
 
    /**
     * Get Deployment Information returns information about the specified deployment.
@@ -80,11 +80,11 @@ public interface DeploymentApi {
     */
    @Named("deployment:validate")
    @Path("/{deploymentname}/validate")
-   @Payload("{properties}")
+   @Payload("{template}")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    Deployment validate(@PathParam("deploymentname") String deploymentname,
-                                 @PayloadParam("properties") String properties);
+                                 @PayloadParam("template") String template);
 
    /**
     * List all deployments in a resource group

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java
index 0797dbd..10e9ac6 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java
@@ -26,7 +26,6 @@ import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
@@ -38,7 +37,6 @@ import org.jclouds.azurecompute.arm.functions.URIParser;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.MapBinder;
-import org.jclouds.rest.annotations.Payload;
 import org.jclouds.rest.annotations.PayloadParam;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
@@ -58,10 +56,8 @@ public interface DiskApi {
 
    @Named("disk:create_or_update")
    @PUT
-   @Payload("%7B\"location\":\"{location}\",\"properties\":{properties}%7D")
    @MapBinder(BindToJsonPayload.class)
    @Path("/{diskName}")
-   @Produces(MediaType.APPLICATION_JSON)
    Disk createOrUpdate(@PathParam("diskName") String diskName,
                        @PayloadParam("location") String location,
                        @PayloadParam("properties") DiskProperties properties);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java
index c97b0ac..96caa40 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java
@@ -26,7 +26,6 @@ import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
@@ -38,7 +37,6 @@ import org.jclouds.azurecompute.arm.functions.URIParser;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.MapBinder;
-import org.jclouds.rest.annotations.Payload;
 import org.jclouds.rest.annotations.PayloadParam;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
@@ -58,10 +56,8 @@ public interface ImageApi {
 
    @Named("image:create_or_update")
    @PUT
-   @Payload("%7B\"location\":\"{location}\",\"properties\":{properties}%7D")
    @MapBinder(BindToJsonPayload.class)
    @Path("/{imageName}")
-   @Produces(MediaType.APPLICATION_JSON)
    Image createOrUpdate(@PathParam("imageName") String imageName,
                        @PayloadParam("location") String location,
                        @PayloadParam("properties") ImageProperties properties);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
index 3c3bab9..5a01e90 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
@@ -40,7 +40,8 @@ import org.jclouds.rest.annotations.SelectJson;
 
 @RequestFilters(OAuthFilter.class)
 @Consumes(MediaType.APPLICATION_JSON)
-public interface JobApi extends Closeable{
+public interface JobApi extends Closeable {
+   
    @GET
    @ResponseParser(ParseJobStatus.class)
    JobStatus jobStatus(@EndpointParam URI jobURI);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LoadBalancerApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LoadBalancerApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LoadBalancerApi.java
index f0ea900..f9805c0 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LoadBalancerApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LoadBalancerApi.java
@@ -27,7 +27,6 @@ import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
@@ -67,7 +66,6 @@ public interface LoadBalancerApi {
    @Path("/{loadbalancername}")
    @PUT
    @MapBinder(BindToJsonPayload.class)
-   @Produces(MediaType.APPLICATION_JSON)
    LoadBalancer createOrUpdate(@PathParam("loadbalancername") String lbName,
          @PayloadParam("location") String location, @Nullable @PayloadParam("tags") Map<String, String> tags,
          @PayloadParam("properties") LoadBalancerProperties properties);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java
index ba4c2cd..41c0c85 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java
@@ -27,7 +27,6 @@ import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
@@ -68,7 +67,6 @@ public interface NetworkSecurityGroupApi {
    @Path("/{networksecuritygroupname}")
    @PUT
    @MapBinder(BindToJsonPayload.class)
-   @Produces(MediaType.APPLICATION_JSON)
    NetworkSecurityGroup createOrUpdate(@PathParam("networksecuritygroupname") String nsgName,
          @PayloadParam("location") String location, @Nullable @PayloadParam("tags") Map<String, String> tags,
          @PayloadParam("properties") NetworkSecurityGroupProperties properties);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java
index 8def4e3..7404234 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java
@@ -26,7 +26,6 @@ import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
@@ -48,11 +47,11 @@ import org.jclouds.rest.binders.BindToJsonPayload;
 @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface NetworkSecurityRuleApi {
+
    @Named("networksecurityrule:createOrUpdate")
    @Path("/securityRules/{networksecurityrulename}")
    @PUT
    @MapBinder(BindToJsonPayload.class)
-   @Produces(MediaType.APPLICATION_JSON)
    NetworkSecurityRule createOrUpdate(@PathParam("networksecurityrulename") String ruleName,
                                       @PayloadParam("properties") NetworkSecurityRuleProperties properties);
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java
index 2c6a8b3..7c51621 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java
@@ -28,7 +28,6 @@ import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
@@ -67,7 +66,6 @@ public interface ResourceGroupApi extends Closeable{
    @Named("resourcegroup:create")
    @PUT
    @Path("/{name}")
-   @Produces(MediaType.APPLICATION_JSON)
    @MapBinder(BindToJsonPayload.class)
    ResourceGroup create(@PathParam("name") String name, @PayloadParam("location") String location, @Nullable @PayloadParam("tags") Map<String, String> tags);
 
@@ -87,7 +85,6 @@ public interface ResourceGroupApi extends Closeable{
 
    @Named("resourcegroup:update")
    @PATCH
-   @Produces(MediaType.APPLICATION_JSON)
    @Path("/{name}")
    @MapBinder(BindToJsonPayload.class)
    ResourceGroup update(@PathParam("name") String name, @Nullable @PayloadParam("tags") Map<String, String> tags);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java
index a25e2a5..56dd0d4 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java
@@ -16,7 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-
 import java.io.Closeable;
 import java.util.List;
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
index 5d2e06c..0c9399c 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
@@ -79,9 +79,7 @@ public interface StorageAccountApi {
     * PUT
     */
    @Named("storageaccount:create")
-   @Payload("%7B\"location\":\"{location}\",\"tags\":{tags},\"properties\":{properties}%7D")
    @Path("/resourcegroups/{resourceGroup}/providers/Microsoft.Storage/storageAccounts/{storageAccountName}")
-   @Produces(MediaType.APPLICATION_JSON)
    @ResponseParser(URIParser.class)
    @MapBinder(BindToJsonPayload.class)
    @PUT
@@ -120,7 +118,6 @@ public interface StorageAccountApi {
    @Named("storageaccountkey:get")
    @POST
    @Path("/resourcegroups/{resourceGroup}/providers/Microsoft.Storage/storageAccounts/{storageAccountName}/listKeys")
-   @Produces(MediaType.APPLICATION_JSON)
    @Fallback(Fallbacks.NullOnNotFoundOr404.class)
    StorageServiceKeys getKeys(@PathParam("storageAccountName") String storageAccountName);
 
@@ -143,10 +140,8 @@ public interface StorageAccountApi {
     */
    @Named("storageaccount:update")
    @PATCH
-   @Payload("%7B\"tags\":{tags},\"properties\":{properties}%7D")
    @MapBinder(BindToJsonPayload.class)
    @Path("/resourcegroups/{resourceGroup}/providers/Microsoft.Storage/storageAccounts/{storageAccountName}")
-   @Produces(MediaType.APPLICATION_JSON)
    StorageServiceUpdateParams update(
            @PathParam("storageAccountName") String storageAccountName,
            @Nullable @PayloadParam("tags") Map<String, String> tags,

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
index c87390e..39ed860 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
@@ -77,11 +77,9 @@ public interface VirtualMachineApi {
    
    @Named("CreateOrUpdateVirtualMachine")
    @PUT
-   @Payload("%7B\"location\":\"{location}\",\"tags\":{tags},\"properties\":{properties},\"plan\":{plan}%7D")
    @MapBinder(BindToJsonPayload.class)
    @Path("/{vmname}")
    @QueryParams(keys = "validating", values = "false")
-   @Produces(MediaType.APPLICATION_JSON)
    VirtualMachine createOrUpdate(@PathParam("vmname") String vmname,
                                  @PayloadParam("location") String location,
                                  @PayloadParam("properties") VirtualMachineProperties properties,
@@ -130,10 +128,10 @@ public interface VirtualMachineApi {
    @Named("capture")
    @POST
    @Payload("%7B\"vhdPrefix\":\"{vhdPrefix}\",\"destinationContainerName\":\"{destinationContainerName}\",\"overwriteVhds\":\"true\"%7D")
-   @MapBinder(BindToJsonPayload.class)
    @Path("/{name}/capture")
    @ResponseParser(URIParser.class)
    @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   @Produces(MediaType.APPLICATION_JSON)
    URI capture(@PathParam("name") String name,
                @PayloadParam("vhdPrefix") String vhdPrefix,
                @PayloadParam("destinationContainerName") String destinationContainerName);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/StorageProfileToStorageAccountName.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/StorageProfileToStorageAccountName.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/StorageProfileToStorageAccountName.java
deleted file mode 100644
index f624886..0000000
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/StorageProfileToStorageAccountName.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azurecompute.arm.functions;
-
-import java.net.URI;
-
-import org.jclouds.azurecompute.arm.domain.StorageProfile;
-
-import com.google.common.base.Function;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterables;
-
-/**
- * Returns the storage account name for a given storage profile.
- */
-public class StorageProfileToStorageAccountName implements Function<StorageProfile, String> {
-
-   @Override
-   public String apply(StorageProfile input) {
-      String storageAccountNameURI = input.osDisk().vhd().uri();
-      return Iterables.get(Splitter.on(".").split(URI.create(storageAccountNameURI).getHost()), 0);
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
deleted file mode 100644
index b42ea5e..0000000
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azurecompute.arm.util;
-
-import static org.jclouds.util.Closeables2.closeQuietly;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jclouds.ContextBuilder;
-import org.jclouds.azureblob.AzureBlobClient;
-import org.jclouds.azureblob.domain.BlobProperties;
-import org.jclouds.azureblob.domain.ContainerProperties;
-import org.jclouds.azureblob.domain.ListBlobsResponse;
-import org.jclouds.azurecompute.arm.domain.VMImage;
-
-public class BlobHelper implements Closeable {
-
-   private final String storageAccount;
-   private final AzureBlobClient azureBlob;
-
-   public BlobHelper(String storageAccount, String key) {
-      this.storageAccount = storageAccount;
-      this.azureBlob = ContextBuilder.newBuilder("azureblob").credentials(storageAccount, key)
-            .buildApi(AzureBlobClient.class);
-   }
-
-   @Override
-   public void close() throws IOException {
-      closeQuietly(azureBlob);
-   }
-
-   public void deleteContainerIfExists(String containerName) {
-      azureBlob.deleteContainer(containerName);
-   }
-
-   public boolean hasContainers() {
-      return !azureBlob.listContainers().isEmpty();
-   }
-
-   public boolean customImageExists() {
-      return azureBlob.containerExists("system");
-   }
-
-   public List<VMImage> getImages(String containerName, String group, String offer, String location) {
-      List<VMImage> list = new ArrayList<VMImage>();
-
-      ContainerProperties systemContainer = azureBlob.getContainerProperties("system");
-      if (systemContainer != null) {
-         ListBlobsResponse blobList = azureBlob.listBlobs(systemContainer.getName());
-         for (BlobProperties blob : blobList) {
-            String name = blob.getName();
-
-            if (name.contains("-osDisk")) {
-               String imageName = name.substring(name.lastIndexOf('/') + 1, name.indexOf("-osDisk"));
-               String imageUrl = blob.getUrl().toString();
-
-               list.add(VMImage.customImage().group(group).storage(storageAccount).vhd1(imageUrl).name(imageName)
-                     .offer(offer).location(location).build());
-            }
-         }
-      }
-
-      return list;
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
index d5b6394..a5944ec 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
@@ -21,7 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 public class VMImages {
 
    public static boolean isCustom(String imageId) {
-      return checkNotNull(imageId, "id").split("/").length == 5;
+      return checkNotNull(imageId, "id").split("/").length == 2;
    }
   
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
index 9c2427c..7c5c97f 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
@@ -16,8 +16,11 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
+import static org.testng.Assert.assertTrue;
 
+import java.net.URI;
 import java.util.Properties;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
@@ -38,10 +41,12 @@ import org.jclouds.sshj.config.SshjSshClientModule;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Predicate;
 import com.google.common.cache.LoadingCache;
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
 
 /**
  * Live tests for the {@link org.jclouds.compute.ComputeService} integration.
@@ -50,6 +55,7 @@ import com.google.inject.TypeLiteral;
 public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
    
    private LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private Predicate<URI> resourceDeleted;
 
    public AzureComputeServiceLiveTest() {
       provider = "azurecompute-arm";
@@ -61,6 +67,8 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
       resourceGroupMap = context.utils().injector()
             .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
             }));
+      resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
+      }, Names.named(TIMEOUT_RESOURCE_DELETED)));
    }
 
    @Override
@@ -71,7 +79,11 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
             ResourceGroup rg = resourceGroupMap.getIfPresent(template.getLocation().getId());
             if (rg != null) {
                AzureComputeApi api = view.unwrapApi(AzureComputeApi.class);
-               api.getResourceGroupApi().delete(rg.name());
+               URI uri = api.getResourceGroupApi().delete(rg.name());
+               if (uri != null) {
+                  assertTrue(resourceDeleted.apply(uri),
+                        String.format("Resource %s was not terminated in the configured timeout", uri));
+               }
             }
          }
       } finally {
@@ -97,7 +109,7 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
index 56200c4..d4cbdb0 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
@@ -56,7 +56,7 @@ public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
@@ -65,8 +65,8 @@ public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
    @Test
    public void testDefaultTemplateBuilder() throws IOException {
       Template defaultTemplate = view.getComputeService().templateBuilder().build();
-      assertTrue(defaultTemplate.getImage().getOperatingSystem().getVersion().matches("1[45]\\.[01][04]\\.[0-9]-LTS"),
-            "Version mismatch, expected dd.dd.d-LTS, found: "
+      assertTrue(defaultTemplate.getImage().getOperatingSystem().getVersion().matches("1[456]\\.[01][04](\\.[0-9])?-LTS"),
+            "Version mismatch, expected dd.dd(.d)?-LTS, found: "
                   + defaultTemplate.getImage().getOperatingSystem().getVersion());
       assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
       assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
index a6d19fa..d708723 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
@@ -17,7 +17,12 @@
 package org.jclouds.azurecompute.arm.compute.extensions;
 
 import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
 
+import java.net.URI;
 import java.util.Map;
 import java.util.Properties;
 
@@ -26,18 +31,23 @@ import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
 import org.jclouds.compute.ComputeTestUtils;
+import org.jclouds.compute.domain.ExecResponse;
+import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.TemplateBuilder;
 import org.jclouds.compute.extensions.internal.BaseImageExtensionLiveTest;
 import org.jclouds.domain.Location;
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.sshj.config.SshjSshClientModule;
 import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Predicate;
 import com.google.common.cache.LoadingCache;
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
 
 /**
  * Live tests for the {@link org.jclouds.compute.extensions.ImageExtension}
@@ -45,32 +55,34 @@ import com.google.inject.TypeLiteral;
  */
 @Test(groups = "live", singleThreaded = true, testName = "AzureComputeImageExtensionLiveTest")
 public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTest {
-   
-   public static final String NAME_PREFIX = "%s";
-   
-   private LoadingCache<String, ResourceGroup> resourceGroupMap;
 
+   private LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private Predicate<URI> resourceDeleted;
+   private ResourceGroup testResourceGroup;
+   
    public AzureComputeImageExtensionLiveTest() {
       provider = "azurecompute-arm";
    }
-
-   @Override
-   public void initializeContext() {
-      super.initializeContext();
+   
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
       resourceGroupMap = context.utils().injector()
             .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
             }));
+      resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
+      }, Names.named(TIMEOUT_RESOURCE_DELETED)));
+      createResourceGroup();
    }
-
+   
+   @AfterClass(groups = { "integration", "live" })
    @Override
-   @AfterClass(groups = "live", alwaysRun = true)
    protected void tearDownContext() {
       try {
-         Location location = getNodeTemplate().build().getLocation();
-         ResourceGroup rg = resourceGroupMap.getIfPresent(location.getId());
-         if (rg != null) {
-            AzureComputeApi api = view.unwrapApi(AzureComputeApi.class);
-            api.getResourceGroupApi().delete(rg.name());
+         URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name());
+         if (uri != null) {
+            assertTrue(resourceDeleted.apply(uri),
+                  String.format("Resource %s was not terminated in the configured timeout", uri));
          }
       } finally {
          super.tearDownContext();
@@ -78,6 +90,17 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
    }
 
    @Override
+   protected void prepareNodeBeforeCreatingImage(NodeMetadata node) {
+      // Don't wrap in the init-script, since the comand will clear the user
+      // config, and jclouds won't be able to execute more than one command
+      // (won't be able to poll for the execution status of the command when
+      // running with the init-script)
+      ExecResponse result = view.getComputeService().runScriptOnNode(node.getId(), "waagent -deprovision+user -force",
+            wrapInInitScript(false));
+      assertEquals(result.getExitStatus(), 0);
+   }
+
+   @Override
    protected Module getSshModule() {
       return new SshjSshClientModule();
    }
@@ -85,7 +108,7 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
@@ -99,9 +122,11 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
    public TemplateBuilder getNodeTemplate() {
       Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
       return super.getNodeTemplate().options(
-            authorizePublicKey(keyPair.get("public"))
-            .overrideLoginPrivateKey(keyPair.get("private")));
+            authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(keyPair.get("private")));
    }
 
-
+   private void createResourceGroup() {
+      Location location = getNodeTemplate().build().getLocation();
+      testResourceGroup = resourceGroupMap.getUnchecked(location.getId());
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java
index 9296d69..e00880b 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java
@@ -18,6 +18,7 @@ package org.jclouds.azurecompute.arm.compute.extensions;
 
 import static com.google.common.collect.Iterables.get;
 import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static org.jclouds.compute.options.TemplateOptions.Builder.inboundPorts;
 import static org.jclouds.compute.options.TemplateOptions.Builder.securityGroups;
 import static org.jclouds.compute.predicates.NodePredicates.inGroup;
@@ -26,6 +27,7 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
+import java.net.URI;
 import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
@@ -49,9 +51,11 @@ import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
 import com.google.common.cache.LoadingCache;
 import com.google.inject.Key;
 import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
 
 /**
  * Live test for AzureCompute
@@ -61,6 +65,7 @@ import com.google.inject.TypeLiteral;
 public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGroupExtensionLiveTest {
 
    private LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private Predicate<URI> resourceDeleted;
    private ResourceGroup testResourceGroup;
 
    public AzureComputeSecurityGroupExtensionLiveTest() {
@@ -73,6 +78,8 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
       resourceGroupMap = context.utils().injector()
             .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
             }));
+      resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
+      }, Names.named(TIMEOUT_RESOURCE_DELETED)));
       createResourceGroup();
    }
 
@@ -134,7 +141,11 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
    @Override
    protected void tearDownContext() {
       try {
-         view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name());
+         URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name());
+         if (uri != null) {
+            assertTrue(resourceDeleted.apply(uri),
+                  String.format("Resource %s was not terminated in the configured timeout", uri));
+         }
       } finally {
          super.tearDownContext();
       }
@@ -143,7 +154,7 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, "sgelivetest");
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiLiveTest.java
index 6e9e1e7..2b9e30a 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiLiveTest.java
@@ -17,6 +17,7 @@
 package org.jclouds.azurecompute.arm.features;
 
 import static com.google.common.collect.Iterables.any;
+import static org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetType.MANAGED;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
@@ -27,6 +28,7 @@ import java.util.UUID;
 
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetProperties;
+import org.jclouds.azurecompute.arm.domain.AvailabilitySet.SKU;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -56,10 +58,13 @@ public class AvailabilitySetApiLiveTest extends BaseAzureComputeApiLiveTest {
    public void createAvailabilitySet() {
       AvailabilitySetProperties props = AvailabilitySetProperties.builder().platformUpdateDomainCount(2)
             .platformFaultDomainCount(3).build();
-      AvailabilitySet as = api().createOrUpdate(asName, LOCATION, null, props);
+      AvailabilitySet as = api().createOrUpdate(asName, SKU.create(MANAGED), LOCATION, null, props);
 
       assertNotNull(as);
       assertEquals(as.name(), asName);
+      
+      assertNotNull(as.sku());
+      assertEquals(as.sku().type(), MANAGED);
    }
 
    @Test(dependsOnMethods = "createAvailabilitySet")
@@ -80,7 +85,7 @@ public class AvailabilitySetApiLiveTest extends BaseAzureComputeApiLiveTest {
    @Test(dependsOnMethods = "createAvailabilitySet")
    public void updateAvailabilitySet() {
       AvailabilitySet as = api().get(asName);
-      as = api().createOrUpdate(asName, LOCATION, ImmutableMap.of("foo", "bar"), as.properties());
+      as = api().createOrUpdate(asName, SKU.create(MANAGED), LOCATION, ImmutableMap.of("foo", "bar"), as.properties());
 
       assertNotNull(as);
       assertTrue(as.tags().containsKey("foo"));

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiMockTest.java
index db9a7ed..430c32f 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiMockTest.java
@@ -17,6 +17,7 @@
 package org.jclouds.azurecompute.arm.features;
 
 import static com.google.common.collect.Iterables.isEmpty;
+import static org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetType.MANAGED;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
@@ -27,6 +28,7 @@ import java.util.List;
 
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetProperties;
+import org.jclouds.azurecompute.arm.domain.AvailabilitySet.SKU;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
 import org.testng.annotations.Test;
 
@@ -36,7 +38,7 @@ public class AvailabilitySetApiMockTest extends BaseAzureComputeApiMockTest {
    private final String subscriptionid = "SUBSCRIPTIONID";
    private final String resourcegroup = "myresourcegroup";
    private final String asName = "myas";
-   private final String apiVersion = "api-version=2016-03-30";
+   private final String apiVersion = "api-version=2016-04-30-preview";
 
    public void createAvailabilitySet() throws InterruptedException {
 
@@ -46,12 +48,12 @@ public class AvailabilitySetApiMockTest extends BaseAzureComputeApiMockTest {
 
       AvailabilitySetProperties props = AvailabilitySetProperties.builder().platformUpdateDomainCount(2)
             .platformFaultDomainCount(3).build();
-      AvailabilitySet as = asApi.createOrUpdate(asName, "westeurope", null, props);
+      AvailabilitySet as = asApi.createOrUpdate(asName, SKU.create(MANAGED), "westeurope", null, props);
 
       String path = String.format(
             "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/availabilitySets/%s?%s", subscriptionid,
             resourcegroup, asName, apiVersion);
-      String json = "{\"location\":\"westeurope\",\"properties\":{\"platformUpdateDomainCount\":2,\"platformFaultDomainCount\":3}}";
+      String json = "{\"location\":\"westeurope\",\"properties\":{\"platformUpdateDomainCount\":2,\"platformFaultDomainCount\":3},\"sku\":{\"name\":\"Aligned\"}}";
       assertSent(server, "PUT", path, json);
 
       assertEquals(as.name(), asName);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
index b485dc2..0b9ab05 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
@@ -23,11 +23,8 @@ import static org.testng.Assert.assertTrue;
 import java.net.URI;
 import java.util.List;
 
-import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.domain.Deployment;
 import org.jclouds.azurecompute.arm.domain.Deployment.ProvisioningState;
-import org.jclouds.azurecompute.arm.domain.Subnet;
-import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
 import org.jclouds.util.Predicates2;
 import org.testng.Assert;
@@ -37,12 +34,10 @@ import org.testng.annotations.Test;
 import com.google.common.base.Predicate;
 import com.google.common.net.UrlEscapers;
 
-@Test(testName = "DeploymentApiLiveTest", singleThreaded = true)
+@Test(groups = "live", testName = "DeploymentApiLiveTest", singleThreaded = true)
 public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
 
    private String deploymentName;
-   private String subnetId;
-
    private String properties;
    private String badProperties;
 
@@ -52,7 +47,6 @@ public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
       super.setup();
       createTestResourceGroup();
       deploymentName = "jc" + System.currentTimeMillis();
-      String virtualNetworkName = String.format("vn-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
       String storageAccountName = String.format("st%s%s", System.getProperty("user.name"), RAND);
 
       String 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')]\"}}]}";
@@ -61,17 +55,6 @@ public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
 
       properties = getPutBody(rawtemplate, "Incremental", rawparameters);
       badProperties = getPutBody(rawtemplate, "Incremental", rawbadParameters);
-
-      //Subnets belong to a virtual network so that needs to be created first
-      VirtualNetwork vn = createDefaultVirtualNetwork(resourceGroupName, virtualNetworkName, "10.3.0.0/16", LOCATION);
-      assertNotNull(vn);
-
-      //Subnet needs to be up & running before NIC can be created
-      String subnetName = String.format("s-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
-      Subnet subnet = createDefaultSubnet(resourceGroupName, subnetName, virtualNetworkName, "10.3.0.0/23");
-      assertNotNull(subnet);
-      assertNotNull(subnet.id());
-      subnetId = subnet.id();
    }
 
    private String getPutBody(String template, String mode, String parameters) {
@@ -104,48 +87,10 @@ public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
       }
       assertNotNull(deploymentValid);
    }
-   @Test
+   
+   @Test(dependsOnMethods = "testValidate")
    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");
-
-      AzureTemplateOptions options = new AzureTemplateOptions();
-      options.authorizePublicKey(rsakey);
-      options.subnetId(subnetId);
-
-      String deploymentTemplate = "{\n" +
-              "  \"id\": \"/subscriptions/04f7ec88-8e28-41ed-8537-5e17766001f5/resourceGroups/jims216group/providers/Microsoft.Resources/deployments/jcdep1458344383064\",\n" +
-              "  \"name\": \"jcdep1458344383064\",\n" +
-              "  \"properties\": {\n" +
-              "    \"parameters\": {\n" +
-              "      \"newStorageAccountName\": {\n" +
-              "        \"type\": \"String\",\n" +
-              "        \"value\": \"jcres1458344383064\"\n" +
-              "      },\n" +
-              "      \"storageAccountType\": {\n" +
-              "        \"type\": \"String\",\n" +
-              "        \"value\": \"Standard_LRS\"\n" +
-              "      },\n" +
-              "      \"location\": {\n" +
-              "        \"type\": \"String\",\n" +
-              "        \"value\": \"West US\"\n" +
-              "      }\n" +
-              "    },\n" +
-              "    \"mode\": \"Incremental\",\n" +
-              "    \"provisioningState\": \"Accepted\",\n" +
-              "    \"timestamp\": \"2016-03-18T23:39:47.3048037Z\",\n" +
-              "    \"duration\": \"PT2.4433028S\",\n" +
-              "    \"correlationId\": \"8dee9711-8632-4948-9fe6-368bb75e6438\",\n" +
-              "    \"providers\": [{\n" +
-              "      \"namespace\": \"Microsoft.Storage\",\n" +
-              "      \"resourceTypes\": [{\n" +
-              "        \"resourceType\": \"storageAccounts\",\n" +
-              "        \"locations\": [\"westus\"]\n" +
-              "      }]\n" +
-              "    }],\n" +
-              "    \"dependencies\": []\n" +
-              "  }\n" +
-              "}";
-      deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
+      String deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(properties);
 
       Deployment deploymentValid = api().validate(deploymentName, deploymentTemplate);
       assertNotNull(deploymentValid);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java
index becfccd..f5af885 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java
@@ -36,10 +36,10 @@ import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
-@Test(groups = "live", singleThreaded = true)
+@Test(groups = "live", testName = "DiskApiLiveTest", singleThreaded = true)
 public class DiskApiLiveTest extends BaseAzureComputeApiLiveTest {
 
-   public static final String JCLOUDS_IMAGE_PREFIX = "jclouds-";
+   public static final String JCLOUDS_DISK_PREFIX = "jclouds-";
    private String diskName;
 
    @BeforeClass
@@ -47,12 +47,12 @@ public class DiskApiLiveTest extends BaseAzureComputeApiLiveTest {
    public void setup() {
       super.setup();
       createTestResourceGroup();
-      diskName = JCLOUDS_IMAGE_PREFIX + RAND;
+      diskName = JCLOUDS_DISK_PREFIX + RAND;
    }
 
    @Test
    public void deleteDiskResourceDoesNotExist() {
-      assertNull(api().delete(JCLOUDS_IMAGE_PREFIX + UUID.randomUUID()));
+      assertNull(api().delete(JCLOUDS_DISK_PREFIX + UUID.randomUUID()));
    }
 
    @Test

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
index 038fc31..d976258 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
@@ -16,90 +16,154 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.any;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.compute.predicates.NodePredicates.inGroup;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
 import java.net.URI;
-import java.util.Collections;
-import java.util.List;
-import java.util.UUID;
+import java.util.Properties;
 
+import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.Image;
 import org.jclouds.azurecompute.arm.domain.ImageProperties;
-import org.jclouds.azurecompute.arm.domain.Provisionable;
-import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
-import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
+import org.jclouds.azurecompute.arm.domain.ResourceGroup;
+import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.domain.Location;
+import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-import com.google.common.base.Supplier;
+import com.google.common.base.Predicate;
+import com.google.common.cache.LoadingCache;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
 
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
+// We extend the BaseComputeServiceContextLiveTest to create nodes using the abstraction, which is much easier
+@Test(groups = "live", singleThreaded = true, testName = "ImageApiLiveTest")
+public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
+
+   private static final String imageName = "imageFromRest";
 
-@Test(groups = "live", singleThreaded = true)
-public class ImageApiLiveTest extends BaseAzureComputeApiLiveTest {
+   private LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private Predicate<URI> resourceDeleted;
+   private AzureComputeApi api;
+
+   private String resourceGroupName;
+   private String location;
+   private ImageApi imageApi;
+   private Image image;
+
+   private String group;
+
+   public ImageApiLiveTest() {
+      provider = "azurecompute-arm";
+      group = getClass().getSimpleName().toLowerCase();
+   }
+
+   @Override
+   protected Properties setupProperties() {
+      Properties properties = super.setupProperties();
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
+      checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
+      return properties;
+   }
 
-   public static final String JCLOUDS_VM_IMAGE_PREFIX = "jclouds-vm-image-";
-   private String imageName;
-   private VirtualMachine virtualMachine;
+   @Override
+   protected void initializeContext() {
+      super.initializeContext();
+      resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
+      }, Names.named(TIMEOUT_RESOURCE_DELETED)));
+      resourceGroupMap = context.utils().injector()
+            .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
+            }));
+      api = view.unwrapApi(AzureComputeApi.class);
+   }
 
+   @Override
    @BeforeClass
+   public void setupContext() {
+      super.setupContext();
+      // Use the resource name conventions used in the abstraction
+      ResourceGroup resourceGroup = createResourceGroup();
+      resourceGroupName = resourceGroup.name();
+      location = resourceGroup.location();
+      imageApi = api.getVirtualMachineImageApi(resourceGroupName);
+   }
+
    @Override
-   public void setup() {
-      super.setup();
-      createTestResourceGroup();
-      imageName = JCLOUDS_VM_IMAGE_PREFIX + RAND;
-      String vmName = "jclouds-vm-" + RAND;
-
-      virtualMachine = api.getVirtualMachineApi(resourceGroupName).createOrUpdate(vmName, LOCATION, VirtualMachineProperties.builder().build(),
-              Collections.<String, String> emptyMap(), null);
+   @AfterClass(alwaysRun = true)
+   protected void tearDownContext() {
+      try {
+         view.getComputeService().destroyNodesMatching(inGroup(group));
+      } finally {
+         try {
+            URI uri = api.getResourceGroupApi().delete(resourceGroupName);
+            assertResourceDeleted(uri);
+         } finally {
+            super.tearDownContext();
+         }
+      }
    }
 
    @Test
-   public void deleteImageResourceDoesNotExist() {
-      assertNull(api().delete(JCLOUDS_VM_IMAGE_PREFIX + UUID.randomUUID()));
+   public void testDeleteImageDoesNotExist() {
+      assertNull(imageApi.delete("notAnImage"));
    }
 
    @Test
-   public void CreateVirtualMachineImageFromExistingVM() {
-      String id = String.format("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/virtualMachines/myVM", getSubscriptionId(), resourceGroupName);
-      ImageProperties properties = ImageProperties.builder()
-              .sourceVirtualMachine(ImageProperties.SourceVirtualMachine.create(id))
-              .build();
-      Image image = api().createOrUpdate(imageName, LOCATION, properties);
-      assertTrue(waitUntilAvailable(imageName), "creation operation did not complete in the configured timeout");
-      assertTrue(id.equals(image.properties().sourceVirtualMachine().id()));
-   }
+   public void testCreateImage() throws RunNodesException {
+      NodeMetadata node = getOnlyElement(view.getComputeService().createNodesInGroup(group, 1));
+      IdReference vmIdRef = IdReference.create(node.getProviderId());
+      view.getComputeService().suspendNode(node.getId());
+
+      api.getVirtualMachineApi(resourceGroupName).generalize(node.getName());
 
-   @Test(dependsOnMethods = "CreateVirtualMachineImageFromExistingVM")
-   public void getImage() {
-      Image image = api().get(imageName);
+      image = imageApi.createOrUpdate(imageName, location, ImageProperties.builder()
+            .sourceVirtualMachine(vmIdRef).build());
       assertNotNull(image);
    }
 
-   @Test(dependsOnMethods = "CreateVirtualMachineImageFromExistingVM")
-   public void listImages() {
-      List<Image> images = api().list();
-      assertTrue(images.size() > 0);
+   @Test(dependsOnMethods = "testCreateImage")
+   public void testListImages() {
+      // Check that the image we've just created exists
+      assertTrue(any(imageApi.list(), new Predicate<Image>() {
+         @Override
+         public boolean apply(Image input) {
+            return image.name().equals(input.name());
+         }
+      }));
+   }
+
+   @Test(dependsOnMethods = "testCreateImage")
+   public void testGetImage() {
+      assertNotNull(imageApi.get(imageName));
    }
 
-   @Test(dependsOnMethods = {"listImages", "getImage"}, alwaysRun = true)
+   @Test(dependsOnMethods = { "testCreateImage", "testListImages", "testGetImage" }, alwaysRun = true)
    public void deleteImage() {
-      URI uri = api().delete(imageName);
-      assertNotNull(uri);
+      assertResourceDeleted(imageApi.delete(imageName));
    }
 
-   private ImageApi api() {
-      return api.getVirtualMachineImageApi(resourceGroupName);
+   private void assertResourceDeleted(final URI uri) {
+      if (uri != null) {
+         assertTrue(resourceDeleted.apply(uri),
+               String.format("Resource %s was not deleted in the configured timeout", uri));
+      }
    }
-   
-   private boolean waitUntilAvailable(final String name) {
-      return resourceAvailable.apply(new Supplier<Provisionable>() {
-         @Override public Provisionable get() {
-            Image image = api().get(name);
-            return image == null ? null : image.properties();
-         }
-      });
+
+   private ResourceGroup createResourceGroup() {
+      Location location = view.getComputeService().templateBuilder().build().getLocation();
+      return resourceGroupMap.getUnchecked(location.getId());
    }
-}
 
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiMockTest.java
new file mode 100644
index 0000000..cec0483
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiMockTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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 org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.net.URI;
+import java.util.List;
+
+import org.jclouds.azurecompute.arm.domain.DataDisk;
+import org.jclouds.azurecompute.arm.domain.IdReference;
+import org.jclouds.azurecompute.arm.domain.Image;
+import org.jclouds.azurecompute.arm.domain.ImageProperties;
+import org.jclouds.azurecompute.arm.domain.OSDisk;
+import org.jclouds.azurecompute.arm.domain.StorageProfile;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+@Test(groups = "unit", testName = "ImageApiMockTest", singleThreaded = true)
+public class ImageApiMockTest extends BaseAzureComputeApiMockTest {
+   private static final String subscriptionid = "SUBSCRIPTIONID";
+   private static final String resourcegroup = "myresourcegroup";
+   private static final String apiVersion = "api-version=2016-04-30-preview";
+   private static final String imageName = "testVirtualMachineImage";
+   private static final String location = "canadaeast";
+   
+   private static final String PATH = String
+         .format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/images/%s?%s", subscriptionid,
+               resourcegroup, imageName, apiVersion);
+
+   public void createVirtualMachineImage() throws InterruptedException {
+      server.enqueue(jsonResponse("/virtualmachineimagecreate.json"));
+
+      ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      Image result = imageApi.createOrUpdate(imageName, location, newVirtualMachineImage().properties());
+      
+      assertSent(server, "PUT", PATH, "{\"location\":\"" + location + "\","
+            + "\"properties\":{\"sourceVirtualMachine\":{\"id\":\"vmId\"},"
+            + "\"storageProfile\":{\"osDisk\":{\"osType\":\"Linux\",\"name\":\"Ubuntu\"},\"dataDisks\":[]},"
+            + "\"provisioningState\":\"Succeeded\"}}");
+
+      assertEquals(result.name(), imageName);
+      assertEquals(result.location(), location);
+   }
+
+   public void getVirtualMachineImage() throws InterruptedException {
+      server.enqueue(jsonResponse("/virtualmachineimageget.json"));
+
+      ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      Image result = imageApi.get(imageName);
+
+      assertSent(server, "GET", PATH);
+
+      assertEquals(result.name(), imageName);
+      assertEquals(result.location(), location);
+      assertNotNull(result.properties().sourceVirtualMachine());
+      assertNotNull(result.properties().storageProfile());
+   }
+
+   public void getVirtualMachineImageReturns404() throws InterruptedException {
+      server.enqueue(response404());
+
+      final ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      Image result = imageApi.get(imageName);
+
+      assertSent(server, "GET", PATH);
+      
+      assertNull(result);
+   }
+
+   public void listVirtualMachineImages() throws InterruptedException {
+      server.enqueue(jsonResponse("/virtualmachineimagelist.json"));
+
+      final ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      List<Image> result = imageApi.list();
+
+      assertSent(server, "GET", String
+            .format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/images?%s", subscriptionid,
+                  resourcegroup, apiVersion));
+
+      assertNotNull(result);
+      assertTrue(result.size() > 0);
+   }
+
+   public void listVirtualMachineImagesReturns404() throws InterruptedException {
+      server.enqueue(response404());
+
+      final ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      List<Image> result = imageApi.list();
+
+      assertSent(server, "GET", String
+            .format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/images?%s", subscriptionid,
+                  resourcegroup, apiVersion));
+
+      assertTrue(isEmpty(result));
+   }
+
+   public void deleteVirtualMachineImage() throws InterruptedException {
+      server.enqueue(response202WithHeader());
+
+      final ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      URI uri = imageApi.delete(imageName);
+
+      assertSent(server, "DELETE", PATH);
+
+      assertNotNull(uri);
+      assertTrue(uri.toString().contains("api-version"));
+      assertTrue(uri.toString().contains("operationresults"));
+   }
+
+   public void deleteVirtualMachineImageDoesNotExist() throws InterruptedException {
+      server.enqueue(response404());
+
+      final ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      URI uri = imageApi.delete(imageName);
+      assertNull(uri);
+
+      assertSent(server, "DELETE", PATH);
+   }
+
+   private Image newVirtualMachineImage() {
+      return Image
+            .builder()
+            .name(imageName)
+            .location(location)
+            .properties(
+                  ImageProperties
+                        .builder()
+                        .sourceVirtualMachine(IdReference.create("vmId"))
+                        .storageProfile(
+                              StorageProfile.create(null, OSDisk.builder().osType("Linux").name("Ubuntu").build(),
+                                    ImmutableList.<DataDisk> of())).provisioningState("Succeeded").build()).build();
+      
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
index 69014a5..5799093 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
@@ -116,7 +116,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
       checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
       return properties;
    }
@@ -356,7 +356,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
       // set
       AvailabilitySetProperties props = AvailabilitySetProperties.builder().platformUpdateDomainCount(count)
             .platformFaultDomainCount(count).build();
-      AvailabilitySet as = AvailabilitySet.builder().name(group).properties(props).build();
+      AvailabilitySet as = AvailabilitySet.managed().name(group).properties(props).build();
 
       Set<? extends NodeMetadata> nodes = view.getComputeService()
             .createNodesInGroup(group, count, availabilitySet(as));


[47/50] [abbrv] jclouds git commit: Add Azure KeyVault support

Posted by na...@apache.org.
Add Azure KeyVault support


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

Branch: refs/heads/master
Commit: a2dee2f84c96ba743e1fa81bd225b066473ea26d
Parents: ac5f3a1
Author: Jim Spring <jm...@gmail.com>
Authored: Fri Dec 22 18:37:08 2017 -0800
Committer: Ignasi Barrera <na...@apache.org>
Committed: Thu Jan 4 01:44:48 2018 +0100

----------------------------------------------------------------------
 .../azurecompute/arm/AzureComputeApi.java       |   12 +-
 .../arm/AzureComputeProviderMetadata.java       |    2 +
 .../arm/AzureManagementApiMetadata.java         |    2 +
 .../arm/compute/AzureComputeServiceAdapter.java |    2 +-
 .../AzureComputeServiceContextModule.java       |  269 ---
 .../compute/config/AzurePredicatesModule.java   |  602 +++++++
 .../ResourceGroupAndNameAndIngressRules.java    |    5 +-
 .../extensions/AzureComputeImageExtension.java  |    4 +-
 .../AzureComputeSecurityGroupExtension.java     |    2 +-
 .../loaders/CreateSecurityGroupIfNeeded.java    |    2 +-
 .../arm/config/AzureComputeProperties.java      |    9 +
 .../azurecompute/arm/domain/Certificate.java    |  638 +++++++
 .../jclouds/azurecompute/arm/domain/Key.java    |  229 +++
 .../jclouds/azurecompute/arm/domain/SKU.java    |   27 +-
 .../jclouds/azurecompute/arm/domain/Secret.java |  186 ++
 .../jclouds/azurecompute/arm/domain/Vault.java  |  112 ++
 .../arm/domain/VaultProperties.java             |  131 ++
 .../azurecompute/arm/features/VaultApi.java     |  635 +++++++
 .../arm/features/LoadBalancerApiLiveTest.java   |    2 +-
 .../arm/features/VaultApiLiveTest.java          | 1057 ++++++++++++
 .../arm/features/VaultApiMockTest.java          | 1619 ++++++++++++++++++
 .../internal/BaseAzureComputeApiLiveTest.java   |   60 +-
 .../internal/BaseAzureComputeApiMockTest.java   |   16 +-
 .../src/test/resources/getvault.json            |   60 +
 .../src/test/resources/vaultbackupkey.json      |    3 +
 .../src/test/resources/vaultbackupsecret.json   |    3 +
 .../src/test/resources/vaultcreate.json         |   26 +
 .../test/resources/vaultcreatecertificate.json  |   11 +
 .../vaultcreatecertificaterequestbody.json      |   21 +
 .../src/test/resources/vaultcreatekey.json      |   15 +
 .../resources/vaultcreatekeyrequestbody.json    |    7 +
 .../test/resources/vaultcreaterequestbody.json  |   21 +
 .../test/resources/vaultdeletecertificate.json  |   58 +
 .../vaultdeletecertificatecontacts.json         |    8 +
 .../resources/vaultdeletecertificateissuer.json |   21 +
 .../vaultdeletecertificateoperation.json        |   11 +
 .../src/test/resources/vaultdeletekey.json      |   15 +
 .../src/test/resources/vaultdeletesecret.json   |   10 +
 .../src/test/resources/vaultget.json            |   26 +
 .../src/test/resources/vaultgetcertificate.json |   55 +
 .../resources/vaultgetcertificatecontacts.json  |    8 +
 .../resources/vaultgetcertificateissuer.json    |   21 +
 .../resources/vaultgetcertificateoperation.json |   11 +
 .../resources/vaultgetcertificatepolicy.json    |   37 +
 .../src/test/resources/vaultgetdeleted.json     |   12 +
 .../resources/vaultgetdeletedcertificate.json   |   55 +
 .../src/test/resources/vaultgetdeletedkey.json  |   18 +
 .../test/resources/vaultgetdeletedsecret.json   |   13 +
 .../src/test/resources/vaultgetkey.json         |   15 +
 .../src/test/resources/vaultgetkeyversions.json |   23 +
 .../src/test/resources/vaultgetsecret.json      |   11 +
 .../test/resources/vaultgetsecretversions.json  |   25 +
 .../src/test/resources/vaultimportablecert.txt  |   58 +
 .../test/resources/vaultimportcertificate.json  |   52 +
 .../vaultimportcertificaterequestbody.json      |    9 +
 .../resources/vaultimportkeyrequestbody.json    |   18 +
 .../src/test/resources/vaultkeybackup.txt       |    1 +
 .../src/test/resources/vaultkeydecrypt.json     |    4 +
 .../resources/vaultkeydecryptrequestbody.json   |    4 +
 .../src/test/resources/vaultkeyencrypt.json     |    4 +
 .../resources/vaultkeyencryptrequestbody.json   |    4 +
 .../src/test/resources/vaultkeysign.json        |    4 +
 .../test/resources/vaultkeysignrequestbody.json |    4 +
 .../src/test/resources/vaultkeyunwrap.json      |    4 +
 .../resources/vaultkeyunwraprequestbody.json    |    4 +
 .../src/test/resources/vaultkeyverify.json      |    3 +
 .../resources/vaultkeyverifyrequestbody.json    |    5 +
 .../src/test/resources/vaultkeywrap.json        |    4 +
 .../test/resources/vaultkeywraprequestbody.json |    4 +
 .../src/test/resources/vaultlist.json           |   29 +
 .../resources/vaultlistcertificateissuers.json  |    7 +
 .../test/resources/vaultlistcertificates.json   |   27 +
 .../resources/vaultlistcertificateversions.json |   17 +
 .../src/test/resources/vaultlistdeleted.json    |   15 +
 .../resources/vaultlistdeletedcertificates.json |   18 +
 .../test/resources/vaultlistdeletedkeys.json    |   15 +
 .../test/resources/vaultlistdeletedsecrets.json |   16 +
 .../src/test/resources/vaultlistkeys.json       |   42 +
 .../src/test/resources/vaultlistsecrets.json    |   40 +
 .../test/resources/vaultmergecertificate.json   |   62 +
 .../vaultmergecertificaterequestbody.json       |   10 +
 .../src/test/resources/vaultmergex5c-1.txt      |    1 +
 .../src/test/resources/vaultmergex5c-2.txt      |    1 +
 .../src/test/resources/vaultmergex5c-3.txt      |    1 +
 .../vaultrecoverdeletedcertificate.json         |   52 +
 .../test/resources/vaultrecoverdeletedkey.json  |   15 +
 .../resources/vaultrecoverdeletedsecret.json    |   10 +
 .../src/test/resources/vaultrestorekey.json     |   15 +
 .../resources/vaultrestorekeyrequestbody.json   |    3 +
 .../src/test/resources/vaultrestoresecret.json  |   10 +
 .../vaultrestoresecretrequestbody.json          |    3 +
 .../src/test/resources/vaultsamplesecret.txt    |   27 +
 .../src/test/resources/vaultsecretbackup.txt    |    1 +
 .../resources/vaultsetcertificatecontacts.json  |    8 +
 .../vaultsetcertificatecontactsrequestbody.json |    7 +
 .../resources/vaultsetcertificateissuer.json    |   21 +
 .../vaultsetcertificateissuerrequestbody.json   |   15 +
 .../src/test/resources/vaultsetsecret.json      |   11 +
 .../resources/vaultsetsecretrequestbody.json    |    7 +
 .../test/resources/vaultupdatecertificate.json  |   58 +
 .../resources/vaultupdatecertificateissuer.json |   21 +
 ...vaultupdatecertificateissuerrequestbody.json |   15 +
 .../vaultupdatecertificateoperation.json        |   11 +
 ...ltupdatecertificateoperationrequestbody.json |    3 +
 .../resources/vaultupdatecertificatepolicy.json |   37 +
 ...vaultupdatecertificatepolicyrequestbody.json |    8 +
 .../vaultupdatecertificaterequestbody.json      |    1 +
 .../src/test/resources/vaultupdatekey.json      |   18 +
 .../resources/vaultupdatekeyrequestbody.json    |    5 +
 .../resources/vaultupdatekeywithversion.json    |   18 +
 .../src/test/resources/vaultupdatesecret.json   |   13 +
 .../resources/vaultupdatesecretrequestbody.json |    5 +
 .../resources/vaultupdatesecretwithversion.json |   13 +
 ...vaultupdatesecretwithversionrequestbody.json |    5 +
 114 files changed, 6861 insertions(+), 305 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index 1f6b726..d62a5b7 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -41,6 +41,7 @@ import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
 import org.jclouds.azurecompute.arm.features.StorageAccountApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
 import org.jclouds.azurecompute.arm.features.VMSizeApi;
+import org.jclouds.azurecompute.arm.features.VaultApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineScaleSetApi;
 import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
@@ -242,7 +243,7 @@ public interface AzureComputeApi extends Closeable {
     */
    @Delegate
    MetricDefinitionsApi getMetricsDefinitionsApi(@PathParam("resourceid") String resourceid);
-   
+
    /**
     * The Azure Active Directory Graph API provides programmatic access to Azure
     * AD through REST API endpoints.
@@ -253,6 +254,15 @@ public interface AzureComputeApi extends Closeable {
    GraphRBACApi getGraphRBACApi();
    
    /**
+    * Managing your key vaults as well as the keys, secrets, and certificates within your key vaults can be 
+    * accomplished through a REST interface.
+    *
+    * @see <a href="https://docs.microsoft.com/en-us/rest/api/keyvault/">docs</a>
+    */
+   @Delegate
+   VaultApi getVaultApi(@PathParam("resourcegroup") String resourcegroup);
+   
+   /**
     * Returns the information about the current service principal.
     */
    @Provides

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index 335de98..c85beb9 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -57,6 +57,7 @@ import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
 import org.jclouds.azurecompute.arm.features.StorageAccountApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
 import org.jclouds.azurecompute.arm.features.VMSizeApi;
+import org.jclouds.azurecompute.arm.features.VaultApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineScaleSetApi;
 import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
@@ -126,6 +127,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(API_VERSION_PREFIX + MetricsApi.class.getSimpleName(), "2016-09-01");
       properties.put(API_VERSION_PREFIX + VirtualMachineScaleSetApi.class.getSimpleName(), "2017-03-30");
       properties.put(API_VERSION_PREFIX + GraphRBACApi.class.getSimpleName(), "1.6");
+      properties.put(API_VERSION_PREFIX + VaultApi.class.getSimpleName(), "2016-10-01");
       
       return properties;
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
index 9c73e99..56cb788 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
@@ -23,6 +23,7 @@ import java.util.Properties;
 
 import org.jclouds.apis.ApiMetadata;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule;
 import org.jclouds.azurecompute.arm.config.AzureComputeHttpApiModule;
 import org.jclouds.azurecompute.arm.config.AzureComputeParserModule;
 import org.jclouds.azurecompute.arm.config.AzureComputeRateLimitModule;
@@ -80,6 +81,7 @@ public class AzureManagementApiMetadata extends BaseHttpApiMetadata<AzureCompute
                          .add(AzureComputeParserModule.class)
                          .add(AzureComputeHttpApiModule.class)
                          .add(AzureComputeServiceContextModule.class)
+                         .add(AzurePredicatesModule.class)
                          .add(AzureComputeRateLimitModule.class)
                          .build());
       }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 37585e2..cd5e0e9 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -45,7 +45,7 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.PublicIpAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
index 11d3ab1..de33fdf 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
@@ -16,22 +16,8 @@
  */
 package org.jclouds.azurecompute.arm.compute.config;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
-import static org.jclouds.util.Predicates2.retry;
-
-import java.net.URI;
-import java.util.List;
-
-import javax.inject.Named;
 import javax.inject.Singleton;
 
-import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.AzureComputeService;
 import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
@@ -47,20 +33,13 @@ import org.jclouds.azurecompute.arm.compute.loaders.CreateSecurityGroupIfNeeded;
 import org.jclouds.azurecompute.arm.compute.loaders.DefaultResourceGroup;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.compute.strategy.CreateResourcesThenCreateNodes;
-import org.jclouds.azurecompute.arm.domain.Image;
 import org.jclouds.azurecompute.arm.domain.Location;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
-import org.jclouds.azurecompute.arm.domain.Provisionable;
-import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
-import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.VMHardware;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
-import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.PowerState;
-import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
 import org.jclouds.compute.ComputeService;
 import org.jclouds.compute.ComputeServiceAdapter;
 import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
@@ -72,15 +51,10 @@ import org.jclouds.compute.extensions.SecurityGroupExtension;
 import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement;
 import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatementWithoutPublicKey;
 import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
-import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
 import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
 import org.jclouds.net.domain.IpPermission;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
@@ -141,247 +115,4 @@ public class AzureComputeServiceContextModule extends
    protected final LoadingCache<String, ResourceGroup> defaultResourceGroup(CacheLoader<String, ResourceGroup> in) {
       return CacheBuilder.newBuilder().build(in);
    }
-
-   @Provides
-   @Named(TIMEOUT_NODE_RUNNING)
-   protected VirtualMachineInStatePredicateFactory provideVirtualMachineRunningPredicate(final AzureComputeApi api,
-         final Timeouts timeouts, final PollPeriod pollPeriod) {
-      return new VirtualMachineInStatePredicateFactory(api, PowerState.RUNNING, timeouts.nodeRunning,
-            pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   @Named(TIMEOUT_NODE_TERMINATED)
-   protected Predicate<URI> provideNodeTerminatedPredicate(final AzureComputeApi api, final Timeouts timeouts,
-         final PollPeriod pollPeriod) {
-      return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod,
-            pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   @Named(TIMEOUT_IMAGE_AVAILABLE)
-   protected Predicate<URI> provideImageCapturedPredicate(final AzureComputeApi api, final Timeouts timeouts,
-         final PollPeriod pollPeriod) {
-      return retry(new ImageCapturedPredicate(api), timeouts.imageAvailable, pollPeriod.pollInitialPeriod,
-            pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   @Named(TIMEOUT_RESOURCE_DELETED)
-   protected Predicate<URI> provideResourceDeletedPredicate(final AzureComputeApi api, final Timeouts timeouts,
-         final PollPeriod pollPeriod) {
-      return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod,
-            pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   @Named(TIMEOUT_NODE_SUSPENDED)
-   protected VirtualMachineInStatePredicateFactory provideNodeSuspendedPredicate(final AzureComputeApi api,
-         final Timeouts timeouts, final PollPeriod pollPeriod) {
-      return new VirtualMachineInStatePredicateFactory(api, PowerState.STOPPED, timeouts.nodeTerminated,
-            pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   protected PublicIpAvailablePredicateFactory providePublicIpAvailablePredicate(final AzureComputeApi api,
-         Predicate<Supplier<Provisionable>> resourceAvailable) {
-      return new PublicIpAvailablePredicateFactory(api, resourceAvailable);
-   }
-
-   @Provides
-   protected SecurityGroupAvailablePredicateFactory provideSecurityGroupAvailablePredicate(final AzureComputeApi api,
-         Predicate<Supplier<Provisionable>> resourceAvailable) {
-      return new SecurityGroupAvailablePredicateFactory(api, resourceAvailable);
-   }
-   
-   @Provides
-   protected ImageAvailablePredicateFactory provideImageAvailablePredicate(final AzureComputeApi api,
-         Predicate<Supplier<Provisionable>> resourceAvailable, final Timeouts timeouts, final PollPeriod pollPeriod) {
-      return new ImageAvailablePredicateFactory(api, retry(new ResourceInStatusPredicate("Succeeded"),
-            timeouts.imageAvailable, pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod));
-   }
-
-   @Provides
-   protected Predicate<Supplier<Provisionable>> provideResourceAvailablePredicate(final AzureComputeApi api,
-         @Named(OPERATION_TIMEOUT) Integer operationTimeout, PollPeriod pollPeriod) {
-      return retry(new ResourceInStatusPredicate("Succeeded"), operationTimeout, pollPeriod.pollInitialPeriod,
-            pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   @Named("STORAGE")
-   protected Predicate<URI> provideStorageAccountAvailablePredicate(final AzureComputeApi api,
-         @Named(OPERATION_TIMEOUT) Integer operationTimeout, PollPeriod pollPeriod) {
-      return retry(new ActionDonePredicate(api), operationTimeout, pollPeriod.pollInitialPeriod,
-            pollPeriod.pollMaxPeriod);
-   }
-
-   @VisibleForTesting
-   static class ActionDonePredicate implements Predicate<URI> {
-
-      private final AzureComputeApi api;
-
-      public ActionDonePredicate(final AzureComputeApi api) {
-         this.api = checkNotNull(api, "api must not be null");
-      }
-
-      @Override
-      public boolean apply(final URI uri) {
-         checkNotNull(uri, "uri cannot be null");
-         return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri)
-               || ParseJobStatus.JobStatus.NO_CONTENT == api.getJobApi().jobStatus(uri);
-      }
-
-   }
-
-   @VisibleForTesting
-   static class ImageCapturedPredicate implements Predicate<URI> {
-
-      private final AzureComputeApi api;
-
-      public ImageCapturedPredicate(final AzureComputeApi api) {
-         this.api = checkNotNull(api, "api must not be null");
-      }
-
-      @Override
-      public boolean apply(final URI uri) {
-         checkNotNull(uri, "uri cannot be null");
-         if (api.getJobApi().jobStatus(uri) != ParseJobStatus.JobStatus.DONE) {
-            return false;
-         }
-         List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
-         return definitions != null;
-      }
-   }
-
-   public static class VirtualMachineInStatePredicateFactory {
-
-      private final AzureComputeApi api;
-      private final PowerState powerState;
-      private final long timeout;
-      private final long period;
-      private final long maxPeriod;
-
-      VirtualMachineInStatePredicateFactory(final AzureComputeApi api, final PowerState powerState, final long timeout,
-            final long period, final long maxPeriod) {
-         this.api = checkNotNull(api, "api cannot be null");
-         this.powerState = checkNotNull(powerState, "powerState cannot be null");
-         this.timeout = timeout;
-         this.period = period;
-         this.maxPeriod = maxPeriod;
-      }
-
-      public Predicate<String> create(final String azureGroup) {
-         return retry(new Predicate<String>() {
-            @Override
-            public boolean apply(final String name) {
-               checkNotNull(name, "name cannot be null");
-               VirtualMachineInstance vmInstance = api.getVirtualMachineApi(azureGroup).getInstanceDetails(name);
-               if (vmInstance == null) {
-                  return false;
-               }
-               return powerState == vmInstance.powerState();
-            }
-         }, timeout, period, maxPeriod);
-      }
-   }
-   
-   public static class ResourceInStatusPredicate implements Predicate<Supplier<Provisionable>> {
-      private final String expectedStatus;
-
-      ResourceInStatusPredicate(String expectedStatus) {
-         this.expectedStatus = checkNotNull(expectedStatus, "expectedStatus cannot be null");
-      }
-
-      @Override
-      public boolean apply(Supplier<Provisionable> provisionableSupplier) {
-         checkNotNull(provisionableSupplier, "provisionableSupplier supplier cannot be null");
-         Provisionable provisionable = provisionableSupplier.get();
-         return provisionable != null && provisionable.provisioningState().equalsIgnoreCase(expectedStatus);
-      }
-   }
-
-   public static class PublicIpAvailablePredicateFactory {
-      private final AzureComputeApi api;
-      private final Predicate<Supplier<Provisionable>> resourceAvailable;
-
-      PublicIpAvailablePredicateFactory(final AzureComputeApi api, Predicate<Supplier<Provisionable>> resourceAvailable) {
-         this.api = checkNotNull(api, "api cannot be null");
-         this.resourceAvailable = resourceAvailable;
-      }
-
-      public Predicate<String> create(final String azureGroup) {
-         checkNotNull(azureGroup, "azureGroup cannot be null");
-         return new Predicate<String>() {
-            @Override
-            public boolean apply(final String name) {
-               checkNotNull(name, "name cannot be null");
-               return resourceAvailable.apply(new Supplier<Provisionable>() {
-                  @Override
-                  public Provisionable get() {
-                     PublicIPAddress publicIp = api.getPublicIPAddressApi(azureGroup).get(name);
-                     return publicIp == null ? null : publicIp.properties();
-                  }
-               });
-            }
-         };
-      }
-   }
-
-   public static class SecurityGroupAvailablePredicateFactory {
-      private final AzureComputeApi api;
-      private final Predicate<Supplier<Provisionable>> resourceAvailable;
-
-      SecurityGroupAvailablePredicateFactory(final AzureComputeApi api,
-            Predicate<Supplier<Provisionable>> resourceAvailable) {
-         this.api = checkNotNull(api, "api cannot be null");
-         this.resourceAvailable = resourceAvailable;
-      }
-
-      public Predicate<String> create(final String resourceGroup) {
-         checkNotNull(resourceGroup, "resourceGroup cannot be null");
-         return new Predicate<String>() {
-            @Override
-            public boolean apply(final String name) {
-               checkNotNull(name, "name cannot be null");
-               return resourceAvailable.apply(new Supplier<Provisionable>() {
-                  @Override
-                  public Provisionable get() {
-                     NetworkSecurityGroup sg = api.getNetworkSecurityGroupApi(resourceGroup).get(name);
-                     return sg == null ? null : sg.properties();
-                  }
-               });
-            }
-         };
-      }
-   }
-   
-   public static class ImageAvailablePredicateFactory {
-      private final AzureComputeApi api;
-      private final Predicate<Supplier<Provisionable>> resourceAvailable;
-      
-      ImageAvailablePredicateFactory(final AzureComputeApi api,
-            Predicate<Supplier<Provisionable>> resourceAvailable) {
-         this.api = checkNotNull(api, "api cannot be null");
-         this.resourceAvailable = resourceAvailable;
-      }
-
-      public Predicate<String> create(final String resourceGroup) {
-         checkNotNull(resourceGroup, "resourceGroup cannot be null");
-         return new Predicate<String>() {
-            @Override
-            public boolean apply(final String name) {
-               checkNotNull(name, "name cannot be null");
-               return resourceAvailable.apply(new Supplier<Provisionable>() {
-                  @Override
-                  public Provisionable get() {
-                     Image img = api.getVirtualMachineImageApi(resourceGroup).get(name);
-                     return img == null ? null : img.properties();
-                  }
-               });
-            }
-         };
-      }
-   }
-
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzurePredicatesModule.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzurePredicatesModule.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzurePredicatesModule.java
new file mode 100644
index 0000000..c8dfd6e
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzurePredicatesModule.java
@@ -0,0 +1,602 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.compute.config;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.name.Named;
+
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
+
+import org.jclouds.azurecompute.arm.domain.Image;
+import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
+import org.jclouds.azurecompute.arm.domain.Provisionable;
+import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
+import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
+import org.jclouds.azurecompute.arm.domain.Vault;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
+import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
+import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.domain.Key.DeletedKeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.KeyBundle;
+import org.jclouds.azurecompute.arm.domain.Secret.DeletedSecretBundle;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateOperation;
+
+import java.net.URI;
+import java.util.List;
+
+import static org.jclouds.util.Predicates2.retry;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_KEY_DELETED_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_KEY_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_SECRET_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_SECRET_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_OPERATION_STATUS;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class AzurePredicatesModule extends AbstractModule {
+    protected void configure() {
+    }
+
+    @Provides
+    @Named(TIMEOUT_NODE_RUNNING)
+    protected VirtualMachineInStatePredicateFactory provideVirtualMachineRunningPredicate(final AzureComputeApi api,
+                                                                                          final ComputeServiceConstants.Timeouts timeouts, final PollPeriod pollPeriod) {
+        return new VirtualMachineInStatePredicateFactory(api, VirtualMachineInstance.PowerState.RUNNING, timeouts.nodeRunning,
+                pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(TIMEOUT_NODE_TERMINATED)
+    protected Predicate<URI> provideNodeTerminatedPredicate(final AzureComputeApi api, final ComputeServiceConstants.Timeouts timeouts,
+                                                            final PollPeriod pollPeriod) {
+        return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod,
+                pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(TIMEOUT_IMAGE_AVAILABLE)
+    protected Predicate<URI> provideImageCapturedPredicate(final AzureComputeApi api, final ComputeServiceConstants.Timeouts timeouts,
+                                                           final PollPeriod pollPeriod) {
+        return retry(new ImageCapturedPredicate(api), timeouts.imageAvailable, pollPeriod.pollInitialPeriod,
+                pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(TIMEOUT_RESOURCE_DELETED)
+    protected Predicate<URI> provideResourceDeletedPredicate(final AzureComputeApi api, final ComputeServiceConstants.Timeouts timeouts,
+                                                             final PollPeriod pollPeriod) {
+        return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod,
+                pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(TIMEOUT_NODE_SUSPENDED)
+    protected VirtualMachineInStatePredicateFactory provideNodeSuspendedPredicate(final AzureComputeApi api,
+                                                                                  final ComputeServiceConstants.Timeouts timeouts, final PollPeriod pollPeriod) {
+        return new VirtualMachineInStatePredicateFactory(api, VirtualMachineInstance.PowerState.STOPPED, timeouts.nodeTerminated,
+                pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    protected PublicIpAvailablePredicateFactory providePublicIpAvailablePredicate(final AzureComputeApi api,
+                                                                                  Predicate<Supplier<Provisionable>> resourceAvailable) {
+        return new PublicIpAvailablePredicateFactory(api, resourceAvailable);
+    }
+
+    @Provides
+    protected SecurityGroupAvailablePredicateFactory provideSecurityGroupAvailablePredicate(final AzureComputeApi api,
+                                                                                            Predicate<Supplier<Provisionable>> resourceAvailable) {
+        return new SecurityGroupAvailablePredicateFactory(api, resourceAvailable);
+    }
+
+    @Provides
+    protected ImageAvailablePredicateFactory provideImageAvailablePredicate(final AzureComputeApi api,
+                                                                            Predicate<Supplier<Provisionable>> resourceAvailable, final ComputeServiceConstants.Timeouts timeouts, final PollPeriod pollPeriod) {
+        return new ImageAvailablePredicateFactory(api, retry(new ResourceInStatusPredicate("Succeeded"),
+                timeouts.imageAvailable, pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod));
+    }
+
+    @Provides
+    protected Predicate<Supplier<Provisionable>> provideResourceAvailablePredicate(final AzureComputeApi api,
+                                                                                   @Named(OPERATION_TIMEOUT) Integer operationTimeout, PollPeriod pollPeriod) {
+        return retry(new ResourceInStatusPredicate("Succeeded"), operationTimeout, pollPeriod.pollInitialPeriod,
+                pollPeriod.pollMaxPeriod);
+    }
+
+    @VisibleForTesting
+    static class ActionDonePredicate implements Predicate<URI> {
+
+        private final AzureComputeApi api;
+
+        public ActionDonePredicate(final AzureComputeApi api) {
+            this.api = checkNotNull(api, "api must not be null");
+        }
+
+        @Override
+        public boolean apply(final URI uri) {
+            checkNotNull(uri, "uri cannot be null");
+            return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri)
+                    || ParseJobStatus.JobStatus.NO_CONTENT == api.getJobApi().jobStatus(uri);
+        }
+    }
+
+    @VisibleForTesting
+    static class ImageCapturedPredicate implements Predicate<URI> {
+
+        private final AzureComputeApi api;
+
+        public ImageCapturedPredicate(final AzureComputeApi api) {
+            this.api = checkNotNull(api, "api must not be null");
+        }
+
+        @Override
+        public boolean apply(final URI uri) {
+            checkNotNull(uri, "uri cannot be null");
+            if (api.getJobApi().jobStatus(uri) != ParseJobStatus.JobStatus.DONE) {
+                return false;
+            }
+            List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
+            return definitions != null;
+        }
+    }
+
+    public static class VirtualMachineInStatePredicateFactory {
+
+        private final AzureComputeApi api;
+        private final VirtualMachineInstance.PowerState powerState;
+        private final long timeout;
+        private final long period;
+        private final long maxPeriod;
+
+        VirtualMachineInStatePredicateFactory(final AzureComputeApi api, final VirtualMachineInstance.PowerState powerState, final long timeout,
+                                              final long period, final long maxPeriod) {
+            this.api = checkNotNull(api, "api cannot be null");
+            this.powerState = checkNotNull(powerState, "powerState cannot be null");
+            this.timeout = timeout;
+            this.period = period;
+            this.maxPeriod = maxPeriod;
+        }
+
+        public Predicate<String> create(final String azureGroup) {
+            return retry(new Predicate<String>() {
+                @Override
+                public boolean apply(final String name) {
+                    checkNotNull(name, "name cannot be null");
+                    VirtualMachineInstance vmInstance = api.getVirtualMachineApi(azureGroup).getInstanceDetails(name);
+                    if (vmInstance == null) {
+                        return false;
+                    }
+                    return powerState == vmInstance.powerState();
+                }
+            }, timeout, period, maxPeriod);
+        }
+    }
+
+    public static class ResourceInStatusPredicate implements Predicate<Supplier<Provisionable>> {
+        private final String expectedStatus;
+
+        ResourceInStatusPredicate(String expectedStatus) {
+            this.expectedStatus = checkNotNull(expectedStatus, "expectedStatus cannot be null");
+        }
+
+        @Override
+        public boolean apply(Supplier<Provisionable> provisionableSupplier) {
+            checkNotNull(provisionableSupplier, "provisionableSupplier supplier cannot be null");
+            Provisionable provisionable = provisionableSupplier.get();
+            return provisionable != null && provisionable.provisioningState().equalsIgnoreCase(expectedStatus);
+        }
+    }
+
+    public static class PublicIpAvailablePredicateFactory {
+        private final AzureComputeApi api;
+        private final Predicate<Supplier<Provisionable>> resourceAvailable;
+
+        PublicIpAvailablePredicateFactory(final AzureComputeApi api, Predicate<Supplier<Provisionable>> resourceAvailable) {
+            this.api = checkNotNull(api, "api cannot be null");
+            this.resourceAvailable = resourceAvailable;
+        }
+
+        public Predicate<String> create(final String azureGroup) {
+            checkNotNull(azureGroup, "azureGroup cannot be null");
+            return new Predicate<String>() {
+                @Override
+                public boolean apply(final String name) {
+                    checkNotNull(name, "name cannot be null");
+                    return resourceAvailable.apply(new Supplier<Provisionable>() {
+                        @Override
+                        public Provisionable get() {
+                            PublicIPAddress publicIp = api.getPublicIPAddressApi(azureGroup).get(name);
+                            return publicIp == null ? null : publicIp.properties();
+                        }
+                    });
+                }
+            };
+        }
+    }
+
+    public static class SecurityGroupAvailablePredicateFactory {
+        private final AzureComputeApi api;
+        private final Predicate<Supplier<Provisionable>> resourceAvailable;
+
+        SecurityGroupAvailablePredicateFactory(final AzureComputeApi api,
+                                               Predicate<Supplier<Provisionable>> resourceAvailable) {
+            this.api = checkNotNull(api, "api cannot be null");
+            this.resourceAvailable = resourceAvailable;
+        }
+
+        public Predicate<String> create(final String resourceGroup) {
+            checkNotNull(resourceGroup, "resourceGroup cannot be null");
+            return new Predicate<String>() {
+                @Override
+                public boolean apply(final String name) {
+                    checkNotNull(name, "name cannot be null");
+                    return resourceAvailable.apply(new Supplier<Provisionable>() {
+                        @Override
+                        public Provisionable get() {
+                            NetworkSecurityGroup sg = api.getNetworkSecurityGroupApi(resourceGroup).get(name);
+                            return sg == null ? null : sg.properties();
+                        }
+                    });
+                }
+            };
+        }
+    }
+
+    public static class ImageAvailablePredicateFactory {
+        private final AzureComputeApi api;
+        private final Predicate<Supplier<Provisionable>> resourceAvailable;
+
+        ImageAvailablePredicateFactory(final AzureComputeApi api,
+                                       Predicate<Supplier<Provisionable>> resourceAvailable) {
+            this.api = checkNotNull(api, "api cannot be null");
+            this.resourceAvailable = resourceAvailable;
+        }
+
+        public Predicate<String> create(final String resourceGroup) {
+            checkNotNull(resourceGroup, "resourceGroup cannot be null");
+            return new Predicate<String>() {
+                @Override
+                public boolean apply(final String name) {
+                    checkNotNull(name, "name cannot be null");
+                    return resourceAvailable.apply(new Supplier<Provisionable>() {
+                        @Override
+                        public Provisionable get() {
+                            Image img = api.getVirtualMachineImageApi(resourceGroup).get(name);
+                            return img == null ? null : img.properties();
+                        }
+                    });
+                }
+            };
+        }
+    }
+
+    @Provides
+    @Named(VAULT_DELETE_STATUS)
+    protected VaultPredicates.DeletedVaultStatusPredicateFactory provideDeletedVaultStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                           @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                           final PollPeriod pollPeriod) {
+        return new VaultPredicates.DeletedVaultStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    public static class VaultPredicates {
+        public static class DeletedVaultStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            DeletedVaultStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final boolean shouldBePresent) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        boolean present = false;
+                        List<Vault.DeletedVault> vaults = api.getVaultApi(resourceGroup).listDeletedVaults();
+                        return shouldBePresent == Iterables.any(vaults, new Predicate<Vault.DeletedVault>() {
+                            @Override public boolean apply(Vault.DeletedVault input) {
+                                return input.name().equals(name);
+                            }
+                        });
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+    }
+
+    @Provides
+    @Named(VAULT_KEY_DELETED_STATUS)
+    protected VaultKeyPredicates.DeletedKeyStatusPredicateFactory provideDeletedKeyStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                          @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                          final PollPeriod pollPeriod) {
+        return new VaultKeyPredicates.DeletedKeyStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(VAULT_KEY_RECOVERABLE_STATUS)
+    protected VaultKeyPredicates.RecoverableKeyStatusPredicateFactory provideRecoverableKeyStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                  @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                  final PollPeriod pollPeriod) {
+        return new VaultKeyPredicates.RecoverableKeyStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    public static class VaultKeyPredicates {
+        public static class DeletedKeyStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            DeletedKeyStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean shouldBePresent) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        boolean present = false;
+                        DeletedKeyBundle key = api.getVaultApi(resourceGroup).getDeletedKey(vaultUri, name);
+                        return shouldBePresent == (key != null);
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+
+        public static class RecoverableKeyStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            RecoverableKeyStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean isRecovered) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        boolean result = false;
+                        KeyBundle key = api.getVaultApi(resourceGroup).getKey(vaultUri, name);
+                        return key != null ? (isRecovered ? true : key.attributes().recoveryLevel().contains("Recoverable")) : false;
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+    }
+
+    @Provides
+    @Named(VAULT_SECRET_DELETE_STATUS)
+    protected VaultSecretPredicates.DeletedSecretStatusPredicateFactory provideDeletedSecretStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                   @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                   final PollPeriod pollPeriod) {
+        return new VaultSecretPredicates.DeletedSecretStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(VAULT_SECRET_RECOVERABLE_STATUS)
+    protected VaultSecretPredicates.RecoverableSecretStatusPredicateFactory provideRecoverableSecretStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                           @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                           final PollPeriod pollPeriod) {
+        return new VaultSecretPredicates.RecoverableSecretStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    public static class VaultSecretPredicates {
+        public static class DeletedSecretStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            DeletedSecretStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean shouldBePresent) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        boolean present = false;
+                        checkNotNull(name, "name cannot be null");
+                        DeletedSecretBundle secret = api.getVaultApi(resourceGroup).getDeletedSecret(vaultUri, name);
+                        return shouldBePresent == (secret != null);
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+
+        public static class RecoverableSecretStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            RecoverableSecretStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean isRecovered) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        SecretBundle secret = api.getVaultApi(resourceGroup).getSecret(vaultUri, name, null);
+                        return secret != null ? (isRecovered ? true : secret.attributes().recoveryLevel().contains("Recoverable")) : false;
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+    }
+
+    @Provides
+    @Named(VAULT_CERTIFICATE_DELETE_STATUS)
+    protected VaultCertificatePredicates.DeletedCertificateStatusPredicateFactory provideDeletedCertificateStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                                  @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                                  final PollPeriod pollPeriod) {
+        return new VaultCertificatePredicates.DeletedCertificateStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(VAULT_CERTIFICATE_RECOVERABLE_STATUS)
+    protected VaultCertificatePredicates.RecoverableCertificateStatusPredicateFactory provideRecoverableCertificateStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                                          @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                                          final PollPeriod pollPeriod) {
+        return new VaultCertificatePredicates.RecoverableCertificateStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(VAULT_CERTIFICATE_OPERATION_STATUS)
+    protected VaultCertificatePredicates.CertificateOperationStatusPredicateFactory provideCertificateOperationStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                                      @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                                      final PollPeriod pollPeriod) {
+        return new VaultCertificatePredicates.CertificateOperationStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    public static class VaultCertificatePredicates {
+        public static class DeletedCertificateStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            DeletedCertificateStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean shouldBePresent) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        boolean present = false;
+                        checkNotNull(name, "name cannot be null");
+                        DeletedCertificateBundle cert = api.getVaultApi(resourceGroup).getDeletedCertificate(vaultUri, name);
+                        return shouldBePresent == (cert != null);
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+
+        public static class RecoverableCertificateStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            RecoverableCertificateStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean isImport) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        CertificateBundle cert = api.getVaultApi(resourceGroup).getCertificate(vaultUri, name, null);
+                        return cert != null ? (isImport ? true : cert.attributes().recoveryLevel().contains("Recoverable")) : false;
+
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+
+        public static class CertificateOperationStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            CertificateOperationStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean isCreate) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        boolean result = false;
+                        CertificateOperation certOp = api.getVaultApi(resourceGroup).getCertificateOperation(vaultUri, name);
+                        return isCreate ? ((certOp != null) ? !certOp.status().equals("inProgress") : false) : (certOp == null);
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java
index 2b07406..7c11642 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java
@@ -18,6 +18,8 @@ package org.jclouds.azurecompute.arm.compute.domain;
 
 import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
 
+import java.util.Arrays;
+
 import com.google.auto.value.AutoValue;
 import com.google.common.base.Objects;
 
@@ -28,6 +30,7 @@ public abstract class ResourceGroupAndNameAndIngressRules {
    
    public abstract String location();
 
+   @SuppressWarnings("mutable")
    public abstract int[] inboundPorts();
 
    ResourceGroupAndNameAndIngressRules() {
@@ -37,7 +40,7 @@ public abstract class ResourceGroupAndNameAndIngressRules {
    public static ResourceGroupAndNameAndIngressRules create(String resourceGroup, String location, String name,
          int[] inboundPorts) {
       return new AutoValue_ResourceGroupAndNameAndIngressRules(fromResourceGroupAndName(resourceGroup, name), location,
-            inboundPorts);
+            Arrays.copyOf(inboundPorts, inboundPorts.length));
    }
 
    public String name() {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
index d826a51..6cba2c4 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
@@ -30,8 +30,8 @@ import javax.annotation.Resource;
 
 import org.jclouds.Constants;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.ImageAvailablePredicateFactory;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.VirtualMachineInStatePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.ImageAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VirtualMachineInStatePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
 import org.jclouds.azurecompute.arm.domain.IdReference;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
index eaf820c..b31e2a0 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
@@ -36,7 +36,7 @@ import javax.inject.Inject;
 import javax.inject.Named;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.SecurityGroupAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.SecurityGroupAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
index 98732d2..baba6f9 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
@@ -29,7 +29,7 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.SecurityGroupAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.SecurityGroupAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
index 4ac5eaa..abe057d 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
@@ -34,4 +34,13 @@ public class AzureComputeProperties {
 
    public static final String API_VERSION_PREFIX = "jclouds.azurecompute.arm.apiversion.";
 
+   // Predicate constants
+   public static final String VAULT_DELETE_STATUS = "jclouds.azurecompute.arm.vault.delete_status";
+   public static final String VAULT_KEY_DELETED_STATUS = "jclouds.azurecompute.arm.vault.key.delete_status";
+   public static final String VAULT_KEY_RECOVERABLE_STATUS = "jclouds.azurecompute.arm.vault.key.recoverable_status";
+   public static final String VAULT_SECRET_DELETE_STATUS = "jclouds.azurecompute.arm.vault.secret.delete_status";
+   public static final String VAULT_SECRET_RECOVERABLE_STATUS = "jclouds.azurecompute.arm.vault.secret.recoverable_status";
+   public static final String VAULT_CERTIFICATE_DELETE_STATUS = "jclouds.azurecompute.arm.vault.certificate.delete_status";
+   public static final String VAULT_CERTIFICATE_RECOVERABLE_STATUS = "jclouds.azurecompute.arm.vault.certificate.recoverable_status";
+   public static final String VAULT_CERTIFICATE_OPERATION_STATUS = "jclouds.azurecompute.arm.vault.certificate.operation_status";
 }


[40/50] [abbrv] jclouds git commit: Rename GraphRBAC live test class

Posted by na...@apache.org.
Rename GraphRBAC live test class


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

Branch: refs/heads/master
Commit: ac5f3a1452b76d4d3d4c22ce7b4796c1965550ec
Parents: 3efce9a
Author: Ignasi Barrera <na...@apache.org>
Authored: Tue Dec 5 09:39:39 2017 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Tue Dec 5 09:39:39 2017 +0100

----------------------------------------------------------------------
 .../CurrentServicePrincipalApiLiveTest.java     | 34 -----------------
 .../arm/features/GraphRBACApiLiveTest.java      | 39 ++++++++++++++++++++
 2 files changed, 39 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/ac5f3a14/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/CurrentServicePrincipalApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/CurrentServicePrincipalApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/CurrentServicePrincipalApiLiveTest.java
deleted file mode 100644
index 50a1e11..0000000
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/CurrentServicePrincipalApiLiveTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azurecompute.arm.features;
-
-import static org.testng.Assert.assertEquals;
-
-import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
-import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
-import org.testng.annotations.Test;
-
-@Test(groups = "live", testName = "CurrentServicePrincipalApiLiveTest", singleThreaded = true)
-public class CurrentServicePrincipalApiLiveTest extends BaseAzureComputeApiLiveTest {
-
-   @Test
-   public void testGetCurrentServicePrincipal() {
-      ServicePrincipal currentUser = api.getServicePrincipal().get();
-      assertEquals(currentUser.appId(), identity);
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/ac5f3a14/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/GraphRBACApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/GraphRBACApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/GraphRBACApiLiveTest.java
new file mode 100644
index 0000000..ca6ce5e
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/GraphRBACApiLiveTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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 org.testng.Assert.assertEquals;
+
+import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "GraphRBACApiLiveTest", singleThreaded = true)
+public class GraphRBACApiLiveTest extends BaseAzureComputeApiLiveTest {
+
+   @Test
+   public void testGetCurrentServicePrincipalSupplier() {
+      ServicePrincipal currentUser = api.getServicePrincipal().get();
+      assertEquals(currentUser.appId(), identity);
+   }
+
+   @Test
+   public void testGetCurrentServicePrincipal() {
+      ServicePrincipal currentUser = api.getGraphRBACApi().getCurrentServicePrincipal();
+      assertEquals(currentUser.appId(), identity);
+   }
+}


[29/50] [abbrv] jclouds git commit: remove overrides from AzureComputeService for destroyNode and destroyNodesMatching

Posted by na...@apache.org.
remove overrides from AzureComputeService for destroyNode and destroyNodesMatching

- uses https://github.com/jclouds/jclouds/pull/1135


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

Branch: refs/heads/master
Commit: 79daee361aa5acca298f16e7fa38a520bbc0c0eb
Parents: fd00c7d
Author: Andrea Turli <an...@gmail.com>
Authored: Wed Sep 6 11:46:10 2017 +0200
Committer: Andrea Turli <an...@gmail.com>
Committed: Wed Sep 6 12:07:17 2017 +0200

----------------------------------------------------------------------
 .../arm/compute/AzureComputeService.java        | 36 +++-----------------
 1 file changed, 5 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/79daee36/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
index e82110a..e676460 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
@@ -16,13 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Sets.newHashSet;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
-import static org.jclouds.compute.predicates.NodePredicates.all;
-
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -69,6 +62,10 @@ import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.ListeningExecutorService;
 
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+
 @Singleton
 public class AzureComputeService extends BaseComputeService {
    private final CleanupResources cleanupResources;
@@ -127,28 +124,5 @@ public class AzureComputeService extends BaseComputeService {
          cleanupResources.deleteResourceGroupIfEmpty(resourceGroup);
       }
    }
-
-   @Override
-   public void destroyNode(String id) {
-      // Azure ARM does not return TERMINATED nodes, so in practice no node will never reach the TERMINATED
-      // state, and the deleted nodes will never be returned.
-      // In order to be able to clean up the resources associated to the deleted nodes, we have to retrieve
-      // the details of the nodes before deleting them.
-      NodeMetadata nodeMetadataBeforeDelete = getNodeMetadata(id);
-      super.destroyNode(id);
-      //Node metadata is null after deletion but we still need to clean up incidental resources
-      cleanUpIncidentalResourcesOfDeadNodes(ImmutableSet.of(nodeMetadataBeforeDelete));
-   }
-
-   @Override
-   public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<? super NodeMetadata> filter) {
-      // Azure ARM does not return TERMINATED nodes, so in practice no node will never reach the TERMINATED
-      // state, and the deleted nodes will never be returned.
-      // In order to be able to clean up the resources associated to the deleted nodes, we have to retrieve
-      // the details of the nodes before deleting them.
-      Set<? extends NodeMetadata> nodes = newHashSet(filter(listNodesDetailsMatching(all()), filter));
-      super.destroyNodesMatching(filter); // This returns an empty list (a list of null elements) in Azure ARM, as the api does not return deleted nodes
-      cleanUpIncidentalResourcesOfDeadNodes(nodes);
-      return nodes;
-   }
+   
 }


[05/50] [abbrv] jclouds git commit: Update ImageExtension to work with Managed Disks

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
index ccf1e70..cecdc01 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
@@ -16,6 +16,12 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -24,7 +30,6 @@ import java.util.List;
 import java.util.Map;
 
 import org.jclouds.azurecompute.arm.domain.DataDisk;
-import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
 import org.jclouds.azurecompute.arm.domain.HardwareProfile;
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.ImageReference;
@@ -37,6 +42,7 @@ 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.ResourceDefinition;
+import org.jclouds.azurecompute.arm.domain.StorageAccountType;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
 import org.jclouds.azurecompute.arm.domain.StorageService;
 import org.jclouds.azurecompute.arm.domain.Subnet;
@@ -45,8 +51,8 @@ import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.PowerState;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
+import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
-import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -55,20 +61,12 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.jclouds.util.Predicates2.retry;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
 @Test(groups = "live", testName = "VirtualMachineApiLiveTest")
 public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
 
    private String subscriptionid;
-   private String storageServiceName;
    private String vmName;
    private String nicName;
-   private StorageService storageService;
    private String virtualNetworkName;
    private String subnetId;
 
@@ -81,9 +79,6 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
       createTestResourceGroup();
       virtualNetworkName = String.format("vn-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
 
-      storageServiceName = String.format("st%s%s", System.getProperty("user.name"), RAND);
-      storageService = createStorageService(resourceGroupName, storageServiceName, LOCATION);
-
       // Subnets belong to a virtual network so that needs to be created first
       assertNotNull(createDefaultVirtualNetwork(resourceGroupName, virtualNetworkName, "10.2.0.0/16", LOCATION));
 
@@ -103,25 +98,10 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
 
    @Test
    public void testCreate() {
-      String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
-
-      VirtualMachine vm = api().createOrUpdate(vmName, LOCATION, getProperties(blob, nicName),
+      VirtualMachine vm = api().createOrUpdate(vmName, LOCATION, getProperties(nicName, null),
             Collections.<String, String> emptyMap(), null);
       assertTrue(!vm.name().isEmpty());
-
-      //Poll until resource is ready to be used
-      boolean jobDone = retry(new Predicate<String>() {
-         @Override
-         public boolean apply(String name) {
-            return !api().get(name).properties().provisioningState().equals(VirtualMachineProperties.ProvisioningState.CREATING);
-         }
-      }, 60 * 20 * 1000).apply(vmName);
-      assertTrue(jobDone, "createOrUpdate operation did not complete in the configured timeout");
-
-      VirtualMachineProperties.ProvisioningState status = api().get(vmName).properties().provisioningState();
-      // Cannot be creating anymore. Should be succeeded or running but not failed.
-      assertThat(status).isNotEqualTo(VirtualMachineProperties.ProvisioningState.CREATING);
-      assertThat(status).isNotEqualTo(VirtualMachineProperties.ProvisioningState.FAILED);
+      waitUntilReady(vmName);
    }
 
    @Test(dependsOnMethods = "testCreate")
@@ -139,7 +119,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
    @Test(dependsOnMethods = "testGet")
    public void testStart() {
       api().start(vmName);
-      assertTrue(stateReached(PowerState.RUNNING), "start operation did not complete in the configured timeout");
+      assertTrue(stateReached(vmName, PowerState.RUNNING), "start operation did not complete in the configured timeout");
    }
 
    @Test(dependsOnMethods = "testStart")
@@ -147,15 +127,12 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
       VirtualMachine vm = api().get(vmName);
       VirtualMachineProperties oldProperties = vm.properties();
       StorageProfile oldStorageProfile = oldProperties.storageProfile();
-
-      String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
-      VHD vhd = VHD.create(blob + "vhds/" + vmName + "new-data-disk.vhd");
+      
       DataDisk newDataDisk = DataDisk.builder()
               .name(vmName + "new-data-disk")
               .diskSizeGB("1")
               .lun(1)
               .createOption(DataDisk.DiskCreateOptionTypes.EMPTY)
-              .vhd(vhd)
               .build();
       List<DataDisk> oldDataDisks = oldStorageProfile.dataDisks();
       assertEquals(oldDataDisks.size(), 1);
@@ -173,15 +150,15 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
    @Test(dependsOnMethods = "testUpdate")
    public void testStop() {
       api().stop(vmName);
-      assertTrue(stateReached(PowerState.STOPPED), "stop operation did not complete in the configured timeout");
+      assertTrue(stateReached(vmName, PowerState.STOPPED), "stop operation did not complete in the configured timeout");
    }
 
    @Test(dependsOnMethods = "testStop")
    public void testRestart() {
       api().start(vmName);
-      assertTrue(stateReached(PowerState.RUNNING), "start operation did not complete in the configured timeout");
+      assertTrue(stateReached(vmName, PowerState.RUNNING), "start operation did not complete in the configured timeout");
       api().restart(vmName);
-      assertTrue(stateReached(PowerState.RUNNING), "restart operation did not complete in the configured timeout");
+      assertTrue(stateReached(vmName, PowerState.RUNNING), "restart operation did not complete in the configured timeout");
    }
 
    @Test(dependsOnMethods = "testCreate")
@@ -201,15 +178,31 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
    @Test(dependsOnMethods = "testRestart")
    public void testGeneralize() throws IllegalStateException {
       api().stop(vmName);
-      assertTrue(stateReached(PowerState.STOPPED), "restart operation did not complete in the configured timeout");
+      assertTrue(stateReached(vmName, PowerState.STOPPED), "restart operation did not complete in the configured timeout");
       api().generalize(vmName);
    }
 
    @SuppressWarnings("unchecked")
-   @Test(dependsOnMethods = "testGeneralize")
+   @Test
    public void testCapture() throws IllegalStateException {
-      URI uri = api().capture(vmName, vmName, vmName);
-      if (uri == null) Assert.fail();
+      // Capture is only allowed for Blob based VMs, so let's create one VM for this test
+      NetworkInterfaceCard nic = createNetworkInterfaceCard(resourceGroupName, "capture-nic-" + RAND, LOCATION, "ipConfig-" + RAND);
+      StorageService storageService = createStorageService(resourceGroupName, "capture" + RAND, LOCATION);
+      String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
+      
+      String captureVmName = "capture-" + RAND;
+      api().createOrUpdate(captureVmName, LOCATION, getProperties(nic.name(), blob),
+            Collections.<String, String> emptyMap(), null);
+      waitUntilReady(captureVmName);
+      
+      api().stop(captureVmName);
+      assertTrue(stateReached(captureVmName, PowerState.STOPPED),
+            "restart operation did not complete in the configured timeout");
+      api().generalize(captureVmName);
+      
+      URI uri = api().capture(captureVmName, captureVmName, captureVmName);
+      assertNotNull(uri);
+      
       if (imageAvailablePredicate.apply(uri)) {
          List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
          if (definitions != null) {
@@ -219,18 +212,13 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
                Map<String, String> properties2 = (Map<String, String>) storageObject;
                Object osDiskObject = properties2.get("osDisk");
                Map<String, String> osProperties = (Map<String, String>) osDiskObject;
-               Object dataDisksObject = properties2.get("dataDisks");
-               List<Object> dataProperties = (List<Object>) dataDisksObject;
-               Map<String, String> datadiskObject = (Map<String, String>) dataProperties.get(0);
-
                assertNotNull(osProperties.get("name"));
-               assertNotNull(datadiskObject.get("name"));
             }
          }
       }
    }
 
-   @Test(dependsOnMethods = "testCapture", alwaysRun = true)
+   @Test(dependsOnMethods = "testGeneralize", alwaysRun = true)
    public void testDelete() throws Exception {
       URI uri = api().delete(vmName);
       assertResourceDeleted(uri);
@@ -240,22 +228,28 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
       return api.getVirtualMachineApi(resourceGroupName);
    }
 
-   private VirtualMachineProperties getProperties(String blob, String nic) {
+   private VirtualMachineProperties getProperties(String nic, String blob) {
 
       HardwareProfile hwProf = HardwareProfile.create("Standard_D1");
       ImageReference imgRef = ImageReference.builder().publisher("MicrosoftWindowsServerEssentials")
               .offer("WindowsServerEssentials").sku("WindowsServerEssentials").version("latest").build();
-      DataDisk dataDisk = DataDisk.builder().name("data").diskSizeGB("100").lun(0).createOption(DataDisk.DiskCreateOptionTypes.EMPTY).build();
-      List<DataDisk> dataDisks = new ArrayList<DataDisk>();
-      dataDisks.add(dataDisk);
-
-      OSDisk osDisk = OSDisk.builder()
+      
+      DataDisk.Builder dataDisk = DataDisk.builder().name("data").diskSizeGB("100").lun(0).createOption(DataDisk.DiskCreateOptionTypes.EMPTY);
+      
+      OSDisk.Builder osDisk = OSDisk.builder()
+              .name("os")
               .osType("Windows")
               .caching(DataDisk.CachingTypes.READ_WRITE.toString())
-              .createOption("FromImage")
-              .managedDiskParameters(ManagedDiskParameters.create(null, ManagedDiskParameters.StorageAccountTypes.STANDARD_LRS.toString()))
-              .build();
-      StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk, dataDisks);
+              .createOption("FromImage");
+      
+      if (blob == null) {
+         osDisk.managedDiskParameters(ManagedDiskParameters.create(null, StorageAccountType.STANDARD_LRS.toString()));
+      } else {
+         osDisk.vhd(VHD.create(blob + "vhds/" + vmName + ".vhd"));
+         dataDisk.vhd(VHD.create(blob + "vhds/" + vmName + "data.vhd"));
+      }
+      
+      StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk.build(), ImmutableList.of(dataDisk.build()));
       OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
               null);
       OSProfile osProfile = OSProfile.create(vmName, "azureuser", "RFe3&432dg", null, null, windowsConfig);
@@ -267,15 +261,12 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
               new ArrayList<IdReference>();
       networkInterfaces.add(networkInterface);
       NetworkProfile networkProfile = NetworkProfile.create(networkInterfaces);
-      DiagnosticsProfile.BootDiagnostics bootDiagnostics =
-              DiagnosticsProfile.BootDiagnostics.create(true, blob);
-      DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics);
       VirtualMachineProperties properties = VirtualMachineProperties.create(null,
-              null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, VirtualMachineProperties.ProvisioningState.CREATING);
+              null, null, hwProf, storageProfile, osProfile, networkProfile, null, VirtualMachineProperties.ProvisioningState.CREATING);
       return properties;
    }
 
-   protected NetworkInterfaceCard createNetworkInterfaceCard(final String resourceGroupName, String networkInterfaceCardName, String locationName, String ipConfigurationName) {
+   private NetworkInterfaceCard createNetworkInterfaceCard(final String resourceGroupName, String networkInterfaceCardName, String locationName, String ipConfigurationName) {
       //Create properties object
       final NetworkInterfaceCardProperties networkInterfaceCardProperties = NetworkInterfaceCardProperties
             .builder()
@@ -286,12 +277,46 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
       final Map<String, String> tags = ImmutableMap.of("jclouds", "livetest");
       return api.getNetworkInterfaceCardApi(resourceGroupName).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, tags);
    }
+   
+   private StorageService createStorageService(final String resourceGroupName, final String storageServiceName,
+         final String location) {
+      URI uri = api.getStorageAccountApi(resourceGroupName).create(storageServiceName, location,
+            ImmutableMap.of("property_name", "property_value"),
+            ImmutableMap.of("accountType", StorageService.AccountType.Standard_LRS.toString()));
+      if (uri != null) {
+         assertTrue(uri.toString().contains("api-version"));
+
+         boolean jobDone = retry(new Predicate<URI>() {
+            @Override
+            public boolean apply(final URI uri) {
+               return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri);
+            }
+         }, 60 * 1 * 1000 /* 1 minute timeout */).apply(uri);
+         assertTrue(jobDone, "create operation did not complete in the configured timeout");
+      }
+      return api.getStorageAccountApi(resourceGroupName).get(storageServiceName);
+   }
 
    private boolean waitForState(String name, final PowerState state) {
       return api().getInstanceDetails(name).powerState().equals(state);
    }
+   
+   private void waitUntilReady(String vmName) {
+      boolean ready = retry(new Predicate<String>() {
+         @Override
+         public boolean apply(String name) {
+            return !api().get(name).properties().provisioningState().equals(VirtualMachineProperties.ProvisioningState.CREATING);
+         }
+      }, 60 * 20 * 1000).apply(vmName);
+      assertTrue(ready, "createOrUpdate operation did not complete in the configured timeout");
+
+      VirtualMachineProperties.ProvisioningState status = api().get(vmName).properties().provisioningState();
+      // Cannot be creating anymore. Should be succeeded or running but not failed.
+      assertThat(status).isNotEqualTo(VirtualMachineProperties.ProvisioningState.CREATING);
+      assertThat(status).isNotEqualTo(VirtualMachineProperties.ProvisioningState.FAILED);
+   }
 
-   private boolean stateReached(final PowerState state) {
+   private boolean stateReached(String vmName, final PowerState state) {
       return retry(new Predicate<String>() {
          @Override
          public boolean apply(String name) {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
index 34b59c3..27e6f6b 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
@@ -233,7 +233,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       assertNotNull(uri);
       assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
             + "/virtualMachines/vm/capture?api-version=2016-04-30-preview",
-            "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\"}");
+            "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\",\"overwriteVhds\":\"true\"}");
    }
 
    public void testCapture404() throws Exception {
@@ -244,7 +244,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       assertNull(uri);
       assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
             + "/virtualMachines/vm/capture?api-version=2016-04-30-preview",
-            "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\"}");
+            "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\",\"overwriteVhds\":\"true\"}");
    }
 
    private VirtualMachineProperties getProperties() {
@@ -252,7 +252,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       ImageReference imgRef = ImageReference.builder().publisher("publisher").offer("offer").sku("sku").version("ver").build();
       VHD vhd = VHD.create("https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd");
       List<DataDisk> dataDisks = new ArrayList<DataDisk>();
-      OSDisk osDisk = OSDisk.create("Windows", "windowsmachine", vhd, "ReadWrite", "FromImage", null, null);
+      OSDisk osDisk = OSDisk.create("Windows", "windowsmachine", vhd, "ReadWrite", "FromImage", null, null, null);
       StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk, dataDisks);
       OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
             null);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
index 6006392..754f5fe 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
@@ -32,21 +32,20 @@ import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
 
 public class AzureLiveTestUtils {
 
-    public static Properties defaultProperties(Properties properties) {
-       properties = properties == null ? new Properties() : properties;
-       properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
-       properties.put(PROPERTY_REGIONS, "westeurope");
-       properties.put(IMAGE_PUBLISHERS, "Canonical");
-       properties.put(RESOURCENAME_PREFIX, "jcloudstest");
-       
-       String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
-       properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);
-       properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout);
-       properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout);
-       properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout);
-       properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout);
-       
-       return properties;
-    }
-}
+   public static Properties defaultProperties(Properties properties, String resourceNamePrefix) {
+      properties = properties == null ? new Properties() : properties;
+      properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
+      properties.put(PROPERTY_REGIONS, "westeurope");
+      properties.put(IMAGE_PUBLISHERS, "Canonical");
+      properties.put(RESOURCENAME_PREFIX, resourceNamePrefix);
+
+      String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
+      properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout);
+      properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout);
 
+      return properties;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
index 0633294..cf65462 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
@@ -38,10 +38,8 @@ import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
 import org.jclouds.azurecompute.arm.domain.Provisionable;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
-import org.jclouds.azurecompute.arm.domain.StorageService;
 import org.jclouds.azurecompute.arm.domain.Subnet;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
-import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
 import org.testng.annotations.AfterClass;
 
 import com.google.common.base.Predicate;
@@ -99,7 +97,7 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
    @Override protected Properties setupProperties() {
       Properties properties = super.setupProperties();
       // for oauth
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
       checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
       return properties;
    }
@@ -139,23 +137,6 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
       return subnet;
    }
 
-   protected StorageService createStorageService(final String resourceGroupName, final String storageServiceName, final String location) {
-      URI uri = api.getStorageAccountApi(resourceGroupName).create(storageServiceName, location, ImmutableMap.of("property_name",
-              "property_value"), ImmutableMap.of("accountType", StorageService.AccountType.Standard_LRS.toString()));
-      if (uri != null) {
-         assertTrue(uri.toString().contains("api-version"));
-
-         boolean jobDone = retry(new Predicate<URI>() {
-            @Override
-            public boolean apply(final URI uri) {
-               return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri);
-            }
-         }, 60 * 1 * 1000 /* 1 minute timeout */).apply(uri);
-         assertTrue(jobDone, "create operation did not complete in the configured timeout");
-      }
-      return api.getStorageAccountApi(resourceGroupName).get(storageServiceName);
-   }
-
    protected void createTestResourceGroup() {
       String name = String.format("rg-%s-%s", this.getClass().getSimpleName().toLowerCase(),
             System.getProperty("user.name"));

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/resources/virtualmachineimagecreate.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachineimagecreate.json b/providers/azurecompute-arm/src/test/resources/virtualmachineimagecreate.json
new file mode 100644
index 0000000..865012f
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachineimagecreate.json
@@ -0,0 +1,21 @@
+{
+  "type": "Microsoft.Compute/images",
+  "location": "canadaeast",
+  "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/images/testVirtualMachineImage",
+  "name": "testVirtualMachineImage",
+  "properties": {
+    "sourceVirtualMachine": {
+      "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/virtualMachines/vm2image"
+    },
+    "storageProfile": {
+      "osDisk": {
+        "osType": "Linux",
+        "osState": "Generalized",
+        "blobUri": "https://jcloudstestcanadaeast982.blob.core.windows.net/vhds/vm2image20170315140332.vhd",
+        "caching": "ReadWrite"
+      },
+      "dataDisks": []
+    },
+    "provisioningState": "Succeeded"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/resources/virtualmachineimageget.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachineimageget.json b/providers/azurecompute-arm/src/test/resources/virtualmachineimageget.json
new file mode 100644
index 0000000..865012f
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachineimageget.json
@@ -0,0 +1,21 @@
+{
+  "type": "Microsoft.Compute/images",
+  "location": "canadaeast",
+  "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/images/testVirtualMachineImage",
+  "name": "testVirtualMachineImage",
+  "properties": {
+    "sourceVirtualMachine": {
+      "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/virtualMachines/vm2image"
+    },
+    "storageProfile": {
+      "osDisk": {
+        "osType": "Linux",
+        "osState": "Generalized",
+        "blobUri": "https://jcloudstestcanadaeast982.blob.core.windows.net/vhds/vm2image20170315140332.vhd",
+        "caching": "ReadWrite"
+      },
+      "dataDisks": []
+    },
+    "provisioningState": "Succeeded"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/test/resources/virtualmachineimagelist.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachineimagelist.json b/providers/azurecompute-arm/src/test/resources/virtualmachineimagelist.json
new file mode 100644
index 0000000..cf4d3ea
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachineimagelist.json
@@ -0,0 +1,25 @@
+{
+  "value": [
+    {
+      "type": "Microsoft.Compute/images",
+      "location": "canadaeast",
+      "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/images/imageFromRest",
+      "name": "testVirtualMachineImage",
+      "properties": {
+        "sourceVirtualMachine": {
+          "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/virtualMachines/vm2image"
+        },
+        "storageProfile": {
+          "osDisk": {
+            "osType": "Linux",
+            "osState": "Generalized",
+            "blobUri": "https://jcloudstestcanadaeast982.blob.core.windows.net/vhds/vm2image20170315140332.vhd",
+            "caching": "ReadWrite"
+          },
+          "dataDisks": []
+        },
+        "provisioningState": "Succeeded"
+      }
+    }
+  ]
+}
\ No newline at end of file


[31/50] [abbrv] jclouds git commit: JCLOUDS-1282: Add back support for Azure ARM custom data

Posted by na...@apache.org.
JCLOUDS-1282: Add back support for Azure ARM custom data


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

Branch: refs/heads/master
Commit: 7d3b1bebd5d40fcc1532ffbe264cdd31ee623f2f
Parents: b0abfa4
Author: Vikas Rangarajan <vi...@cable.comcast.com>
Authored: Fri May 26 16:16:35 2017 -0500
Committer: Ignasi Barrera <na...@apache.org>
Committed: Fri Sep 29 11:29:08 2017 +0200

----------------------------------------------------------------------
 .../arm/compute/AzureComputeServiceAdapter.java |   8 +-
 .../compute/options/AzureTemplateOptions.java   | 128 +++++++++++++------
 2 files changed, 94 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/7d3b1beb/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 213d438..37585e2 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -99,6 +99,7 @@ import com.google.common.base.Function;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
 import com.google.common.base.Supplier;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
@@ -381,7 +382,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       OSProfile.Builder builder = OSProfile.builder().adminUsername(adminUsername).adminPassword(adminPassword)
               .computerName(computerName);
 
-      if (template.getOptions().getPublicKey() != null
+      if (!Strings.isNullOrEmpty(template.getOptions().getPublicKey())
               && OsFamily.WINDOWS != template.getImage().getOperatingSystem().getFamily()) {
          OSProfile.LinuxConfiguration linuxConfiguration = OSProfile.LinuxConfiguration.create("true",
                  OSProfile.LinuxConfiguration.SSH.create(of(
@@ -391,7 +392,6 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
          builder.linuxConfiguration(linuxConfiguration);
       }
 
-
       AzureTemplateOptions azureTemplateOptions = template.getOptions().as(AzureTemplateOptions.class);
 
       if (azureTemplateOptions.getWindowsConfiguration() != null) {
@@ -402,6 +402,10 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
           builder.secrets(azureTemplateOptions.getSecrets());
       }
 
+      if (!Strings.isNullOrEmpty(azureTemplateOptions.getCustomData())) {
+         builder.customData(azureTemplateOptions.getCustomData());
+      }
+
       return builder.build();
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7d3b1beb/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
index 92f592e..b551811 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
@@ -42,7 +42,8 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
    private List<IpOptions> ipOptions = ImmutableList.of();
    private WindowsConfiguration windowsConfiguration;
    private List<Secrets> secrets = ImmutableList.of();
-   
+   private String customData;
+
    /**
     * Sets the availability set where the nodes will be configured. If it does
     * not exist jclouds will create a new one with the given configuration.
@@ -60,7 +61,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       this.availabilitySetName = availabilitySetName;
       return this;
    }
-   
+
    /**
     * The resource group where the new resources will be created.
     */
@@ -79,7 +80,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
    public AzureTemplateOptions dataDisks(DataDisk... dataDisks) {
       return dataDisks(ImmutableList.copyOf(checkNotNull(dataDisks, "dataDisks")));
    }
-   
+
    /**
     * Configure the NICs that will be attached to the created nodes.
     * <p>
@@ -99,6 +100,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
 
    /**
     * @see {@link AzureTemplateOptions#ipOptions(Iterable)
+
     */
    public AzureTemplateOptions ipOptions(IpOptions... ipOptions) {
       return ipOptions(ImmutableList.copyOf(checkNotNull(ipOptions, "ipOptions")));
@@ -107,32 +109,66 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
    /**
     * Windows configuration parameters
     *
-    * @see <a href="https://docs.microsoft.com/en-us/rest/api/compute/virtualmachines/virtualmachines-create-or-update#bk_windowsconfig5">docs</a>
+    * @see <a
+    *      href="https://docs.microsoft.com/en-us/rest/api/compute/virtualmachines/virtualmachines-create-or-update#bk_windowsconfig5">docs</a>
     */
    public AzureTemplateOptions windowsConfiguration(WindowsConfiguration windowsConfiguration) {
-       this.windowsConfiguration = windowsConfiguration;
-       return this;
-    }
+      this.windowsConfiguration = windowsConfiguration;
+      return this;
+   }
 
    /**
     * Import certificates in the Windows Certificate Store
     *
-    * @see <a href="https://docs.microsoft.com/en-us/rest/api/compute/virtualmachines/virtualmachines-create-or-update#bk_srcvault">docs</a>
+    * @see <a
+    *      href="https://docs.microsoft.com/en-us/rest/api/compute/virtualmachines/virtualmachines-create-or-update#bk_srcvault">docs</a>
     */
    public AzureTemplateOptions secrets(Iterable<? extends Secrets> secrets) {
-       for (Secrets secret : checkNotNull(secrets, "secrets"))
-           checkNotNull(secret, "secrets can not be empty");
-       this.secrets = ImmutableList.copyOf(secrets);
-       return this;
-    }
-
-   public AvailabilitySet getAvailabilitySet() { return availabilitySet; }
-   public String getAvailabilitySetName() { return availabilitySetName; }
-   public List<DataDisk> getDataDisks() { return dataDisks; }
-   public String getResourceGroup() { return resourceGroup; }
-   public List<IpOptions> getIpOptions() { return ipOptions; }
-   public WindowsConfiguration getWindowsConfiguration() { return windowsConfiguration; }
-   public List<Secrets> getSecrets() { return secrets; }
+      for (Secrets secret : checkNotNull(secrets, "secrets"))
+         checkNotNull(secret, "secrets can not be empty");
+      this.secrets = ImmutableList.copyOf(secrets);
+      return this;
+   }
+
+   /**
+    * Custom data (for cloud-init) for the Azure ARM API
+    */
+   public AzureTemplateOptions customData(String customData) {
+      this.customData = customData;
+      return this;
+   }
+
+   public AvailabilitySet getAvailabilitySet() {
+      return availabilitySet;
+   }
+
+   public String getAvailabilitySetName() {
+      return availabilitySetName;
+   }
+
+   public List<DataDisk> getDataDisks() {
+      return dataDisks;
+   }
+
+   public String getResourceGroup() {
+      return resourceGroup;
+   }
+
+   public List<IpOptions> getIpOptions() {
+      return ipOptions;
+   }
+
+   public WindowsConfiguration getWindowsConfiguration() {
+      return windowsConfiguration;
+   }
+
+   public List<Secrets> getSecrets() {
+      return secrets;
+   }
+
+   public String getCustomData() {
+      return customData;
+   }
 
    @Override
    public AzureTemplateOptions clone() {
@@ -153,30 +189,32 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          eTo.ipOptions(ipOptions);
          eTo.windowsConfiguration(windowsConfiguration);
          eTo.secrets(secrets);
+         eTo.customData(customData);
       }
    }
 
    @Override
    public boolean equals(Object o) {
-      if (this == o) return true;
-      if (!(o instanceof AzureTemplateOptions)) return false;
-      if (!super.equals(o)) return false;
+      if (this == o)
+         return true;
+      if (!(o instanceof AzureTemplateOptions))
+         return false;
+      if (!super.equals(o))
+         return false;
 
       AzureTemplateOptions that = (AzureTemplateOptions) o;
-      
-      return Objects.equal(availabilitySetName, that.availabilitySetName) &&
-            Objects.equal(resourceGroup, that.resourceGroup) &&
-            Objects.equal(availabilitySet, that.availabilitySet) &&
-            Objects.equal(dataDisks, that.dataDisks) &&
-            Objects.equal(ipOptions, that.ipOptions) &&
-            Objects.equal(windowsConfiguration, that.windowsConfiguration) &&
-            Objects.equal(secrets, that.secrets);
+
+      return Objects.equal(availabilitySetName, that.availabilitySetName)
+            && Objects.equal(resourceGroup, that.resourceGroup) && Objects.equal(availabilitySet, that.availabilitySet)
+            && Objects.equal(dataDisks, that.dataDisks) && Objects.equal(ipOptions, that.ipOptions)
+            && Objects.equal(windowsConfiguration, that.windowsConfiguration) && Objects.equal(secrets, that.secrets)
+            && Objects.equal(this.customData, that.customData);
    }
 
    @Override
    public int hashCode() {
-      return Objects.hashCode(availabilitySet, availabilitySetName, dataDisks,
-            resourceGroup, ipOptions);
+      return Objects.hashCode(super.hashCode(), availabilitySet, availabilitySetName, dataDisks, resourceGroup,
+            ipOptions, customData);
    }
 
    @Override
@@ -193,14 +231,16 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       if (!ipOptions.isEmpty())
          toString.add("ipOptions", ipOptions);
       if (windowsConfiguration != null)
-          toString.add("windowsConfiguration", windowsConfiguration);
+         toString.add("windowsConfiguration", windowsConfiguration);
       if (!secrets.isEmpty())
-          toString.add("secrets", secrets);
+         toString.add("secrets", secrets);
+      if (customData != null)
+         toString.add("customData", customData);
       return toString;
    }
 
    public static class Builder {
-      
+
       /**
        * @see AzureTemplateOptions#availabilitySet(AvailabilitySet)
        */
@@ -208,7 +248,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          AzureTemplateOptions options = new AzureTemplateOptions();
          return options.availabilitySet(availabilitySet);
       }
-      
+
       /**
        * @see AzureTemplateOptions#availabilitySet(String)
        */
@@ -232,7 +272,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          AzureTemplateOptions options = new AzureTemplateOptions();
          return options.dataDisks(dataDisks);
       }
-      
+
       /**
        * @see AzureTemplateOptions#resourceGroup(String)
        */
@@ -240,7 +280,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          AzureTemplateOptions options = new AzureTemplateOptions();
          return options.resourceGroup(resourceGroup);
       }
-      
+
       /**
        * @see AzureTemplateOptions#ipOptions(IpOptions...)
        */
@@ -272,5 +312,13 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          AzureTemplateOptions options = new AzureTemplateOptions();
          return options.secrets(secrets);
       }
+
+      /**
+       * @see AzureTemplateOptions#customData
+       */
+      public static AzureTemplateOptions customData(String customData) {
+         AzureTemplateOptions options = new AzureTemplateOptions();
+         return options.customData(customData);
+      }
    }
 }


[34/50] [abbrv] jclouds git commit: Azure ARM fix OSProfile domain object

Posted by na...@apache.org.
Azure ARM fix OSProfile domain object


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

Branch: refs/heads/master
Commit: af79f8f812962fd658753586783b690e89dabb88
Parents: bc520cf
Author: Andrea Turli <an...@apache.org>
Authored: Thu Oct 26 11:49:13 2017 +0200
Committer: Andrea Turli <an...@apache.org>
Committed: Thu Oct 26 12:02:25 2017 +0200

----------------------------------------------------------------------
 .../main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/af79f8f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
index 3f5a0bc..67c1ad3 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
@@ -148,7 +148,7 @@ public abstract class OSProfile {
 
          public abstract String settingName();
 
-         public abstract String content();
+         @Nullable public abstract String content();
 
          @SerializedNames({"passName", "componentName", "settingName", "content"})
          public static AdditionalUnattendContent create(final String passName, final String componentName,


[22/50] [abbrv] jclouds git commit: Fix SGE.removeSecurityGroup for when the SG doesn't exist

Posted by na...@apache.org.
Fix SGE.removeSecurityGroup for when the SG doesn't exist


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

Branch: refs/heads/master
Commit: cb556428e36543abb40035554e5bad685e6af0d2
Parents: f086c05
Author: Svetoslav Neykov <sv...@neykov.name>
Authored: Thu Jul 6 10:51:27 2017 +0300
Committer: Svetoslav Neykov <sv...@neykov.name>
Committed: Fri Jul 7 10:37:03 2017 +0300

----------------------------------------------------------------------
 .../extensions/AzureComputeSecurityGroupExtension.java    | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/cb556428/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
index 50cb75a..eaf820c 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
@@ -190,7 +190,15 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
       final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
       URI uri = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup())
             .delete(resourceGroupAndName.name());
-      return resourceDeleted.apply(uri);
+
+      // https://docs.microsoft.com/en-us/rest/api/network/virtualnetwork/delete-a-network-security-group
+      if (uri != null) {
+         // 202-Accepted if resource exists and the request is accepted.
+         return resourceDeleted.apply(uri);
+      } else {
+         // 204-No Content if resource does not exist.
+         return false;
+      }
    }
 
    @Override


[23/50] [abbrv] jclouds git commit: Generate Azure VM password on the fly

Posted by na...@apache.org.
Generate Azure VM password on the fly


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

Branch: refs/heads/master
Commit: 180efdf799c3df627f5538aae0b9429fa173b935
Parents: cb55642
Author: Svetoslav Neykov <sv...@neykov.name>
Authored: Wed Jul 12 08:08:54 2017 +0300
Committer: Svetoslav Neykov <sv...@neykov.name>
Committed: Wed Jul 12 14:50:06 2017 +0300

----------------------------------------------------------------------
 .../arm/AzureComputeProviderMetadata.java       |  5 +--
 .../arm/compute/AzureComputeServiceAdapter.java | 11 ++++---
 .../CreateResourcesThenCreateNodes.java         | 15 +++++++++
 .../azurecompute/arm/util/Passwords.java        | 32 ++++++++++++++++++++
 4 files changed, 56 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/180efdf7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index 6a5c587..a866ffb 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -94,8 +94,9 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(RESOURCENAME_PREFIX, "jclouds");
       properties.put(RESOURCENAME_DELIMITER, "-");
       properties.put(IMAGE_PUBLISHERS, "Canonical,RedHat");
-      // Default credentials for all images
-      properties.put(IMAGE_LOGIN_USER, "jclouds:Password12345!");
+      // Default credentials for all images, Azure doesn't accept root, admin; generate the password on the fly
+      properties.put(IMAGE_LOGIN_USER, "jclouds");
+      // Azure allows for passwordless sudo only when using a public key to login to the machine
       properties.put(IMAGE_AUTHENTICATE_SUDO, "true");
       properties.put(TEMPLATE, "imageNameMatches=UbuntuServer,osVersionMatches=1[456]\\.[01][04](\\.[0-9])?-LTS");
       // Api versions used in each API

http://git-wip-us.apache.org/repos/asf/jclouds/blob/180efdf7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index ccb748a..0a37d5d 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -375,18 +375,19 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
 
    private OSProfile createOsProfile(String computerName, Template template) {
       String defaultLoginUser = template.getImage().getDefaultCredentials().getUser();
-      String defaultLoginPassword = template.getImage().getDefaultCredentials().getOptionalPassword().get();
       String adminUsername = Objects.firstNonNull(template.getOptions().getLoginUser(), defaultLoginUser);
-      String adminPassword = Objects.firstNonNull(template.getOptions().getLoginPassword(), defaultLoginPassword);
+      // Password already generated in CreateResourcesThenCreateNodes (if not set by user)
+      String adminPassword = template.getOptions().getLoginPassword();
       OSProfile.Builder builder = OSProfile.builder().adminUsername(adminUsername).adminPassword(adminPassword)
               .computerName(computerName);
 
       if (template.getOptions().getPublicKey() != null
               && OsFamily.WINDOWS != template.getImage().getOperatingSystem().getFamily()) {
          OSProfile.LinuxConfiguration linuxConfiguration = OSProfile.LinuxConfiguration.create("true",
-                 OSProfile.LinuxConfiguration.SSH.create(of(OSProfile.LinuxConfiguration.SSH.SSHPublicKey
-                         .create(String.format("/home/%s/.ssh/authorized_keys", adminUsername), template.getOptions()
-                                 .getPublicKey()))));
+                 OSProfile.LinuxConfiguration.SSH.create(of(
+                         OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create(
+                                 String.format("/home/%s/.ssh/authorized_keys", adminUsername),
+                                 template.getOptions().getPublicKey()))));
          builder.linuxConfiguration(linuxConfiguration);
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/180efdf7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
index 2ddb340..e1d346c 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
@@ -34,6 +34,7 @@ import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import com.google.common.base.Optional;
 import org.jclouds.Constants;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
@@ -49,10 +50,12 @@ import org.jclouds.azurecompute.arm.domain.Subnet;
 import org.jclouds.azurecompute.arm.domain.Subnet.SubnetProperties;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork.AddressSpace;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork.VirtualNetworkProperties;
+import org.jclouds.azurecompute.arm.util.Passwords;
 import org.jclouds.compute.config.CustomizationResponse;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.options.TemplateOptions;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
 import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
@@ -108,6 +111,9 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
          Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
 
       AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class);
+
+      // TODO Generate a private key instead. Also no need to use AUTHENTICATE_SUDO in this case.
+      generatePasswordIfNoneProvided(template);
       
       // If there is a script to be run on the node and public key
       // authentication has been configured, warn users if the private key
@@ -130,6 +136,15 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
       return super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
    }
 
+   // Azure requires that we pass it the VM password. Need to generate one if not overridden by the user.
+   private void generatePasswordIfNoneProvided(Template template) {
+      TemplateOptions options = template.getOptions();
+      if (options.getLoginPassword() == null) {
+         Optional<String> passwordOptional = template.getImage().getDefaultCredentials().getOptionalPassword();
+         options.overrideLoginPassword(passwordOptional.or(Passwords.generate()));
+      }
+   }
+
    protected synchronized void createDefaultNetworkIfNeeded(String group, String location, AzureTemplateOptions options) {
       if (options.getIpOptions().isEmpty()) {
          String name = namingConvention.create().sharedNameForGroup(group);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/180efdf7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/Passwords.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/Passwords.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/Passwords.java
new file mode 100644
index 0000000..9bc189e
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/Passwords.java
@@ -0,0 +1,32 @@
+/*
+ * 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.io.BaseEncoding;
+
+import java.util.Random;
+
+// Seems to be a common theme between providers, perhaps should be provided by core (see other 'Passwords' classes)
+public class Passwords {
+    private static final Random random = new Random();
+
+    public static String generate() {
+        final byte[] buffer = new byte[15];
+        random.nextBytes(buffer);
+        return BaseEncoding.base64Url().omitPadding().encode(buffer);
+    }
+}


[50/50] [abbrv] jclouds git commit: Update maven coordinates for promoted Azure ARM

Posted by na...@apache.org.
Update maven coordinates for promoted Azure ARM


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

Branch: refs/heads/master
Commit: 3877303ede35a243de6bfba61ed56196f6523daa
Parents: cc96905
Author: Ignasi Barrera <na...@apache.org>
Authored: Mon Jan 8 15:03:41 2018 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon Jan 8 15:11:22 2018 +0100

----------------------------------------------------------------------
 allcompute/pom.xml                   | 5 +++++
 providers/azurecompute-arm/README.md | 8 ++++----
 providers/azurecompute-arm/pom.xml   | 7 +++++--
 providers/pom.xml                    | 1 +
 4 files changed, 15 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/3877303e/allcompute/pom.xml
----------------------------------------------------------------------
diff --git a/allcompute/pom.xml b/allcompute/pom.xml
index 4d8db81..730abf2 100644
--- a/allcompute/pom.xml
+++ b/allcompute/pom.xml
@@ -143,5 +143,10 @@
       <artifactId>packet</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.provider</groupId>
+      <artifactId>azurecompute-arm</artifactId>
+      <version>${project.version}</version>
+    </dependency>
   </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3877303e/providers/azurecompute-arm/README.md
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/README.md b/providers/azurecompute-arm/README.md
index ed8abd4..560b815 100644
--- a/providers/azurecompute-arm/README.md
+++ b/providers/azurecompute-arm/README.md
@@ -1,8 +1,8 @@
-jclouds Labs - Azure Compute ARM Provider
-============
+Azure Compute ARM Provider
+==========================
 
-Build status for azurecomputearm module:
-[![Build Status](https://jclouds.ci.cloudbees.com/buildStatus/icon?job=jclouds-labs/org.apache.jclouds.labs$azurecompute-arm)](https://jclouds.ci.cloudbees.com/job/jclouds-labs/org.apache.jclouds.labs$azurecompute-arm/)
+Build status for azurecompute-arm module:
+[![Build Status](https://jclouds.ci.cloudbees.com/buildStatus/icon?job=jclouds/org.apache.jclouds.provider$azurecompute-arm)](https://jclouds.ci.cloudbees.com/job/jclouds/org.apache.jclouds.provider$azurecompute-arm/)
 
 ## Setting Up Test Credentials
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3877303e/providers/azurecompute-arm/pom.xml
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/pom.xml b/providers/azurecompute-arm/pom.xml
index 72ff3e2..9a8db61 100644
--- a/providers/azurecompute-arm/pom.xml
+++ b/providers/azurecompute-arm/pom.xml
@@ -21,10 +21,13 @@
 
   <modelVersion>4.0.0</modelVersion>
   <parent>
-    <groupId>org.apache.jclouds.labs</groupId>
-    <artifactId>jclouds-labs</artifactId>
+    <groupId>org.apache.jclouds</groupId>
+    <artifactId>jclouds-project</artifactId>
     <version>2.1.0-SNAPSHOT</version>
+    <relativePath>../../project/pom.xml</relativePath>
   </parent>
+
+  <groupId>org.apache.jclouds.provider</groupId>
   <artifactId>azurecompute-arm</artifactId>
   <name>jclouds Azure Compute ARM API</name>
   <description>jclouds components to access an implementation of Azure's ARM Compute Service</description>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3877303e/providers/pom.xml
----------------------------------------------------------------------
diff --git a/providers/pom.xml b/providers/pom.xml
index 7d518ad..df0fe88 100644
--- a/providers/pom.xml
+++ b/providers/pom.xml
@@ -37,6 +37,7 @@
     <module>aws-sqs</module>
     <module>aws-sts</module>
     <module>azureblob</module>
+    <module>azurecompute-arm</module>
     <module>b2</module>
     <module>digitalocean2</module>
     <module>dynect</module>


[15/50] [abbrv] jclouds git commit: JCLOUDS-1278: Allow to configure virtual machine NICs

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
index cecdc01..f3f6aac 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
@@ -51,6 +51,8 @@ import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.PowerState;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface.NetworkInterfaceProperties;
 import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
 import org.testng.annotations.BeforeClass;
@@ -253,12 +255,11 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
       OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
               null);
       OSProfile osProfile = OSProfile.create(vmName, "azureuser", "RFe3&432dg", null, null, windowsConfig);
-      IdReference networkInterface =
-              IdReference.create("/subscriptions/" + subscriptionid +
+      NetworkInterface networkInterface =
+            NetworkInterface.create("/subscriptions/" + subscriptionid +
                       "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Network/networkInterfaces/"
-                      + nic);
-      List<IdReference> networkInterfaces =
-              new ArrayList<IdReference>();
+                      + nic, NetworkInterfaceProperties.create(true));
+      List<NetworkInterface> networkInterfaces = new ArrayList<NetworkInterface>();
       networkInterfaces.add(networkInterface);
       NetworkProfile networkProfile = NetworkProfile.create(networkInterfaces);
       VirtualMachineProperties properties = VirtualMachineProperties.create(null,

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
index 27e6f6b..95d967e 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
@@ -16,6 +16,12 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import static com.google.common.collect.Iterables.isEmpty;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
 import java.net.URI;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
@@ -26,9 +32,9 @@ import java.util.List;
 import org.jclouds.azurecompute.arm.domain.DataDisk;
 import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
 import org.jclouds.azurecompute.arm.domain.HardwareProfile;
-import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.ImageReference;
 import org.jclouds.azurecompute.arm.domain.NetworkProfile;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
 import org.jclouds.azurecompute.arm.domain.OSDisk;
 import org.jclouds.azurecompute.arm.domain.OSProfile;
 import org.jclouds.azurecompute.arm.domain.Plan;
@@ -45,12 +51,6 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.squareup.okhttp.mockwebserver.MockResponse;
 
-import static com.google.common.collect.Iterables.isEmpty;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
 @Test(groups = "unit", testName = "VirtualMachineApiMockTest", singleThreaded = true)
 public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
 
@@ -257,9 +257,9 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
             null);
       OSProfile osProfile = OSProfile.create("windowsmachine", "azureuser", null, null, null, windowsConfig);
-      IdReference networkInterface = IdReference.create("/subscriptions/SUBSCRIPTIONID"
-            + "/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/" + "windowsmachine167");
-      List<IdReference> networkInterfaces = new ArrayList<IdReference>();
+      NetworkInterface networkInterface = NetworkInterface.create("/subscriptions/SUBSCRIPTIONID"
+            + "/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/" + "windowsmachine167", null);
+      List<NetworkInterface> networkInterfaces = new ArrayList<NetworkInterface>();
       networkInterfaces.add(networkInterface);
       NetworkProfile networkProfile = NetworkProfile.create(networkInterfaces);
       DiagnosticsProfile.BootDiagnostics bootDiagnostics = DiagnosticsProfile.BootDiagnostics.create(true,


[43/50] [abbrv] jclouds git commit: Add Azure KeyVault support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultbackupkey.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultbackupkey.json b/providers/azurecompute-arm/src/test/resources/vaultbackupkey.json
new file mode 100644
index 0000000..05a469f
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultbackupkey.json
@@ -0,0 +1,3 @@
+{
+	"value": "JkF6dXJlS2V5VmF1bHRLZXlCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLnVWeGFLX3g3V1kyMzhLTEY0TDNVOXJEYUlWdnpwaEt6ckY3WGtqcVhkOGwzaVMwMXdfdncwLUFpS3JocEVoY3NGaHVkMHREaFV2eXBNS2cyN1UxZlZNRkZoRExxVmxwUk5vdTZnSVZKVThSa3N6anZmU3phaS1hYS0zSzFacHU3eENBazJXTW1iZzJMSXB5bWI0T29HZ3B0NXA3dk16RW9fN1ZjRTRKTXhUckVQV0xOY1plQXRKUkxlVFkza3YyUHZCTHQ4cGN3MmhNWUYtQ1hpd1UtcGt3R0s5QUMxUVFwZzBFWEZXZnpGZkNwVkg0UUpZQ1dyckd5MXhUMlpWbERPdGZHcG9zSkZ2cDBfSWR0X2ZnY2lxeVZ4Ym1Ccnk4eGJ4blRXcVdySm1KOExmMldzRXdMcXNvZ3pQUzZlRFJqU29YRlBCd1lqal9ENFVhcDNqTGlCQS5DOEV1cFF1aUNSOU12YVBabGVKSTN3LkQwT01pTHBHd1pVVW5GdDI0OFJYUjNycS1KcVFqeTJSUzZnTFBUMkM1SVFyOHVTZmpoaUI1cTRoQV9TN2NMQTVnWXo4VVZpWTRRNEQ3eTdSU2JxemhRTUNPa1QxclBNUkxtZjYzbC03ckNBaHhHNWNwVzFCZVlma2FBaTFMUGxwZ1RnYi1EN2h2NjFNQzhCcXMtU0t1eTEyN2tfSXV5d0hMelFtXzQ5WTNBQ0xJSGlDQlhYZTlSTWJKSEhuY21nMTc1WGlGY2RuRlhKTnRKb1B6MWZWZWlrRFBkb2
 x2Z3pYSkFHYTROcDI2SDhJVGRTanRpOWUtWVNUTllTUEs0ZXlwRFRNcFlYcTJZNUJIYjNTNnYzMHZCNWhCdHkxdy1jXy1iQ3pUQ3VHNzA4WnZneHB5V3VXU3prZ2g1VVF4Y0F5djdaUk5fZk1VVEVQdXMxTmRKaEt1N1Vna3FxdWU1c0ZPVm1mS3ZTaXdlN21QZldUajA2N1JpTXVWY29JLTU0eUhLU3NRTXcyZjRteTR4eDk1QlloUmlXOE9HMS1ISzdkN2Z0TGRYbHRKMDR2WjFDUmFOTjlQdldUOWhNR25DUlFRYTMwamlWNDd1Mm9oTnZGRDJNLUlQT25pb1ZYbWNPeGQ2eXluaUpxQzBodWNuMWo3ZnRlTFpNbVlLMDJEOTZNZzZ1aEZnU2ZWVDFDRDdVeUtISk9tamIwX3FtNXBLZ24xWGkxZVhlSWsxMnNpeTBqMDlBNkJDTW9JM3NIdEZaeWxaTmY1SDlTMmRzcEhZN0JvTWt5eUZqOWJjMEFWY1F4Umpjc2YyMEE1cHd4TWlLZ2tRSUlIT3RkbEpGUHQxWUVrQ0Yxc182LTlSenpGbVI2OW5LaUZJdVYwS1BWRjVOT05RYmc1Vm5qcnhhNFEweFhVcE1Ecmsxa2ZQZ0lSRG5LQ1dUMEtlbWkzSVctdS1EMzBHNXJUZ1RvYjdDNkdLd3NYeHpCXy1scWdEb2RqUk9LdVhISFdjMzZlZ3ZwbWNRdDNRaHFkYUt5UEVRTWNUbHdSWGw1VE9yangwWHloZENpZ2hWSk95XzVMVGxLUkpXdVh6dHZ0Z3lIaGhGVi1CdS02UFBKeDFSSTF6NmV0Q2xSNGd3WnlYU3p4c0cwem9tSjlKVTJqczBrQVBmWlFVc1FQZ0FZZFlvTEFkTV93a0l1eXVrNks1RmVTZ2FQbFJiRXEtNmZzdnhCVXM1STRwcm9BYnZDR0c2RXc1YXRDVU8ycTh2V3VrcFBZNG5DVzdseDkxZWI2QVV
 QRjdhMFUyQzh2SjRJU3VuSGdpaURvX19YaDlTZDk3ZDNZNnFUemZhd1A5eUIwTERKZDZIeDQ4QWNWd1ZYQWdNeVo1Vm1YWWtVTjgxTFVxNzNLY21lRGV6R2hlelpBVmp3cEVXQzZKdzdRMUJfM2luMlA0SzB2bGVXa3ROWjFaV2ltd20yRDNkTjNYdWc2Rkh3MWdjZ0RyaEc1OXd4ZEVTVU40eXFwY2hZQWZSZnlLc0R0NkdpOFRZWThiSGI4eXFCWUxITEpQd2p4UzY3dTc1QVRZTGNKU2lTQXk1cEtPSzRSUGhDMzRVWjR4Wi1mZEFVUGdHNmJIcHd1eHdOWVhYM3dnZzR4LUN4X0s1bERGWTJfenhUdG91c0tGSXZ3N3BDNkRkT215N0JPQkRyRzhUMkVKYmJHQW41QzJxZXNCRHNQMlh0U3RwZno2MXF5QWlpeVFzWVF1UWR0Ums2MWVfaWlDZldaYlBhVTZPYnRYemJrblVCM3lwcHpybnZiQlB3S2RuY2RVVHU2Q2hldzduc1gzRkR3TGdPSnNld0xjb1BwSndSWGl2QnY1Z1pNT2NFLVB3VUc4WmVLWjQzUDMweW9UenJWWnkzUmgtQW80ZVVyR3k0QXFja0UwbUx1ald0d1JUQnpEbFBwWE9aWHV4dTkwTENOdVJXQ0RBYnRfajdKd1hCbkZjSlVTYTJVUkM5VHdWaTNZWW01aURrSnRZR2s4ZkFILVU4b0xIT2dRb2Itb0o1eTdwQjNrM3pnNmpLWC04T0wtbWlLWkw3a1JPYUlOVzNtWEZHSmhIdmR0cHNaaFNVV29FaU9ZbkdNT1NwSFpSdkJtYVRlVDRHNTFLWlB5bHV3aEx2bXNNVTFjZlpYVzE0SnlXZlpYbUk3YWRrQ1cyRTBDZGE4Si0tbGtLQ0pxVUVtdW5WZmhndVRaakRxVF8xSy14ZF9ldkk3TV9mZVNfX3ppZFJncDFiV2NrTl9EZ0NZSjkyNHpS
 V3h4bVE1MU5NSF9pcVZiS2FFOXhSOXZ5cFNRLS0xV0tONWZFWHh2NFdYa29sbkRTYUp2VWhaYmE1bGFSbXUzT19sQnZMU2VRbEM3eDQ5MWJTbGhmdXpWV2gxOUpzdGRtYkF6Y0dZQk1ZYXpwMDRMclc0cW5ZTVNYWHFQU2VJcWpWMVBzTHg1WTUzR2JxbnY0TktRMEJubnhjRVZHZzVPZGl5ZlB6UTRMZUlPZzZhTzBxUy05eUVqTHFZdGY3dDVWRnZaN1RDWTRDWlI4dlRoT0Z0cURvSHYyVWo0eUJaODFuYU41OFF1aXMtb01iampETTM1OV9WMy1OUWhvTk9vSllpZXFiYW9fSTRlUzVNclAxZXNEYzNvck5BWEptV1M4MDB3SG9maGRjUE9vYmt6dzNjUmhQN19wYjduZGtWZjEwUmVJZEktcnAwTjJiOGk4bEppRG1Xb1otR291bkdkbGZoSVlqdUpROUczRHhMNXcyRWIxRDlXMlBnTlZON3FSRk1fM29Dc045MWs1YnJjNWJUUWdBMTZ4TTg4NlNXb0ttaGViYjdEb2ZSU3NQV1RTRno2Y1JjTzcyTUZNSkQxUDY2T2otcVlfUGU3cElhZ3IyVl9QVFNQclBsb2MyYjBlRmt6bTZROGhlRUdpZVlZcnd0SGFTUVVoWmlyN1N4aW5IVmxTblBYVkpDUzZmcWRKbnBaeHhOdzVaZ2JiWGJobDRwU0tLOGY5b0FDdTNvTk1XUGdWaVRpVjRSS09WalM0QXF1bjB5T2ljRkRoVzVOZEExZWItakhfN2V2RGxaNmNnemZ5bkNfdjFpbzFucDAyTEs2WG9jNURIZEhUMzlqZDkzQUdvZmtkT1c1LWx0clUycW0wMzYxVDA3WTAtSG5ZeHNDQW96VGs1M25zQmdTMkRQWklYaWpiRVpIVHc2OWJINTZPX2J1R0ZBYUdNMUNySV9RLUJoWW9QWHpINHFuMXMyZ3RlcUNaOUtKM
 GZlMy1lVnE1ZGZkNVRmR2pfUzNCWl9QZnlPYUtIR1pBdk1mcS12cTdhdU52UjN2YnRMTjJkZHhLVTZoQkNpRkcwbmtWZ3JMNVVBbzZ2em5fTXZBdC0zYktaRXhXSDB3WGtjM05rc1U2YnBpMkQyVnFVeV9RUE9TVUlsTktRUDVwX3ExMERheXFleWdwdlZYNWJsMGVwWDd4ZGxURmN3Z3lZUGxpc2h4VnlZX2ZydTV0QlRCX3hjZWgzMXFTeEZjTUNMYnFLMUpIZm5LVjltUVJZNUZDRURibllwQVNTeDBJVkxRVFpqNjBSN3MyVTVqTk0tZzFzXzc2RlNSSDlZS2VEc1FXcUpZNkVxNjJxaHBUNjBDOTFhMGhRRGdIdW5xTU5lSl96azFDbGZZZmJwSWdDaHZFd01YX3VOS1FMRmNDdWVjWG1mS0Fxb1ZfczRLTXJlbVJqMDMzNDQwWUZxS2FiZWhjVDVpYWhDSnRkZnZxSXUwc3pDRnNmY09INGtyRndYTmlXYV9VY09aY3FHc0Fxbjh6eWFfZVRSV3BUanNFelYzY0tjU3F1aHBtQUU2SWpnQ1NFTGw3SmxsZVdteFdzM214NnFJYmJlakhNLV9ndUZ4QmQxc2FJMUZVWFlQYWJsMXFybzJNZDhPSWtGeUR0WmJad3Zla1JoTU9lWFBJWFNKRGFuVkR1S0h3akRCbEktSWgxd2R4TndqN2tBVW5fSm5rM1BZQzVKM2MxTm80Q3hxdW9ocm1nZGJTUEdqNXBzZWNWRDRGaFh2VDVvNUxtRDdVcEVVT3lFemtjVFJNeHNQTTMxVFprRVlnOHktX3V0VTFJLVQxN3NLOGo3dGxnVTFfTm9kQW1TUHM4WmdHaFRhRXA1SVRRZXNFNXN4NFl4TnZBVXpHTklPUGNzSExfTi15WnA4OGN5dlhyV1g4TXdBZEhwYTFNX19Xd09DOS1KempvRVYyejJ3YWNyTk83bUxiQWNydVFoSz
 BQMXBrRmpsbENzUHdqSkdwWGN4dldtaEdrMDE0cjA1dWtjRkp0LS05bGw1WFFvQkdwWU1GWGY1Q0l1SG9HaUF0cGJvRDlRd2NhN0ZiNkU5MFRqSVhUMkJ4cmhKR1lXY0dWajAzNlFja2I2WVJpOVZiRWxweXBmbkxscEdvWDcxVndVTWJnY1RvMHlORElWLTNtMEM2VlVndmtxS0ljT2RnYi1SX0VPdkVSVHNhODQzVHA0Z3JlM1pnRzlTNVI3UE1GdE40ZUY3NkJZbzdFYm5IcGttdTJkdlg1aDdQdnF0R216cnp0QVozZ1ZWUUcyNFVVNHRDN0VmaHdkLXR1MkNWcU5QTVRROFhSaUxlM3JKMjJuRktEdFNXSXVHcFRoV0hqNGJ1Uy0xRFlkNHBxV1hNUjBtUDNLNkYxbFJ2SUlUSnhlNEhjeVhvaVJtaktJQjVvbFJFZEFsR2ZhY0taY1FmcDhvVUlmM0liNEJnSDVQU1VHSGFMWFhjSDZaN3RPU1pERzZCVmJsZTVvT1VMdkd1SzVUaUQtaVh1bWFSMjk3TFB3SHl0dEZDQ1BjN0txdGZhbEJPTy15dUJacmRtRlVtN3ljMkdpRWtnWnNuVlFzcHl3NHZmU2hWb3VCTGdsbHJuU05NN1l1NWoxM2hTOEFkblBmWGNOQ0xsVkFleTVVeVVuTWlpcmR5ek90Yk9TekI1dHRGcDFpR1AtaElfSmtvUHdvT0RIZUJlbzQ0cXhkekZvUVBWbUFGNS10RzN4QWFqU0FUNGVyNXNLVlZ3dmsxWmZUQlJxYXhQWTdHd3RaWmxpa3hYcThpTC0wdm5mNEtINktnT09uUGtoajM2VmhCeXp1c1BrNkYyUUdQdjNXdlRxX3VMalgxV2V4UWVmS0JjYUtrOTF4R1Nxakl0YXVZQTZGWWpNd3Jmc0NPelNwOGV0VjNQc0NhWEt4dHJyWGxHd1dEOV9EeFhKVmprNDMyc3UyR0pEaVk3aVN
 fOGl6XzBlQWQxakxOQ09YcFN4SzlFYjdvY2RjS3pTX05JVktqMTZFYWxDa1Z1MGI3OXZfLU0tY055NUwyc0lUZHpGRmZEOVZDdjVRdk5hbFFzTU1Fc2VoRm5JXzAtMW1fRXFNMUtFdTVlWGtZa3JwMThoWXU3RFpCbXg4dDZhTXY0Q0tpVk9kVDhhUVFmeXhwZ3BSSS1jUGdBNHVxVzk0U2dRZ0RURWhmeGVxbzg5WEd1MXBaOTRndHliOXEzVHd3VDZTeWNYRW5vSlExck9EaEhqV0gzRUJyUjZRSVR3d1VqRUFjRHdDZmFPREJ0OWlUeHJjZk0tem5mekx3elZkUjVBakVNd3RSTVZUOEpzd3JYeHI5bXlWMU52cGtZeFdFUlpvbTItcW1DWm1vRWZWdG13d1Axa2g2d1U0a1VGNWo4Q1psOWdUck5NVk9Ra1pzbkxuWDRKVnhpc2k5WENBVWRkLXE3NlZpemNFNGpFYzVmamd6ZzdsdF9IZldWUXpIVWZaR1NXVUg5OGZEd0k3N0otSmh2dlJMMF9uQkpvZDZlYUxVNjRpODgzSDFrODdpTXFXcTl6ZVNrcFpmRGhpZVhvb1Brc1YyRUROZG5pSkt4dHZvcU8zLU53bTdoVTNDZXNEMjZ0STB3dHhEZk1MdkQ3Y2VZMTVRZXNOdTJqSmRTdGE1bmNtZVNMMmNVVWZkUmJyWmhRYmV3VFFtMTh6UWlXSTN5d09jWXhadm9SNXpXc3ctQmIwT29XRWVwbFJQNzR1S3RXTVZVQUlpYTdHcVN0aGxFT2tXcllFMUNLT2ExajB5dU85Q0czTk1jSmdHYnlOMXJUYmR5azBfQXlEUV9JT1NEQUp3TVg0UkZadkNSdjRNWU01U1hPYVhWWVRwa0t0bEdFWXlUaEQyT3liU2ZLNjJhTnNTQUJDc29MWm1Pb1pYeWlwT2swT0F1Rkw1djh6S0hzMkJENVBkTGNRc3B0d0pyUlFPZ3Nt
 S3JRU1dJNFJrTDJwVzJ4VEtfdkJibC1LcnpEcGdJUHZwaUFENUJYS2FEbzlvU3BKRWZQbEw4VTBLX1k4Z00taGtqUmYyZzBzRFdJeVUxYV9raUdzY21UYl9oNlRiYTg5aVQ3cjg3RVhUTlhwMmI2TnNmdDI3QlMxdy1qc0RPSVZtdlNfNThTbVVDXzAwdmxjVENBcUhaM1ItWnE0dFdHdkY4UkE3UnVabDBDYXVvY3hXTFNBV0NEbkVCUXM0X2wyUmowek04NFBXeVhRN0loZlRDVU12X1gzZmwwYVJJN18wYTd2c1BYLXRILThBSTBPRzVRb2tUZm1scXhFWTNhSjRxUTlOTERJN0t1TExpWGE1clZ0WjFVelJLNHRWTUNKaUJPQzRGZ3BiRDRkT1VEWFRQWVUyenRMN3F2dy1pbGxYNTc1WlNyUzVCMGVQSXFUdFl6NWZoX2pXeUtiR2x2U1RlbHpSNFdueVBxa01CaUNWQmd0dkZGS09nZV9vclpEM25CNVVuVHBTd0NGWVFkLTZwVDRKeEdNTDF4RWloWk9tTTdSV1BaaHpFNWVfRGczdzZ5UVlSbUhabV9hb3lrNGh5Tld6OW01Q3hleVlIRjc0N2c5a3NpOHpJN3hycTVLWHVHeFhxMXNIWEtvV21jNTVySV9LeGpTb3Y1bTlLYkVNNGZOMW4tMFVORmF3cDM2Vkk2WGQ3enAwa2pZeXVJY2J1TTZqMkdNUEJIeXZWbmFEYzIzMkVwWWVTdnhOUUJZUW1NR1hDNUNoWm1KQzN5T0ZXV09OQy11SkZjbVY4eENuXzE2LTkzS3JCT1U1eVVYaUZRQlV3M0hzTU5BRnNrdllwWjBncTNwZ1dWNTBOMXRRcDZjclFTTXBNNFppOTdVUU10TlhZLWNPZHpsNHl2Q05mM1ExN013U2Z5MFlrN2F6bVpIalNhclZaajZHbTdadjdFRHRpT0lYNTlDNEJRVGpkTDZONUZJLXROZ
 ElxOVlJODB6N3pvRXZpOHE4czY0UmsxZm5TY3NWbkpNOEFKTVVHV1Vkay12REYyTzR0QjNQQllKZXdheUkyNjRHSWJRSElJeDB2Z0pkVkhLYnFmZE56bzZwQnVHaldCUWVkczhWakJxdnA5b3BERnRhamx5X2lkY0p5ZGFtbFNfN0RCekdGaS1SLUNYSmxqVTgtdllvekVJM3h2SkxzamViN3ZtRFNpNml0a3BEaVZwX0hDSUhzQTM5MkhhZzZjN0VSbWJ3cEk0MkZaOUVUYzVReVRoc2ExZkVYaEw3aG5mR2N4b0RpdlJSc2dFdXdndEZTb2N4T0U0Y0o5UjUzeFNTYWRYcUFqSS1NSWdGWDNXRGhjcWlNemRBRm1SQVRnLW9tc1NMN0ZoZ2NmNk5WUUtpaVZVMEJZRUNPQjh2YTVFZVlnd0gwOGZfeTdNUF9Fb0xOZHBQN2IxMWFoSkR3cDRsN3FhaXNWcDZzX0ZoMi03OVN2a3o4RGU5azVNT25WVjQzOEVVUzJGUGMwb2RfQkpxWng2bVNaSFE1MFdpSTYwV2hSTnEtMy1DQWJ3ODVrSVBPTXlCdjlvNXNIVEVVU1EyQjVFSm1HOV9rZFVxTkF6aXE5cWNWbGJ4RHFHc0hsaFJ5QmlZdi1jQjd6NlVack1ZaWNwT3VaYzVNbUFseGxoY0t3cHl2R2RuX0hkRS1RT0dvekNHdUF1M3UwbjU5Um5qWDRCWm1hdTFWeXhJeWkxdkYydXNKUFZub3RoU0NxUlY0U1RNTWljZDhrNm9zU1BIWTZLUmRrRVN1SnRoZjlxWWctVFQ0MVp0M3RYVUE4bUhfWWxNTEU1NnVpWWlJMlZCT2FNbFktMlQ4My1MUHcwTEpnQ2k3RElvZ3BOTnFWRE14ZVVDTWdpX2pKMnotMEYta0pWdUtNMTJMT0YwSENWQmJUeWJ0cFlGVHB2eXFVSU02d1dzanp1WjNGdUh3c3hyVnRqWWZFUHJfaV
 htM2FQazBHSEdFVUFLMG1YTUozN3Y1Zm1GZmhwcTJ6aFRyLXJYR29sYVU1NHlBVkZrV2pLbkJYTWdxb0pCLWZMbHh0WFlvMllHbzdHUDFDMkFVRkUzTWFiOW5zSTlacmhGYV8yN0RXMHVDeTBsV09QQ2JCNTRPRUpIdTR2MGdSaTZCeERDUU5NUS1NNFZQUGdfQUVyOWV2aEFnQlRseUZtbFdDX1A0Vm1ONzJmYV9sdjBnSldsZERGQWdpOHFaaGhRUHdoamdUekRvR2ZqNzRDOFZiZE5KbXgyMm5DSW5fQVhiUi1PV0hsM200TnVVeEdZblVZcDNKczRoTF84UVFqNFJlWHppajVnSWJVYXhTTWx4UTFhRmVLLVVJaXFuQVJDcC12TW1TNm16V3N6TGJRUzVEN0RXSnl5N2JuRmtFLVljblYzTlJCTEFaei1ndU5DX1Z1bkpwVGxuSVJ5bzIzaERIZkNQeDROM0lLVWMyTWlxUDdTNW1vT09HMjZUb0Y3LUJBZktzT2ttMl84UGNudU51VWhmRWpxYzN3VUlZU2c1TmlyZzlUSVlOQks1YVNhSEFjS1AwcXdENW0tMkt0T2lEMkJ0RmhrelJPdm9fUnF6SnAtR21kajFwdFRyQlIwcy1KdU9rY1lud3VJcW9RRFBhVy16WDJXTzRjX3pDMDR2YlZjcDRGdXFoZzhaTVNiQWFkQldQWFZlNENGU1A1R2RfVkJvVFU5V3RLRkdEOXViLVNLQkNfbXRZcVVfRDN6SUpxTFJmUm5mT1JoT2RoemdJNVFpMlAxTVlISjdFenF6NHhNSzlzZVU5OEdtZkM5cUwteEZhRW9RTlVCajBUaHp1dVUwNkxUbENYZXh0OWNtVXRhYnVFZGwzQXE5RnhQVXJwRWxwWGhoLTQ1N2gzQk1Bal94Nmk1a0RBUV85X1EzZVEtay05Y3dPQmRrRUcwNk5xX0NhNFFyNUFTRTZvcXVEazBVMHBjcER
 Ha2ltTUM1MVZ5N1lzNWlqQk42cTFKVzNzYU8yN1ZUV19LSC01YWFQQUw1ZmVBZ2lXeW56T0l5V3pEX1BwWm40SHNGaFNwU1RKcVViYXI3amZIRERNaUN6bUhybFVJQWF3QW10blhsS0drWF9RMDhjeEN0Ni1YMDlCd0poQk5JMDJkTXpWZDFPQzhPVUo1VFEtX28zTzgwZmNIeml6UDhENk1GS1R1SDFfcjgwczlBX1IybVRObGdFaTY4T19fdFVqZUdQNWZqd0JlbWJjSGc1aEREdDBDaVBMZmZMUm1iQ1dtT2JJR0xMNFlLazNrWEh3ejQ3MlpjZFRCZndGT0dDT1BzUXcyc1hMcDhtNE5TeWpIeTlTSzN6a2tNdHE2cVJ5YWQ0dHpnaTVoTmJJLWpYRUdLWmZGWWFDSkxXQUJGbzljSU5hb2VhU2lFbTdXeDNkWEV3R0QtNmZQU0JVRzVLVl84QTZmU1R2WVVkMU5QSmRuSkgyY1lUOTFIekk2cjAwQUpOcFg4NWtfbG8yZlJKVkNSUE1UVkVZb1JqSWtBUURQVDdDMlI1Y1pxcDhneURod2JGc1pzUlhTWGp3RkgxOU1Kd2lsaHFNNnQzNW1FU3o2Zy1aeldMQzJrNDZBSkd2eTUzajJwYzQwbTVXRGpxdVBzQjh6RUt6bGlobHpFbWtTdzlIT2VJNjJPM050RDFBQTVSTnFNYkdVeVhUN09KWEFIRWZrOV8wOHRkOUJoMkhQaUVxOVVZSERsWW10WjdUbjkxV3NpelZYNEZxeFpzMjR4OE9XQ2VJTm9PZFRDZHFocGNxRVQ4aldYYmZvX0Z2Mkl0UEljMndSSWVqekZ4X2h2bjBVbVc3UTRFSWRTdnNJelI1ZnQ4ZHJzUUZHN3ZQZTRfQlhCOEw0cmtQY2JGUGVWU29XejdvcnhxWWc5bGJlWEVRR2s3dzN3OG9FTU1rZ0VPVnk1eVdvREFQY2xldTk3VmVKdFJlRUkz
 clBKNE9jUFh2bnRVUG4zSDFsSjBnUzQxT1dwckVMRWFWTl9ocVpsaXdkRUpJTXAtNTdydGN5SVk4N19McU1rUEFDVkJtX2dtZ2V4MVZkTlhkYzU1OUlvWVljd0NDUlBERWVpRXVSLWcxMWtTRHFJZ3lRaHE1OWRDSmpRN2JCSTV5andfMG5PNkpYRjU5eWRWcURfU1ZEb2xkazNpa09VcEYwUTRrZkZKYlYxY29wQl9DRFJKM3pXRE5ScENhVEZxbEVGc3dMWEtRSFliTUwyOThKR3dIWW5FX0N0dWtrU1Q0YU9kbnBkcGVfTGhhLWJvUVQwQ2RKMUhhZHJOb21uWlhER3VxckZQcWVBRGkyOTJHZzRLZGxEV2MwVkh1RGtrSGREYkRtaWd2RXhhVjVEQlFhd05zcFJxaUhIa0R0cDFZRmVlT2FwdTRFM3o2WkhkYzFNUWpFRWlGYjczSmNNQVVTMGlwS1VLV0NhS1B3ZE51dU95ZUF0Q0o0dnpicmczTFdSaWJaVjRzc0pqZElRYjZneFpMOHZteTUtMUFiZ0czekpJSUNvSElJM3ZqWWxEVXk1UVRqMkhoaEp3TnFYR1hxTmNaM1ptMGRoMlRzSTJseHZEVDVVRlBzeG9ab2F6dXZIUW1uSjR0ZXlma1hNalNFMEgyRGF0YVhiS1pndGJTaEY3Q0tpYjRwdXN1SHpyMFllOTI1MDdPaHk5Rzg2WENSUWxkb2xlVkhVMEczWUVhQ1AxeWhjRG9qbmg4ZVBFSlFwdFhpRGxBU3hXSFFiY1FNOUE5dWs3ZmNRVEFLZ1hsYTdjR3JFamwwODJENWtWWmhROTV2dVpXTEtDN2lqZlE3dGVnX09WOHNzel9pSGxlSHpiV1o3SGhWaGM2YmZLMW9GUGdCS0dESmlmTk1fZ040QkVQRjFSaTR0ajh3cGdLbzIyaWpieG5faXhac2pUUDU4TTRmSXEyWmFweWFSVkpoQ3NKTkRWWlFab
 nRKTGVsVVNVWmxrZktPOURfdjNXcVZwZ2RhbngxVHZ5M1BCUWhlU1RzVXE3Yk0xdXJhMEdEbXN4dFZVdnBncW5HTWtuNHRoZUlNRm1ndWJoTmlXUFd2ZlJNNUpDM2hBVjJXb28zRGpvS1lISkVrMFA1MnBqOUVuVEVXZWlTcWZHcklqUndjZml2RXFRNHk2ZkRfSFZaSUx2RzhxMl9IemoyWXVPVHN1dWFPNExnZkZCeUNXN29kemZNejJDeDVVeHdXUEZPYm9LcF9INVdUUTFfRTFDQjB4bHIxRGVFSElwS0ZLUVowakZIQ0IwWGtsLUc0OE9tYTRXS1dZcW5JSV9LaGdBRkY5Y0NUQ1dQZlNwTUtGWS1MRXN3R18xN2hxOEswYXNoTzZZbFR1TkNNczlpZEdCRnZyZEd6THhoUGVldDI1bVlPSDRLZUs3WkZPeUh5RnY3YWVSVmlESkQ2dW8zbHV4TXM5UV9NTkF4WnZ5SUZhMG4yQ0V3eUwxVTlQcGhhNm9UMW4zZHFsbDhSVFVLaGZDZXRQZWtaQVJfT20ybDhRMWFVY0tHV2RaN3d2Xzd5SXVCWEpHbTdieDgwVnpxTDYxMVN3OE5FdFh1cVprLUVkRGlvMEx0SU1kNDZ3MWpTQ0l6QTFueUdtSklrTjktZWF3czlkNy1Uc3FUcHpQQTV5WS1KRkl3c2NXcEozcE5ma1d5RDFKaDV2cldvcEE4THRJaWJNdHlEU2ZnZ1FZckNvQWNWSmdGcmRzUWJ4Z2x5UXpablVNVEZKV2IwYjZnWnRqNHh4cndlb3lEV25zMmRlMWVqMDV5QUl1c3E4MVZXTU5fc0pDZG5NOGpOUWxSMzhPcnhXaVU3SDBVT3N2ejZPTG1WMmUwSzN6RmRKbUItWVk0eDdmd3hGaDVMREQ2Y2VteDA3UndQSzhxSzJGem5VNmx1eEVrTkpIRHNKSDZmdENxb19BaGgxQ2I2a0tmUGhkc1BYSTZxUl
 JIM2psOGJKMkVDRkhiVHpDTHUtM2RVQTJjQXo0amd3Ynpfd2ZQZWItNG9wR0xTVHpMVU5RYVhibkFaLTkwZnpNTmM2SUY5MFNVeHRXY190bFFPUzhxclBvcFVRSF9ObV9wR0sxT0VmRkg0U2J3SVFVY2xrQnZQUXh1VEs2TS1QZFh2QVFpQUZTWlEyTVVlSmZkRk56LXNyaTJUWV9yY01KQU02cTVOVEdPMS1INEV4SEZVTmRZYUt5RWkyNEJ2Z1pRTEtBREtBLV9uRElqNE93ME4zOGFnZ0ZFX0VIUDZ3bXNPWXFXQ09VLVlSb2dyT2VXREhlenBwaGIxeklPVVF0SmxHdHhlREZEdTRmNjc2bVUtM2hhcmlBRzNtV2ZYUUJ3RDB3dzhnc2ZZWXNkdUduUWpEdUgwZjlYRGZlVHhHbi02T0RxVG9mcHFGMl82ZVZOM0pUR3hieXFLMkpWVGo3YU04Mi1WMVJ3RG1iZV85N05uM0lfSzZGbmpCclJzZEowNklJcF9vdW5aUVVVT1pEbXdyRXZKN0dxWXRYYktubnlYTVdYcHI4UmRaUjItVWphWXBFNDZjRmRFM0ZhTTk0ZnRDS3Ezd1BTMXZFbU1KVnUzLUZSTVMtc3VKZDZCTlFPWUEzTjU4VHF6c1NIWEk4Nm1FOXA4dW5zazZMSHN1OXFxMHVMS1UwS2xDTTZWZFd1b0pfMy1yMk1ELVZHc2VoWFZ0VzdwTmE3SzF4bWVDcjVnNEFXX0tWaGJLMy1nWUY1RWNQd3JLR2ttNktYMkx0emZOSWZtcEhHN2djaFFGbm9KeEZwclZQejR2b1lwbDRTUTlKaHhCOXFJbUhWVll6WTI1dm1UdnpZd3FDRnUxYnZDN0VrTE9fNzZTemc2OUdLeHc5QThlSmFucHBydDVjMzE0YjB5Z1FVSUtXdWV2YVJXcFVhTEI0Ml9wSXJBcWQxV1VZSk5idy04MzZoM1QxZkdhR1pqUDduX1B
 HRDlpVzB5TUlXMHBGdmdfTXVoajN1N1ZHUTZ2aEEzZEo2MHB2ZEZIOWUzVmNMdktFcC1hYXl3ZUdlaHBKTVJiUkc1amhOaC1DODdOMzZNUzBaWVIwX1F2YjQ0ZnVyekVoRXdRcUN0M1k2a2xSb05tS2x5LW9rZmtRTWgxWG9xc1dLMUJxSTEyZjl4N1ZOSnFPV0VxWkRNYlNPcmlCb1g4a3prY0VaWHh0YUpDeEVFZkhxZWZkcldiN3RLWldvaXFiei1mSUVCazk2N0s4OHJSQ3V5TnhRR1BXcnNuTEtrTnNVdnhKOWhzckdNZFVoendUX2d2OV9iUllGVXN6ZXdweHA2QXdJNEpac041Z1RScWRvRkhaZnVUb3FIZ1NlODQ4TFUtelRJV245Y3ROWUtWb1Z4VWNEdzBiZHdSdXRUdmk0R2RvY0JiMTlqRXRzeWR5Y1VyclZWVXY1UTc3UjVRVi1tSFFtSTZ1VmRGR0JHUUdiM0Nkakw2YUNRTG5GVEl3U25LalN0N0pSLXAtb3Q4WFFvNDVRR1dGZEJSMkZXT2FmZGZkSkJ4Qno5MExmZjJrczZ4bXhfVmx2b3ptV0JFMi1zV2hLbXFONVRrZ1JnMXNNWFhZTWpBUEsxMENoR2doanVLLWxydndvOWYuYVFLYzIzRDR0TUlkZUhoVklVQ3FqZw"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultbackupsecret.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultbackupsecret.json b/providers/azurecompute-arm/src/test/resources/vaultbackupsecret.json
new file mode 100644
index 0000000..ac51969
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultbackupsecret.json
@@ -0,0 +1,3 @@
+{
+	"value": "KUF6dXJlS2V5VmF1bHRTZWNyZXRCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLlFLelA2anZVR0Y5X1M3UU8tRkZDTHIyNGp0RXJuandkQThNZUtsSGE1MmhvS01rNjdiOHQyckZhNTJ6dGR2and1d1I3VWh4RldRLUpuOHk3YlJiNlYtcTlUYl9iV3E5clplUlhpUy1jdUhPak9ONHB1bHd1cVVmQkJOU2V3NlJGUXpOUzRrQks3RmxQSGZpQVRRaUUtLTc1cnZIM0dMTEdDd25KTkxIUDNTR0FtWlR1dXo0bTN6X1owR3RsZUU5XzFZT3pqczU1UmJFNEdOTC0tWDhDWnlRWmVFNGdGRXZ2WmFrYkRXTk5hOWd6SnBUNlNOTm5tcGtpMFZocGxaNGdzWmNmR29xQktZNF8wTS1WTmpIbkZ5QUlySXdsSTNjZkIzWUVCbHJ3X1A1QXhQVFFvNDJNa1pETmNKYjFwaGh0c1phaTNLcWRxT0E0ZEVWNVZWQ1VNZy5fTkN5eTNJSS1VV1VtWDB4UXhTVnNRLjJkbEFpUEpSa3NlenNVTEZocTE3ZmdCWm11XzBBaU5GUWkyTU8zMnlVanpEMjMxQlY0bHhwU21ZMmI1bGdsTXlYQzNtYy1PT2VmcVNseXdqMlcwTllOYzJKOUg4MzFHc0VCdXZ1SS1BWEQ3dzdocGRNTG5VaG5DQ0RUQTJYY0ZTZ2lXTWMzMFFISHUzRi1KcDh2VGU1QUk5R1ljelEzSFVPRjJOREpjRERoLU9CNFFJRlZWMS0zWEJkeS1uOWR5MjlSY0FwNEo4WHRPMjZxN2dJa3BDT1JxMT
 VuOXZHd3ViVlZhdGhfMlZwM3p1ZEJPX3k5SlFTVVYxMW1jZFVIQXNCVGxFMU5xYkZaU0lfX093NTl6ZktGRTVTMnZrYWl6a1RFbXFVQi1EcTVnMnMxQ05PcUdUNk1wQWNiSEtUNTNSajNZN2RlOFlBckZIMlNSZF9udUV6Q09PMnAxeFpFUjh4c2RIRjlDM1Nnc3ZRQzIzX3BfeDBIR1RfbWY5V3B4amZOWF9Bd1E5NWNLZ0JOdU1ENEZ1TTdWTmpKc1JaSGtvM2tNTlJ5N3BybkhhaVd5aHRiVV9ic0w3X3FRa1JGNEl3eGFzUlh6M3RtZzYyT2tCWl82MEMyRE11Q0pIZWtqSnI5SGJDeGp6Z1lGMjVmRDhDTk00YmNaRV9ma1Z4Y2lVVklWU2lvemREX3owTFBMY09paVp6dTNIWGIxekplZkJsVXduc1NBT0RZa2lWbjJPMjFOMHpkRGwwMjNPSnJTdWQycWo1UkEtVTlsVWRxU0w1QUltN1ZaMTFSVzh5clpkWXc4NFJTejVySldRSm1sVW54RzJHb3lMMTFaQkJacXY5bEJ5Wnd3SDN6ZGNDZWFRQWM0LVZJWjQ5NzBfTC1tT2paNUFwdXI4UERHVDIydkNKdEw1cVVaNGJabThBeXQ0NDFEX2o2cG16NzRUWWlIU210ZnlJcnNvRTMzbG9QM0xGdTFKMklXLXJTdk9HUElveEx1ai1ZMkNKMENYTk1lR0UyQVNhOEY5RmY3enhVLVRkbVZneWpfYi1EY05XUmVJZUMyTEF4OV9EWDY0QlRJV0pNSFc3a2plbjRkem9kajMzbjM1aFU0UUVmRVM0a2pmUUtMVENrYnRlWXliVUlQWmhaa3BDRzRpTVBQSVpTRVdqU2RMckl6NlRYN3FJZHFHcE1UYk9zeld3eWc2dzI1WTd4aDFvelY2RjJEOFpKR3FiZjhQZTVDRWtIcE5LeC1kNExUTzNsOWZlZVd6RFRwTzRnTWp
 BZ1RNdHBqdXRqT2xhSEYyN1JLaVNGWU82eFNQY0ZVb3JGMlZKRERlQUxZSk9Pb0JOMkhpalJ1Y0R5bWR3NUtzNHBZTmZvV3dCeHVnbjBPenJoNVFIS2Q3dWpoUll1XzhkLWd2RVNKQzNJY3JZWFI1aFhxaUp5WGVNMGtULWlnRUFQRFVmSXE0cjJiRW5iZ0RhdUZrN2syekZzXzZzeGZ4Ty1TNEp0alp2UkJia0lnZm1WdVB5OXZTQy02QUl0aEctMW5OUE9PNG1oak9ON2EzVUdzQVpvREg0T1RFczA3ajJMQ092VGdqX05PN1pJcEt6LWhyU0daSXdCdjlRdHJ5NjY4US1kTUpRZzAzRi1UXzZlX1htc1BWRWt1RWdaSzdnS092STNzdjk4Y0VVODFiVEZfNjQ3cmE5bjN6NHdnbmZwVE1lWEhMQ1JWeGpKbHJURmxJcW9wbkdZeHlQdm5iVXBzb3A2NktHbVAtTEpTeERjNlJJckpuQ2drbjN1OGN0c25NZWxuWHZSeGZFdFRsNnkyendUV3ZSdnVEcVR1UFphQXdNVmllbTdaaXZqNTdMYjNHT3RUcjBxQXNrMC15dHN2TkpmY19tYTEydVlUWll1b2RCM2ZoVFBITjFaclFoQzdiWDVHdXFDUFFDQXFuenJjT0lESDIweTFlZHAxam1ZdTFyZThPaG9yMDRiVWhLa2stcUVVdEVsZTFqYzFTckNuWkEyMlRZMFNVYkxkVm1hb2dyaUJfckpackVaM0tneGFaSjNnZ3FQd2NhSW0wNUVoMDQwYUpUa20xOWdzRzVCNEExQ2dDWHRMOGhUMFl4TmNneW9tT0dnRzd2Q2FzdW43WGhtdjJZLWROWVNrZzRZbzlfdkktWWlmZEp2MnhJVWY3eGFvS1RRRzY4NkNzaE0zTkVubFRWb1FjaWxjaXllaHc3RkpiMnYyTDFNV0tlamRWM2dPNjIyVjZ3QXV4MW9GdXJhdWZORzh2
 cnkyS2NwczFOUzBWeFJObU9mNDFkbFRhSkljUmFJM2tSbUg5UkpTakJZcnA1Y1ZzZWh5WGVaQXpnU2JzUlg0eGp6LURJSGVPa1dRS05HMlZvTnloZ3BZS05FVnlNN2dkdFBWTUo3TmlkVE9PM3BaYTBMeV9GaUhHLXc0dkUwTTR0X1ZpOFhvRzBFbWhJcjBWdmRvN0RGUXVUbmdoblRGVnpreEtyRlJSZzRMWkhCNzR2Z1BycTVTNGxTV2hlZGRfekRad2JVeUxJY1NXWmk3QzlpWDctczNHeGp2UjNGekxJT3NuSXUxVHpaQ3B4a0d4ZGkzU1VyS1c0NGlTaDM3eGNmaEpsNDVDcTQ5N1pQQmo1eVA0UmYwazVTS3djM1JvOUJoUXN0aUdzVk5qMlIzcmpHTHZfOEwtUHNxOG1IYTZKZHVvaEtRbEVQT1hYNzZ5aDdab05KUUZhemRNRWV3eVJNOGQ3eUZIcFc0M3RTZTA4Mi1BUmRjcW55OXFZRmJLMFJfV3dNTDlOQkFpNWxjQldUSms2ZHJXN1RPRmJ2eDFyZ0p5cUcza2w4TEdwRExheFNfaFhXZVRxSy1YS3pVRk9zNjA4WEp6U2NhVE1xay1QTVZIdkN5c3Vjci1mOFN3SF9wdks0bTNQYWprcGVOMjl3dmVZdUp1X1ZKZHlPNE9yY043cnRYVXR3VWNSblBzNUNXYWF0N1RfUWhnZ1VTdHBZczBJTlVuNXU2Rm5oNGVsUUxTTEhvdWZDdE9RekpDV0VVd3N2TWdkdkc2cEUzU2FZU244OFd6YzdMbGctZEVMeERLQXE1dmI1bXFleXAyem9hZFhJa20wWks5amlwdnBZdmQyRlFnNE50NF9nOUo3WTRoeVp3TjFWdXlqQ2YyUkFpMzJXZlNid1B4ZmdVdjhVVkktcUlKWjc5TjNQOTFnWnB4X2xxdF9aNFB0bzIwTTZqamw0MGkwUXRwMUdaRU5hbHoxN00zbFRBU
 l81WkY5Ql81dTIwN1FGbGh3UDYzbFRNMF8td1lCOVBzV2VtdGJUTEZYZmJFU0t6VGVzckVzQWwzQkVDMFotSndhMno3cEc3VHhvQWhON21hWDdKajVjbWtzdmJjVk05MENSNTVwbmtwOUM0Tm1BRWM2amw1dXRBSGlGOEdaV1A1V2lGVFFwVTBpYktXLUVycEMyblVvRVBmbFRPbVowM2lzaFNLbnZTSUFUQjBMSW95S1lhYm9tcU5NWkZhWDV5OWVjTGtFdmlmYS04dW8zRzNYSWFhQWk3TE5YRXpqQm9iZWlVSzBFeGJxaGd0VzNvbE85V1o1MGxqOWw5UXpGV3FWOGRiUThOeTdkdzRnT2wzNl93ZVNrbHJ3b19VVDA0Sm9Oc0IzOWFrUnJaWkdzaXJuamR1T0F4RWZaaXRLdHdTdkpZSzRtV0huSk5uRENMVlo2cVpzVG50NThjVjQ2cFY3T1FxckNpVnlQREU3Y1N0RW5neXhEbzRZdlpibDNrNndkaGxYOXAwZXNaOUdXbHNxcXlGVUJCc19QbVN2UUd6djZ3bDlWSnk4WnNKYmpIdlkwclZOUFJnN2FYTjlNOElsVWpia3B6RmdqY0VPZVVrZ1M5UFp5RURLYUw5U2NjeFJFbjI1OUR3MDFJZFJPS2U5Mnp3U1hSQUJlbVhBcVRaSGZPd1Z2VDBUS2JnWkwxcE5vb242NWRMR0hKZ2dYWmt6SjVHT3dvbFRkYkEwczVkaXRQZllxU3ZwQmpmVHpfQTZhTWl3bmFnamlET0QzT2doeTQxc1Q2UDdTWTFxanpfWkxjZ1puc1djWDlkOWc4TkpzZ1had184d2dUY3hRdW1TM3oxVTYxX2dlbndBNzNPaEs5MWl5YW90Z2ZySWNzOWxodm1taEcwRC1KX3lkQUxfdXNROWc0dHRlN1ptN0hMZDZOb1pCYnJFTkZ0ODRmejdJbjJxMXItM1lsYk9kMm1xRXIxZUdZMmtCTl
 h1eFc0XzlVZVFOZER5UHZPRFR0Ni1mR3FuMF9sd2dYOXJldUxsRzY1UjFKY29yMnczWmZBLWU3SEN3Y2tCTTBEcmhjZmwxdmhtcVY4WXpMcHBxUUhPa1F2YUpMNHE2ZG1ZS0thZmhGbXcxVk1qSnp5UWswUVNzazFWUGdzUmpta3l0YmpjZjRoenJNdVRMU0VQTGZVWGVPOEYzbEdLNE03bWlhblRPQ0xXSmRNWnc5dFlKSHVTQ0g3SjhZOUVwNS1XWTRBeUZlaFJfaDVSNHVYdlBPUmUzSzZQcWJibHlaMEJuclpCcDZnTUNvNVcwZkd5ZEdiQ1N6dzUzVndsY3FEWnJlb0p0Rk5pZFNzdTBtLUFub1g0SWxsSFFnYVB4SnlLYWRPSWpvalNKMnZTTTZCYXRkci1pR3VTbDJSZmswLXkyX3FFeDZRakNOQWFXaWNvM2RsS3VIY0h6TU13YzVXT1J4bzdweXdWYmtOUmpoOUVPZlkxSW51Tk11SjdfYWt2T0V5MGpMVXlCc04zR0hrTzlEUExFLTk2bVlIMWd6R19IbGQ5aVRpOWcxZTB5WjdBVkNEQzBoaVRZMXB5V0pVanpGVE91clJaYW5qOWl5MWdjcFdpeFVPN2xiWjl2aHFhdHg0VUh4VFRneS1IbUcydmRTYjhJbGl2bHNqLXVpM3dxUjBYeVNXRDFVYmVJUFVIZk15bTR2bXkzdkIyWEJKMEJnTF80bkx2VWQ2MEpFdXI1Z0ZOSUUtR0RSY0JwSkdPZXN4b1lyQktYU1I2QUd1UG84b2ptemFudUFIaF83OTI5OWg2aDdtN3JRZ0NxYzJ0Wjg1dU9YVHNzZzRYSW1kVjdCN3ZrcHRlUmt5WjZEQ1RFYW5GRmNvWEJzSThYMVFZeFFDRzgtdzltYlppTHNiRGN6bVV5Z3RiRkNQUXludjByclNiRzFUUWtmZnk4UGVfT0tRYkxSdWJNNG55dmZxWG81X21FcXA0T1d
 zMlJSMDhiSE9YTWpDU0FlYUwyaC1RRjg2MmRrLUNpV05ZSVVuUHhTYWkyWTEzeGVqVklwYkI1YkZzaVUzTWJmY2pyNnduRUVuMmhzWGx1aGpWVXFtUzNIOEZwZDFkS0pSa1lzM2NWZWRHTEhaRFZRM0hTWHlBWk1FbXNzX01kTUlGMFZhUjU0WTU3QXhhcnR5QUFmZy1OWWtkNVhtVkxPQWJnRFdCMzdrbEVPVEZCYXV4SGg4dXJjVk9neVF6Z1RNcTIwTWpEUzhzaDlZLUNHNUxSRHJiYVlRU2ZoR0VSYVFYcFpuVEdWX20tcDFpWU1zMEMzRFBJanMxSWIxZVR4X0lJbTFPRlBGOWcwWVJsbXFCdkx2bGtGeExqM0t2SGxQVEUwaUYyZ1JaMmN4NUMtckJGZ0dXaU1hRUQzdjcxTW0xQlFJeklaY1lfUUI5V3FsWEVaSmJWZHNZc0FmNm93eW9XckpVQUszTEswclRPaEdNS2VaUzlzUGxvZWU4T0x2OTluc2wxRUM0Z3F2MHJqdk9JQ0pVR0kwb1R1dXV5enhSbU41cHJtX2VycHNLbkM3QmRXV3VaLXRab0g0c2ZDeExiYVppeW8tQU1xdVRhMzB0ckFOV21rSUtuTHFubFRvcXJXZ1JiQjF3Q0hlVjA4WXR1ak9sQUdKc0dHRTRLVjc0X2QwSXZ2NXA3RUxQZlJJcU51cGVLdlpTZ0pxU19tQmU0eG5wTFZsWDhmaHRIOE9aSUxKQ25ZQUt5VHZyNGFoZG9jd0NrOE9JX0xVOG5wQ1Rpc1VFdEo1MXpON2dqUEs2eGhCazZ1YnNNeE9oalhNSjhUd01sWHZvMjcwSXdYV08wVm1lN3pGbnp2S3dnWjV0UlB4c1hwTjlySDBlLUxIZU9uNHIzWWtHeHlpRDFrMkUyM0s4ay02RmxhM2JwMV9DQktfdkM0VUhBU3NqQnJjd21kOHVvYzdJTDRsQmRfeldQbEtyUXp6bmxy
 ZVlMV2w3S1RmdG5ELXF0STlLMlFpWm9Ib3E4anZSYUJTTjZqUTk3RXhEb0E5dUk1LVRFc21UYlpCV3pGemdoOS1mbXBKZmQ1R3VNUXVhblJDN2VPbzh4bkJrVnI2UVVnZjVhYzV6Um0zc1ZBaktBVDJ5djc0dTNyOEJjUEJMcTBsc1gwTUpza3FlNEZhN193NXB5Q0Y4dS1RbVFkN2dmeUdPSW1OdTgySGJPSk5yMHg4Vm9NZU9uUExsVUhyY2cxNk43czY5ekU3SEM2UExpcHJobHdmY2JvMXlaZDZYVUxYNGI5MXJ4ME5SU0VpYURISGV1QS1LNWFQb1F6VVZiSFJ0cExvdHpwTEFTZkhwMWFhSEoyakRQUElfcVllbzkwWjVrR3RiV2plSTBYVDlzMy1TMk5pcW16Z2Q5WEMxNEJaUTM0UWpNdksyNUpJYXpqWW5FdGQzYUFYRWFZNU9CdGZ5R2NIcV96UmRaZlVQdDdDNk1LTFdRbnpzTXNWZHJ4cnpCcWRMMVV0NzlIQnZ5M3RlWDZ0RmJuYjR2ZkgxY3NZUl82a041T205VndHelRZYWNGM1dDTkNuOHljMk13N1Y4b25ZOXFLU0VLS1hRYk5KYlB1cEJsT29qLV9tV1drTkdmSy1TUHJoRmFGNF9LaDFTd25TelBydHRVVU9WMXg4ejNmUVFXZml5eVllcGd0VHVGSEZheHE0YXNCUjRQVndfUnBJN3c4QTNiSGR5ODQteWprZU0wU0k4WE5CdkRmVThRXzA2aVZjWkg1UWhwU2VENVpZNWotcDNzN3c4X2MtRXo3RHRZaHgyQzducWU2OFNVYmt3dmd4d2RUOFhaYzcySTJwSUFwYklPTzN0SEFIVmpvVHdVX3dsSHctSVZKbzZfSlBvRE5JbEdZcHdDZ21oMV9rb2FCLXFvMGdQd0UyeG1sRmdNeVVCd3lfWHNEdVRUcVJfT3pYVHBQbWdhTWNZMXJldEgzVjBDZ
 3BHaTBqYVZoN2NJSUpoVWNRcXRIVHl6S1hDTWVMRVBXYzJuVV9oXzB5U0tTanJMUmR1cHpkMTZ6V2sxdTRzdDRDak9CR1AxbloxVU14X3lGQ3ZsVVlESGY5OHhBelJNbUg0c1YxMnVMYmlCS2l0eTEwSG83X2N6T0htQ09LeE1oaFlhRmVrS19veUU3X3pWbTRjUzhHbEJiMUo2UVZMeHpGMXlORnlqeHdITEtnNURXUzN1T0JfSGpNdHlMOHh4WXhNR2FjNTh1X2g5ZEM5QThtVGJ5bEF6Wll6eTUtU3pvSVJYZHhVOGtBN1c0QzFWYmI1VGgyVHZmemF1Vk1mNVg0SWc1WTU4NzMtd3oxNVpHZW5xU3JreFVqU0tVUWVlZkI2eEg1aGtKeWs1cDZWY1JJNzF6SkVEVEU2LWZHSGsxTlNRd2QtS2tTaWlwMjI2d0JCOHZSVWdGQ1VZcy1EZC10TXF1aDdKZjlaRTU5amNzR0ZkTDJhamFRcjc4Z21VZEFVYS1HRHpQeHp3YkM0b1FKS29ObkNEZGc5WV94S3NHeEtDWnRVT1VjM0Z4MlptZFpfM292ZGExaHdyVDZpYVJLM0MxZnh0ZVpheE9IWkNvdW5MeU8wZUkzZ1Nnd2dkVERxODZ3TzY2U3pHdGRxYmo0bGZrT3NkRUYtUDNhQU1yOGNuclh3b2NOdGVpaVJ0YnVqLXhfNlVQUk5hWHJCV0lHRk1Mc2x3b1VlRXE1ZUpuOUhSYmdvd25vU3psOUdDWWdtdnRsb1ZIVHFVLXpNWk9TcmxPejA2aU1ZZjBjakliUDJtdHUyWHlDS3dkRnFsZHJqUWs3VmNUUEJkczluRjR2Z3lmOU1nSFVTeVpHTHFubHNtdG5ER1p4VTN0UmR1eXZfTFRLcDgxYVVQVVprb0EtTkMzdEFncHdQbUtodzVnY3M4U19aSC16VVNFd1BjLVR6NGtJSzhrSFVxQ2ZFY0pfMmhpX2RTWHRKbF
 B3TG9EeU95R1hTWkp5ZGIzb2hjblk3Z3RneGpQaU82Vmlwd1NZMXRVVUV1YmFKbHkzTGFwRjN0cXlEZXBBdHMxc2JDdzNSSm1HcE92WjlfaTk5SXZ6WjY1WDZPSDB1YUpDTWl6bFpzdGQwZ1FRMXl2ZTNQRDRaVHZPdzlMMm9Na0ZDQlFvQzBUalU5b0tPTHNpdlAzbTZOWjROLVpiaWFaNTIxbWU1ZjBWV1loRkN3RENxajRyUDZ5WmloOXVPTW5rWnNhZ3BtS0RlaVV6d1RpaENKdlRkZnBfbG1GQ3cyc0Jyd0lIVWJfdkxWY1RWNDd4NVNwSnhuS2dpWHpZUG8weElnYnY1bmZGWTJvM1NBWkZpSlNlNEJQbmFsX2FQLUFnNDdWM2h5NmNzT0xCM3l0VlNCRDdlNjFpU1VGWVhBUmZJVEVXa0VRaHBIWWJyRTlvemdldzdOLU5HaXdtWndOUy04SUFSbmRFS0tXSXRXb01fMllXVmYxS1ZoME8xQ2wwR0ZDV2NCNzFDLWxMazVJbkpKUm5Wd2dPQ1M2YUFKaEM2T2pIVVYydTR3TTdndFI1c1Y2Snk1NUxQcjFUbVpZQXAyVFNSMG0zUWMyN0ZKRnhxaFU2R20tZGtVNXZKbGtnSjUwY2xTUVVGcVl4Z0pDX1hSdWVpOXNzdkNmbnZVOW1ZSEFQZTU2Q2dXNWFiVGhSOEJCcTc2aTlxUjBlRVV4eFVWUUtCemFhVlB3TmVqaFRVYnpWcHZnNGlqSFRocFBlRzdDZ3hwQ00zT0pCaHFnS2k3RzVTeHFHYjdNVEhoclp2Q3I2WHZtZGdFc3NxWW9RdUQyYUQ4TlhjdVU0Mm1NVGwyZS1sY2pwU1E5R29hdlRHSjFCeFp2YWlYZzRNS1FGUjBjRDQzYkxsaXo2Y2NCeEEwZnJTU2dqbUhRNERxdHhjYkFiNFlPTDFlYkFQNFNSQnJwa3hGQW5fc1l6ci1aR0F0R0l3R1JfUHR
 RbjVLQ05yaXBueDRITVBmS2UtTHg4MzBIWFNxVGV5c0hRbGtuRlRSeFdwLXdNcUxPMlFhTHJnMlUzdnBDekloRmh4dG1tWnpPSE8zZmY2YTAySk9BaDVDek9GcG9oTDFXakl5a1RMd0dNMDZMQ25uNmhGeDVOZEhmVTlqaTdKNGZuT2RkcVh2ZnZ4TDhSN0wtM1d6SThIUVI4TkRHRzl6ZGtHZDUyQVlkNTBqUTZPN29qNUdkZldGMDdQTVY3WWFETjhGc1YwT19wZDM5bFpiUnM0SlV1Y0xWMzBXNGpqVGdselZGeXBaZEFxQXU0d2pWTVd5T1I0X1RSMnh6YW0wemx0ZXc1bm01TUk4NTlZYVhCVE95bkV5T18yRndDR2hzdmxQR2t5SHZuc050NFVya3pjRGswX0JaYUlYYWFNbUhxMUJQUWdiR0d6bUxNV0FXcFY0OUszdnBkN250WHFBZEVyN25VUnVpS2RSckVTYnpEUnAxclh2NExOMUdGNXRnRUFCZFhwYTVQVG9nVDM3cHUwb1BNNW5FZXFDeklRbmtjemMzUVk5SEZwY1J6bWFmbV9fSngxRFd0ak5qR1J0cVM4aHVUcVNKOG5ORl90ZXZsV2dwOU5uZU9KSUZwZkVMMnhYMTc2dnkyQ1FONTBFRzZZWmM4dXZreHFNUmk3OFNjdENEeXQ0WS5Sc3FFM1dad19XclIxRmtQc1RtWW1B"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultcreate.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultcreate.json b/providers/azurecompute-arm/src/test/resources/vaultcreate.json
new file mode 100644
index 0000000..604810e
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultcreate.json
@@ -0,0 +1,26 @@
+{
+  "id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults/kvvaultapilivetest",
+  "name": "kvvaultapilivetest",
+  "type": "Microsoft.KeyVault/vaults",
+  "location": "westeurope",
+  "tags": {},
+  "properties": {
+    "sku": {
+      "family": "A",
+      "name": "standard"
+    },
+    "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+    "accessPolicies": [{
+      "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+      "objectId": "5a7f4cb9-ce9d-4b31-87ce-f61083c4b0ea",
+      "permissions": {
+        "certificates": ["Get", "List", "Update", "Create", "Import", "Delete", "ManageContacts", "ManageIssuers", "GetIssuers", "ListIssuers", "SetIssuers", "DeleteIssuers", "Purge", "Recover"],
+        "keys": ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", "Purge"],
+        "secrets": ["Get", "List", "Set", "Delete", "Recover", "Backup", "Restore", "Purge"],
+        "storage": []
+      }
+    }],
+    "enabledForDeployment": false,
+    "vaultUri": "https://kvvaultapilivetest.vault.azure.net"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultcreatecertificate.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultcreatecertificate.json b/providers/azurecompute-arm/src/test/resources/vaultcreatecertificate.json
new file mode 100644
index 0000000..15b7aa6
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultcreatecertificate.json
@@ -0,0 +1,11 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/pending",
+	"issuer": {
+		"name": "Self"
+	},
+	"csr": "MIICszCCAZsCAQAwIzEhMB8GA1UEAxMYbXljZXJ0aWZpY2F0ZS5mb29iYXIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArrIwtQO60BI1vUkS/Vx0TQ5dBLjWBFfQFUHABJoKXCeloLrHWrWnhaxyj5jvEVGYF5OLBNeHd6PR43bmHKnzq3vhQXUA1sKBRxAJavSM9a+MKBpN39aKvSnqRNdnETE8kwNteIpbmDVMe18UnGtyhRbMKqJ73HpGyyRdiD8nTS9F65SCRQlKALNz0Vi3z52Loo6kRoZPAfcRkDAbbg7JxIuMEEcbrBR0dScR0m2OucYtR3PQ7PUQMXSsLwZmGAu1e/KuqjTNC6XpxRpWSTHf3kS1Q4LjNXde8sk1/5Xovzo/MlVQ7L2tt4pVK79ZkeePbL9ZSKsTc3Thi7G+o8pCewIDAQABoEswSQYJKoZIhvcNAQkOMTwwOjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBABoDgWVU0DqfhKsujIa4gUHyZKvRWhms0reqb4Ld9GkF4O6TV+TxibBUZRW3SSVvA+po8G7aX+E+si0BfQiwM1PutcK0f5WuYMiEkQ6xaiDhIblrouCYRCTiYmmt2+8iuKAtDNqgqMJjViGXUKcGQgz7UTEJY/LLlgxW2kDyfEJOhGls40AT7tuXAjZ6QPLT9vAdQ8B0L0JNzJ6lJcDe7KattWonjQ4cLZ7xvY0SwUyvabui1UkOFze/EEkLwnJjigvfWkzhoJS7j0Cp3nI08c5zd/rQGq1XNVb9plnjtQP0kwNVQdHVeTug9rqZCyuS3jqwa1prrXkZJyufMmuNSV0=",
+	"cancellation_requested": false,
+	"status": "inProgress",
+	"status_details": "Pending certificate created. Certificate request is in progress. This may take some time based on the issuer provider. Please check again later.",
+	"request_id": "550fcfd2c33440aea6cd354658f91ddb"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultcreatecertificaterequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultcreatecertificaterequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultcreatecertificaterequestbody.json
new file mode 100644
index 0000000..c85aeb1
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultcreatecertificaterequestbody.json
@@ -0,0 +1,21 @@
+{
+	"policy": {
+		"id": "myCertificate",
+		"issuer": {
+			"name": "Self"
+		},
+		"key_props": {
+			"exportable": false,
+			"key_size": 2048,
+			"kty": "RSA",
+			"reuse_key": false
+		},
+		"lifetime_actions": [],
+		"x509_props": {
+			"ekus": [],
+			"key_usage": [],
+			"subject": "CN\u003dmycertificate.foobar.com",
+			"validity_months": 12
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultcreatekey.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultcreatekey.json b/providers/azurecompute-arm/src/test/resources/vaultcreatekey.json
new file mode 100644
index 0000000..470007a
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultcreatekey.json
@@ -0,0 +1,15 @@
+{
+  "key": {
+    "kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/f5cfaa4b90a34710a646af83636a5c1b",
+    "kty": "RSA",
+    "key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+    "n": "zattdXaoaTAnEDPv38dpgkLSuVp56_7TNczuyBGy3GOF62LgLEId1i7You5R4SGAXJDVDWBVAFIcbw3ppgbn-DgCf4QbAWWREQUOvPNhFvm78Ey6tewofP5jyrCDeSBkjlXC5lRgd8XtVXv0JvNtOU_GbTLMVAGOwPE-0nZWXaD__nkO90AS_2D1tDywcZ7vKix9WjkjYTmY1CEw06-vsQJSYSaaL2M5MmE-S21sgoGZUv7a0jHxDR2rEX3okFoW0sjynz6yxCZtYUmUyDMpWdTIaqKu9ZhfxZPtb6T9E8yAStvma0M5xc70gfOj1LJRK8mMhLmB4lh0POj-2a4fBw",
+    "e": "AQAB"
+  },
+  "attributes": {
+    "enabled": true,
+    "created": 1509314506,
+    "updated": 1509314506,
+    "recoveryLevel": "Purgeable"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultcreatekeyrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultcreatekeyrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultcreatekeyrequestbody.json
new file mode 100644
index 0000000..bfb19a2
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultcreatekeyrequestbody.json
@@ -0,0 +1,7 @@
+{
+  "attributes": {
+    "enabled": true
+  },
+  "key_size": 2048,
+  "kty": "RSA"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultcreaterequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultcreaterequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultcreaterequestbody.json
new file mode 100644
index 0000000..0b0742d
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultcreaterequestbody.json
@@ -0,0 +1,21 @@
+{
+  "location": "westeurope",
+  "properties": {
+    "tenantId": "myTenantId",
+    "sku": {
+      "location": "westeurope",
+      "name": "standard",
+      "family": "A"
+    },
+    "accessPolicies": [{
+      "objectId": "myIdentityObjectId",
+      "tenantId": "myTenantId",
+      "permissions": {
+        "certificates": ["Get", "List", "Update", "Create", "Import", "Delete", "ManageContacts", "ManageIssuers", "GetIssuers", "ListIssuers", "SetIssuers", "DeleteIssuers", "Purge", "Recover"],
+        "keys": ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", "Purge", "Encrypt", "Decrypt", "Sign", "Verify", "WrapKey", "UnwrapKey"],
+        "secrets": ["Get", "List", "Set", "Delete", "Recover", "Backup", "Restore", "Purge"],
+        "storage": []
+      }
+    }]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultdeletecertificate.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultdeletecertificate.json b/providers/azurecompute-arm/src/test/resources/vaultdeletecertificate.json
new file mode 100644
index 0000000..eba51a6
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultdeletecertificate.json
@@ -0,0 +1,58 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"x5t": "K7HXO6YIK6xwCX8W1InUKsJV9Rk",
+	"cer": "MIIDTDCCAjSgAwIBAgIQVA+XomvgS56ybBWv2MnacjANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wHhcNMTcxMDMwMDY0NDI3WhcNMTgxMDMwMDY1NDI3WjAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCusjC1A7rQEjW9SRL9XHRNDl0EuNYEV9AVQcAEmgpcJ6WgusdataeFrHKPmO8RUZgXk4sE14d3o9HjduYcqfOre+FBdQDWwoFHEAlq9Iz1r4woGk3f1oq9KepE12cRMTyTA214iluYNUx7XxSca3KFFswqonvcekbLJF2IPydNL0XrlIJFCUoAs3PRWLfPnYuijqRGhk8B9xGQMBtuDsnEi4wQRxusFHR1JxHSbY65xi1Hc9Ds9RAxdKwvBmYYC7V78q6qNM0LpenFGlZJMd/eRLVDguM1d17yyTX/lei/Oj8yVVDsva23ilUrv1mR549sv1lIqxNzdOGLsb6jykJ7AgMBAAGjfDB6MA4GA1UdDwEB/wQEAwIFoDAJBgNVHRMEAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBRnlX51KtyJ/m/V8I/3il4cAW/HOzAdBgNVHQ4EFgQUZ5V+dSrcif5v1fCP94peHAFvxzswDQYJKoZIhvcNAQELBQADggEBAAbSFuMRMbXyH80iA/jU7vuUCYe0Ra/wTTB1qVHTBuqQ/W8RI01mdqI9+GAPOTyN94XPPYVpSz9ZQ3P0/dhgcsahW5bZQkC0CcUSE5R7JUOKI5Up6n8zZM/unHlC6ZcEpNA/scObPKhQXdZayxgf2/p30bii4CiyS7ADEH92xMnzo1Eu9Dckxh1MRDypfxMY9YIzggks
 iY78BxoNsRDyxNjeRHVUxAIJ3n9TUv+WG31r7rMOIs6ZPsWc96AzUHHAZREVTEh2kiKKIenbMXn1tCpF6/GJKGfp7rt5ObUoQAlnn7kgAceteKZHEMgRZ4c4EQq+yqBw3hJrz4dOabJcmcU=",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509345867,
+		"exp": 1540882467,
+		"created": 1509346467,
+		"updated": 1509346472,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"selfsigned": "true"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/policy",
+		"key_props": {
+			"exportable": true,
+			"kty": "RSA",
+			"key_size": 3072,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pkcs12"
+		},
+		"x509_props": {
+			"subject": "CN=mycertificate.foobar.com",
+			"ekus": ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 12,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "AutoRenew"
+			}
+		}],
+		"issuer": {
+			"name": "Self"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346452,
+			"updated": 1509346474
+		}
+	},
+	"pending": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/pending"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultdeletecertificatecontacts.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultdeletecertificatecontacts.json b/providers/azurecompute-arm/src/test/resources/vaultdeletecertificatecontacts.json
new file mode 100644
index 0000000..ca89576
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultdeletecertificatecontacts.json
@@ -0,0 +1,8 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/contacts",
+	"contacts": [{
+		"email": "foo@bar.com",
+		"name": "Foo bar",
+		"phone": "867-5309"
+	}]
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultdeletecertificateissuer.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultdeletecertificateissuer.json b/providers/azurecompute-arm/src/test/resources/vaultdeletecertificateissuer.json
new file mode 100644
index 0000000..73421fe
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultdeletecertificateissuer.json
@@ -0,0 +1,21 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/issuers/globalsign01",
+	"provider": "GlobalSign",
+	"credentials": {
+		"account_id": "imauser"
+	},
+	"org_details": {
+		"zip": 0,
+		"admin_details": [{
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"email": "adminguy@certsforme.com",
+			"phone": "867-5309"
+		}]
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346474,
+		"updated": 1509346479
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultdeletecertificateoperation.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultdeletecertificateoperation.json b/providers/azurecompute-arm/src/test/resources/vaultdeletecertificateoperation.json
new file mode 100644
index 0000000..800f399
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultdeletecertificateoperation.json
@@ -0,0 +1,11 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myTempCertificate/pending",
+	"issuer": {
+		"name": "Self"
+	},
+	"csr": "MIIEtzCCAp8CAQAwJzElMCMGA1UEAxMcbXl0ZW1wY2VydGlmaWNhdGUuZm9vYmFyLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMmt2TbL1ndbSggTwx2l3k/ZUzt0IGO/FMB/oqpmc5izy2KGi0/uSoEdFA9cSqfctL3FGx2J1cFVTz287cvLB8HB3A4svAoPnKsZmKpXuYbF4fK2wQGXm/iNk+JVq1KL0lfoqW2g52lHDM85XURMn8YCkAGIKeTlOVyEn7EMBuBumcJbszj0g56Ij+VKmxoua/Ja4ONmIGsKdyZRBEuvFQ1GTnJUvCWHwyo1pT0M5EY/VL9ikc283DSvpQcfvNelQgQfWCpTRX1Q7nTUHk14DD4d/Y6OdbjcVuqE0Jdqdw6MXfU2zrkPo/nZBf5GHsUChiaxzVeEafPjWKvqVDzhEYXpmMB5SDAELaQtV6PoX+kxcjAO4K//BQtwneHHVF/Sh+7ke3nNUlSf4Mjn541wS7LdkBDOlTnKdYu+DhfbdkRD4E9LPiDduWDWHZs051uFBecR93JaZmX2b376RORQygDkBRga/MNENoEEnsz4zmoMYCGspZhRXEC9Uts1hzYEtwM1hyLqJlfadX/sct20N4JkhDkM8NG2V43R8jcnKFmzjfv6Yc1tuiQ1GQpYNFPJWh+fakAZkt7IwYsvy1CQg92Yvi3ne9zRTBn00enDpBTWaGCZ84gYYaT7Yfyo7/WRTjinYt6R0+u8l0AmZb0xkgxEACIQoyrg+oWQZI4YrneRAgMBAAGgSzBJBgkqhkiG9w0BCQ4xPDA6MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAgEAr8RMKLLpGG31Mq4Dor6Tf11AoiHCLH33MUqblF1VfDiw0++qBZ1dgm0D
 +uzQph/bZ6jKe/PUWpS1bErfaOt3iaVNOHom8jP/U3kZiYWvc/YHetU03prm1Qb+izNZA97NNeZRsuCXMAkNAHQnXa/rz/zG6BmGXFigh55wglX6aB8PnfKZb7N6RCct8BsKSV8uPpxXzRWPKrv7TA2RKfMifUD/Dzt7FSDuYJ8FGkvQNX012RXb2DqHp8tbZgUSj7iXdoZMZ1jfwlh6P61yhfItbF4SYvtBd9PTWIxP6SkCfDjJ7f0/ofwoV2DvAiwfH7URdQIMC+B8dPCqbjya3Ku+B2fWXXhdG7gJqa1zRY066QTIsHwfwd3WbeLQxCcBUEQUG0u23gj9fDX81fvKsgHtN9Nod5wXsdLtjjpHpJQJlDanII4H3fvDxAOlqSnxxEhjL9uA3YXUERMGGjExXA5kCOqKrdfGT5x4yosuNutylvF8YYn8r+mvMgegtVl8XmKnyP+uESSE2krVVmnSM2gveq7ILxBvanq70LmQVeYQB4AlLtUsxPUPIPiOryDI39KrlqWKdl3/oC7Gx+WbVzXxs37NEwt/tx8E+r1Nq/jRFxP0QlyyUdjpiPXjUpuCdn4y6erpCuahbMP+CZNCNgeEh1v2pNljuaGCIB+VA2Fz/oU=",
+	"cancellation_requested": true,
+	"status": "inProgress",
+	"status_details": "Pending certificate created. Certificate request is in progress. This may take some time based on the issuer provider. Please check again later.",
+	"request_id": "32051e4e4ac947c5b9ad1b6737bee7c0"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultdeletekey.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultdeletekey.json b/providers/azurecompute-arm/src/test/resources/vaultdeletekey.json
new file mode 100644
index 0000000..9ca672e
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultdeletekey.json
@@ -0,0 +1,15 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/1374543b3de34500a97d075991ee3893",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "tY2pzXPfU7NFYCWvZB1gJNAetkgJ7Qi75lTVOzVns9KjFFo6e_F9GSETZbAYl5oMwfLtdqQqT5fxzWDk0sYlz09HXvCCoYmbzobd3gJ6-WLAqhtCbBikr5HAIlCzy_UqKT--WhEw8AT_EJFBPIY9xNktqnaNZuRBmjmXinzT02qUmBZRsAdJmaYfG9IZSmToOkb54OytI5TreWN0JvceoQ3GSeFLMC5PUmXP6HmZliOzBBHWnXNq3H7a3qfWV3rxT2QpbrIuz18ZqOVp7o5868kN8knKytVcqEzmdiQUdabkqbrwuh-z_IEre9AqTfw6OjUUmLjs4lyKcpWLYFh8KJuML1ub-8u0VgNGwczUZ7aAld1iwGMsoMmQfMRDOnv-9pqtY-y40ZWpBGXpzFV-IvtKHnqQk_vWqowpE8xwx7yZ74z9XNgS9TmkVpcC-ONbEfNE1sez0Zf-RZ9eOm_7WSxxH6OJYtJI7wotBXYoy1bJaqo7mgHs1IUOFhSE-Evj",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335925,
+		"updated": 1509335925,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultdeletesecret.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultdeletesecret.json b/providers/azurecompute-arm/src/test/resources/vaultdeletesecret.json
new file mode 100644
index 0000000..bff4c9d
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultdeletesecret.json
@@ -0,0 +1,10 @@
+{
+	"contentType": "aNewSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/8c418537cbc948539ea2ac12c0bfcfb4",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335944,
+		"updated": 1509335944,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultget.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultget.json b/providers/azurecompute-arm/src/test/resources/vaultget.json
new file mode 100644
index 0000000..46de8b9
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultget.json
@@ -0,0 +1,26 @@
+{
+  "id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults/kvvaultapilivetest",
+  "name": "kvvaultapilivetest",
+  "type": "Microsoft.KeyVault/vaults",
+  "location": "westeurope",
+  "tags": {},
+  "properties": {
+    "sku": {
+      "family": "A",
+      "name": "standard"
+    },
+    "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+    "accessPolicies": [{
+      "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+      "objectId": "5a7f4cb9-ce9d-4b31-87ce-f61083c4b0ea",
+      "permissions": {
+        "certificates": ["Get", "List", "Update", "Create", "Import", "Delete", "ManageContacts", "ManageIssuers", "GetIssuers", "ListIssuers", "SetIssuers", "DeleteIssuers", "Purge", "Recover"],
+        "keys": ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", "Purge"],
+        "secrets": ["Get", "List", "Set", "Delete", "Recover", "Backup", "Restore", "Purge"],
+        "storage": []
+      }
+    }],
+    "enabledForDeployment": false,
+    "vaultUri": "https://kvvaultapilivetest.vault.azure.net/"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetcertificate.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetcertificate.json b/providers/azurecompute-arm/src/test/resources/vaultgetcertificate.json
new file mode 100644
index 0000000..31e982f
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetcertificate.json
@@ -0,0 +1,55 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"x5t": "K7HXO6YIK6xwCX8W1InUKsJV9Rk",
+	"cer": "MIIDTDCCAjSgAwIBAgIQVA+XomvgS56ybBWv2MnacjANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wHhcNMTcxMDMwMDY0NDI3WhcNMTgxMDMwMDY1NDI3WjAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCusjC1A7rQEjW9SRL9XHRNDl0EuNYEV9AVQcAEmgpcJ6WgusdataeFrHKPmO8RUZgXk4sE14d3o9HjduYcqfOre+FBdQDWwoFHEAlq9Iz1r4woGk3f1oq9KepE12cRMTyTA214iluYNUx7XxSca3KFFswqonvcekbLJF2IPydNL0XrlIJFCUoAs3PRWLfPnYuijqRGhk8B9xGQMBtuDsnEi4wQRxusFHR1JxHSbY65xi1Hc9Ds9RAxdKwvBmYYC7V78q6qNM0LpenFGlZJMd/eRLVDguM1d17yyTX/lei/Oj8yVVDsva23ilUrv1mR549sv1lIqxNzdOGLsb6jykJ7AgMBAAGjfDB6MA4GA1UdDwEB/wQEAwIFoDAJBgNVHRMEAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBRnlX51KtyJ/m/V8I/3il4cAW/HOzAdBgNVHQ4EFgQUZ5V+dSrcif5v1fCP94peHAFvxzswDQYJKoZIhvcNAQELBQADggEBAAbSFuMRMbXyH80iA/jU7vuUCYe0Ra/wTTB1qVHTBuqQ/W8RI01mdqI9+GAPOTyN94XPPYVpSz9ZQ3P0/dhgcsahW5bZQkC0CcUSE5R7JUOKI5Up6n8zZM/unHlC6ZcEpNA/scObPKhQXdZayxgf2/p30bii4CiyS7ADEH92xMnzo1Eu9Dckxh1MRDypfxMY9YIzggks
 iY78BxoNsRDyxNjeRHVUxAIJ3n9TUv+WG31r7rMOIs6ZPsWc96AzUHHAZREVTEh2kiKKIenbMXn1tCpF6/GJKGfp7rt5ObUoQAlnn7kgAceteKZHEMgRZ4c4EQq+yqBw3hJrz4dOabJcmcU=",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509345867,
+		"exp": 1540882467,
+		"created": 1509346467,
+		"updated": 1509346467,
+		"recoveryLevel": "Purgeable"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/policy",
+		"key_props": {
+			"exportable": false,
+			"kty": "RSA",
+			"key_size": 2048,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pkcs12"
+		},
+		"x509_props": {
+			"subject": "CN=mycertificate.foobar.com",
+			"ekus": ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 12,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "AutoRenew"
+			}
+		}],
+		"issuer": {
+			"name": "Self"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346452,
+			"updated": 1509346452
+		}
+	},
+	"pending": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/pending"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetcertificatecontacts.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetcertificatecontacts.json b/providers/azurecompute-arm/src/test/resources/vaultgetcertificatecontacts.json
new file mode 100644
index 0000000..ca89576
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetcertificatecontacts.json
@@ -0,0 +1,8 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/contacts",
+	"contacts": [{
+		"email": "foo@bar.com",
+		"name": "Foo bar",
+		"phone": "867-5309"
+	}]
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetcertificateissuer.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetcertificateissuer.json b/providers/azurecompute-arm/src/test/resources/vaultgetcertificateissuer.json
new file mode 100644
index 0000000..dd08fe9
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetcertificateissuer.json
@@ -0,0 +1,21 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/issuers/globalsign01",
+	"provider": "GlobalSign",
+	"credentials": {
+		"account_id": "imauser"
+	},
+	"org_details": {
+		"zip": 0,
+		"admin_details": [{
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"email": "adminguy@certsforme.com",
+			"phone": "867-5309"
+		}]
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346474,
+		"updated": 1509346474
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetcertificateoperation.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetcertificateoperation.json b/providers/azurecompute-arm/src/test/resources/vaultgetcertificateoperation.json
new file mode 100644
index 0000000..15b7aa6
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetcertificateoperation.json
@@ -0,0 +1,11 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/pending",
+	"issuer": {
+		"name": "Self"
+	},
+	"csr": "MIICszCCAZsCAQAwIzEhMB8GA1UEAxMYbXljZXJ0aWZpY2F0ZS5mb29iYXIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArrIwtQO60BI1vUkS/Vx0TQ5dBLjWBFfQFUHABJoKXCeloLrHWrWnhaxyj5jvEVGYF5OLBNeHd6PR43bmHKnzq3vhQXUA1sKBRxAJavSM9a+MKBpN39aKvSnqRNdnETE8kwNteIpbmDVMe18UnGtyhRbMKqJ73HpGyyRdiD8nTS9F65SCRQlKALNz0Vi3z52Loo6kRoZPAfcRkDAbbg7JxIuMEEcbrBR0dScR0m2OucYtR3PQ7PUQMXSsLwZmGAu1e/KuqjTNC6XpxRpWSTHf3kS1Q4LjNXde8sk1/5Xovzo/MlVQ7L2tt4pVK79ZkeePbL9ZSKsTc3Thi7G+o8pCewIDAQABoEswSQYJKoZIhvcNAQkOMTwwOjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBABoDgWVU0DqfhKsujIa4gUHyZKvRWhms0reqb4Ld9GkF4O6TV+TxibBUZRW3SSVvA+po8G7aX+E+si0BfQiwM1PutcK0f5WuYMiEkQ6xaiDhIblrouCYRCTiYmmt2+8iuKAtDNqgqMJjViGXUKcGQgz7UTEJY/LLlgxW2kDyfEJOhGls40AT7tuXAjZ6QPLT9vAdQ8B0L0JNzJ6lJcDe7KattWonjQ4cLZ7xvY0SwUyvabui1UkOFze/EEkLwnJjigvfWkzhoJS7j0Cp3nI08c5zd/rQGq1XNVb9plnjtQP0kwNVQdHVeTug9rqZCyuS3jqwa1prrXkZJyufMmuNSV0=",
+	"cancellation_requested": false,
+	"status": "inProgress",
+	"status_details": "Pending certificate created. Certificate request is in progress. This may take some time based on the issuer provider. Please check again later.",
+	"request_id": "550fcfd2c33440aea6cd354658f91ddb"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetcertificatepolicy.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetcertificatepolicy.json b/providers/azurecompute-arm/src/test/resources/vaultgetcertificatepolicy.json
new file mode 100644
index 0000000..97e126a
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetcertificatepolicy.json
@@ -0,0 +1,37 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/policy",
+	"key_props": {
+		"exportable": false,
+		"kty": "RSA",
+		"key_size": 2048,
+		"reuse_key": false
+	},
+	"secret_props": {
+		"contentType": "application/x-pkcs12"
+	},
+	"x509_props": {
+		"subject": "CN=mycertificate.foobar.com",
+		"ekus": ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"],
+		"key_usage": ["digitalSignature", "keyEncipherment"],
+		"validity_months": 12,
+		"basic_constraints": {
+			"ca": false
+		}
+	},
+	"lifetime_actions": [{
+		"trigger": {
+			"lifetime_percentage": 80
+		},
+		"action": {
+			"action_type": "AutoRenew"
+		}
+	}],
+	"issuer": {
+		"name": "Self"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346452,
+		"updated": 1509346452
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetdeleted.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetdeleted.json b/providers/azurecompute-arm/src/test/resources/vaultgetdeleted.json
new file mode 100644
index 0000000..bb3bb2c
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetdeleted.json
@@ -0,0 +1,12 @@
+{
+  "id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/providers/Microsoft.KeyVault/locations/westeurope/deletedVaults/kvvaultapilivetest",
+  "name": "kvvaultapilivetest",
+  "type": "Microsoft.KeyVault/deletedVaults",
+  "properties": {
+    "vaultId": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults/kvvaultapilivetest",
+    "location": "westeurope",
+    "tags": {},
+    "deletionDate": "2017-10-29T22:06:02Z",
+    "scheduledPurgeDate": "2018-01-27T22:06:02Z"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetdeletedcertificate.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetdeletedcertificate.json b/providers/azurecompute-arm/src/test/resources/vaultgetdeletedcertificate.json
new file mode 100644
index 0000000..73635de
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetdeletedcertificate.json
@@ -0,0 +1,55 @@
+{
+	"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedcertificates/myRecoverableCertificate",
+	"deletedDate": 1509346545,
+	"scheduledPurgeDate": 1517122545,
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"x5t": "-qEnW6P9TdfOOXzbNQNS5ZKveRo",
+	"cer": "MIIFNDCCAxygAwIBAgICQ0MwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEhMB8GA1UEAwwYRm9vYmFyIEludGVybWVkaWF0ZSBDQSAxMB4XDTE3MTAyODIyNTIxNFoXDTE4MTEwNzIyNTIxNFowUTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEcMBoGA1UEAwwTdGVzdHNpdGUuZm9vYmFyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKlPGmdiqKloSbUri9gvo2lyS0x2axSpeTfgIxI4Qnqhq8wMkih+SuO8+2rzIUd3S9nYqVww6yy+qHiJLXi3DKVYM/jgJnF+PlUoXxulD1abN8kX+TCKuHeAfTSIjM6WSgimGqW3hoB6bYHsaUFaAIg5FYbg5/IpbEMnD2yjU4M/nHVbxRwPqHGYdYfSqGDeHYjDb8GdA/+N0JDEoMVflTQKrDzq9R0lwOg+kICem1D+kww9ajyTu/7QdE8oOhAzuqFIVkCyZwpkrs576ng34mP04vpGcBs8YiKODydtFl2p5labXr5la0LVpLJL6rUkM3EhWOhQ0s+fCGtfrlmFRMCAwEAAaOCAQ8wggELMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNPsyKBhnCjL7pVBLRYK3jaoZ8PfMHIGA1UdIwRrMGmAFAf9rGqvLeJheBNJOHBKTG3Oz32PoU2kSzBJMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEPMA0GA1UECgwGRm9vYmFy
 MRQwEgYDVQQDDAtGb29iYXIgUm9vdIICQkIwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQA4sFKv4JDZ0+CVjcHL9bkTpk5I2L45xXk3d7GrhBpGveyy8vlb/g7P0qyAVo0UnB+eRTtwk6GTsJdzz4FBem+FDq8ZO/N51Rn4ZJQbDg24eGErK4rpbOo5OQgKKhTKjjBYwsAsIOkJ1TKQDQ3++Kqw3cWh/vlCWoxGPSMOeU/Iro34IWzSeEREMamYo5kIYq2ERCcVSoTcYB87cTYMU+ORyQSEx/OncDuAKm45ub92By5NpeFVMk+8ibifgzbNJHVnaZUVg8ScdM1A4Db6WAL0SUsYIawrnQ+TENs+6Ekls+wu8G5FAmbtOEV0WOafGvdcnELn5IPXlkvLbiRx5EChG+nF3XrLgn3dBQwP2cGrI/IPRm1XfaaBAkMSkf6St5TX3C40g1CGcNSVoKBYBB2Di+hPXwTHImGggR1JF34ljHCokMoPxmr7lP9pam0dhP/SSpIwxfsvDJylBgUEqTr3tsVDIDfMtJjudK7A7H1HMoqEiqlzRvJIEZ1koOxANFcQ1f9am2PPUNFvfK9IbLQlV8d4k1w6xBAeOVke79lJI9pTTCSVb+PTDniEL79JXjmjQUoKE4zo1u41d+wLu3dEGM27GI7BdLYt6bRsolZvrbey7Nn4c0t4ug4B4GTd1SLLVJns/IRLBrNr1anBJ7u9WFruBUEWwtdxAwSoXdtIIQ==",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509231134,
+		"exp": 1541631134,
+		"created": 1509346510,
+		"updated": 1509346510,
+		"recoveryLevel": "Recoverable+Purgeable"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myRecoverableCertificate/policy",
+		"key_props": {
+			"exportable": true,
+			"kty": "RSA",
+			"key_size": 2048,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pem-file"
+		},
+		"x509_props": {
+			"subject": "CN=testsite.foobar.com, O=Foobar, S=California, C=US",
+			"ekus": ["1.3.6.1.5.5.7.3.1"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 13,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "EmailContacts"
+			}
+		}],
+		"issuer": {
+			"name": "Unknown"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346510,
+			"updated": 1509346510
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetdeletedkey.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetdeletedkey.json b/providers/azurecompute-arm/src/test/resources/vaultgetdeletedkey.json
new file mode 100644
index 0000000..687a1cc
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetdeletedkey.json
@@ -0,0 +1,18 @@
+{
+	"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedkeys/myRecoverableKey",
+	"deletedDate": 1509335960,
+	"scheduledPurgeDate": 1517111960,
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myRecoverableKey/274f6c69b94b41359a5932226425eb43",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "urhKlXbEGvYetOSH-GLytvSJ5djS0-5SKBtFOlJ2885PE0s_ZbnkRURDm2fImv_RV763HKSUQbEolQNs8I99N-3uCkrDStVZ6MPii9-0U6lrEkX7LrMRNYCfPAaSSZhSjCbsyqX9Y-N_A5Jz9uHNuXvpjQ9N7ojUK7fqqhnJKcJ6l6YsGOhGCD3uei4SL5GzbSAn2auIK51lj77UXjBZaudnNWTiKaCbTAmSmEe13DOJkg82_7Y1eWea3NJn4T2nY8WqRJCp4hzBsPBmFXjE1lgFWcSjm_afiSb0mCUP7v7tSOLR3xUBv9WgMO7p4_ce_--A9ZWP418Uqq0COcHAWQ",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335950,
+		"updated": 1509335950,
+		"recoveryLevel": "Recoverable+Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetdeletedsecret.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetdeletedsecret.json b/providers/azurecompute-arm/src/test/resources/vaultgetdeletedsecret.json
new file mode 100644
index 0000000..cd57373
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetdeletedsecret.json
@@ -0,0 +1,13 @@
+{
+	"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedsecrets/myRecoverableSecret",
+	"deletedDate": 1509335980,
+	"scheduledPurgeDate": 1517111980,
+	"contentType": "aNewSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/myRecoverableSecret/d7194ca6b0214d0ba382353109cd7e58",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335958,
+		"updated": 1509335958,
+		"recoveryLevel": "Recoverable+Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetkey.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetkey.json b/providers/azurecompute-arm/src/test/resources/vaultgetkey.json
new file mode 100644
index 0000000..66fcf42
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetkey.json
@@ -0,0 +1,15 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/bd6566ec707e4ad89f4ab9577d9d0bef",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "2ZWsir4hwVxFTQXfWN7Vy1zA33jg1kxUMHmkmEFtVjGDByzmMfEXpnPziNCtYppBtpNT4AJEVQ60aIgSLNrUYBMoeiI2HCf2NM0NTdwYp7wq5tImtbGDASdDXQ1v3Bv3hXGh3CVmN2VLRf0OmoXnZUG_2UZZ05iPXOY6lNFfq8L81v0ZCMiXwFvNVhZ_fzppzhnwuHQf-X6Lnvrd1ocFqF8IFjV3663eumAfZmBLPP6tmiAZYW3G68_G0I2CHLtTPFX05aN51Jn42RITgcs63HFMT_iVW5556YR0BwtqkCXIUgTD714Fipz7EKGqhHsqND7YUSKpiRVQhfoZEckAkQ",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335902,
+		"updated": 1509335902,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetkeyversions.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetkeyversions.json b/providers/azurecompute-arm/src/test/resources/vaultgetkeyversions.json
new file mode 100644
index 0000000..c534f8f
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetkeyversions.json
@@ -0,0 +1,23 @@
+{
+	"value": [{
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/1374543b3de34500a97d075991ee3893",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335925,
+			"updated": 1509335925,
+			"recoveryLevel": "Purgeable"
+		}
+	}, {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/bd6566ec707e4ad89f4ab9577d9d0bef",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335902,
+			"updated": 1509335923,
+			"recoveryLevel": "Purgeable"
+		},
+		"tags": {
+			"purpose": "testing"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetsecret.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetsecret.json b/providers/azurecompute-arm/src/test/resources/vaultgetsecret.json
new file mode 100644
index 0000000..9f1e929
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetsecret.json
@@ -0,0 +1,11 @@
+{
+	"value": "-----BEGIN RSA PRIVATE KEY-----\\nMIIEogIBAAKCAQEAvZiOgV6b4EmGiasBskXYnTaRyWzBHBGnWB11BzFN3FGigfWx\\nVvjI7Ox1SHTx+vGsnjbqQPvIP4JnPEsNcWLyHa6tNAcnj/M7BuyIwdD5+Hvs6kOe\\nPuSOJUf8dRjPMUpr6rcUcBmmOwTnKOH4rdpb6jXNnuCIHP+lgXCeRWveZ62TjEB+\\n9aB8W8UHH854FGebiUd/aY0tpCFC7wkWz3KbgmjmY2vSe2U98Yj4+l/IWydIZ7ON\\nLicteEEIGbNM0o2QSYhQBCJSw5RixDpPlrUUB094qgqUOyW0k8PvjibGxxTh0LYy\\nWqWydPF0XaqFRQ6v36UvEiVGwzVsLwsJL/QVtQIDAQABAoIBAEJ6790lE3s9zNMR\\nB3M/UoktzUjXvY7eEdOv4I05GJgcd+MiB6D7c1jAQQ+7Ee5wN5rynolSwBCk5RYb\\nKweLLmKCEXGg4Jp1K0luPzXW1Q/wRE6Qjzh2Y/FmoHtey6f49IZE1AHKvKMNQRDw\\ny4YKfxhM7WC8Un34lkwg9R5aiI3JkOG9/yNkOGrJfQnGUKt+AOAdu6fNYsRLWAPo\\nG3vWSNIgwaG5WL5cKd1gacbGBlc6tLB7+LrZuNrqln5ibTtN6QJvRF9KfOrMSvxy\\nL/xiHRpyzec/jrxJxAIIwFHiw2jbLdxNqDaVPFA6X1Cks4fvY40KymOS8Ecmkgx4\\nC6/ZqLECgYEA38rL8zmbJRRWgrxSoROucaN/9DyvE8Hd97s1zf3I0LIF+GI3JdcN\\nDV5O5VDIgQ7QZ55lOaTqJ0f2fOQZF1UbTU1gBUHVF6j1nv6Xic3OV+ZmhTMbt0Op\\nWxPaKup6dkNEAe/Xg0p308r8xw/psh4/gjL1ICHwycjUlz9FQz8FLGsCgYEA2OHc\\n/F4vAdK04U4w6A
 yivuJdIsDAks1ikl+3TqgzyesPg+DpKVNSy6DhraDFKdRqWhbK\\nDqigTud8TVk9kmyF3WIb1BDf4IrxlTK08s6Jf25QA/lBlwIst3rejqWwRBY2fJp4\\nO8hU31xNLd8nZq8tKYaP+yvyI6fSC+9ZIgyATl8CgYBtTlYzZG2cvMRMcsNBHaXU\\np3E1z/YLhmNuPqhXBp/xHyK/YOliuBkN8IREiSKFtsCf+8OhViVwLjv8YETJGq6N\\nIT/HEZKNTd86W0uU6UrhsA1e/cmJx6iObbHfyEssPEqZT5ZJ8DN65Oh2KhWRBCks\\n5MrJeQps5ITBowunfr5+JQKBgBln09goPD9tbEzcOPRlzoanw5s3kxdfQcW9up5X\\nK8HibC3ZodZ6cT9zOBx7sbzlqhOlicPP0v+LNE9nPcQyPDgjrvjXhTIrdIMyrmmm\\n8gpgZLUidKF42r4fgYSaOhyvsXBFNAJkxDRp/ox6EIaBzLuJjMIycqnklcFaJ0nK\\nxxjnAoGAU/3jRok74Yn0MY183UCXICf/WxVYzwEi3cyRWVh6gAo2ExNye97rau/B\\nY2woAcVxEN9h1HNirq8Z2AwrZKd/BcBnvulZqECeH5zBQ0W56ADX72r+lzOAxTJa\\nU1AIlNCIkfsQ5CpIoYsVoNEM8P+GyS8B9kaEmk/FVKldRTKJqkI=\\n-----END RSA PRIVATE KEY-----\\n",
+	"contentType": "testSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/b936ececbc674f3bb1367ae50d28ada0",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335932,
+		"updated": 1509335932,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultgetsecretversions.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultgetsecretversions.json b/providers/azurecompute-arm/src/test/resources/vaultgetsecretversions.json
new file mode 100644
index 0000000..c09ca45
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultgetsecretversions.json
@@ -0,0 +1,25 @@
+{
+	"value": [{
+		"contentType": "aNewSecretKey",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/8c418537cbc948539ea2ac12c0bfcfb4",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335944,
+			"updated": 1509335944,
+			"recoveryLevel": "Purgeable"
+		}
+	}, {
+		"contentType": "testSecretKey",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/b936ececbc674f3bb1367ae50d28ada0",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335932,
+			"updated": 1509335934,
+			"recoveryLevel": "Purgeable"
+		},
+		"tags": {
+			"purpose": "testing"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultimportablecert.txt
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultimportablecert.txt b/providers/azurecompute-arm/src/test/resources/vaultimportablecert.txt
new file mode 100644
index 0000000..f364c85
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultimportablecert.txt
@@ -0,0 +1,58 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCipTxpnYqipaEm
+1K4vYL6NpcktMdmsUqXk34CMSOEJ6oavMDJIofkrjvPtq8yFHd0vZ2KlcMOssvqh
+4iS14twylWDP44CZxfj5VKF8bpQ9WmzfJF/kwirh3gH00iIzOlkoIphqlt4aAem2
+B7GlBWgCIORWG4OfyKWxDJw9so1ODP5x1W8UcD6hxmHWH0qhg3h2Iw2/BnQP/jdC
+QxKDFX5U0Cqw86vUdJcDoPpCAnptQ/pMMPWo8k7v+0HRPKDoQM7qhSFZAsmcKZK7
+Oe+p4N+Jj9OL6RnAbPGIijg8nbRZdqeZWm16+ZWtC1aSyS+q1JDNxIVjoUNLPnwh
+rX65ZhUTAgMBAAECggEAQWLiXadbM7YYik7YU+21zaZHsWaoFtIHJXMA7+Tgq6bg
+TI+4t2B+lpda00LM7vspj8QlcVNbJxOxFOGgVosEcUWCbTEN40Qmqr3uSeL+r4ep
+2y95abLxoGorKSxNWYDslOkLk1Zhpdz9AxQmw6vfu3NTuJZJHTSCACKMsXUVv7lv
+gMzyaZQ5JC+NFjLv/AK1moq4AqkjwQYzwXou2jbzJ9aoSS+hGSijGwmJbYBe1tev
+3PZVa708PTUF/U0Iw2FaEIg7BrkUxILic6THRBE/Lak+nBG7dlmQhL/3gEukTojr
+iMMtYhCEv0mhKGa7AycIGk31ySbAtV7/KXMEvgMROQKBgQDOrv9f9skNdanV5YyU
+OoOzfc8LOFUlTMyDS5Ioh5PWD0YqzELcBbcbsMmVwRBlChDiJcwDG7Ro4DCSLG9I
+G4vo0JHDxyKJpWLq07E8MRzL3804K0XKKP/AFS4u0P8LMVAny7OK2c58NvFXmDqu
+RV+k3S65AVQNaie0uUZ7IoXfvwKBgQDJdDm6hOJtKuZiZP7k23k1rcBGc0mPkd0w
+8yUooWNZGBjPpwzX7ELqYFnK+6Wy8qOJSEYVjzov7ArSmbmhq09bej9uLP0fWYcm
+O6C7FMw++Gkz+MF5s7EGcUQI36wGWIlGuNyHTVNqOgBhCYBulhtQVj0CImuV5XHg
+HMv3YppfrQKBgB3jNnClGjvFCRMyR5rjv0nEZp1DvyROr8BIvFD6EgnBWa80rHJu
+rSTm8q+iJIHH69sYBiFo7zS/PqbUoB74RMoc5wc9k6P984jrpdSDcZuVuHJn54at
+WRZoua3xcQAoWGP40/S/PFnABDRbghjTVVpc1bXRGFt8P1Ol+ygxPNS3AoGACRbq
+Z+UJBl3yKSxfZ9oTPP3K+CLJheXR8hx2Z7/oaKOysuPZq4BogIS6aHM0Rb+260HM
+j7p3qKPg1SHEg2vkV79LT2BOR3TVqT71gJtun8S7knG94QzfhufjZvcYnuytvPgo
+Ux6FDfzx+W7hUZwKPXS2qfr9mbTRj4gdF9tmFb0CgYBTT/j/J4pHnUUVTMROhHTb
+4HlyZLvfaT5TSHa+W+WyqtYNvsR1yUrQ+bErjBiSg8lFZjVUiGlUeWtysMBUttdr
+uulnqRnPp3QFmwNdu+6gIfJmz0R8QZfkBc57X/9wDLmEb6nN8PnysQ8zvRDTE1ga
+8MCiq3A3u1HM0+JN+v0c2g==
+-----END PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIFNDCCAxygAwIBAgICQ0MwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEhMB8GA1UEAwwY
+Rm9vYmFyIEludGVybWVkaWF0ZSBDQSAxMB4XDTE3MTAyODIyNTIxNFoXDTE4MTEw
+NzIyNTIxNFowUTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzAN
+BgNVBAoMBkZvb2JhcjEcMBoGA1UEAwwTdGVzdHNpdGUuZm9vYmFyLmNvbTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKlPGmdiqKloSbUri9gvo2lyS0x
+2axSpeTfgIxI4Qnqhq8wMkih+SuO8+2rzIUd3S9nYqVww6yy+qHiJLXi3DKVYM/j
+gJnF+PlUoXxulD1abN8kX+TCKuHeAfTSIjM6WSgimGqW3hoB6bYHsaUFaAIg5FYb
+g5/IpbEMnD2yjU4M/nHVbxRwPqHGYdYfSqGDeHYjDb8GdA/+N0JDEoMVflTQKrDz
+q9R0lwOg+kICem1D+kww9ajyTu/7QdE8oOhAzuqFIVkCyZwpkrs576ng34mP04vp
+GcBs8YiKODydtFl2p5labXr5la0LVpLJL6rUkM3EhWOhQ0s+fCGtfrlmFRMCAwEA
+AaOCAQ8wggELMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG
++EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYD
+VR0OBBYEFNPsyKBhnCjL7pVBLRYK3jaoZ8PfMHIGA1UdIwRrMGmAFAf9rGqvLeJh
+eBNJOHBKTG3Oz32PoU2kSzBJMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZv
+cm5pYTEPMA0GA1UECgwGRm9vYmFyMRQwEgYDVQQDDAtGb29iYXIgUm9vdIICQkIw
+DgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEB
+CwUAA4ICAQA4sFKv4JDZ0+CVjcHL9bkTpk5I2L45xXk3d7GrhBpGveyy8vlb/g7P
+0qyAVo0UnB+eRTtwk6GTsJdzz4FBem+FDq8ZO/N51Rn4ZJQbDg24eGErK4rpbOo5
+OQgKKhTKjjBYwsAsIOkJ1TKQDQ3++Kqw3cWh/vlCWoxGPSMOeU/Iro34IWzSeERE
+MamYo5kIYq2ERCcVSoTcYB87cTYMU+ORyQSEx/OncDuAKm45ub92By5NpeFVMk+8
+ibifgzbNJHVnaZUVg8ScdM1A4Db6WAL0SUsYIawrnQ+TENs+6Ekls+wu8G5FAmbt
+OEV0WOafGvdcnELn5IPXlkvLbiRx5EChG+nF3XrLgn3dBQwP2cGrI/IPRm1XfaaB
+AkMSkf6St5TX3C40g1CGcNSVoKBYBB2Di+hPXwTHImGggR1JF34ljHCokMoPxmr7
+lP9pam0dhP/SSpIwxfsvDJylBgUEqTr3tsVDIDfMtJjudK7A7H1HMoqEiqlzRvJI
+EZ1koOxANFcQ1f9am2PPUNFvfK9IbLQlV8d4k1w6xBAeOVke79lJI9pTTCSVb+PT
+DniEL79JXjmjQUoKE4zo1u41d+wLu3dEGM27GI7BdLYt6bRsolZvrbey7Nn4c0t4
+ug4B4GTd1SLLVJns/IRLBrNr1anBJ7u9WFruBUEWwtdxAwSoXdtIIQ==
+-----END CERTIFICATE-----
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultimportcertificate.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultimportcertificate.json b/providers/azurecompute-arm/src/test/resources/vaultimportcertificate.json
new file mode 100644
index 0000000..d431070
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultimportcertificate.json
@@ -0,0 +1,52 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myImportableCertificate/f69168f2963e4ac7b68622b2bb2f80d3",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myImportableCertificate/f69168f2963e4ac7b68622b2bb2f80d3",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myImportableCertificate/f69168f2963e4ac7b68622b2bb2f80d3",
+	"x5t": "-qEnW6P9TdfOOXzbNQNS5ZKveRo",
+	"cer": "MIIFNDCCAxygAwIBAgICQ0MwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEhMB8GA1UEAwwYRm9vYmFyIEludGVybWVkaWF0ZSBDQSAxMB4XDTE3MTAyODIyNTIxNFoXDTE4MTEwNzIyNTIxNFowUTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEcMBoGA1UEAwwTdGVzdHNpdGUuZm9vYmFyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKlPGmdiqKloSbUri9gvo2lyS0x2axSpeTfgIxI4Qnqhq8wMkih+SuO8+2rzIUd3S9nYqVww6yy+qHiJLXi3DKVYM/jgJnF+PlUoXxulD1abN8kX+TCKuHeAfTSIjM6WSgimGqW3hoB6bYHsaUFaAIg5FYbg5/IpbEMnD2yjU4M/nHVbxRwPqHGYdYfSqGDeHYjDb8GdA/+N0JDEoMVflTQKrDzq9R0lwOg+kICem1D+kww9ajyTu/7QdE8oOhAzuqFIVkCyZwpkrs576ng34mP04vpGcBs8YiKODydtFl2p5labXr5la0LVpLJL6rUkM3EhWOhQ0s+fCGtfrlmFRMCAwEAAaOCAQ8wggELMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNPsyKBhnCjL7pVBLRYK3jaoZ8PfMHIGA1UdIwRrMGmAFAf9rGqvLeJheBNJOHBKTG3Oz32PoU2kSzBJMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEPMA0GA1UECgwGRm9vYmFy
 MRQwEgYDVQQDDAtGb29iYXIgUm9vdIICQkIwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQA4sFKv4JDZ0+CVjcHL9bkTpk5I2L45xXk3d7GrhBpGveyy8vlb/g7P0qyAVo0UnB+eRTtwk6GTsJdzz4FBem+FDq8ZO/N51Rn4ZJQbDg24eGErK4rpbOo5OQgKKhTKjjBYwsAsIOkJ1TKQDQ3++Kqw3cWh/vlCWoxGPSMOeU/Iro34IWzSeEREMamYo5kIYq2ERCcVSoTcYB87cTYMU+ORyQSEx/OncDuAKm45ub92By5NpeFVMk+8ibifgzbNJHVnaZUVg8ScdM1A4Db6WAL0SUsYIawrnQ+TENs+6Ekls+wu8G5FAmbtOEV0WOafGvdcnELn5IPXlkvLbiRx5EChG+nF3XrLgn3dBQwP2cGrI/IPRm1XfaaBAkMSkf6St5TX3C40g1CGcNSVoKBYBB2Di+hPXwTHImGggR1JF34ljHCokMoPxmr7lP9pam0dhP/SSpIwxfsvDJylBgUEqTr3tsVDIDfMtJjudK7A7H1HMoqEiqlzRvJIEZ1koOxANFcQ1f9am2PPUNFvfK9IbLQlV8d4k1w6xBAeOVke79lJI9pTTCSVb+PTDniEL79JXjmjQUoKE4zo1u41d+wLu3dEGM27GI7BdLYt6bRsolZvrbey7Nn4c0t4ug4B4GTd1SLLVJns/IRLBrNr1anBJ7u9WFruBUEWwtdxAwSoXdtIIQ==",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509231134,
+		"exp": 1541631134,
+		"created": 1509346469,
+		"updated": 1509346469,
+		"recoveryLevel": "Purgeable"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myImportableCertificate/policy",
+		"key_props": {
+			"exportable": true,
+			"kty": "RSA",
+			"key_size": 2048,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pem-file"
+		},
+		"x509_props": {
+			"subject": "CN=testsite.foobar.com, O=Foobar, S=California, C=US",
+			"ekus": ["1.3.6.1.5.5.7.3.1"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 13,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "EmailContacts"
+			}
+		}],
+		"issuer": {
+			"name": "Unknown"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346469,
+			"updated": 1509346469
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultimportcertificaterequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultimportcertificaterequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultimportcertificaterequestbody.json
new file mode 100644
index 0000000..2ca39cb
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultimportcertificaterequestbody.json
@@ -0,0 +1,9 @@
+{
+	"policy": {
+		"lifetime_actions": [],
+		"secret_props": {
+			"contentType": "application/x-pem-file"
+		}
+	},
+	"value": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCipTxpnYqipaEm\n1K4vYL6NpcktMdmsUqXk34CMSOEJ6oavMDJIofkrjvPtq8yFHd0vZ2KlcMOssvqh\n4iS14twylWDP44CZxfj5VKF8bpQ9WmzfJF/kwirh3gH00iIzOlkoIphqlt4aAem2\nB7GlBWgCIORWG4OfyKWxDJw9so1ODP5x1W8UcD6hxmHWH0qhg3h2Iw2/BnQP/jdC\nQxKDFX5U0Cqw86vUdJcDoPpCAnptQ/pMMPWo8k7v+0HRPKDoQM7qhSFZAsmcKZK7\nOe+p4N+Jj9OL6RnAbPGIijg8nbRZdqeZWm16+ZWtC1aSyS+q1JDNxIVjoUNLPnwh\nrX65ZhUTAgMBAAECggEAQWLiXadbM7YYik7YU+21zaZHsWaoFtIHJXMA7+Tgq6bg\nTI+4t2B+lpda00LM7vspj8QlcVNbJxOxFOGgVosEcUWCbTEN40Qmqr3uSeL+r4ep\n2y95abLxoGorKSxNWYDslOkLk1Zhpdz9AxQmw6vfu3NTuJZJHTSCACKMsXUVv7lv\ngMzyaZQ5JC+NFjLv/AK1moq4AqkjwQYzwXou2jbzJ9aoSS+hGSijGwmJbYBe1tev\n3PZVa708PTUF/U0Iw2FaEIg7BrkUxILic6THRBE/Lak+nBG7dlmQhL/3gEukTojr\niMMtYhCEv0mhKGa7AycIGk31ySbAtV7/KXMEvgMROQKBgQDOrv9f9skNdanV5YyU\nOoOzfc8LOFUlTMyDS5Ioh5PWD0YqzELcBbcbsMmVwRBlChDiJcwDG7Ro4DCSLG9I\nG4vo0JHDxyKJpWLq07E8MRzL3804K0XKKP/AFS4u0P8LMVAny7OK2c58NvFXmDqu\nRV+k3S65AVQNaie0uUZ7IoXfvwKBgQDJd
 Dm6hOJtKuZiZP7k23k1rcBGc0mPkd0w\n8yUooWNZGBjPpwzX7ELqYFnK+6Wy8qOJSEYVjzov7ArSmbmhq09bej9uLP0fWYcm\nO6C7FMw++Gkz+MF5s7EGcUQI36wGWIlGuNyHTVNqOgBhCYBulhtQVj0CImuV5XHg\nHMv3YppfrQKBgB3jNnClGjvFCRMyR5rjv0nEZp1DvyROr8BIvFD6EgnBWa80rHJu\nrSTm8q+iJIHH69sYBiFo7zS/PqbUoB74RMoc5wc9k6P984jrpdSDcZuVuHJn54at\nWRZoua3xcQAoWGP40/S/PFnABDRbghjTVVpc1bXRGFt8P1Ol+ygxPNS3AoGACRbq\nZ+UJBl3yKSxfZ9oTPP3K+CLJheXR8hx2Z7/oaKOysuPZq4BogIS6aHM0Rb+260HM\nj7p3qKPg1SHEg2vkV79LT2BOR3TVqT71gJtun8S7knG94QzfhufjZvcYnuytvPgo\nUx6FDfzx+W7hUZwKPXS2qfr9mbTRj4gdF9tmFb0CgYBTT/j/J4pHnUUVTMROhHTb\n4HlyZLvfaT5TSHa+W+WyqtYNvsR1yUrQ+bErjBiSg8lFZjVUiGlUeWtysMBUttdr\nuulnqRnPp3QFmwNdu+6gIfJmz0R8QZfkBc57X/9wDLmEb6nN8PnysQ8zvRDTE1ga\n8MCiq3A3u1HM0+JN+v0c2g\u003d\u003d\n-----END PRIVATE KEY-----\n-----BEGIN CERTIFICATE-----\nMIIFNDCCAxygAwIBAgICQ0MwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEhMB8GA1UEAwwY\nRm9vYmFyIEludGVybWVkaWF0ZSBDQSAxMB4XDTE3MTAyODIyNTIxNFoXDTE4MTEw\nNzIyNTIxNFowUT
 ELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzAN\nBgNVBAoMBkZvb2JhcjEcMBoGA1UEAwwTdGVzdHNpdGUuZm9vYmFyLmNvbTCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKlPGmdiqKloSbUri9gvo2lyS0x\n2axSpeTfgIxI4Qnqhq8wMkih+SuO8+2rzIUd3S9nYqVww6yy+qHiJLXi3DKVYM/j\ngJnF+PlUoXxulD1abN8kX+TCKuHeAfTSIjM6WSgimGqW3hoB6bYHsaUFaAIg5FYb\ng5/IpbEMnD2yjU4M/nHVbxRwPqHGYdYfSqGDeHYjDb8GdA/+N0JDEoMVflTQKrDz\nq9R0lwOg+kICem1D+kww9ajyTu/7QdE8oOhAzuqFIVkCyZwpkrs576ng34mP04vp\nGcBs8YiKODydtFl2p5labXr5la0LVpLJL6rUkM3EhWOhQ0s+fCGtfrlmFRMCAwEA\nAaOCAQ8wggELMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG\n+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYD\nVR0OBBYEFNPsyKBhnCjL7pVBLRYK3jaoZ8PfMHIGA1UdIwRrMGmAFAf9rGqvLeJh\neBNJOHBKTG3Oz32PoU2kSzBJMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZv\ncm5pYTEPMA0GA1UECgwGRm9vYmFyMRQwEgYDVQQDDAtGb29iYXIgUm9vdIICQkIw\nDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEB\nCwUAA4ICAQA4sFKv4JDZ0+CVjcHL9bkTpk5I2L45xXk3d7GrhBpGveyy8vlb/g7P\n0qyAVo0UnB+eRTtwk6GTs
 Jdzz4FBem+FDq8ZO/N51Rn4ZJQbDg24eGErK4rpbOo5\nOQgKKhTKjjBYwsAsIOkJ1TKQDQ3++Kqw3cWh/vlCWoxGPSMOeU/Iro34IWzSeERE\nMamYo5kIYq2ERCcVSoTcYB87cTYMU+ORyQSEx/OncDuAKm45ub92By5NpeFVMk+8\nibifgzbNJHVnaZUVg8ScdM1A4Db6WAL0SUsYIawrnQ+TENs+6Ekls+wu8G5FAmbt\nOEV0WOafGvdcnELn5IPXlkvLbiRx5EChG+nF3XrLgn3dBQwP2cGrI/IPRm1XfaaB\nAkMSkf6St5TX3C40g1CGcNSVoKBYBB2Di+hPXwTHImGggR1JF34ljHCokMoPxmr7\nlP9pam0dhP/SSpIwxfsvDJylBgUEqTr3tsVDIDfMtJjudK7A7H1HMoqEiqlzRvJI\nEZ1koOxANFcQ1f9am2PPUNFvfK9IbLQlV8d4k1w6xBAeOVke79lJI9pTTCSVb+PT\nDniEL79JXjmjQUoKE4zo1u41d+wLu3dEGM27GI7BdLYt6bRsolZvrbey7Nn4c0t4\nug4B4GTd1SLLVJns/IRLBrNr1anBJ7u9WFruBUEWwtdxAwSoXdtIIQ\u003d\u003d\n-----END CERTIFICATE-----"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultimportkeyrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultimportkeyrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultimportkeyrequestbody.json
new file mode 100644
index 0000000..fe9312e
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultimportkeyrequestbody.json
@@ -0,0 +1,18 @@
+{
+  "Hsm": false,
+  "attributes": {
+    "enabled": true
+  },
+  "key": {
+    "d": "DjU54mYvHpICXHjc5-JiFqiH8NkUgOG8LL4kwt3DeBp9bP0-5hSJH8vmzwJkeGG9L79EWG4b_bfxgYdeNX7cFFagmWPRFrlxbd64VRYFawZHRJt-2cbzMVI6DL8EK4bu5Ux5qTiV44Jw19hoD9nDzCTfPzSTSGrKD3iLPdnREYaIGDVxcjBv3Tx6rrv3Z2lhHHKhEHb0RRjATcjAVKV9NZhMajJ4l9pqJ3A4IQrCBl95ux6Xm1oXP0i6aR78cjchsCpcMXdP3WMsvHgTlsZT0RZLFHrvkiNHlPiil4G2_eHkwvT__CrcbO6SmI_zCtMmypuHJqcr-Xb7GPJoa64WoQ",
+    "dp": "DB9nGuHplY_7Xv5a5UCs5YgxkWPtJFfbIZ1Zr-XHCCY09JIWReOGQG226OhjwixKtOK_OqmAKtMKM9OmKviJRHNbDhbTxumN3u7cL8dftjXpSryiEQlPmWyW94MneI2WNIrvh4wruQuDt8EztgOiDFxwcnUgey8iend7WmZnE7E",
+    "dq": "O-bSTUQ4N_UuQezgkF3TDrnBraO67leDGwRbfiE_U0ghQvqh5DA0QSPVzlWDZc9KUitvj8vxsR9o1PW9GS0an17GJEYuetLnkShKK3NWOhBBX6d1yP9rVdH6JhgIJEy_g0Suz7TAFiFc8i7JF8u4QJ05C8bZAMhOLotqftQeVOM",
+    "e": "AQAB",
+    "key_ops": ["encrypt"],
+    "kty": "RSA",
+    "n": "33TqqLR3eeUmDtHS89qF3p4MP7Wfqt2Zjj3lZjLjjCGDvwr9cJNlNDiuKboODgUiT4ZdPWbOiMAfDcDzlOxA04DDnEFGAf-kDQiNSe2ZtqC7bnIc8-KSG_qOGQIVaay4Ucr6ovDkykO5Hxn7OU7sJp9TP9H0JH8zMQA6YzijYH9LsupTerrY3U6zyihVEDXXOv08vBHk50BMFJbE9iwFwnxCsU5-UZUZYw87Uu0n4LPFS9BT8tUIvAfnRXIEWCha3KbFWmdZQZlyrFw0buUEf0YN3_Q0auBkdbDR_ES2PbgKTJdkjc_rEeM0TxvOUf7HuUNOhrtAVEN1D5uuxE1WSw",
+    "p": "8K33pX90XX6PZGiv26wZm7tfvqlqWFT03nUMvOAytqdxhO2HysiPn4W58OaJd1tY4372Qpiv6enmUeI4MidCie-s-d0_B6A0xfhU5EeeaDN0xDOOl8yN-kaaVj9b4HDR3c91OAwKpDJQIeJVZtxoijxl-SRx3u7Vs_7meeSpOfE",
+    "q": "7a5KnUs1pTo72A-JquJvIz4Eu794Yh3ftTk_Et-83aE_FVc6Nk-EhfnwYSNpVmM6UKdrAoy5gsCvZPxrq-eR9pEwU8M5UOlki03vWY_nqDBpJSIqwPvGHUB16zvggsPQUyQBfnN3N8XlDi12n88ltvWwEhn1LQOwMUALEfka9_s",
+    "qi": "InfGmkb2jNkPGuNiZ-mU0-ZrOgLza_fLL9ErZ35jUPhGFzdGxJNobklvsNoTd-E2GAU41YkJh24bncMLvJVYxHHA5iF7FBWx1SvpEyKVhhnIcuXGD7N5PbNZzEdmr9C6I7cPVkWO-sUV7zfFukexIcANmsd_oBBGKRoYzP5Tti4"
+  }
+}
\ No newline at end of file


[24/50] [abbrv] jclouds git commit: Subscription ID wasn't being substituted, add default oauth.endpoint

Posted by na...@apache.org.
Subscription ID wasn't being substituted, add default oauth.endpoint


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

Branch: refs/heads/master
Commit: c7050757f5d9d7fa396a0b297202dcf3856c0a66
Parents: 180efdf
Author: jims <ji...@jdork.localdomain>
Authored: Thu Jul 27 13:04:39 2017 -0700
Committer: Ignasi Barrera <na...@apache.org>
Committed: Tue Aug 1 08:17:09 2017 +0200

----------------------------------------------------------------------
 .../jclouds/azurecompute/arm/AzureComputeProviderMetadata.java   | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/c7050757/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index a866ffb..eb52746 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -89,6 +89,8 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(PROPERTY_MAX_RATE_LIMIT_WAIT, 330000);
       properties.put(RESOURCE, "https://management.azure.com/");
       properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
+      // Set a default Oauth endpoint for Azure, fill in the tenantId based on the value supplied
+      properties.put("oauth.endpoint", "https://login.microsoft.com/${azurecompute-arm.tenantId}/oauth2/token");
       properties.put(DEFAULT_VNET_ADDRESS_SPACE_PREFIX, "10.0.0.0/16");
       properties.put(DEFAULT_SUBNET_ADDRESS_PREFIX, "10.0.0.0/24");
       properties.put(RESOURCENAME_PREFIX, "jclouds");
@@ -135,7 +137,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
          id("azurecompute-arm")
                  .name("Azure Resource Management")
                  .apiMetadata(new AzureManagementApiMetadata())
-                 .endpoint("https://management.azure.com/subscriptions/SUBSCRIPTION_ID")
+                 .endpoint("https://management.azure.com/subscriptions/${azurecompute-arm.subscriptionId}")
                  .homepage(URI.create("https://www.windowsazure.com/"))
                  .console(URI.create("https://windows.azure.com/default.aspx"))
                  .linkedServices("azureblob")


[26/50] [abbrv] jclouds git commit: JCLOUDS-1225: Address Guava 18 Objects changes

Posted by na...@apache.org.
JCLOUDS-1225: Address Guava 18 Objects changes

Fixed with:

find -name \*.java | xargs sed -i 's/Objects.[Tt]oStringHelper/More&/g'
find -name \*.java | xargs sed -i 's/Objects.firstNonNull/More&/g'
find -name \*.java | xargs sed -i 's/^\(import com.google.common.base.\)\(Objects.*\)/\1More\2\n\1\2/g'
find -name \*.java | xargs java -jar google-java-format-1.3-all-deps.jar -i --fix-imports-only --skip-sorting-imports


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

Branch: refs/heads/master
Commit: b38ce8d7b317f2e8d486c38a81365d30ec4145f5
Parents: 7100e81
Author: Andrew Gaul <ga...@apache.org>
Authored: Thu Aug 24 18:26:39 2017 -0700
Committer: Andrew Gaul <ga...@apache.org>
Committed: Thu Aug 24 18:28:07 2017 -0700

----------------------------------------------------------------------
 .../azurecompute/arm/compute/AzureComputeServiceAdapter.java    | 4 ++--
 .../azurecompute/arm/compute/options/AzureTemplateOptions.java  | 5 +++--
 2 files changed, 5 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/b38ce8d7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 0a37d5d..213d438 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -96,7 +96,7 @@ import org.jclouds.location.Region;
 import org.jclouds.logging.Logger;
 
 import com.google.common.base.Function;
-import com.google.common.base.Objects;
+import com.google.common.base.MoreObjects;
 import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
 import com.google.common.base.Supplier;
@@ -375,7 +375,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
 
    private OSProfile createOsProfile(String computerName, Template template) {
       String defaultLoginUser = template.getImage().getDefaultCredentials().getUser();
-      String adminUsername = Objects.firstNonNull(template.getOptions().getLoginUser(), defaultLoginUser);
+      String adminUsername = MoreObjects.firstNonNull(template.getOptions().getLoginUser(), defaultLoginUser);
       // Password already generated in CreateResourcesThenCreateNodes (if not set by user)
       String adminPassword = template.getOptions().getLoginPassword();
       OSProfile.Builder builder = OSProfile.builder().adminUsername(adminUsername).adminPassword(adminPassword)

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b38ce8d7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
index 6ba85d1..92f592e 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
@@ -26,6 +26,7 @@ import org.jclouds.azurecompute.arm.domain.OSProfile.WindowsConfiguration;
 import org.jclouds.azurecompute.arm.domain.Secrets;
 import org.jclouds.compute.options.TemplateOptions;
 
+import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableList;
 
@@ -179,8 +180,8 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
    }
 
    @Override
-   public Objects.ToStringHelper string() {
-      Objects.ToStringHelper toString = super.string();
+   public MoreObjects.ToStringHelper string() {
+      MoreObjects.ToStringHelper toString = super.string();
       if (availabilitySet != null)
          toString.add("availabilitySet", availabilitySet);
       if (availabilitySetName != null)


[42/50] [abbrv] jclouds git commit: Add Azure KeyVault support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeybackup.txt
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeybackup.txt b/providers/azurecompute-arm/src/test/resources/vaultkeybackup.txt
new file mode 100644
index 0000000..7c68c54
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeybackup.txt
@@ -0,0 +1 @@
+JkF6dXJlS2V5VmF1bHRLZXlCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLk9tXzl6QnhwTEw5a3NCVmNfR1JLUHR5akZ6R1JGV3BBWFVvVm91dmdNQXNEcFo2UUp1QUloRzZJWFB4ZHBOUDNlbEZFc19Ld3RpMlBhRXNEQWM4TEVQVHZvVzlSRmlROHZTY3JiWHlKcFNROXJSS1V5NlQ2SWo3UEpDV3Z6alp5ZlNYbklPNjRYMUtzRThFZWNKRDdudDRhN2tfZkpiSkw4a3paWnhXWFZLZnZwZEQ4c3dobFdOLVhMU0RsWDFORmlYQk5ILVRoU1BDbkNMOHc4RjlpV0o0LWFxeXozc0ozRDAzb3JzTHdKczFBTF9LN1c4eUlUNlprb3Azc20zeGlBb2pYZl92WDdOLXhQMUtKMU1tRlFnQVpaMmNpQWdJc2UzVDdoWFhsa0RaNGJqSXpYa2ZocGg1YlNuUEkzQU5kbDRUaXZkdVlxM0lCdlZrQ0hpWnY0US5pLXNxb3lQVVNHdlM2SVdUdld0MzBRLkR5N0U0cE9vanU3bzlMQ2dkcVYwd1c2MGxkOWRaU0tPN0wxWXhid1RMQzd3Z0piSmhlNno5b3VWN0FFMnBMLXFFMUhLclI3Nk9TVTJ3c1FBMFZuTDhlR1RnVFk0TWJOaklzSERraGFSUWN4bGRjOHpGWEVxNzNOWlhPWE5vaWJ2QVhUcm9oX3JnS0plNVFYWE1MSFJ6T2lVWEtqVEU3ak11Qm0zejNMRm1mQ1pQb0xWTnpNT09mdmFwQTh5XzNEUFk1OUdxOUFzWlZsakNpTWoxUlVrQV9QQTBwREUwRU8xd25pV
 0dIb0t1R3h2N2hLb18wcFVMMWRPalZrNFA1ZmRWRmtGOENVemVvSDNja29xbUxMRmktQ0Nra2E5Q1JZcUE5ekZFckJsZGYzQTlIOVNuazdiUkNhb3c5Tk0tdXFBbkF1OWF6U3JBbnZZZ1NUT0VFUjFvX01Yc1Bqc1loTHp0NFZoTGx4RjlQNDROSU1ZTjEwWVZBYlVIQ0FaREZZejl5d3l2YWJPSXF1bjUzc25DZTBYVjBaWndabFNmSktJUkNsMk9zU29vVEt2OWx6U2kwOVFlUTRxb1NCMFdXSThobjFGd1pYV0RhdHNSNFFxOTB4RXB1bFVyWV9mOWI3cnNSem9jYmF6c0cxek50a0t5bjNVY29fR00yRjJDclFybi1uRVlXMkZRcVpkMlpHT2Nnbk52NFVyWmMxRjB5MUpTdXgxS29qdHBkZDgzR2JPd2s5dmVlSGs2NXlCdmtMTUYtcGtUWGdFS0lZeVN5ZUM4ekdndVZJOHhrX2VndXhQVlhCVVBMWk0xTHJ3U1VDc2JhaGR3WnRZZDN0R1dZVjZsSzhyT1UtQjhlWllvRTd0QUF2RkZxNEJ1R0U1TXRsdHFSRVpkcHlkOWFkTDRVRkttZ05YcTlvNWVqdWJuSmV2RWhRQmhVRXpRLUdCZ3RudVgtSlNTYjBDVllxV3p0NVU2dzJpcVNwZzBNMnQ4WG5OQXN5WTlvYXVBbVhuUGhMZ3lYYWpaSE1TS2FqNjIwOHdrZVA5ME1CSkt1anBfSFhJaEttSW1TOXVwLVY1NXBHRXdMQnhfYlU3TFpwYnhIcm14R3VOTE9pNXhJUGt3QkpTdXFZRlNSMWdaUU5lb1ZHUncwTW5TQW5HYnJ3eE92NFVjVlpUUjhkVTI1Y0NTOHpENjNwQ0ZUdm5CNllyN0pwcGhYekd3SFZYeTM2TkJPdWVuQ2NYQUR2QXNXS2M5a1RQeTlEalVFRFVQd0QydUpZQmhqaV9RR2taYjhfQnNwdU
 RUbWM1Z0Y3TkdsV2NPRTBqZmFwUi1CSlJhUXJENFhxeU95NTRsTUxCZlNSTFBIN0w4VnMyUTVvc0FfVHlPYUoxa3B6dG5iLUhyNTdSQ1E4UWNsRnd5eVRfakpLaXFQRFEyWFlrZ2NjMmdkZlAtS29GNHFHSl9HRERMN3NVaThKeWRnOFNBdDBoRGdUOTh4Zk1URTlQc0twTU9FQUkwWF9KRWdsRTFwRmNxbVFkT2NOU2Z0VUxRaEFPVWd6Qlgxb1UtYTdiX2gtX0l5RVgyb0htZDdaNUJJRV80b0ZEYWVMaXh6ck9BWFdTTzVFZ3B4U0pYUXZ2ZEVZUV9mNHhPVFU3SExmUWkyNEthdGNUTWJJczlBVU1UY1NvVUhIY0RLWVhZbTl3SWR0RXR3MG5mbFp5YVJMYkx4cVJNTzd0X1ZLbnJ6OGVOZ2dJWENBVno4dmJmXzk1VWdVNGJUTzZDLU9BbHJqbUZNbVNzaEpwY0VhRjAwaGx3MnZud2s2QWlCRTlWUzdOYmJFb0JVZmtuaWJFeVJ5NHp2MmZtMWxhRkJnYmUzWV9QVEtHQTlVOGJlNGJsb2lkQmlVOGwxUS1qT3oxeFRNVFUybkpnYkJ6b0xzWEtadEw0d0ZDTnlNVFN3N1pyX3c0aDJjUzU4UHZsVWlYalRhcGpNdTJzYWJtdVJnVXROTjFlWVdxZjBRSEVFdGoydE5nd25TaHNBOHBRWkZKaXp6Rlc2VXpKRXdPbnN4S25tcjFEQktnZ1hsZFFtdmlxWHU5aE00MzdWcUJIeVA2SFZ1dUdiOEUtTlM5WlBPekJWMEFrcTM2QXVJcWNIMXUwTm1NT0laaXR1WVhFNXp3UGlVczJxSmMzQ1BHbVdZQ3d6THNibF9YRkx1dU5udXlIa2VGN1cwOGtxNjhBU2FBMTVic3BQMDU1a2UyMlRVbzNqVl9PeHRUY205OUdBcktGOE82elBjTlQyQ0xNdjkwZ3I1SEx0MVg1WjF
 4WFNTTVczZ0NRVEs0TmFtNUsyTzFUNXdoTWtPdnhYYmdkb3Jwc245amhGb25aaC00VG5RczJiUmMxVTM1Q1BudmRVM0s1dUVOTzNxZGVxV28zR20xeFRMaUdJSUhsNkdpX0dFdnlqWjdEQzRjeVhlYkI5enRiMklLQXZLVFhyQkF0aXd2bWF4U2FzNFRXVUc5Qy1RYUxLZnpRdDZwVm82NU8wLUZHQ3VLSU1Fc1I4bm9lM19jVVVJNzRiYl9sTVFWdnNyOW9KamJtS1RrWVBhREViQWZCd0FLdGw2dzdWUER4bGt6UmFZVTdPVENsdmFhMTVZQ1hJSzQ2V2hkd2QxMDNoR0x5UjltWlFSdmcyLWhfN0tESzNSVWRzcjNtTlBEYmpCcU16U202MldDNnZTclBVdENKTks2UG1ZWjhfT3A4bXp0U0xUbDBLWlN4dWt5U3d1Y2hfQXZLcGdqa3ktQmVfS0JXNTdka05TT2JlWmZKZElRT0xkSVcwZExqd1BWeTdENEhPS3FyWE1JRGdIdkRIR25zWFBZb0VRZG9wX05BOFZfTW03bWp1blhtZWoxVDI4cTN5VTcxRDEzVUxhdXNwVnNQVHBTcEVDX19mS2ZVSUF2dnI3RmszN19uSFU2QXowSndhNklSU19mTUZHamRuSDI5RXBUcTZGRDdaY1hPZzMxSGdNMHNtNUZlUnkxaHFqUUdIOTRwd2JpUktfWXhQaWVzZHd3cUh2TE1MZE02SU1CU0tuZlVfdTV0bkJISEV6NzZvQ0dHSEJmM0ZnTzFkX1hZZGhtVDZIR2FRUmZhV0s5QTVRNkpUbHBaWUpkOHc2eVlLSDVvNktFR01TWXRKbDFhM29KQ1A2Q0o5Wmh0R0ZWcHlQYlk3M1BkenozR2xvdFlqOE8zYzgtT3BxTm0xaEc2MU1IeEFnNkJYZHgxeFBqZ1RuTVRHbUtTYUplV0d6OWdHc2JDWm52RmlwSExjbHJQVHczVVR0
 NThOdmpkcGJtOGV1VVdxUDM3RVZzMFFoVHZkNzdmc1duZTgzZlpsYkh5SHF1Y3gwWEtBRmNlMURZNlM5Vlc1Ulp4akU4bHJHemxpVXplTGtsS19wVG91d191MXBVWktLV25jTzJ5RzlrZ3dOT0pkazZiWVlPb1dCRGhVNHU3TFVZR2tETENFaVJrSGRIeVBQbjJBeGNXTGhQYml5cUZ2RWRtNUNMMzMtaHN0OHFRNC1QYldfQV85QVFLZ2hoLXJfUUE2Wjlzd3F4QWJFeWI5R294TUFPenAzMlBoaVhpOHRxTC1qQ1ZqSEFnRTdqYm1jRVBVQVh4QlZFUXNLRGd0MFFRM2RscG0xSUd0OU9fMzNwWEIwUmt1bUxYT3pnWjYzYzNGNVp4ZlRyTGtZZ2MxM0p5dXdjb0Nxa0VxS2RxY0F1N3RFODUtSnkxZnpNTHQzLW9wXzBOWUdqallIZTQxU2drdDZjWjdnQXRFeHlDek5YRjBZcG10WFlralI2UTF0dnFIczhRWU9GaTF4RFZBb01pUjBMczFjRGFRcm5WMEhVZ05QeFJSdUlaYld3dWc1OE9QYnNvUDZYdHRhVGo5RU9yRlJEbUR3OVhiSjhxWEV6YkQ5ZXcxUjVsWGVPZWZZcjVnQVlIU1k0X2lTMXR2Qzg0QkY3RGtYUjVDVUxWZXNkTDBwckh6RFA5MHZfRC1oemJSUDVBNFJMM0RLNmFGN3Z6dFktRlRJSnM0bTNKZ3NyVUp4WkV4NjFMQjRIdGJKM2RTMUYxTjJ2YTJPc2VBSWZ0dkhESWFyV21tbjhBZy12T1JhTW1kWC1pT2YtajI2dWlYV3VvTkNPV085NnM3ZWsyUzRoQ1psN0lPNzVzQThkZGprbDNtaFhrSmEtaVBZZk9Nb3pKWDV5WEREX1E2WDg2YzNvZThLZEdVODJCbGluNXRycjRUdlVXcHBEYVZoYzJ6MENyclN4dko2ZjBIb2ZrYVVNTW9seVlpW
 W1rSEdpVWNzdmRNbDhMS1MxVEZoWVZiVW9xNUVyYWhKdW0yTjlqdk9DOGd0Ty0yempNR2NjbkEwUzhqbTR2SFVTRDV4MGtkWFotY0NrZ01HSWM2LW1LaHU1YVRpTTFWX01mN3dteTlrdHZITVRqVUM1d0kwU3JMU1F2RnNWZUZHamthLW1qajlsUEkzMFhORmRLajRTR3A5T2pmclRyYnhfeV91emZ5b3NudGVvRHF0RURmVmFSSFhVOF9pQncwWEdZUDBIaGloR3VlczdrdTZJVlE5aTVjVTBNSTRKR01vR0xJRUJKUG1NckxmamJMdkdVWTgzOWUwc0s5NFNBVHJseXo1YzYyeUloTC1xdEdIeTJBMmxxRUhnVnNvQjF0M0J5bDhwME1OSWJId1ZaUlkxcFBDdFBJVmctYWJCZ1ZVSGZneC1FSDVhVlR3QUZGekw5YjBhVUF5eEhnam1XVTlkYjJTMGJ2S3lKaTh2UXJuOWVnYkt4QWM4OEw1NDNsY1dUU1BIOUQ2Zmk5Z19hY0JUUXF5VUt6S3JxYmJUUGxMNWxQdGdfazFhd3ZLNmhNUDZfR0FLUi15a3JzTlcwVUZHaFI0WDNkTE5DNnFUdGdNaXFnYThKN1dVSjdMZUtaRTV1dzlzQlVRemJSdUxjUDFSMnEwQ29DSHdRYWJIRGhPUkdNMkFyMF9HbmIxZVotRXNNSXJHcWcxQkY5T2FMMTdZWE9RWXRhZXBhUEZGcXI5TS1FTHpEWEtYWlBFU1RVZGZqU1g0RllvMFk5cXNTUGdnTjlhajNnMWxfYVNoclA2SVdxZjJrRWoxTjNIMWVaZVUzQjZrWHBCUFV4VXV0LXk3MkU4Q3l6czJtUDgyQjRvNW9GOUVncldIZXF6WGw5XzQyVDFYNlB0Y0l2TGZ2d2hzd2FTVzlGamxVbC1hczVQbUtxSlRtUzl3bE9CdHZybDh1YWdIT1psMW1zZ3Ezd0hWTGVxMmRQclc4Um
 RjZXJwSTNySGVDZGVzZGJUb3pnS3FuTVhSSVNmZWtvQThLRTkzWFRDOXl1SkM2NmdMcTNJbkJnZ2NUMFp3X0pmWldvN2tmb2dyd2dMRTYwTm9uamxvMERGWFlCRDlKcDd6VGFDRGFGLUZRbHZ5MFdGb1YzRlh2dDllMDdJajBTN0c3THZ0OXVOaW1sbnYyazZOUUJxemlLT01zSjVRQ0pYOEFsbnMwNk9rZG9aVmIzV3Q5MjRQcFM4U0N5R3JnYWVPb24xTHhiMXp2QkIyZDQ5cGJ4a1ZMQnZjcnpFZkYzbExSOU9NdThGNERjS1VHcnBiMjUtNHFQQXVIZXJCcEVEWVBDY3p1RWJaQktZakZQSlozejhKNk45S2l6MktaQTQ0Z3ZKVE42QW5rcThnXzRJMWRBNzRtME9QMEcxd3dtd1pQQU10VXJqYmJ2TVNtbHVjb0FibXhSbDNPd2hFbGRoVFVwdi1iQ3d6ZHVqYnNPMVBsYWI5am1LQUZZaFloU0RZR0FoOTRRRVJ1dkd2VTJnQzlzRmYxTGFTM0Zaa24tRXIxWmgyallpc3BwMlFFd1FBdFlDcmMwaUptMlYwOF95RTVheEVJSnlpZzBhVnFZQ1FiN05GS2diX19LRF9uMi1yN2YwX2RIOFgxeUdJcXpiNzNGbHRCU05RRG1oUU1TdVlVYjlMbHFlREhuNVFtZ3JpQW02d3kwR25QMmE2X2k2TGZWejhMckUxVm94d253V1h4SDlSeDVuTUdpREFvRGxaVlIzVzd1cW1BZ0lMaGFvNldXb0xuYVZSU0pRUTFybTY2R2dCTENUa1QwcE9kS0Vpelc4TlpwXy00Q0tWSHB4ZUpRVFBodXo1cXBmalM4Xzh2M3Nkb0lHNko5RkxwMUludnlmTnFIM0djZ0sxbWZZbWZPUW42cXUybU4yckpiMDg2Y3U2cU5VZnpRcXJqQVpwckdpQ2pCU3Z5T3JwdnZCdGQxVHBQTXFMZEZ
 xbmtGeC1GSTdYWDJocUtoRGFyX2R6QldTWXFPSE9adG50d0hocGNWVExLeXdqQTl0MmxGWTFuNFJtR1l1SHlKdlhVeFZvc05BU19nd1EzM015U25lTk40am5aTWFCNFMyM2lNV0Y0UktSaUlSXzAtTV9Nc1kwbDZmbUxOekZFbFJrUE1LcWFsOHFmbUo3VDkxU2IxdkJFQl9WX052dGxlVzd2VnlaSXBpbV8xUHJ3MC1oMXBMcXVXVDFodll4SWNtbHllSldIUy1NQURnaVdWbnlFOVJBOHpXWFI3TWR2V2s0U2MtaGV0U29LUk1YbmxCM0F2cFc1bEVYN2g0aTJEcVNfLTI0RGdMS09iNWlfVTMwZHNxcWJCdTFMUkNiX2p5dHJhUUlwMEJOczhEMFFXQmFzYlZDbTdNTkM2WlpESlZLMFlBQWkyZnktM3RPSjA3dFF2OFRQelNiaHZETDh6UHdqTmVCSURMWjlvTmdlZFNJYk5sRWdZS3RKZHh6emJEOVp2UmNKSzNYUTBYVHY5bGc0V19HVGJYSUx1bF9fa1owcGZ2RjV6N1Rlc21obV9hRFY2MzNYTEJzWG1wNHJqWUdKUE4tdWxkNW11YkZoWnFWRjJaRHpOTFI5czNKSXNkeHZubnl5QVpiR3dfVjI3eFVKQ19WbktXTzN4bVhGdW5lV0dVSkNFZFpWR2FyZkQ3MHgzc1JIeHJzM29jSEQyQ1JhcnFpM19SOHlndWM4NzlveEJuU29FbXJJTkd5dWkxbXkyRHdnOFYyaGNrcVZKSjhBakxONjNJaGZBR0FTNEU4QWpQODdBczlPX0ZUcnVESWhtOHBEOGpFbUpQTFlTV0hNbkl5WDV6VXEwa3p0NE1QMkNpdzF0Z1pXMGtvRGtHVFhMX1hTV2JCX2ZmVG1lWDN0cDVYU0M0YUh3X3BzUV9oNE44Y2NkS3ItWE1jYXo2aTJ0U3k0Ymh6U2lwWXdqcGx6S3hTYU5wdVpm
 cURWUHlEVXpfSE9OSHVvV0ZVSEw5alhpTEVuR2JFYW5HZ2VlRXN0cEFDcGMyS2JNN0NhSWpDdUtubmpxVy1EZWoxWGNMY3Y5LU1EVFVraGZwTGhMV3ZOWUZKV19UZ1F3eHhEbllTdEwxYTNZVGRfMjJuQ3dJUm5SekY1Y19YTU5KM0JleDh5c3F6ZTJyN1Q4b1hUcFhvY2ozQ2sxaGgzdEh0dHhCOEIyYUh0UlRUanIzRFltamc1RllTOENLNl9mOThkX1QyS2FHYkViZFd4eDhyTDdEZ3JKTGdqeC1Ba05ma0pCR3prY1JaRnBFX1VHVnNhMW1nZlNwOC00QTVaM1Bfdzhuc1RsdzhsaUZ1MUpxcTR2S2ZyQmNUWTI2UEptdEdkZWQ5N21KQnN1aFhyWW5uZW5qamg5bEZYZ3g1TmYyOFFKNHdoV2w5eTFnSS0wNHF5ZEdfem5CbVJ0MkY1Q0FNbXdMQ0hpZV83LUNZVzNDTkJNWlRPcV80VUpaWndxcTUzNkJYdWtmNHZNZ2ZJSENnT1JfczcxUTRleGRmWWZ2ZTU5ZEp3WEc4ZHRMa2xxdXM5SlM4dlgzSnFHdHpLOUhWYjhlVkdmVWpNNXVnU3J6RWJCRFQ2SE1vLWhqVFpNbzBrbjAtY2hTV0hpVV81X2xRanlmdDZMYkxWZFZEbkxlLXFhczlhUi05YXZDZGk2Wmt1SmxuNVJPbXI1XzVpam54Y0haam1ZU3ZXdU9xX0tZT1JxLTMwRXhMdldTM29YbjNQc0lzOTNWTGktU1hHSEpXamJ6YXVlWDFySWlsMGZFLVY4ektpMU5aLXVVWjJJQnVHdjllVWtYeXJyVl9EWmZxUE94RlpMT1NqYWZuWWxSNEt0dE9WMHJVeURaUExob2h6bkZHdG9jRjAwV29xOVB6b1dCT3VJNjNjeE1YNVZGSnpmYTdTdTZ4Vk1FRExLVEZZRzh0bGVDdUpLSHpTV2hpR0FaY1djU3NvL
 U1VNnQ3LUJMVEQwWHEzVklNZU5qQzdQcmU2TjU3YkZheWpqaVVTdTBrOEh1SjBhWGZnNDlOZ2M5S1AxWHp5bjA3M3p4NWd4dEVQYTFhSFVFVEROMkVWakc2SDZMdE50VnNqNGVWRVVzTzZ1VTZTWk1hOHhfX1ZPUEM0WEgzVGRYVFMwTl9KZUw4OENyWmZSMmt3VDh2RWdSUHNVLUc1MU9fQnBXcnVzRndXMElRWXBZTnUwLVVmUjB3VDBlUUFsdHpCbDQ5VkZ6SkVMeHhsTXlKc3ByVUNmMHp1cUNUaVg4d0VUNEc5YWtZZzZKWlV5SVptSUk2RmNycy1sWTBPWlVYSW5IS3pqY0w0WnRVbHhZTTFFUENXVXBibWw4SXN2SlpBN1FELUtWOEJVeFdTXzdUOHRLOWtfbUpGT2pTdVhZUTNjTFVDVktyVkRwU3RZZ3JUREdiUlR5bk9EX3QxU2dwbHczMFFUS01mTXNyZkJweWQ1VEpkSGg2eVdSNFFwUlJnWnVaWGR6STRfWVFUMXIzT3NnWDBWM1NaMUZQN2hSNF9NQnFQSkVTenpZc2pQWVdkTzdzaE55Tl8yaXJDLVNxbG81UkJaNVZvZ2VNZDNaVmhhZEQzcnF0UjJmVHZNZm1aYUtuN0piT2FoUUFJYjY3a3NVUHZHQU9rRC1kNS1VRDV0N2JTU0xkd2xXel9aUjFLakxES0xaTE1WSEtTRk40ejhOUGhIcjc3d21GSDZ0ZEw4X0dEaWh3YnVGTEdmbHl3VmRuWi1uenFQcXNhaTU5MGU4SnBfOVQ3dGtMczZQUHBwclFGSGFVRnFtSTAyYUNvaFJDMGRhTEZDY0JrTXA4blkxeFRlamJyZm1yLVpNcmNLMGQtUmM3bWtpVTY3bUpBRTJSQ3BFZ0Y1dUNiT0xoTlNxMXh5SEZHa0llUE92RkFYMWFGQjNwa1VCN0Q4OWxoUkF1ZGd1bW9JWkRCd0dzdVBSRGZPUlR1T3
 hZakZhaWozZzVyenZHdEVlanB0SVJDbVhNZXhhMVFnYlpQOWJabWh4a0k1SXdHNHJDS0pvZ3NBWnFhYmZUSmUwY18xQTdLYjIzNkEzSHRSMFhJMWRIbVotM2c4cXBwVG9Eb0JPYTZ2RW5vU3NkOFNsX1g1Z0JlZFdmWXZwYzd3X1pfdXJGUXlac3BBbDJrS0N5N2w2U19BUkZqR0dvSnVNWVFicElIbjZGbkJCcjhsTGlyMExZUDVTQlJfM3NaSHNyb3UwamxyLWNMejRZSlpUYzBZcnBGNnRETHA3NFJ0bWM3cDk5aHhNRVE1UG40S1VGNlZJcWt2R2JocjJjdlgzb1d1bk52S0tOcmdXaDYtYzBONFNDTjBkMklveVZfbktzNG4wR2tQcmtDS1ExSGJMbUg1N2ZSTGdqSzFFaEtydGp1SUx3dXFRM0pCeUhISlpOdEdsbV9nZkt5bzZsQ2IyQ2xacElxR2Y0X3ozcVVyMmZVQXhMdWxtRFRMZzh6Z0RlTEViVVdUTXYxTWRUc0pSb0NTZGJiS1NvQ3k2UE1YZUwycllBR2tHT1VYMnVPaDVnRlVkZkdzRVg3enVHamtadnhra2J3VHpTSFlibkMxNHlaRXZsbS1qRkhWS0JjUFdJemJKSnFoUl8zdFVNZ2xRc0xrZzQ2WHFlLUREblVTYUMxbzZ0NnNXOE5CbGR3aGdnOU9JUXhlT2NacVhTanY4TW84SkdrUWlBMnp2WUVWNmJpa09MS3BTbXQyRnNWVE5BSVBQNm1nazE2NG5JaVZXSTN3dlljZ0pCb1ZxeEpCdXJVY2NVNksyVmc1MkU1cnVQc09rNVZwTlphR0ZCb3NYNnU1bjhBM2RfR0laV3VhTUxsZnZnVkdxN21nbFowaFBlM3F3WHI5QndCNm5VV1lJdU1ycFVxUDFQanBmck9OZ3BSOHprQlJ1T0R5R040XzJzRHloMDFWUWRxOGF6OUY4a1gwRU9RaHZ2ZUJ
 KcmtqTTRENGJ5dFVSeVR5RHJRX0hYTExFYUw4UjBPMm9MOGNPeUtSa3F6b1ZGc0NjUC1jMzB1UHFnV2E0T0NzYXhnYUxkTUJveTFKdkFENVF3SWp5dHd2QzR6THNpSXljd3JqeEZaZnVlUnBNRVZLOTR4WVRvNkhlWGQxX0VweFBYMkhiMFFBb0VVVS1zWkFCQVBFZG1OQi1XMEtoUnNpMmJSZi12b3JVZzhJbS1remxCZmxaQ19zUU1RckcwZjR0VE9qTlR0QnlHWUt2dXRqQWJuTjhMQlFSN2JmT0tzM1BvQktQc3pTWDNWMUhtTTUyNnd0X1ZmcDk4d1lFZUNOc3RwcTl1YTRKUlcxRWNGTTRJNnY2aXBXQ3Q5b1V3dVVsTkhUOHNhR2NaUVptRzdZTTRUTDNYVVJITHdaZnNzeUFma2dHejZ0Qm84RWp2MlhNVlZta0ZlRGQ4REl5QXNSUEVHRzZFYUowXzdYajRxNWttR2lUOEJBNE9jMm5pS0M3eVJCVE5CNnhMSldPaXRHcHM0a3ZSX3JfVTl2VUQwMTZ6U19PVlgzLTBqLWNwNzYyWjRicHhNeUswbmNzbFc0M1diUFhRajh2N1libjR1bmtPOU5lc0ZkMC1YWlRvU0J0ZlBTeDk2dGVMM0t4YXEwOFBzV1U5NzhDTVdrUlZHXzZnZWtWWGI0SDdrQUo1M0RoTlpFTW1yM0hSM0lsampIM1YySDRvVGlmeW82ZWdiMHZQX1VEQVNFZGVCUkNYT3JuLUJhTUxzaWhGZE8wVjFxNmNwS2FLVlBkTHgtOTRlelRSRWdtcEpjYjNvSXZoa21RRzJhZ3pZejFEMy1lX0FRU3ladE03TUx6NmY3Ni1HYkkyMy05S0JtVnBVQjJOTnU1aS1xZl8tN3ExQ3JVTFNxNE04aGJsN2E2OUt1UW1RZ0xtQUJZVzlwX3J0ZGFGUzJTRTNGZ0ZPWk1GYnB3MEo3SzRDbXd1VURXb0ty
 ejlGZXAwRDktdkR5NEtpQmdnZWlZTHY3ZFJPVEMwblV2WWlMX00ydXlHbXZtMGJDc29ZMXB3VFNjcDl0aUJZVTZuYW9Ub21ua09qWXZ3T0ZHN3h5R1ZSMF9yT2o3aHpWbzlfbDY3ZE4xaHRFcXZud1BTRno0dXNEcE5UOEFnR3VDVXlMVW5NVVc3ZjNDUFVlOGlqWk5PTm14NEpBT2ZZY1E4dXh3SVRPaExqSEU2alFJOVVFSGNnRmJsMUtrVFJJSDFveGhNSDI3ajJTaUNkS2VrUWVZX3J6cllHTWNmTWF0NTFrdXVzT2pMWDZvbnZWVzBEc1ZXS1FnaUt1OVI1QW8tQkFUTXhxMGJUMWl1X2FaZGNLNkxlZHVwTnVqRXJzSHpNTzF3eGRRcWtMcDVvN2M0ajlQLU5xTTJWWGpnQm93OWJrUmxYdWd2a3Z4WV9tNU1fMm1oeWF1amdtdHg1bXNPR0pIUl9OckY1djZiUGk2aWZkU2o5emhuWGV4MDFEb1B1VmRHeXJkaGN3N25FRjZrczV2N1pOT2ZvRFZuemxCbUpsQVA1eHFjX21SQjI0ZmdWQW5JTzNXMTFSX0V2ZF9UbWxXd085a1cyemFxbi1OeURLUGxtOWp0aXdSSExYRmR1Snc2d2MtdVhJYXdxZFNkZVJkSUV2TWhYX2ExSFhNTG9RYk5VZnpHYk0xSi1aUVBNNWRfbkJPMGN3S0xyRUhlX1ZiT1R4UmZuUU1UVEw1ZnlrcmJGZkgwWUdPYl90aVlqWGJ3QWRsUmtFcFVuSmRWemtCY0tPZUxHMF9ydkRXdmJKX3E4QTFkeFpONm9PSlFvOHRjV0IyVTIyMFNmWjNoNmhUdC12dVBPelltdG1WMDZQb1ZSQTQ5c0JxRWJhNUVKU0pRSGRkVEQyZERDVnRBSV9XNFFFNF9QRGFhQ2kyZFVsN09pZnZJS09TMnJVeVRRckJ2eG1LSnN2Rm9yM2hjOEQ1a3UxMEFQc
 nlUQmdtOFFTbXJma0xlZGNHUEk0YzlxLW53QnRPM1l0cXExTmhnaHU1WFBxc3h4RXZiMkpOekdXME1DeFJGSGI1bzZLbFg4cExjLWZzUFV1V05lWlV0MnQ3R3ppd1dDc2QtTno2VW1Hb1JicU52SmNKeE56VjUtdnotNWJpUzN5UWkwVlJSczl4elhmN05jYURrQlR1N090Q28wVDFUYWQ3bVE1WTVVREN6UXJGVkR4YS05Q1JubDczLUFvZXp2SUtSWUtYWDZLam5RUjZpNmRJOWNBN2pKRFFFT0thMGY3UHFXcU5tYktMalhSY25ocXZJNW56UU5pYUh5bkUzTXpMb3VOMzEwQ2wtM2d5VFloci1ya3c1UE15VHY4enZpYWtMbER5Vm93dTF4OHMzcmdlSDFUbFp5U0JRUDRIcDBBWFYxelZQQUhNbFU0R1dZdXNOSk0tWk1uSGxBdW5RSVd1WF9pRmxVbmFqMWhyR3pfUFJ3dzRVajF5aVZOLW1UR2laSUdadXRDQXRYeGZUd1hwOE5Lc1pwNThYU2QyeTNfTE4xc2QwZDMydEI3Z20xRE1ybHpqQmFybkdBQ3pEQVo4LXpwUDhhVzh5cXFDQ25GdHdiU1hGOUtiNkVEZzRPckNqZmlpTlZXQTZHSFE2TDlPTnZvemozOXpvaU1nOTdDc2dLY2tZTnUxTXo3NWhtSG14NjdudzZLdFBrcnBBRTFmVDBzeDlYdUtWczhUWEdlUFdvVHREMGRDOUVTRjRsV3RPMnpoV3NsTzhHaWVkQnhjTDVUOTNmWGFwR05sbG12d2lIVWx3S29TSFVnS2JwVWp6MU9WenBGM0l0TGNzVnpoRXlRQXJKakp4THoyNkFGSzVaTE5NUGc0Z2V4ZlRtMmI3YTNkX0g0LUhvMlY0THE4WDVMN1ZBZzh2b1dXY0tfZnBfbERHLWp2STduQzFOYzd0UmkyWnkwU05zY2FKbVQyeE1pZ1ZZM1ZYaG
 JyRG9iQXJvbjZBZkJlZjRibE9PMHNVTFdWMVRobzVMMmc3TEs1alc1am41bjRYSDkzNEYydTNPazhwT211T25HOWwzZDVySy1zWVpYQ3g3NENqVDJmN3BjZ3FiQ2F3cExBMmx2T1VqOVFublRiaVpkQzc5LXF4YVpZWXRUOVc4dEFVQllpQllJTUY3UFl4ME1KaFVWUFBWM1NMR0syTkJURTF2bWM2c1RFZ2l3ODltcTRPakJLZ3hUTTNNa2paRGJzMm1OVktqUjhHODBYYjlKX3VMOWYzRzI1c1RBemdVcDB5ZEItaHR3OGFwRDlmRkhSZzhYSEdDZTVmSHNGTDNpejJvb0d0RTRkeHZSQ1ZDLW5lY3FtRG1KMS1jMEZkVDE4djRWX2ZZcGc3QXpNQzNYT2xQLXNiOE5KS2d6RUZOZldseUtHWXhaRkt6R0RhZnBBYjdEYUloWVpmU2Faa3Ftbnh4eHpDbGVrSTk2T2ZnZElsbkgtUEd6dW5Nb2FvcElxN0lPek1rZGVPazBpUFF6VmtDUGxxc0M0LXZ1enFJODZvLTQxbHZGVmhpU20yeEozRHJWQzBXbGpVUjlPVVZ0R2JoNEF3Zm8tb3hMdVFLMW1Ma2pqLW1yNkQ3d3ktNDBrcmdOV1ZLeEpET0Z4UEhnOVBQc09xQlBvbWpwUXpkNUowYWg1RmdvNk9uODJlVmVRZzdHRzkwUjZZbVBSR2dFVFVQUWl0XzRHZGE0U0xnTVZDSktZdGZvZHY2WWQwZ2pSZzJEVW5qZUtOVUp3c1RjSEhyYWs3MXNRaVNfVmRtekZsSm1CNjVhYjFlSE9VQ2I4SmtYalF1XzR3UmZXdnhuc1VmcExWd1VMMGNmNi1YWmp1RVpIUF9PaGlGWDlzWldTSjBLS1RfVFI4RzFTbWpFcTZUbXhKa1E1RHRnV014OWNwTjJSRlNwcWFyU1V0STJtUWNIM191U0tERjNuY1lhWDl0Vk55ZGpEOFl
 oUkdwWHVQdk4wWHZyejBKTklHLVBWeVlqUUJPdXNvOF9GeV9yX0ctSmVhdVNxMFRpVUhEUVM0Yl96ZDlfQWxMM2wySzZJdzAyQkVhWEhwb2Jpd3pFeEdFeU4weWFVMDRVNjliUEl5TGxIcy1sVVpnMTl5Z3hOR2pzdkxDaktqQ2gzdlhxdDRsMnlZZmFnY0RHSzdWcXpUYzhDWG5wZ1p1bnR3LnRTWm9BN2tNdGItRVJtRWs3d2MyT2c
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeydecrypt.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeydecrypt.json b/providers/azurecompute-arm/src/test/resources/vaultkeydecrypt.json
new file mode 100644
index 0000000..279b0d5
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeydecrypt.json
@@ -0,0 +1,4 @@
+{
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/003a927b194f4f6a9070ebdbdce57c59",
+	"value": "R29sZCUyNTIxJTJCR29sZCUyNTIxJTJCR29sZCUyQmZyb20lMkJ0aGUlMkJBbWVyaWNhbiUyQlJpdmVyJTI1MjE"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeydecryptrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeydecryptrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultkeydecryptrequestbody.json
new file mode 100644
index 0000000..9ac39e3
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeydecryptrequestbody.json
@@ -0,0 +1,4 @@
+{
+	"alg": "RSA-OAEP",
+	"value": "0_S8pyjjnGRlcbDa-Lt0jYjMXpXrf9Fat3elx-fSOg3dj6mYgEEs6kt79OMD4MFmVyOt6umeWAfdDIkNVnqb5fgyWceveh9wN-37jc5CFgG2PF3XIA6RII-HF2BkBcVa9KcAX3_di4KQE70PXgHf-dlz_RgLOJILeG50wzFeBFCLsjEEPp3itmoaiE6vfDidCRm5At8Vjka0G-N_afwkIijfQZLT0VaXvL39cIJE2QN3HJPZM8YPUlkFlYnY4GIRyRWSBpK_KYuVufzUGtDi6Sh8pUa67ppa7DHVZlixlmnVqI3Oeg6XUvMqbFFqVSrcNbRQDwVGL3cUtK-KB1PfKg"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeyencrypt.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeyencrypt.json b/providers/azurecompute-arm/src/test/resources/vaultkeyencrypt.json
new file mode 100644
index 0000000..53adb40
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeyencrypt.json
@@ -0,0 +1,4 @@
+{
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/003a927b194f4f6a9070ebdbdce57c59",
+	"value": "0_S8pyjjnGRlcbDa-Lt0jYjMXpXrf9Fat3elx-fSOg3dj6mYgEEs6kt79OMD4MFmVyOt6umeWAfdDIkNVnqb5fgyWceveh9wN-37jc5CFgG2PF3XIA6RII-HF2BkBcVa9KcAX3_di4KQE70PXgHf-dlz_RgLOJILeG50wzFeBFCLsjEEPp3itmoaiE6vfDidCRm5At8Vjka0G-N_afwkIijfQZLT0VaXvL39cIJE2QN3HJPZM8YPUlkFlYnY4GIRyRWSBpK_KYuVufzUGtDi6Sh8pUa67ppa7DHVZlixlmnVqI3Oeg6XUvMqbFFqVSrcNbRQDwVGL3cUtK-KB1PfKg"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeyencryptrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeyencryptrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultkeyencryptrequestbody.json
new file mode 100644
index 0000000..f246914
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeyencryptrequestbody.json
@@ -0,0 +1,4 @@
+{
+	"alg": "RSA-OAEP",
+	"value": "R29sZCUyNTIxJTJCR29sZCUyNTIxJTJCR29sZCUyQmZyb20lMkJ0aGUlMkJBbWVyaWNhbiUyQlJpdmVyJTI1MjE"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeysign.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeysign.json b/providers/azurecompute-arm/src/test/resources/vaultkeysign.json
new file mode 100644
index 0000000..b64e05a
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeysign.json
@@ -0,0 +1,4 @@
+{
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/003a927b194f4f6a9070ebdbdce57c59",
+	"value": "uO0r4P1cB-fKsDZ8cj5ahiNw8Tdsudt5zLCeEKOt29LAlPDpeGx9Q1SOFNaR7JlRYVelxsohdzvydwX8ao6MLnqlpdEj0Xt5Aadp-kN84AXW238gabS1AUyiWILCmdsBFeRU4wTRSxz2qGS_0ztHkaNln32P_9GJC72ZRlgZoVA4C_fowZolUoCWGj4V7fAzcSoiNYipWP0HkFe3xmuz-cSQg3CCAs-MclHHfMeSagLJZZQ9bpl5LIr-Ik89bNtqEqyP7Jb_fCgHajAx2lUFcRZhSIKuCfrLPMl6wzejQ2rQXX-ixEkDa73dYaPIrVW4IL3iC0UfxnfxYffHJ7QCRw"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeysignrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeysignrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultkeysignrequestbody.json
new file mode 100644
index 0000000..ea66595
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeysignrequestbody.json
@@ -0,0 +1,4 @@
+{
+	"alg": "RS256",
+	"value": "FvabKT6qGwpml59iHUJ72DZ4XyJcJ8bgpgFA4_8JFmM"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeyunwrap.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeyunwrap.json b/providers/azurecompute-arm/src/test/resources/vaultkeyunwrap.json
new file mode 100644
index 0000000..03b6740
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeyunwrap.json
@@ -0,0 +1,4 @@
+{
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/003a927b194f4f6a9070ebdbdce57c59",
+	"value": "YxzoHR65aFwD2_IOiZ5rD08jMSALA1y7b_yYW0G3hyI"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeyunwraprequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeyunwraprequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultkeyunwraprequestbody.json
new file mode 100644
index 0000000..b3f4efc
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeyunwraprequestbody.json
@@ -0,0 +1,4 @@
+{
+	"alg": "RSA-OAEP",
+	"value": "1jcTlu3KJNDBYydhaH9POWOo0tAPGkpsZVizCkHpC3g_9Kg91Q3HKK-rfZynn5W5nVPM-SVFHA3JTankcXX8gx8GycwUh4pMoyil_DV35m2QjyuiTln83OJXw-nMvRXyKdVfF7nyRcs256kW7gthAOsYUVBrfFS7DFFxsXqLNREsA8j85IqIXIm8pAB3C9uvl1I7SQhLvrwZZXXqjeCWMfseVJwWgsQFyyqH2P0f3-xnngV7cvik2k3Elrk3G_2CuJCozIIrANg9zG9Z8DrwSNNm9YooxWkSu0ZeDLOJ0bMdhcPGGm5OvKz3oZqX-39yv5klNlCRbr0q7gqmI0x25w"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeyverify.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeyverify.json b/providers/azurecompute-arm/src/test/resources/vaultkeyverify.json
new file mode 100644
index 0000000..ceca009
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeyverify.json
@@ -0,0 +1,3 @@
+{
+	"value": true
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeyverifyrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeyverifyrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultkeyverifyrequestbody.json
new file mode 100644
index 0000000..a34a45d
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeyverifyrequestbody.json
@@ -0,0 +1,5 @@
+{
+	"alg": "RS256",
+	"digest": "FvabKT6qGwpml59iHUJ72DZ4XyJcJ8bgpgFA4_8JFmM",
+	"value": "FvabKT6qGwpml59iHUJ72DZ4XyJcJ8bgpgFA4_8JFmM","value":"uO0r4P1cB-fKsDZ8cj5ahiNw8Tdsudt5zLCeEKOt29LAlPDpeGx9Q1SOFNaR7JlRYVelxsohdzvydwX8ao6MLnqlpdEj0Xt5Aadp-kN84AXW238gabS1AUyiWILCmdsBFeRU4wTRSxz2qGS_0ztHkaNln32P_9GJC72ZRlgZoVA4C_fowZolUoCWGj4V7fAzcSoiNYipWP0HkFe3xmuz-cSQg3CCAs-MclHHfMeSagLJZZQ9bpl5LIr-Ik89bNtqEqyP7Jb_fCgHajAx2lUFcRZhSIKuCfrLPMl6wzejQ2rQXX-ixEkDa73dYaPIrVW4IL3iC0UfxnfxYffHJ7QCRw"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeywrap.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeywrap.json b/providers/azurecompute-arm/src/test/resources/vaultkeywrap.json
new file mode 100644
index 0000000..bb30400
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeywrap.json
@@ -0,0 +1,4 @@
+{
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/003a927b194f4f6a9070ebdbdce57c59",
+	"value": "1jcTlu3KJNDBYydhaH9POWOo0tAPGkpsZVizCkHpC3g_9Kg91Q3HKK-rfZynn5W5nVPM-SVFHA3JTankcXX8gx8GycwUh4pMoyil_DV35m2QjyuiTln83OJXw-nMvRXyKdVfF7nyRcs256kW7gthAOsYUVBrfFS7DFFxsXqLNREsA8j85IqIXIm8pAB3C9uvl1I7SQhLvrwZZXXqjeCWMfseVJwWgsQFyyqH2P0f3-xnngV7cvik2k3Elrk3G_2CuJCozIIrANg9zG9Z8DrwSNNm9YooxWkSu0ZeDLOJ0bMdhcPGGm5OvKz3oZqX-39yv5klNlCRbr0q7gqmI0x25w"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultkeywraprequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultkeywraprequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultkeywraprequestbody.json
new file mode 100644
index 0000000..634f37b
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultkeywraprequestbody.json
@@ -0,0 +1,4 @@
+{
+	"alg": "RSA-OAEP",
+	"value": "YxzoHR65aFwD2_IOiZ5rD08jMSALA1y7b_yYW0G3hyI"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultlist.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultlist.json b/providers/azurecompute-arm/src/test/resources/vaultlist.json
new file mode 100644
index 0000000..d8c1421
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultlist.json
@@ -0,0 +1,29 @@
+{
+  "value": [{
+    "id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults/kvvaultapilivetest",
+    "name": "kvvaultapilivetest",
+    "type": "Microsoft.KeyVault/vaults",
+    "location": "westeurope",
+    "tags": {},
+    "properties": {
+      "sku": {
+        "family": "A",
+        "name": "standard"
+      },
+      "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+      "accessPolicies": [{
+        "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+        "objectId": "5a7f4cb9-ce9d-4b31-87ce-f61083c4b0ea",
+        "permissions": {
+          "certificates": ["Get", "List", "Update", "Create", "Import", "Delete", "ManageContacts", "ManageIssuers", "GetIssuers", "ListIssuers", "SetIssuers", "DeleteIssuers", "Purge", "Recover"],
+          "keys": ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", "Purge"],
+          "secrets": ["Get", "List", "Set", "Delete", "Recover", "Backup", "Restore", "Purge"],
+          "storage": []
+        }
+      }],
+      "enabledForDeployment": false,
+      "vaultUri": "https://kvvaultapilivetest.vault.azure.net/"
+    }
+  }],
+  "nextLink": "https://management.azure.com/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourcegroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults?api-version=2016-10-01&$skiptoken=a3Z2YXVsdGFwaWxpdmV0ZXN0"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultlistcertificateissuers.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultlistcertificateissuers.json b/providers/azurecompute-arm/src/test/resources/vaultlistcertificateissuers.json
new file mode 100644
index 0000000..0342427
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultlistcertificateissuers.json
@@ -0,0 +1,7 @@
+{
+	"value": [{
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/issuers/globalsign01",
+		"provider": "GlobalSign"
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultlistcertificates.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultlistcertificates.json b/providers/azurecompute-arm/src/test/resources/vaultlistcertificates.json
new file mode 100644
index 0000000..99e714d
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultlistcertificates.json
@@ -0,0 +1,27 @@
+{
+	"value": [{
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate",
+		"x5t": "K7HXO6YIK6xwCX8W1InUKsJV9Rk",
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509345867,
+			"exp": 1540882467,
+			"created": 1509346467,
+			"updated": 1509346472
+		},
+		"tags": {
+			"selfsigned": "true"
+		}
+	}, {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myImportableCertificate",
+		"x5t": "-qEnW6P9TdfOOXzbNQNS5ZKveRo",
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509231134,
+			"exp": 1541631134,
+			"created": 1509346469,
+			"updated": 1509346469
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultlistcertificateversions.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultlistcertificateversions.json b/providers/azurecompute-arm/src/test/resources/vaultlistcertificateversions.json
new file mode 100644
index 0000000..0480f2e
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultlistcertificateversions.json
@@ -0,0 +1,17 @@
+{
+	"value": [{
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+		"x5t": "K7HXO6YIK6xwCX8W1InUKsJV9Rk",
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509345867,
+			"exp": 1540882467,
+			"created": 1509346467,
+			"updated": 1509346472
+		},
+		"tags": {
+			"selfsigned": "true"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultlistdeleted.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultlistdeleted.json b/providers/azurecompute-arm/src/test/resources/vaultlistdeleted.json
new file mode 100644
index 0000000..332785a
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultlistdeleted.json
@@ -0,0 +1,15 @@
+{
+	"value": [{
+		"id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/providers/Microsoft.KeyVault/locations/westeurope/deletedVaults/kvvaultapilivetest",
+		"name": "kvvaultapilivetest",
+		"type": "Microsoft.KeyVault/deletedVaults",
+		"properties": {
+			"vaultId": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults/kvvaultapilivetest",
+			"location": "westeurope",
+			"tags": {},
+			"deletionDate": "2017-10-29T22:06:02Z",
+			"scheduledPurgeDate": "2018-01-27T22:06:02Z"
+		}
+	}],
+	"nextLink": "https://management.azure.com/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/providers/Microsoft.KeyVault/deletedVaults?api-version=2016-10-01&%24skiptoken=HY1db4IwGEb%2fS7PsrpQyUCQxiwts0QkMbDHxjo8Xh%2bUrtLgN438f8fJJzjnPDbXwq%2fZVKyRybujoHZjH4%2fDLQw76VqqXDiFN2qZnaKBVWjqNA2h51xA5ZjIfql5VXSvJSwlgUwqY0qzEZmbleJUvDJwapWFnFl0uDZP0Q3etChgk8at86GRXKu0T%2fpJ0rBUpoAYFxWPI17Sv8HUm5%2fja0OkCUx3r9PlJivmxE9CuuUiOcbJjMY%2ffmZfwA1%2bFe17z0t1Sn50t%2fyLM4LKZgknogZubPkvsQOzeQrdwQ49PMRNT4J3cSN9akfCNaDp9%2bOzh%2fERsg%2b73fw%3d%3d"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultlistdeletedcertificates.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultlistdeletedcertificates.json b/providers/azurecompute-arm/src/test/resources/vaultlistdeletedcertificates.json
new file mode 100644
index 0000000..4ac53b0
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultlistdeletedcertificates.json
@@ -0,0 +1,18 @@
+{
+	"value": [{
+		"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedcertificates/myRecoverableCertificate",
+		"deletedDate": 1509346545,
+		"scheduledPurgeDate": 1517122545,
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myRecoverableCertificate",
+		"x5t": "-qEnW6P9TdfOOXzbNQNS5ZKveRo",
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509231134,
+			"exp": 1541631134,
+			"created": 1509346510,
+			"updated": 1509346510,
+			"recoveryLevel": "Recoverable+Purgeable"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultlistdeletedkeys.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultlistdeletedkeys.json b/providers/azurecompute-arm/src/test/resources/vaultlistdeletedkeys.json
new file mode 100644
index 0000000..08dde30
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultlistdeletedkeys.json
@@ -0,0 +1,15 @@
+{
+	"value": [{
+		"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedkeys/myRecoverableKey",
+		"deletedDate": 1509335960,
+		"scheduledPurgeDate": 1517111960,
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myRecoverableKey",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335950,
+			"updated": 1509335950,
+			"recoveryLevel": "Recoverable+Purgeable"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultlistdeletedsecrets.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultlistdeletedsecrets.json b/providers/azurecompute-arm/src/test/resources/vaultlistdeletedsecrets.json
new file mode 100644
index 0000000..1719798
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultlistdeletedsecrets.json
@@ -0,0 +1,16 @@
+{
+	"value": [{
+		"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedsecrets/myRecoverableSecret",
+		"deletedDate": 1509335980,
+		"scheduledPurgeDate": 1517111980,
+		"contentType": "aNewSecretKey",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/myRecoverableSecret",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335958,
+			"updated": 1509335958,
+			"recoveryLevel": "Recoverable+Purgeable"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultlistkeys.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultlistkeys.json b/providers/azurecompute-arm/src/test/resources/vaultlistkeys.json
new file mode 100644
index 0000000..313dae2
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultlistkeys.json
@@ -0,0 +1,42 @@
+{
+  "value": [{
+    "kid": "https://kvvaultapilivetest.vault.azure.net/keys/myCertificate",
+    "attributes": {
+      "enabled": true,
+      "nbf": 1509313915,
+      "exp": 1540850515,
+      "created": 1509314515,
+      "updated": 1509314515,
+      "recoveryLevel": "Purgeable"
+    },
+    "managed": true
+  }, {
+    "kid": "https://kvvaultapilivetest.vault.azure.net/keys/myImportableCertificate",
+    "attributes": {
+      "enabled": true,
+      "nbf": 1509231134,
+      "exp": 1541631134,
+      "created": 1509314521,
+      "updated": 1509314521,
+      "recoveryLevel": "Purgeable"
+    },
+    "managed": true
+  }, {
+    "kid": "https://kvvaultapilivetest.vault.azure.net/keys/myImportKey",
+    "attributes": {
+      "enabled": true,
+      "created": 1509314522,
+      "updated": 1509314522,
+      "recoveryLevel": "Purgeable"
+    }
+  }, {
+    "kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey",
+    "attributes": {
+      "enabled": true,
+      "created": 1509314506,
+      "updated": 1509314506,
+      "recoveryLevel": "Purgeable"
+    }
+  }],
+  "nextLink": null
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultlistsecrets.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultlistsecrets.json b/providers/azurecompute-arm/src/test/resources/vaultlistsecrets.json
new file mode 100644
index 0000000..73063d1
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultlistsecrets.json
@@ -0,0 +1,40 @@
+{
+	"value": [{
+		"contentType": "application/x-pkcs12",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/myCertificate",
+		"managed": true,
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509335314,
+			"exp": 1540871914,
+			"created": 1509335914,
+			"updated": 1509335920,
+			"recoveryLevel": "Purgeable"
+		},
+		"tags": {
+			"selfsigned": "true"
+		}
+	}, {
+		"contentType": "application/x-pem-file",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/myImportableCertificate",
+		"managed": true,
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509231134,
+			"exp": 1541631134,
+			"created": 1509335917,
+			"updated": 1509335917,
+			"recoveryLevel": "Purgeable"
+		}
+	}, {
+		"contentType": "testSecretKey",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335932,
+			"updated": 1509335932,
+			"recoveryLevel": "Purgeable"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultmergecertificate.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultmergecertificate.json b/providers/azurecompute-arm/src/test/resources/vaultmergecertificate.json
new file mode 100644
index 0000000..4511b2b
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultmergecertificate.json
@@ -0,0 +1,62 @@
+{
+  "id": "https://jimskv1.vault.azure.net/certificates/jmskv1cert6/d8f385d3741b4b1cba9c002299e892dd",
+  "kid": "https://jimskv1.vault.azure.net/keys/jmskv1cert6/d8f385d3741b4b1cba9c002299e892dd",
+  "sid": "https://jimskv1.vault.azure.net/secrets/jmskv1cert6/d8f385d3741b4b1cba9c002299e892dd",
+  "x5t": "SQix1jyV9XeF2Q8MCecpUr0etk4",
+  "cer": "MIIEQTCCAikCAhABMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMSIwIAYDVQQDDBlBQ01FIFRlc3QgSW50ZXJtZWRpYXRlIENBMB4XDTE3MTEyODIzMDkxMVoXDTE4MTIwODIzMDkxMVowbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlBbGxlZ2hhbnkxDTALBgNVBAoTBEFDTUUxFDASBgNVBAsTC0VuZ2luZWVyaW5nMRkwFwYDVQQDExBBQ01FIEZvb2JhciBDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwE0Gu/rJlbkqL0ynSbkCdrM+XP4dis/QNPz819ybXXpIX8HfkmAxrpLmfWh36KlflFYgpuV/J5lnJKlRmPWWOFjizAhq0dBijJUdLf6+QuImDjijd/nkO5SeQApZ4D50imTJL81vs2vwAfcCLwdlf7MNrMIfBsyjRSJh/Phjqib6kcYWcz6I6yTfkcsXcUB1JgR8KnQdVy0gYDu1MacHu2VYuS35HpPcQyXRqR1Ky9qh16+OhheRJw03ghEiPMcKbWS5NRgw/l/itoST2Qd6BzJTHUkJaXHNSO9fNF/fAccqECp0ZfaCSrfZs47EcjCv+N7bvrqfFl4BhB77tb7ZAQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCbpjL5XGC3T6gWU8sxCbS0VBmgamyvSHA8jLkWUXQfPirGFwgdGN7394mYViVU0qe6ZqmnhlhqZ1h6VbkBMVwzp3KlRhuoz/fXlW+TFvEC8Q3F+7oUdHn8w3EMyjKA5EbLzRIYXBizdbfEn8eJynjyWEdOaJpMmy9au/oFSqpmZDcxWW2SKq4j+Pqjhr+Ig4BmTVvwR6iEERPYQI4pv0O
 xRa7xA6Hb8NF02TyDzV7k02kN9PL/QO2dh9f3U0YY5XlV1HQzQ/BmavudPT1MiuH0CVSlCHE/JetXdJdWZA4HRiwXJn+5K8MgE5i1hjjXN/dLuaY8vItJzyrgxGRtRZoJA8t7B3QJjDECmey2m0K0qjYu7l1jAVFBWaqDdJQLmnKxViuz0MF4uFqgveW6CZEMcdqwZQ2cmZPlmcjneT0veBBh5qCdFNFM9pYDn0wqt5ruK+vqHkqJdMToBPNaBfGX10ADlB8rKW24eve+2c0iVmorJuTPdOqm2L9NKGpf2scvZZU4n/khkGKihrSOLygeLZ6SQc74cRL35FmzJqqKKpZtG9/a91dkJDz2XUiTO5TialaOU9+A1+Xrzj8LGG9JnB0KizF5dOd5mbZTROr3VCexRxyTrtZLpeJK+lYQLkDQ5ixWnd2sikym4hy3+NZ1g6nE+GQpqSALB4YnsFgUdg==",
+  "attributes": {
+    "enabled": true,
+    "nbf": 1511910551,
+    "exp": 1544310551,
+    "created": 1511911458,
+    "updated": 1511911458,
+    "recoveryLevel": "Purgeable"
+  },
+  "policy": {
+    "id": "https://jimskv1.vault.azure.net/certificates/jmskv1cert6/policy",
+    "key_props": {
+      "exportable": true,
+      "kty": "RSA",
+      "key_size": 2048,
+      "reuse_key": true
+    },
+    "secret_props": {
+      "contentType": "application/x-pem-file"
+    },
+    "x509_props": {
+      "subject": "C=US, ST=CA, L=Alleghany, O=ACME, OU=Engineering, CN=ACME Foobar Cert",
+      "sans": {
+        "emails": [],
+        "dns_names": [],
+        "upns": []
+      },
+      "ekus": [
+        "1.3.6.1.5.5.7.3.1"
+      ],
+      "key_usage": [
+        "cRLSign",
+        "dataEncipherment",
+        "digitalSignature",
+        "keyAgreement",
+        "keyCertSign",
+        "keyEncipherment"
+      ],
+      "validity_months": 24,
+      "basic_constraints": {
+        "ca": false
+      }
+    },
+    "lifetime_actions": [],
+    "issuer": {
+      "name": "Unknown"
+    },
+    "attributes": {
+      "enabled": true,
+      "created": 1511910301,
+      "updated": 1511910301
+    }
+  },
+  "pending": {
+    "id": "https://jimskv1.vault.azure.net/certificates/jmskv1cert6/pending"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultmergecertificaterequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultmergecertificaterequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultmergecertificaterequestbody.json
new file mode 100644
index 0000000..045b0c3
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultmergecertificaterequestbody.json
@@ -0,0 +1,10 @@
+{
+    "attributes": {
+        "enabled": true
+    },
+    "x5c": [
+        "MIIFljCCA36gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAoMDUFDTUUgVGVzdCBMdGQxGjAYBgNVBAMMEUFDTUUgVGVzdCBSb290IENBMB4XDTE3MTEyODIwMDA1NVoXDTI3MTEyNjIwMDA1NVowXjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAoMDUFDTUUgVGVzdCBMdGQxIjAgBgNVBAMMGUFDTUUgVGVzdCBJbnRlcm1lZGlhdGUgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDU1CRXpOEOzNxom8xwA3kYb4kmc3JX8cSuWZKoaPm8KvhsgYOkH+1z4dt2OC/FtSaWJuMZrSTJs/lFmdyE1yuyRBhyqwCK3ZnFxCG10NXiHgj+uHK8ajNJQDitFuz4yLwgp6R91UhuCPPMAKL3eDwC/PPqnT6/D/EPG7eotlokUrpNrhTdz5YYH4VhXwM3VKkIdtSkPQTMftZ0Rbzd0u4sJlsF+RtXVY7/zzg2st0d2vEddpaOENFQfYT7D8C9VsKqo13sClQGoKoPa20a1Yvh65bK2P0SDzhbIu2xQCeis+wC/h0ZZrwCW5/ivCFo4DILk9269LaN4xqpnwJz9QrNFxwglktZm2j7gm4K9BH5a437E6xMvo7WXYwt+0305lLN4khL2ZhagFrvEYG6SLgJwZRWTAE8IsOC9Oyrq0CgpX+KpGkGMpokrgH8aWVCSgQxsUCPJYaBwMgAWepuf3Rx54cUV66vYb7z2NlSvV7JNvtNdXFFjddOfdoQC0QIVOJM1sOgUN/9negFRUtspudB397h+ncvnLnlrg+QaTZNjfCvP4YV+t0eMmlyhBpxIKxPnP0vQCVH9JfpJeZxpY9hFwbxfKcsNLhYHC/2
 2ntbr1UMiIV1HDN8o1gQb6KwyPnS4SVggnf+WPqO4xhXCtwqSDQSAuVe9t03xAs1SGvt8wIDAQABo2YwZDAdBgNVHQ4EFgQURR0ZtFNyLfu1x57+yYiybG149JQwHwYDVR0jBBgwFoAUSCW8FQ+iFqE5L3zx0+2Onc3d1vYwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAMo/VnCd/ndvOfBrI29QhBcwaHEgiC9QUA9u63EhAFGHaThtSd8dFnJLhOQaS2+rYC1nUhkZa03ImceTQpWsGpXOm/sFIAWojzgxqTEopCP5OUxVu6FuJMOGaUvaupGLIJSrUpzpn31NJxThOANEtd0sbMK5fk7sYXLlLNeCOfLu/dytit5jfDsUERJQGTi2YmzIYgFli0ECdswgxAb3b1klKvqOcXZI4K6WkCl5L/wjEP5XygnfyXJ6nMTSLpxuD7dRpqyitmauavfscGpLwYMArx+5gn2jwlq4TIDWdaKi86Oz8VAg+X0C5qBcAdx6k8pFUSjeD2kvykNbEdxBtkD4dgUn5UDmqB2IfW5UiL04cDBaxijDLbsYvjOE+wiXbESxnZf9bQXdeFSemARIWmE6to0uOmdp+snetB88Nw8EQ6faL9aKGBYPI3+KDy1IdMtyU50dMj7BSogZeBHh+6B/1qqlp3VGm5/PBaoyZJLRgx7VQNYFcPjUk0iLaBK7bqJ1CFkr5YX3/Ypjty4u1BD1LxEG2u60Q6PpLgBGGxqXDH6KpNkH2Z9mdagLL+HfZDf73m+J2PD0puLzVVcvzwPRf3nJyyh7ALnG9gd5gl8ksy6uHBizAOmzO0Ize7B8/1he1dSxZQ7wnHIuZ9HSvTvVHv8ST2l7XkKGaB0+BBHR",
+        "MIIFkjCCA3qgAwIBAgIJANPuNc8d4n46MA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMRowGAYDVQQDDBFBQ01FIFRlc3QgUm9vdCBDQTAeFw0xNzExMjgxOTU3MDJaFw0zNzExMjMxOTU3MDJaMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMRowGAYDVQQDDBFBQ01FIFRlc3QgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOP2me/TzHq4fGve9X2fdDXQFayCq4XZ/mijLkerAPoka3T7lNfO4FI0jvnPNbrf6KZ2YolwiQ04OnFekder5WoVuoQFKZMLCFulHK/+GpyJPdE0fRRrbIsnSRiTvX7fvarHilQKu1B5vKyn6SLzNbvA8+zKJuCiA+ghIxiIKTI3wenzp/uuaWS9+qUXISINJnitgNxD9FnV3CSvAbuzTWfoWDNjS4q7BqUsY6sHCLCmds8kd2ah/CLOmraC7diwA5okE6CCSNzMI7fSzAztRx4BmYW9EgZjwacoWPUp+lGM9ZxRhPcD/euk91Qks10h04EkUXV2HpSVwtNYoSuFBADlNYw7mmn+UpzvG7wBUusDbjhDWG22i5IyOBRuuiUGYgDzleo7v7b9W8ocn5/q4cgEryed7LRxspP7wa614DcHz/6Rmg7CD1dH7zo96EyDl4tlyFB37XQzDtdvs0tU9ahQxFMVj+wcNEnVf7IBv93ukv5YA0sgcfmanLu5fiRBT+hw2ADb4OWNFhR+ZnuTpAtsc27bbjrJ6h6cwYnUFLdYiOVTTFYZjVKLlIhfpB1gNhzZFeiYwZBeU8bvmhD3xASApNyJL93PqTJYHxVY
 v9rfW5hcGkAJz+0gEBXSDEuKekm0vEujdMDMo9Atkv6HR3oeQttd3mRL81PfcxAqQbC1AgMBAAGjYzBhMB0GA1UdDgQWBBRIJbwVD6IWoTkvfPHT7Y6dzd3W9jAfBgNVHSMEGDAWgBRIJbwVD6IWoTkvfPHT7Y6dzd3W9jAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAlLFwOq4VgtDEJ6vpWn21GfweuB2Saz8DYoDBrvcXLGImArfp9n0baeXqa9qqR8Tu12ZF2dEkvQsFnZ6gzobmctw3k4c+Oz0pJ5/iFUTotkqhFf8/RcZCwEk0pcEyAqlQ2LehMyB5UvFhSg54uucj4Ofp1CSjQ59GSe7u9LvHO0cEOdN7jQS9OaAnP03WYktDFTupxD+7xyQsIKePilCKVYgOAlJPKMAaaYcSGMGljUOizLVNYPLaFermcOzdaoyHz6btjq56febLQ2c0VSrL1C2+qOaVbJz0oQSEwt6meADvO8rcP/ZNK9T0kmDxbQzqpKZ31bt/d0iRBygGaFy2vYgybwo3iPGqPTInv2FaTRvWnHP/NlbdNKFwd876hMM+8m9PcNRcIeM+yFwD0aCJtfqorxdN2nNEioP5X08yVnexO9ywkDcAXQTj4RV9TyGlzZRc+1JM1LkhIgLvI6OAOxmrnXnHW08Vzo3yhK72NtnDukU4UcCAHOao6Vq+MJu2Ngb11WBlZulObcEoccxhpx929xIeOj67ZSLOEopP7z+fesjgABc4HQVQQ0v37eiYvVT3Bzz+TklfL/gEVLAk6AqLcFizs9vND2bTrGDgE8AWEX77lBsLGg92ofPXeXZsHsh43m2fRjAnroXQVsziQ0zJgHcA7OmLlB8mkb8fl3E=",
+        "MIIEQTCCAikCAhABMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMSIwIAYDVQQDDBlBQ01FIFRlc3QgSW50ZXJtZWRpYXRlIENBMB4XDTE3MTEyODIzMDkxMVoXDTE4MTIwODIzMDkxMVowbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlBbGxlZ2hhbnkxDTALBgNVBAoTBEFDTUUxFDASBgNVBAsTC0VuZ2luZWVyaW5nMRkwFwYDVQQDExBBQ01FIEZvb2JhciBDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwE0Gu/rJlbkqL0ynSbkCdrM+XP4dis/QNPz819ybXXpIX8HfkmAxrpLmfWh36KlflFYgpuV/J5lnJKlRmPWWOFjizAhq0dBijJUdLf6+QuImDjijd/nkO5SeQApZ4D50imTJL81vs2vwAfcCLwdlf7MNrMIfBsyjRSJh/Phjqib6kcYWcz6I6yTfkcsXcUB1JgR8KnQdVy0gYDu1MacHu2VYuS35HpPcQyXRqR1Ky9qh16+OhheRJw03ghEiPMcKbWS5NRgw/l/itoST2Qd6BzJTHUkJaXHNSO9fNF/fAccqECp0ZfaCSrfZs47EcjCv+N7bvrqfFl4BhB77tb7ZAQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCbpjL5XGC3T6gWU8sxCbS0VBmgamyvSHA8jLkWUXQfPirGFwgdGN7394mYViVU0qe6ZqmnhlhqZ1h6VbkBMVwzp3KlRhuoz/fXlW+TFvEC8Q3F+7oUdHn8w3EMyjKA5EbLzRIYXBizdbfEn8eJynjyWEdOaJpMmy9au/oFSqpmZDcxWW2SKq4j+Pqjhr+Ig4BmTVvwR6iEERPYQI4pv0Ox
 Ra7xA6Hb8NF02TyDzV7k02kN9PL/QO2dh9f3U0YY5XlV1HQzQ/BmavudPT1MiuH0CVSlCHE/JetXdJdWZA4HRiwXJn+5K8MgE5i1hjjXN/dLuaY8vItJzyrgxGRtRZoJA8t7B3QJjDECmey2m0K0qjYu7l1jAVFBWaqDdJQLmnKxViuz0MF4uFqgveW6CZEMcdqwZQ2cmZPlmcjneT0veBBh5qCdFNFM9pYDn0wqt5ruK+vqHkqJdMToBPNaBfGX10ADlB8rKW24eve+2c0iVmorJuTPdOqm2L9NKGpf2scvZZU4n/khkGKihrSOLygeLZ6SQc74cRL35FmzJqqKKpZtG9/a91dkJDz2XUiTO5TialaOU9+A1+Xrzj8LGG9JnB0KizF5dOd5mbZTROr3VCexRxyTrtZLpeJK+lYQLkDQ5ixWnd2sikym4hy3+NZ1g6nE+GQpqSALB4YnsFgUdg=="
+    ]
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultmergex5c-1.txt
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultmergex5c-1.txt b/providers/azurecompute-arm/src/test/resources/vaultmergex5c-1.txt
new file mode 100644
index 0000000..d8ff78d
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultmergex5c-1.txt
@@ -0,0 +1 @@
+MIIFljCCA36gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAoMDUFDTUUgVGVzdCBMdGQxGjAYBgNVBAMMEUFDTUUgVGVzdCBSb290IENBMB4XDTE3MTEyODIwMDA1NVoXDTI3MTEyNjIwMDA1NVowXjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAoMDUFDTUUgVGVzdCBMdGQxIjAgBgNVBAMMGUFDTUUgVGVzdCBJbnRlcm1lZGlhdGUgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDU1CRXpOEOzNxom8xwA3kYb4kmc3JX8cSuWZKoaPm8KvhsgYOkH+1z4dt2OC/FtSaWJuMZrSTJs/lFmdyE1yuyRBhyqwCK3ZnFxCG10NXiHgj+uHK8ajNJQDitFuz4yLwgp6R91UhuCPPMAKL3eDwC/PPqnT6/D/EPG7eotlokUrpNrhTdz5YYH4VhXwM3VKkIdtSkPQTMftZ0Rbzd0u4sJlsF+RtXVY7/zzg2st0d2vEddpaOENFQfYT7D8C9VsKqo13sClQGoKoPa20a1Yvh65bK2P0SDzhbIu2xQCeis+wC/h0ZZrwCW5/ivCFo4DILk9269LaN4xqpnwJz9QrNFxwglktZm2j7gm4K9BH5a437E6xMvo7WXYwt+0305lLN4khL2ZhagFrvEYG6SLgJwZRWTAE8IsOC9Oyrq0CgpX+KpGkGMpokrgH8aWVCSgQxsUCPJYaBwMgAWepuf3Rx54cUV66vYb7z2NlSvV7JNvtNdXFFjddOfdoQC0QIVOJM1sOgUN/9negFRUtspudB397h+ncvnLnlrg+QaTZNjfCvP4YV+t0eMmlyhBpxIKxPnP0vQCVH9JfpJeZxpY9hFwbxfKcsNLhYHC/22ntbr1UMi
 IV1HDN8o1gQb6KwyPnS4SVggnf+WPqO4xhXCtwqSDQSAuVe9t03xAs1SGvt8wIDAQABo2YwZDAdBgNVHQ4EFgQURR0ZtFNyLfu1x57+yYiybG149JQwHwYDVR0jBBgwFoAUSCW8FQ+iFqE5L3zx0+2Onc3d1vYwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAMo/VnCd/ndvOfBrI29QhBcwaHEgiC9QUA9u63EhAFGHaThtSd8dFnJLhOQaS2+rYC1nUhkZa03ImceTQpWsGpXOm/sFIAWojzgxqTEopCP5OUxVu6FuJMOGaUvaupGLIJSrUpzpn31NJxThOANEtd0sbMK5fk7sYXLlLNeCOfLu/dytit5jfDsUERJQGTi2YmzIYgFli0ECdswgxAb3b1klKvqOcXZI4K6WkCl5L/wjEP5XygnfyXJ6nMTSLpxuD7dRpqyitmauavfscGpLwYMArx+5gn2jwlq4TIDWdaKi86Oz8VAg+X0C5qBcAdx6k8pFUSjeD2kvykNbEdxBtkD4dgUn5UDmqB2IfW5UiL04cDBaxijDLbsYvjOE+wiXbESxnZf9bQXdeFSemARIWmE6to0uOmdp+snetB88Nw8EQ6faL9aKGBYPI3+KDy1IdMtyU50dMj7BSogZeBHh+6B/1qqlp3VGm5/PBaoyZJLRgx7VQNYFcPjUk0iLaBK7bqJ1CFkr5YX3/Ypjty4u1BD1LxEG2u60Q6PpLgBGGxqXDH6KpNkH2Z9mdagLL+HfZDf73m+J2PD0puLzVVcvzwPRf3nJyyh7ALnG9gd5gl8ksy6uHBizAOmzO0Ize7B8/1he1dSxZQ7wnHIuZ9HSvTvVHv8ST2l7XkKGaB0+BBHR
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultmergex5c-2.txt
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultmergex5c-2.txt b/providers/azurecompute-arm/src/test/resources/vaultmergex5c-2.txt
new file mode 100644
index 0000000..c1f842d
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultmergex5c-2.txt
@@ -0,0 +1 @@
+MIIFkjCCA3qgAwIBAgIJANPuNc8d4n46MA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMRowGAYDVQQDDBFBQ01FIFRlc3QgUm9vdCBDQTAeFw0xNzExMjgxOTU3MDJaFw0zNzExMjMxOTU3MDJaMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMRowGAYDVQQDDBFBQ01FIFRlc3QgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOP2me/TzHq4fGve9X2fdDXQFayCq4XZ/mijLkerAPoka3T7lNfO4FI0jvnPNbrf6KZ2YolwiQ04OnFekder5WoVuoQFKZMLCFulHK/+GpyJPdE0fRRrbIsnSRiTvX7fvarHilQKu1B5vKyn6SLzNbvA8+zKJuCiA+ghIxiIKTI3wenzp/uuaWS9+qUXISINJnitgNxD9FnV3CSvAbuzTWfoWDNjS4q7BqUsY6sHCLCmds8kd2ah/CLOmraC7diwA5okE6CCSNzMI7fSzAztRx4BmYW9EgZjwacoWPUp+lGM9ZxRhPcD/euk91Qks10h04EkUXV2HpSVwtNYoSuFBADlNYw7mmn+UpzvG7wBUusDbjhDWG22i5IyOBRuuiUGYgDzleo7v7b9W8ocn5/q4cgEryed7LRxspP7wa614DcHz/6Rmg7CD1dH7zo96EyDl4tlyFB37XQzDtdvs0tU9ahQxFMVj+wcNEnVf7IBv93ukv5YA0sgcfmanLu5fiRBT+hw2ADb4OWNFhR+ZnuTpAtsc27bbjrJ6h6cwYnUFLdYiOVTTFYZjVKLlIhfpB1gNhzZFeiYwZBeU8bvmhD3xASApNyJL93PqTJYHxVYv9rfW5hcG
 kAJz+0gEBXSDEuKekm0vEujdMDMo9Atkv6HR3oeQttd3mRL81PfcxAqQbC1AgMBAAGjYzBhMB0GA1UdDgQWBBRIJbwVD6IWoTkvfPHT7Y6dzd3W9jAfBgNVHSMEGDAWgBRIJbwVD6IWoTkvfPHT7Y6dzd3W9jAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAlLFwOq4VgtDEJ6vpWn21GfweuB2Saz8DYoDBrvcXLGImArfp9n0baeXqa9qqR8Tu12ZF2dEkvQsFnZ6gzobmctw3k4c+Oz0pJ5/iFUTotkqhFf8/RcZCwEk0pcEyAqlQ2LehMyB5UvFhSg54uucj4Ofp1CSjQ59GSe7u9LvHO0cEOdN7jQS9OaAnP03WYktDFTupxD+7xyQsIKePilCKVYgOAlJPKMAaaYcSGMGljUOizLVNYPLaFermcOzdaoyHz6btjq56febLQ2c0VSrL1C2+qOaVbJz0oQSEwt6meADvO8rcP/ZNK9T0kmDxbQzqpKZ31bt/d0iRBygGaFy2vYgybwo3iPGqPTInv2FaTRvWnHP/NlbdNKFwd876hMM+8m9PcNRcIeM+yFwD0aCJtfqorxdN2nNEioP5X08yVnexO9ywkDcAXQTj4RV9TyGlzZRc+1JM1LkhIgLvI6OAOxmrnXnHW08Vzo3yhK72NtnDukU4UcCAHOao6Vq+MJu2Ngb11WBlZulObcEoccxhpx929xIeOj67ZSLOEopP7z+fesjgABc4HQVQQ0v37eiYvVT3Bzz+TklfL/gEVLAk6AqLcFizs9vND2bTrGDgE8AWEX77lBsLGg92ofPXeXZsHsh43m2fRjAnroXQVsziQ0zJgHcA7OmLlB8mkb8fl3E=
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultmergex5c-3.txt
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultmergex5c-3.txt b/providers/azurecompute-arm/src/test/resources/vaultmergex5c-3.txt
new file mode 100644
index 0000000..5ac2516
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultmergex5c-3.txt
@@ -0,0 +1 @@
+MIIEQTCCAikCAhABMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMSIwIAYDVQQDDBlBQ01FIFRlc3QgSW50ZXJtZWRpYXRlIENBMB4XDTE3MTEyODIzMDkxMVoXDTE4MTIwODIzMDkxMVowbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlBbGxlZ2hhbnkxDTALBgNVBAoTBEFDTUUxFDASBgNVBAsTC0VuZ2luZWVyaW5nMRkwFwYDVQQDExBBQ01FIEZvb2JhciBDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwE0Gu/rJlbkqL0ynSbkCdrM+XP4dis/QNPz819ybXXpIX8HfkmAxrpLmfWh36KlflFYgpuV/J5lnJKlRmPWWOFjizAhq0dBijJUdLf6+QuImDjijd/nkO5SeQApZ4D50imTJL81vs2vwAfcCLwdlf7MNrMIfBsyjRSJh/Phjqib6kcYWcz6I6yTfkcsXcUB1JgR8KnQdVy0gYDu1MacHu2VYuS35HpPcQyXRqR1Ky9qh16+OhheRJw03ghEiPMcKbWS5NRgw/l/itoST2Qd6BzJTHUkJaXHNSO9fNF/fAccqECp0ZfaCSrfZs47EcjCv+N7bvrqfFl4BhB77tb7ZAQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCbpjL5XGC3T6gWU8sxCbS0VBmgamyvSHA8jLkWUXQfPirGFwgdGN7394mYViVU0qe6ZqmnhlhqZ1h6VbkBMVwzp3KlRhuoz/fXlW+TFvEC8Q3F+7oUdHn8w3EMyjKA5EbLzRIYXBizdbfEn8eJynjyWEdOaJpMmy9au/oFSqpmZDcxWW2SKq4j+Pqjhr+Ig4BmTVvwR6iEERPYQI4pv0OxRa7xA6Hb8
 NF02TyDzV7k02kN9PL/QO2dh9f3U0YY5XlV1HQzQ/BmavudPT1MiuH0CVSlCHE/JetXdJdWZA4HRiwXJn+5K8MgE5i1hjjXN/dLuaY8vItJzyrgxGRtRZoJA8t7B3QJjDECmey2m0K0qjYu7l1jAVFBWaqDdJQLmnKxViuz0MF4uFqgveW6CZEMcdqwZQ2cmZPlmcjneT0veBBh5qCdFNFM9pYDn0wqt5ruK+vqHkqJdMToBPNaBfGX10ADlB8rKW24eve+2c0iVmorJuTPdOqm2L9NKGpf2scvZZU4n/khkGKihrSOLygeLZ6SQc74cRL35FmzJqqKKpZtG9/a91dkJDz2XUiTO5TialaOU9+A1+Xrzj8LGG9JnB0KizF5dOd5mbZTROr3VCexRxyTrtZLpeJK+lYQLkDQ5ixWnd2sikym4hy3+NZ1g6nE+GQpqSALB4YnsFgUdg==
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedcertificate.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedcertificate.json b/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedcertificate.json
new file mode 100644
index 0000000..d75a38a
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedcertificate.json
@@ -0,0 +1,52 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"x5t": "-qEnW6P9TdfOOXzbNQNS5ZKveRo",
+	"cer": "MIIFNDCCAxygAwIBAgICQ0MwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEhMB8GA1UEAwwYRm9vYmFyIEludGVybWVkaWF0ZSBDQSAxMB4XDTE3MTAyODIyNTIxNFoXDTE4MTEwNzIyNTIxNFowUTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEcMBoGA1UEAwwTdGVzdHNpdGUuZm9vYmFyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKlPGmdiqKloSbUri9gvo2lyS0x2axSpeTfgIxI4Qnqhq8wMkih+SuO8+2rzIUd3S9nYqVww6yy+qHiJLXi3DKVYM/jgJnF+PlUoXxulD1abN8kX+TCKuHeAfTSIjM6WSgimGqW3hoB6bYHsaUFaAIg5FYbg5/IpbEMnD2yjU4M/nHVbxRwPqHGYdYfSqGDeHYjDb8GdA/+N0JDEoMVflTQKrDzq9R0lwOg+kICem1D+kww9ajyTu/7QdE8oOhAzuqFIVkCyZwpkrs576ng34mP04vpGcBs8YiKODydtFl2p5labXr5la0LVpLJL6rUkM3EhWOhQ0s+fCGtfrlmFRMCAwEAAaOCAQ8wggELMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNPsyKBhnCjL7pVBLRYK3jaoZ8PfMHIGA1UdIwRrMGmAFAf9rGqvLeJheBNJOHBKTG3Oz32PoU2kSzBJMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEPMA0GA1UECgwGRm9vYmFy
 MRQwEgYDVQQDDAtGb29iYXIgUm9vdIICQkIwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQA4sFKv4JDZ0+CVjcHL9bkTpk5I2L45xXk3d7GrhBpGveyy8vlb/g7P0qyAVo0UnB+eRTtwk6GTsJdzz4FBem+FDq8ZO/N51Rn4ZJQbDg24eGErK4rpbOo5OQgKKhTKjjBYwsAsIOkJ1TKQDQ3++Kqw3cWh/vlCWoxGPSMOeU/Iro34IWzSeEREMamYo5kIYq2ERCcVSoTcYB87cTYMU+ORyQSEx/OncDuAKm45ub92By5NpeFVMk+8ibifgzbNJHVnaZUVg8ScdM1A4Db6WAL0SUsYIawrnQ+TENs+6Ekls+wu8G5FAmbtOEV0WOafGvdcnELn5IPXlkvLbiRx5EChG+nF3XrLgn3dBQwP2cGrI/IPRm1XfaaBAkMSkf6St5TX3C40g1CGcNSVoKBYBB2Di+hPXwTHImGggR1JF34ljHCokMoPxmr7lP9pam0dhP/SSpIwxfsvDJylBgUEqTr3tsVDIDfMtJjudK7A7H1HMoqEiqlzRvJIEZ1koOxANFcQ1f9am2PPUNFvfK9IbLQlV8d4k1w6xBAeOVke79lJI9pTTCSVb+PTDniEL79JXjmjQUoKE4zo1u41d+wLu3dEGM27GI7BdLYt6bRsolZvrbey7Nn4c0t4ug4B4GTd1SLLVJns/IRLBrNr1anBJ7u9WFruBUEWwtdxAwSoXdtIIQ==",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509231134,
+		"exp": 1541631134,
+		"created": 1509346510,
+		"updated": 1509346510,
+		"recoveryLevel": "Recoverable+Purgeable"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myRecoverableCertificate/policy",
+		"key_props": {
+			"exportable": true,
+			"kty": "RSA",
+			"key_size": 2048,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pem-file"
+		},
+		"x509_props": {
+			"subject": "CN=testsite.foobar.com, O=Foobar, S=California, C=US",
+			"ekus": ["1.3.6.1.5.5.7.3.1"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 13,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "EmailContacts"
+			}
+		}],
+		"issuer": {
+			"name": "Unknown"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346510,
+			"updated": 1509346510
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedkey.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedkey.json b/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedkey.json
new file mode 100644
index 0000000..f9c45a0
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedkey.json
@@ -0,0 +1,15 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myRecoverableKey/274f6c69b94b41359a5932226425eb43",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "urhKlXbEGvYetOSH-GLytvSJ5djS0-5SKBtFOlJ2885PE0s_ZbnkRURDm2fImv_RV763HKSUQbEolQNs8I99N-3uCkrDStVZ6MPii9-0U6lrEkX7LrMRNYCfPAaSSZhSjCbsyqX9Y-N_A5Jz9uHNuXvpjQ9N7ojUK7fqqhnJKcJ6l6YsGOhGCD3uei4SL5GzbSAn2auIK51lj77UXjBZaudnNWTiKaCbTAmSmEe13DOJkg82_7Y1eWea3NJn4T2nY8WqRJCp4hzBsPBmFXjE1lgFWcSjm_afiSb0mCUP7v7tSOLR3xUBv9WgMO7p4_ce_--A9ZWP418Uqq0COcHAWQ",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335950,
+		"updated": 1509335950,
+		"recoveryLevel": "Recoverable+Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedsecret.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedsecret.json b/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedsecret.json
new file mode 100644
index 0000000..e36c591
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultrecoverdeletedsecret.json
@@ -0,0 +1,10 @@
+{
+	"contentType": "aNewSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/myRecoverableSecret/d7194ca6b0214d0ba382353109cd7e58",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335958,
+		"updated": 1509335958,
+		"recoveryLevel": "Recoverable+Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultrestorekey.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultrestorekey.json b/providers/azurecompute-arm/src/test/resources/vaultrestorekey.json
new file mode 100644
index 0000000..9ca672e
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultrestorekey.json
@@ -0,0 +1,15 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/1374543b3de34500a97d075991ee3893",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "tY2pzXPfU7NFYCWvZB1gJNAetkgJ7Qi75lTVOzVns9KjFFo6e_F9GSETZbAYl5oMwfLtdqQqT5fxzWDk0sYlz09HXvCCoYmbzobd3gJ6-WLAqhtCbBikr5HAIlCzy_UqKT--WhEw8AT_EJFBPIY9xNktqnaNZuRBmjmXinzT02qUmBZRsAdJmaYfG9IZSmToOkb54OytI5TreWN0JvceoQ3GSeFLMC5PUmXP6HmZliOzBBHWnXNq3H7a3qfWV3rxT2QpbrIuz18ZqOVp7o5868kN8knKytVcqEzmdiQUdabkqbrwuh-z_IEre9AqTfw6OjUUmLjs4lyKcpWLYFh8KJuML1ub-8u0VgNGwczUZ7aAld1iwGMsoMmQfMRDOnv-9pqtY-y40ZWpBGXpzFV-IvtKHnqQk_vWqowpE8xwx7yZ74z9XNgS9TmkVpcC-ONbEfNE1sez0Zf-RZ9eOm_7WSxxH6OJYtJI7wotBXYoy1bJaqo7mgHs1IUOFhSE-Evj",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335925,
+		"updated": 1509335925,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultrestorekeyrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultrestorekeyrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultrestorekeyrequestbody.json
new file mode 100644
index 0000000..4fd7296
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultrestorekeyrequestbody.json
@@ -0,0 +1,3 @@
+{
+  "value": "JkF6dXJlS2V5VmF1bHRLZXlCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLk9tXzl6QnhwTEw5a3NCVmNfR1JLUHR5akZ6R1JGV3BBWFVvVm91dmdNQXNEcFo2UUp1QUloRzZJWFB4ZHBOUDNlbEZFc19Ld3RpMlBhRXNEQWM4TEVQVHZvVzlSRmlROHZTY3JiWHlKcFNROXJSS1V5NlQ2SWo3UEpDV3Z6alp5ZlNYbklPNjRYMUtzRThFZWNKRDdudDRhN2tfZkpiSkw4a3paWnhXWFZLZnZwZEQ4c3dobFdOLVhMU0RsWDFORmlYQk5ILVRoU1BDbkNMOHc4RjlpV0o0LWFxeXozc0ozRDAzb3JzTHdKczFBTF9LN1c4eUlUNlprb3Azc20zeGlBb2pYZl92WDdOLXhQMUtKMU1tRlFnQVpaMmNpQWdJc2UzVDdoWFhsa0RaNGJqSXpYa2ZocGg1YlNuUEkzQU5kbDRUaXZkdVlxM0lCdlZrQ0hpWnY0US5pLXNxb3lQVVNHdlM2SVdUdld0MzBRLkR5N0U0cE9vanU3bzlMQ2dkcVYwd1c2MGxkOWRaU0tPN0wxWXhid1RMQzd3Z0piSmhlNno5b3VWN0FFMnBMLXFFMUhLclI3Nk9TVTJ3c1FBMFZuTDhlR1RnVFk0TWJOaklzSERraGFSUWN4bGRjOHpGWEVxNzNOWlhPWE5vaWJ2QVhUcm9oX3JnS0plNVFYWE1MSFJ6T2lVWEtqVEU3ak11Qm0zejNMRm1mQ1pQb0xWTnpNT09mdmFwQTh5XzNEUFk1OUdxOUFzWlZsakNpTWoxUlVrQV9QQTBwR
 EUwRU8xd25pV0dIb0t1R3h2N2hLb18wcFVMMWRPalZrNFA1ZmRWRmtGOENVemVvSDNja29xbUxMRmktQ0Nra2E5Q1JZcUE5ekZFckJsZGYzQTlIOVNuazdiUkNhb3c5Tk0tdXFBbkF1OWF6U3JBbnZZZ1NUT0VFUjFvX01Yc1Bqc1loTHp0NFZoTGx4RjlQNDROSU1ZTjEwWVZBYlVIQ0FaREZZejl5d3l2YWJPSXF1bjUzc25DZTBYVjBaWndabFNmSktJUkNsMk9zU29vVEt2OWx6U2kwOVFlUTRxb1NCMFdXSThobjFGd1pYV0RhdHNSNFFxOTB4RXB1bFVyWV9mOWI3cnNSem9jYmF6c0cxek50a0t5bjNVY29fR00yRjJDclFybi1uRVlXMkZRcVpkMlpHT2Nnbk52NFVyWmMxRjB5MUpTdXgxS29qdHBkZDgzR2JPd2s5dmVlSGs2NXlCdmtMTUYtcGtUWGdFS0lZeVN5ZUM4ekdndVZJOHhrX2VndXhQVlhCVVBMWk0xTHJ3U1VDc2JhaGR3WnRZZDN0R1dZVjZsSzhyT1UtQjhlWllvRTd0QUF2RkZxNEJ1R0U1TXRsdHFSRVpkcHlkOWFkTDRVRkttZ05YcTlvNWVqdWJuSmV2RWhRQmhVRXpRLUdCZ3RudVgtSlNTYjBDVllxV3p0NVU2dzJpcVNwZzBNMnQ4WG5OQXN5WTlvYXVBbVhuUGhMZ3lYYWpaSE1TS2FqNjIwOHdrZVA5ME1CSkt1anBfSFhJaEttSW1TOXVwLVY1NXBHRXdMQnhfYlU3TFpwYnhIcm14R3VOTE9pNXhJUGt3QkpTdXFZRlNSMWdaUU5lb1ZHUncwTW5TQW5HYnJ3eE92NFVjVlpUUjhkVTI1Y0NTOHpENjNwQ0ZUdm5CNllyN0pwcGhYekd3SFZYeTM2TkJPdWVuQ2NYQUR2QXNXS2M5a1RQeTlEalVFRFVQd0QydUpZQmhqaV9RR2
 taYjhfQnNwdURUbWM1Z0Y3TkdsV2NPRTBqZmFwUi1CSlJhUXJENFhxeU95NTRsTUxCZlNSTFBIN0w4VnMyUTVvc0FfVHlPYUoxa3B6dG5iLUhyNTdSQ1E4UWNsRnd5eVRfakpLaXFQRFEyWFlrZ2NjMmdkZlAtS29GNHFHSl9HRERMN3NVaThKeWRnOFNBdDBoRGdUOTh4Zk1URTlQc0twTU9FQUkwWF9KRWdsRTFwRmNxbVFkT2NOU2Z0VUxRaEFPVWd6Qlgxb1UtYTdiX2gtX0l5RVgyb0htZDdaNUJJRV80b0ZEYWVMaXh6ck9BWFdTTzVFZ3B4U0pYUXZ2ZEVZUV9mNHhPVFU3SExmUWkyNEthdGNUTWJJczlBVU1UY1NvVUhIY0RLWVhZbTl3SWR0RXR3MG5mbFp5YVJMYkx4cVJNTzd0X1ZLbnJ6OGVOZ2dJWENBVno4dmJmXzk1VWdVNGJUTzZDLU9BbHJqbUZNbVNzaEpwY0VhRjAwaGx3MnZud2s2QWlCRTlWUzdOYmJFb0JVZmtuaWJFeVJ5NHp2MmZtMWxhRkJnYmUzWV9QVEtHQTlVOGJlNGJsb2lkQmlVOGwxUS1qT3oxeFRNVFUybkpnYkJ6b0xzWEtadEw0d0ZDTnlNVFN3N1pyX3c0aDJjUzU4UHZsVWlYalRhcGpNdTJzYWJtdVJnVXROTjFlWVdxZjBRSEVFdGoydE5nd25TaHNBOHBRWkZKaXp6Rlc2VXpKRXdPbnN4S25tcjFEQktnZ1hsZFFtdmlxWHU5aE00MzdWcUJIeVA2SFZ1dUdiOEUtTlM5WlBPekJWMEFrcTM2QXVJcWNIMXUwTm1NT0laaXR1WVhFNXp3UGlVczJxSmMzQ1BHbVdZQ3d6THNibF9YRkx1dU5udXlIa2VGN1cwOGtxNjhBU2FBMTVic3BQMDU1a2UyMlRVbzNqVl9PeHRUY205OUdBcktGOE82elBjTlQyQ0xNdjkwZ3I
 1SEx0MVg1WjF4WFNTTVczZ0NRVEs0TmFtNUsyTzFUNXdoTWtPdnhYYmdkb3Jwc245amhGb25aaC00VG5RczJiUmMxVTM1Q1BudmRVM0s1dUVOTzNxZGVxV28zR20xeFRMaUdJSUhsNkdpX0dFdnlqWjdEQzRjeVhlYkI5enRiMklLQXZLVFhyQkF0aXd2bWF4U2FzNFRXVUc5Qy1RYUxLZnpRdDZwVm82NU8wLUZHQ3VLSU1Fc1I4bm9lM19jVVVJNzRiYl9sTVFWdnNyOW9KamJtS1RrWVBhREViQWZCd0FLdGw2dzdWUER4bGt6UmFZVTdPVENsdmFhMTVZQ1hJSzQ2V2hkd2QxMDNoR0x5UjltWlFSdmcyLWhfN0tESzNSVWRzcjNtTlBEYmpCcU16U202MldDNnZTclBVdENKTks2UG1ZWjhfT3A4bXp0U0xUbDBLWlN4dWt5U3d1Y2hfQXZLcGdqa3ktQmVfS0JXNTdka05TT2JlWmZKZElRT0xkSVcwZExqd1BWeTdENEhPS3FyWE1JRGdIdkRIR25zWFBZb0VRZG9wX05BOFZfTW03bWp1blhtZWoxVDI4cTN5VTcxRDEzVUxhdXNwVnNQVHBTcEVDX19mS2ZVSUF2dnI3RmszN19uSFU2QXowSndhNklSU19mTUZHamRuSDI5RXBUcTZGRDdaY1hPZzMxSGdNMHNtNUZlUnkxaHFqUUdIOTRwd2JpUktfWXhQaWVzZHd3cUh2TE1MZE02SU1CU0tuZlVfdTV0bkJISEV6NzZvQ0dHSEJmM0ZnTzFkX1hZZGhtVDZIR2FRUmZhV0s5QTVRNkpUbHBaWUpkOHc2eVlLSDVvNktFR01TWXRKbDFhM29KQ1A2Q0o5Wmh0R0ZWcHlQYlk3M1BkenozR2xvdFlqOE8zYzgtT3BxTm0xaEc2MU1IeEFnNkJYZHgxeFBqZ1RuTVRHbUtTYUplV0d6OWdHc2JDWm52RmlwSExj
 bHJQVHczVVR0NThOdmpkcGJtOGV1VVdxUDM3RVZzMFFoVHZkNzdmc1duZTgzZlpsYkh5SHF1Y3gwWEtBRmNlMURZNlM5Vlc1Ulp4akU4bHJHemxpVXplTGtsS19wVG91d191MXBVWktLV25jTzJ5RzlrZ3dOT0pkazZiWVlPb1dCRGhVNHU3TFVZR2tETENFaVJrSGRIeVBQbjJBeGNXTGhQYml5cUZ2RWRtNUNMMzMtaHN0OHFRNC1QYldfQV85QVFLZ2hoLXJfUUE2Wjlzd3F4QWJFeWI5R294TUFPenAzMlBoaVhpOHRxTC1qQ1ZqSEFnRTdqYm1jRVBVQVh4QlZFUXNLRGd0MFFRM2RscG0xSUd0OU9fMzNwWEIwUmt1bUxYT3pnWjYzYzNGNVp4ZlRyTGtZZ2MxM0p5dXdjb0Nxa0VxS2RxY0F1N3RFODUtSnkxZnpNTHQzLW9wXzBOWUdqallIZTQxU2drdDZjWjdnQXRFeHlDek5YRjBZcG10WFlralI2UTF0dnFIczhRWU9GaTF4RFZBb01pUjBMczFjRGFRcm5WMEhVZ05QeFJSdUlaYld3dWc1OE9QYnNvUDZYdHRhVGo5RU9yRlJEbUR3OVhiSjhxWEV6YkQ5ZXcxUjVsWGVPZWZZcjVnQVlIU1k0X2lTMXR2Qzg0QkY3RGtYUjVDVUxWZXNkTDBwckh6RFA5MHZfRC1oemJSUDVBNFJMM0RLNmFGN3Z6dFktRlRJSnM0bTNKZ3NyVUp4WkV4NjFMQjRIdGJKM2RTMUYxTjJ2YTJPc2VBSWZ0dkhESWFyV21tbjhBZy12T1JhTW1kWC1pT2YtajI2dWlYV3VvTkNPV085NnM3ZWsyUzRoQ1psN0lPNzVzQThkZGprbDNtaFhrSmEtaVBZZk9Nb3pKWDV5WEREX1E2WDg2YzNvZThLZEdVODJCbGluNXRycjRUdlVXcHBEYVZoYzJ6MENyclN4dko2ZjBIb2ZrY
 VVNTW9seVlpWW1rSEdpVWNzdmRNbDhMS1MxVEZoWVZiVW9xNUVyYWhKdW0yTjlqdk9DOGd0Ty0yempNR2NjbkEwUzhqbTR2SFVTRDV4MGtkWFotY0NrZ01HSWM2LW1LaHU1YVRpTTFWX01mN3dteTlrdHZITVRqVUM1d0kwU3JMU1F2RnNWZUZHamthLW1qajlsUEkzMFhORmRLajRTR3A5T2pmclRyYnhfeV91emZ5b3NudGVvRHF0RURmVmFSSFhVOF9pQncwWEdZUDBIaGloR3VlczdrdTZJVlE5aTVjVTBNSTRKR01vR0xJRUJKUG1NckxmamJMdkdVWTgzOWUwc0s5NFNBVHJseXo1YzYyeUloTC1xdEdIeTJBMmxxRUhnVnNvQjF0M0J5bDhwME1OSWJId1ZaUlkxcFBDdFBJVmctYWJCZ1ZVSGZneC1FSDVhVlR3QUZGekw5YjBhVUF5eEhnam1XVTlkYjJTMGJ2S3lKaTh2UXJuOWVnYkt4QWM4OEw1NDNsY1dUU1BIOUQ2Zmk5Z19hY0JUUXF5VUt6S3JxYmJUUGxMNWxQdGdfazFhd3ZLNmhNUDZfR0FLUi15a3JzTlcwVUZHaFI0WDNkTE5DNnFUdGdNaXFnYThKN1dVSjdMZUtaRTV1dzlzQlVRemJSdUxjUDFSMnEwQ29DSHdRYWJIRGhPUkdNMkFyMF9HbmIxZVotRXNNSXJHcWcxQkY5T2FMMTdZWE9RWXRhZXBhUEZGcXI5TS1FTHpEWEtYWlBFU1RVZGZqU1g0RllvMFk5cXNTUGdnTjlhajNnMWxfYVNoclA2SVdxZjJrRWoxTjNIMWVaZVUzQjZrWHBCUFV4VXV0LXk3MkU4Q3l6czJtUDgyQjRvNW9GOUVncldIZXF6WGw5XzQyVDFYNlB0Y0l2TGZ2d2hzd2FTVzlGamxVbC1hczVQbUtxSlRtUzl3bE9CdHZybDh1YWdIT1psMW1zZ3Ezd0hWTG
 VxMmRQclc4UmRjZXJwSTNySGVDZGVzZGJUb3pnS3FuTVhSSVNmZWtvQThLRTkzWFRDOXl1SkM2NmdMcTNJbkJnZ2NUMFp3X0pmWldvN2tmb2dyd2dMRTYwTm9uamxvMERGWFlCRDlKcDd6VGFDRGFGLUZRbHZ5MFdGb1YzRlh2dDllMDdJajBTN0c3THZ0OXVOaW1sbnYyazZOUUJxemlLT01zSjVRQ0pYOEFsbnMwNk9rZG9aVmIzV3Q5MjRQcFM4U0N5R3JnYWVPb24xTHhiMXp2QkIyZDQ5cGJ4a1ZMQnZjcnpFZkYzbExSOU9NdThGNERjS1VHcnBiMjUtNHFQQXVIZXJCcEVEWVBDY3p1RWJaQktZakZQSlozejhKNk45S2l6MktaQTQ0Z3ZKVE42QW5rcThnXzRJMWRBNzRtME9QMEcxd3dtd1pQQU10VXJqYmJ2TVNtbHVjb0FibXhSbDNPd2hFbGRoVFVwdi1iQ3d6ZHVqYnNPMVBsYWI5am1LQUZZaFloU0RZR0FoOTRRRVJ1dkd2VTJnQzlzRmYxTGFTM0Zaa24tRXIxWmgyallpc3BwMlFFd1FBdFlDcmMwaUptMlYwOF95RTVheEVJSnlpZzBhVnFZQ1FiN05GS2diX19LRF9uMi1yN2YwX2RIOFgxeUdJcXpiNzNGbHRCU05RRG1oUU1TdVlVYjlMbHFlREhuNVFtZ3JpQW02d3kwR25QMmE2X2k2TGZWejhMckUxVm94d253V1h4SDlSeDVuTUdpREFvRGxaVlIzVzd1cW1BZ0lMaGFvNldXb0xuYVZSU0pRUTFybTY2R2dCTENUa1QwcE9kS0Vpelc4TlpwXy00Q0tWSHB4ZUpRVFBodXo1cXBmalM4Xzh2M3Nkb0lHNko5RkxwMUludnlmTnFIM0djZ0sxbWZZbWZPUW42cXUybU4yckpiMDg2Y3U2cU5VZnpRcXJqQVpwckdpQ2pCU3Z5T3JwdnZCdGQ
 xVHBQTXFMZEZxbmtGeC1GSTdYWDJocUtoRGFyX2R6QldTWXFPSE9adG50d0hocGNWVExLeXdqQTl0MmxGWTFuNFJtR1l1SHlKdlhVeFZvc05BU19nd1EzM015U25lTk40am5aTWFCNFMyM2lNV0Y0UktSaUlSXzAtTV9Nc1kwbDZmbUxOekZFbFJrUE1LcWFsOHFmbUo3VDkxU2IxdkJFQl9WX052dGxlVzd2VnlaSXBpbV8xUHJ3MC1oMXBMcXVXVDFodll4SWNtbHllSldIUy1NQURnaVdWbnlFOVJBOHpXWFI3TWR2V2s0U2MtaGV0U29LUk1YbmxCM0F2cFc1bEVYN2g0aTJEcVNfLTI0RGdMS09iNWlfVTMwZHNxcWJCdTFMUkNiX2p5dHJhUUlwMEJOczhEMFFXQmFzYlZDbTdNTkM2WlpESlZLMFlBQWkyZnktM3RPSjA3dFF2OFRQelNiaHZETDh6UHdqTmVCSURMWjlvTmdlZFNJYk5sRWdZS3RKZHh6emJEOVp2UmNKSzNYUTBYVHY5bGc0V19HVGJYSUx1bF9fa1owcGZ2RjV6N1Rlc21obV9hRFY2MzNYTEJzWG1wNHJqWUdKUE4tdWxkNW11YkZoWnFWRjJaRHpOTFI5czNKSXNkeHZubnl5QVpiR3dfVjI3eFVKQ19WbktXTzN4bVhGdW5lV0dVSkNFZFpWR2FyZkQ3MHgzc1JIeHJzM29jSEQyQ1JhcnFpM19SOHlndWM4NzlveEJuU29FbXJJTkd5dWkxbXkyRHdnOFYyaGNrcVZKSjhBakxONjNJaGZBR0FTNEU4QWpQODdBczlPX0ZUcnVESWhtOHBEOGpFbUpQTFlTV0hNbkl5WDV6VXEwa3p0NE1QMkNpdzF0Z1pXMGtvRGtHVFhMX1hTV2JCX2ZmVG1lWDN0cDVYU0M0YUh3X3BzUV9oNE44Y2NkS3ItWE1jYXo2aTJ0U3k0Ymh6U2lwWXdqcGx6
 S3hTYU5wdVpmcURWUHlEVXpfSE9OSHVvV0ZVSEw5alhpTEVuR2JFYW5HZ2VlRXN0cEFDcGMyS2JNN0NhSWpDdUtubmpxVy1EZWoxWGNMY3Y5LU1EVFVraGZwTGhMV3ZOWUZKV19UZ1F3eHhEbllTdEwxYTNZVGRfMjJuQ3dJUm5SekY1Y19YTU5KM0JleDh5c3F6ZTJyN1Q4b1hUcFhvY2ozQ2sxaGgzdEh0dHhCOEIyYUh0UlRUanIzRFltamc1RllTOENLNl9mOThkX1QyS2FHYkViZFd4eDhyTDdEZ3JKTGdqeC1Ba05ma0pCR3prY1JaRnBFX1VHVnNhMW1nZlNwOC00QTVaM1Bfdzhuc1RsdzhsaUZ1MUpxcTR2S2ZyQmNUWTI2UEptdEdkZWQ5N21KQnN1aFhyWW5uZW5qamg5bEZYZ3g1TmYyOFFKNHdoV2w5eTFnSS0wNHF5ZEdfem5CbVJ0MkY1Q0FNbXdMQ0hpZV83LUNZVzNDTkJNWlRPcV80VUpaWndxcTUzNkJYdWtmNHZNZ2ZJSENnT1JfczcxUTRleGRmWWZ2ZTU5ZEp3WEc4ZHRMa2xxdXM5SlM4dlgzSnFHdHpLOUhWYjhlVkdmVWpNNXVnU3J6RWJCRFQ2SE1vLWhqVFpNbzBrbjAtY2hTV0hpVV81X2xRanlmdDZMYkxWZFZEbkxlLXFhczlhUi05YXZDZGk2Wmt1SmxuNVJPbXI1XzVpam54Y0haam1ZU3ZXdU9xX0tZT1JxLTMwRXhMdldTM29YbjNQc0lzOTNWTGktU1hHSEpXamJ6YXVlWDFySWlsMGZFLVY4ektpMU5aLXVVWjJJQnVHdjllVWtYeXJyVl9EWmZxUE94RlpMT1NqYWZuWWxSNEt0dE9WMHJVeURaUExob2h6bkZHdG9jRjAwV29xOVB6b1dCT3VJNjNjeE1YNVZGSnpmYTdTdTZ4Vk1FRExLVEZZRzh0bGVDdUpLSHpTV2hpR
 0FaY1djU3NvLU1VNnQ3LUJMVEQwWHEzVklNZU5qQzdQcmU2TjU3YkZheWpqaVVTdTBrOEh1SjBhWGZnNDlOZ2M5S1AxWHp5bjA3M3p4NWd4dEVQYTFhSFVFVEROMkVWakc2SDZMdE50VnNqNGVWRVVzTzZ1VTZTWk1hOHhfX1ZPUEM0WEgzVGRYVFMwTl9KZUw4OENyWmZSMmt3VDh2RWdSUHNVLUc1MU9fQnBXcnVzRndXMElRWXBZTnUwLVVmUjB3VDBlUUFsdHpCbDQ5VkZ6SkVMeHhsTXlKc3ByVUNmMHp1cUNUaVg4d0VUNEc5YWtZZzZKWlV5SVptSUk2RmNycy1sWTBPWlVYSW5IS3pqY0w0WnRVbHhZTTFFUENXVXBibWw4SXN2SlpBN1FELUtWOEJVeFdTXzdUOHRLOWtfbUpGT2pTdVhZUTNjTFVDVktyVkRwU3RZZ3JUREdiUlR5bk9EX3QxU2dwbHczMFFUS01mTXNyZkJweWQ1VEpkSGg2eVdSNFFwUlJnWnVaWGR6STRfWVFUMXIzT3NnWDBWM1NaMUZQN2hSNF9NQnFQSkVTenpZc2pQWVdkTzdzaE55Tl8yaXJDLVNxbG81UkJaNVZvZ2VNZDNaVmhhZEQzcnF0UjJmVHZNZm1aYUtuN0piT2FoUUFJYjY3a3NVUHZHQU9rRC1kNS1VRDV0N2JTU0xkd2xXel9aUjFLakxES0xaTE1WSEtTRk40ejhOUGhIcjc3d21GSDZ0ZEw4X0dEaWh3YnVGTEdmbHl3VmRuWi1uenFQcXNhaTU5MGU4SnBfOVQ3dGtMczZQUHBwclFGSGFVRnFtSTAyYUNvaFJDMGRhTEZDY0JrTXA4blkxeFRlamJyZm1yLVpNcmNLMGQtUmM3bWtpVTY3bUpBRTJSQ3BFZ0Y1dUNiT0xoTlNxMXh5SEZHa0llUE92RkFYMWFGQjNwa1VCN0Q4OWxoUkF1ZGd1bW9JWkRCd0dzdV
 BSRGZPUlR1T3hZakZhaWozZzVyenZHdEVlanB0SVJDbVhNZXhhMVFnYlpQOWJabWh4a0k1SXdHNHJDS0pvZ3NBWnFhYmZUSmUwY18xQTdLYjIzNkEzSHRSMFhJMWRIbVotM2c4cXBwVG9Eb0JPYTZ2RW5vU3NkOFNsX1g1Z0JlZFdmWXZwYzd3X1pfdXJGUXlac3BBbDJrS0N5N2w2U19BUkZqR0dvSnVNWVFicElIbjZGbkJCcjhsTGlyMExZUDVTQlJfM3NaSHNyb3UwamxyLWNMejRZSlpUYzBZcnBGNnRETHA3NFJ0bWM3cDk5aHhNRVE1UG40S1VGNlZJcWt2R2JocjJjdlgzb1d1bk52S0tOcmdXaDYtYzBONFNDTjBkMklveVZfbktzNG4wR2tQcmtDS1ExSGJMbUg1N2ZSTGdqSzFFaEtydGp1SUx3dXFRM0pCeUhISlpOdEdsbV9nZkt5bzZsQ2IyQ2xacElxR2Y0X3ozcVVyMmZVQXhMdWxtRFRMZzh6Z0RlTEViVVdUTXYxTWRUc0pSb0NTZGJiS1NvQ3k2UE1YZUwycllBR2tHT1VYMnVPaDVnRlVkZkdzRVg3enVHamtadnhra2J3VHpTSFlibkMxNHlaRXZsbS1qRkhWS0JjUFdJemJKSnFoUl8zdFVNZ2xRc0xrZzQ2WHFlLUREblVTYUMxbzZ0NnNXOE5CbGR3aGdnOU9JUXhlT2NacVhTanY4TW84SkdrUWlBMnp2WUVWNmJpa09MS3BTbXQyRnNWVE5BSVBQNm1nazE2NG5JaVZXSTN3dlljZ0pCb1ZxeEpCdXJVY2NVNksyVmc1MkU1cnVQc09rNVZwTlphR0ZCb3NYNnU1bjhBM2RfR0laV3VhTUxsZnZnVkdxN21nbFowaFBlM3F3WHI5QndCNm5VV1lJdU1ycFVxUDFQanBmck9OZ3BSOHprQlJ1T0R5R040XzJzRHloMDFWUWRxOGF6OUY4a1g
 wRU9RaHZ2ZUJKcmtqTTRENGJ5dFVSeVR5RHJRX0hYTExFYUw4UjBPMm9MOGNPeUtSa3F6b1ZGc0NjUC1jMzB1UHFnV2E0T0NzYXhnYUxkTUJveTFKdkFENVF3SWp5dHd2QzR6THNpSXljd3JqeEZaZnVlUnBNRVZLOTR4WVRvNkhlWGQxX0VweFBYMkhiMFFBb0VVVS1zWkFCQVBFZG1OQi1XMEtoUnNpMmJSZi12b3JVZzhJbS1remxCZmxaQ19zUU1RckcwZjR0VE9qTlR0QnlHWUt2dXRqQWJuTjhMQlFSN2JmT0tzM1BvQktQc3pTWDNWMUhtTTUyNnd0X1ZmcDk4d1lFZUNOc3RwcTl1YTRKUlcxRWNGTTRJNnY2aXBXQ3Q5b1V3dVVsTkhUOHNhR2NaUVptRzdZTTRUTDNYVVJITHdaZnNzeUFma2dHejZ0Qm84RWp2MlhNVlZta0ZlRGQ4REl5QXNSUEVHRzZFYUowXzdYajRxNWttR2lUOEJBNE9jMm5pS0M3eVJCVE5CNnhMSldPaXRHcHM0a3ZSX3JfVTl2VUQwMTZ6U19PVlgzLTBqLWNwNzYyWjRicHhNeUswbmNzbFc0M1diUFhRajh2N1libjR1bmtPOU5lc0ZkMC1YWlRvU0J0ZlBTeDk2dGVMM0t4YXEwOFBzV1U5NzhDTVdrUlZHXzZnZWtWWGI0SDdrQUo1M0RoTlpFTW1yM0hSM0lsampIM1YySDRvVGlmeW82ZWdiMHZQX1VEQVNFZGVCUkNYT3JuLUJhTUxzaWhGZE8wVjFxNmNwS2FLVlBkTHgtOTRlelRSRWdtcEpjYjNvSXZoa21RRzJhZ3pZejFEMy1lX0FRU3ladE03TUx6NmY3Ni1HYkkyMy05S0JtVnBVQjJOTnU1aS1xZl8tN3ExQ3JVTFNxNE04aGJsN2E2OUt1UW1RZ0xtQUJZVzlwX3J0ZGFGUzJTRTNGZ0ZPWk1GYnB3MEo3SzRD
 bXd1VURXb0tyejlGZXAwRDktdkR5NEtpQmdnZWlZTHY3ZFJPVEMwblV2WWlMX00ydXlHbXZtMGJDc29ZMXB3VFNjcDl0aUJZVTZuYW9Ub21ua09qWXZ3T0ZHN3h5R1ZSMF9yT2o3aHpWbzlfbDY3ZE4xaHRFcXZud1BTRno0dXNEcE5UOEFnR3VDVXlMVW5NVVc3ZjNDUFVlOGlqWk5PTm14NEpBT2ZZY1E4dXh3SVRPaExqSEU2alFJOVVFSGNnRmJsMUtrVFJJSDFveGhNSDI3ajJTaUNkS2VrUWVZX3J6cllHTWNmTWF0NTFrdXVzT2pMWDZvbnZWVzBEc1ZXS1FnaUt1OVI1QW8tQkFUTXhxMGJUMWl1X2FaZGNLNkxlZHVwTnVqRXJzSHpNTzF3eGRRcWtMcDVvN2M0ajlQLU5xTTJWWGpnQm93OWJrUmxYdWd2a3Z4WV9tNU1fMm1oeWF1amdtdHg1bXNPR0pIUl9OckY1djZiUGk2aWZkU2o5emhuWGV4MDFEb1B1VmRHeXJkaGN3N25FRjZrczV2N1pOT2ZvRFZuemxCbUpsQVA1eHFjX21SQjI0ZmdWQW5JTzNXMTFSX0V2ZF9UbWxXd085a1cyemFxbi1OeURLUGxtOWp0aXdSSExYRmR1Snc2d2MtdVhJYXdxZFNkZVJkSUV2TWhYX2ExSFhNTG9RYk5VZnpHYk0xSi1aUVBNNWRfbkJPMGN3S0xyRUhlX1ZiT1R4UmZuUU1UVEw1ZnlrcmJGZkgwWUdPYl90aVlqWGJ3QWRsUmtFcFVuSmRWemtCY0tPZUxHMF9ydkRXdmJKX3E4QTFkeFpONm9PSlFvOHRjV0IyVTIyMFNmWjNoNmhUdC12dVBPelltdG1WMDZQb1ZSQTQ5c0JxRWJhNUVKU0pRSGRkVEQyZERDVnRBSV9XNFFFNF9QRGFhQ2kyZFVsN09pZnZJS09TMnJVeVRRckJ2eG1LSnN2Rm9yM2hjO
 EQ1a3UxMEFQcnlUQmdtOFFTbXJma0xlZGNHUEk0YzlxLW53QnRPM1l0cXExTmhnaHU1WFBxc3h4RXZiMkpOekdXME1DeFJGSGI1bzZLbFg4cExjLWZzUFV1V05lWlV0MnQ3R3ppd1dDc2QtTno2VW1Hb1JicU52SmNKeE56VjUtdnotNWJpUzN5UWkwVlJSczl4elhmN05jYURrQlR1N090Q28wVDFUYWQ3bVE1WTVVREN6UXJGVkR4YS05Q1JubDczLUFvZXp2SUtSWUtYWDZLam5RUjZpNmRJOWNBN2pKRFFFT0thMGY3UHFXcU5tYktMalhSY25ocXZJNW56UU5pYUh5bkUzTXpMb3VOMzEwQ2wtM2d5VFloci1ya3c1UE15VHY4enZpYWtMbER5Vm93dTF4OHMzcmdlSDFUbFp5U0JRUDRIcDBBWFYxelZQQUhNbFU0R1dZdXNOSk0tWk1uSGxBdW5RSVd1WF9pRmxVbmFqMWhyR3pfUFJ3dzRVajF5aVZOLW1UR2laSUdadXRDQXRYeGZUd1hwOE5Lc1pwNThYU2QyeTNfTE4xc2QwZDMydEI3Z20xRE1ybHpqQmFybkdBQ3pEQVo4LXpwUDhhVzh5cXFDQ25GdHdiU1hGOUtiNkVEZzRPckNqZmlpTlZXQTZHSFE2TDlPTnZvemozOXpvaU1nOTdDc2dLY2tZTnUxTXo3NWhtSG14NjdudzZLdFBrcnBBRTFmVDBzeDlYdUtWczhUWEdlUFdvVHREMGRDOUVTRjRsV3RPMnpoV3NsTzhHaWVkQnhjTDVUOTNmWGFwR05sbG12d2lIVWx3S29TSFVnS2JwVWp6MU9WenBGM0l0TGNzVnpoRXlRQXJKakp4THoyNkFGSzVaTE5NUGc0Z2V4ZlRtMmI3YTNkX0g0LUhvMlY0THE4WDVMN1ZBZzh2b1dXY0tfZnBfbERHLWp2STduQzFOYzd0UmkyWnkwU05zY2FKbVQyeE
 1pZ1ZZM1ZYaGJyRG9iQXJvbjZBZkJlZjRibE9PMHNVTFdWMVRobzVMMmc3TEs1alc1am41bjRYSDkzNEYydTNPazhwT211T25HOWwzZDVySy1zWVpYQ3g3NENqVDJmN3BjZ3FiQ2F3cExBMmx2T1VqOVFublRiaVpkQzc5LXF4YVpZWXRUOVc4dEFVQllpQllJTUY3UFl4ME1KaFVWUFBWM1NMR0syTkJURTF2bWM2c1RFZ2l3ODltcTRPakJLZ3hUTTNNa2paRGJzMm1OVktqUjhHODBYYjlKX3VMOWYzRzI1c1RBemdVcDB5ZEItaHR3OGFwRDlmRkhSZzhYSEdDZTVmSHNGTDNpejJvb0d0RTRkeHZSQ1ZDLW5lY3FtRG1KMS1jMEZkVDE4djRWX2ZZcGc3QXpNQzNYT2xQLXNiOE5KS2d6RUZOZldseUtHWXhaRkt6R0RhZnBBYjdEYUloWVpmU2Faa3Ftbnh4eHpDbGVrSTk2T2ZnZElsbkgtUEd6dW5Nb2FvcElxN0lPek1rZGVPazBpUFF6VmtDUGxxc0M0LXZ1enFJODZvLTQxbHZGVmhpU20yeEozRHJWQzBXbGpVUjlPVVZ0R2JoNEF3Zm8tb3hMdVFLMW1Ma2pqLW1yNkQ3d3ktNDBrcmdOV1ZLeEpET0Z4UEhnOVBQc09xQlBvbWpwUXpkNUowYWg1RmdvNk9uODJlVmVRZzdHRzkwUjZZbVBSR2dFVFVQUWl0XzRHZGE0U0xnTVZDSktZdGZvZHY2WWQwZ2pSZzJEVW5qZUtOVUp3c1RjSEhyYWs3MXNRaVNfVmRtekZsSm1CNjVhYjFlSE9VQ2I4SmtYalF1XzR3UmZXdnhuc1VmcExWd1VMMGNmNi1YWmp1RVpIUF9PaGlGWDlzWldTSjBLS1RfVFI4RzFTbWpFcTZUbXhKa1E1RHRnV014OWNwTjJSRlNwcWFyU1V0STJtUWNIM191U0tERjNuY1lhWDl
 0Vk55ZGpEOFloUkdwWHVQdk4wWHZyejBKTklHLVBWeVlqUUJPdXNvOF9GeV9yX0ctSmVhdVNxMFRpVUhEUVM0Yl96ZDlfQWxMM2wySzZJdzAyQkVhWEhwb2Jpd3pFeEdFeU4weWFVMDRVNjliUEl5TGxIcy1sVVpnMTl5Z3hOR2pzdkxDaktqQ2gzdlhxdDRsMnlZZmFnY0RHSzdWcXpUYzhDWG5wZ1p1bnR3LnRTWm9BN2tNdGItRVJtRWs3d2MyT2c"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultrestoresecret.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultrestoresecret.json b/providers/azurecompute-arm/src/test/resources/vaultrestoresecret.json
new file mode 100644
index 0000000..bff4c9d
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultrestoresecret.json
@@ -0,0 +1,10 @@
+{
+	"contentType": "aNewSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/8c418537cbc948539ea2ac12c0bfcfb4",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335944,
+		"updated": 1509335944,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultrestoresecretrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultrestoresecretrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultrestoresecretrequestbody.json
new file mode 100644
index 0000000..d57bc99
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultrestoresecretrequestbody.json
@@ -0,0 +1,3 @@
+{
+    "value": "KUF6dXJlS2V5VmF1bHRTZWNyZXRCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLlFLelA2anZVR0Y5X1M3UU8tRkZDTHIyNGp0RXJuandkQThNZUtsSGE1MmhvS01rNjdiOHQyckZhNTJ6dGR2and1d1I3VWh4RldRLUpuOHk3YlJiNlYtcTlUYl9iV3E5clplUlhpUy1jdUhPak9ONHB1bHd1cVVmQkJOU2V3NlJGUXpOUzRrQks3RmxQSGZpQVRRaUUtLTc1cnZIM0dMTEdDd25KTkxIUDNTR0FtWlR1dXo0bTN6X1owR3RsZUU5XzFZT3pqczU1UmJFNEdOTC0tWDhDWnlRWmVFNGdGRXZ2WmFrYkRXTk5hOWd6SnBUNlNOTm5tcGtpMFZocGxaNGdzWmNmR29xQktZNF8wTS1WTmpIbkZ5QUlySXdsSTNjZkIzWUVCbHJ3X1A1QXhQVFFvNDJNa1pETmNKYjFwaGh0c1phaTNLcWRxT0E0ZEVWNVZWQ1VNZy5fTkN5eTNJSS1VV1VtWDB4UXhTVnNRLjJkbEFpUEpSa3NlenNVTEZocTE3ZmdCWm11XzBBaU5GUWkyTU8zMnlVanpEMjMxQlY0bHhwU21ZMmI1bGdsTXlYQzNtYy1PT2VmcVNseXdqMlcwTllOYzJKOUg4MzFHc0VCdXZ1SS1BWEQ3dzdocGRNTG5VaG5DQ0RUQTJYY0ZTZ2lXTWMzMFFISHUzRi1KcDh2VGU1QUk5R1ljelEzSFVPRjJOREpjRERoLU9CNFFJRlZWMS0zWEJkeS1uOWR5MjlSY0FwNEo4WHRPMjZxN2dJa3BDT1J
 xMTVuOXZHd3ViVlZhdGhfMlZwM3p1ZEJPX3k5SlFTVVYxMW1jZFVIQXNCVGxFMU5xYkZaU0lfX093NTl6ZktGRTVTMnZrYWl6a1RFbXFVQi1EcTVnMnMxQ05PcUdUNk1wQWNiSEtUNTNSajNZN2RlOFlBckZIMlNSZF9udUV6Q09PMnAxeFpFUjh4c2RIRjlDM1Nnc3ZRQzIzX3BfeDBIR1RfbWY5V3B4amZOWF9Bd1E5NWNLZ0JOdU1ENEZ1TTdWTmpKc1JaSGtvM2tNTlJ5N3BybkhhaVd5aHRiVV9ic0w3X3FRa1JGNEl3eGFzUlh6M3RtZzYyT2tCWl82MEMyRE11Q0pIZWtqSnI5SGJDeGp6Z1lGMjVmRDhDTk00YmNaRV9ma1Z4Y2lVVklWU2lvemREX3owTFBMY09paVp6dTNIWGIxekplZkJsVXduc1NBT0RZa2lWbjJPMjFOMHpkRGwwMjNPSnJTdWQycWo1UkEtVTlsVWRxU0w1QUltN1ZaMTFSVzh5clpkWXc4NFJTejVySldRSm1sVW54RzJHb3lMMTFaQkJacXY5bEJ5Wnd3SDN6ZGNDZWFRQWM0LVZJWjQ5NzBfTC1tT2paNUFwdXI4UERHVDIydkNKdEw1cVVaNGJabThBeXQ0NDFEX2o2cG16NzRUWWlIU210ZnlJcnNvRTMzbG9QM0xGdTFKMklXLXJTdk9HUElveEx1ai1ZMkNKMENYTk1lR0UyQVNhOEY5RmY3enhVLVRkbVZneWpfYi1EY05XUmVJZUMyTEF4OV9EWDY0QlRJV0pNSFc3a2plbjRkem9kajMzbjM1aFU0UUVmRVM0a2pmUUtMVENrYnRlWXliVUlQWmhaa3BDRzRpTVBQSVpTRVdqU2RMckl6NlRYN3FJZHFHcE1UYk9zeld3eWc2dzI1WTd4aDFvelY2RjJEOFpKR3FiZjhQZTVDRWtIcE5LeC1kNExUTzNsOWZlZVd6RFRwTzRn
 TWpBZ1RNdHBqdXRqT2xhSEYyN1JLaVNGWU82eFNQY0ZVb3JGMlZKRERlQUxZSk9Pb0JOMkhpalJ1Y0R5bWR3NUtzNHBZTmZvV3dCeHVnbjBPenJoNVFIS2Q3dWpoUll1XzhkLWd2RVNKQzNJY3JZWFI1aFhxaUp5WGVNMGtULWlnRUFQRFVmSXE0cjJiRW5iZ0RhdUZrN2syekZzXzZzeGZ4Ty1TNEp0alp2UkJia0lnZm1WdVB5OXZTQy02QUl0aEctMW5OUE9PNG1oak9ON2EzVUdzQVpvREg0T1RFczA3ajJMQ092VGdqX05PN1pJcEt6LWhyU0daSXdCdjlRdHJ5NjY4US1kTUpRZzAzRi1UXzZlX1htc1BWRWt1RWdaSzdnS092STNzdjk4Y0VVODFiVEZfNjQ3cmE5bjN6NHdnbmZwVE1lWEhMQ1JWeGpKbHJURmxJcW9wbkdZeHlQdm5iVXBzb3A2NktHbVAtTEpTeERjNlJJckpuQ2drbjN1OGN0c25NZWxuWHZSeGZFdFRsNnkyendUV3ZSdnVEcVR1UFphQXdNVmllbTdaaXZqNTdMYjNHT3RUcjBxQXNrMC15dHN2TkpmY19tYTEydVlUWll1b2RCM2ZoVFBITjFaclFoQzdiWDVHdXFDUFFDQXFuenJjT0lESDIweTFlZHAxam1ZdTFyZThPaG9yMDRiVWhLa2stcUVVdEVsZTFqYzFTckNuWkEyMlRZMFNVYkxkVm1hb2dyaUJfckpackVaM0tneGFaSjNnZ3FQd2NhSW0wNUVoMDQwYUpUa20xOWdzRzVCNEExQ2dDWHRMOGhUMFl4TmNneW9tT0dnRzd2Q2FzdW43WGhtdjJZLWROWVNrZzRZbzlfdkktWWlmZEp2MnhJVWY3eGFvS1RRRzY4NkNzaE0zTkVubFRWb1FjaWxjaXllaHc3RkpiMnYyTDFNV0tlamRWM2dPNjIyVjZ3QXV4MW9GdXJhdWZOR
 zh2cnkyS2NwczFOUzBWeFJObU9mNDFkbFRhSkljUmFJM2tSbUg5UkpTakJZcnA1Y1ZzZWh5WGVaQXpnU2JzUlg0eGp6LURJSGVPa1dRS05HMlZvTnloZ3BZS05FVnlNN2dkdFBWTUo3TmlkVE9PM3BaYTBMeV9GaUhHLXc0dkUwTTR0X1ZpOFhvRzBFbWhJcjBWdmRvN0RGUXVUbmdoblRGVnpreEtyRlJSZzRMWkhCNzR2Z1BycTVTNGxTV2hlZGRfekRad2JVeUxJY1NXWmk3QzlpWDctczNHeGp2UjNGekxJT3NuSXUxVHpaQ3B4a0d4ZGkzU1VyS1c0NGlTaDM3eGNmaEpsNDVDcTQ5N1pQQmo1eVA0UmYwazVTS3djM1JvOUJoUXN0aUdzVk5qMlIzcmpHTHZfOEwtUHNxOG1IYTZKZHVvaEtRbEVQT1hYNzZ5aDdab05KUUZhemRNRWV3eVJNOGQ3eUZIcFc0M3RTZTA4Mi1BUmRjcW55OXFZRmJLMFJfV3dNTDlOQkFpNWxjQldUSms2ZHJXN1RPRmJ2eDFyZ0p5cUcza2w4TEdwRExheFNfaFhXZVRxSy1YS3pVRk9zNjA4WEp6U2NhVE1xay1QTVZIdkN5c3Vjci1mOFN3SF9wdks0bTNQYWprcGVOMjl3dmVZdUp1X1ZKZHlPNE9yY043cnRYVXR3VWNSblBzNUNXYWF0N1RfUWhnZ1VTdHBZczBJTlVuNXU2Rm5oNGVsUUxTTEhvdWZDdE9RekpDV0VVd3N2TWdkdkc2cEUzU2FZU244OFd6YzdMbGctZEVMeERLQXE1dmI1bXFleXAyem9hZFhJa20wWks5amlwdnBZdmQyRlFnNE50NF9nOUo3WTRoeVp3TjFWdXlqQ2YyUkFpMzJXZlNid1B4ZmdVdjhVVkktcUlKWjc5TjNQOTFnWnB4X2xxdF9aNFB0bzIwTTZqamw0MGkwUXRwMUdaRU5hbHoxN00zbF
 RBUl81WkY5Ql81dTIwN1FGbGh3UDYzbFRNMF8td1lCOVBzV2VtdGJUTEZYZmJFU0t6VGVzckVzQWwzQkVDMFotSndhMno3cEc3VHhvQWhON21hWDdKajVjbWtzdmJjVk05MENSNTVwbmtwOUM0Tm1BRWM2amw1dXRBSGlGOEdaV1A1V2lGVFFwVTBpYktXLUVycEMyblVvRVBmbFRPbVowM2lzaFNLbnZTSUFUQjBMSW95S1lhYm9tcU5NWkZhWDV5OWVjTGtFdmlmYS04dW8zRzNYSWFhQWk3TE5YRXpqQm9iZWlVSzBFeGJxaGd0VzNvbE85V1o1MGxqOWw5UXpGV3FWOGRiUThOeTdkdzRnT2wzNl93ZVNrbHJ3b19VVDA0Sm9Oc0IzOWFrUnJaWkdzaXJuamR1T0F4RWZaaXRLdHdTdkpZSzRtV0huSk5uRENMVlo2cVpzVG50NThjVjQ2cFY3T1FxckNpVnlQREU3Y1N0RW5neXhEbzRZdlpibDNrNndkaGxYOXAwZXNaOUdXbHNxcXlGVUJCc19QbVN2UUd6djZ3bDlWSnk4WnNKYmpIdlkwclZOUFJnN2FYTjlNOElsVWpia3B6RmdqY0VPZVVrZ1M5UFp5RURLYUw5U2NjeFJFbjI1OUR3MDFJZFJPS2U5Mnp3U1hSQUJlbVhBcVRaSGZPd1Z2VDBUS2JnWkwxcE5vb242NWRMR0hKZ2dYWmt6SjVHT3dvbFRkYkEwczVkaXRQZllxU3ZwQmpmVHpfQTZhTWl3bmFnamlET0QzT2doeTQxc1Q2UDdTWTFxanpfWkxjZ1puc1djWDlkOWc4TkpzZ1had184d2dUY3hRdW1TM3oxVTYxX2dlbndBNzNPaEs5MWl5YW90Z2ZySWNzOWxodm1taEcwRC1KX3lkQUxfdXNROWc0dHRlN1ptN0hMZDZOb1pCYnJFTkZ0ODRmejdJbjJxMXItM1lsYk9kMm1xRXIxZUdZMmt
 CTlh1eFc0XzlVZVFOZER5UHZPRFR0Ni1mR3FuMF9sd2dYOXJldUxsRzY1UjFKY29yMnczWmZBLWU3SEN3Y2tCTTBEcmhjZmwxdmhtcVY4WXpMcHBxUUhPa1F2YUpMNHE2ZG1ZS0thZmhGbXcxVk1qSnp5UWswUVNzazFWUGdzUmpta3l0YmpjZjRoenJNdVRMU0VQTGZVWGVPOEYzbEdLNE03bWlhblRPQ0xXSmRNWnc5dFlKSHVTQ0g3SjhZOUVwNS1XWTRBeUZlaFJfaDVSNHVYdlBPUmUzSzZQcWJibHlaMEJuclpCcDZnTUNvNVcwZkd5ZEdiQ1N6dzUzVndsY3FEWnJlb0p0Rk5pZFNzdTBtLUFub1g0SWxsSFFnYVB4SnlLYWRPSWpvalNKMnZTTTZCYXRkci1pR3VTbDJSZmswLXkyX3FFeDZRakNOQWFXaWNvM2RsS3VIY0h6TU13YzVXT1J4bzdweXdWYmtOUmpoOUVPZlkxSW51Tk11SjdfYWt2T0V5MGpMVXlCc04zR0hrTzlEUExFLTk2bVlIMWd6R19IbGQ5aVRpOWcxZTB5WjdBVkNEQzBoaVRZMXB5V0pVanpGVE91clJaYW5qOWl5MWdjcFdpeFVPN2xiWjl2aHFhdHg0VUh4VFRneS1IbUcydmRTYjhJbGl2bHNqLXVpM3dxUjBYeVNXRDFVYmVJUFVIZk15bTR2bXkzdkIyWEJKMEJnTF80bkx2VWQ2MEpFdXI1Z0ZOSUUtR0RSY0JwSkdPZXN4b1lyQktYU1I2QUd1UG84b2ptemFudUFIaF83OTI5OWg2aDdtN3JRZ0NxYzJ0Wjg1dU9YVHNzZzRYSW1kVjdCN3ZrcHRlUmt5WjZEQ1RFYW5GRmNvWEJzSThYMVFZeFFDRzgtdzltYlppTHNiRGN6bVV5Z3RiRkNQUXludjByclNiRzFUUWtmZnk4UGVfT0tRYkxSdWJNNG55dmZxWG81X21FcXA0
 T1dzMlJSMDhiSE9YTWpDU0FlYUwyaC1RRjg2MmRrLUNpV05ZSVVuUHhTYWkyWTEzeGVqVklwYkI1YkZzaVUzTWJmY2pyNnduRUVuMmhzWGx1aGpWVXFtUzNIOEZwZDFkS0pSa1lzM2NWZWRHTEhaRFZRM0hTWHlBWk1FbXNzX01kTUlGMFZhUjU0WTU3QXhhcnR5QUFmZy1OWWtkNVhtVkxPQWJnRFdCMzdrbEVPVEZCYXV4SGg4dXJjVk9neVF6Z1RNcTIwTWpEUzhzaDlZLUNHNUxSRHJiYVlRU2ZoR0VSYVFYcFpuVEdWX20tcDFpWU1zMEMzRFBJanMxSWIxZVR4X0lJbTFPRlBGOWcwWVJsbXFCdkx2bGtGeExqM0t2SGxQVEUwaUYyZ1JaMmN4NUMtckJGZ0dXaU1hRUQzdjcxTW0xQlFJeklaY1lfUUI5V3FsWEVaSmJWZHNZc0FmNm93eW9XckpVQUszTEswclRPaEdNS2VaUzlzUGxvZWU4T0x2OTluc2wxRUM0Z3F2MHJqdk9JQ0pVR0kwb1R1dXV5enhSbU41cHJtX2VycHNLbkM3QmRXV3VaLXRab0g0c2ZDeExiYVppeW8tQU1xdVRhMzB0ckFOV21rSUtuTHFubFRvcXJXZ1JiQjF3Q0hlVjA4WXR1ak9sQUdKc0dHRTRLVjc0X2QwSXZ2NXA3RUxQZlJJcU51cGVLdlpTZ0pxU19tQmU0eG5wTFZsWDhmaHRIOE9aSUxKQ25ZQUt5VHZyNGFoZG9jd0NrOE9JX0xVOG5wQ1Rpc1VFdEo1MXpON2dqUEs2eGhCazZ1YnNNeE9oalhNSjhUd01sWHZvMjcwSXdYV08wVm1lN3pGbnp2S3dnWjV0UlB4c1hwTjlySDBlLUxIZU9uNHIzWWtHeHlpRDFrMkUyM0s4ay02RmxhM2JwMV9DQktfdkM0VUhBU3NqQnJjd21kOHVvYzdJTDRsQmRfeldQbEtyUXp6b
 mxyZVlMV2w3S1RmdG5ELXF0STlLMlFpWm9Ib3E4anZSYUJTTjZqUTk3RXhEb0E5dUk1LVRFc21UYlpCV3pGemdoOS1mbXBKZmQ1R3VNUXVhblJDN2VPbzh4bkJrVnI2UVVnZjVhYzV6Um0zc1ZBaktBVDJ5djc0dTNyOEJjUEJMcTBsc1gwTUpza3FlNEZhN193NXB5Q0Y4dS1RbVFkN2dmeUdPSW1OdTgySGJPSk5yMHg4Vm9NZU9uUExsVUhyY2cxNk43czY5ekU3SEM2UExpcHJobHdmY2JvMXlaZDZYVUxYNGI5MXJ4ME5SU0VpYURISGV1QS1LNWFQb1F6VVZiSFJ0cExvdHpwTEFTZkhwMWFhSEoyakRQUElfcVllbzkwWjVrR3RiV2plSTBYVDlzMy1TMk5pcW16Z2Q5WEMxNEJaUTM0UWpNdksyNUpJYXpqWW5FdGQzYUFYRWFZNU9CdGZ5R2NIcV96UmRaZlVQdDdDNk1LTFdRbnpzTXNWZHJ4cnpCcWRMMVV0NzlIQnZ5M3RlWDZ0RmJuYjR2ZkgxY3NZUl82a041T205VndHelRZYWNGM1dDTkNuOHljMk13N1Y4b25ZOXFLU0VLS1hRYk5KYlB1cEJsT29qLV9tV1drTkdmSy1TUHJoRmFGNF9LaDFTd25TelBydHRVVU9WMXg4ejNmUVFXZml5eVllcGd0VHVGSEZheHE0YXNCUjRQVndfUnBJN3c4QTNiSGR5ODQteWprZU0wU0k4WE5CdkRmVThRXzA2aVZjWkg1UWhwU2VENVpZNWotcDNzN3c4X2MtRXo3RHRZaHgyQzducWU2OFNVYmt3dmd4d2RUOFhaYzcySTJwSUFwYklPTzN0SEFIVmpvVHdVX3dsSHctSVZKbzZfSlBvRE5JbEdZcHdDZ21oMV9rb2FCLXFvMGdQd0UyeG1sRmdNeVVCd3lfWHNEdVRUcVJfT3pYVHBQbWdhTWNZMXJldEgzVj
 BDZ3BHaTBqYVZoN2NJSUpoVWNRcXRIVHl6S1hDTWVMRVBXYzJuVV9oXzB5U0tTanJMUmR1cHpkMTZ6V2sxdTRzdDRDak9CR1AxbloxVU14X3lGQ3ZsVVlESGY5OHhBelJNbUg0c1YxMnVMYmlCS2l0eTEwSG83X2N6T0htQ09LeE1oaFlhRmVrS19veUU3X3pWbTRjUzhHbEJiMUo2UVZMeHpGMXlORnlqeHdITEtnNURXUzN1T0JfSGpNdHlMOHh4WXhNR2FjNTh1X2g5ZEM5QThtVGJ5bEF6Wll6eTUtU3pvSVJYZHhVOGtBN1c0QzFWYmI1VGgyVHZmemF1Vk1mNVg0SWc1WTU4NzMtd3oxNVpHZW5xU3JreFVqU0tVUWVlZkI2eEg1aGtKeWs1cDZWY1JJNzF6SkVEVEU2LWZHSGsxTlNRd2QtS2tTaWlwMjI2d0JCOHZSVWdGQ1VZcy1EZC10TXF1aDdKZjlaRTU5amNzR0ZkTDJhamFRcjc4Z21VZEFVYS1HRHpQeHp3YkM0b1FKS29ObkNEZGc5WV94S3NHeEtDWnRVT1VjM0Z4MlptZFpfM292ZGExaHdyVDZpYVJLM0MxZnh0ZVpheE9IWkNvdW5MeU8wZUkzZ1Nnd2dkVERxODZ3TzY2U3pHdGRxYmo0bGZrT3NkRUYtUDNhQU1yOGNuclh3b2NOdGVpaVJ0YnVqLXhfNlVQUk5hWHJCV0lHRk1Mc2x3b1VlRXE1ZUpuOUhSYmdvd25vU3psOUdDWWdtdnRsb1ZIVHFVLXpNWk9TcmxPejA2aU1ZZjBjakliUDJtdHUyWHlDS3dkRnFsZHJqUWs3VmNUUEJkczluRjR2Z3lmOU1nSFVTeVpHTHFubHNtdG5ER1p4VTN0UmR1eXZfTFRLcDgxYVVQVVprb0EtTkMzdEFncHdQbUtodzVnY3M4U19aSC16VVNFd1BjLVR6NGtJSzhrSFVxQ2ZFY0pfMmhpX2RTWHR
 KbFB3TG9EeU95R1hTWkp5ZGIzb2hjblk3Z3RneGpQaU82Vmlwd1NZMXRVVUV1YmFKbHkzTGFwRjN0cXlEZXBBdHMxc2JDdzNSSm1HcE92WjlfaTk5SXZ6WjY1WDZPSDB1YUpDTWl6bFpzdGQwZ1FRMXl2ZTNQRDRaVHZPdzlMMm9Na0ZDQlFvQzBUalU5b0tPTHNpdlAzbTZOWjROLVpiaWFaNTIxbWU1ZjBWV1loRkN3RENxajRyUDZ5WmloOXVPTW5rWnNhZ3BtS0RlaVV6d1RpaENKdlRkZnBfbG1GQ3cyc0Jyd0lIVWJfdkxWY1RWNDd4NVNwSnhuS2dpWHpZUG8weElnYnY1bmZGWTJvM1NBWkZpSlNlNEJQbmFsX2FQLUFnNDdWM2h5NmNzT0xCM3l0VlNCRDdlNjFpU1VGWVhBUmZJVEVXa0VRaHBIWWJyRTlvemdldzdOLU5HaXdtWndOUy04SUFSbmRFS0tXSXRXb01fMllXVmYxS1ZoME8xQ2wwR0ZDV2NCNzFDLWxMazVJbkpKUm5Wd2dPQ1M2YUFKaEM2T2pIVVYydTR3TTdndFI1c1Y2Snk1NUxQcjFUbVpZQXAyVFNSMG0zUWMyN0ZKRnhxaFU2R20tZGtVNXZKbGtnSjUwY2xTUVVGcVl4Z0pDX1hSdWVpOXNzdkNmbnZVOW1ZSEFQZTU2Q2dXNWFiVGhSOEJCcTc2aTlxUjBlRVV4eFVWUUtCemFhVlB3TmVqaFRVYnpWcHZnNGlqSFRocFBlRzdDZ3hwQ00zT0pCaHFnS2k3RzVTeHFHYjdNVEhoclp2Q3I2WHZtZGdFc3NxWW9RdUQyYUQ4TlhjdVU0Mm1NVGwyZS1sY2pwU1E5R29hdlRHSjFCeFp2YWlYZzRNS1FGUjBjRDQzYkxsaXo2Y2NCeEEwZnJTU2dqbUhRNERxdHhjYkFiNFlPTDFlYkFQNFNSQnJwa3hGQW5fc1l6ci1aR0F0R0l3R1Jf
 UHRRbjVLQ05yaXBueDRITVBmS2UtTHg4MzBIWFNxVGV5c0hRbGtuRlRSeFdwLXdNcUxPMlFhTHJnMlUzdnBDekloRmh4dG1tWnpPSE8zZmY2YTAySk9BaDVDek9GcG9oTDFXakl5a1RMd0dNMDZMQ25uNmhGeDVOZEhmVTlqaTdKNGZuT2RkcVh2ZnZ4TDhSN0wtM1d6SThIUVI4TkRHRzl6ZGtHZDUyQVlkNTBqUTZPN29qNUdkZldGMDdQTVY3WWFETjhGc1YwT19wZDM5bFpiUnM0SlV1Y0xWMzBXNGpqVGdselZGeXBaZEFxQXU0d2pWTVd5T1I0X1RSMnh6YW0wemx0ZXc1bm01TUk4NTlZYVhCVE95bkV5T18yRndDR2hzdmxQR2t5SHZuc050NFVya3pjRGswX0JaYUlYYWFNbUhxMUJQUWdiR0d6bUxNV0FXcFY0OUszdnBkN250WHFBZEVyN25VUnVpS2RSckVTYnpEUnAxclh2NExOMUdGNXRnRUFCZFhwYTVQVG9nVDM3cHUwb1BNNW5FZXFDeklRbmtjemMzUVk5SEZwY1J6bWFmbV9fSngxRFd0ak5qR1J0cVM4aHVUcVNKOG5ORl90ZXZsV2dwOU5uZU9KSUZwZkVMMnhYMTc2dnkyQ1FONTBFRzZZWmM4dXZreHFNUmk3OFNjdENEeXQ0WS5Sc3FFM1dad19XclIxRmtQc1RtWW1B"
+}
\ No newline at end of file


[02/50] [abbrv] jclouds git commit: JCLOUDS-1254 Filters storage account by current available locations

Posted by na...@apache.org.
JCLOUDS-1254 Filters storage account by current available locations


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

Branch: refs/heads/master
Commit: c45728e085797fe3fca8e4a7bc53f7143fef5133
Parents: 894be79
Author: Dani Estevez <co...@danielestevez.com>
Authored: Tue Mar 14 10:59:57 2017 -0400
Committer: Ignasi Barrera <na...@apache.org>
Committed: Tue Mar 28 08:23:46 2017 +0200

----------------------------------------------------------------------
 .../arm/compute/AzureComputeServiceAdapter.java | 42 +++++++++++---------
 1 file changed, 24 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/c45728e0/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index f510109..572e2be 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -16,10 +16,23 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.contains;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.find;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
+import static org.jclouds.util.Closeables2.closeQuietly;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.Resource;
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -84,20 +97,6 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.contains;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.find;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
-import static org.jclouds.util.Closeables2.closeQuietly;
-
 /**
  * Defines the connection between the {@link AzureComputeApi} implementation and
  * the jclouds {@link org.jclouds.compute.ComputeService}.
@@ -226,8 +225,15 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    public Iterable<VMImage> listImages() {
       final List<VMImage> osImages = Lists.newArrayList();
 
-      for (Location location : listLocations()) {
-         osImages.addAll(listImagesByLocation(location.name()));
+      final List<String> availableLocationNames = FluentIterable.from(listLocations())
+          .transform(new Function<Location, String>() {
+             @Override public String apply(Location location) {
+                return location.name();
+             }
+          }).toList();
+
+      for (String locationName : availableLocationNames) {
+         osImages.addAll(listImagesByLocation(locationName));
       }
 
       // list custom images
@@ -239,7 +245,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
             try {
                String name = storage.name();
                StorageService storageService = api.getStorageAccountApi(azureGroup).get(name);
-               if (storageService != null
+               if (storageService != null && availableLocationNames.contains(storageService.location())
                      && Status.Succeeded == storageService.storageServiceProperties().provisioningState()) {
                   String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1();
                   BlobHelper blobHelper = new BlobHelper(storage.name(), key);


[33/50] [abbrv] jclouds git commit: fix domain object

Posted by na...@apache.org.
fix domain object

- fix VirtuaMachineMockTest


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

Branch: refs/heads/master
Commit: bc520cfdf2ab1977356502fa2d97c30d1bc177e8
Parents: e1e89b5
Author: Andrea Turli <an...@gmail.com>
Authored: Wed Oct 11 17:26:14 2017 +0100
Committer: Andrea Turli <an...@apache.org>
Committed: Wed Oct 25 15:55:06 2017 +0200

----------------------------------------------------------------------
 .../jclouds/azurecompute/arm/domain/OSProfile.java  |  6 +++---
 .../arm/features/VirtualMachineApiMockTest.java     | 16 ++++++++--------
 .../resources/createvirtualmachineresponse.json     |  4 ++--
 .../src/test/resources/virtualmachine.json          |  4 ++--
 .../src/test/resources/virtualmachines.json         |  8 ++++----
 5 files changed, 19 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/bc520cfd/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
index b77dc9e..3f5a0bc 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
@@ -150,13 +150,13 @@ public abstract class OSProfile {
 
          public abstract String content();
 
-         @SerializedNames({"pass", "component", "settingName", "content"})
-         public static AdditionalUnattendContent create(final String pass, final String component,
+         @SerializedNames({"passName", "componentName", "settingName", "content"})
+         public static AdditionalUnattendContent create(final String passName, final String componentName,
                                                         final String settingName,
                                                         final String content) {
 
             return new AutoValue_OSProfile_WindowsConfiguration_AdditionalUnattendContent(
-                    pass, component, settingName, content);
+                    passName, componentName, settingName, content);
          }
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/bc520cfd/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
index 258ae1a..372b303 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
@@ -16,12 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-import static com.google.common.collect.Iterables.isEmpty;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
 import java.net.URI;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
@@ -59,6 +53,12 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.squareup.okhttp.mockwebserver.MockResponse;
 
+import static com.google.common.collect.Iterables.isEmpty;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
 @Test(groups = "unit", testName = "VirtualMachineApiMockTest", singleThreaded = true)
 public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
 
@@ -141,7 +141,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
                   + "\"managedDisk\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk\",\"storageAccountType\":\"Standard_LRS\"}},"
                   + "\"dataDisks\":[{\"name\":\"mydatadisk1\",\"diskSizeGB\":\"1\",\"lun\":0,\"createOption\":\"Empty\",\"caching\":\"ReadWrite\",\"managedDisk\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk\",\"storageAccountType\":\"Standard_LRS\"}}]},"
                   + "\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"adminPassword\":\"password\",\"customData\":\"\",\"windowsConfiguration\":{\"provisionVMAgent\":false,"
-                  + "\"winRM\":{\"listeners\":[{\"protocol\":\"https\",\"certificateUrl\":\"url-to-certificate\"}]},\"additionalUnattendContent\":[{\"pass\":\"oobesystem\",\"component\":\"Microsoft-Windows-Shell-Setup\",\"settingName\":\"FirstLogonCommands\",\"content\":\"<XML unattend content>\"}],"
+                  + "\"winRM\":{\"listeners\":[{\"protocol\":\"https\",\"certificateUrl\":\"url-to-certificate\"}]},\"additionalUnattendContent\":[{\"passName\":\"oobesystem\",\"componentName\":\"Microsoft-Windows-Shell-Setup\",\"settingName\":\"FirstLogonCommands\",\"content\":\"<XML unattend content>\"}],"
                   + "\"enableAutomaticUpdates\":true},"
                   + "\"secrets\":[{\"sourceVault\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/Microsoft.KeyVault/vaults/myvault1\"},\"vaultCertificates\":[{\"certificateUrl\":\"https://myvault1.vault.azure.net/secrets/SECRETNAME/SECRETVERSION\",\"certificateStore\":\"CERTIFICATESTORENAME\"}]}]},"
                   + "\"networkProfile\":{\"networkInterfaces\":[{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167\"}]},"
@@ -176,7 +176,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
                   + "\"managedDisk\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk\",\"storageAccountType\":\"Standard_LRS\"}},"
                   + "\"dataDisks\":[{\"name\":\"mydatadisk1\",\"diskSizeGB\":\"1\",\"lun\":0,\"createOption\":\"Empty\",\"caching\":\"ReadWrite\",\"managedDisk\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk\",\"storageAccountType\":\"Standard_LRS\"}}]},"
                   + "\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"adminPassword\":\"password\",\"customData\":\"\",\"windowsConfiguration\":{\"provisionVMAgent\":false,"
-                  + "\"winRM\":{\"listeners\":[{\"protocol\":\"https\",\"certificateUrl\":\"url-to-certificate\"}]},\"additionalUnattendContent\":[{\"pass\":\"oobesystem\",\"component\":\"Microsoft-Windows-Shell-Setup\",\"settingName\":\"FirstLogonCommands\",\"content\":\"<XML unattend content>\"}],"
+                  + "\"winRM\":{\"listeners\":[{\"protocol\":\"https\",\"certificateUrl\":\"url-to-certificate\"}]},\"additionalUnattendContent\":[{\"passName\":\"oobesystem\",\"componentName\":\"Microsoft-Windows-Shell-Setup\",\"settingName\":\"FirstLogonCommands\",\"content\":\"<XML unattend content>\"}],"
                   + "\"enableAutomaticUpdates\":true},"
                   + "\"secrets\":[{\"sourceVault\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/Microsoft.KeyVault/vaults/myvault1\"},\"vaultCertificates\":[{\"certificateUrl\":\"https://myvault1.vault.azure.net/secrets/SECRETNAME/SECRETVERSION\",\"certificateStore\":\"CERTIFICATESTORENAME\"}]}]},"
                   + "\"networkProfile\":{\"networkInterfaces\":[{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167\"}]},"

http://git-wip-us.apache.org/repos/asf/jclouds/blob/bc520cfd/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json b/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
index 4279f83..7402e14 100644
--- a/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
+++ b/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
@@ -58,8 +58,8 @@
         },    
         "additionalUnattendContent": [
           {      
-            "pass":"oobesystem",    
-            "component":"Microsoft-Windows-Shell-Setup",    
+            "passName":"oobesystem",    
+            "componentName":"Microsoft-Windows-Shell-Setup",    
             "settingName":"FirstLogonCommands",    
             "content":"<XML unattend content>"    
           }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/bc520cfd/providers/azurecompute-arm/src/test/resources/virtualmachine.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachine.json b/providers/azurecompute-arm/src/test/resources/virtualmachine.json
index 51ad1fb..17d89b5 100644
--- a/providers/azurecompute-arm/src/test/resources/virtualmachine.json
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachine.json
@@ -57,8 +57,8 @@
         },
         "additionalUnattendContent":[
           {
-            "pass":"oobesystem",    
-            "component":"Microsoft-Windows-Shell-Setup",
+            "passName":"oobesystem",    
+            "componentName":"Microsoft-Windows-Shell-Setup",
             "settingName":"FirstLogonCommands",
             "content":"<XML unattend content>"
           }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/bc520cfd/providers/azurecompute-arm/src/test/resources/virtualmachines.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachines.json b/providers/azurecompute-arm/src/test/resources/virtualmachines.json
index 27ee602..e77e58b 100644
--- a/providers/azurecompute-arm/src/test/resources/virtualmachines.json
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachines.json
@@ -58,8 +58,8 @@
             },    
             "additionalUnattendContent":[
               {
-                "pass":"oobesystem",    
-                "component":"Microsoft-Windows-Shell-Setup",
+                "passName":"oobesystem",    
+                "componentName":"Microsoft-Windows-Shell-Setup",
                 "settingName":"FirstLogonCommands",
                 "content":"<XML unattend content>"
               }
@@ -158,8 +158,8 @@
             },
             "additionalUnattendContent":[
               {
-                "pass":"oobesystem",
-                "component":"Microsoft-Windows-Shell-Setup",
+                "passName":"oobesystem",
+                "componentName":"Microsoft-Windows-Shell-Setup",
                 "settingName":"FirstLogonCommands",
                 "content":"<XML unattend content>"
               }


[49/50] [abbrv] jclouds git commit: Promote Azure ARM from jclouds-labs

Posted by na...@apache.org.
Promote Azure ARM from jclouds-labs


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

Branch: refs/heads/master
Commit: cc969052a7a10099fc310247903b24e8ca1641b1
Parents: 9fef6ed eebcc00
Author: Ignasi Barrera <na...@apache.org>
Authored: Mon Jan 8 14:58:45 2018 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon Jan 8 14:58:45 2018 +0100

----------------------------------------------------------------------
 providers/azurecompute-arm/README.md            |  101 ++
 providers/azurecompute-arm/pom.xml              |  165 ++
 .../azurecompute/arm/AzureComputeApi.java       |  270 +++
 .../arm/AzureComputeProviderMetadata.java       |  165 ++
 .../arm/AzureManagementApiMetadata.java         |   99 ++
 .../arm/compute/AzureComputeService.java        |  128 ++
 .../arm/compute/AzureComputeServiceAdapter.java |  545 ++++++
 .../AzureComputeServiceContextModule.java       |  134 ++
 .../compute/config/AzurePredicatesModule.java   |  602 +++++++
 .../arm/compute/domain/LocationAndName.java     |   50 +
 .../compute/domain/ResourceGroupAndName.java    |   50 +
 .../ResourceGroupAndNameAndIngressRules.java    |   74 +
 .../extensions/AzureComputeImageExtension.java  |  134 ++
 .../AzureComputeSecurityGroupExtension.java     |  345 ++++
 .../compute/functions/CustomImageToVMImage.java |   33 +
 .../compute/functions/LocationToLocation.java   |   61 +
 .../functions/LocationToResourceGroupName.java  |   46 +
 .../NetworkSecurityGroupToSecurityGroup.java    |   73 +
 .../NetworkSecurityRuleToIpPermission.java      |   76 +
 .../functions/TemplateToAvailabilitySet.java    |   94 +
 .../compute/functions/VMHardwareToHardware.java |   82 +
 .../arm/compute/functions/VMImageToImage.java   |  157 ++
 .../functions/VirtualMachineToNodeMetadata.java |  208 +++
 .../functions/VirtualMachineToStatus.java       |  116 ++
 .../loaders/CreateSecurityGroupIfNeeded.java    |  100 ++
 .../compute/loaders/DefaultResourceGroup.java   |   62 +
 .../compute/options/AzureTemplateOptions.java   |  324 ++++
 .../arm/compute/options/IpOptions.java          |   76 +
 .../arm/compute/strategy/CleanupResources.java  |  237 +++
 .../CreateResourcesThenCreateNodes.java         |  258 +++
 .../arm/config/AzureComputeHttpApiModule.java   |  108 ++
 .../arm/config/AzureComputeParserModule.java    |   29 +
 .../arm/config/AzureComputeProperties.java      |   46 +
 .../arm/config/AzureComputeRateLimitModule.java |   30 +
 .../arm/config/AzureOAuthConfigFactory.java     |   60 +
 .../azurecompute/arm/config/GraphRBAC.java      |   54 +
 .../azurecompute/arm/config/OAuthResource.java  |   35 +
 .../jclouds/azurecompute/arm/config/Tenant.java |   34 +
 .../azurecompute/arm/domain/Availability.java   |   32 +
 .../arm/domain/AvailabilitySet.java             |  223 +++
 .../arm/domain/BackendAddressPool.java          |   43 +
 .../domain/BackendAddressPoolProperties.java    |   74 +
 .../azurecompute/arm/domain/Certificate.java    |  638 +++++++
 .../azurecompute/arm/domain/ComputeNode.java    |   31 +
 .../azurecompute/arm/domain/CreationData.java   |   54 +
 .../azurecompute/arm/domain/DataDisk.java       |  160 ++
 .../azurecompute/arm/domain/Deployment.java     |  254 +++
 .../azurecompute/arm/domain/DeploymentBody.java |   42 +
 .../arm/domain/DeploymentProperties.java        |   31 +
 .../arm/domain/DeploymentTemplate.java          |  125 ++
 .../arm/domain/DiagnosticsProfile.java          |   74 +
 .../jclouds/azurecompute/arm/domain/Disk.java   |  105 ++
 .../azurecompute/arm/domain/DiskProperties.java |   78 +
 .../azurecompute/arm/domain/DnsSettings.java    |   60 +
 .../azurecompute/arm/domain/Extension.java      |   40 +
 .../arm/domain/ExtensionProfile.java            |   39 +
 .../arm/domain/ExtensionProfileSettings.java    |   42 +
 .../arm/domain/ExtensionProperties.java         |   70 +
 .../arm/domain/FrontendIPConfigurations.java    |   45 +
 .../FrontendIPConfigurationsProperties.java     |   66 +
 .../arm/domain/HardwareProfile.java             |   48 +
 .../azurecompute/arm/domain/IdReference.java    |   71 +
 .../jclouds/azurecompute/arm/domain/Image.java  |   86 +
 .../arm/domain/ImageProperties.java             |   61 +
 .../azurecompute/arm/domain/ImageReference.java |  106 ++
 .../azurecompute/arm/domain/InboundNatRule.java |   43 +
 .../arm/domain/InboundNatRuleProperties.java    |  105 ++
 .../arm/domain/IpConfiguration.java             |   68 +
 .../arm/domain/IpConfigurationProperties.java   |  105 ++
 .../jclouds/azurecompute/arm/domain/Key.java    |  229 +++
 .../arm/domain/KeyVaultReference.java           |   46 +
 .../azurecompute/arm/domain/LoadBalancer.java   |   67 +
 .../arm/domain/LoadBalancerProperties.java      |  109 ++
 .../arm/domain/LoadBalancingRule.java           |   43 +
 .../arm/domain/LoadBalancingRuleProperties.java |  135 ++
 .../azurecompute/arm/domain/Location.java       |   58 +
 .../arm/domain/ManagedDiskParameters.java       |   36 +
 .../jclouds/azurecompute/arm/domain/Metric.java |   51 +
 .../azurecompute/arm/domain/MetricData.java     |   74 +
 .../arm/domain/MetricDefinition.java            |   97 ++
 .../azurecompute/arm/domain/MetricName.java     |   38 +
 .../arm/domain/NetworkInterfaceCard.java        |   57 +
 .../domain/NetworkInterfaceCardProperties.java  |   78 +
 .../domain/NetworkInterfaceConfiguration.java   |   44 +
 ...NetworkInterfaceConfigurationProperties.java |   68 +
 .../azurecompute/arm/domain/NetworkProfile.java |   92 +
 .../arm/domain/NetworkSecurityGroup.java        |   49 +
 .../domain/NetworkSecurityGroupProperties.java  |   89 +
 .../arm/domain/NetworkSecurityRule.java         |   46 +
 .../domain/NetworkSecurityRuleProperties.java   |  146 ++
 .../jclouds/azurecompute/arm/domain/OSDisk.java |   99 ++
 .../azurecompute/arm/domain/OSProfile.java      |  277 +++
 .../jclouds/azurecompute/arm/domain/Offer.java  |   51 +
 .../jclouds/azurecompute/arm/domain/Plan.java   |   47 +
 .../jclouds/azurecompute/arm/domain/Probe.java  |   42 +
 .../arm/domain/ProbeProperties.java             |   91 +
 .../azurecompute/arm/domain/Provisionable.java  |   22 +
 .../arm/domain/PublicIPAddress.java             |   71 +
 .../arm/domain/PublicIPAddressProperties.java   |   86 +
 .../azurecompute/arm/domain/Publisher.java      |   52 +
 .../jclouds/azurecompute/arm/domain/Region.java |  103 ++
 .../azurecompute/arm/domain/Resource.java       |   72 +
 .../arm/domain/ResourceDefinition.java          |  106 ++
 .../azurecompute/arm/domain/ResourceGroup.java  |   52 +
 .../arm/domain/ResourceProviderMetaData.java    |   71 +
 .../jclouds/azurecompute/arm/domain/SKU.java    |   40 +
 .../jclouds/azurecompute/arm/domain/Secret.java |  186 ++
 .../azurecompute/arm/domain/Secrets.java        |   55 +
 .../arm/domain/ServicePrincipal.java            |   66 +
 .../jclouds/azurecompute/arm/domain/Status.java |   49 +
 .../arm/domain/StorageAccountType.java          |   47 +
 .../azurecompute/arm/domain/StorageProfile.java |   82 +
 .../azurecompute/arm/domain/StorageService.java |  226 +++
 .../arm/domain/StorageServiceKeys.java          |   39 +
 .../arm/domain/StorageServiceUpdateParams.java  |   65 +
 .../jclouds/azurecompute/arm/domain/Subnet.java |  136 ++
 .../arm/domain/TemplateParameterType.java       |   34 +
 .../jclouds/azurecompute/arm/domain/VHD.java    |   48 +
 .../azurecompute/arm/domain/VMDeployment.java   |   44 +
 .../azurecompute/arm/domain/VMHardware.java     |   70 +
 .../azurecompute/arm/domain/VMImage.java        |  182 ++
 .../jclouds/azurecompute/arm/domain/VMSize.java |   67 +
 .../jclouds/azurecompute/arm/domain/Value.java  |   42 +
 .../jclouds/azurecompute/arm/domain/Vault.java  |  112 ++
 .../arm/domain/VaultCertificate.java            |   46 +
 .../arm/domain/VaultProperties.java             |  131 ++
 .../azurecompute/arm/domain/Version.java        |   90 +
 .../azurecompute/arm/domain/VirtualMachine.java |  103 ++
 .../arm/domain/VirtualMachineInstance.java      |   90 +
 .../arm/domain/VirtualMachineProperties.java    |  154 ++
 .../arm/domain/VirtualMachineScaleSet.java      |  110 ++
 .../VirtualMachineScaleSetDNSSettings.java      |   41 +
 .../VirtualMachineScaleSetIpConfiguration.java  |   61 +
 ...achineScaleSetIpConfigurationProperties.java |  104 ++
 .../VirtualMachineScaleSetNetworkProfile.java   |   58 +
 ...tualMachineScaleSetNetworkSecurityGroup.java |   39 +
 .../domain/VirtualMachineScaleSetOSProfile.java |  273 +++
 .../arm/domain/VirtualMachineScaleSetPlan.java  |   51 +
 .../VirtualMachineScaleSetProperties.java       |  106 ++
 ...ineScaleSetPublicIPAddressConfiguration.java |   59 +
 ...achineScaleSetPublicIPAddressProperties.java |   54 +
 .../arm/domain/VirtualMachineScaleSetSKU.java   |   45 +
 .../VirtualMachineScaleSetUpgradeMode.java      |   35 +
 .../VirtualMachineScaleSetUpgradePolicy.java    |   35 +
 ...ualMachineScaleSetVirtualMachineProfile.java |   83 +
 .../azurecompute/arm/domain/VirtualNetwork.java |  122 ++
 .../AzureComputeRateLimitExceededException.java |   51 +
 .../arm/features/AvailabilitySetApi.java        |   84 +
 .../arm/features/DeploymentApi.java             |  107 ++
 .../azurecompute/arm/features/DiskApi.java      |   77 +
 .../azurecompute/arm/features/GraphRBACApi.java |   50 +
 .../azurecompute/arm/features/ImageApi.java     |   77 +
 .../azurecompute/arm/features/JobApi.java       |   58 +
 .../arm/features/LoadBalancerApi.java           |   80 +
 .../azurecompute/arm/features/LocationApi.java  |   56 +
 .../arm/features/MetricDefinitionsApi.java      |   52 +
 .../azurecompute/arm/features/MetricsApi.java   |   51 +
 .../arm/features/NetworkInterfaceCardApi.java   |   80 +
 .../arm/features/NetworkSecurityGroupApi.java   |   79 +
 .../arm/features/NetworkSecurityRuleApi.java    |   91 +
 .../azurecompute/arm/features/OSImageApi.java   |   94 +
 .../arm/features/PublicIPAddressApi.java        |   78 +
 .../arm/features/ResourceGroupApi.java          |   99 ++
 .../arm/features/ResourceProviderApi.java       |   56 +
 .../arm/features/StorageAccountApi.java         |  160 ++
 .../azurecompute/arm/features/SubnetApi.java    |   74 +
 .../azurecompute/arm/features/VMSizeApi.java    |   45 +
 .../azurecompute/arm/features/VaultApi.java     |  635 +++++++
 .../arm/features/VirtualMachineApi.java         |  140 ++
 .../arm/features/VirtualMachineScaleSetApi.java |   88 +
 .../arm/features/VirtualNetworkApi.java         |   76 +
 .../arm/filters/ApiVersionFilter.java           |   90 +
 .../azurecompute/arm/functions/FalseOn204.java  |   40 +
 .../arm/functions/ParseJobStatus.java           |   51 +
 .../arm/functions/StatusCodeParser.java         |   38 +
 .../azurecompute/arm/functions/URIParser.java   |   40 +
 .../arm/handlers/AzureComputeErrorHandler.java  |   93 +
 .../handlers/AzureRateLimitRetryHandler.java    |   39 +
 .../azurecompute/arm/util/GetEnumValue.java     |   35 +
 .../jclouds/azurecompute/arm/util/VMImages.java |   27 +
 .../arm/AzureComputeProviderMetadataTest.java   |   28 +
 .../compute/AzureComputeServiceLiveTest.java    |  121 ++
 .../compute/AzureTemplateBuilderLiveTest.java   |   80 +
 .../AzureComputeImageExtensionLiveTest.java     |  128 ++
 ...reComputeSecurityGroupExtensionLiveTest.java |  177 ++
 .../CreateResourcesThenCreateNodesTest.java     |  116 ++
 .../arm/config/ParseTenantIdTest.java           |   50 +
 .../arm/domain/IdReferenceTest.java             |   63 +
 .../azurecompute/arm/domain/SubnetTest.java     |   47 +
 .../features/AvailabilitySetApiLiveTest.java    |  105 ++
 .../features/AvailabilitySetApiMockTest.java    |  155 ++
 .../arm/features/DeploymentApiLiveTest.java     |  156 ++
 .../arm/features/DeploymentApiMockTest.java     |  154 ++
 .../arm/features/DiskApiLiveTest.java           |  107 ++
 .../arm/features/DiskApiMockTest.java           |  141 ++
 .../arm/features/GraphRBACApiLiveTest.java      |   39 +
 .../arm/features/GraphRBACApiMockTest.java      |   39 +
 .../arm/features/ImageApiLiveTest.java          |  155 ++
 .../arm/features/ImageApiMockTest.java          |  155 ++
 .../arm/features/JobApiMockTest.java            |   96 ++
 .../arm/features/LoadBalancerApiLiveTest.java   |  449 +++++
 .../arm/features/LoadBalancerApiMockTest.java   |  160 ++
 .../arm/features/LocationApiLiveTest.java       |   51 +
 .../arm/features/LocationApiMockTest.java       |   50 +
 .../features/MetricDefinitionsApiLiveTest.java  |  131 ++
 .../features/MetricDefinitionsApiMockTest.java  |   65 +
 .../arm/features/MetricsApiLiveTest.java        |  143 ++
 .../arm/features/MetricsApiMockTest.java        |   69 +
 .../NetworkInterfaceCardApiLiveTest.java        |  119 ++
 .../NetworkInterfaceCardApiMockTest.java        |  145 ++
 .../NetworkSecurityGroupApiLiveTest.java        |  106 ++
 .../NetworkSecurityGroupApiMockTest.java        |  163 ++
 .../NetworkSecurityRuleApiLiveTest.java         |  156 ++
 .../NetworkSecurityRuleApiMockTest.java         |  206 +++
 .../arm/features/OSImageApiLiveTest.java        |   70 +
 .../arm/features/OSImageApiMockTest.java        |  123 ++
 .../features/PublicIPAddressApiLiveTest.java    |  129 ++
 .../features/PublicIPAddressApiMockTest.java    |  178 ++
 .../arm/features/ResourceGroupApiLiveTest.java  |  112 ++
 .../arm/features/ResourceGroupApiMockTest.java  |  173 ++
 .../features/ResourceProviderAPIMockTest.java   |   66 +
 .../features/ResourceProviderApiLiveTest.java   |   55 +
 .../arm/features/StorageAccountApiLiveTest.java |  143 ++
 .../arm/features/StorageAccountApiMockTest.java |  312 ++++
 .../arm/features/SubnetApiLiveTest.java         |   93 +
 .../arm/features/SubnetApiMockTest.java         |  139 ++
 .../arm/features/VMSizeApiLiveTest.java         |   40 +
 .../arm/features/VMSizeApiMockTest.java         |   57 +
 .../arm/features/VaultApiLiveTest.java          | 1057 ++++++++++++
 .../arm/features/VaultApiMockTest.java          | 1619 ++++++++++++++++++
 .../arm/features/VirtualMachineApiLiveTest.java |  349 ++++
 .../arm/features/VirtualMachineApiMockTest.java |  409 +++++
 .../VirtualMachineScaleSetApiLiveTest.java      |  265 +++
 .../VirtualMachineScaleSetApiMockTest.java      |  453 +++++
 .../arm/features/VirtualNetworkApiLiveTest.java |   89 +
 .../arm/features/VirtualNetworkApiMockTest.java |  137 ++
 .../arm/filters/ApiVersionFilterTest.java       |  129 ++
 .../arm/functions/URIParserTest.java            |   51 +
 .../arm/internal/AzureLiveTestUtils.java        |   49 +
 .../internal/BaseAzureComputeApiLiveTest.java   |  249 +++
 .../internal/BaseAzureComputeApiMockTest.java   |  203 +++
 .../test/resources/PublicIPAddressCreate.json   |   20 +
 .../PublicIPAddressCreateDnsRecordInUse.json    |    7 +
 .../test/resources/PublicIPAddressGetInfo.json  |   24 +
 .../src/test/resources/PublicIPAddressList.json |   80 +
 .../test/resources/availabilitysetcreate.json   |   11 +
 .../src/test/resources/availabilitysetget.json  |   12 +
 .../src/test/resources/availabilitysetlist.json |   16 +
 .../resources/createdeploymentaccepted.json     |   33 +
 .../resources/createdeploymentsucceeded.json    |   36 +
 .../src/test/resources/creatediskresponse.json  |   11 +
 .../resources/createnetworkinterfacecard.json   |   35 +
 .../src/test/resources/createsubnet.json        |    5 +
 .../test/resources/createsubnetresponse.json    |   14 +
 .../resources/createvirtualmachineresponse.json |  109 ++
 .../test/resources/createvirtualnetwork.json    |   20 +
 .../src/test/resources/getdisk.json             |   19 +
 .../test/resources/getnetworkinterfacecard.json |   35 +
 .../src/test/resources/getonesubnet.json        |   14 +
 .../resources/getresourceprovidermetadata.json  |  366 ++++
 .../src/test/resources/getvault.json            |   60 +
 .../src/test/resources/image.json               |   43 +
 .../resources/isavailablestorageservice.json    |    3 +
 .../src/test/resources/listdeployments.json     |   99 ++
 .../src/test/resources/listdisks.json           |   23 +
 .../test/resources/listnetworkinterfaces.json   |   68 +
 .../listsubnetswithinvirtualnetwork.json        |   18 +
 .../src/test/resources/listvirtualnetworks.json |   79 +
 .../src/test/resources/loadbalancercreate.json  |   28 +
 .../src/test/resources/loadbalancerget.json     |   54 +
 .../src/test/resources/loadbalancerlist.json    |   35 +
 .../src/test/resources/locations.json           |   10 +
 .../src/test/resources/logback-test.xml         |   42 +
 .../src/test/resources/metricdefinitions.json   |   25 +
 .../src/test/resources/metrics.json             |   19 +
 .../resources/networksecuritygroupcreate.json   |  125 ++
 .../test/resources/networksecuritygroupget.json |  125 ++
 .../resources/networksecuritygrouplist.json     |  127 ++
 .../resources/networksecurityrulecreate.json    |   17 +
 .../test/resources/networksecurityruleget.json  |   17 +
 .../networksecurityrulegetdefault.json          |   17 +
 .../test/resources/networksecurityrulelist.json |   35 +
 .../networksecurityrulelistdefault.json         |   99 ++
 .../src/test/resources/offers.json              |    7 +
 .../src/test/resources/publishers.json          |   12 +
 .../src/test/resources/resourceDefinition.json  |   22 +
 .../test/resources/resourcegroup-resources.json |   46 +
 .../src/test/resources/resourcegroup.json       |   11 +
 .../src/test/resources/resourcegroups.json      |   21 +
 .../test/resources/resourcegroupupdated.json    |    9 +
 .../src/test/resources/serviceprincipals.json   |   53 +
 .../src/test/resources/skus.json                |   12 +
 .../src/test/resources/storageAccounts.json     |   90 +
 .../test/resources/storageCreateResponse.json   |    9 +
 .../src/test/resources/storageaccountkeys.json  |    4 +
 .../test/resources/storageaccountupdate.json    |    7 +
 .../src/test/resources/storageservices.json     |   30 +
 .../src/test/resources/vaultbackupkey.json      |    3 +
 .../src/test/resources/vaultbackupsecret.json   |    3 +
 .../src/test/resources/vaultcreate.json         |   26 +
 .../test/resources/vaultcreatecertificate.json  |   11 +
 .../vaultcreatecertificaterequestbody.json      |   21 +
 .../src/test/resources/vaultcreatekey.json      |   15 +
 .../resources/vaultcreatekeyrequestbody.json    |    7 +
 .../test/resources/vaultcreaterequestbody.json  |   21 +
 .../test/resources/vaultdeletecertificate.json  |   58 +
 .../vaultdeletecertificatecontacts.json         |    8 +
 .../resources/vaultdeletecertificateissuer.json |   21 +
 .../vaultdeletecertificateoperation.json        |   11 +
 .../src/test/resources/vaultdeletekey.json      |   15 +
 .../src/test/resources/vaultdeletesecret.json   |   10 +
 .../src/test/resources/vaultget.json            |   26 +
 .../src/test/resources/vaultgetcertificate.json |   55 +
 .../resources/vaultgetcertificatecontacts.json  |    8 +
 .../resources/vaultgetcertificateissuer.json    |   21 +
 .../resources/vaultgetcertificateoperation.json |   11 +
 .../resources/vaultgetcertificatepolicy.json    |   37 +
 .../src/test/resources/vaultgetdeleted.json     |   12 +
 .../resources/vaultgetdeletedcertificate.json   |   55 +
 .../src/test/resources/vaultgetdeletedkey.json  |   18 +
 .../test/resources/vaultgetdeletedsecret.json   |   13 +
 .../src/test/resources/vaultgetkey.json         |   15 +
 .../src/test/resources/vaultgetkeyversions.json |   23 +
 .../src/test/resources/vaultgetsecret.json      |   11 +
 .../test/resources/vaultgetsecretversions.json  |   25 +
 .../src/test/resources/vaultimportablecert.txt  |   58 +
 .../test/resources/vaultimportcertificate.json  |   52 +
 .../vaultimportcertificaterequestbody.json      |    9 +
 .../resources/vaultimportkeyrequestbody.json    |   18 +
 .../src/test/resources/vaultkeybackup.txt       |    1 +
 .../src/test/resources/vaultkeydecrypt.json     |    4 +
 .../resources/vaultkeydecryptrequestbody.json   |    4 +
 .../src/test/resources/vaultkeyencrypt.json     |    4 +
 .../resources/vaultkeyencryptrequestbody.json   |    4 +
 .../src/test/resources/vaultkeysign.json        |    4 +
 .../test/resources/vaultkeysignrequestbody.json |    4 +
 .../src/test/resources/vaultkeyunwrap.json      |    4 +
 .../resources/vaultkeyunwraprequestbody.json    |    4 +
 .../src/test/resources/vaultkeyverify.json      |    3 +
 .../resources/vaultkeyverifyrequestbody.json    |    5 +
 .../src/test/resources/vaultkeywrap.json        |    4 +
 .../test/resources/vaultkeywraprequestbody.json |    4 +
 .../src/test/resources/vaultlist.json           |   29 +
 .../resources/vaultlistcertificateissuers.json  |    7 +
 .../test/resources/vaultlistcertificates.json   |   27 +
 .../resources/vaultlistcertificateversions.json |   17 +
 .../src/test/resources/vaultlistdeleted.json    |   15 +
 .../resources/vaultlistdeletedcertificates.json |   18 +
 .../test/resources/vaultlistdeletedkeys.json    |   15 +
 .../test/resources/vaultlistdeletedsecrets.json |   16 +
 .../src/test/resources/vaultlistkeys.json       |   42 +
 .../src/test/resources/vaultlistsecrets.json    |   40 +
 .../test/resources/vaultmergecertificate.json   |   62 +
 .../vaultmergecertificaterequestbody.json       |   10 +
 .../src/test/resources/vaultmergex5c-1.txt      |    1 +
 .../src/test/resources/vaultmergex5c-2.txt      |    1 +
 .../src/test/resources/vaultmergex5c-3.txt      |    1 +
 .../vaultrecoverdeletedcertificate.json         |   52 +
 .../test/resources/vaultrecoverdeletedkey.json  |   15 +
 .../resources/vaultrecoverdeletedsecret.json    |   10 +
 .../src/test/resources/vaultrestorekey.json     |   15 +
 .../resources/vaultrestorekeyrequestbody.json   |    3 +
 .../src/test/resources/vaultrestoresecret.json  |   10 +
 .../vaultrestoresecretrequestbody.json          |    3 +
 .../src/test/resources/vaultsamplesecret.txt    |   27 +
 .../src/test/resources/vaultsecretbackup.txt    |    1 +
 .../resources/vaultsetcertificatecontacts.json  |    8 +
 .../vaultsetcertificatecontactsrequestbody.json |    7 +
 .../resources/vaultsetcertificateissuer.json    |   21 +
 .../vaultsetcertificateissuerrequestbody.json   |   15 +
 .../src/test/resources/vaultsetsecret.json      |   11 +
 .../resources/vaultsetsecretrequestbody.json    |    7 +
 .../test/resources/vaultupdatecertificate.json  |   58 +
 .../resources/vaultupdatecertificateissuer.json |   21 +
 ...vaultupdatecertificateissuerrequestbody.json |   15 +
 .../vaultupdatecertificateoperation.json        |   11 +
 ...ltupdatecertificateoperationrequestbody.json |    3 +
 .../resources/vaultupdatecertificatepolicy.json |   37 +
 ...vaultupdatecertificatepolicyrequestbody.json |    8 +
 .../vaultupdatecertificaterequestbody.json      |    1 +
 .../src/test/resources/vaultupdatekey.json      |   18 +
 .../resources/vaultupdatekeyrequestbody.json    |    5 +
 .../resources/vaultupdatekeywithversion.json    |   18 +
 .../src/test/resources/vaultupdatesecret.json   |   13 +
 .../resources/vaultupdatesecretrequestbody.json |    5 +
 .../resources/vaultupdatesecretwithversion.json |   13 +
 ...vaultupdatesecretwithversionrequestbody.json |    5 +
 .../src/test/resources/versions.json            |   12 +
 .../src/test/resources/virtualmachine.json      |  107 ++
 .../test/resources/virtualmachineInstance.json  |   40 +
 .../resources/virtualmachineimagecreate.json    |   21 +
 .../test/resources/virtualmachineimageget.json  |   21 +
 .../test/resources/virtualmachineimagelist.json |   25 +
 .../src/test/resources/virtualmachines.json     |  203 +++
 .../resources/virtualmachinescalesetget.json    |   64 +
 .../virtualmachinescalesetgetwhen404.json       |    6 +
 .../resources/virtualmachinescalesetlist.json   |   93 +
 .../virtualmachinescalesetlistwhen404.json      |    6 +
 ...almachinescalesetresponsecreateorupdate.json |  103 ++
 .../src/test/resources/virtualnetwork.json      |   20 +
 .../src/test/resources/vmsizes.json             |   28 +
 401 files changed, 33119 insertions(+)
----------------------------------------------------------------------



[17/50] [abbrv] jclouds git commit: Fixes India regions to their actual name

Posted by na...@apache.org.
Fixes India regions to their actual name


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

Branch: refs/heads/master
Commit: 45480c49131063a4eeedc801ba53d730bafb3f01
Parents: df30057
Author: Dani Estevez <co...@danielestevez.com>
Authored: Mon May 22 13:49:59 2017 -0400
Committer: Ignasi Barrera <na...@apache.org>
Committed: Tue May 23 08:13:33 2017 +0200

----------------------------------------------------------------------
 .../main/java/org/jclouds/azurecompute/arm/domain/Region.java  | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/45480c49/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Region.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Region.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Region.java
index c7d5718..c65ae59 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Region.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Region.java
@@ -54,9 +54,9 @@ public enum Region {
    BRAZIL_SOUTH("Brazil South", "BR"),
    AUSTRALIA_EAST("Australia East", "AU-NSW"),
    AUSTRALIA_SOUTH_EAST("Australia Southeast", "AU-VIC"),
-   INDIA_CENTRAL("Central India", "IN-GA"),
-   INDIA_SOUTH("South India", "IN-TN"),
-   INDIA_WEST("West India", "IN-MH"),
+   CENTRAL_INDIA("Central India", "IN-GA"),
+   SOUTH_INDIA("South India", "IN-TN"),
+   WEST_INDIA("West India", "IN-MH"),
    CHINA_EAST("China East", "CN-SH"),
    CHINA_NORTH("China North", "CN-BJ"),
    CANADA_CENTRAL("Canada Central", "CA-ON"),


[35/50] [abbrv] jclouds git commit: Add tags to virtual network creation

Posted by na...@apache.org.
Add tags to virtual network creation


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

Branch: refs/heads/master
Commit: 8b33c4407889fdd11c06f0275a6275dcdc11f327
Parents: af79f8f
Author: Ignasi Barrera <na...@apache.org>
Authored: Mon Nov 6 09:09:30 2017 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon Nov 6 09:09:30 2017 +0100

----------------------------------------------------------------------
 .../arm/compute/strategy/CreateResourcesThenCreateNodes.java      | 2 +-
 .../org/jclouds/azurecompute/arm/features/VirtualNetworkApi.java  | 3 +++
 .../azurecompute/arm/features/VirtualNetworkApiLiveTest.java      | 2 +-
 .../azurecompute/arm/features/VirtualNetworkApiMockTest.java      | 2 +-
 .../azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java    | 2 +-
 5 files changed, 7 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/8b33c440/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
index fb832c1..e5d38fb 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
@@ -159,7 +159,7 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
          logger.debug(">> network options have not been configured. Creating network %s(%s) and subnet %s(%s)", name,
                defaultVnetAddressPrefix, name, defaultSubnetAddressPrefix);
          
-         api.getVirtualNetworkApi(options.getResourceGroup()).createOrUpdate(name, location, properties);
+         api.getVirtualNetworkApi(options.getResourceGroup()).createOrUpdate(name, location, null, properties);
          Subnet createdSubnet = api.getSubnetApi(options.getResourceGroup(), name).get(name);
          
          options.ipOptions(IpOptions.builder().subnet(createdSubnet.id()).allocateNewPublicIp(true).build());

http://git-wip-us.apache.org/repos/asf/jclouds/blob/8b33c440/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApi.java
index 1e657f3..a4237ff 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApi.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.azurecompute.arm.features;
 import java.util.List;
+import java.util.Map;
 
 import javax.inject.Named;
 import javax.ws.rs.Consumes;
@@ -31,6 +32,7 @@ import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
 import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.functions.FalseOn204;
+import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.MapBinder;
@@ -57,6 +59,7 @@ public interface VirtualNetworkApi {
    @PUT
    VirtualNetwork createOrUpdate(@PathParam("virtualnetworkname") String virtualnetworkname,
                                                @PayloadParam("location") String location,
+                                               @Nullable @PayloadParam("tags") Map<String, String> tags,
                                                @PayloadParam("properties")VirtualNetwork.VirtualNetworkProperties properties);
 
    @Named("virtualnetwork:get")

http://git-wip-us.apache.org/repos/asf/jclouds/blob/8b33c440/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApiLiveTest.java
index 4459a1e..c0271d3 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualNetworkApiLiveTest.java
@@ -55,7 +55,7 @@ public class VirtualNetworkApiLiveTest extends BaseAzureComputeApiLiveTest {
               VirtualNetwork.VirtualNetworkProperties.builder().addressSpace(
                       VirtualNetwork.AddressSpace.create(Arrays.asList(DEFAULT_VIRTUALNETWORK_ADDRESS_PREFIX))).build();
 
-      VirtualNetwork vn = api().createOrUpdate(virtualNetworkName, LOCATION, virtualNetworkProperties);
+      VirtualNetwork vn = api().createOrUpdate(virtualNetworkName, LOCATION, null, virtualNetworkProperties);
 
       assertEquals(vn.name(), virtualNetworkName);
       assertEquals(vn.location(), LOCATION);

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

http://git-wip-us.apache.org/repos/asf/jclouds/blob/8b33c440/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
index 90502fe..f439315 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
@@ -132,7 +132,7 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
       final VirtualNetwork.VirtualNetworkProperties virtualNetworkProperties =
               VirtualNetwork.VirtualNetworkProperties.create(null, null,
                       VirtualNetwork.AddressSpace.create(Arrays.asList(virtualnetworkAddressPrefix)), null);
-      VirtualNetwork virtualNetwork = api.getVirtualNetworkApi(resourceGroupName).createOrUpdate(virtualNetworkName, location, virtualNetworkProperties);
+      VirtualNetwork virtualNetwork = api.getVirtualNetworkApi(resourceGroupName).createOrUpdate(virtualNetworkName, location, null, virtualNetworkProperties);
       retry(new Predicate<String>() {
          @Override
          public boolean apply(final String name) {


[37/50] [abbrv] jclouds git commit: JCLOUDS-1342 : Azure-ARM Virtual Machine Scale Set Support

Posted by na...@apache.org.
JCLOUDS-1342 : Azure-ARM Virtual Machine Scale Set Support


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

Branch: refs/heads/master
Commit: 7368d58ad9534aaea2800860c07d311ff15d98d2
Parents: 8b33c44
Author: jucolon <ju...@microsoft.com>
Authored: Thu Aug 10 16:17:39 2017 -0400
Committer: Ignasi Barrera <na...@apache.org>
Committed: Tue Nov 21 10:20:07 2017 +0100

----------------------------------------------------------------------
 .../azurecompute/arm/AzureComputeApi.java       |  39 +-
 .../arm/AzureComputeProviderMetadata.java       |  20 +-
 .../azurecompute/arm/domain/Extension.java      |  40 ++
 .../arm/domain/ExtensionProfile.java            |  39 ++
 .../arm/domain/ExtensionProfileSettings.java    |  42 ++
 .../arm/domain/ExtensionProperties.java         |  70 +++
 .../arm/domain/NetworkInterfaceCard.java        |   3 +-
 .../domain/NetworkInterfaceCardProperties.java  |   3 +-
 .../domain/NetworkInterfaceConfiguration.java   |  44 ++
 ...NetworkInterfaceConfigurationProperties.java |  68 +++
 .../domain/NetworkSecurityGroupProperties.java  |   3 +-
 .../azurecompute/arm/domain/VirtualMachine.java |  16 +-
 .../arm/domain/VirtualMachineScaleSet.java      | 110 +++++
 .../VirtualMachineScaleSetDNSSettings.java      |  41 ++
 .../VirtualMachineScaleSetIpConfiguration.java  |  61 +++
 ...achineScaleSetIpConfigurationProperties.java | 118 +++++
 .../VirtualMachineScaleSetNetworkProfile.java   |  58 +++
 ...tualMachineScaleSetNetworkSecurityGroup.java |  39 ++
 .../domain/VirtualMachineScaleSetOSProfile.java | 277 ++++++++++++
 .../arm/domain/VirtualMachineScaleSetPlan.java  |  51 +++
 .../VirtualMachineScaleSetProperties.java       | 106 +++++
 ...ineScaleSetPublicIPAddressConfiguration.java |  59 +++
 ...achineScaleSetPublicIPAddressProperties.java |  54 +++
 .../arm/domain/VirtualMachineScaleSetSKU.java   |  45 ++
 .../VirtualMachineScaleSetUpgradeMode.java      |  35 ++
 .../VirtualMachineScaleSetUpgradePolicy.java    |  35 ++
 ...ualMachineScaleSetVirtualMachineProfile.java |  83 ++++
 .../arm/features/VirtualMachineScaleSetApi.java |  88 ++++
 .../VirtualMachineScaleSetApiLiveTest.java      | 297 ++++++++++++
 .../VirtualMachineScaleSetApiMockTest.java      | 453 +++++++++++++++++++
 .../internal/BaseAzureComputeApiMockTest.java   |   1 +
 .../src/test/resources/virtualmachine.json      |   1 -
 .../resources/virtualmachinescalesetget.json    |  64 +++
 .../virtualmachinescalesetgetwhen404.json       |   6 +
 .../resources/virtualmachinescalesetlist.json   |  93 ++++
 .../virtualmachinescalesetlistwhen404.json      |   6 +
 ...almachinescalesetresponsecreateorupdate.json | 103 +++++
 37 files changed, 2635 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index 123f6e3..8623580 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -20,27 +20,28 @@ import java.io.Closeable;
 
 import javax.ws.rs.PathParam;
 
-import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
-import org.jclouds.azurecompute.arm.features.DeploymentApi;
-import org.jclouds.azurecompute.arm.features.DiskApi;
-import org.jclouds.azurecompute.arm.features.ImageApi;
 import org.jclouds.azurecompute.arm.features.JobApi;
-import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
 import org.jclouds.azurecompute.arm.features.LocationApi;
-import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
-import org.jclouds.azurecompute.arm.features.MetricsApi;
-import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
-import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
-import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
-import org.jclouds.azurecompute.arm.features.OSImageApi;
-import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
 import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
-import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
 import org.jclouds.azurecompute.arm.features.StorageAccountApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
-import org.jclouds.azurecompute.arm.features.VMSizeApi;
-import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
 import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
+import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
+import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
+import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
+import org.jclouds.azurecompute.arm.features.VirtualMachineScaleSetApi;
+import org.jclouds.azurecompute.arm.features.VMSizeApi;
+import org.jclouds.azurecompute.arm.features.OSImageApi;
+import org.jclouds.azurecompute.arm.features.DeploymentApi;
+import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
+import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
+import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
+import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
+import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
+import org.jclouds.azurecompute.arm.features.DiskApi;
+import org.jclouds.azurecompute.arm.features.ImageApi;
+import org.jclouds.azurecompute.arm.features.MetricsApi;
+import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
 import org.jclouds.rest.annotations.Delegate;
 
 /**
@@ -125,6 +126,14 @@ public interface AzureComputeApi extends Closeable {
    VirtualMachineApi getVirtualMachineApi(@PathParam("resourceGroup") String resourceGroup);
 
    /**
+    * The Virtual Machine Scale Set API includes operations for managing the virtual machines in your subscription.
+    *
+    * @see <a href="https://msdn.microsoft.com/en-us/library/azure/mt163630.aspx">docs</a>
+    */
+   @Delegate
+   VirtualMachineScaleSetApi getVirtualMachineScaleSetApi(@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>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index eb52746..8849a1f 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -38,26 +38,27 @@ import java.net.URI;
 import java.util.Properties;
 
 import org.jclouds.azurecompute.arm.domain.Region;
-import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
 import org.jclouds.azurecompute.arm.features.DeploymentApi;
-import org.jclouds.azurecompute.arm.features.ImageApi;
-import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
 import org.jclouds.azurecompute.arm.features.LocationApi;
-import org.jclouds.azurecompute.arm.features.DiskApi;
-import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
-import org.jclouds.azurecompute.arm.features.MetricsApi;
 import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
 import org.jclouds.azurecompute.arm.features.OSImageApi;
-import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
 import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
+import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
 import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
 import org.jclouds.azurecompute.arm.features.StorageAccountApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
+import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
 import org.jclouds.azurecompute.arm.features.VMSizeApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
-import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
+import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
+import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
+import org.jclouds.azurecompute.arm.features.DiskApi;
+import org.jclouds.azurecompute.arm.features.ImageApi;
+import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
+import org.jclouds.azurecompute.arm.features.MetricsApi;
+import org.jclouds.azurecompute.arm.features.VirtualMachineScaleSetApi;
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.providers.internal.BaseProviderMetadata;
 
@@ -122,7 +123,8 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(API_VERSION_PREFIX + ImageApi.class.getSimpleName(), "2016-04-30-preview");
       properties.put(API_VERSION_PREFIX + MetricDefinitionsApi.class.getSimpleName(), "2017-05-01-preview");
       properties.put(API_VERSION_PREFIX + MetricsApi.class.getSimpleName(), "2016-09-01");
-      
+      properties.put(API_VERSION_PREFIX + VirtualMachineScaleSetApi.class.getSimpleName(), "2017-03-30");
+
       return properties;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Extension.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Extension.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Extension.java
new file mode 100644
index 0000000..5eafb04
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Extension.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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class Extension {
+
+   /**
+    * The name reference of the extension profile
+    */
+   public abstract String name();
+
+   /**
+    * The properties reference of the extension profile
+    */
+   public abstract ExtensionProperties properties();
+
+
+   @SerializedNames({"name", "properties"})
+   public static Extension create(final String name, final ExtensionProperties properties) {
+      return new AutoValue_Extension(name, properties);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProfile.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProfile.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProfile.java
new file mode 100644
index 0000000..92ab4fb
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProfile.java
@@ -0,0 +1,39 @@
+/*
+ * 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 org.jclouds.json.SerializedNames;
+
+import java.util.List;
+
+@AutoValue
+public abstract class ExtensionProfile {
+
+   /**
+    * The list of extensions of the extension profile
+    */
+   public abstract List<Extension> extensions();
+
+
+   @SerializedNames({"extensions"})
+   public static ExtensionProfile create(final List<Extension> extensions) {
+      return new AutoValue_ExtensionProfile(extensions == null ?
+         ImmutableList.<Extension>of() : ImmutableList.copyOf(extensions));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProfileSettings.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProfileSettings.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProfileSettings.java
new file mode 100644
index 0000000..265bf76
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProfileSettings.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 com.google.common.collect.ImmutableList;
+import org.jclouds.json.SerializedNames;
+
+import java.util.List;
+
+@AutoValue
+public abstract class ExtensionProfileSettings {
+
+   /**
+    * The fileUris reference of the extension profile settings
+    */
+   public abstract List<String> fileUris();
+
+   /**
+    * The commandToExecute of the extension profile settings
+    */
+   public abstract String commandToExecute();
+
+   @SerializedNames({"fileUris", "commandToExecute"})
+   public static ExtensionProfileSettings create(final List<String> fileUris, final String commandToExecute) {
+      return new AutoValue_ExtensionProfileSettings(fileUris == null ? ImmutableList.<String>of() : ImmutableList.copyOf(fileUris), commandToExecute);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProperties.java
new file mode 100644
index 0000000..d4e8b7f
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ExtensionProperties.java
@@ -0,0 +1,70 @@
+/*
+ * 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.ImmutableMap;
+import org.jclouds.json.SerializedNames;
+
+import java.util.Map;
+
+@AutoValue
+public abstract class ExtensionProperties {
+
+   /**
+    * The publisher reference of the extension properties
+    */
+   public abstract String publisher();
+
+   /**
+    * The type reference of the extension properties
+    */
+   public abstract String type();
+
+   /**
+    * The typeHandlerVersion reference of the extension properties
+    */
+   public abstract String typeHandlerVersion();
+
+   /**
+    * The autoUpgradeMinorVersion reference of the extension properties
+    */
+   public abstract Boolean autoUpgradeMinorVersion();
+
+   /**
+    * The ExtensionProfileSettings of the extension properties
+    */
+   public abstract ExtensionProfileSettings settings();
+
+   /**
+    * The list of the protectedSettings of the extension properties
+    */
+   public abstract Map<String, String> protectedSettings();
+
+   @SerializedNames({ "publisher", "type", "typeHandlerVersion",
+      "autoUpgradeMinorVersion", "settings", "protectedSettings"})
+   public static ExtensionProperties create(final String publisher, String type,
+                                            final String typeHandlerVersion,
+                                            final Boolean autoUpgradeMinorVersion,
+                                            final ExtensionProfileSettings settings,
+                                            final Map<String, String> protectedSettings) {
+      return new AutoValue_ExtensionProperties(publisher, type, typeHandlerVersion, autoUpgradeMinorVersion,
+         settings, protectedSettings == null ?
+         ImmutableMap.<String, String>of() : ImmutableMap.copyOf(protectedSettings));
+   }
+}
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCard.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCard.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCard.java
index 567addc..66bc1a3 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCard.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCard.java
@@ -51,6 +51,7 @@ public abstract class NetworkInterfaceCard {
                                              final String location,
                                              final NetworkInterfaceCardProperties properties,
                                              final Map<String, String> tags) {
-      return new AutoValue_NetworkInterfaceCard(name, id, etag, location, properties, tags == null ? null : ImmutableMap.copyOf(tags));
+      return new AutoValue_NetworkInterfaceCard(name, id, etag, location, properties,
+         tags != null ? ImmutableMap.copyOf(tags) : null);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java
index 84c8ca2..680d0a2 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java
@@ -32,7 +32,8 @@ public abstract class NetworkInterfaceCardProperties implements Provisionable {
    @Nullable public abstract List<IpConfiguration> ipConfigurations();
    @Nullable public abstract IdReference networkSecurityGroup();
 
-   @SerializedNames({"provisioningState", "resourceGuid", "enableIPForwarding", "ipConfigurations", "networkSecurityGroup"})
+   @SerializedNames({"provisioningState", "resourceGuid", "enableIPForwarding", "ipConfigurations",
+      "networkSecurityGroup"})
    public static NetworkInterfaceCardProperties create(final String provisioningState, final String resourceGuid,
          final Boolean enableIPForwarding, final List<IpConfiguration> ipConfigurations,
          final IdReference networkSecurityGroup) {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceConfiguration.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceConfiguration.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceConfiguration.java
new file mode 100644
index 0000000..b2e81b2
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceConfiguration.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+@AutoValue
+public abstract class NetworkInterfaceConfiguration {
+   /**
+    * The name of the NetworkInterfaceConfiguration
+    */
+   @Nullable
+   public abstract String name();
+
+   /**
+    * The networkConfigurationProperties of the NetworkInterfaceConfiguration
+    */
+   @Nullable
+   public abstract NetworkInterfaceConfigurationProperties networkInterfaceConfigurationProperties();
+
+   @SerializedNames({"name", "properties"})
+   public static NetworkInterfaceConfiguration create(
+      final String name, NetworkInterfaceConfigurationProperties networkInterfaceConfigurationProperties) {
+
+      return new AutoValue_NetworkInterfaceConfiguration(name, networkInterfaceConfigurationProperties);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceConfigurationProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceConfigurationProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceConfigurationProperties.java
new file mode 100644
index 0000000..85518b8
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceConfigurationProperties.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import java.util.List;
+
+
+@AutoValue
+public abstract class NetworkInterfaceConfigurationProperties {
+    /**
+     * The primary of the NetworkInterfaceConfigurationProperties
+     */
+    @Nullable
+    public abstract Boolean primary();
+
+    /**
+     * The enableAcceleratedNetworking of the NetworkInterfaceConfigurationProperties
+     */
+    @Nullable
+    public abstract Boolean enableAcceleratedNetworking();
+
+    /**
+     * The networkSecurityGroup of the NetworkInterfaceConfigurationProperties
+     */
+    @Nullable
+    public abstract VirtualMachineScaleSetNetworkSecurityGroup networkSecurityGroup();
+
+   /**
+    * The dnsSettings of the NetworkInterfaceConfigurationProperties
+    */
+   @Nullable
+   public abstract VirtualMachineScaleSetDNSSettings dnsSettings();
+
+   /**
+    * The ipConfigurations of the NetworkInterfaceConfigurationProperties
+    */
+   public abstract List<VirtualMachineScaleSetIpConfiguration> ipConfigurations();
+
+
+    @SerializedNames({"primary", "enableAcceleratedNetworking", "networkSecurityGroup", "dnsSettings", "ipConfigurations"})
+    public static NetworkInterfaceConfigurationProperties create(final Boolean primary,
+                                                               final Boolean enableAcceleratedNetworking,
+                                                               final VirtualMachineScaleSetNetworkSecurityGroup networkSecurityGroup,
+                                                               final VirtualMachineScaleSetDNSSettings dnsSettings,
+                                                               final List<VirtualMachineScaleSetIpConfiguration> ipConfigurations) {
+
+        return new AutoValue_NetworkInterfaceConfigurationProperties(primary, enableAcceleratedNetworking,
+                networkSecurityGroup, dnsSettings, ipConfigurations);
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkSecurityGroupProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkSecurityGroupProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkSecurityGroupProperties.java
index bbc2746..60fb2e6 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkSecurityGroupProperties.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkSecurityGroupProperties.java
@@ -45,7 +45,8 @@ public abstract class NetworkSecurityGroupProperties implements Provisionable {
    @Nullable
    public abstract String provisioningState();
 
-   @SerializedNames({"securityRules", "defaultSecurityRules", "networkInterfaces", "subnets", "resourceGuid", "provisioningState"})
+   @SerializedNames({"securityRules", "defaultSecurityRules", "networkInterfaces", "subnets", "resourceGuid",
+      "provisioningState"})
    public static NetworkSecurityGroupProperties create(final List<NetworkSecurityRule> securityRules,
                                           final List<NetworkSecurityRule> defaultSecurityRules,
                                           final List<NetworkInterfaceCard> networkInterfaces,

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java
index 86810e5..c0224f3 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java
@@ -60,7 +60,7 @@ public abstract class VirtualMachine {
     * Specifies the properties of the vm
     */
    public abstract VirtualMachineProperties properties();
-   
+
    /**
     * Specifies the plan, for marketplace images
     */
@@ -69,20 +69,20 @@ public abstract class VirtualMachine {
 
    @SerializedNames({"id", "name", "type", "location", "tags", "properties", "plan"})
    public static VirtualMachine create(final String id, final String name, final String type, final String location,
-         @Nullable final Map<String, String> tags, VirtualMachineProperties properties, @Nullable Plan plan) {
+                                       @Nullable final Map<String, String> tags, VirtualMachineProperties properties, @Nullable Plan plan) {
       return builder().id(id).name(name).type(type).location(location).tags(tags).properties(properties).plan(plan)
-            .build();
+         .build();
    }
-   
+
    public abstract Builder toBuilder();
-   
+
    public static Builder builder() {
       return new AutoValue_VirtualMachine.Builder();
    }
-   
+
    @AutoValue.Builder
    public abstract static class Builder {
-      
+
       public abstract Builder id(String id);
       public abstract Builder name(String name);
       public abstract Builder type(String type);
@@ -90,7 +90,7 @@ public abstract class VirtualMachine {
       public abstract Builder tags(Map<String, String> tags);
       public abstract Builder properties(VirtualMachineProperties properties);
       public abstract Builder plan(Plan plan);
-      
+
       abstract Map<String, String> tags();
 
       abstract VirtualMachine autoBuild();

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSet.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSet.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSet.java
new file mode 100644
index 0000000..2fc3f59
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSet.java
@@ -0,0 +1,110 @@
+/*
+ * 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.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import java.util.Map;
+
+/**
+ * VirtualMachineScaleSet for subscription
+ */
+@AutoValue
+public abstract class VirtualMachineScaleSet {
+
+   /**
+    * The id of the virtual machine scale set
+    */
+   @Nullable
+   public abstract String id();
+
+   /**
+    * The name of the virtual machine scale set
+    */
+   @Nullable
+   public abstract String name();
+
+   /**
+    * The location of the virtual machine scale set
+    */
+   @Nullable
+   public abstract String location();
+
+   /**
+    * Specifies the sku of the virtual machine scale set
+    */
+   public abstract VirtualMachineScaleSetSKU sku();
+
+   /**
+    * Specifies the tags of the virtual machine scale set
+    */
+   @Nullable
+   public abstract Map<String, String> tags();
+
+
+   /**
+    * Specifies the optional plan of the virtual machine scale set (only for market image)
+    */
+   @Nullable
+   public abstract VirtualMachineScaleSetPlan plan();
+
+   /**
+    * Specifies the properties of the availability set
+    */
+   @Nullable
+   public abstract VirtualMachineScaleSetProperties properties();
+
+   @SerializedNames({  "id", "name", "location", "sku", "tags", "plan", "properties"})
+   public static VirtualMachineScaleSet create(final String id, final String name, final String location,
+                                               VirtualMachineScaleSetSKU sku, final Map<String, String> tags,
+                                               VirtualMachineScaleSetPlan plan,
+                                               VirtualMachineScaleSetProperties properties) {
+      return builder().id(id).name(name).location(location).sku(sku).tags(tags)
+         .plan(plan).properties(properties)
+         .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   private static Builder builder() {
+      return new AutoValue_VirtualMachineScaleSet.Builder();
+   }
+
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder name(String name);
+      public abstract Builder location(String location);
+      public abstract Builder sku(VirtualMachineScaleSetSKU sku);
+      public abstract Builder tags(Map<String, String> tags);
+      public abstract Builder plan(VirtualMachineScaleSetPlan plan);
+      public abstract Builder properties(VirtualMachineScaleSetProperties properties);
+
+      abstract Map<String, String> tags();
+      abstract VirtualMachineScaleSet autoBuild();
+
+      public VirtualMachineScaleSet build() {
+         tags(tags() != null ? ImmutableMap.copyOf(tags()) : null);
+         return autoBuild();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetDNSSettings.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetDNSSettings.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetDNSSettings.java
new file mode 100644
index 0000000..d91c68b
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetDNSSettings.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.jclouds.json.SerializedNames;
+
+import java.util.List;
+
+/**
+ * VirtualMachineScaleSetDNSSettings
+ */
+@AutoValue
+public abstract class VirtualMachineScaleSetDNSSettings {
+   /**
+    * The list of DNS servers of the Virtual Machine Scale Set DNS Settings
+    */
+   public abstract List<String> dnsServers();
+
+   @SerializedNames({"dnsServers"})
+   public static VirtualMachineScaleSetDNSSettings create(final List<String> dnsServers) {
+
+      return new AutoValue_VirtualMachineScaleSetDNSSettings(
+         dnsServers == null ? ImmutableList.<String>of() : ImmutableList.copyOf(dnsServers));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfiguration.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfiguration.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfiguration.java
new file mode 100644
index 0000000..257072e
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfiguration.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.azurecompute.arm.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class VirtualMachineScaleSetIpConfiguration {
+
+   /**
+    * The name of the Virtual Machine Scale Set Ip Configuration
+    */
+   @Nullable
+   public abstract String name();
+
+   /**
+    * The properties of the Virtual Machine Scale Set Ip Configuration
+    */
+   @Nullable
+   public abstract VirtualMachineScaleSetIpConfigurationProperties properties();
+
+   @SerializedNames({"name", "properties"})
+   public static VirtualMachineScaleSetIpConfiguration create(
+      final String name,
+      final VirtualMachineScaleSetIpConfigurationProperties properties) {
+      return builder()
+         .name(name)
+         .properties(properties)
+         .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_VirtualMachineScaleSetIpConfiguration.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder name(String name);
+      public abstract Builder properties(VirtualMachineScaleSetIpConfigurationProperties properties);
+      public abstract VirtualMachineScaleSetIpConfiguration build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfigurationProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfigurationProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfigurationProperties.java
new file mode 100644
index 0000000..ee23152
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfigurationProperties.java
@@ -0,0 +1,118 @@
+/*
+ * 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 org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import java.util.List;
+
+@AutoValue
+public abstract class VirtualMachineScaleSetIpConfigurationProperties {
+
+   /**
+    * The public IP address configuration of the Virtual Machine Scale Set Ip Configuration Properties
+    */
+   @Nullable
+   public abstract VirtualMachineScaleSetPublicIPAddressConfiguration publicIPAddressConfiguration();
+
+   /**
+    * The subnet of the Virtual Machine Scale Set Ip Configuration Properties
+    */
+   public abstract Subnet subnet();
+
+   /**
+    * The private IP address version of the Virtual Machine Scale Set Ip Configuration Properties
+    */
+   @Nullable
+   public abstract String privateIPAddressVersion();
+
+   /**
+    * The load balancer backend address pools of the Virtual Machine Scale Set Ip Configuration Properties
+    */
+   public abstract List<IdReference> loadBalancerBackendAddressPools();
+
+   /**
+    * The load balancer inbound nat pools of the Virtual Machine Scale Set Ip Configuration Properties
+    */
+   public abstract List<IdReference> loadBalancerInboundNatPools();
+
+   /**
+    * The application gateway backend address Pools of the Virtual Machine Scale Set Ip Configuration Properties
+    */
+   @Nullable
+   public abstract String applicationGatewayBackendAddressPools();
+
+   @SerializedNames({"publicIPAddressConfiguration", "subnet", "privateIPAddressVersion",
+      "loadBalancerBackendAddressPools", "loadBalancerInboundNatPools", "applicationGatewayBackendAddressPools"})
+   public static VirtualMachineScaleSetIpConfigurationProperties create(
+      final VirtualMachineScaleSetPublicIPAddressConfiguration publicIPAddressConfiguration,
+      final Subnet subnet,
+      final String privateIPAddressVersion,
+      final List<IdReference> loadBalancerBackendAddressPools,
+      final List<IdReference> loadBalancerInboundNatPools,
+      final String applicationGatewayBackendAddressPools)
+
+   {
+
+      return builder()
+         .publicIPAddressConfiguration(publicIPAddressConfiguration)
+         .subnet(subnet)
+         .privateIPAddressVersion(privateIPAddressVersion)
+         .lbBackendAddressPools(loadBalancerBackendAddressPools)
+         .lbInboundNatPools(loadBalancerInboundNatPools)
+         .applicationGatewayBackendAddressPools(applicationGatewayBackendAddressPools)
+         .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_VirtualMachineScaleSetIpConfigurationProperties.Builder()
+              .lbBackendAddressPools(null)
+              .lbInboundNatPools(null);
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder publicIPAddressConfiguration(VirtualMachineScaleSetPublicIPAddressConfiguration publicIPAddressConfiguration);
+
+      public abstract Builder subnet(Subnet subnet);
+
+      public abstract Builder loadBalancerBackendAddressPools(List<IdReference> loadBalancerBackendAddressPools);
+
+      public abstract Builder loadBalancerInboundNatPools(List<IdReference> loadBalancerInboundNatPools);
+
+      public abstract Builder privateIPAddressVersion(String privateIPAddressVersion);
+
+      public Builder lbBackendAddressPools(List<IdReference> loadBalancerBackendAddressPools) {
+         return loadBalancerBackendAddressPools(loadBalancerBackendAddressPools != null ? ImmutableList
+                 .copyOf(loadBalancerBackendAddressPools) : ImmutableList.<IdReference>of());
+      }
+      public Builder lbInboundNatPools(List<IdReference> loadBalancerInboundNatPools) {
+         return loadBalancerInboundNatPools(loadBalancerInboundNatPools != null ? ImmutableList
+         .copyOf(loadBalancerInboundNatPools) : ImmutableList.<IdReference>of());
+      }
+
+      public abstract Builder applicationGatewayBackendAddressPools(String applicationGatewayBackendAddressPools);
+      public abstract VirtualMachineScaleSetIpConfigurationProperties build();
+
+   }
+}
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetNetworkProfile.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetNetworkProfile.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetNetworkProfile.java
new file mode 100644
index 0000000..9d4c462
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetNetworkProfile.java
@@ -0,0 +1,58 @@
+/*
+ * 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 org.jclouds.json.SerializedNames;
+
+import java.util.List;
+
+@AutoValue
+public abstract class VirtualMachineScaleSetNetworkProfile {
+
+   /**
+    * The network interface configurations of the Virtual Machine Scale Set Network Profile
+    */
+   public abstract List<NetworkInterfaceConfiguration> networkInterfaceConfigurations();
+
+
+   @SerializedNames({"networkInterfaceConfigurations"})
+   public static VirtualMachineScaleSetNetworkProfile create(
+      final List<NetworkInterfaceConfiguration> networkInterfaceConfigurations) {
+         return builder()
+            .networkInterfaceConfigurations(networkInterfaceConfigurations == null ?
+               ImmutableList.<NetworkInterfaceConfiguration>of() : ImmutableList.copyOf(networkInterfaceConfigurations) )
+            .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_VirtualMachineScaleSetNetworkProfile.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+
+      public abstract Builder networkInterfaceConfigurations(
+         List<NetworkInterfaceConfiguration> networkInterfaceConfigurations);
+
+      public abstract VirtualMachineScaleSetNetworkProfile build();
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetNetworkSecurityGroup.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetNetworkSecurityGroup.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetNetworkSecurityGroup.java
new file mode 100644
index 0000000..8874d50
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetNetworkSecurityGroup.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+/**
+ * Virtual Machine Scale Set Network Security Group
+ */
+@AutoValue
+public abstract class VirtualMachineScaleSetNetworkSecurityGroup {
+   /**
+    * The id of the Virtual Machine Scale Set Network Security Group
+    */
+   @Nullable
+   public abstract String id();
+
+   @SerializedNames({"id"})
+   public static VirtualMachineScaleSetNetworkSecurityGroup create(final String id) {
+
+      return new AutoValue_VirtualMachineScaleSetNetworkSecurityGroup(id);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetOSProfile.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetOSProfile.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetOSProfile.java
new file mode 100644
index 0000000..5593457
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetOSProfile.java
@@ -0,0 +1,277 @@
+/*
+ * 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 org.jclouds.azurecompute.arm.util.GetEnumValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import java.util.List;
+
+@AutoValue
+public abstract class VirtualMachineScaleSetOSProfile {
+
+   @AutoValue
+   public abstract static class LinuxConfiguration {
+
+
+      @AutoValue
+      public abstract static class SSH {
+
+         @AutoValue
+         public abstract static class SSHPublicKey {
+
+            /**
+             * The path for the SSH public key
+             */
+            @Nullable
+            public abstract String path();
+
+            /**
+             * The key data for the SSH public key
+             */
+            @Nullable
+            public abstract String keyData();
+
+            @SerializedNames({"path", "keyData"})
+            public static SSHPublicKey create(final String path, final String keyData) {
+
+               return new AutoValue_VirtualMachineScaleSetOSProfile_LinuxConfiguration_SSH_SSHPublicKey(
+                  path, keyData);
+            }
+         }
+
+         /**
+          * The list of public keys and paths
+          */
+         @Nullable
+         public abstract List<SSHPublicKey> publicKeys();
+
+         @SerializedNames({"publicKeys"})
+         public static SSH create(final List<SSHPublicKey> publicKeys) {
+
+            return new AutoValue_VirtualMachineScaleSetOSProfile_LinuxConfiguration_SSH(
+               publicKeys);
+         }
+      }
+
+      /**
+       * The authentication method password or ssh
+       */
+      public abstract Boolean disablePasswordAuthentication();
+
+      /**
+       * ssh keys
+       */
+      @Nullable
+      public abstract SSH ssh();
+
+      @SerializedNames({"disablePasswordAuthentication", "ssh"})
+      public static LinuxConfiguration create(final Boolean disablePasswordAuthentication,
+                                              final SSH ssh) {
+
+         return new AutoValue_VirtualMachineScaleSetOSProfile_LinuxConfiguration(disablePasswordAuthentication,
+            ssh);
+      }
+   }
+
+   @AutoValue
+   public abstract static class WindowsConfiguration {
+
+      @AutoValue
+      public abstract static class WinRM {
+         public enum Protocol {
+
+            HTTP("http"),
+            HTTPS("https"),
+            UNRECOGNIZED("Unrecognized");
+
+            private String value;
+
+            Protocol(String value) {
+               this.value = value;
+            }
+
+            public static Protocol fromValue(String value) {
+               return (Protocol) GetEnumValue.fromValueOrDefault(value, Protocol.UNRECOGNIZED);
+            }
+
+            @Override
+            public String toString() {
+               return this.value;
+            }
+         }
+
+         @AutoValue
+         public abstract static class ProtocolListener {
+
+            /**
+             * The protocol for the protcol listener
+             */
+            public abstract Protocol protocol();
+
+            /**
+             * The certificate url or the protcol listener
+             */
+            @Nullable
+            public abstract String certificateUrl();
+
+            @SerializedNames({"protocol", "certificateUrl"})
+            public static ProtocolListener create(final Protocol protocol, final String certificateUrl) {
+
+               return new AutoValue_VirtualMachineScaleSetOSProfile_WindowsConfiguration_WinRM_ProtocolListener(
+                  protocol, certificateUrl);
+            }
+         }
+
+         /**
+          * Map of different settings
+          */
+         public abstract List<ProtocolListener> listeners();
+
+         @SerializedNames({"listeners"})
+         public static WinRM create(final List<ProtocolListener> listeners) {
+            return new AutoValue_VirtualMachineScaleSetOSProfile_WindowsConfiguration_WinRM(listeners == null ? ImmutableList.<ProtocolListener>of() : ImmutableList.copyOf(listeners));
+         }
+      }
+
+      @AutoValue
+      public abstract static class AdditionalUnattendContent {
+
+         public abstract String pass();
+
+         public abstract String component();
+
+         public abstract String settingName();
+
+         public abstract String content();
+
+         @SerializedNames({"pass", "component", "settingName", "content"})
+         public static AdditionalUnattendContent create(final String pass, final String component,
+                                                        final String settingName,
+                                                        final String content) {
+
+            return new AutoValue_VirtualMachineScaleSetOSProfile_WindowsConfiguration_AdditionalUnattendContent(
+               pass, component, settingName, content);
+         }
+      }
+
+      /**
+       * The provision VM Agent true of false.
+       */
+      public abstract boolean provisionVMAgent();
+
+      /**
+       * winRM
+       */
+      @Nullable
+      public abstract WinRM winRM();
+
+      /**
+       * unattend content
+       */
+      public abstract List<AdditionalUnattendContent> additionalUnattendContent();
+
+      /**
+       * is automatic updates enabled
+       */
+      public abstract boolean enableAutomaticUpdates();
+
+      @SerializedNames({"provisionVMAgent", "winRM", "additionalUnattendContent", "enableAutomaticUpdates"})
+      public static WindowsConfiguration create(final boolean provisionVMAgent, final WinRM winRM,
+                                                final List<AdditionalUnattendContent> additionalUnattendContent,
+                                                final boolean enableAutomaticUpdates) {
+
+         return new AutoValue_VirtualMachineScaleSetOSProfile_WindowsConfiguration(provisionVMAgent, winRM,
+            additionalUnattendContent == null ? ImmutableList.<AdditionalUnattendContent>of() : ImmutableList.copyOf(additionalUnattendContent), enableAutomaticUpdates);
+      }
+   }
+
+   /**
+    * The computer name of the VM
+    */
+   @Nullable
+   public abstract String computerNamePrefix();
+
+   /**
+    * The admin username of the VM
+    */
+   @Nullable
+   public abstract String adminUsername();
+
+   /**
+    * The admin password of the VM
+    */
+   @Nullable
+   public abstract String adminPassword();
+
+   /**
+    * The linux configuration of the VM
+    */
+   @Nullable
+   public abstract LinuxConfiguration linuxConfiguration();
+
+   /**
+    * The windows configuration of the VM
+    */
+   @Nullable
+   public abstract WindowsConfiguration windowsConfiguration();
+
+   /**
+    * The Secrets configuration of the VM
+    */
+   public abstract List<Secrets> secrets();
+
+   @SerializedNames({"computerNamePrefix", "adminUsername", "adminPassword", "linuxConfiguration",
+      "windowsConfiguration", "secrets"})
+   public static VirtualMachineScaleSetOSProfile create(final String computerNamePrefix, final String adminUsername,
+                                                        final String adminPassword, final LinuxConfiguration linuxConfiguration,
+                                                        final WindowsConfiguration windowsConfiguration, final List<Secrets> secrets) {
+      return builder()
+         .computerNamePrefix(computerNamePrefix)
+         .adminUsername(adminUsername)
+         .adminPassword(adminPassword)
+         .linuxConfiguration(linuxConfiguration)
+         .windowsConfiguration(windowsConfiguration)
+         ._secrets(secrets)
+         .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_VirtualMachineScaleSetOSProfile.Builder()._secrets(null);
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder computerNamePrefix(String computerNamePrefix);
+      public abstract Builder adminUsername(String adminUsername);
+      public abstract Builder adminPassword(String adminPassword);
+      public abstract Builder linuxConfiguration(LinuxConfiguration linuxConfiguration);
+      public abstract Builder windowsConfiguration(WindowsConfiguration windowsConfiguration);
+      public abstract Builder secrets(List<Secrets> secrets);
+
+      public Builder _secrets(List<Secrets> secrets) {
+         return secrets(secrets != null ? ImmutableList.copyOf(secrets) : ImmutableList.<Secrets>of());
+      }
+
+      public abstract VirtualMachineScaleSetOSProfile build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPlan.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPlan.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPlan.java
new file mode 100644
index 0000000..1864ca7
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPlan.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 VirtualMachineScaleSetPlan {
+   /**
+    * The name of the Virtual Machine Scale Set Plan
+    */
+   @Nullable
+   public abstract String name();
+
+   /**
+    * The publisher of the Virtual Machine Scale Set Plan
+    */
+   @Nullable
+   public abstract String publisher();
+
+   /**
+    * The product of the Virtual Machine Scale Set Plan
+    */
+   @Nullable
+   public abstract String product();
+
+   @SerializedNames({"name", "publisher", "product"})
+   public static VirtualMachineScaleSetPlan create(final String name, final String publisher, final String product) {
+
+      return new AutoValue_VirtualMachineScaleSetPlan(name, publisher, product);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetProperties.java
new file mode 100644
index 0000000..d737086
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetProperties.java
@@ -0,0 +1,106 @@
+/*
+ * 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.util.GetEnumValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+
+@AutoValue
+public abstract class VirtualMachineScaleSetProperties {
+
+   public enum ProvisioningState {
+      ACCEPTED,
+      CREATING,
+      READY,
+      CANCELED,
+      FAILED,
+      DELETED,
+      SUCCEEDED,
+      RUNNING,
+      UPDATING,
+      UNRECOGNIZED;
+
+      public static ProvisioningState fromValue(final String text) {
+         return (ProvisioningState) GetEnumValue.fromValueOrDefault(text, ProvisioningState.UNRECOGNIZED);
+      }
+   }
+
+   /**
+    * The singlePlacementGroup of the VirtualMachineScaleSetProperties
+    */
+   @Nullable
+   public abstract Boolean singlePlacementGroup();
+
+   /**
+    * Specifies the over provision of the virtual machine scale set
+    */
+   @Nullable
+   public abstract Boolean overProvision();
+
+   /**
+    * Specifies the upgrade policy of the virtual machine scale set
+    */
+   public abstract VirtualMachineScaleSetUpgradePolicy upgradePolicy();
+
+   /**
+    * Specifies the state of the provision of the virtual machine scale set
+    */
+   @Nullable
+   public abstract ProvisioningState provisioningState();
+
+   /**
+    * Specifies the virtual machine profile of the virtual machine scale set
+    */
+   public abstract VirtualMachineScaleSetVirtualMachineProfile virtualMachineProfile();
+
+   @SerializedNames({"singlePlacementGroup", "overProvision", "upgradePolicy", "provisioningState", "virtualMachineProfile"})
+   public static VirtualMachineScaleSetProperties create(
+           final Boolean singlePlacementGroup,
+           final Boolean overProvision,
+           final VirtualMachineScaleSetUpgradePolicy upgradePolicy,
+           final ProvisioningState provisioningState,
+           final VirtualMachineScaleSetVirtualMachineProfile virtualMachineProfile) {
+      return builder().singlePlacementGroup(singlePlacementGroup).overProvision(overProvision).
+              upgradePolicy(upgradePolicy).provisioningState(provisioningState).virtualMachineProfile(virtualMachineProfile).build();
+   }
+
+   public abstract Builder toBuilder();
+
+   private static Builder builder() {
+      return new AutoValue_VirtualMachineScaleSetProperties.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder singlePlacementGroup(Boolean singlePlacementGroup);
+
+      public abstract Builder overProvision(Boolean overProvision);
+
+      public abstract Builder upgradePolicy(VirtualMachineScaleSetUpgradePolicy upgradePolicy);
+
+      public abstract Builder provisioningState(ProvisioningState provisioningState);
+
+      public abstract Builder virtualMachineProfile(VirtualMachineScaleSetVirtualMachineProfile virtualMachineProfile);
+
+      public abstract VirtualMachineScaleSetProperties build();
+   }
+}
+
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPublicIPAddressConfiguration.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPublicIPAddressConfiguration.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPublicIPAddressConfiguration.java
new file mode 100644
index 0000000..3347713
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPublicIPAddressConfiguration.java
@@ -0,0 +1,59 @@
+/*
+ * 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 VirtualMachineScaleSetPublicIPAddressConfiguration {
+
+   /**
+    * The name of the Virtual Machine Scale Set Public IP Address Configuration
+    */
+   public abstract String name();
+
+   /**
+    * The properties of the Virtual Machine Scale Set Public IP Address Configuration
+    */
+   public abstract VirtualMachineScaleSetPublicIPAddressProperties properties();
+
+   @SerializedNames({ "name",  "properties" })
+   public static VirtualMachineScaleSetPublicIPAddressConfiguration create(
+      String name,
+      VirtualMachineScaleSetPublicIPAddressProperties properties) {
+         return builder().name(name).properties(properties).build();
+   }
+
+   VirtualMachineScaleSetPublicIPAddressConfiguration() {
+
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_VirtualMachineScaleSetPublicIPAddressConfiguration.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder name(String name);
+      public abstract Builder properties(VirtualMachineScaleSetPublicIPAddressProperties properties);
+      public abstract VirtualMachineScaleSetPublicIPAddressConfiguration build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPublicIPAddressProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPublicIPAddressProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPublicIPAddressProperties.java
new file mode 100644
index 0000000..d01e305
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetPublicIPAddressProperties.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class VirtualMachineScaleSetPublicIPAddressProperties  {
+
+   /**
+    * The idle timeout (in minutes) of the Virtual Machine Scale Set Public IP Address Configuration
+    */
+   @Nullable
+   public abstract Integer idleTimeoutInMinutes();
+
+
+   @SerializedNames({ "idleTimeoutInMinutes" })
+   public static VirtualMachineScaleSetPublicIPAddressProperties create(final Integer idleTimeoutInMinutes) {
+      return builder()
+         .idleTimeoutInMinutes(idleTimeoutInMinutes)
+         .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_VirtualMachineScaleSetPublicIPAddressProperties.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+
+      public abstract Builder idleTimeoutInMinutes(Integer idleTimeoutInMinutes);
+
+      public abstract VirtualMachineScaleSetPublicIPAddressProperties build();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetSKU.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetSKU.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetSKU.java
new file mode 100644
index 0000000..251562d
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetSKU.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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+
+@AutoValue
+public abstract class VirtualMachineScaleSetSKU {
+   /**
+    * The name of the Virtual Machine Scale Set SKU
+    */
+   public abstract String name();
+
+   /**
+    * The tier of the Virtual Machine Scale Set SKU
+    */
+   public abstract String tier();
+
+   /**
+    * The capacity of the Virtual Machine Scale Set SKU
+    */
+   public abstract int capacity();
+
+   @SerializedNames({"name", "tier", "capacity"})
+   public static VirtualMachineScaleSetSKU create(final String name, final String tier, final int capacity) {
+
+      return new AutoValue_VirtualMachineScaleSetSKU(name, tier, capacity);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetUpgradeMode.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetUpgradeMode.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetUpgradeMode.java
new file mode 100644
index 0000000..cca007f
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetUpgradeMode.java
@@ -0,0 +1,35 @@
+/*
+ * 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 VirtualMachineScaleSetUpgradeMode {
+   /**
+    * VirtualMachineScaleSetUpgradeMode
+    * **/
+   public enum Status {
+      Manual,
+      Automatic,
+      Unrecognized;
+
+      public static Status fromValue(final String text) {
+         return (Status) GetEnumValue.fromValueOrDefault(text, Status.Unrecognized);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetUpgradePolicy.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetUpgradePolicy.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetUpgradePolicy.java
new file mode 100644
index 0000000..6945e81
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetUpgradePolicy.java
@@ -0,0 +1,35 @@
+/*
+ * 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 VirtualMachineScaleSetUpgradePolicy {
+   /**
+    * The mode of the Virtual Machine Scale Set Upgrade Policy
+    */
+   public abstract String mode();
+
+   @SerializedNames({"mode"})
+   public static VirtualMachineScaleSetUpgradePolicy create(final String mode) {
+
+      return new AutoValue_VirtualMachineScaleSetUpgradePolicy(mode);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetVirtualMachineProfile.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetVirtualMachineProfile.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetVirtualMachineProfile.java
new file mode 100644
index 0000000..a238467
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetVirtualMachineProfile.java
@@ -0,0 +1,83 @@
+/*
+ * 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 virtual machine properties for the virtual machine.
+ */
+@AutoValue
+public abstract class VirtualMachineScaleSetVirtualMachineProfile {
+
+   /**
+    * The storage profile of the Virtual Machine Scale Set Virtual Machine Profile.
+    */
+   public abstract StorageProfile storageProfile();
+
+   /**
+    * The OS profile of the Virtual Machine Scale Set Virtual Machine Profile.
+    */
+   public abstract VirtualMachineScaleSetOSProfile osProfile();
+
+   /**
+    * The network profile of the Virtual Machine Scale Set Virtual Machine Profile
+    */
+   public abstract VirtualMachineScaleSetNetworkProfile networkProfile();
+
+   /**
+    * The extension profile of the Virtual Machine Scale Set Virtual Machine Profile .
+    */
+   public abstract ExtensionProfile extensionProfile();
+
+
+
+   @SerializedNames({"storageProfile", "osProfile", "networkProfile", "extensionProfile"})
+   public static VirtualMachineScaleSetVirtualMachineProfile create(
+      final StorageProfile storageProfile,
+      final VirtualMachineScaleSetOSProfile osProfile,
+      final VirtualMachineScaleSetNetworkProfile networkProfile,
+      final ExtensionProfile extensionProfile) {
+         return builder()
+            .storageProfile(storageProfile)
+            .osProfile(osProfile)
+            .networkProfile(networkProfile)
+            .extensionProfile(extensionProfile)
+            .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_VirtualMachineScaleSetVirtualMachineProfile.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+
+      public abstract Builder storageProfile(StorageProfile storageProfile);
+
+      public abstract Builder osProfile(VirtualMachineScaleSetOSProfile osProfile);
+
+      public abstract Builder networkProfile(VirtualMachineScaleSetNetworkProfile networkProfile);
+
+      public abstract Builder extensionProfile(ExtensionProfile extensionProfile);
+
+      public abstract VirtualMachineScaleSetVirtualMachineProfile build();
+   }
+}


[04/50] [abbrv] jclouds git commit: Initial support ManagedDataDisks

Posted by na...@apache.org.
Initial support ManagedDataDisks

- add DiskApi + tests
- add ImageApi + tests
- add TemplateOptions.dataDisks
- use dataDisks in adapter
- fix CreateOptions enum usage
- fix VirtualMachineApiMockTest


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

Branch: refs/heads/master
Commit: 37dcb87dfa261ab42f91f304eaf7ed8c6ecd7635
Parents: c45728e
Author: Andrea Turli <an...@gmail.com>
Authored: Thu Feb 23 14:52:41 2017 +0100
Committer: Andrea Turli <an...@gmail.com>
Committed: Tue Apr 11 11:45:18 2017 +0200

----------------------------------------------------------------------
 .../azurecompute/arm/AzureComputeApi.java       |  18 +-
 .../arm/AzureComputeProviderMetadata.java       |  11 +-
 .../arm/compute/AzureComputeServiceAdapter.java | 218 ++++++++++---------
 .../arm/compute/functions/VMImageToImage.java   |  15 +-
 .../compute/options/AzureTemplateOptions.java   | 100 ++++++---
 .../CreateResourceGroupThenCreateNodes.java     |  92 +-------
 .../azurecompute/arm/domain/CreationData.java   |  54 +++++
 .../azurecompute/arm/domain/DataDisk.java       |  98 +++++++--
 .../jclouds/azurecompute/arm/domain/Disk.java   | 105 +++++++++
 .../azurecompute/arm/domain/DiskProperties.java |  78 +++++++
 .../jclouds/azurecompute/arm/domain/Image.java  |  73 +++++++
 .../arm/domain/ImageProperties.java             |  70 ++++++
 .../azurecompute/arm/domain/ImageReference.java |  20 +-
 .../arm/domain/ManagedDiskParameters.java       |  65 ++++++
 .../jclouds/azurecompute/arm/domain/OSDisk.java |  18 +-
 .../azurecompute/arm/features/DiskApi.java      |  81 +++++++
 .../azurecompute/arm/features/ImageApi.java     |  81 +++++++
 .../azurecompute/arm/features/OSImageApi.java   |   5 +-
 .../jclouds/azurecompute/arm/util/VMImages.java |  27 +++
 .../arm/features/DiskApiLiveTest.java           | 107 +++++++++
 .../arm/features/DiskApiMockTest.java           | 141 ++++++++++++
 .../arm/features/ImageApiLiveTest.java          | 105 +++++++++
 .../arm/features/VirtualMachineApiLiveTest.java |  25 ++-
 .../arm/features/VirtualMachineApiMockTest.java |  50 ++---
 .../arm/internal/AzureLiveTestUtils.java        |   8 +-
 .../src/test/resources/creatediskresponse.json  |  11 +
 .../src/test/resources/getdisk.json             |  19 ++
 .../src/test/resources/image.json               |  43 ++++
 .../src/test/resources/listdisks.json           |  23 ++
 29 files changed, 1466 insertions(+), 295 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index 3700069..51ed402 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -22,9 +22,11 @@ import javax.ws.rs.PathParam;
 
 import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
 import org.jclouds.azurecompute.arm.features.DeploymentApi;
+import org.jclouds.azurecompute.arm.features.ImageApi;
 import org.jclouds.azurecompute.arm.features.JobApi;
 import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
 import org.jclouds.azurecompute.arm.features.LocationApi;
+import org.jclouds.azurecompute.arm.features.DiskApi;
 import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
@@ -37,7 +39,6 @@ import org.jclouds.azurecompute.arm.features.SubnetApi;
 import org.jclouds.azurecompute.arm.features.VMSizeApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
 import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
-
 import org.jclouds.rest.annotations.Delegate;
 
 /**
@@ -189,4 +190,19 @@ public interface AzureComputeApi extends Closeable {
    @Delegate
    ResourceProviderApi getResourceProviderApi();
 
+   /**
+    * The ManagedDataDisk API includes operations for managing data disks within your subscription.
+    *
+    * @see <a href="https://docs.microsoft.com/en-us/rest/api/manageddisks/disks/disks-rest-api">docs</a>
+    */
+   @Delegate
+   DiskApi getDiskApi(@PathParam("resourcegroup") String resourcegroup);
+
+   /**
+    * The virtual machine image API includes operations for managing data disks within your subscription.
+    *
+    * @see <a href="https://docs.microsoft.com/en-us/rest/api/manageddisks/images/images-rest-api">docs</a>
+    */
+   @Delegate
+   ImageApi getVirtualMachineImageApi(@PathParam("resourcegroup") String resourcegroup);
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index 08979b7..3bf1ab3 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -23,8 +23,10 @@ import java.util.Properties;
 import org.jclouds.azurecompute.arm.domain.Region;
 import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
 import org.jclouds.azurecompute.arm.features.DeploymentApi;
+import org.jclouds.azurecompute.arm.features.ImageApi;
 import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
 import org.jclouds.azurecompute.arm.features.LocationApi;
+import org.jclouds.azurecompute.arm.features.DiskApi;
 import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
@@ -109,14 +111,11 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(API_VERSION_PREFIX + SubnetApi.class.getSimpleName(), "2015-06-15");
       properties.put(API_VERSION_PREFIX + VirtualNetworkApi.class.getSimpleName(), "2015-06-15");
       properties.put(API_VERSION_PREFIX + VMSizeApi.class.getSimpleName(), "2015-06-15");
-      properties.put(API_VERSION_PREFIX + VirtualMachineApi.class.getSimpleName(), "2015-06-15");
+      properties.put(API_VERSION_PREFIX + VirtualMachineApi.class.getSimpleName(), "2016-04-30-preview");
       properties.put(API_VERSION_PREFIX + LoadBalancerApi.class.getSimpleName(), "2016-03-30");
       properties.put(API_VERSION_PREFIX + AvailabilitySetApi.class.getSimpleName(), "2016-03-30");
-      properties.put(API_VERSION_PREFIX + "GetVirtualMachine", "2016-03-30");
-      properties.put(API_VERSION_PREFIX + "GetVirtualMachineInstance", "2016-03-30");
-      properties.put(API_VERSION_PREFIX + "CreateOrUpdateVirtualMachine", "2016-03-30");
-      properties.put(API_VERSION_PREFIX + "ListVirtualMachines", "2015-06-15");
-      properties.put(API_VERSION_PREFIX + "DeleteVirtualMachine", "2016-03-30");
+      properties.put(API_VERSION_PREFIX + DiskApi.class.getSimpleName(), "2017-03-30");
+      properties.put(API_VERSION_PREFIX + ImageApi.class.getSimpleName(), "2016-04-30-preview");
       
       return properties;
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 572e2be..e79c50d 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -16,23 +16,10 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.contains;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.find;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
-import static org.jclouds.util.Closeables2.closeQuietly;
-
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 import javax.annotation.Resource;
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -42,6 +29,8 @@ import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources;
+import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
+import org.jclouds.azurecompute.arm.domain.CreationData;
 import org.jclouds.azurecompute.arm.domain.DataDisk;
 import org.jclouds.azurecompute.arm.domain.HardwareProfile;
 import org.jclouds.azurecompute.arm.domain.IdReference;
@@ -49,6 +38,7 @@ import org.jclouds.azurecompute.arm.domain.ImageReference;
 import org.jclouds.azurecompute.arm.domain.IpConfiguration;
 import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
 import org.jclouds.azurecompute.arm.domain.Location;
+import org.jclouds.azurecompute.arm.domain.ManagedDiskParameters;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
 import org.jclouds.azurecompute.arm.domain.NetworkProfile;
@@ -66,7 +56,6 @@ import org.jclouds.azurecompute.arm.domain.StorageProfile;
 import org.jclouds.azurecompute.arm.domain.StorageService;
 import org.jclouds.azurecompute.arm.domain.StorageService.Status;
 import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
-import org.jclouds.azurecompute.arm.domain.VHD;
 import org.jclouds.azurecompute.arm.domain.VMHardware;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VMSize;
@@ -97,6 +86,23 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.ImmutableList.builder;
+import static com.google.common.collect.ImmutableList.of;
+import static com.google.common.collect.Iterables.contains;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.find;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
+import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
+import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
+import static org.jclouds.util.Closeables2.closeQuietly;
+
 /**
  * Defines the connection between the {@link AzureComputeApi} implementation and
  * the jclouds {@link org.jclouds.compute.ComputeService}.
@@ -105,11 +111,11 @@ import com.google.common.collect.Lists;
 public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location> {
 
    public static final String GROUP_KEY = "jclouds_group";
-   
+
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
-   
+
    private final CleanupResources cleanupResources;
    private final AzureComputeApi api;
    private final List<String> imagePublishers;
@@ -119,8 +125,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
 
    @Inject
    AzureComputeServiceAdapter(final AzureComputeApi api, @Named(IMAGE_PUBLISHERS) String imagePublishers,
-         CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
-         PublicIpAvailablePredicateFactory publicIpAvailable, LoadingCache<String, ResourceGroup> resourceGroupMap) {
+                              CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
+                              PublicIpAvailablePredicateFactory publicIpAvailable, LoadingCache<String, ResourceGroup> resourceGroupMap) {
       this.api = api;
       this.imagePublishers = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(imagePublishers);
       this.cleanupResources = cleanupResources;
@@ -130,35 +136,32 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    }
 
    @Override
-   public NodeAndInitialCredentials<VirtualMachine> createNodeWithGroupEncodedIntoName(final String group,
-         final String name, final Template template) {
-
-      AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(template.getLocation().getId());
-
-      // TODO ARM specific options
-      // TODO network ids => createOrUpdate one nic in each network
-      
-      IdReference availabilitySet = null;
-      if (templateOptions.getAvailabilitySet() != null) {
-         availabilitySet = IdReference.create(templateOptions.getAvailabilitySet().id());
-      }
+   public NodeAndInitialCredentials<VirtualMachine> createNodeWithGroupEncodedIntoName(final String group, final String name, final Template template) {
+      // TODO network ids => create one nic in each network
 
       String locationName = template.getLocation().getId();
+      Image image = template.getImage();
+      String hardwareId = template.getHardware().getId();
+      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(locationName);
+      // TODO ARM specific options
+      AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class);
       String subnetId = templateOptions.getSubnetId();
-      NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName, resourceGroup.name(),
-            template.getOptions());
-      StorageProfile storageProfile = createStorageProfile(name, template.getImage(), templateOptions.getBlob());
-      HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(template.getHardware().getId()).build();
+      
+      IdReference availabilitySet = getAvailabilitySetIdReference(templateOptions.getAvailabilitySet());
+      StorageProfile storageProfile = createStorageProfile(image, templateOptions.getDataDisks());
+      NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName, resourceGroup.name(), template.getOptions());
+      HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(hardwareId).build();
       OSProfile osProfile = createOsProfile(name, template);
-      NetworkProfile networkProfile = NetworkProfile.builder()
-            .networkInterfaces(ImmutableList.of(IdReference.create(nic.id()))).build();
+      NetworkProfile networkProfile = NetworkProfile.builder().networkInterfaces(of(IdReference.create(nic.id()))).build();
       VirtualMachineProperties virtualMachineProperties = VirtualMachineProperties.builder()
-            .licenseType(null) // TODO
-            .availabilitySet(availabilitySet)
-            .hardwareProfile(hardwareProfile).storageProfile(storageProfile).osProfile(osProfile)
-            .networkProfile(networkProfile).build();
-      
+              .licenseType(null) // TODO
+              .availabilitySet(availabilitySet)
+              .hardwareProfile(hardwareProfile)
+              .storageProfile(storageProfile)
+              .osProfile(osProfile)
+              .networkProfile(networkProfile)
+              .build();
+
       // Store group apart from the name to be able to identify nodes with
       // custom names in the configured group
       template.getOptions().getUserMetadata().put(GROUP_KEY, group);
@@ -171,7 +174,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       // Safe to pass null credentials here, as jclouds will default populate
       // the node with the default credentials from the image, or the ones in
       // the options, if provided.
-      RegionAndId regionAndId = RegionAndId.fromRegionAndId(template.getLocation().getId(), name);
+      RegionAndId regionAndId = RegionAndId.fromRegionAndId(locationName, name);
       return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, regionAndId.slashEncode(), null);
    }
 
@@ -182,9 +185,9 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
          Iterable<VMSize> vmSizes = api.getVMSizeApi(location.name()).list();
          for (VMSize vmSize : vmSizes) {
             VMHardware hwProfile = VMHardware
-                  .create(vmSize.name(), vmSize.numberOfCores(), vmSize.osDiskSizeInMB(),
-                        vmSize.resourceDiskSizeInMB(), vmSize.memoryInMB(), vmSize.maxDataDiskCount(), location.name(),
-                        false);
+                    .create(vmSize.name(), vmSize.numberOfCores(), vmSize.osDiskSizeInMB(),
+                            vmSize.resourceDiskSizeInMB(), vmSize.memoryInMB(), vmSize.maxDataDiskCount(), location.name(),
+                            false);
             hwProfiles.add(hwProfile);
          }
       }
@@ -204,8 +207,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
             for (Version version : versionList) {
                Version versionDetails = osImageApi.getVersion(publisherName, offer.name(), sku.name(), version.name());
                VMImage vmImage = VMImage.azureImage().publisher(publisherName).offer(offer.name()).sku(sku.name())
-                     .version(versionDetails.name()).location(location).versionProperties(versionDetails.properties())
-                     .build();
+                       .version(versionDetails.name()).location(location).versionProperties(versionDetails.properties())
+                       .build();
                osImagesRef.add(vmImage);
             }
          }
@@ -245,13 +248,13 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
             try {
                String name = storage.name();
                StorageService storageService = api.getStorageAccountApi(azureGroup).get(name);
-               if (storageService != null && availableLocationNames.contains(storageService.location())
-                     && Status.Succeeded == storageService.storageServiceProperties().provisioningState()) {
+               if (storageService != null
+                       && Status.Succeeded == storageService.storageServiceProperties().provisioningState()) {
                   String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1();
                   BlobHelper blobHelper = new BlobHelper(storage.name(), key);
                   try {
                      List<VMImage> images = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER,
-                           storage.location());
+                             storage.location());
                      osImages.addAll(images);
                   } finally {
                      closeQuietly(blobHelper);
@@ -284,7 +287,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
          try {
             if (blobHelper.customImageExists()) {
                List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, resourceGroup.name(),
-                     CUSTOM_IMAGE_OFFER, image.location());
+                       CUSTOM_IMAGE_OFFER, image.location());
                customImage = find(customImagesInStorage, new Predicate<VMImage>() {
                   @Override
                   public boolean apply(VMImage input) {
@@ -308,7 +311,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       if (!versions.isEmpty()) {
          Version version = osImageApi.getVersion(publisher, offer, sku, versions.get(0).name());
          return VMImage.azureImage().publisher(publisher).offer(offer).sku(sku).version(version.name())
-               .location(location).versionProperties(version.properties()).build();
+                 .location(location).versionProperties(version.properties()).build();
       }
       return null;
    }
@@ -316,17 +319,17 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    @Override
    public Iterable<Location> listLocations() {
       final Iterable<String> vmLocations = FluentIterable.from(api.getResourceProviderApi().get("Microsoft.Compute"))
-            .filter(new Predicate<ResourceProviderMetaData>() {
-               @Override
-               public boolean apply(ResourceProviderMetaData input) {
-                  return input.resourceType().equals("virtualMachines");
-               }
-            }).transformAndConcat(new Function<ResourceProviderMetaData, Iterable<String>>() {
-               @Override
-               public Iterable<String> apply(ResourceProviderMetaData resourceProviderMetaData) {
-                  return resourceProviderMetaData.locations();
-               }
-            });
+              .filter(new Predicate<ResourceProviderMetaData>() {
+                 @Override
+                 public boolean apply(ResourceProviderMetaData input) {
+                    return input.resourceType().equals("virtualMachines");
+                 }
+              }).transformAndConcat(new Function<ResourceProviderMetaData, Iterable<String>>() {
+                 @Override
+                 public Iterable<String> apply(ResourceProviderMetaData resourceProviderMetaData) {
+                    return resourceProviderMetaData.locations();
+                 }
+              });
 
       List<Location> locations = FluentIterable.from(api.getLocationApi().list()).filter(new Predicate<Location>() {
          @Override
@@ -378,7 +381,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
 
    @Override
    public Iterable<VirtualMachine> listNodes() {
-      ImmutableList.Builder<VirtualMachine> nodes = ImmutableList.builder();
+      ImmutableList.Builder<VirtualMachine> nodes = builder();
       for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
          nodes.addAll(api.getVirtualMachineApi(resourceGroup.name()).list());
       }
@@ -401,14 +404,14 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       String adminUsername = Objects.firstNonNull(template.getOptions().getLoginUser(), defaultLoginUser);
       String adminPassword = Objects.firstNonNull(template.getOptions().getLoginPassword(), defaultLoginPassword);
       OSProfile.Builder builder = OSProfile.builder().adminUsername(adminUsername).adminPassword(adminPassword)
-            .computerName(computerName);
+              .computerName(computerName);
 
       if (template.getOptions().getPublicKey() != null
-            && OsFamily.WINDOWS != template.getImage().getOperatingSystem().getFamily()) {
+              && OsFamily.WINDOWS != template.getImage().getOperatingSystem().getFamily()) {
          OSProfile.LinuxConfiguration linuxConfiguration = OSProfile.LinuxConfiguration.create("true",
-               OSProfile.LinuxConfiguration.SSH.create(ImmutableList.of(OSProfile.LinuxConfiguration.SSH.SSHPublicKey
-                     .create(String.format("/home/%s/.ssh/authorized_keys", adminUsername), template.getOptions()
-                           .getPublicKey()))));
+                 OSProfile.LinuxConfiguration.SSH.create(of(OSProfile.LinuxConfiguration.SSH.SSHPublicKey
+                         .create(String.format("/home/%s/.ssh/authorized_keys", adminUsername), template.getOptions()
+                                 .getPublicKey()))));
          builder.linuxConfiguration(linuxConfiguration);
       }
 
@@ -416,29 +419,29 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    }
 
    private NetworkInterfaceCard createNetworkInterfaceCard(String subnetId, String name, String locationName,
-         String azureGroup, TemplateOptions options) {
+                                                           String azureGroup, TemplateOptions options) {
       final PublicIPAddressApi ipApi = api.getPublicIPAddressApi(azureGroup);
 
       PublicIPAddressProperties properties = PublicIPAddressProperties.builder().publicIPAllocationMethod("Static")
-            .idleTimeoutInMinutes(4).build();
+              .idleTimeoutInMinutes(4).build();
 
       String publicIpAddressName = "public-address-" + name;
       PublicIPAddress ip = ipApi.createOrUpdate(publicIpAddressName, locationName, ImmutableMap.of("jclouds", name),
-            properties);
+              properties);
 
       checkState(publicIpAvailable.create(azureGroup).apply(publicIpAddressName),
-            "Public IP was not provisioned in the configured timeout");
+              "Public IP was not provisioned in the configured timeout");
 
       final NetworkInterfaceCardProperties.Builder networkInterfaceCardProperties = NetworkInterfaceCardProperties
-            .builder()
-            .ipConfigurations(
-                  ImmutableList.of(IpConfiguration
-                        .builder()
-                        .name("ipConfig-" + name)
-                        .properties(
-                              IpConfigurationProperties.builder().privateIPAllocationMethod("Dynamic")
-                                    .publicIPAddress(IdReference.create(ip.id())).subnet(IdReference.create(subnetId))
-                                    .build()).build()));
+              .builder()
+              .ipConfigurations(
+                      of(IpConfiguration
+                              .builder()
+                              .name("ipConfig-" + name)
+                              .properties(
+                                      IpConfigurationProperties.builder().privateIPAllocationMethod("Dynamic")
+                                              .publicIPAddress(IdReference.create(ip.id())).subnet(IdReference.create(subnetId))
+                                              .build()).build()));
 
       String securityGroup = getOnlyElement(options.getGroups(), null);
       if (securityGroup != null) {
@@ -447,29 +450,36 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
 
       String networkInterfaceCardName = "jc-nic-" + name;
       return api.getNetworkInterfaceCardApi(azureGroup).createOrUpdate(networkInterfaceCardName, locationName,
-            networkInterfaceCardProperties.build(), ImmutableMap.of("jclouds", name));
+              networkInterfaceCardProperties.build(), ImmutableMap.of("jclouds", name));
    }
 
-   private StorageProfile createStorageProfile(String name, Image image, String blob) {
-      VMImage imageRef = decodeFieldsFromUniqueId(image.getId());
-      ImageReference imageReference = null;
-      VHD sourceImage = null;
-      String osType = null;
-
-      if (!imageRef.custom()) {
-         imageReference = ImageReference.builder().publisher(image.getProviderId()).offer(image.getName())
-               .sku(image.getVersion()).version("latest").build();
-      } else {
-         sourceImage = VHD.create(image.getProviderId());
-
-         // TODO: read the ostype from the image blob
-         OsFamily osFamily = image.getOperatingSystem().getFamily();
-         osType = osFamily == OsFamily.WINDOWS ? "Windows" : "Linux";
-      }
+   private StorageProfile createStorageProfile(Image image, List<DataDisk> dataDisks) {
+      return StorageProfile.create(createImageReference(image), createOSDisk(image), dataDisks);
+   }
 
-      VHD vhd = VHD.create(blob + "vhds/" + name + ".vhd");
-      OSDisk osDisk = OSDisk.create(osType, name, vhd, "ReadWrite", "FromImage", sourceImage);
+   private ImageReference createImageReference(Image image) {
+      return isCustom(image.getId()) ? ImageReference.builder().id(image.getId()).build() :
+              ImageReference.builder()
+                      .publisher(image.getProviderId())
+                      .offer(image.getName())
+                      .sku(image.getVersion())
+                      .version("latest")
+                      .build();
+   }
 
-      return StorageProfile.create(imageReference, osDisk, ImmutableList.<DataDisk> of());
+   private OSDisk createOSDisk(Image image) {
+      OsFamily osFamily = image.getOperatingSystem().getFamily();
+      String osType = osFamily == OsFamily.WINDOWS ? "Windows" : "Linux";
+      return OSDisk.builder()
+              .osType(osType)
+              .caching(DataDisk.CachingTypes.READ_WRITE.toString())
+              .createOption(CreationData.CreateOptions.FROM_IMAGE.toString())
+              .managedDiskParameters(ManagedDiskParameters.create(null, ManagedDiskParameters.StorageAccountTypes.STANDARD_LRS.toString()))
+              .build();
    }
+   
+   private IdReference getAvailabilitySetIdReference(AvailabilitySet availabilitySet) {
+      return availabilitySet != null ? IdReference.create(availabilitySet.id()) : null;
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
index 38c0769..25bcc3b 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
@@ -16,10 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.compute.functions;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.tryFind;
-import static java.util.Arrays.asList;
-
 import java.util.Map;
 import java.util.Set;
 
@@ -43,6 +39,11 @@ import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
 import com.google.inject.Inject;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.tryFind;
+import static java.util.Arrays.asList;
+import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
+
 public class VMImageToImage implements Function<VMImage, Image> {
 
    private static final Map<String, OsFamily> OTHER_OS_MAP = ImmutableMap.<String, OsFamily> builder()
@@ -71,10 +72,9 @@ public class VMImageToImage implements Function<VMImage, Image> {
    }
 
    public static VMImage decodeFieldsFromUniqueId(final String id) {
-      String[] fields = checkNotNull(id, "id").split("/");
       VMImage vmImage;
-      boolean custom = fields.length == 5;
-      if (custom) {
+      String[] fields = checkNotNull(id, "id").split("/");
+      if (isCustom(id)) {
          /* id fields indexes
          0: imageReference.location) + "/" +
          1: imageReference.group + "/" +
@@ -193,4 +193,5 @@ public class VMImageToImage implements Function<VMImage, Image> {
          }
       });
    }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
index ec6858f..5566ecf 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
@@ -16,12 +16,16 @@
  */
 package org.jclouds.azurecompute.arm.compute.options;
 
+import java.util.List;
+
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
+import org.jclouds.azurecompute.arm.domain.DataDisk;
 import org.jclouds.compute.options.TemplateOptions;
 
 import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
 
-import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Azure ARM custom options
@@ -33,6 +37,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
    private String blob;
    private AvailabilitySet availabilitySet;
    private String availabilitySetName;
+   private List<DataDisk> dataDisks = ImmutableList.of();
 
    /**
     * Sets the virtual network name
@@ -76,12 +81,25 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       return this;
    }
 
+   public AzureTemplateOptions dataDisks(Iterable<DataDisk> dataDisks) {
+      for (DataDisk dataDisk : checkNotNull(dataDisks, "dataDisks"))
+         checkNotNull(dataDisk, "all dataDisks must be non-empty");
+      this.dataDisks = ImmutableList.copyOf(dataDisks);
+      return this;
+   }
+
+   public AzureTemplateOptions dataDisks(DataDisk... dataDisks) {
+      return dataDisks(ImmutableList.copyOf(checkNotNull(dataDisks, "dataDisks")));
+   }
+   
    public String getVirtualNetworkName() { return virtualNetworkName; }
    public String getSubnetId() { return subnetId; }
    public String getBlob() { return blob; }
    public AvailabilitySet getAvailabilitySet() { return availabilitySet; }
    public String getAvailabilitySetName() { return availabilitySetName; }
-
+   public List<DataDisk> getDataDisks() {
+      return dataDisks;
+   }
 
    @Override
    public AzureTemplateOptions clone() {
@@ -100,43 +118,56 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          eTo.blob(blob);
          eTo.availabilitySet(availabilitySet);
          eTo.availabilitySet(availabilitySetName);
+         eTo.dataDisks(dataDisks);
       }
    }
 
    @Override
-   public int hashCode() {
-      return Objects.hashCode(super.hashCode(), virtualNetworkName, subnetId, blob, availabilitySet,
-            availabilitySetName);
-   }
+   public boolean equals(Object o) {
+      if (this == o) return true;
+      if (!(o instanceof AzureTemplateOptions)) return false;
+      if (!super.equals(o)) return false;
 
-   @Override
-   public boolean equals(Object obj) {
-      if (this == obj) {
-         return true;
-      }
-      if (!super.equals(obj)) {
+      AzureTemplateOptions that = (AzureTemplateOptions) o;
+
+      if (virtualNetworkName != null ? !virtualNetworkName.equals(that.virtualNetworkName) : that.virtualNetworkName != null)
          return false;
-      }
-      if (getClass() != obj.getClass()) {
+      if (subnetId != null ? !subnetId.equals(that.subnetId) : that.subnetId != null) return false;
+      if (blob != null ? !blob.equals(that.blob) : that.blob != null) return false;
+      if (availabilitySet != null ? !availabilitySet.equals(that.availabilitySet) : that.availabilitySet != null)
          return false;
-      }
-      AzureTemplateOptions other = (AzureTemplateOptions) obj;
-      return super.equals(other)
-            && equal(this.virtualNetworkName, other.virtualNetworkName)
-            && equal(this.subnetId, other.subnetId)
-            && equal(this.blob, other.blob)
-            && equal(this.availabilitySet, other.availabilitySet)
-            && equal(this.availabilitySetName, other.availabilitySetName);
+      if (availabilitySetName != null ? !availabilitySetName.equals(that.availabilitySetName) : that.availabilitySetName != null)
+         return false;
+      return dataDisks != null ? dataDisks.equals(that.dataDisks) : that.dataDisks == null;
+   }
+
+   @Override
+   public int hashCode() {
+      int result = super.hashCode();
+      result = 31 * result + (virtualNetworkName != null ? virtualNetworkName.hashCode() : 0);
+      result = 31 * result + (subnetId != null ? subnetId.hashCode() : 0);
+      result = 31 * result + (blob != null ? blob.hashCode() : 0);
+      result = 31 * result + (availabilitySet != null ? availabilitySet.hashCode() : 0);
+      result = 31 * result + (availabilitySetName != null ? availabilitySetName.hashCode() : 0);
+      result = 31 * result + (dataDisks != null ? dataDisks.hashCode() : 0);
+      return result;
    }
 
    @Override
    public Objects.ToStringHelper string() {
-      Objects.ToStringHelper toString = super.string().omitNullValues();
-      toString.add("virtualNetworkName", virtualNetworkName);
-      toString.add("subnetId", subnetId);
-      toString.add("blob", blob);
-      toString.add("availabilitySet", availabilitySet);
-      toString.add("availabilitySetName", availabilitySetName);
+      Objects.ToStringHelper toString = super.string();
+      if (virtualNetworkName != null)
+         toString.add("virtualNetworkName", virtualNetworkName);
+      if (subnetId != null)
+         toString.add("subnetId", subnetId);
+      if (blob != null)
+         toString.add("blob", blob);
+      if (availabilitySet != null)
+         toString.add("availabilitySet", availabilitySet);
+      if (availabilitySetName != null)
+         toString.add("availabilitySetName", availabilitySetName);
+      if (!dataDisks.isEmpty())
+         toString.add("dataDisks", dataDisks);
       return toString;
    }
 
@@ -181,5 +212,18 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          AzureTemplateOptions options = new AzureTemplateOptions();
          return options.availabilitySet(availabilitySetName);
       }
+
+      /**
+       * @see AzureTemplateOptions#dataDisks
+       */
+      public static AzureTemplateOptions dataDisks(DataDisk... dataDisks) {
+         AzureTemplateOptions options = new AzureTemplateOptions();
+         return options.dataDisks(dataDisks);
+      }
+
+      public static AzureTemplateOptions dataDisks(Iterable<DataDisk> dataDisks) {
+         AzureTemplateOptions options = new AzureTemplateOptions();
+         return options.dataDisks(dataDisks);
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
index 92c9499..5f6d88f 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
@@ -16,19 +16,9 @@
  */
 package org.jclouds.azurecompute.arm.compute.strategy;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
-
-import java.net.URI;
 import java.util.Arrays;
 import java.util.Map;
 import java.util.Set;
-import java.util.UUID;
 
 import javax.annotation.Resource;
 import javax.inject.Inject;
@@ -44,14 +34,11 @@ import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
-import org.jclouds.azurecompute.arm.domain.StorageService;
 import org.jclouds.azurecompute.arm.domain.Subnet;
-import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
 import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
 import org.jclouds.compute.config.CustomizationResponse;
-import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.functions.GroupNamingConvention;
@@ -65,14 +52,17 @@ import org.jclouds.domain.Location;
 import org.jclouds.logging.Logger;
 
 import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.base.Strings;
 import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Multimap;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
+
 @Singleton
 public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEncodedIntoNameThenAddToSet {
 
@@ -85,7 +75,6 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
    private final LoadingCache<String, ResourceGroup> resourceGroupMap;
    private final String defaultVnetAddressPrefix;
    private final String defaultSubnetAddressPrefix;
-   private final Predicate<URI> storageAccountCreated;
    private final TemplateToAvailabilitySet templateToAvailabilitySet;
 
    @Inject
@@ -98,7 +87,7 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
          AzureComputeApi api, @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX) String defaultVnetAddressPrefix,
          @Named(DEFAULT_SUBNET_ADDRESS_PREFIX) String defaultSubnetAddressPrefix,
          LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap,
-         LoadingCache<String, ResourceGroup> resourceGroupMap, @Named("STORAGE") Predicate<URI> storageAccountCreated,
+         LoadingCache<String, ResourceGroup> resourceGroupMap, 
          TemplateToAvailabilitySet templateToAvailabilitySet) {
       super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
             customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
@@ -108,7 +97,6 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
       this.resourceGroupMap = resourceGroupMap;
       this.defaultVnetAddressPrefix = defaultVnetAddressPrefix;
       this.defaultSubnetAddressPrefix = defaultSubnetAddressPrefix;
-      this.storageAccountCreated = storageAccountCreated;
       this.templateToAvailabilitySet = templateToAvailabilitySet;
    }
 
@@ -136,9 +124,6 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
       configureSecurityGroupForOptions(group, azureGroupName, template.getLocation(), options);
       configureAvailabilitySetForTemplate(template);
 
-      StorageService storageService = getOrCreateStorageService(group, azureGroupName, location, template.getImage());
-      options.blob(storageService.storageServiceProperties().primaryEndpoints().get("blob"));
-
       return super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
    }
 
@@ -175,32 +160,6 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
             && !template.getOptions().hasLoginPrivateKeyOption();
    }
 
-   public StorageService getOrCreateStorageService(String name, String resourceGroupName, String locationName,
-         Image image) {
-      String storageAccountName = null;
-      VMImage imageRef = decodeFieldsFromUniqueId(image.getId());
-      if (imageRef.custom()) {
-         storageAccountName = imageRef.storage();
-      }
-
-      if (Strings.isNullOrEmpty(storageAccountName)) {
-         storageAccountName = generateStorageAccountName(name);
-      }
-
-      StorageService storageService = api.getStorageAccountApi(resourceGroupName).get(storageAccountName);
-      if (storageService != null)
-         return storageService;
-
-      URI uri = api.getStorageAccountApi(resourceGroupName).create(storageAccountName, locationName,
-            ImmutableMap.of("jclouds", name),
-            ImmutableMap.of("accountType", StorageService.AccountType.Standard_LRS.toString()));
-
-      checkState(storageAccountCreated.apply(uri), "Storage account %s was not created in the configured timeout",
-            storageAccountName);
-
-      return api.getStorageAccountApi(resourceGroupName).get(storageAccountName);
-   }
-
    private void configureSecurityGroupForOptions(String group, String resourceGroup, Location location,
          TemplateOptions options) {
 
@@ -231,41 +190,4 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
          template.getOptions().as(AzureTemplateOptions.class).availabilitySet(availabilitySet);
       }
    }
-
-   /**
-    * Generates a valid storage account
-    *
-    * Storage account names must be between 3 and 24 characters in length and
-    * may contain numbers and lowercase letters only.
-    *
-    * @param name
-    *           the node name
-    * @return the storage account name starting from a sanitized name (with only
-    *         numbers and lowercase letters only ). If sanitized name is between
-    *         3 and 24 characters, storage account name is equals to sanitized
-    *         name. If sanitized name is less than 3 characters, storage account
-    *         is sanitized name plus 4 random chars. If sanitized name is more
-    *         than 24 characters, storage account is first 10 chars of sanitized
-    *         name plus 4 random chars plus last 10 chars of sanitized name.
-    */
-   public static String generateStorageAccountName(String name) {
-      String random = UUID.randomUUID().toString().substring(0, 4);
-      String storageAccountName = new StringBuilder().append(name).append(random).toString();
-      String sanitizedStorageAccountName = storageAccountName.replaceAll("[^a-z0-9]", "");
-      int nameLength = sanitizedStorageAccountName.length();
-      if (nameLength >= 3 && nameLength <= 24) {
-         return sanitizedStorageAccountName;
-      }
-
-      if (nameLength > 24) {
-         sanitizedStorageAccountName = shorten(sanitizedStorageAccountName, random);
-      }
-      return sanitizedStorageAccountName;
-   }
-
-   private static String shorten(String storageAccountName, String random) {
-      String prefix = storageAccountName.substring(0, 10);
-      String suffix = storageAccountName.substring(storageAccountName.length() - 10, storageAccountName.length());
-      return String.format("%s%s%s", prefix, random, suffix);
-   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/CreationData.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/CreationData.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/CreationData.java
new file mode 100644
index 0000000..ff31ef2
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/CreationData.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.domain;
+
+import org.jclouds.azurecompute.arm.util.GetEnumValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.CaseFormat;
+
+@AutoValue
+public abstract class CreationData {
+
+
+   public enum CreateOptions {
+      EMPTY,
+      FROM_IMAGE,
+      COPY,
+      IMPORT,
+      UNRECOGNIZED;
+
+      public static CreateOptions fromValue(final String text) {
+         return (CreateOptions) GetEnumValue.fromValueOrDefault(text, UNRECOGNIZED);
+      }
+
+      @Override
+      public String toString() {
+         return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+      }
+   }
+   
+   @Nullable
+   public abstract CreateOptions createOption();
+
+   @SerializedNames({ "createOption" })
+   public static CreationData create(CreateOptions createOption) {
+      return new AutoValue_CreationData(createOption);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DataDisk.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DataDisk.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DataDisk.java
index ebb137b..40189c3 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DataDisk.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DataDisk.java
@@ -16,47 +16,108 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
-
+import org.jclouds.azurecompute.arm.util.GetEnumValue;
+import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
+import com.google.auto.value.AutoValue;
+import com.google.common.base.CaseFormat;
+
 @AutoValue
-public abstract class DataDisk {
+public abstract class DataDisk implements Provisionable {
+
+   public enum DiskCreateOptionTypes {
+      FROM_IMAGE,
+      EMPTY,
+      ATTACH,
+      UNRECOGNIZED;
+
+      public static DiskCreateOptionTypes fromValue(final String text) {
+         return (DiskCreateOptionTypes) GetEnumValue.fromValueOrDefault(text, UNRECOGNIZED);
+      }
+
+      @Override
+      public String toString() {
+         return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+      }
+   }
+   
+   public enum CachingTypes {
+      NONE,
+      READ_ONLY,
+      READ_WRITE,
+      UNRECOGNIZED;
+
+      public static CachingTypes fromValue(final String text) {
+         return (CachingTypes) GetEnumValue.fromValueOrDefault(text, UNRECOGNIZED);
+      }
+
+      @Override
+      public String toString() {
+         return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+      }
+   }
 
    /**
     * The name of the data disk
     */
-   public abstract String name();
+   @Nullable public abstract String name();
 
    /**
     * The size of the data disk
     */
-   public abstract String diskSizeGB();
+   @Nullable public abstract String diskSizeGB();
 
    /**
     * The lun value of the data disk
     */
-   public abstract int lun();
+   @Nullable public abstract Integer lun();
 
    /**
     * The vhd of the data disk
     */
-   public abstract VHD vhd();
+   @Nullable public abstract VHD vhd();
+
+   /**
+    * The source user image virtual hard disk. This virtual hard disk will be
+    * copied before using it to attach to the virtual machine. If SourceImage
+    * is provided, the destination virtual hard disk must not exist.
+    */
+   @Nullable public abstract VHD image();
 
    /**
     * The create option of the data disk
     */
-   public abstract String createOption();
+   public abstract DiskCreateOptionTypes createOption();
+   
+   /**
+    * The caching type. Possible values include: 'None', 'ReadOnly',
+    * 'ReadWrite'.
+    */
+   @Nullable public abstract CachingTypes caching();
+
+   /**
+    * The managed disk parameters.
+    */
+   @Nullable public abstract ManagedDiskParameters managedDiskParameters();
+
+   @Nullable
+   public abstract String provisioningState();
 
-   @SerializedNames({"name", "diskSizeGB", "lun", "vhd", "createOption"})
-   public static DataDisk create(final String name, final String diskSizeGB, final int lun,
-                                 final VHD vhd, final String createOption) {
+   @SerializedNames({"name", "diskSizeGB", "lun", "vhd", "image", "createOption", "caching", "managedDisk", "provisioningState"})
+   public static DataDisk create(final String name, final String diskSizeGB, final Integer lun,
+                                 final VHD vhd, final VHD image, final String createOption, final String caching, 
+                                 final ManagedDiskParameters managedDiskParamenters, final String provisioningState) {
       return builder()
               .name(name)
               .diskSizeGB(diskSizeGB)
               .lun(lun)
-              .createOption(createOption)
               .vhd(vhd)
+              .image(image)
+              .caching(CachingTypes.fromValue(caching))
+              .createOption(DiskCreateOptionTypes.fromValue(createOption))
+              .managedDiskParameters(managedDiskParamenters)
+              .provisioningState(provisioningState)
               .build();
    }
    
@@ -68,16 +129,25 @@ public abstract class DataDisk {
 
    @AutoValue.Builder
    public abstract static class Builder {
+      
       public abstract Builder name(String name);
 
       public abstract Builder diskSizeGB(String diskSizeGB);
 
-      public abstract Builder createOption(String createOption);
+      public abstract Builder createOption(DiskCreateOptionTypes createOption);
 
-      public abstract Builder lun(int lun);
+      public abstract Builder lun(Integer lun);
 
       public abstract Builder vhd(VHD vhd);
 
+      public abstract Builder image(VHD image);
+
+      public abstract Builder caching(CachingTypes caching);
+
+      public abstract Builder managedDiskParameters(ManagedDiskParameters managedDiskParameters);
+      
+      public abstract Builder provisioningState(String provisioningState);
+
       public abstract DataDisk build();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Disk.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Disk.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Disk.java
new file mode 100644
index 0000000..c090aa8
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Disk.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 java.util.Map;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
+
+@AutoValue
+public abstract class Disk {
+
+   /**
+    * The id of the disk
+    */
+   @Nullable public abstract String id();
+   
+   /**
+    * The name of the disk
+    */
+   @Nullable public abstract String name();
+
+   /**
+    * The location of the disk
+    */
+   public abstract String location();
+
+   /**
+    * The type of the disk
+    */
+   @Nullable public abstract String type();
+
+   /**
+    * The sku of the disk
+    */
+   @Nullable public abstract SKU sku();
+
+   /**
+    * The managed disk parameters.
+    */
+   public abstract DiskProperties properties();
+   
+   /**
+    * the tags of the disk
+    */
+   @Nullable public abstract Map<String, String> tags();
+
+   @SerializedNames({"id", "name", "location", "type", "sku", "properties", "tags"})
+   public static Disk create(final String id, final String name, final String location,
+                             final String type, final SKU sku, 
+                             final DiskProperties properties, final Map<String, String> tags) {
+      return builder()
+              .id(id)
+              .name(name)
+              .location(location)
+              .type(type)
+              .sku(sku)
+              .properties(properties)
+              .tags(tags)
+              .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_Disk.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder name(String name);
+      public abstract Builder location(String location);
+      public abstract Builder type(String type);
+      public abstract Builder sku(SKU sku);
+      public abstract Builder properties(DiskProperties properties);
+      public abstract Builder tags(Map<String, String> tags);
+
+      abstract Map<String, String> tags();
+      abstract Disk autoBuild();
+
+      public Disk build() {
+         tags(tags() != null ? ImmutableMap.copyOf(tags()) : null);
+         return autoBuild();
+      }
+      
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DiskProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DiskProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DiskProperties.java
new file mode 100644
index 0000000..bcc62ca
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DiskProperties.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.domain;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class DiskProperties implements Provisionable {
+
+   @Nullable
+   public abstract String provisioningState();
+   
+   @Nullable
+   public abstract String timeCreated();
+   
+   @Nullable
+   public abstract String diskState();
+
+   @Nullable
+   public abstract Integer diskSizeGB();
+   
+   @Nullable
+   public abstract Integer lun();
+
+   @Nullable
+   public abstract VHD vhd();
+
+   public abstract CreationData creationData();
+   
+   @SerializedNames({"provisioningState", "timeCreated", "diskState", "diskSizeGB", "lun", "vhd", "creationData"})
+   public static DiskProperties create(final String provisioningState, final String timeCreated, final String diskState, final Integer diskSizeGB, final Integer lun, final VHD vhd, final CreationData creationData) {
+      return builder()
+              .provisioningState(provisioningState)
+              .timeCreated(timeCreated)
+              .diskState(diskState)
+              .diskSizeGB(diskSizeGB)
+              .lun(lun)
+              .vhd(vhd)
+              .creationData(creationData)
+              .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_DiskProperties.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder provisioningState(String provisioningState);
+      public abstract Builder timeCreated(String timeCreated);
+      public abstract Builder diskState(String diskState);
+      public abstract Builder diskSizeGB(Integer diskSizeGB);
+      public abstract Builder lun(Integer lun);
+      public abstract Builder vhd(VHD vhd);
+      public abstract Builder creationData(CreationData creationData);
+      public abstract DiskProperties build();
+
+   }
+}

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

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
new file mode 100644
index 0000000..ef877be
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
@@ -0,0 +1,70 @@
+/*
+ * 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.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class ImageProperties implements Provisionable {
+
+   @AutoValue
+   public abstract static class SourceVirtualMachine {
+      public abstract String id();
+
+      @SerializedNames({"id"})
+      public static SourceVirtualMachine create(final String id) {
+         return new AutoValue_ImageProperties_SourceVirtualMachine(id);
+      }
+   }
+   
+   public abstract SourceVirtualMachine sourceVirtualMachine();
+   
+   @Nullable
+   public abstract StorageProfile storageProfile();
+
+   @Nullable
+   public abstract String provisioningState();
+   
+   @SerializedNames({ "sourceVirtualMachine", "storageProfile", "provisioningState"})
+   public static ImageProperties create(final SourceVirtualMachine sourceVirtualMachine, 
+                                        final StorageProfile storageProfile,
+                                        final String provisioningState) {
+      return builder()
+              .sourceVirtualMachine(sourceVirtualMachine)
+              .storageProfile(storageProfile)
+              .provisioningState(provisioningState)
+              .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_ImageProperties.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder sourceVirtualMachine(SourceVirtualMachine sourceVirtualMachine);
+      public abstract Builder storageProfile(StorageProfile storageProfile);
+      public abstract Builder provisioningState(String provisioningState);
+      public abstract ImageProperties build();
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
index f9e1875..443e054 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
@@ -16,15 +16,21 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
-
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
+import com.google.auto.value.AutoValue;
+
 @AutoValue
 public abstract class ImageReference {
 
    /**
+    * The id of the image reference.
+    */
+   @Nullable
+   public abstract String id();
+   
+   /**
     * The publisher of the image reference.
     */
    @Nullable
@@ -48,13 +54,15 @@ public abstract class ImageReference {
    @Nullable
    public abstract String version();
 
-   @SerializedNames({"publisher", "offer", "sku", "version"})
-   public static ImageReference create(final String publisher,
+   @SerializedNames({"id", "publisher", "offer", "sku", "version"})
+   public static ImageReference create(final String id,
+                                       final String publisher,
                                        final String offer,
                                        final String sku,
                                        final String version) {
 
       return builder()
+              .id(id)
               .publisher(publisher)
               .offer(offer)
               .sku(sku)
@@ -70,12 +78,10 @@ public abstract class ImageReference {
 
    @AutoValue.Builder
    public abstract static class Builder {
+      public abstract Builder id(String id);
       public abstract Builder publisher(String publisher);
-
       public abstract Builder offer(String offer);
-
       public abstract Builder sku(String sku);
-
       public abstract Builder version(String version);
 
       public abstract ImageReference build();

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
new file mode 100644
index 0000000..84cbab1
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
@@ -0,0 +1,65 @@
+/*
+ * 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.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class ManagedDiskParameters {
+
+   public enum StorageAccountTypes {
+      /** Enum value Standard_LRS. */
+      STANDARD_LRS("Standard_LRS"),
+
+      /** Enum value Premium_LRS. */
+      PREMIUM_LRS("Premium_LRS");
+
+      /** The actual serialized value for a StorageAccountTypes instance. */
+      private String value;
+
+      StorageAccountTypes(String value) {
+         this.value = value;
+      }
+
+      public static StorageAccountTypes fromString(String value) {
+         StorageAccountTypes[] items = StorageAccountTypes.values();
+         for (StorageAccountTypes item : items) {
+            if (item.toString().equalsIgnoreCase(value)) {
+               return item;
+            }
+         }
+         return null;
+      }
+
+      @Override
+      public String toString() {
+         return this.value;
+      }
+   }
+
+   @Nullable public abstract String id();
+
+   public abstract StorageAccountTypes storageAccountType();
+
+   @SerializedNames({"id", "storageAccountType"})
+   public static ManagedDiskParameters create(final String id, final String storageAccountType) {
+      return new AutoValue_ManagedDiskParameters(id, StorageAccountTypes.fromString(storageAccountType));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
index 9cdee44..c87fe75 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
@@ -16,11 +16,11 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
-
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
+import com.google.auto.value.AutoValue;
+
 @AutoValue
 public abstract class OSDisk {
    /**
@@ -59,9 +59,15 @@ public abstract class OSDisk {
    @Nullable
    public abstract VHD image();
 
-   @SerializedNames({"osType", "name", "vhd", "caching", "createOption", "image"})
+   /**
+    * The managed disk parameters.
+    */
+   @Nullable public abstract ManagedDiskParameters managedDiskParameters();
+   
+   @SerializedNames({"osType", "name", "vhd", "caching", "createOption", "image", "managedDisk"})
    public static OSDisk create(final String osType, final String name, final VHD vhd,
-                               final String caching, final String createOption, final VHD image) {
+                               final String caching, final String createOption, final VHD image, 
+                               final ManagedDiskParameters managedDiskParamenters) {
       return builder()
             .osType(osType)
             .name(name)
@@ -69,7 +75,8 @@ public abstract class OSDisk {
             .caching(caching)
             .createOption(createOption)
             .image(image)
-            .build();
+              .managedDiskParameters(managedDiskParamenters)
+              .build();
    }
    
    public abstract Builder toBuilder();
@@ -86,6 +93,7 @@ public abstract class OSDisk {
       public abstract Builder createOption(String createOption);
       public abstract Builder vhd(VHD vhd);
       public abstract Builder image(VHD image);
+      public abstract Builder managedDiskParameters(ManagedDiskParameters managedDiskParameters);
       public abstract OSDisk build();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java
new file mode 100644
index 0000000..0797dbd
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.azurecompute.arm.domain.Disk;
+import org.jclouds.azurecompute.arm.domain.DiskProperties;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.azurecompute.arm.functions.URIParser;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Compute/disks")
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
+@Consumes(MediaType.APPLICATION_JSON)
+public interface DiskApi {
+
+   @Named("disk:list")
+   @SelectJson("value")
+   @GET
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Disk> list();
+
+   @Named("disk:create_or_update")
+   @PUT
+   @Payload("%7B\"location\":\"{location}\",\"properties\":{properties}%7D")
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/{diskName}")
+   @Produces(MediaType.APPLICATION_JSON)
+   Disk createOrUpdate(@PathParam("diskName") String diskName,
+                       @PayloadParam("location") String location,
+                       @PayloadParam("properties") DiskProperties properties);
+
+   @Named("disk:get")
+   @Path("/{diskName}")
+   @GET
+   @Fallback(NullOnNotFoundOr404.class)
+   Disk get(@PathParam("diskName") String diskName);
+
+   @Named("disk:delete")
+   @Path("/{diskName}")
+   @DELETE
+   @ResponseParser(URIParser.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   URI delete(@PathParam("diskName") String diskName);
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java
new file mode 100644
index 0000000..c97b0ac
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.azurecompute.arm.domain.Image;
+import org.jclouds.azurecompute.arm.domain.ImageProperties;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.azurecompute.arm.functions.URIParser;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Compute/images")
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
+@Consumes(MediaType.APPLICATION_JSON)
+public interface ImageApi {
+
+   @Named("image:list")
+   @SelectJson("value")
+   @GET
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Image> list();
+
+   @Named("image:create_or_update")
+   @PUT
+   @Payload("%7B\"location\":\"{location}\",\"properties\":{properties}%7D")
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/{imageName}")
+   @Produces(MediaType.APPLICATION_JSON)
+   Image createOrUpdate(@PathParam("imageName") String imageName,
+                       @PayloadParam("location") String location,
+                       @PayloadParam("properties") ImageProperties properties);
+
+   @Named("image:get")
+   @Path("/{imageName}")
+   @GET
+   @Fallback(NullOnNotFoundOr404.class)
+   Image get(@PathParam("imageName") String imageName);
+
+   @Named("image:delete")
+   @Path("/{imageName}")
+   @DELETE
+   @ResponseParser(URIParser.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   URI delete(@PathParam("imageName") String imageName);
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/OSImageApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/OSImageApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/OSImageApi.java
index 50c5c45..32b3ccc 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/OSImageApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/OSImageApi.java
@@ -16,8 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-
 import java.util.List;
 
 import javax.inject.Named;
@@ -36,6 +34,8 @@ import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.RequestFilters;
 
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
 /**
  * The Azure Resource Management API includes operations for managing the OS images in your subscription.
  */
@@ -90,4 +90,5 @@ public interface OSImageApi {
    @Fallback(EmptyListOnNotFoundOr404.class)
    Version getVersion(@PathParam("publisher") String publisher, @PathParam("offer") String offer,
                           @PathParam("sku") String sku, @PathParam("version") String version);
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
new file mode 100644
index 0000000..d5b6394
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
@@ -0,0 +1,27 @@
+/*
+ * 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 static com.google.common.base.Preconditions.checkNotNull;
+
+public class VMImages {
+
+   public static boolean isCustom(String imageId) {
+      return checkNotNull(imageId, "id").split("/").length == 5;
+   }
+  
+}


[13/50] [abbrv] jclouds git commit: Better encapsulated the image id encoding logic

Posted by na...@apache.org.
Better encapsulated the image id encoding logic


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

Branch: refs/heads/master
Commit: 3a9f5787bf64673a403a2fcbd6fb3237aee95cbd
Parents: 3b9609f
Author: Ignasi Barrera <na...@apache.org>
Authored: Tue Apr 25 16:28:17 2017 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Apr 26 00:13:06 2017 +0200

----------------------------------------------------------------------
 .../arm/compute/AzureComputeServiceAdapter.java |  3 +-
 .../extensions/AzureComputeImageExtension.java  |  3 +-
 .../NetworkSecurityGroupToSecurityGroup.java    |  2 +-
 .../arm/compute/functions/VMImageToImage.java   | 91 +++++---------------
 .../functions/VirtualMachineToNodeMetadata.java |  7 +-
 .../azurecompute/arm/domain/ImageReference.java | 13 +++
 .../azurecompute/arm/domain/VMImage.java        | 46 ++++++++--
 7 files changed, 78 insertions(+), 87 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/3a9f5787/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 73ecda9..d01d6ec 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -25,7 +25,6 @@ import static com.google.common.collect.Iterables.transform;
 import static com.google.common.collect.Lists.newArrayList;
 import static org.jclouds.azurecompute.arm.compute.domain.LocationAndName.fromSlashEncoded;
 import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
 import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
 import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
@@ -256,7 +255,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
 
    @Override
    public VMImage getImage(final String id) {
-      VMImage image = decodeFieldsFromUniqueId(id);
+      VMImage image = VMImage.decodeFieldsFromUniqueId(id);
 
       if (image.custom()) {
          org.jclouds.azurecompute.arm.domain.Image vmImage = api.getVirtualMachineImageApi(image.resourceGroup()).get(

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3a9f5787/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
index 7d654d5..d826a51 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
@@ -20,7 +20,6 @@ import static com.google.common.base.Functions.compose;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromSlashEncoded;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
 
@@ -125,7 +124,7 @@ public class AzureComputeImageExtension implements ImageExtension {
 
    @Override
    public boolean deleteImage(String id) {
-      VMImage image = decodeFieldsFromUniqueId(id);
+      VMImage image = VMImage.decodeFieldsFromUniqueId(id);
       checkArgument(image.custom(), "Only custom images can be deleted");
 
       logger.debug(">> deleting image %s", id);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3a9f5787/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityGroupToSecurityGroup.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityGroupToSecurityGroup.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityGroupToSecurityGroup.java
index 71d51aa..d38f94c 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityGroupToSecurityGroup.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityGroupToSecurityGroup.java
@@ -61,7 +61,7 @@ public class NetworkSecurityGroupToSecurityGroup implements Function<NetworkSecu
       builder.location(getLocation(locations, input.location()));
 
       if (input.properties().securityRules() != null) {
-         // We just supoprt security groups that allow traffic to a set of
+         // We just support security groups that allow traffic to a set of
          // targets. We don't support deny rules or origin based rules in the
          // security group api.
          builder.ipPermissions(transform(filter(input.properties().securityRules(), InboundRule), ruleToPermission));

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3a9f5787/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
index 2a5075c..028ad9c 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
@@ -19,14 +19,12 @@ package org.jclouds.azurecompute.arm.compute.functions;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.Iterables.tryFind;
 import static java.util.Arrays.asList;
-import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
-import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
+import static org.jclouds.location.predicates.LocationPredicates.idEquals;
 
 import java.util.Map;
 import java.util.Set;
 
 import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
-import org.jclouds.azurecompute.arm.domain.ImageReference;
 import org.jclouds.azurecompute.arm.domain.Plan;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.collect.Memoized;
@@ -36,7 +34,6 @@ import org.jclouds.compute.domain.OperatingSystem;
 import org.jclouds.compute.domain.OsFamily;
 import org.jclouds.domain.Location;
 import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.predicates.LocationPredicates;
 
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
@@ -57,51 +54,6 @@ public class VMImageToImage implements Function<VMImage, Image> {
 
    private final Supplier<Set<? extends org.jclouds.domain.Location>> locations;
 
-   public static String encodeFieldsToUniqueId(boolean globallyAvailable, String locationName,
-         ImageReference imageReference) {
-      return (globallyAvailable ? "global" : locationName) + "/" + imageReference.publisher() + "/"
-            + imageReference.offer() + "/" + imageReference.sku();
-   }
-
-   public static String encodeFieldsToUniqueIdCustom(boolean globallyAvailable, String locationName,
-         ImageReference imageReference) {
-      return extractResourceGroup(imageReference.customImageId()) + "/" + (globallyAvailable ? "global" : locationName)
-            + "/" + imageReference.customImageId().substring(imageReference.customImageId().lastIndexOf("/") + 1);
-   }
-
-   public static String encodeFieldsToUniqueId(VMImage imageReference) {
-      return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/"
-            + imageReference.publisher() + "/" + imageReference.offer() + "/" + imageReference.sku();
-   }
-
-   public static String encodeFieldsToUniqueIdCustom(VMImage imageReference) {
-      return imageReference.resourceGroup() + "/"
-            + (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.name();
-   }
-
-   public static VMImage decodeFieldsFromUniqueId(final String id) {
-      VMImage vmImage;
-      String[] fields = checkNotNull(id, "id").split("/");
-      if (isCustom(id)) {
-         /* id fields indexes
-         0: imageReference.resourceGroup
-         1: imageReference.location + "/" +
-         2: imageReference.name
-         */
-         vmImage = VMImage.customImage().resourceGroup(fields[0]).location(fields[1]).name(fields[2]).build();
-      } else {
-         /* id fields indexes
-         0: imageReference.location + "/" +
-         1: imageReference.publisher + "/" +
-         2: imageReference.offer + "/" +
-         3: imageReference.sku + "/" +
-         */
-         vmImage = VMImage.azureImage().location(fields[0]).publisher(fields[1]).offer(fields[2]).sku(fields[3])
-               .build();
-      }
-      return vmImage;
-   }
-
    @Inject
    VMImageToImage(@Memoized Supplier<Set<? extends Location>> locations) {
       this.locations = locations;
@@ -111,29 +63,32 @@ public class VMImageToImage implements Function<VMImage, Image> {
    public Image apply(final VMImage image) {
       final ImageBuilder builder = new ImageBuilder();
       addMarketplacePlanToMetadataIfPresent(builder, image);
+      
+      Location location = FluentIterable.from(locations.get()).firstMatch(idEquals(image.location())).get();
+      
       if (image.custom()) {
-         builder.location(
-                     FluentIterable.from(locations.get()).firstMatch(LocationPredicates.idEquals(image.location()))
-                           .get()).name(image.name()).description(image.group()).status(Image.Status.AVAILABLE)
-               .version("latest").providerId(image.customImageId()).id(encodeFieldsToUniqueIdCustom(image));
-
-         final OperatingSystem.Builder osBuilder = osFamily().apply(image);
-         builder.operatingSystem(osBuilder.build());
+         builder
+            .id(image.encodeFieldsToUniqueIdCustom())
+            .providerId(image.customImageId())
+            .name(image.name())
+            .location(location)
+            .description(image.group())
+            .status(Image.Status.AVAILABLE)
+            .version("latest");
       } else {
          builder
-               .name(image.offer())
-               .description(image.sku())
-               .status(Image.Status.AVAILABLE)
-               .version(image.sku())
-               .id(encodeFieldsToUniqueId(image))
-               .providerId(image.publisher())
-               .location(
-                     image.globallyAvailable() ? null : FluentIterable.from(locations.get())
-                           .firstMatch(LocationPredicates.idEquals(image.location())).get());
-
-         final OperatingSystem.Builder osBuilder = osFamily().apply(image);
-         builder.operatingSystem(osBuilder.build());
+            .id(image.encodeFieldsToUniqueId())
+            .providerId(image.publisher())
+            .name(image.offer())
+            .location(location)
+            .description(image.sku())
+            .status(Image.Status.AVAILABLE)
+            .version(image.sku());
       }
+      
+      final OperatingSystem.Builder osBuilder = osFamily().apply(image);
+      builder.operatingSystem(osBuilder.build());
+      
       return builder.build();
    }
    

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3a9f5787/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
index bcfd4fe..e4b7da8 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
@@ -22,8 +22,6 @@ import static com.google.common.collect.Iterables.find;
 import static org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.GROUP_KEY;
 import static org.jclouds.azurecompute.arm.compute.domain.LocationAndName.fromLocationAndName;
 import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
 import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
 import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
 import static org.jclouds.location.predicates.LocationPredicates.idEquals;
@@ -185,10 +183,9 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
 
    protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName) {
       if (storageProfile.imageReference() != null) {
-         // FIXME check this condition
          String imageId = storageProfile.imageReference().customImageId() != null ?
-               encodeFieldsToUniqueIdCustom(false, locatioName, storageProfile.imageReference()) :
-               encodeFieldsToUniqueId(false, locatioName, storageProfile.imageReference());
+               storageProfile.imageReference().encodeFieldsToUniqueIdCustom(locatioName) :
+               storageProfile.imageReference().encodeFieldsToUniqueId(locatioName); 
          return imageCache.get(imageId);
       } else {
          logger.warn("could not find image for storage profile %s", storageProfile);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3a9f5787/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
index d9b43cd..d001949 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
@@ -16,6 +16,9 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractName;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
+
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
@@ -90,4 +93,14 @@ public abstract class ImageReference {
 
       public abstract ImageReference build();
    }
+   
+   public String encodeFieldsToUniqueId(String location) {
+      return VMImage.azureImage().location(location).publisher(publisher()).offer(offer()).sku(sku()).build()
+            .encodeFieldsToUniqueId();
+   }
+
+   public String encodeFieldsToUniqueIdCustom(String location) {
+      return VMImage.customImage().resourceGroup(extractResourceGroup(customImageId())).location(location)
+            .name(extractName(customImageId())).build().encodeFieldsToUniqueIdCustom();
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3a9f5787/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
index 91ca818..202481d 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
@@ -16,6 +16,9 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
+
 import org.jclouds.azurecompute.arm.domain.Version.VersionProperties;
 import org.jclouds.javax.annotation.Nullable;
 
@@ -54,11 +57,6 @@ public abstract class VMImage {
    public abstract String location();
 
    /**
-    * Specifies if this image is globally available
-    */
-   public abstract boolean globallyAvailable();
-
-   /**
     * The group of the custom image
     */
    @Nullable
@@ -112,16 +110,16 @@ public abstract class VMImage {
    @Nullable
    public abstract VersionProperties versionProperties();
    
-   public static Builder builder() {
+   private static Builder builder() {
       return new AutoValue_VMImage.Builder();
    }
    
    public static Builder azureImage() {
-      return builder().globallyAvailable(false).custom(false);
+      return builder().custom(false);
    }
    
    public static Builder customImage() {
-      return builder().globallyAvailable(false).custom(true);
+      return builder().custom(true);
    }
    
    VMImage() {
@@ -140,7 +138,6 @@ public abstract class VMImage {
       public abstract Builder sku(String sku);
       public abstract Builder version(String version);
       public abstract Builder location(String location);
-      public abstract Builder globallyAvailable(boolean globallyAvailable);
       public abstract Builder group(String group);
       public abstract Builder storage(String storage);
       public abstract Builder vhd1(String vhd1);
@@ -151,4 +148,35 @@ public abstract class VMImage {
       
       public abstract VMImage build();
    }
+
+   public String encodeFieldsToUniqueId() {
+      return String.format("%s/%s/%s/%s", location(), publisher(), offer(), sku());
+   }
+
+   public String encodeFieldsToUniqueIdCustom() {
+      return String.format("%s/%s/%s", resourceGroup(), location(), name());
+   }
+
+   public static VMImage decodeFieldsFromUniqueId(final String id) {
+      VMImage vmImage;
+      String[] fields = checkNotNull(id, "id").split("/");
+      if (isCustom(id)) {
+         /* id fields indexes
+         0: imageReference.resourceGroup
+         1: imageReference.location + "/" +
+         2: imageReference.name
+         */
+         vmImage = VMImage.customImage().resourceGroup(fields[0]).location(fields[1]).name(fields[2]).build();
+      } else {
+         /* id fields indexes
+         0: imageReference.location + "/" +
+         1: imageReference.publisher + "/" +
+         2: imageReference.offer + "/" +
+         3: imageReference.sku + "/" +
+         */
+         vmImage = VMImage.azureImage().location(fields[0]).publisher(fields[1]).offer(fields[2]).sku(fields[3])
+               .build();
+      }
+      return vmImage;
+   }
 }


[12/50] [abbrv] jclouds git commit: Added ID to the LoadBalancer entity

Posted by na...@apache.org.
Added ID to the LoadBalancer entity


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

Branch: refs/heads/master
Commit: 3b9609f2d546b43a305d01c9517f69a5e50588ac
Parents: 3d27423
Author: Ignasi Barrera <na...@apache.org>
Authored: Tue Apr 25 12:44:13 2017 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Apr 26 00:13:02 2017 +0200

----------------------------------------------------------------------
 .../azurecompute/arm/domain/LoadBalancer.java   | 51 +++++++++++++-------
 .../arm/features/LoadBalancerApiLiveTest.java   | 10 ++--
 .../arm/features/LoadBalancerApiMockTest.java   |  9 +++-
 3 files changed, 48 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/3b9609f2/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/LoadBalancer.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/LoadBalancer.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/LoadBalancer.java
index d313e36..6e3e748 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/LoadBalancer.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/LoadBalancer.java
@@ -26,25 +26,42 @@ import com.google.common.collect.ImmutableMap;
 
 @AutoValue
 public abstract class LoadBalancer {
-   @Nullable
-   public abstract String name();
+   
+   @Nullable public abstract String id();
+   @Nullable public abstract String name();
+   @Nullable public abstract String location();
+   @Nullable public abstract String etag();
+   @Nullable public abstract Map<String, String> tags();
+   @Nullable public abstract LoadBalancerProperties properties();
 
-   @Nullable
-   public abstract String location();
-
-   @Nullable
-   public abstract Map<String, String> tags();
-
-   @Nullable
-   public abstract LoadBalancerProperties properties();
+   @SerializedNames({ "id", "name", "location", "etag", "tags", "properties", })
+   public static LoadBalancer create(String id, final String name, final String location, final String etag,
+         final Map<String, String> tags, final LoadBalancerProperties properties) {
+      return builder().id(id).name(name).location(location).etag(etag).tags(tags).properties(properties).build();
+   }
+   
+   public abstract Builder toBuilder();
 
-   @Nullable
-   public abstract String etag();
+   public static Builder builder() {
+      return new AutoValue_LoadBalancer.Builder();
+   }
+   
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder name(String name);
+      public abstract Builder location(String location);
+      public abstract Builder etag(String etag);
+      public abstract Builder tags(Map<String, String> tags);
+      public abstract Builder properties(LoadBalancerProperties properties);
+      
+      abstract Map<String, String> tags();
 
-   @SerializedNames({ "name", "location", "tags", "properties", "etag" })
-   public static LoadBalancer create(final String name, final String location, final Map<String, String> tags,
-         final LoadBalancerProperties properties, final String etag) {
-      return new AutoValue_LoadBalancer(name, location, tags == null ? null : ImmutableMap.copyOf(tags), properties,
-            etag);
+      abstract LoadBalancer autoBuild();
+      
+      public LoadBalancer build() {
+         tags(tags() != null ? ImmutableMap.copyOf(tags()) : null);
+         return autoBuild();
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3b9609f2/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
index d267912..c5b836b 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
@@ -326,9 +326,13 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
             .builder().build();
       FrontendIPConfigurations frontendIPConfigurations = FrontendIPConfigurations.create("ipConfigs", null,
             frontendIPConfigurationsProperties, null);
-      return LoadBalancer.create(lbName, locationName, null,
-            LoadBalancerProperties.builder().frontendIPConfigurations(ImmutableList.of(frontendIPConfigurations))
-                  .build(), null);
+      return LoadBalancer
+            .builder()
+            .name(lbName)
+            .location(locationName)
+            .properties(
+                  LoadBalancerProperties.builder().frontendIPConfigurations(ImmutableList.of(frontendIPConfigurations))
+                        .build()).build();
    }
 
    private void assertResourceDeleted(final URI uri) {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3b9609f2/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiMockTest.java
index 49e88db..45663ea 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiMockTest.java
@@ -149,7 +149,12 @@ public class LoadBalancerApiMockTest extends BaseAzureComputeApiMockTest {
             .builder().build();
       FrontendIPConfigurations frontendIPConfigurations = FrontendIPConfigurations.create("ipConfigs", null,
             frontendIPConfigurationsProperties, null);
-      return LoadBalancer.create(lbName, "westus", null, LoadBalancerProperties.builder()
-            .frontendIPConfigurations(ImmutableList.of(frontendIPConfigurations)).build(), null);
+      return LoadBalancer
+            .builder()
+            .name(lbName)
+            .location("westus")
+            .properties(
+                  LoadBalancerProperties.builder().frontendIPConfigurations(ImmutableList.of(frontendIPConfigurations))
+                        .build()).build();
    }
 }


[18/50] [abbrv] jclouds git commit: Adding support for provisioning of Windows VMs with enabled WinRM

Posted by na...@apache.org.
Adding support for provisioning of Windows VMs with enabled WinRM

- Provisioning using pre-existing KeyVault
- Enabling WinRM with pre-existing certificate


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

Branch: refs/heads/master
Commit: 50ae01985af0e630cb71078e58db3cc746482cce
Parents: 45480c4
Author: Yavor Yanchev <ya...@yanchev.com>
Authored: Fri May 19 12:41:16 2017 +0300
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Thu May 25 16:34:00 2017 +0300

----------------------------------------------------------------------
 .../arm/compute/AzureComputeServiceAdapter.java | 16 +++-
 .../compute/options/AzureTemplateOptions.java   | 60 +++++++++++++-
 .../azurecompute/arm/domain/OSProfile.java      | 82 ++++++++++++++------
 .../azurecompute/arm/domain/Secrets.java        | 55 +++++++++++++
 .../arm/domain/VaultCertificate.java            | 46 +++++++++++
 .../arm/features/VirtualMachineApiLiveTest.java | 35 +++++++--
 .../arm/features/VirtualMachineApiMockTest.java | 82 +++++++++++++++-----
 .../internal/BaseAzureComputeApiLiveTest.java   | 19 +++++
 .../resources/createvirtualmachineresponse.json | 69 ++++++++++++++--
 .../src/test/resources/virtualmachine.json      | 65 ++++++++++++++--
 .../src/test/resources/virtualmachines.json     | 57 ++++++++++++--
 11 files changed, 513 insertions(+), 73 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae0198/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 02e69fa..ccb748a 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -64,6 +64,8 @@ import org.jclouds.azurecompute.arm.domain.ManagedDiskParameters;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
 import org.jclouds.azurecompute.arm.domain.NetworkProfile;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface.NetworkInterfaceProperties;
 import org.jclouds.azurecompute.arm.domain.OSDisk;
 import org.jclouds.azurecompute.arm.domain.OSProfile;
 import org.jclouds.azurecompute.arm.domain.Offer;
@@ -82,8 +84,6 @@ import org.jclouds.azurecompute.arm.domain.VMSize;
 import org.jclouds.azurecompute.arm.domain.Version;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
-import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
-import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface.NetworkInterfaceProperties;
 import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
 import org.jclouds.azurecompute.arm.features.OSImageApi;
 import org.jclouds.compute.ComputeServiceAdapter;
@@ -390,6 +390,17 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
          builder.linuxConfiguration(linuxConfiguration);
       }
 
+
+      AzureTemplateOptions azureTemplateOptions = template.getOptions().as(AzureTemplateOptions.class);
+
+      if (azureTemplateOptions.getWindowsConfiguration() != null) {
+          builder.windowsConfiguration(azureTemplateOptions.getWindowsConfiguration());
+      }
+
+      if (azureTemplateOptions.getSecrets() != null) {
+          builder.secrets(azureTemplateOptions.getSecrets());
+      }
+
       return builder.build();
    }
 
@@ -526,5 +537,4 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    private IdReference getAvailabilitySetIdReference(AvailabilitySet availabilitySet) {
       return availabilitySet != null ? IdReference.create(availabilitySet.id()) : null;
    }
-
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae0198/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
index c3140dd..6ba85d1 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
@@ -16,17 +16,19 @@
  */
 package org.jclouds.azurecompute.arm.compute.options;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import java.util.List;
 
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
 import org.jclouds.azurecompute.arm.domain.DataDisk;
+import org.jclouds.azurecompute.arm.domain.OSProfile.WindowsConfiguration;
+import org.jclouds.azurecompute.arm.domain.Secrets;
 import org.jclouds.compute.options.TemplateOptions;
 
 import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableList;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 /**
  * Azure ARM custom options
  */
@@ -37,6 +39,8 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
    private List<DataDisk> dataDisks = ImmutableList.of();
    private String resourceGroup;
    private List<IpOptions> ipOptions = ImmutableList.of();
+   private WindowsConfiguration windowsConfiguration;
+   private List<Secrets> secrets = ImmutableList.of();
    
    /**
     * Sets the availability set where the nodes will be configured. If it does
@@ -98,12 +102,36 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
    public AzureTemplateOptions ipOptions(IpOptions... ipOptions) {
       return ipOptions(ImmutableList.copyOf(checkNotNull(ipOptions, "ipOptions")));
    }
-   
+
+   /**
+    * Windows configuration parameters
+    *
+    * @see <a href="https://docs.microsoft.com/en-us/rest/api/compute/virtualmachines/virtualmachines-create-or-update#bk_windowsconfig5">docs</a>
+    */
+   public AzureTemplateOptions windowsConfiguration(WindowsConfiguration windowsConfiguration) {
+       this.windowsConfiguration = windowsConfiguration;
+       return this;
+    }
+
+   /**
+    * Import certificates in the Windows Certificate Store
+    *
+    * @see <a href="https://docs.microsoft.com/en-us/rest/api/compute/virtualmachines/virtualmachines-create-or-update#bk_srcvault">docs</a>
+    */
+   public AzureTemplateOptions secrets(Iterable<? extends Secrets> secrets) {
+       for (Secrets secret : checkNotNull(secrets, "secrets"))
+           checkNotNull(secret, "secrets can not be empty");
+       this.secrets = ImmutableList.copyOf(secrets);
+       return this;
+    }
+
    public AvailabilitySet getAvailabilitySet() { return availabilitySet; }
    public String getAvailabilitySetName() { return availabilitySetName; }
    public List<DataDisk> getDataDisks() { return dataDisks; }
    public String getResourceGroup() { return resourceGroup; }
    public List<IpOptions> getIpOptions() { return ipOptions; }
+   public WindowsConfiguration getWindowsConfiguration() { return windowsConfiguration; }
+   public List<Secrets> getSecrets() { return secrets; }
 
    @Override
    public AzureTemplateOptions clone() {
@@ -122,6 +150,8 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          eTo.dataDisks(dataDisks);
          eTo.resourceGroup(resourceGroup);
          eTo.ipOptions(ipOptions);
+         eTo.windowsConfiguration(windowsConfiguration);
+         eTo.secrets(secrets);
       }
    }
 
@@ -137,7 +167,9 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
             Objects.equal(resourceGroup, that.resourceGroup) &&
             Objects.equal(availabilitySet, that.availabilitySet) &&
             Objects.equal(dataDisks, that.dataDisks) &&
-            Objects.equal(ipOptions, that.ipOptions);
+            Objects.equal(ipOptions, that.ipOptions) &&
+            Objects.equal(windowsConfiguration, that.windowsConfiguration) &&
+            Objects.equal(secrets, that.secrets);
    }
 
    @Override
@@ -159,6 +191,10 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          toString.add("resourceGroup", resourceGroup);
       if (!ipOptions.isEmpty())
          toString.add("ipOptions", ipOptions);
+      if (windowsConfiguration != null)
+          toString.add("windowsConfiguration", windowsConfiguration);
+      if (!secrets.isEmpty())
+          toString.add("secrets", secrets);
       return toString;
    }
 
@@ -219,5 +255,21 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          AzureTemplateOptions options = new AzureTemplateOptions();
          return options.ipOptions(ipOptions);
       }
+
+      /**
+       * @see AzureTemplateOptions#windowsConfiguration(WindowsConfiguration)
+       */
+      public static AzureTemplateOptions windowsConfiguration(WindowsConfiguration windowsConfiguration) {
+         AzureTemplateOptions options = new AzureTemplateOptions();
+         return options.windowsConfiguration(windowsConfiguration);
+      }
+
+      /**
+       * @see AzureTemplateOptions#secrets(List)
+       */
+      public static AzureTemplateOptions secrets(Iterable<? extends Secrets> secrets) {
+         AzureTemplateOptions options = new AzureTemplateOptions();
+         return options.secrets(secrets);
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae0198/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
index 5592b4c..b77dc9e 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java
@@ -16,15 +16,14 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableList;
+import java.util.List;
 
+import org.jclouds.azurecompute.arm.util.GetEnumValue;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
-import java.util.List;
-import java.util.Map;
-import com.google.common.collect.ImmutableMap;
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
 
 @AutoValue
 public abstract class OSProfile {
@@ -91,15 +90,52 @@ public abstract class OSProfile {
 
       @AutoValue
       public abstract static class WinRM {
+          public enum Protocol {
+
+              HTTP("http"),
+              HTTPS("https"),
+              UNRECOGNIZED("Unrecognized");
+
+              private String value;
+
+              Protocol(String value) {
+                 this.value = value;
+              }
+
+              public static Protocol fromValue(String value) {
+                  return (Protocol) GetEnumValue.fromValueOrDefault(value, Protocol.UNRECOGNIZED);
+              }
+
+              @Override
+              public String toString() {
+                 return this.value;
+              }
+           }
+
+          @AutoValue
+          public abstract static class ProtocolListener {
+
+             public abstract Protocol protocol();
+
+             @Nullable
+             public abstract String certificateUrl();
+
+             @SerializedNames({"protocol", "certificateUrl"})
+             public static ProtocolListener create(final Protocol protocol, final String certificateUrl) {
+
+                return new AutoValue_OSProfile_WindowsConfiguration_WinRM_ProtocolListener(
+                        protocol, certificateUrl);
+             }
+          }
 
          /**
           * Map of different settings
           */
-         public abstract Map<String, String> listeners();
+         public abstract List<ProtocolListener> listeners();
 
          @SerializedNames({"listeners"})
-         public static WinRM create(final Map<String, String> listeners) {
-            return new AutoValue_OSProfile_WindowsConfiguration_WinRM(listeners == null ? ImmutableMap.<String, String>of() : ImmutableMap.copyOf(listeners));
+         public static WinRM create(final List<ProtocolListener> listeners) {
+            return new AutoValue_OSProfile_WindowsConfiguration_WinRM(listeners == null ? ImmutableList.<ProtocolListener>of() : ImmutableList.copyOf(listeners));
          }
       }
 
@@ -139,27 +175,20 @@ public abstract class OSProfile {
        * unattend content
        */
       @Nullable
-      public abstract AdditionalUnattendContent additionalUnattendContent();
+      public abstract List<AdditionalUnattendContent> additionalUnattendContent();
 
       /**
        * is automatic updates enabled
        */
       public abstract boolean enableAutomaticUpdates();
 
-      /**
-       * list of certificates
-       */
-      @Nullable
-      public abstract List<String> secrets();
-
-      @SerializedNames({"provisionVMAgent", "winRM", "additionalUnattendContent", "enableAutomaticUpdates",
-              "secrets"})
+      @SerializedNames({"provisionVMAgent", "winRM", "additionalUnattendContent", "enableAutomaticUpdates"})
       public static WindowsConfiguration create(final boolean provisionVMAgent, final WinRM winRM,
-                                                final AdditionalUnattendContent additionalUnattendContent,
-                                                final boolean enableAutomaticUpdates, final List<String> secrets) {
+                                                final List<AdditionalUnattendContent> additionalUnattendContent,
+                                                final boolean enableAutomaticUpdates) {
 
          return new AutoValue_OSProfile_WindowsConfiguration(provisionVMAgent, winRM,
-                 additionalUnattendContent, enableAutomaticUpdates, secrets == null ? null : ImmutableList.copyOf(secrets));
+                 additionalUnattendContent, enableAutomaticUpdates);
       }
    }
 
@@ -199,11 +228,17 @@ public abstract class OSProfile {
    @Nullable
    public abstract WindowsConfiguration windowsConfiguration();
 
+   /**
+    * The Secrets configuration of the VM
+    */
+   @Nullable
+   public abstract List<Secrets> secrets();
+
    @SerializedNames({"computerName", "adminUsername", "adminPassword", "customData", "linuxConfiguration",
-           "windowsConfiguration"})
+           "windowsConfiguration", "secrets"})
    public static OSProfile create(final String computerName, final String adminUsername, final String adminPassword,
                                   final String customData, final LinuxConfiguration linuxConfiguration,
-                                  final WindowsConfiguration windowsConfiguration) {
+                                  final WindowsConfiguration windowsConfiguration, final List<Secrets> secrets) {
       return builder()
               .computerName(computerName)
               .adminUsername(adminUsername)
@@ -211,6 +246,7 @@ public abstract class OSProfile {
               .customData(customData)
               .linuxConfiguration(linuxConfiguration)
               .windowsConfiguration(windowsConfiguration)
+              .secrets(secrets)
               .build();
    }
    
@@ -234,6 +270,8 @@ public abstract class OSProfile {
 
       public abstract Builder windowsConfiguration(WindowsConfiguration windowsConfiguration);
 
+      public abstract Builder secrets(List<Secrets> secrets);
+
       public abstract OSProfile build();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae0198/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secrets.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secrets.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secrets.java
new file mode 100644
index 0000000..5fcf704
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secrets.java
@@ -0,0 +1,55 @@
+/*
+ * 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;
+import java.util.List;
+
+/**
+ * Group of certificates stored in one and the same KeyVault
+ */
+@AutoValue
+public abstract class Secrets {
+
+    @AutoValue
+    public abstract static class SourceVault {
+
+        public abstract String id();
+
+        @SerializedNames({"id"})
+        public static SourceVault create(final String id) {
+            return new AutoValue_Secrets_SourceVault(id);
+        }
+    }
+
+    /**
+     * Name of the KeyVault which contains all the certificates
+     */
+    public abstract SourceVault sourceVault();
+
+    /**
+     * List of the certificates
+     */
+    public abstract List<VaultCertificate> vaultCertificates();
+
+    @SerializedNames({"sourceVault", "vaultCertificates"})
+    public static Secrets create(final SourceVault sourceVault, final List<VaultCertificate> vaultCertificates) {
+       return new AutoValue_Secrets(sourceVault, vaultCertificates);
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae0198/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultCertificate.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultCertificate.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultCertificate.java
new file mode 100644
index 0000000..dd35eb6
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultCertificate.java
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+/**
+ * Certificate stored in a Key Vault
+ */
+@AutoValue
+public abstract class VaultCertificate {
+
+    /**
+     * The URL of the certificate
+     */
+    public abstract String certificateUrl();
+
+    /**
+     * Certificate's store name
+     */
+    @Nullable
+    public abstract String certificateStore();
+
+    @SerializedNames({"certificateUrl", "certificateStore"})
+    public static VaultCertificate create(final String certificateUrl, final String certificateStore) {
+       return new AutoValue_VaultCertificate(certificateUrl, certificateStore);
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae0198/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
index f3f6aac..34b289e 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
@@ -42,22 +42,28 @@ 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.ResourceDefinition;
+import org.jclouds.azurecompute.arm.domain.Secrets;
 import org.jclouds.azurecompute.arm.domain.StorageAccountType;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
 import org.jclouds.azurecompute.arm.domain.StorageService;
 import org.jclouds.azurecompute.arm.domain.Subnet;
 import org.jclouds.azurecompute.arm.domain.VHD;
+import org.jclouds.azurecompute.arm.domain.VaultCertificate;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.PowerState;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
 import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
 import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface.NetworkInterfaceProperties;
+import org.jclouds.azurecompute.arm.domain.OSProfile.WindowsConfiguration.WinRM.Protocol;
+import org.jclouds.azurecompute.arm.domain.OSProfile.WindowsConfiguration.WinRM.ProtocolListener;
 import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
+import static org.testng.util.Strings.isNullOrEmpty;
 
+import com.beust.jcommander.internal.Lists;
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -79,6 +85,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
       subscriptionid = getSubscriptionId();
 
       createTestResourceGroup();
+
       virtualNetworkName = String.format("vn-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
 
       // Subnets belong to a virtual network so that needs to be created first
@@ -232,9 +239,9 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
 
    private VirtualMachineProperties getProperties(String nic, String blob) {
 
-      HardwareProfile hwProf = HardwareProfile.create("Standard_D1");
-      ImageReference imgRef = ImageReference.builder().publisher("MicrosoftWindowsServerEssentials")
-              .offer("WindowsServerEssentials").sku("WindowsServerEssentials").version("latest").build();
+      HardwareProfile hwProf = HardwareProfile.create("Standard_D1_v2");
+      ImageReference imgRef = ImageReference.builder().publisher("MicrosoftWindowsServer")
+              .offer("WindowsServer").sku("2008-R2-SP1").version("latest").build();
       
       DataDisk.Builder dataDisk = DataDisk.builder().name("data").diskSizeGB("100").lun(0).createOption(DataDisk.DiskCreateOptionTypes.EMPTY);
       
@@ -250,11 +257,25 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
          osDisk.vhd(VHD.create(blob + "vhds/" + vmName + ".vhd"));
          dataDisk.vhd(VHD.create(blob + "vhds/" + vmName + "data.vhd"));
       }
-      
+
       StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk.build(), ImmutableList.of(dataDisk.build()));
-      OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
-              null);
-      OSProfile osProfile = OSProfile.create(vmName, "azureuser", "RFe3&432dg", null, null, windowsConfig);
+
+      List<Secrets> secrets = null;
+      OSProfile.WindowsConfiguration.WinRM winRm = null;
+      if (!isNullOrEmpty(vaultResourceGroup) && !isNullOrEmpty(vaultName) && !isNullOrEmpty(vaultCertificateUrl)) {
+          List<ProtocolListener> listeners = Lists.newArrayList();
+
+          listeners.add(OSProfile.WindowsConfiguration.WinRM.ProtocolListener.create(Protocol.HTTPS, vaultCertificateUrl));
+          listeners.add(OSProfile.WindowsConfiguration.WinRM.ProtocolListener.create(Protocol.HTTP, null));
+
+          winRm = OSProfile.WindowsConfiguration.WinRM.create(listeners);
+          VaultCertificate vaultCertificate = VaultCertificate.create(vaultCertificateUrl, vaultName);
+          secrets = ImmutableList.of(Secrets.create(Secrets.SourceVault.create(String.format("%s/providers/Microsoft.KeyVault/vaults/%s",
+                            api.getResourceGroupApi().get(vaultResourceGroup).id(), vaultName)),
+                    ImmutableList.of(vaultCertificate)));
+      }
+      OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(true, winRm, null, true);
+      OSProfile osProfile = OSProfile.create(vmName, "azureuser", "RFe3&432dg", null, null, windowsConfig, secrets);
       NetworkInterface networkInterface =
             NetworkInterface.create("/subscriptions/" + subscriptionid +
                       "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.Network/networkInterfaces/"

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae0198/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
index 95d967e..83e5ef2 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
@@ -32,15 +32,23 @@ import java.util.List;
 import org.jclouds.azurecompute.arm.domain.DataDisk;
 import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
 import org.jclouds.azurecompute.arm.domain.HardwareProfile;
+import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.ImageReference;
+import org.jclouds.azurecompute.arm.domain.ManagedDiskParameters;
 import org.jclouds.azurecompute.arm.domain.NetworkProfile;
 import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
 import org.jclouds.azurecompute.arm.domain.OSDisk;
 import org.jclouds.azurecompute.arm.domain.OSProfile;
+import org.jclouds.azurecompute.arm.domain.OSProfile.LinuxConfiguration;
+import org.jclouds.azurecompute.arm.domain.OSProfile.WindowsConfiguration.AdditionalUnattendContent;
+import org.jclouds.azurecompute.arm.domain.OSProfile.WindowsConfiguration.WinRM.Protocol;
+import org.jclouds.azurecompute.arm.domain.Secrets.SourceVault;
 import org.jclouds.azurecompute.arm.domain.Plan;
+import org.jclouds.azurecompute.arm.domain.Secrets;
 import org.jclouds.azurecompute.arm.domain.Status;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
 import org.jclouds.azurecompute.arm.domain.VHD;
+import org.jclouds.azurecompute.arm.domain.VaultCertificate;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
@@ -122,18 +130,30 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
             "PUT",
             "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
                   + "/virtualMachines/windowsmachine?validating=false&api-version=2016-04-30-preview",
-            "{\"location\":\"westus\",\"tags\":{\"foo\":\"bar\"},\"properties\":"
-                  + "{\"vmId\":\"27ee085b-d707-xxxx-yyyy-2370e2eb1cc1\","
+            "{\"location\":\"westus\",\"properties\":"
+                  + "{\"vmId\":\"27ee085b-d707-xxxx-yyyy-2370e2eb1cc1\",\"licenseType\":\"Windows_Server\","
+                  + "\"availabilitySet\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/availabilitySets/myAVSet\"},"
                   + "\"hardwareProfile\":{\"vmSize\":\"Standard_D1\"},"
-                  + "\"storageProfile\":{\"imageReference\":{\"publisher\":\"publisher\",\"offer\":\"offer\",\"sku\":\"sku\",\"version\":\"ver\"},"
+                  + "\"storageProfile\":{\"imageReference\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/westus/publishers/MicrosoftWindowsServerEssentials/artifactype/vmimage/offers/OFFER/skus/OFFER/versions/latest\","
+                  + "\"publisher\":\"publisher\",\"offer\":\"OFFER\",\"sku\":\"sku\",\"version\":\"ver\"},"
                   + "\"osDisk\":{\"osType\":\"Windows\",\"name\":\"windowsmachine\","
-                  + "\"vhd\":{\"uri\":\"https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd\"},\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\"},\"dataDisks\":[]},"
-                  + "\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"windowsConfiguration\":{\"provisionVMAgent\":false,\"enableAutomaticUpdates\":true}},"
+                  + "\"vhd\":{\"uri\":\"https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd\"},\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\","
+                  + "\"managedDisk\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk\",\"storageAccountType\":\"Standard_LRS\"}},"
+                  + "\"dataDisks\":[{\"name\":\"mydatadisk1\",\"diskSizeGB\":\"1\",\"lun\":0,\"vhd\":{\"uri\":\"http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd\"},\"createOption\":\"Empty\",\"caching\":\"Unrecognized\"}]},"
+                  + "\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"adminPassword\":\"password\",\"customData\":\"\",\"windowsConfiguration\":{\"provisionVMAgent\":false,"
+                  + "\"winRM\":{\"listeners\":[{\"protocol\":\"https\",\"certificateUrl\":\"url-to-certificate\"}]},\"additionalUnattendContent\":[{\"pass\":\"oobesystem\",\"component\":\"Microsoft-Windows-Shell-Setup\",\"settingName\":\"FirstLogonCommands\",\"content\":\"<XML unattend content>\"}],"
+                  + "\"enableAutomaticUpdates\":true},"
+                  + "\"secrets\":[{\"sourceVault\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/Microsoft.KeyVault/vaults/myvault1\"},\"vaultCertificates\":[{\"certificateUrl\":\"https://myvault1.vault.azure.net/secrets/SECRETNAME/SECRETVERSION\",\"certificateStore\":\"CERTIFICATESTORENAME\"}]}]},"
                   + "\"networkProfile\":{\"networkInterfaces\":[{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167\"}]},"
                   + "\"diagnosticsProfile\":{\"bootDiagnostics\":{\"enabled\":true,\"storageUri\":\"https://groupname2760.blob.core.windows.net/\"}},\"provisioningState\":\"CREATING\"},"
+                  + "\"tags\":{\"foo\":\"bar\"},"
                   + "\"plan\":{\"name\":\"deadline-slave-7-2\",\"publisher\":\"thinkboxsoftware\",\"product\":\"deadline7-2\"}}");
    }
-   
+
+   // See https://docs.microsoft.com/en-us/rest/api/compute/virtualmachines/virtualmachines-create-or-update
+   // for where part of the example json response comes from. Unfortunately examples in the microsoft docs
+   // are not valid json (e.g. missing commas, illegal quotes). Therefore this example merges the original 
+   // real-world example (presumably taken from the jclouds wire log), and snippets from the microsoft docs.
    public void testCreate() throws Exception {
       server.enqueue(jsonResponse("/createvirtualmachineresponse.json"));
 
@@ -145,15 +165,23 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
             "PUT",
             "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
                   + "/virtualMachines/windowsmachine?validating=false&api-version=2016-04-30-preview",
-            "{\"location\":\"westus\",\"tags\":{\"foo\":\"bar\"},\"properties\":"
-                  + "{\"vmId\":\"27ee085b-d707-xxxx-yyyy-2370e2eb1cc1\","
+            "{\"location\":\"westus\",\"properties\":"
+                  + "{\"vmId\":\"27ee085b-d707-xxxx-yyyy-2370e2eb1cc1\",\"licenseType\":\"Windows_Server\","
+                  + "\"availabilitySet\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/availabilitySets/myAVSet\"},"
                   + "\"hardwareProfile\":{\"vmSize\":\"Standard_D1\"},"
-                  + "\"storageProfile\":{\"imageReference\":{\"publisher\":\"publisher\",\"offer\":\"offer\",\"sku\":\"sku\",\"version\":\"ver\"},"
+                  + "\"storageProfile\":{\"imageReference\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/westus/publishers/MicrosoftWindowsServerEssentials/artifactype/vmimage/offers/OFFER/skus/OFFER/versions/latest\","
+                  + "\"publisher\":\"publisher\",\"offer\":\"OFFER\",\"sku\":\"sku\",\"version\":\"ver\"},"
                   + "\"osDisk\":{\"osType\":\"Windows\",\"name\":\"windowsmachine\","
-                  + "\"vhd\":{\"uri\":\"https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd\"},\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\"},\"dataDisks\":[]},"
-                  + "\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"windowsConfiguration\":{\"provisionVMAgent\":false,\"enableAutomaticUpdates\":true}},"
+                  + "\"vhd\":{\"uri\":\"https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd\"},\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\","
+                  + "\"managedDisk\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk\",\"storageAccountType\":\"Standard_LRS\"}},"
+                  + "\"dataDisks\":[{\"name\":\"mydatadisk1\",\"diskSizeGB\":\"1\",\"lun\":0,\"vhd\":{\"uri\":\"http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd\"},\"createOption\":\"Empty\",\"caching\":\"Unrecognized\"}]},"
+                  + "\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"adminPassword\":\"password\",\"customData\":\"\",\"windowsConfiguration\":{\"provisionVMAgent\":false,"
+                  + "\"winRM\":{\"listeners\":[{\"protocol\":\"https\",\"certificateUrl\":\"url-to-certificate\"}]},\"additionalUnattendContent\":[{\"pass\":\"oobesystem\",\"component\":\"Microsoft-Windows-Shell-Setup\",\"settingName\":\"FirstLogonCommands\",\"content\":\"<XML unattend content>\"}],"
+                  + "\"enableAutomaticUpdates\":true},"
+                  + "\"secrets\":[{\"sourceVault\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/Microsoft.KeyVault/vaults/myvault1\"},\"vaultCertificates\":[{\"certificateUrl\":\"https://myvault1.vault.azure.net/secrets/SECRETNAME/SECRETVERSION\",\"certificateStore\":\"CERTIFICATESTORENAME\"}]}]},"
                   + "\"networkProfile\":{\"networkInterfaces\":[{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167\"}]},"
-                  + "\"diagnosticsProfile\":{\"bootDiagnostics\":{\"enabled\":true,\"storageUri\":\"https://groupname2760.blob.core.windows.net/\"}},\"provisioningState\":\"CREATING\"}}");
+                  + "\"diagnosticsProfile\":{\"bootDiagnostics\":{\"enabled\":true,\"storageUri\":\"https://groupname2760.blob.core.windows.net/\"}},\"provisioningState\":\"CREATING\"},"
+                  + "\"tags\":{\"foo\":\"bar\"}}");
    }
 
    public void testDeleteReturns404() throws Exception {
@@ -248,15 +276,31 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
    }
 
    private VirtualMachineProperties getProperties() {
+      String licenseType = "Windows_Server";
+      IdReference availabilitySet = IdReference.create("/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/availabilitySets/myAVSet");
       HardwareProfile hwProf = HardwareProfile.create("Standard_D1");
-      ImageReference imgRef = ImageReference.builder().publisher("publisher").offer("offer").sku("sku").version("ver").build();
+      ImageReference imgRef = ImageReference.builder().publisher("publisher").offer("OFFER").sku("sku").version("ver")
+            .customImageId("/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/westus/publishers/MicrosoftWindowsServerEssentials/artifactype/vmimage/offers/OFFER/skus/OFFER/versions/latest")
+            .build();
       VHD vhd = VHD.create("https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd");
-      List<DataDisk> dataDisks = new ArrayList<DataDisk>();
-      OSDisk osDisk = OSDisk.create("Windows", "windowsmachine", vhd, "ReadWrite", "FromImage", null, null, null);
+      List<DataDisk> dataDisks = ImmutableList.of(
+            DataDisk.create("mydatadisk1", "1", 0, VHD.create("http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd"), 
+                  null, "Empty", null, null, null));
+      ManagedDiskParameters managedDiskParameters = ManagedDiskParameters.create("/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
+            "Standard_LRS");
+      OSDisk osDisk = OSDisk.create("Windows", "windowsmachine", vhd, "ReadWrite", "FromImage", null, managedDiskParameters, null);
       StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk, dataDisks);
-      OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
-            null);
-      OSProfile osProfile = OSProfile.create("windowsmachine", "azureuser", null, null, null, windowsConfig);
+      LinuxConfiguration linuxConfig = null;
+      OSProfile.WindowsConfiguration.WinRM winrm = OSProfile.WindowsConfiguration.WinRM.create(
+            ImmutableList.of(
+                  OSProfile.WindowsConfiguration.WinRM.ProtocolListener.create(Protocol.HTTPS, "url-to-certificate")));
+      List<AdditionalUnattendContent> additionalUnattendContent = ImmutableList.of(
+            AdditionalUnattendContent.create("oobesystem", "Microsoft-Windows-Shell-Setup", "FirstLogonCommands", "<XML unattend content>"));
+      OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, winrm, additionalUnattendContent, true);
+      List<Secrets> secrets =  ImmutableList.of(
+            Secrets.create(SourceVault.create("/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/Microsoft.KeyVault/vaults/myvault1"), 
+                  ImmutableList.of(VaultCertificate.create("https://myvault1.vault.azure.net/secrets/SECRETNAME/SECRETVERSION", "CERTIFICATESTORENAME"))));
+      OSProfile osProfile = OSProfile.create("windowsmachine", "azureuser", "password", "", linuxConfig, windowsConfig, secrets);
       NetworkInterface networkInterface = NetworkInterface.create("/subscriptions/SUBSCRIPTIONID"
             + "/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/" + "windowsmachine167", null);
       List<NetworkInterface> networkInterfaces = new ArrayList<NetworkInterface>();
@@ -266,7 +310,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
             "https://groupname2760.blob.core.windows.net/");
       DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics);
       VirtualMachineProperties properties = VirtualMachineProperties.create("27ee085b-d707-xxxx-yyyy-2370e2eb1cc1",
-            null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile,
+            licenseType, availabilitySet, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile,
             VirtualMachineProperties.ProvisioningState.CREATING);
       return properties;
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae0198/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
index 10406b8..90502fe 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
@@ -41,6 +41,7 @@ import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.Subnet;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
 import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
 
 import com.google.common.base.Predicate;
 import com.google.common.base.Supplier;
@@ -66,6 +67,10 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
    
    protected String resourceGroupName;
    
+   protected String vaultResourceGroup;
+   protected String vaultName;
+   protected String vaultCertificateUrl;
+
    public BaseAzureComputeApiLiveTest() {
       provider = "azurecompute-arm";
    }
@@ -82,6 +87,20 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
       }
    }
 
+   @BeforeClass
+   @Override
+   public void setup() {
+      super.setup();
+
+      // Providing system properties for specifying the required Azure KeyVault configurations for Live tests
+      // They have to be externally provided, because azurecompute-arm doesn't support creating KeyVaults yet
+      //
+      // TODO Replace the used configurations once full KeyVault implementation is added to azurecompute-arm
+      vaultResourceGroup = System.getProperty("test.azurecompute-arm.vault.resource.group");
+      vaultName = System.getProperty("test.azurecompute-arm.vault.name");
+      vaultCertificateUrl = System.getProperty("test.azurecompute-arm.vault.certificate.url");
+   }
+
    @Override protected AzureComputeApi create(Properties props, Iterable<Module> modules) {
       Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
       imageAvailablePredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae0198/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json b/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
index 2963100..bc8ca2d 100644
--- a/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
+++ b/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
@@ -1,37 +1,92 @@
 {
   "properties": {
     "vmId": "27ee085b-d707-xxxx-yyyy-2370e2eb1cc1",
+    "licenseType": "Windows_Server",
+    "availabilitySet": {
+      "id":"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/availabilitySets/myAVSet"
+    },
     "hardwareProfile": {
       "vmSize": "Standard_D1"
     },
     "storageProfile": {
       "imageReference": {
         "publisher": "publisher",
-        "offer": "offer",
+        "offer": "OFFER",
         "sku": "sku",
-        "version": "ver"
+        "version": "ver",
+        "id": "/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/westus/publishers/MicrosoftWindowsServerEssentials/artifactype/vmimage/offers/OFFER/skus/OFFER/versions/latest"
       },
       "osDisk": {
         "osType": "Windows",
         "name": "windowsmachine",
         "createOption": "FromImage",
+        "managedDisk": {
+          "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
+          "storageAccountType": "Standard_LRS"
+        },
         "vhd": {
           "uri": "https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd"
         },
         "caching": "ReadWrite"
       },
-      "dataDisks": []
+      "dataDisks":[
+        {
+          "name":"mydatadisk1",
+          "diskSizeGB":"1",
+          "lun": 0,
+          "vhd": {
+            "uri" : "http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd"
+          },
+          "createOption":"Empty"
+        }
+      ]
     },
     "osProfile": {
       "computerName": "windowsmachine",
       "adminUsername": "azureuser",
+      "adminPassword": "password",
+      "customData": "",
       "windowsConfiguration": {
         "provisionVMAgent": false,
-        "enableAutomaticUpdates": true
+        "enableAutomaticUpdates": true,
+        "winRM": {    
+          "listeners": [
+            {    
+              "protocol": "https",    
+              "certificateUrl": "url-to-certificate"    
+            }
+          ]
+        },    
+        "additionalUnattendContent": [
+          {      
+            "pass":"oobesystem",    
+            "component":"Microsoft-Windows-Shell-Setup",    
+            "settingName":"FirstLogonCommands",    
+            "content":"<XML unattend content>"    
+          }
+        ]
       },
-      "secrets": []
+      "secrets":[
+        {     
+          "sourceVault": {
+             "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/Microsoft.KeyVault/vaults/myvault1"     
+           },
+           "vaultCertificates": [
+             {
+               "certificateUrl": "https://myvault1.vault.azure.net/secrets/SECRETNAME/SECRETVERSION",
+               "certificateStore": "CERTIFICATESTORENAME"
+             }
+           ]
+         }
+       ]
+    },
+    "networkProfile": {
+      "networkInterfaces":[
+        {
+          "id":"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167"
+        }
+      ]
     },
-    "networkProfile": {"networkInterfaces":[{"id":"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167"}]},
     "diagnosticsProfile": {
       "bootDiagnostics": {
         "enabled": true,
@@ -52,4 +107,4 @@
     "publisher": "thinkboxsoftware",
     "product": "deadline7-2"
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae0198/providers/azurecompute-arm/src/test/resources/virtualmachine.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachine.json b/providers/azurecompute-arm/src/test/resources/virtualmachine.json
index 874227d..70e7f4a 100644
--- a/providers/azurecompute-arm/src/test/resources/virtualmachine.json
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachine.json
@@ -1,37 +1,90 @@
 {
   "properties": {
     "vmId": "27ee085b-d707-xxxx-yyyy-2370e2eb1cc1",
+    "licenseType": "Windows_Server",    
+    "availabilitySet":{    
+      "id":"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/availabilitySets/myAVSet"
+    },
     "hardwareProfile": {
       "vmSize": "Standard_D1"
     },
     "storageProfile": {
       "imageReference": {
         "publisher": "publisher",
-        "offer": "offer",
+        "offer": "OFFER",
         "sku": "sku",
-        "version": "ver"
+        "version": "ver",
+        "id": "/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/westus/publishers/MicrosoftWindowsServerEssentials/artifactype/vmimage/offers/OFFER/skus/OFFER/versions/latest"
       },
       "osDisk": {
         "osType": "Windows",
         "name": "windowsmachine",
         "createOption": "FromImage",
+        "managedDisk": {
+          "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
+          "storageAccountType": "Standard_LRS"
+        },
         "vhd": {
           "uri": "https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd"
         },
         "caching": "ReadWrite"
       },
-      "dataDisks": []
+      "dataDisks":[
+        {
+          "name":"mydatadisk1",
+          "diskSizeGB":"1",
+          "lun": 0,
+          "vhd": {
+            "uri" : "http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd"
+          },
+          "createOption":"Empty"
+        }
+      ]
     },
     "osProfile": {
       "computerName": "windowsmachine",
       "adminUsername": "azureuser",
+      "adminPassword":"password",
+      "customData":"",
       "windowsConfiguration": {
         "provisionVMAgent": false,
-        "enableAutomaticUpdates": true
+        "enableAutomaticUpdates": true,
+        "winRM": {
+           "listeners":[{
+             "protocol": "https",
+             "certificateUrl": "url-to-certificate"
+           }]
+        },
+        "additionalUnattendContent":[
+          {
+            "pass":"oobesystem",    
+            "component":"Microsoft-Windows-Shell-Setup",
+            "settingName":"FirstLogonCommands",
+            "content":"<XML unattend content>"
+          }
+        ]
       },
-      "secrets": []
+      "secrets":[
+        {     
+          "sourceVault": {     
+             "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/Microsoft.KeyVault/vaults/myvault1"     
+           },     
+           "vaultCertificates": [
+             {     
+               "certificateUrl": "https://myvault1.vault.azure.net/secrets/SECRETNAME/SECRETVERSION",     
+               "certificateStore": "CERTIFICATESTORENAME"     
+             }
+           ]     
+         }
+       ]
+    },
+    "networkProfile": {
+      "networkInterfaces":[
+        {
+          "id":"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167"
+        }
+      ]
     },
-    "networkProfile": {"networkInterfaces":[{"id":"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167"}]},
     "diagnosticsProfile": {
       "bootDiagnostics": {
         "enabled": true,

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae0198/providers/azurecompute-arm/src/test/resources/virtualmachines.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachines.json b/providers/azurecompute-arm/src/test/resources/virtualmachines.json
index cd0e24b..758a109 100644
--- a/providers/azurecompute-arm/src/test/resources/virtualmachines.json
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachines.json
@@ -3,35 +3,82 @@
     {
       "properties": {
         "vmId": "27ee085b-d707-xxxx-yyyy-2370e2eb1cc1",
+        "licenseType": "Windows_Server",    
+        "availabilitySet":{    
+          "id":"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/availabilitySets/myAVSet"
+        },    
         "hardwareProfile": {
           "vmSize": "Standard_D1"
         },
         "storageProfile": {
           "imageReference": {
             "publisher": "publisher",
-            "offer": "offer",
+            "offer": "OFFER",
             "sku": "sku",
-            "version": "ver"
+            "version": "ver",
+            "id": "/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/westus/publishers/MicrosoftWindowsServerEssentials/artifactype/vmimage/offers/OFFER/skus/OFFER/versions/latest"
           },
           "osDisk": {
             "osType": "Windows",
             "name": "windowsmachine",
             "createOption": "FromImage",
+            "managedDisk": {
+              "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
+              "storageAccountType": "Standard_LRS" 
+            },
             "vhd": {
               "uri": "https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd"
             },
             "caching": "ReadWrite"
           },
-          "dataDisks": []
+          "dataDisks":[
+            {
+              "name":"mydatadisk1",
+              "diskSizeGB":"1",
+              "lun": 0,
+              "vhd": {
+                "uri" : "http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd"
+              },
+              "createOption":"Empty"
+            }
+          ]    
         },
         "osProfile": {
           "computerName": "windowsmachine",
           "adminUsername": "azureuser",
+          "adminPassword":"password",
+          "customData":"",
           "windowsConfiguration": {
             "provisionVMAgent": false,
-            "enableAutomaticUpdates": true
+            "enableAutomaticUpdates": true,
+            "winRM": {
+               "listeners":[{
+                 "protocol": "https",
+                 "certificateUrl": "url-to-certificate"
+               }]
+            },    
+            "additionalUnattendContent":[
+              {
+                "pass":"oobesystem",    
+                "component":"Microsoft-Windows-Shell-Setup",
+                "settingName":"FirstLogonCommands",
+                "content":"<XML unattend content>"
+              }
+            ]
           },
-          "secrets": []
+          "secrets":[
+            {
+              "sourceVault": {
+                 "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/Microsoft.KeyVault/vaults/myvault1"     
+               },
+               "vaultCertificates": [
+                 {
+                   "certificateUrl": "https://myvault1.vault.azure.net/secrets/SECRETNAME/SECRETVERSION",
+                   "certificateStore": "CERTIFICATESTORENAME"
+                 }
+               ]
+             }
+           ]
         },
         "networkProfile": {
           "networkInterfaces": [


[32/50] [abbrv] jclouds git commit: Update Azure ARM credentials instructions

Posted by na...@apache.org.
Update Azure ARM credentials instructions


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

Branch: refs/heads/master
Commit: e1e89b5ffb1053b3ee750309c6b1e16976184c69
Parents: 7d3b1be
Author: Ignasi Barrera <na...@apache.org>
Authored: Wed Oct 25 15:17:39 2017 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Oct 25 15:17:59 2017 +0200

----------------------------------------------------------------------
 providers/azurecompute-arm/README.md | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/e1e89b5f/providers/azurecompute-arm/README.md
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/README.md b/providers/azurecompute-arm/README.md
index 50ebedb..ed8abd4 100644
--- a/providers/azurecompute-arm/README.md
+++ b/providers/azurecompute-arm/README.md
@@ -13,24 +13,21 @@ Install and configure Azure CLI following these [steps](http://azure.microsoft.c
 Using the Azure CLI, run the following commands to create a service principal
 
 ```bash
-# Set mode to ARM
-azure config mode arm
-
 # Enter your Microsoft account credentials when prompted
-azure login
+az login
 
 # Set current subscription to create a service principal
-azure account set <Subscription-id>
+az account set --subscription <Subscription-id>
 
-# Create an AAD application with your information.
-azure ad app create --name <name> --password <password> --home-page <home-page> --identifier-uris <identifier-uris>
+# Create an AD application with your information.
+az ad app create --display-name <name> --password <password> --homepage <home-page> --identifier-uris <identifier-uris>
 
-# For example: azure ad app create --name "jcloudsarm"  --password abcd --home-page "https://jcloudsarm" --identifier-uris "https://jcloudsarm"
+# For example: az ad app create --display-name "jcloudsarm" --password abcd --homepage "https://jcloudsarm" --identifier-uris "https://jcloudsarm"
 
 # Output will include a value for `Application Id`, which will be used for the live tests
 
 # Create a Service Principal
-azure ad sp create <Application-id>
+az ad sp create --id <Application-id>
 
 # Output will include a value for `Object Id`, to be used in the next step 
 ```
@@ -39,13 +36,13 @@ Run the following commands to assign roles to the service principal
 
 ```bash
 # Assign roles for this service principal
-azure role assignment create --objectId <Object-id> -o Contributor -c /subscriptions/<Subscription-id>/
+az role assignment create --role Contributor --assignee <ObjectId>
 ```
 
 Look up the the tenant Id
 
 ```bash
-azure account show -s <Subscription-id> --json
+az account show
 
 # output will be a JSON which will include the `Tenant id`
 ```
@@ -53,7 +50,7 @@ azure account show -s <Subscription-id> --json
 Verify service principal
 
 ```bash
-azure login -u <Application-id> -p <password> --service-principal --tenant <Tenant-id>
+az login -u <Application-id> -p <password> --service-principal --tenant <Tenant-id>
 ```
 
 ## Run Live Tests


[03/50] [abbrv] jclouds git commit: Initial support ManagedDataDisks

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java
new file mode 100644
index 0000000..becfccd
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import java.net.URI;
+import java.util.List;
+import java.util.UUID;
+
+import org.jclouds.azurecompute.arm.domain.CreationData;
+import org.jclouds.azurecompute.arm.domain.Disk;
+import org.jclouds.azurecompute.arm.domain.DiskProperties;
+import org.jclouds.azurecompute.arm.domain.Provisionable;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+@Test(groups = "live", singleThreaded = true)
+public class DiskApiLiveTest extends BaseAzureComputeApiLiveTest {
+
+   public static final String JCLOUDS_IMAGE_PREFIX = "jclouds-";
+   private String diskName;
+
+   @BeforeClass
+   @Override
+   public void setup() {
+      super.setup();
+      createTestResourceGroup();
+      diskName = JCLOUDS_IMAGE_PREFIX + RAND;
+   }
+
+   @Test
+   public void deleteDiskResourceDoesNotExist() {
+      assertNull(api().delete(JCLOUDS_IMAGE_PREFIX + UUID.randomUUID()));
+   }
+
+   @Test
+   public void createDisk() {
+      DiskProperties properties = DiskProperties.builder().creationData(CreationData.create(CreationData.CreateOptions.EMPTY)).diskSizeGB(2).build();
+      Disk dataDisk = api().createOrUpdate(diskName, LOCATION, properties);
+      assertTrue(waitUntilAvailable(diskName), "creation operation did not complete in the configured timeout");
+      assertTrue(dataDisk.properties().diskSizeGB() == 2);
+   }
+
+   @Test(dependsOnMethods = "createDisk")
+   public void getDisk() {
+      Disk dataDisk = api().get(diskName);
+      assertNotNull(dataDisk.name());
+      assertTrue(dataDisk.properties().diskSizeGB() == 2);
+   }
+
+   @Test(dependsOnMethods = "createDisk")
+   public void listDisks() {
+      List<Disk> dataDisks = api().list();
+      assertTrue(dataDisks.size() > 0);
+      final Disk dataDisk = api().get(diskName);
+
+      assertTrue(Iterables.any(dataDisks, new Predicate<Disk>() {
+         @Override
+         public boolean apply(Disk input) {
+            return dataDisk.equals(input);
+         }
+      }));
+   }
+
+   @Test(dependsOnMethods = {"listDisks", "getDisk"}, alwaysRun = true)
+   public void deleteDisk() {
+      URI uri = api().delete(diskName);
+      assertNotNull(uri);
+   }
+
+   private DiskApi api() {
+      return api.getDiskApi(resourceGroupName);
+   }
+
+   private boolean waitUntilAvailable(final String name) {
+      return resourceAvailable.apply(new Supplier<Provisionable>() {
+         @Override public Provisionable get() {
+            Disk disk = api().get(name);
+            return disk == null ? null : disk.properties();
+         }
+      });
+   }
+   
+}
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiMockTest.java
new file mode 100644
index 0000000..4c8ba2e
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiMockTest.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import java.net.URI;
+import java.util.List;
+
+import org.jclouds.azurecompute.arm.domain.CreationData;
+import org.jclouds.azurecompute.arm.domain.Disk;
+import org.jclouds.azurecompute.arm.domain.DiskProperties;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+
+@Test(groups = "unit", testName = "DiskApiMockTest", singleThreaded = true)
+public class DiskApiMockTest extends BaseAzureComputeApiMockTest {
+
+   private final String subscriptionid = "SUBSCRIPTIONID";
+   private final String resourcegroup = "myresourcegroup";
+   private final String diskName = "myDisk";
+   private final String apiVersion = "api-version=2017-03-30";
+
+   public void createDisk() throws InterruptedException {
+
+      server.enqueue(jsonResponse("/creatediskresponse.json").setResponseCode(200));
+
+      final DiskApi diskApi = api.getDiskApi(resourcegroup);
+
+      DiskProperties properties = DiskProperties.builder().diskSizeGB(2).creationData(CreationData.create(CreationData.CreateOptions.EMPTY)).build();
+
+      Disk dataDisk = diskApi.createOrUpdate(diskName, "westus", properties);
+
+      String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/disks/%s?%s", subscriptionid, resourcegroup, diskName, apiVersion);
+      String json = "{\"location\":\"westus\",\"properties\":{\"diskSizeGB\":2,\"creationData\":{\"createOption\":\"Empty\"}}}";
+      assertSent(server, "PUT", path, json);
+
+      assertEquals(dataDisk.properties().provisioningState(), "Updating");
+      assertTrue(dataDisk.properties().diskSizeGB() == 2);
+   }
+
+   public void getDisk() throws InterruptedException {
+
+      server.enqueue(jsonResponse("/getdisk.json").setResponseCode(200));
+
+      final DiskApi diskApi = api.getDiskApi(resourcegroup);
+
+      Disk dataDisk = diskApi.get(diskName);
+
+      String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/disks/%s?%s", subscriptionid, resourcegroup, diskName, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertEquals(dataDisk.name(), diskName);
+      assertTrue(dataDisk.properties().diskSizeGB() == 2);
+   }
+
+   public void getDiskReturns404() throws InterruptedException {
+      server.enqueue(response404());
+
+      final DiskApi diskApi = api.getDiskApi(resourcegroup);
+
+      Disk dataDisk = diskApi.get(diskName);
+
+      String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/disks/%s?%s", subscriptionid, resourcegroup, diskName, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(dataDisk);
+   }
+
+   public void listDisks() throws InterruptedException {
+
+      server.enqueue(jsonResponse("/listdisks.json").setResponseCode(200));
+
+      final DiskApi diskApi = api.getDiskApi(resourcegroup);
+
+      List<Disk> dataDisks = diskApi.list();
+
+      String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/disks?%s", subscriptionid, resourcegroup, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(dataDisks.size() > 0);
+   }
+
+   public void listDisksReturns404() throws InterruptedException {
+      server.enqueue(response404());
+
+      final DiskApi diskApi = api.getDiskApi(resourcegroup);
+
+      List<Disk> dataDisks = diskApi.list();
+
+      String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/disks?%s", subscriptionid, resourcegroup, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(isEmpty(dataDisks));
+   }
+
+   public void deleteDisk() throws InterruptedException {
+
+      server.enqueue(response202WithHeader());
+
+      final DiskApi diskApi = api.getDiskApi(resourcegroup);
+
+      URI uri = diskApi.delete(diskName);
+      Assert.assertNotNull(uri);
+
+      String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/disks/%s?%s", subscriptionid, resourcegroup, diskName, apiVersion);
+      assertSent(server, "DELETE", path);
+   }
+
+   public void deleteDiskResourceDoesNotExist() throws InterruptedException {
+
+      server.enqueue(response204());
+
+      final DiskApi diskApi = api.getDiskApi(resourcegroup);
+
+      URI uri = diskApi.delete(diskName);
+      assertNull(uri);
+
+      String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/disks/%s?%s", subscriptionid, resourcegroup, diskName, apiVersion);
+      assertSent(server, "DELETE", path);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
new file mode 100644
index 0000000..038fc31
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.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.features;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+import org.jclouds.azurecompute.arm.domain.Image;
+import org.jclouds.azurecompute.arm.domain.ImageProperties;
+import org.jclouds.azurecompute.arm.domain.Provisionable;
+import org.jclouds.azurecompute.arm.domain.VirtualMachine;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Supplier;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+@Test(groups = "live", singleThreaded = true)
+public class ImageApiLiveTest extends BaseAzureComputeApiLiveTest {
+
+   public static final String JCLOUDS_VM_IMAGE_PREFIX = "jclouds-vm-image-";
+   private String imageName;
+   private VirtualMachine virtualMachine;
+
+   @BeforeClass
+   @Override
+   public void setup() {
+      super.setup();
+      createTestResourceGroup();
+      imageName = JCLOUDS_VM_IMAGE_PREFIX + RAND;
+      String vmName = "jclouds-vm-" + RAND;
+
+      virtualMachine = api.getVirtualMachineApi(resourceGroupName).createOrUpdate(vmName, LOCATION, VirtualMachineProperties.builder().build(),
+              Collections.<String, String> emptyMap(), null);
+   }
+
+   @Test
+   public void deleteImageResourceDoesNotExist() {
+      assertNull(api().delete(JCLOUDS_VM_IMAGE_PREFIX + UUID.randomUUID()));
+   }
+
+   @Test
+   public void CreateVirtualMachineImageFromExistingVM() {
+      String id = String.format("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/virtualMachines/myVM", getSubscriptionId(), resourceGroupName);
+      ImageProperties properties = ImageProperties.builder()
+              .sourceVirtualMachine(ImageProperties.SourceVirtualMachine.create(id))
+              .build();
+      Image image = api().createOrUpdate(imageName, LOCATION, properties);
+      assertTrue(waitUntilAvailable(imageName), "creation operation did not complete in the configured timeout");
+      assertTrue(id.equals(image.properties().sourceVirtualMachine().id()));
+   }
+
+   @Test(dependsOnMethods = "CreateVirtualMachineImageFromExistingVM")
+   public void getImage() {
+      Image image = api().get(imageName);
+      assertNotNull(image);
+   }
+
+   @Test(dependsOnMethods = "CreateVirtualMachineImageFromExistingVM")
+   public void listImages() {
+      List<Image> images = api().list();
+      assertTrue(images.size() > 0);
+   }
+
+   @Test(dependsOnMethods = {"listImages", "getImage"}, alwaysRun = true)
+   public void deleteImage() {
+      URI uri = api().delete(imageName);
+      assertNotNull(uri);
+   }
+
+   private ImageApi api() {
+      return api.getVirtualMachineImageApi(resourceGroupName);
+   }
+   
+   private boolean waitUntilAvailable(final String name) {
+      return resourceAvailable.apply(new Supplier<Provisionable>() {
+         @Override public Provisionable get() {
+            Image image = api().get(name);
+            return image == null ? null : image.properties();
+         }
+      });
+   }
+}
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
index 6fe65e3..ccf1e70 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
@@ -30,6 +30,7 @@ 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.ManagedDiskParameters;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
 import org.jclouds.azurecompute.arm.domain.NetworkProfile;
@@ -149,7 +150,13 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
 
       String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
       VHD vhd = VHD.create(blob + "vhds/" + vmName + "new-data-disk.vhd");
-      DataDisk newDataDisk = DataDisk.create(vmName + "new-data-disk", "1", 1, vhd, "Empty");
+      DataDisk newDataDisk = DataDisk.builder()
+              .name(vmName + "new-data-disk")
+              .diskSizeGB("1")
+              .lun(1)
+              .createOption(DataDisk.DiskCreateOptionTypes.EMPTY)
+              .vhd(vhd)
+              .build();
       List<DataDisk> oldDataDisks = oldStorageProfile.dataDisks();
       assertEquals(oldDataDisks.size(), 1);
 
@@ -236,14 +243,18 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
    private VirtualMachineProperties getProperties(String blob, String nic) {
 
       HardwareProfile hwProf = HardwareProfile.create("Standard_D1");
-      ImageReference imgRef = ImageReference.create("MicrosoftWindowsServerEssentials",
-              "WindowsServerEssentials", "WindowsServerEssentials", "latest");
-      VHD vhd = VHD.create(blob + "vhds/" + vmName + ".vhd");
-      VHD vhd2 = VHD.create(blob + "vhds/" + vmName + "data.vhd");
-      DataDisk dataDisk = DataDisk.create(vmName + "data", "100", 0, vhd2, "Empty");
+      ImageReference imgRef = ImageReference.builder().publisher("MicrosoftWindowsServerEssentials")
+              .offer("WindowsServerEssentials").sku("WindowsServerEssentials").version("latest").build();
+      DataDisk dataDisk = DataDisk.builder().name("data").diskSizeGB("100").lun(0).createOption(DataDisk.DiskCreateOptionTypes.EMPTY).build();
       List<DataDisk> dataDisks = new ArrayList<DataDisk>();
       dataDisks.add(dataDisk);
-      OSDisk osDisk = OSDisk.create(null, vmName, vhd, "ReadWrite", "FromImage", null);
+
+      OSDisk osDisk = OSDisk.builder()
+              .osType("Windows")
+              .caching(DataDisk.CachingTypes.READ_WRITE.toString())
+              .createOption("FromImage")
+              .managedDiskParameters(ManagedDiskParameters.create(null, ManagedDiskParameters.StorageAccountTypes.STANDARD_LRS.toString()))
+              .build();
       StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk, dataDisks);
       OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
               null);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
index 0c03fb1..34b59c3 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
@@ -16,12 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-import static com.google.common.collect.Iterables.isEmpty;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
 import java.net.URI;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
@@ -38,12 +32,12 @@ 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.Plan;
+import org.jclouds.azurecompute.arm.domain.Status;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
 import org.jclouds.azurecompute.arm.domain.VHD;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
-import org.jclouds.azurecompute.arm.domain.Status;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
 import org.testng.annotations.Test;
 
@@ -51,6 +45,12 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.squareup.okhttp.mockwebserver.MockResponse;
 
+import static com.google.common.collect.Iterables.isEmpty;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
 @Test(groups = "unit", testName = "VirtualMachineApiMockTest", singleThreaded = true)
 public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
 
@@ -60,7 +60,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       assertEquals(vmAPI.get("windowsmachine"),
             getVM(Plan.create("thinkboxsoftware", "deadline-slave-7-2", "deadline7-2")));
       assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/windowsmachine?api-version=2016-03-30");
+            + "/virtualMachines/windowsmachine?api-version=2016-04-30-preview");
    }
 
    public void testGetEmpty() throws Exception {
@@ -68,7 +68,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
       assertNull(vmAPI.get("windowsmachine"));
       assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/windowsmachine?api-version=2016-03-30");
+            + "/virtualMachines/windowsmachine?api-version=2016-04-30-preview");
    }
 
    public void testGetInstanceDetails() throws Exception {
@@ -83,7 +83,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       // assertEquals(actual.statuses().get(0).time().toString(),
       // expected.statuses().get(0).time().toString());
       assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/windowsmachine/instanceView?api-version=2016-03-30");
+            + "/virtualMachines/windowsmachine/instanceView?api-version=2016-04-30-preview");
    }
 
    public void testGetInstanceDetailsEmpty() throws Exception {
@@ -91,7 +91,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
       assertNull(vmAPI.getInstanceDetails("windowsmachine"));
       assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/windowsmachine/instanceView?api-version=2016-03-30");
+            + "/virtualMachines/windowsmachine/instanceView?api-version=2016-04-30-preview");
    }
 
    public void testList() throws Exception {
@@ -99,7 +99,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
       assertEquals(vmAPI.list(), getVMList());
       assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines?api-version=2015-06-15");
+            + "/virtualMachines?api-version=2016-04-30-preview");
    }
 
    public void testListEmpty() throws Exception {
@@ -107,7 +107,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
       assertTrue(isEmpty(vmAPI.list()));
       assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines?api-version=2015-06-15");
+            + "/virtualMachines?api-version=2016-04-30-preview");
    }
 
    public void testCreateWithPlan() throws Exception {
@@ -121,7 +121,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
             server,
             "PUT",
             "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-                  + "/virtualMachines/windowsmachine?validating=false&api-version=2016-03-30",
+                  + "/virtualMachines/windowsmachine?validating=false&api-version=2016-04-30-preview",
             "{\"location\":\"westus\",\"tags\":{\"foo\":\"bar\"},\"properties\":"
                   + "{\"vmId\":\"27ee085b-d707-xxxx-yyyy-2370e2eb1cc1\","
                   + "\"hardwareProfile\":{\"vmSize\":\"Standard_D1\"},"
@@ -144,7 +144,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
             server,
             "PUT",
             "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-                  + "/virtualMachines/windowsmachine?validating=false&api-version=2016-03-30",
+                  + "/virtualMachines/windowsmachine?validating=false&api-version=2016-04-30-preview",
             "{\"location\":\"westus\",\"tags\":{\"foo\":\"bar\"},\"properties\":"
                   + "{\"vmId\":\"27ee085b-d707-xxxx-yyyy-2370e2eb1cc1\","
                   + "\"hardwareProfile\":{\"vmSize\":\"Standard_D1\"},"
@@ -167,7 +167,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       assertNull(uri);
 
       assertSent(server, "DELETE", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/windowsmachine?api-version=2016-03-30");
+            + "/virtualMachines/windowsmachine?api-version=2016-04-30-preview");
    }
 
    public void testDelete() throws Exception {
@@ -181,7 +181,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       assertNotNull(uri);
 
       assertSent(server, "DELETE", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/windowsmachine?api-version=2016-03-30");
+            + "/virtualMachines/windowsmachine?api-version=2016-04-30-preview");
    }
 
    public void testStart() throws Exception {
@@ -192,7 +192,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       vmAPI.start("windowsmachine");
 
       assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/windowsmachine/start?api-version=2015-06-15");
+            + "/virtualMachines/windowsmachine/start?api-version=2016-04-30-preview");
    }
 
    public void testRestart() throws Exception {
@@ -203,7 +203,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       vmAPI.restart("windowsmachine");
 
       assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/windowsmachine/restart?api-version=2015-06-15");
+            + "/virtualMachines/windowsmachine/restart?api-version=2016-04-30-preview");
    }
 
    public void testStop() throws Exception {
@@ -214,7 +214,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       vmAPI.stop("windowsmachine");
 
       assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/windowsmachine/powerOff?api-version=2015-06-15");
+            + "/virtualMachines/windowsmachine/powerOff?api-version=2016-04-30-preview");
    }
 
    public void testGeneralize() throws Exception {
@@ -222,7 +222,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
       vmAPI.generalize("vm"); // IllegalStateException if failed
       assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/vm/generalize?api-version=2015-06-15");
+            + "/virtualMachines/vm/generalize?api-version=2016-04-30-preview");
    }
 
    public void testCapture() throws Exception {
@@ -232,7 +232,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       URI uri = vmAPI.capture("vm", "prefix", "container");
       assertNotNull(uri);
       assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/vm/capture?api-version=2015-06-15",
+            + "/virtualMachines/vm/capture?api-version=2016-04-30-preview",
             "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\"}");
    }
 
@@ -243,16 +243,16 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       URI uri = vmAPI.capture("vm", "prefix", "container");
       assertNull(uri);
       assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
-            + "/virtualMachines/vm/capture?api-version=2015-06-15",
+            + "/virtualMachines/vm/capture?api-version=2016-04-30-preview",
             "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\"}");
    }
 
    private VirtualMachineProperties getProperties() {
       HardwareProfile hwProf = HardwareProfile.create("Standard_D1");
-      ImageReference imgRef = ImageReference.create("publisher", "offer", "sku", "ver");
+      ImageReference imgRef = ImageReference.builder().publisher("publisher").offer("offer").sku("sku").version("ver").build();
       VHD vhd = VHD.create("https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd");
       List<DataDisk> dataDisks = new ArrayList<DataDisk>();
-      OSDisk osDisk = OSDisk.create("Windows", "windowsmachine", vhd, "ReadWrite", "FromImage", null);
+      OSDisk osDisk = OSDisk.create("Windows", "windowsmachine", vhd, "ReadWrite", "FromImage", null, null);
       StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk, dataDisks);
       OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
             null);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
index 8cd662a..6006392 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
@@ -16,6 +16,9 @@
  */
 package org.jclouds.azurecompute.arm.internal;
 
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
 import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
@@ -27,15 +30,12 @@ import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
 import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
 import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
 
-import java.util.Properties;
-import java.util.concurrent.TimeUnit;
-
 public class AzureLiveTestUtils {
 
     public static Properties defaultProperties(Properties properties) {
        properties = properties == null ? new Properties() : properties;
        properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
-       properties.put(PROPERTY_REGIONS, "eastus");
+       properties.put(PROPERTY_REGIONS, "westeurope");
        properties.put(IMAGE_PUBLISHERS, "Canonical");
        properties.put(RESOURCENAME_PREFIX, "jcloudstest");
        

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/test/resources/creatediskresponse.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/creatediskresponse.json b/providers/azurecompute-arm/src/test/resources/creatediskresponse.json
new file mode 100644
index 0000000..1fcc2bb
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/creatediskresponse.json
@@ -0,0 +1,11 @@
+{
+  "properties": {
+    "creationData": {
+      "createOption": "Empty"
+    },
+    "diskSizeGB": 2,
+    "provisioningState": "Updating",
+    "isArmResource": true
+  },
+  "location": "westeurope"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/test/resources/getdisk.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/getdisk.json b/providers/azurecompute-arm/src/test/resources/getdisk.json
new file mode 100644
index 0000000..db09d8d
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/getdisk.json
@@ -0,0 +1,19 @@
+{
+  "sku": {
+    "name": "Standard_LRS",
+    "tier": "Standard"
+  },
+  "properties": {
+    "creationData": {
+      "createOption": "Empty"
+    },
+    "diskSizeGB": 2,
+    "timeCreated": "2017-03-01T09:38:18.5808215+00:00",
+    "provisioningState": "Succeeded",
+    "diskState": "Unattached"
+  },
+  "type": "Microsoft.Compute/disks",
+  "location": "westeurope",
+  "id": "/subscriptions/610bba05-d7a7-4567-96af-48ecbd09453b/resourceGroups/rg-diskapilivetest-andrea/providers/Microsoft.Compute/disks/myDisk",
+  "name": "myDisk"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/test/resources/image.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/image.json b/providers/azurecompute-arm/src/test/resources/image.json
new file mode 100644
index 0000000..3dbdf11
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/image.json
@@ -0,0 +1,43 @@
+{
+  "location": "West US",
+  "tags": {
+    "key": "value"
+  },
+  "properties": {
+    "sourceVirtualMachine": {
+      "id": "/subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM"
+    },
+    "storageProfile": {
+      "osDisk": {
+        "osType": "Windows",
+        "blobUri": "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
+        "snapshot": {
+          "id": "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1"
+        },
+        "managedDisk": {
+          "id": "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk1"
+        },
+        "osState": "generalized",
+        "hostCaching": "readwrite",
+        "storageAccountType": "Standard_LRS",
+        "diskSizeGB": 20
+      },
+      "dataDisks": [
+        {
+          "lun": "1",
+          "blobUri": "https://mystorageaccount.blob.core.windows.net/dataimages/dataimage.vhd",
+          "snapshot": {
+            "id": "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot2"
+          },
+          "managedDisk": {
+            "id": "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk2"
+          },
+          "hostCaching": "readwrite",
+          "storageAccountType": "Standard_LRS",
+          "diskSizeInGB": 20
+        }
+      ]
+    },
+    "provisioningState": "creating"
+  }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/37dcb87d/providers/azurecompute-arm/src/test/resources/listdisks.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/listdisks.json b/providers/azurecompute-arm/src/test/resources/listdisks.json
new file mode 100644
index 0000000..c84c561
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/listdisks.json
@@ -0,0 +1,23 @@
+{
+  "value": [
+    {
+      "sku": {
+        "name": "Standard_LRS",
+        "tier": "Standard"
+      },
+      "properties": {
+        "creationData": {
+          "createOption": "Empty"
+        },
+        "diskSizeGB": 2,
+        "timeCreated": "2017-03-01T09:48:27.4526118+00:00",
+        "provisioningState": "Succeeded",
+        "diskState": "Unattached"
+      },
+      "type": "Microsoft.Compute/disks",
+      "location": "westeurope",
+      "id": "/subscriptions/610bba05-d7a7-4567-96af-48ecbd09453b/resourceGroups/rg-diskapilivetest-andrea/providers/Microsoft.Compute/disks/jclouds-646",
+      "name": "jclouds-646"
+    }
+  ]
+}


[28/50] [abbrv] jclouds git commit: Make auto service optional

Posted by na...@apache.org.
Make auto service optional

This makes dependencies consistent and eliminates warnings of the
form:

$M2_HOME/repository/org/apache/jclouds/driver/jclouds-slf4j/2.1.0-SNAPSHOT/jclouds-slf4j-2.1.0-SNAPSHOT.jar(org/jclouds/logging/slf4j/config/SLF4JLoggingModule.class): warning: Cannot find annotation method 'value()' in type 'AutoService': class file for com.google.auto.service.AutoService not found

Reference:

https://github.com/google/auto/tree/master/service#download


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

Branch: refs/heads/master
Commit: fd00c7db7504a8067a2a972f7606e29ff067f51d
Parents: 4e66420
Author: Andrew Gaul <ga...@apache.org>
Authored: Wed Aug 30 12:24:36 2017 -0700
Committer: Andrew Gaul <ga...@apache.org>
Committed: Wed Aug 30 12:26:29 2017 -0700

----------------------------------------------------------------------
 providers/azurecompute-arm/pom.xml | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/fd00c7db/providers/azurecompute-arm/pom.xml
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/pom.xml b/providers/azurecompute-arm/pom.xml
index 028e476..72ff3e2 100644
--- a/providers/azurecompute-arm/pom.xml
+++ b/providers/azurecompute-arm/pom.xml
@@ -52,6 +52,7 @@
       <groupId>com.google.auto.service</groupId>
       <artifactId>auto-service</artifactId>
       <scope>provided</scope>
+      <optional>true</optional>
     </dependency>
     <dependency>
       <groupId>com.google.auto.value</groupId>


[45/50] [abbrv] jclouds git commit: Add Azure KeyVault support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiLiveTest.java
new file mode 100644
index 0000000..026aa28
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiLiveTest.java
@@ -0,0 +1,1057 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import org.jclouds.azurecompute.arm.domain.Certificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contact;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contacts;
+import org.jclouds.azurecompute.arm.domain.Certificate.AdministrationDetails;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateIssuer;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateOperation;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificatePolicy;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.OrganizationDetails;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerCredentials;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerParameters;
+import org.jclouds.azurecompute.arm.domain.Certificate.KeyProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.SecretProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.X509CertificateProperties;
+import org.jclouds.azurecompute.arm.domain.Secret;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretBundle;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretAttributes;
+import org.jclouds.azurecompute.arm.domain.Secret.DeletedSecretBundle;
+import org.jclouds.azurecompute.arm.domain.Key;
+import org.jclouds.azurecompute.arm.domain.Key.JsonWebKey;
+import org.jclouds.azurecompute.arm.domain.Key.KeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.KeyAttributes;
+import org.jclouds.azurecompute.arm.domain.Key.DeletedKeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.KeyOperationResult;
+import org.jclouds.azurecompute.arm.domain.SKU;
+import org.jclouds.azurecompute.arm.domain.Vault;
+import org.jclouds.azurecompute.arm.domain.Vault.DeletedVault;
+import org.jclouds.azurecompute.arm.domain.VaultProperties;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
+import org.testng.SkipException;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+import static com.google.common.base.Preconditions.checkState;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+
+@Test(groups = "live", testName = "VaultApiLiveTest")
+public class VaultApiLiveTest extends BaseAzureComputeApiLiveTest {
+   private String vaultName;
+   private URI vaultUri = null;
+   private static String KEY_NAME = "myKey";
+   private static String IMPORT_KEY_NAME = "myImportKey";
+   private static String RECOVERABLE_KEY_NAME = "myRecoverableKey";
+   private static String SECRET_NAME = "mySecret";
+   private static String RECOVERABLE_SECRET_NAME = "myRecoverableSecret";
+   private static String CERTIFICATE_NAME = "myCertificate";
+   private static String TEMP_CERTIFICATE_NAME = "myTempCertificate";
+   private static String RECOVERABLE_CERTIFICATE_NAME = "myRecoverableCertificate";
+   private static String IMPORTABLE_CERTIFICATE_NAME = "myImportableCertificate";
+   private String importableCertificatePem = stringFromResource("/vaultimportablecert.txt");
+   private String sampleSecret = stringFromResource("/vaultsamplesecret.txt");
+   private static String cryptoText = "R29sZCUyNTIxJTJCR29sZCUyNTIxJTJCR2" +
+           "9sZCUyQmZyb20lMkJ0aGUlMkJBbWVyaWNhbiUyQlJpdmVyJTI1MjE";
+   private static String cryptoAlgorithm = "RSA-OAEP";
+   private static String hashToSign = "FvabKT6qGwpml59iHUJ72DZ4XyJcJ8bgpgFA4_8JFmM";
+   private static String signatureAlgorithm = "RS256";
+   private static String contentEncryptionKey = "YxzoHR65aFwD2_IOiZ5rD08jMSALA1y7b_yYW0G3hyI";
+
+   @BeforeClass
+   @Override
+   public void setup() {
+      super.setup();
+      createTestResourceGroup();
+      vaultName = String.format("kv%s", this.getClass().getSimpleName().toLowerCase());
+   }
+
+   @AfterClass(alwaysRun = true)
+   public void forceVaultRemoval() {
+      // see if the vault has been deleted or not
+      Vault vault = api().getVault(vaultName);
+      if (vault != null) {
+         if ((vault.properties().enableSoftDelete() != null) && vault.properties().enableSoftDelete()) {
+            api().deleteVault(vaultName);
+            checkState(deletedVaultStatus.create(resourceGroupName, true).apply(vaultName),
+                    "vault was not deleted before timeout");
+         } else {
+            return;
+         }
+      }
+
+      DeletedVault deletedVault = api().getDeletedVault(LOCATION, vaultName);
+      if (deletedVault != null) {
+         api().purgeVault(LOCATION, vaultName);
+         checkState(deletedVaultStatus.create(resourceGroupName, false).apply(vaultName),
+                 "vault was not purged before timeout");
+      }
+   }
+
+   @Test
+   public void testCreate() {
+      String objectId = api.getServicePrincipal().get().objectId();
+      Vault vault = api().createOrUpdateVault(vaultName, LOCATION, VaultProperties.builder()
+              .tenantId(tenantId)
+              .sku(SKU.create(LOCATION, "standard", null, "A"))
+              .accessPolicies(ImmutableList.of(VaultProperties.AccessPolicyEntry.create(null, objectId, tenantId,
+                      VaultProperties.Permissions.create(
+                              ImmutableList.of( // certificates
+                                      "Get",
+                                      "List",
+                                      "Update",
+                                      "Create",
+                                      "Import",
+                                      "Delete",
+                                      "ManageContacts",
+                                      "ManageIssuers",
+                                      "GetIssuers",
+                                      "ListIssuers",
+                                      "SetIssuers",
+                                      "DeleteIssuers",
+                                      "Purge",
+                                      "Recover"
+                              ),
+                              ImmutableList.of( // keys
+                                      "Get",
+                                      "List",
+                                      "Update",
+                                      "Create",
+                                      "Import",
+                                      "Delete",
+                                      "Recover",
+                                      "Backup",
+                                      "Restore",
+                                      "Purge",
+                                      "Encrypt",
+                                      "Decrypt",
+                                      "Sign",
+                                      "Verify",
+                                      "WrapKey",
+                                      "UnwrapKey"
+                              ),
+                              ImmutableList.of( // secrets
+                                      "Get",
+                                      "List",
+                                      "Set",
+                                      "Delete",
+                                      "Recover",
+                                      "Backup",
+                                      "Restore",
+                                      "Purge"
+                              ),
+                              ImmutableList.<String>of()
+                      ))))
+              .build(),
+              null);
+      vaultUri = vault.properties().vaultUri();
+      assertTrue(!vault.name().isEmpty());
+   }
+
+   @Test(dependsOnMethods = "testCreate")
+   public void testGet() {
+      Vault vaultFound = api().getVault(vaultName);
+      assertNotNull(vaultFound);
+   }
+
+   @Test(dependsOnMethods = "testCreate")
+   public void testList() {
+      for (Vault vault : api().listVaults()) {
+         assertTrue(!vault.name().isEmpty());
+      }
+   }
+
+   @Test(dependsOnMethods = {"testDeleteKey", "testDeleteSecret"})
+   public void testUpdateVaultToSoftDelete() {
+      Vault v = api().getVault(vaultName);
+      assertNotNull(v);
+      VaultProperties newProps = VaultProperties.create(v.properties().tenantId(),
+              v.properties().vaultUri(),
+              v.properties().enabledForDeployment(),
+              v.properties().enabledForTemplateDeployment(),
+              true,
+              v.properties().createMode(),
+              v.properties().sku(),
+              v.properties().accessPolicies());
+      Vault updatedVault = api().createOrUpdateVault(vaultName, LOCATION, newProps, null);
+      assertNotNull(updatedVault);
+      updatedVault = api().getVault(vaultName);
+      assertTrue(updatedVault.properties().enableSoftDelete());
+   }
+
+   @Test(dependsOnMethods = {"testPurgeDeletedKey", "testPurgeDeletedSecret"})
+   public void testDelete() {
+      boolean result =  api().deleteVault(vaultName);
+      assertTrue(result);
+      checkState(deletedVaultStatus.create(resourceGroupName, true).apply(vaultName),
+              "vault was not deleted before timeout");
+   }
+
+   @Test(dependsOnMethods = "testDelete")
+   public void testGetDeleted() {
+      DeletedVault dv = api().getDeletedVault(LOCATION, vaultName);
+      assertNotNull(dv);
+   }
+
+   @Test(dependsOnMethods = "testDelete")
+   public void testListDeleted() {
+      for (DeletedVault vault : api().listDeletedVaults()) {
+         assertNotNull(vault.name());
+      }
+   }
+
+   @Test(dependsOnMethods = {"testGetDeleted", "testListDeleted"})
+   public void testPurgeDeletedVault() {
+      api().purgeVault(LOCATION, vaultName);
+      checkState(deletedVaultStatus.create(resourceGroupName, true).apply(vaultName),
+              "vault was not purged before timeout");
+
+   }
+
+   @Test(dependsOnMethods = "testGet")
+   public void testCreateKey() {
+      KeyAttributes keyAttr = KeyAttributes.create(true, 0, null, null, null, null);
+      KeyBundle keyBundle = api().createKey(vaultUri,
+              KEY_NAME,
+              keyAttr,
+              null,
+              null,
+              2048,
+              "RSA",
+              null
+      );
+      assertNotNull(keyBundle);
+   }
+
+   @Test(dependsOnMethods = "testCreateKey")
+   public void testImportKey() {
+      KeyAttributes keyAttr = KeyAttributes.create(true, null, null, null, null, null);
+      List<String> keyOps = new ArrayList<String>();
+      keyOps.add("encrypt");
+      JsonWebKey keyInfo = JsonWebKey.create(
+              null,
+              "DjU54mYvHpICXHjc5-JiFqiH8NkUgOG8LL4kwt3DeBp9bP0-5hSJH8vmzwJkeGG9L79EWG4b_bfxgYdeNX7cFFagmW" +
+                      "PRFrlxbd64VRYFawZHRJt-2cbzMVI6DL8EK4bu5Ux5qTiV44Jw19hoD9nDzCTfPzSTSGrKD3iLPdnREYaIGDVxcjB" +
+                      "v3Tx6rrv3Z2lhHHKhEHb0RRjATcjAVKV9NZhMajJ4l9pqJ3A4IQrCBl95ux6Xm1oXP0i6aR78cjchsCpcMXdP3WMs" +
+                      "vHgTlsZT0RZLFHrvkiNHlPiil4G2_eHkwvT__CrcbO6SmI_zCtMmypuHJqcr-Xb7GPJoa64WoQ",
+              "DB9nGuHplY_7Xv5a5UCs5YgxkWPtJFfbIZ1Zr-XHCCY09JIWReOGQG226OhjwixKtOK_OqmAKtMKM9OmKviJRHNbD" +
+                      "hbTxumN3u7cL8dftjXpSryiEQlPmWyW94MneI2WNIrvh4wruQuDt8EztgOiDFxwcnUgey8iend7WmZnE7E",
+              "O-bSTUQ4N_UuQezgkF3TDrnBraO67leDGwRbfiE_U0ghQvqh5DA0QSPVzlWDZc9KUitvj8vxsR9o1PW9GS0an17GJ" +
+                      "EYuetLnkShKK3NWOhBBX6d1yP9rVdH6JhgIJEy_g0Suz7TAFiFc8i7JF8u4QJ05C8bZAMhOLotqftQeVOM",
+              "AQAB",
+              null,
+              null,
+              keyOps,
+              null,
+              "RSA",
+              "33TqqLR3eeUmDtHS89qF3p4MP7Wfqt2Zjj3lZjLjjCGDvwr9cJNlNDiuKboODgUiT4ZdPWbOiMAfDcDzlOxA04DDnEF" +
+                      "GAf-kDQiNSe2ZtqC7bnIc8-KSG_qOGQIVaay4Ucr6ovDkykO5Hxn7OU7sJp9TP9H0JH8zMQA6YzijYH9LsupTerrY" +
+                      "3U6zyihVEDXXOv08vBHk50BMFJbE9iwFwnxCsU5-UZUZYw87Uu0n4LPFS9BT8tUIvAfnRXIEWCha3KbFWmdZQZlyr" +
+                      "Fw0buUEf0YN3_Q0auBkdbDR_ES2PbgKTJdkjc_rEeM0TxvOUf7HuUNOhrtAVEN1D5uuxE1WSw",
+              "8K33pX90XX6PZGiv26wZm7tfvqlqWFT03nUMvOAytqdxhO2HysiPn4W58OaJd1tY4372Qpiv6enmUeI4MidCie-s-d0" +
+                      "_B6A0xfhU5EeeaDN0xDOOl8yN-kaaVj9b4HDR3c91OAwKpDJQIeJVZtxoijxl-SRx3u7Vs_7meeSpOfE",
+              "7a5KnUs1pTo72A-JquJvIz4Eu794Yh3ftTk_Et-83aE_FVc6Nk-EhfnwYSNpVmM6UKdrAoy5gsCvZPxrq-eR9pEwU8M" +
+                      "5UOlki03vWY_nqDBpJSIqwPvGHUB16zvggsPQUyQBfnN3N8XlDi12n88ltvWwEhn1LQOwMUALEfka9_s",
+              "InfGmkb2jNkPGuNiZ-mU0-ZrOgLza_fLL9ErZ35jUPhGFzdGxJNobklvsNoTd-E2GAU41YkJh24bncMLvJVYxHHA5iF" +
+                      "7FBWx1SvpEyKVhhnIcuXGD7N5PbNZzEdmr9C6I7cPVkWO-sUV7zfFukexIcANmsd_oBBGKRoYzP5Tti4",
+              null,
+              null
+      );
+      KeyBundle importedKey = api().importKey(vaultUri, IMPORT_KEY_NAME, false, keyAttr, keyInfo, null);
+      assertNotNull(importedKey);
+   }
+
+   @Test(dependsOnMethods = "testCreateKey")
+   public void testListKeys() {
+      for (Key key : api().listKeys(vaultUri)) {
+         assertNotNull(key);   
+      }
+   }
+
+   @Test(dependsOnMethods = "testListKeys")
+   public void testGetKey() {
+      KeyBundle keyBundle = api().getKey(vaultUri, KEY_NAME);
+      assertNotNull(keyBundle);
+   }
+
+   @Test(dependsOnMethods = "testGetKey")
+   public void testUpdateKey() {
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing");
+      KeyBundle updatedKey = api().updateKey(vaultUri, KEY_NAME, "", null, null, tags);
+      assertNotNull(updatedKey.tags());
+      assertEquals(updatedKey.tags().size(), 1);
+   }
+
+   @Test(dependsOnMethods = "testUpdateKey")
+   public void testListKeyVersions() {
+      // Create a second version of the key
+      KeyAttributes keyAttr = KeyAttributes.create(true, null, null, null, null, null);
+      KeyBundle keyBundle = api().createKey(vaultUri,
+              KEY_NAME,
+              keyAttr,
+              null,
+              null,
+              3072,
+              "RSA",
+              null);
+
+      // List key versions
+      List<Key> keys = api().getKeyVersions(vaultUri, KEY_NAME);
+      assertNotNull(keys);
+      assertTrue(keys.size() > 1);
+   }
+
+   @Test(dependsOnMethods = "testListKeyVersions")
+   public void testUpdateKeyWithVersion() {
+      List<Key> keys = api().getKeyVersions(vaultUri, KEY_NAME);
+      assertNotNull(keys);
+      assertTrue(keys.size() > 1);
+
+      // get key version to operate on
+      Key key = keys.get(1);
+      assertNotNull(key);
+      final String version = key.kid().substring(key.kid().lastIndexOf("/") + 1).trim();
+
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing again");
+      KeyBundle updatedKey = api().updateKey(vaultUri, KEY_NAME, version, null, null, tags);
+      assertNotNull(updatedKey);
+
+      FluentIterable<Key> iKeys = FluentIterable.from(api().getKeyVersions(vaultUri, KEY_NAME));
+      assertTrue(iKeys.anyMatch(new Predicate<Key>() {
+         @Override public boolean apply(Key input) {
+            return input.kid().contains(version);
+         }
+      }));
+
+      assertEquals(tags, updatedKey.tags());
+   }
+
+   @Test(dependsOnMethods = "testUpdateKeyWithVersion")
+   public void testBackupRestoreKey() {
+      KeyBundle originalKey = api().getKey(vaultUri, KEY_NAME);
+      assertNotNull(originalKey);
+
+      String backupKey = api().backupKey(vaultUri, KEY_NAME);
+      assertNotNull(backupKey);
+
+      DeletedKeyBundle dkb = api().deleteKey(vaultUri, KEY_NAME);
+      assertNotNull(dkb);
+
+      KeyBundle restoredKey = api().restoreKey(vaultUri, backupKey);
+      assertNotNull(restoredKey);
+
+      KeyBundle verifyKey = api().getKey(vaultUri, KEY_NAME);
+      assertNotNull(verifyKey);
+
+      assertEquals(verifyKey, originalKey);
+   }
+
+   @Test(dependsOnMethods = "testBackupRestoreKey")
+   public void testDeleteKey() {
+      DeletedKeyBundle dkb = api().deleteKey(vaultUri, KEY_NAME);
+      assertNotNull(dkb);
+   }
+
+   @Test(dependsOnMethods = "testUpdateVaultToSoftDelete")
+   public void testCreateRecoverableKey() {
+      KeyAttributes keyAttr = KeyAttributes.create(true, null, null, null, null, null);
+      KeyBundle keyBundle = api().createKey(vaultUri, RECOVERABLE_KEY_NAME,
+              keyAttr,
+              null,
+              null,
+              2048,
+              "RSA",
+              null
+      );
+      assertNotNull(keyBundle);
+      checkState(recoverableKeyStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_KEY_NAME),
+              "key was not created before timeout");
+   }
+
+   @Test(dependsOnMethods = "testCreateRecoverableKey")
+   public void testDeleteRecoverableKey() {
+      DeletedKeyBundle dkb = api().deleteKey(vaultUri, RECOVERABLE_KEY_NAME);
+      assertNotNull(dkb.deletedDate());
+      assertNotNull(dkb.recoveryId());
+      checkState(deletedKeyStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_KEY_NAME),
+              "key was not deleted before timeout");
+   }
+
+   @Test(dependsOnMethods = "testDeleteRecoverableKey")
+   public void testListDeletedKeys() {
+      for (DeletedKeyBundle key : api().listDeletedKeys(vaultUri)) {
+         assertNotNull(key.deletedDate());
+      }
+   }
+
+   @Test(dependsOnMethods = "testListDeletedKeys")
+   public void testGetDeletedKey() {
+      DeletedKeyBundle key = api().getDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+      assertNotNull(key.deletedDate());
+   }
+
+   @Test(dependsOnMethods = {"testDeleteRecoverableKey", "testGetDeletedKey"})
+   public void testRecoverDeletedKey() {
+      KeyBundle key = api().recoverDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+      checkState(recoverableKeyStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_KEY_NAME),
+              "key was not recovered before timeout");
+   }
+
+   @Test(dependsOnMethods = "testRecoverDeletedKey")
+   public void testPurgeDeletedKey() {
+      // delete the key
+      DeletedKeyBundle dkb = api().deleteKey(vaultUri, RECOVERABLE_KEY_NAME);
+      checkState(deletedKeyStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_KEY_NAME),
+              "key was not deleted before timeout");
+
+      // purge the key and verify that it is no longer listed as deleted
+      api().purgeDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+      checkState(deletedKeyStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_KEY_NAME),
+              "key was not purged before timeout");
+   }
+
+   @Test(dependsOnMethods = "testCreateKey")
+   public void testEncryptDecrypt() {
+      // Encrypt some text
+      KeyOperationResult encryptResult = api().encrypt(vaultUri,
+              KEY_NAME,
+              "",
+              cryptoAlgorithm,
+              cryptoText
+      );
+      assertNotNull(encryptResult);
+      assertTrue(encryptResult.value().length() > cryptoText.length());
+
+      // Decrypt the encrypted text
+      KeyOperationResult decryptResult = api().decrypt(vaultUri,
+              KEY_NAME,
+              "",
+              cryptoAlgorithm,
+              encryptResult.value()
+      );
+      assertNotNull(decryptResult);
+      assertTrue(decryptResult.value().equals(cryptoText));
+   }
+
+   @Test(dependsOnMethods = "testCreateKey")
+   public void testSignVerify() {
+      // Sign a hash
+      KeyOperationResult signResult = api().sign(vaultUri,
+              KEY_NAME,
+              "",
+              signatureAlgorithm,
+              hashToSign
+      );
+      assertNotNull(signResult);
+      assertTrue(!signResult.value().isEmpty());
+
+      // Verify the signature
+      boolean verifyResult = api().verify(vaultUri,
+              KEY_NAME,
+              "",
+              signatureAlgorithm,
+              hashToSign,
+              signResult.value()
+      );
+      assertTrue(verifyResult);
+   }
+
+   @Test(dependsOnMethods = "testCreateKey")
+   public void testWrapUnwrapKey() {
+      // Wrap a 256bit symmetric key
+      KeyOperationResult wrapResult = api().wrap(vaultUri,
+              KEY_NAME,
+              "",
+              cryptoAlgorithm,
+              contentEncryptionKey
+      );
+      assertNotNull(wrapResult);
+      assertTrue(!wrapResult.value().isEmpty());
+
+      // Unwrap symmetric key
+      KeyOperationResult unwrapResult = api().unwrap(vaultUri,
+              KEY_NAME,
+              "",
+              cryptoAlgorithm,
+              wrapResult.value()
+      );
+      assertNotNull(unwrapResult);
+      assertTrue(unwrapResult.value().equals(contentEncryptionKey));
+   }
+
+   @Test(dependsOnMethods = "testBackupRestoreKey")
+   public void testSetSecret() {
+      SecretAttributes attributes = SecretAttributes.create(true, null, null, null, null, null);
+      SecretBundle secretBundle = api().setSecret(vaultUri,
+              SECRET_NAME,
+              attributes,
+              "testSecretKey",
+              null,
+              sampleSecret
+      );
+      assertNotNull(secretBundle);
+   }
+
+   @Test(dependsOnMethods = "testSetSecret")
+   public void testGetSecret() {
+      SecretBundle secret = api().getSecret(vaultUri, SECRET_NAME, null);
+      assertNotNull(secret);
+   }
+
+   @Test(dependsOnMethods = "testSetSecret")
+   public void testGetSecrets() {
+      for (Secret secret : api().listSecrets(vaultUri)) {
+         assertNotNull(secret);
+      }
+   }
+
+   @Test(dependsOnMethods = {"testBackupRestoreSecret"})
+   public void testDeleteSecret() {
+      DeletedSecretBundle dsb = api().deleteSecret(vaultUri, SECRET_NAME);
+      assertNotNull(dsb);
+   }
+
+   @Test(dependsOnMethods = "testGetSecret")
+   public void testUpdateSecret() {
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing");
+      SecretBundle updatedSecret = api().updateSecret(vaultUri, SECRET_NAME, "", null, null, tags);
+      assertNotNull(updatedSecret.tags());
+      assertEquals(updatedSecret.tags().size(), 1);
+   }
+
+   @Test(dependsOnMethods = "testUpdateSecret")
+   public void testListSecretVersions() {
+      // Create a second version of the secret
+      SecretAttributes attributes = SecretAttributes.create(true, null, null, null, null, null);
+      SecretBundle secretBundle = api().setSecret(vaultUri,
+              SECRET_NAME,
+              attributes,
+              "aNewSecretKey",
+              null,
+              "-----BEGIN DSA PRIVATE KEY-----\n" +
+                      "MIIBvAIBAAKBgQDvgcVEyeU5gfw69xY2n1zHWGp/Z8O573SiWIcy29rW382W6jvn\n" +
+                      "X5rF/LX8AscwRhf2pUTEy64ECkd08eRgEjRIKdGSaTZpBXxM25TPb2fF9k1/ObXd\n" +
+                      "SkNOQNlwoCHdyQlvwdkVRohJoBX9u371owXObwLiBR1V597p3PdGNYD3DQIVAPtD\n" +
+                      "dHQQaHCYMxAIXRsaCmOZfsjdAoGBANVOovY4XqS48hvi/RzcCMbRbuHMFBXh/lEM\n" +
+                      "FmBdZ5sczpi1S3KpEjnBPQfOTzspTlEm5y6cHbkQjh1qT1tMdPAAr5aHYVLCTR+v\n" +
+                      "CSSALXP48YiZrJcgdyfhbyr5h/Su2QuwX2DvYrR9d88fYHU4O0njEyMd8UFwQ6Uy\n" +
+                      "qez/catgAoGAJ2AbSklFUXYvehmCVO6XVo3bgO++C3GMycJY3HHTTFQNAb3LJkeO\n" +
+                      "fa2ZCSqWbd85M00Lt0VEkqlb0EkjDvAgL0R78IJUmvb3FH1RiUofP/yK3g1/3I/l\n" +
+                      "jUa1fXXn2jSFYcyzGaDnC2U/B55g9G7hXsXJuldwATfDnLtqCdNPoWcCFQDx5K/k\n" +
+                      "Ub4xHF/4Tau8wDAkxHeJiw==\n" +
+                      "-----END DSA PRIVATE KEY-----"
+      );
+
+      // List secret versions
+      List<Secret> secrets = api().getSecretVersions(vaultUri, SECRET_NAME);
+      assertNotNull(secrets);
+      assertEquals(secrets.size(), 2);
+   }
+
+   @Test(dependsOnMethods = "testListSecretVersions")
+   public void testUpdateSecretWithVersion() {
+      List<Secret> secrets = api().getSecretVersions(vaultUri, SECRET_NAME);
+      assertNotNull(secrets);
+      assertEquals(secrets.size(), 2);
+
+      // get secret version to operate on
+      Secret secret = secrets.get(1);
+      assertNotNull(secret);
+      String version = secret.id().substring(secret.id().lastIndexOf("/") + 1).trim();
+
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing again");
+      SecretBundle updatedSecret = api().updateSecret(vaultUri, SECRET_NAME, version, null, null, tags);
+      assertNotNull(updatedSecret);
+
+      secrets = api().getSecretVersions(vaultUri, SECRET_NAME);
+      assertNotNull(secrets);
+      boolean found = false;
+      for (Secret s : secrets) {
+         if (s.id().contains(version)) {
+            secret = s;
+            found = true;
+            break;
+         }
+      }
+      assertTrue(found);
+      assertEquals(tags, secret.tags());
+   }
+
+   @Test(dependsOnMethods = "testUpdateSecretWithVersion")
+   public void testBackupRestoreSecret() {
+      SecretBundle originalSecret = api().getSecret(vaultUri, SECRET_NAME, null);
+      assertNotNull(originalSecret);
+
+      String backupSecret = api().backupSecret(vaultUri, SECRET_NAME);
+      assertNotNull(backupSecret);
+
+      DeletedSecretBundle dsb = api().deleteSecret(vaultUri, SECRET_NAME);
+      assertNotNull(dsb);
+
+      SecretBundle restoredSecret = api().restoreSecret(vaultUri, backupSecret);
+      assertNotNull(restoredSecret);
+
+      SecretBundle verifySecret = api().getSecret(vaultUri, SECRET_NAME, null);
+      assertNotNull(verifySecret);
+
+      assertEquals(verifySecret, originalSecret);
+   }
+
+   @Test(dependsOnMethods = "testUpdateVaultToSoftDelete")
+   public void testCreateRecoverableSecret() {
+      SecretAttributes attributes = SecretAttributes.create(true, null, null, null, null, null);
+      SecretBundle secretBundle = api().setSecret(vaultUri,
+              RECOVERABLE_SECRET_NAME,
+              attributes,
+              "aNewSecretKey",
+              null,
+              "-----BEGIN DSA PRIVATE KEY-----\n" +
+                      "MIIBvAIBAAKBgQDvgcVEyeU5gfw69xY2n1zHWGp/Z8O573SiWIcy29rW382W6jvn\n" +
+                      "X5rF/LX8AscwRhf2pUTEy64ECkd08eRgEjRIKdGSaTZpBXxM25TPb2fF9k1/ObXd\n" +
+                      "SkNOQNlwoCHdyQlvwdkVRohJoBX9u371owXObwLiBR1V597p3PdGNYD3DQIVAPtD\n" +
+                      "dHQQaHCYMxAIXRsaCmOZfsjdAoGBANVOovY4XqS48hvi/RzcCMbRbuHMFBXh/lEM\n" +
+                      "FmBdZ5sczpi1S3KpEjnBPQfOTzspTlEm5y6cHbkQjh1qT1tMdPAAr5aHYVLCTR+v\n" +
+                      "CSSALXP48YiZrJcgdyfhbyr5h/Su2QuwX2DvYrR9d88fYHU4O0njEyMd8UFwQ6Uy\n" +
+                      "qez/catgAoGAJ2AbSklFUXYvehmCVO6XVo3bgO++C3GMycJY3HHTTFQNAb3LJkeO\n" +
+                      "fa2ZCSqWbd85M00Lt0VEkqlb0EkjDvAgL0R78IJUmvb3FH1RiUofP/yK3g1/3I/l\n" +
+                      "jUa1fXXn2jSFYcyzGaDnC2U/B55g9G7hXsXJuldwATfDnLtqCdNPoWcCFQDx5K/k\n" +
+                      "Ub4xHF/4Tau8wDAkxHeJiw==\n" +
+                      "-----END DSA PRIVATE KEY-----"
+      );
+      assertNotNull(secretBundle);
+      checkState(recoverableSecretStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_SECRET_NAME),
+              "secret was not created before timeout");
+   }
+
+   @Test(dependsOnMethods = "testCreateRecoverableSecret")
+   public void testDeleteRecoverableSecret() {
+      DeletedSecretBundle dsb = api().deleteSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+      assertNotNull(dsb.deletedDate());
+      assertNotNull(dsb.recoveryId());
+      checkState(deletedSecretStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_SECRET_NAME),
+              "secret was not deleted before timeout");
+   }
+
+   @Test(dependsOnMethods = "testDeleteRecoverableSecret")
+   public void testListDeletedSecrets() {
+      for (DeletedSecretBundle secret : api().listDeletedSecrets(vaultUri)) {
+         assertNotNull(secret.deletedDate());
+      }
+   }
+
+   @Test(dependsOnMethods = "testListDeletedSecrets")
+   public void testGetDeletedSecret() {
+      DeletedSecretBundle dsb = api().getDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+      assertNotNull(dsb.deletedDate());
+   }
+
+   @Test(dependsOnMethods = {"testDeleteRecoverableSecret", "testGetDeletedSecret"})
+   public void testRecoverDeletedSecret() {
+      SecretBundle secret = api().recoverDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+      checkState(recoverableSecretStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_SECRET_NAME),
+              "secret was not created before timeout");
+   }
+
+   @Test(dependsOnMethods = "testRecoverDeletedSecret")
+   public void testPurgeDeletedSecret() {
+      // delete the secret
+      DeletedSecretBundle dsb = api().deleteSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+      checkState(deletedSecretStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_SECRET_NAME),
+              "secret was not deleted before timeout");
+
+      // purge the secret and verify that it is no longer listed as deleted
+      api().purgeDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+      checkState(deletedSecretStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_SECRET_NAME),
+              "secret was not purged before timeout");
+   }
+
+   @Test(dependsOnMethods = "testGet")
+   public void testCreateCertificate() {
+      CertificatePolicy policy = Certificate.CertificatePolicy.create(null,
+              CERTIFICATE_NAME,
+              IssuerParameters.create(null, "Self"),
+              KeyProperties.create(false, 2048, "RSA", false),
+              null,
+              null,
+              X509CertificateProperties.create(null, null, null, "CN=mycertificate.foobar.com", 12)
+      );
+      assertNotNull(policy);
+
+      CertificateOperation certOp = api().createCertificate(vaultUri,
+              CERTIFICATE_NAME,
+              null,
+              policy,
+              null
+      );
+      assertNotNull(certOp);
+   }
+
+   @Test(dependsOnMethods = "testCreateCertificate")
+   public void testImportCertificate() {
+      String certPem = importableCertificatePem;
+      CertificateBundle certBundle = api().importCertificate(
+              vaultUri,
+              IMPORTABLE_CERTIFICATE_NAME,
+              null,
+              CertificatePolicy.create(
+                      null,
+                      null,
+                      null,
+                      null,
+                      null,
+                      SecretProperties.create("application/x-pem-file"),
+                      null
+              ),
+              null,
+              null,
+              certPem);
+      assertNotNull(certBundle);
+   }
+
+   @Test(dependsOnMethods = "testImportCertificate")
+   public void testMergeCertificate() {
+      /* XXX - Merging certificates is used in the case where a CSR is generated
+       * within the Azure Key Vault and then signed by an external entity.
+       * Since this requires an offline process outside the scope of automated
+       * tests, this test is currently not implemented.
+       */
+      throw new SkipException("merging certificates requires an external entity, skipping");
+   }
+
+   @Test(dependsOnMethods = "testGetCertificateOperation")
+   public void testGetCertificate() {
+      CertificateBundle certBundle = api().getCertificate(vaultUri, "myCertificate", null);
+      assertNotNull(certBundle);
+   }
+
+   @Test(dependsOnMethods = "testGetCertificateOperation")
+   public void testListCertificates() {
+      List<Certificate> certs = api().getCertificates(vaultUri);
+      assertTrue(!certs.isEmpty());
+      for (Certificate cert : certs) {
+         assertNotNull(cert.id());
+      }
+   }
+
+   @Test(dependsOnMethods = "testGetCertificateOperation")
+   public void testListCertificateVersions() {
+      List<Certificate> certs = api().getCertificateVersions(vaultUri, CERTIFICATE_NAME);
+      assertNotNull(certs);
+      assertEquals(certs.size(), 1);
+   }
+
+   @Test(dependsOnMethods = "testGetCertificatePolicy")
+   public void testUpdateCertificate() {
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("selfsigned", "true");
+      CertificatePolicy policy = api().getCertificatePolicy(
+              vaultUri,
+              CERTIFICATE_NAME
+      );
+      assertNotNull(policy);
+      CertificateBundle certBundle = api().updateCertificate(
+              vaultUri,
+              CERTIFICATE_NAME,
+              "",
+              null,
+              policy,
+              tags
+      );
+      assertNotNull(certBundle);
+      assertEquals(certBundle.tags().size(), 1);
+   }
+
+   @Test(dependsOnMethods = "testUpdateCertificate")
+   public void testUpdateCertificateVersion() {
+      // create a new version of the certificate
+      /*
+       * XXX -- update using version complains about needing policy (required input), yet
+       * passing in the same policy results in the error:
+       *
+       * Policy cannot be updated with a specific version of a certificate
+       *
+       * Will uncomment/fix once this issue is resolved.
+       *
+       */
+      throw new SkipException("bug in requirements for function");
+   }
+
+   @Test(dependsOnMethods = {"testDeleteCertificateOperation", "testDeleteCertificateIssuer",
+                             "testDeleteCertificateContacts", "testUpdateCertificatePolicy"})
+   public void testDeleteCertificate() {
+      DeletedCertificateBundle dcb = api().deleteCertificate(
+              vaultUri,
+              CERTIFICATE_NAME
+      );
+      assertNotNull(dcb);
+   }
+
+   @Test(dependsOnMethods = "testCreateCertificate")
+   public void testGetCertificateOperation() {
+      CertificateOperation certOp = api().getCertificateOperation(vaultUri, CERTIFICATE_NAME);
+      assertNotNull(certOp);
+      checkState(certificateOperationStatus.create(resourceGroupName, vaultUri, true).apply(CERTIFICATE_NAME),
+              "certificate was not created before timeout");
+   }
+
+   @Test(dependsOnMethods = "testDeleteCertificateContacts")
+   public void testUpdateCertificateOperation() {
+      CertificatePolicy policy = Certificate.CertificatePolicy.create(null,
+              TEMP_CERTIFICATE_NAME,
+              IssuerParameters.create(null, "Self"),
+              KeyProperties.create(false, 4096, "RSA", false),
+              null,
+              null,
+              X509CertificateProperties.create(null, null, null, "CN=mytempcertificate.foobar.com", 12)
+      );
+      assertNotNull(policy);
+      CertificateOperation certOp = api().createCertificate(vaultUri,
+              TEMP_CERTIFICATE_NAME,
+              null,
+              policy,
+              null
+      );
+      assertNotNull(certOp);
+
+      certOp = api().updateCertificateOperation(vaultUri, TEMP_CERTIFICATE_NAME, true);
+      assertNotNull(certOp);
+      assertTrue(certOp.cancellationRequested());
+   }
+
+   @Test(dependsOnMethods = "testUpdateCertificateOperation")
+   public void testDeleteCertificateOperation() {
+      CertificateOperation certOp = api().deleteCertificateOperation(vaultUri, TEMP_CERTIFICATE_NAME);
+      assertNotNull(certOp);
+      checkState(certificateOperationStatus.create(resourceGroupName, vaultUri, false).apply(TEMP_CERTIFICATE_NAME),
+              "certificate was not deleted before timeout");
+   }
+
+   @Test(dependsOnMethods = "testGetCertificate")
+   public void testSetCertificateIssuer() {
+      AdministrationDetails adminDetail = AdministrationDetails.create(
+              "adminguy@certsforme.com",
+              "Admin",
+              "Guy",
+              "867-5309"
+      );
+      List<AdministrationDetails> adminDetails = new ArrayList<AdministrationDetails>();
+      adminDetails.add(adminDetail);
+      OrganizationDetails orgDetails = OrganizationDetails.create(
+              adminDetails,
+              null
+      );
+      IssuerBundle issuer = api().setCertificateIssuer(
+              vaultUri,
+              "globalsign01",
+              null,
+              IssuerCredentials.create("imauser", "This1sMyPa55wurD!"),
+              orgDetails,
+              "GlobalSign"
+      );
+      assertNotNull(issuer);
+   }
+
+   @Test(dependsOnMethods = "testSetCertificateIssuer")
+   public void testGetCertificateIssuers() {
+      List<CertificateIssuer> issuers = api().getCertificateIssuers(vaultUri);
+      assertNotNull(issuers);
+      assertTrue(issuers.size() > 0);
+   }
+
+   @Test(dependsOnMethods = "testSetCertificateIssuer")
+   public void testGetCertificateIssuer() {
+      IssuerBundle issuer = api().getCertificateIssuer(vaultUri, "globalsign01");
+      assertNotNull(issuer);
+      assertEquals(issuer.provider(), "GlobalSign");
+   }
+
+   @Test(dependsOnMethods = "testGetCertificateIssuer")
+   public void testUpdateCertificateIssuer() {
+      AdministrationDetails adminDetail = AdministrationDetails.create(
+              "adminguy@certsforme.com",
+              "Admin",
+              "Guy",
+              "867-5309"
+      );
+      List<AdministrationDetails> adminDetails = new ArrayList<AdministrationDetails>();
+      adminDetails.add(adminDetail);
+      OrganizationDetails orgDetails = OrganizationDetails.create(
+              adminDetails,
+              null
+      );
+      IssuerBundle issuer = api().updateCertificateIssuer(
+              vaultUri,
+              "globalsign01",
+              null,
+              IssuerCredentials.create("imauser", "CanHa5P455wuRd!"),
+              orgDetails,
+              "GlobalSign"
+      );
+      assertNotNull(issuer);
+   }
+
+   @Test(dependsOnMethods = "testUpdateCertificateIssuer")
+   public void testDeleteCertificateIssuer() {
+      IssuerBundle issuer = api().deleteCertificateIssuer(vaultUri, "globalsign01");
+      assertNotNull(issuer);
+
+      issuer = api().getCertificateIssuer(vaultUri, "globalsign01");
+      assertEquals(issuer, null);
+   }
+
+   @Test(dependsOnMethods = "testDeleteCertificateIssuer")
+   public void testSetCertificateContacts() {
+      List<Contact> contactsIn = new ArrayList<Contact>();
+      contactsIn.add(Contact.create("foo@bar.com", "Foo bar", "867-5309"));
+      Contacts contacts = api().setCertificateContacts(vaultUri, contactsIn);
+      assertNotNull(contacts);
+   }
+   @Test(dependsOnMethods = "testSetCertificateContacts")
+   public void testGetCertificateContacts() {
+      Contacts contacts = api().getCertificateContacts(vaultUri);
+      assertNotNull(contacts.id());
+      assertEquals(contacts.contacts().size(), 1);
+   }
+
+   @Test(dependsOnMethods = "testGetCertificateContacts")
+   public void testDeleteCertificateContacts() {
+      Contacts contacts = api().deleteCertificateContacts(vaultUri);
+      assertNotNull(contacts.id());
+
+      contacts = api().getCertificateContacts(vaultUri);
+      assertNull(contacts);
+   }
+
+   @Test(dependsOnMethods = "testCreateCertificate")
+   public void testGetCertificatePolicy() {
+      CertificatePolicy policy = api().getCertificatePolicy(vaultUri, CERTIFICATE_NAME);
+      assertNotNull(policy);
+   }
+
+   @Test(dependsOnMethods = "testUpdateCertificate")
+   public void testUpdateCertificatePolicy() {
+      CertificatePolicy policy = api().updateCertificatePolicy(
+              vaultUri,
+              CERTIFICATE_NAME,
+              null,
+              null,
+              KeyProperties.create(true, 3072, "RSA", false),
+              null,
+              null,
+              null
+      );
+      assertNotNull(policy);
+      assertTrue(policy.keyProps().exportable());
+   }
+
+   @Test(dependsOnMethods = "testUpdateVaultToSoftDelete")
+   public void testImportRecoverableCertificate() {
+      String certPem = importableCertificatePem;
+      CertificateBundle certBundle = api().importCertificate(
+              vaultUri,
+              RECOVERABLE_CERTIFICATE_NAME,
+              null,
+              CertificatePolicy.create(
+                      null,
+                      null,
+                      null,
+                      null,
+                      null,
+                      SecretProperties.create("application/x-pem-file"),
+                      null
+              ),
+              null,
+              null,
+              certPem);
+      checkState(recoverableCertificateStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_CERTIFICATE_NAME),
+              "certificate was not imported before timeout");
+
+      certBundle = api().getCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME, null);
+      assertNotNull(certBundle);
+      assertTrue(certBundle.attributes().recoveryLevel().contains("Recoverable"));
+   }
+
+   @Test(dependsOnMethods = "testImportRecoverableCertificate")
+   public void testDeleteRecoverableCertificate() {
+      DeletedCertificateBundle dcb = api().deleteCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+      assertNotNull(dcb.deletedDate());
+      assertNotNull(dcb.recoveryId());
+      checkState(deletedCertificateStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_CERTIFICATE_NAME),
+              "certificate was not deleted before timeout");
+   }
+
+   @Test(dependsOnMethods = "testDeleteRecoverableCertificate")
+   public void testListDeletedCertificates() {
+      for (DeletedCertificate dc : api().getDeletedCertificates(vaultUri)) {
+         assertNotNull(dc.deletedDate());
+      }
+   }
+
+   @Test(dependsOnMethods = "testListDeletedCertificates")
+   public void testGetDeletedCertificate() {
+      DeletedCertificateBundle dcb = api().getDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+      assertNotNull(dcb.deletedDate());
+   }
+
+   @Test(dependsOnMethods = "testGetDeletedCertificate")
+   public void testRecoverDeletedCertificate() {
+      CertificateBundle dcb = api().recoverDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+      assertNotNull(dcb);
+      checkState(recoverableCertificateStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_CERTIFICATE_NAME),
+              "certificate was not recovered before timeout");
+   }
+
+   @Test(dependsOnMethods = "testRecoverDeletedCertificate")
+   public void testPurgeDeletedCertificate() {
+      // delete the certificate
+      DeletedCertificateBundle dcb = api().deleteCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+      checkState(deletedCertificateStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_CERTIFICATE_NAME),
+              "certificate was not deleted before timeout");
+
+      // purge the certificate and verify that it is no longer listed as deleted
+      api().purgeDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+      checkState(deletedCertificateStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_CERTIFICATE_NAME),
+              "certificate was not purged before timeout");
+   }
+
+   private VaultApi api() {
+      return api.getVaultApi(resourceGroupName);
+   }
+}


[08/50] [abbrv] jclouds git commit: JCLOUDS-1273/JCLOUDS-1226: Support multiple resource groups in ARM

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
index 5799093..d267912 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
@@ -16,13 +16,12 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.availabilitySet;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.Iterables.any;
-import static com.google.common.collect.Iterables.getLast;
 import static com.google.common.collect.Iterables.transform;
 import static com.google.common.collect.Lists.newArrayList;
+import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.availabilitySet;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static org.jclouds.azurecompute.arm.domain.InboundNatRuleProperties.Protocol.Tcp;
 import static org.jclouds.compute.predicates.NodePredicates.inGroup;
@@ -40,7 +39,9 @@ import java.util.Set;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
+import org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetProperties;
 import org.jclouds.azurecompute.arm.domain.BackendAddressPool;
 import org.jclouds.azurecompute.arm.domain.BackendAddressPoolProperties;
 import org.jclouds.azurecompute.arm.domain.FrontendIPConfigurations;
@@ -62,24 +63,18 @@ import org.jclouds.azurecompute.arm.domain.ProbeProperties;
 import org.jclouds.azurecompute.arm.domain.Provisionable;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
-import org.jclouds.azurecompute.arm.domain.RegionAndId;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetProperties;
 import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
 import org.jclouds.compute.RunNodesException;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.domain.Location;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
-import com.google.common.base.Splitter;
 import com.google.common.base.Supplier;
-import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.inject.Key;
@@ -93,13 +88,11 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
    private static final String lbName = String.format("lb-%s-%s", LoadBalancerApiLiveTest.class.getSimpleName()
          .toLowerCase(), System.getProperty("user.name"));
 
-   private LoadingCache<String, ResourceGroup> resourceGroupMap;
    private Predicate<URI> resourceDeleted;
    private PublicIpAvailablePredicateFactory publicIpAvailable;
    private Predicate<Supplier<Provisionable>> resourceAvailable;
    private AzureComputeApi api;
 
-   private String resourceGroupName;
    private String location;
    private LoadBalancerApi lbApi;
    private NetworkInterfaceCardApi nicApi;
@@ -116,7 +109,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
+      AzureLiveTestUtils.defaultProperties(properties);
       checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
       return properties;
    }
@@ -126,9 +119,6 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
       super.initializeContext();
       resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
       }, Names.named(TIMEOUT_RESOURCE_DELETED)));
-      resourceGroupMap = context.utils().injector()
-            .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
-            }));
       publicIpAvailable = context.utils().injector().getInstance(PublicIpAvailablePredicateFactory.class);
       resourceAvailable = context.utils().injector()
             .getInstance(Key.get(new TypeLiteral<Predicate<Supplier<Provisionable>>>() {
@@ -142,11 +132,10 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
       super.setupContext();
       // Use the resource name conventions used in the abstraction so the nodes
       // can see the load balancer
-      ResourceGroup resourceGroup = createResourceGroup();
-      resourceGroupName = resourceGroup.name();
-      location = resourceGroup.location();
-      lbApi = api.getLoadBalancerApi(resourceGroupName);
-      nicApi = api.getNetworkInterfaceCardApi(resourceGroupName);
+      location = view.getComputeService().templateBuilder().build().getLocation().getId();
+      view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(group, location, null);
+      lbApi = api.getLoadBalancerApi(group);
+      nicApi = api.getNetworkInterfaceCardApi(group);
    }
 
    @Override
@@ -156,7 +145,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
          view.getComputeService().destroyNodesMatching(inGroup(group));
       } finally {
          try {
-            URI uri = api.getResourceGroupApi().delete(resourceGroupName);
+            URI uri = api.getResourceGroupApi().delete(group);
             assertResourceDeleted(uri);
          } finally {
             super.tearDownContext();
@@ -316,7 +305,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
    }
 
    private PublicIPAddress createPublicIPAddress(final String publicIpAddressName) {
-      final PublicIPAddressApi ipApi = view.unwrapApi(AzureComputeApi.class).getPublicIPAddressApi(resourceGroupName);
+      final PublicIPAddressApi ipApi = view.unwrapApi(AzureComputeApi.class).getPublicIPAddressApi(group);
       PublicIPAddress publicIPAddress = ipApi.get(publicIpAddressName);
 
       if (publicIPAddress == null) {
@@ -325,7 +314,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
                .idleTimeoutInMinutes(4).build();
          publicIPAddress = ipApi.createOrUpdate(publicIpAddressName, location, tags, properties);
 
-         checkState(publicIpAvailable.create(resourceGroupName).apply(publicIpAddressName),
+         checkState(publicIpAvailable.create(group).apply(publicIpAddressName),
                "Public IP was not provisioned in the configured timeout");
       }
 
@@ -358,16 +347,16 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
             .platformFaultDomainCount(count).build();
       AvailabilitySet as = AvailabilitySet.managed().name(group).properties(props).build();
 
-      Set<? extends NodeMetadata> nodes = view.getComputeService()
-            .createNodesInGroup(group, count, availabilitySet(as));
+      Set<? extends NodeMetadata> nodes = view.getComputeService().createNodesInGroup(group, count,
+            availabilitySet(as).resourceGroup(this.group));
 
       List<String> nicNames = new ArrayList<String>();
       for (NodeMetadata node : nodes) {
-         RegionAndId regionAndId = RegionAndId.fromSlashEncoded(node.getId());
-         VirtualMachine vm = api.getVirtualMachineApi(resourceGroupName).get(regionAndId.id());
+         ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(node.getId());
+         VirtualMachine vm = api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).get(
+               resourceGroupAndName.name());
 
-         String nicName = getLast(Splitter.on("/").split(
-               vm.properties().networkProfile().networkInterfaces().get(0).id()));
+         String nicName = vm.properties().networkProfile().networkInterfaces().get(0).name();
          nicNames.add(nicName);
       }
 
@@ -426,11 +415,6 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
       return nicApi.get(nicName);
    }
 
-   private ResourceGroup createResourceGroup() {
-      Location location = view.getComputeService().templateBuilder().build().getLocation();
-      return resourceGroupMap.getUnchecked(location.getId());
-   }
-
    private LoadBalancer updateLoadBalancer(final String name, LoadBalancerProperties props) {
       lbApi.createOrUpdate(name, location, null, props);
       resourceAvailable.apply(new Supplier<Provisionable>() {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
index 754f5fe..4d101ca 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
@@ -16,11 +16,7 @@
  */
 package org.jclouds.azurecompute.arm.internal;
 
-import java.util.Properties;
-import java.util.concurrent.TimeUnit;
-
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
@@ -30,14 +26,16 @@ import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
 import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
 import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
 
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
 public class AzureLiveTestUtils {
 
-   public static Properties defaultProperties(Properties properties, String resourceNamePrefix) {
+   public static Properties defaultProperties(Properties properties) {
       properties = properties == null ? new Properties() : properties;
       properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
       properties.put(PROPERTY_REGIONS, "westeurope");
       properties.put(IMAGE_PUBLISHERS, "Canonical");
-      properties.put(RESOURCENAME_PREFIX, resourceNamePrefix);
 
       String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
       properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
index cf65462..10406b8 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
@@ -97,7 +97,7 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
    @Override protected Properties setupProperties() {
       Properties properties = super.setupProperties();
       // for oauth
-      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
+      AzureLiveTestUtils.defaultProperties(properties);
       checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
       return properties;
    }


[07/50] [abbrv] jclouds git commit: Update ImageExtension to work with Managed Disks

Posted by na...@apache.org.
Update ImageExtension to work with Managed Disks


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

Branch: refs/heads/master
Commit: cc13cfeda1e949db8fd82467b30cf2ac3cb9f950
Parents: 37dcb87
Author: Dani Estevez <co...@danielestevez.com>
Authored: Fri Mar 17 17:23:49 2017 -0400
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon Apr 24 08:22:43 2017 +0200

----------------------------------------------------------------------
 providers/azurecompute-arm/pom.xml              |  29 +--
 .../azurecompute/arm/AzureComputeApi.java       |   3 +-
 .../arm/AzureComputeProviderMetadata.java       |  39 ++--
 .../arm/compute/AzureComputeServiceAdapter.java | 134 +++++---------
 .../AzureComputeServiceContextModule.java       |  48 ++++-
 .../extensions/AzureComputeImageExtension.java  |  83 ++++-----
 .../compute/functions/CustomImageToVMImage.java |  31 ++++
 .../ResourceDefinitionToCustomImage.java        |  91 ----------
 .../functions/TemplateToAvailabilitySet.java    |   3 +-
 .../arm/compute/functions/VMImageToImage.java   |  32 ++--
 .../functions/VirtualMachineToNodeMetadata.java |  62 ++-----
 .../arm/compute/strategy/CleanupResources.java  |  40 +----
 .../arm/domain/AvailabilitySet.java             |  75 +++++++-
 .../jclouds/azurecompute/arm/domain/Image.java  |  23 ++-
 .../arm/domain/ImageProperties.java             |  17 +-
 .../azurecompute/arm/domain/ImageReference.java |  16 +-
 .../arm/domain/ManagedDiskParameters.java       |  35 +---
 .../jclouds/azurecompute/arm/domain/OSDisk.java |  28 +--
 .../arm/domain/StorageAccountType.java          |  47 +++++
 .../azurecompute/arm/domain/VMImage.java        |  21 ++-
 .../arm/features/AvailabilitySetApi.java        |   9 +-
 .../arm/features/DeploymentApi.java             |   8 +-
 .../azurecompute/arm/features/DiskApi.java      |   4 -
 .../azurecompute/arm/features/ImageApi.java     |   4 -
 .../azurecompute/arm/features/JobApi.java       |   3 +-
 .../arm/features/LoadBalancerApi.java           |   2 -
 .../arm/features/NetworkSecurityGroupApi.java   |   2 -
 .../arm/features/NetworkSecurityRuleApi.java    |   3 +-
 .../arm/features/ResourceGroupApi.java          |   3 -
 .../arm/features/ResourceProviderApi.java       |   1 -
 .../arm/features/StorageAccountApi.java         |   5 -
 .../arm/features/VirtualMachineApi.java         |   4 +-
 .../StorageProfileToStorageAccountName.java     |  38 ----
 .../azurecompute/arm/util/BlobHelper.java       |  83 ---------
 .../jclouds/azurecompute/arm/util/VMImages.java |   2 +-
 .../compute/AzureComputeServiceLiveTest.java    |  16 +-
 .../compute/AzureTemplateBuilderLiveTest.java   |   6 +-
 .../AzureComputeImageExtensionLiveTest.java     |  63 +++++--
 ...reComputeSecurityGroupExtensionLiveTest.java |  15 +-
 .../features/AvailabilitySetApiLiveTest.java    |   9 +-
 .../features/AvailabilitySetApiMockTest.java    |   8 +-
 .../arm/features/DeploymentApiLiveTest.java     |  63 +------
 .../arm/features/DiskApiLiveTest.java           |   8 +-
 .../arm/features/ImageApiLiveTest.java          | 176 +++++++++++++------
 .../arm/features/ImageApiMockTest.java          | 155 ++++++++++++++++
 .../arm/features/LoadBalancerApiLiveTest.java   |   4 +-
 .../arm/features/VirtualMachineApiLiveTest.java | 153 +++++++++-------
 .../arm/features/VirtualMachineApiMockTest.java |   6 +-
 .../arm/internal/AzureLiveTestUtils.java        |  33 ++--
 .../internal/BaseAzureComputeApiLiveTest.java   |  21 +--
 .../resources/virtualmachineimagecreate.json    |  21 +++
 .../test/resources/virtualmachineimageget.json  |  21 +++
 .../test/resources/virtualmachineimagelist.json |  25 +++
 53 files changed, 954 insertions(+), 877 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/pom.xml
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/pom.xml b/providers/azurecompute-arm/pom.xml
index 5860c30..028e476 100644
--- a/providers/azurecompute-arm/pom.xml
+++ b/providers/azurecompute-arm/pom.xml
@@ -67,7 +67,11 @@
       <groupId>org.apache.jclouds.api</groupId>
       <artifactId>oauth</artifactId>
       <version>${project.version}</version>
-      <type>jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.driver</groupId>
+      <artifactId>jclouds-okhttp</artifactId>
+      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>org.apache.jclouds.api</groupId>
@@ -103,27 +107,11 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache.jclouds.driver</groupId>
-      <artifactId>jclouds-slf4j</artifactId>
-      <version>${project.parent.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds.provider</groupId>
-      <artifactId>azureblob</artifactId>
-      <version>${project.parent.version}</version>
-    </dependency>
-    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache.jclouds.driver</groupId>
-      <artifactId>jclouds-okhttp</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
       <groupId>com.squareup.okhttp</groupId>
       <artifactId>mockwebserver</artifactId>
       <scope>test</scope>
@@ -135,20 +123,13 @@
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-blobstore</artifactId>
-      <version>${project.parent.version}</version>
-    </dependency>
   </dependencies>
 
   <profiles>
     <profile>
       <id>live</id>
-
       <build>
         <defaultGoal>clean verify</defaultGoal>
-
         <plugins>
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index 51ed402..70814868 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -17,7 +17,6 @@
 package org.jclouds.azurecompute.arm;
 
 import java.io.Closeable;
-
 import javax.ws.rs.PathParam;
 
 import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
@@ -170,7 +169,7 @@ public interface AzureComputeApi extends Closeable {
     */
    @Delegate
    LoadBalancerApi getLoadBalancerApi(@PathParam("resourcegroup") String resourcegroup);
-   
+
    /**
     * The AvailabilitySet API includes operations for managing availability sets
     * within your subscription.

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index 3bf1ab3..9d3f05d 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -16,6 +16,23 @@
  */
 package org.jclouds.azurecompute.arm;
 
+import static org.jclouds.Constants.PROPERTY_MAX_RATE_LIMIT_WAIT;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
+import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_AUTHENTICATE_SUDO;
+import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER;
+import static org.jclouds.compute.config.ComputeServiceProperties.POLL_INITIAL_PERIOD;
+import static org.jclouds.compute.config.ComputeServiceProperties.POLL_MAX_PERIOD;
+import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
+import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
+import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
+import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
+import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
 
 import java.net.URI;
 import java.util.Properties;
@@ -44,24 +61,6 @@ import org.jclouds.providers.internal.BaseProviderMetadata;
 
 import com.google.auto.service.AutoService;
 
-import static org.jclouds.Constants.PROPERTY_MAX_RATE_LIMIT_WAIT;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
-import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_AUTHENTICATE_SUDO;
-import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER;
-import static org.jclouds.compute.config.ComputeServiceProperties.POLL_INITIAL_PERIOD;
-import static org.jclouds.compute.config.ComputeServiceProperties.POLL_MAX_PERIOD;
-import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
-import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
-import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
-import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
-import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
-import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
-
 @AutoService(ProviderMetadata.class)
 public class AzureComputeProviderMetadata extends BaseProviderMetadata {
 
@@ -96,7 +95,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       // Default credentials for all images
       properties.put(IMAGE_LOGIN_USER, "jclouds:Password12345!");
       properties.put(IMAGE_AUTHENTICATE_SUDO, "true");
-      properties.put(TEMPLATE, "imageNameMatches=UbuntuServer,osVersionMatches=1[45]\\.[01][04]\\.[0-9]-LTS");
+      properties.put(TEMPLATE, "imageNameMatches=UbuntuServer,osVersionMatches=1[456]\\.[01][04](\\.[0-9])?-LTS");
       // Api versions used in each API
       properties.put(API_VERSION_PREFIX + DeploymentApi.class.getSimpleName(), "2016-02-01");
       properties.put(API_VERSION_PREFIX + LocationApi.class.getSimpleName(), "2015-11-01");
@@ -113,7 +112,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(API_VERSION_PREFIX + VMSizeApi.class.getSimpleName(), "2015-06-15");
       properties.put(API_VERSION_PREFIX + VirtualMachineApi.class.getSimpleName(), "2016-04-30-preview");
       properties.put(API_VERSION_PREFIX + LoadBalancerApi.class.getSimpleName(), "2016-03-30");
-      properties.put(API_VERSION_PREFIX + AvailabilitySetApi.class.getSimpleName(), "2016-03-30");
+      properties.put(API_VERSION_PREFIX + AvailabilitySetApi.class.getSimpleName(), "2016-04-30-preview");
       properties.put(API_VERSION_PREFIX + DiskApi.class.getSimpleName(), "2017-03-30");
       properties.put(API_VERSION_PREFIX + ImageApi.class.getSimpleName(), "2016-04-30-preview");
       

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index e79c50d..8f9b67c 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -16,6 +16,19 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.ImmutableList.builder;
+import static com.google.common.collect.ImmutableList.of;
+import static com.google.common.collect.Iterables.contains;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.collect.Iterables.transform;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
+import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -27,6 +40,7 @@ import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
@@ -52,10 +66,8 @@ import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
 import org.jclouds.azurecompute.arm.domain.SKU;
+import org.jclouds.azurecompute.arm.domain.StorageAccountType;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
-import org.jclouds.azurecompute.arm.domain.StorageService;
-import org.jclouds.azurecompute.arm.domain.StorageService.Status;
-import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VMHardware;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VMSize;
@@ -64,7 +76,6 @@ import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
 import org.jclouds.azurecompute.arm.features.OSImageApi;
 import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
-import org.jclouds.azurecompute.arm.util.BlobHelper;
 import org.jclouds.compute.ComputeServiceAdapter;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.OsFamily;
@@ -86,23 +97,6 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.ImmutableList.builder;
-import static com.google.common.collect.ImmutableList.of;
-import static com.google.common.collect.Iterables.contains;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.find;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
-import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
-import static org.jclouds.util.Closeables2.closeQuietly;
-
 /**
  * Defines the connection between the {@link AzureComputeApi} implementation and
  * the jclouds {@link org.jclouds.compute.ComputeService}.
@@ -122,17 +116,20 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    private final Supplier<Set<String>> regionIds;
    private final PublicIpAvailablePredicateFactory publicIpAvailable;
    private final LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private final CustomImageToVMImage customImagetoVmImage;
 
    @Inject
    AzureComputeServiceAdapter(final AzureComputeApi api, @Named(IMAGE_PUBLISHERS) String imagePublishers,
-                              CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
-                              PublicIpAvailablePredicateFactory publicIpAvailable, LoadingCache<String, ResourceGroup> resourceGroupMap) {
+         CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
+         PublicIpAvailablePredicateFactory publicIpAvailable, LoadingCache<String, ResourceGroup> resourceGroupMap,
+         CustomImageToVMImage customImagetoVmImage) {
       this.api = api;
       this.imagePublishers = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(imagePublishers);
       this.cleanupResources = cleanupResources;
       this.regionIds = regionIds;
       this.publicIpAvailable = publicIpAvailable;
       this.resourceGroupMap = resourceGroupMap;
+      this.customImagetoVmImage = customImagetoVmImage;
    }
 
    @Override
@@ -223,50 +220,30 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       }
       return osImages;
    }
+   
+   private List<VMImage> listCustomImagesByLocation(String location) {
+      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location);
+      List<org.jclouds.azurecompute.arm.domain.Image> customImages = api.getVirtualMachineImageApi(resourceGroup.name()).list();
+      return Lists.transform(customImages, customImagetoVmImage);
+   }
 
    @Override
    public Iterable<VMImage> listImages() {
-      final List<VMImage> osImages = Lists.newArrayList();
-
-      final List<String> availableLocationNames = FluentIterable.from(listLocations())
-          .transform(new Function<Location, String>() {
-             @Override public String apply(Location location) {
-                return location.name();
-             }
-          }).toList();
+      final ImmutableList.Builder<VMImage> osImages = ImmutableList.builder();
+      
+      Iterable<String> availableLocationNames = transform(listLocations(), new Function<Location, String>() {
+         @Override
+         public String apply(Location location) {
+            return location.name();
+         }
+      });
 
       for (String locationName : availableLocationNames) {
          osImages.addAll(listImagesByLocation(locationName));
+         osImages.addAll(listCustomImagesByLocation(locationName));
       }
 
-      // list custom images
-      for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
-         String azureGroup = resourceGroup.name();
-         List<StorageService> storages = api.getStorageAccountApi(azureGroup).list();
-
-         for (StorageService storage : storages) {
-            try {
-               String name = storage.name();
-               StorageService storageService = api.getStorageAccountApi(azureGroup).get(name);
-               if (storageService != null
-                       && Status.Succeeded == storageService.storageServiceProperties().provisioningState()) {
-                  String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1();
-                  BlobHelper blobHelper = new BlobHelper(storage.name(), key);
-                  try {
-                     List<VMImage> images = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER,
-                             storage.location());
-                     osImages.addAll(images);
-                  } finally {
-                     closeQuietly(blobHelper);
-                  }
-               }
-            } catch (Exception ex) {
-               logger.warn("<< could not get custom images from storage account %s: %s", storage, ex.getMessage());
-            }
-         }
-      }
-
-      return osImages;
+      return osImages.build();
    }
 
    @Override
@@ -275,30 +252,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(image.location());
 
       if (image.custom()) {
-         VMImage customImage = null;
-         StorageServiceKeys keys = api.getStorageAccountApi(resourceGroup.name()).getKeys(image.storage());
-         if (keys == null) {
-            // If the storage account for the image does not exist, it means the
-            // image was deleted
-            return null;
-         }
-
-         BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1());
-         try {
-            if (blobHelper.customImageExists()) {
-               List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, resourceGroup.name(),
-                       CUSTOM_IMAGE_OFFER, image.location());
-               customImage = find(customImagesInStorage, new Predicate<VMImage>() {
-                  @Override
-                  public boolean apply(VMImage input) {
-                     return id.equals(encodeFieldsToUniqueIdCustom(input));
-                  }
-               }, null);
-            }
-         } finally {
-            closeQuietly(blobHelper);
-         }
-         return customImage;
+         org.jclouds.azurecompute.arm.domain.Image vmImage = api.getVirtualMachineImageApi(resourceGroup.name()).get(image.name());
+         return vmImage == null ? null : customImagetoVmImage.apply(vmImage);
       }
 
       String location = image.location();
@@ -313,6 +268,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
          return VMImage.azureImage().publisher(publisher).offer(offer).sku(sku).version(version.name())
                  .location(location).versionProperties(version.properties()).build();
       }
+      
       return null;
    }
 
@@ -458,13 +414,9 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    }
 
    private ImageReference createImageReference(Image image) {
-      return isCustom(image.getId()) ? ImageReference.builder().id(image.getId()).build() :
-              ImageReference.builder()
-                      .publisher(image.getProviderId())
-                      .offer(image.getName())
-                      .sku(image.getVersion())
-                      .version("latest")
-                      .build();
+      return isCustom(image.getId()) ? ImageReference.builder().customImageId(image.getProviderId()).build() : ImageReference
+            .builder().publisher(image.getProviderId()).offer(image.getName()).sku(image.getVersion())
+            .version("latest").build();
    }
 
    private OSDisk createOSDisk(Image image) {
@@ -474,7 +426,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
               .osType(osType)
               .caching(DataDisk.CachingTypes.READ_WRITE.toString())
               .createOption(CreationData.CreateOptions.FROM_IMAGE.toString())
-              .managedDiskParameters(ManagedDiskParameters.create(null, ManagedDiskParameters.StorageAccountTypes.STANDARD_LRS.toString()))
+              .managedDiskParameters(ManagedDiskParameters.create(null, StorageAccountType.STANDARD_LRS.toString()))
               .build();
    }
    

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
index 690022b..cf3c90c 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
@@ -40,7 +40,6 @@ import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeSecurityGroup
 import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation;
 import org.jclouds.azurecompute.arm.compute.functions.NetworkSecurityGroupToSecurityGroup;
 import org.jclouds.azurecompute.arm.compute.functions.NetworkSecurityRuleToIpPermission;
-import org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage;
 import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware;
 import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
 import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata;
@@ -48,6 +47,7 @@ import org.jclouds.azurecompute.arm.compute.loaders.CreateSecurityGroupIfNeeded;
 import org.jclouds.azurecompute.arm.compute.loaders.ResourceGroupForLocation;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes;
+import org.jclouds.azurecompute.arm.domain.Image;
 import org.jclouds.azurecompute.arm.domain.Location;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
@@ -86,7 +86,6 @@ import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import com.google.inject.Provides;
 import com.google.inject.TypeLiteral;
-import com.google.inject.assistedinject.FactoryModuleBuilder;
 
 public class AzureComputeServiceContextModule extends
       ComputeServiceAdapterContextModule<VirtualMachine, VMHardware, VMImage, Location> {
@@ -115,8 +114,6 @@ public class AzureComputeServiceContextModule extends
       install(new LocationsFromComputeServiceAdapterModule<VirtualMachine, VMHardware, VMImage, Location>() {
       });
 
-      install(new FactoryModuleBuilder().build(ResourceDefinitionToCustomImage.Factory.class));
-
       bind(TemplateOptions.class).to(AzureTemplateOptions.class);
       bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class);
       bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class);
@@ -163,9 +160,9 @@ public class AzureComputeServiceContextModule extends
 
    @Provides
    @Named(TIMEOUT_IMAGE_AVAILABLE)
-   protected Predicate<URI> provideImageAvailablePredicate(final AzureComputeApi api, final Timeouts timeouts,
+   protected Predicate<URI> provideImageCapturedPredicate(final AzureComputeApi api, final Timeouts timeouts,
          final PollPeriod pollPeriod) {
-      return retry(new ImageDonePredicate(api), timeouts.imageAvailable, pollPeriod.pollInitialPeriod,
+      return retry(new ImageCapturedPredicate(api), timeouts.imageAvailable, pollPeriod.pollInitialPeriod,
             pollPeriod.pollMaxPeriod);
    }
 
@@ -196,6 +193,13 @@ public class AzureComputeServiceContextModule extends
          Predicate<Supplier<Provisionable>> resourceAvailable) {
       return new SecurityGroupAvailablePredicateFactory(api, resourceAvailable);
    }
+   
+   @Provides
+   protected ImageAvailablePredicateFactory provideImageAvailablePredicate(final AzureComputeApi api,
+         Predicate<Supplier<Provisionable>> resourceAvailable, final Timeouts timeouts, final PollPeriod pollPeriod) {
+      return new ImageAvailablePredicateFactory(api, retry(new ResourceInStatusPredicate("Succeeded"),
+            timeouts.imageAvailable, pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod));
+   }
 
    @Provides
    protected Predicate<Supplier<Provisionable>> provideResourceAvailablePredicate(final AzureComputeApi api,
@@ -231,11 +235,11 @@ public class AzureComputeServiceContextModule extends
    }
 
    @VisibleForTesting
-   static class ImageDonePredicate implements Predicate<URI> {
+   static class ImageCapturedPredicate implements Predicate<URI> {
 
       private final AzureComputeApi api;
 
-      public ImageDonePredicate(final AzureComputeApi api) {
+      public ImageCapturedPredicate(final AzureComputeApi api) {
          this.api = checkNotNull(api, "api must not be null");
       }
 
@@ -351,5 +355,33 @@ public class AzureComputeServiceContextModule extends
          };
       }
    }
+   
+   public static class ImageAvailablePredicateFactory {
+      private final AzureComputeApi api;
+      private final Predicate<Supplier<Provisionable>> resourceAvailable;
+      
+      ImageAvailablePredicateFactory(final AzureComputeApi api,
+            Predicate<Supplier<Provisionable>> resourceAvailable) {
+         this.api = checkNotNull(api, "api cannot be null");
+         this.resourceAvailable = resourceAvailable;
+      }
+
+      public Predicate<String> create(final String resourceGroup) {
+         checkNotNull(resourceGroup, "resourceGroup cannot be null");
+         return new Predicate<String>() {
+            @Override
+            public boolean apply(final String name) {
+               checkNotNull(name, "name cannot be null");
+               return resourceAvailable.apply(new Supplier<Provisionable>() {
+                  @Override
+                  public Provisionable get() {
+                     Image img = api.getVirtualMachineImageApi(resourceGroup).get(name);
+                     return img == null ? null : img.properties();
+                  }
+               });
+            }
+         };
+      }
+   }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
index cae2c7e..4bfa449 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
@@ -16,30 +16,29 @@
  */
 package org.jclouds.azurecompute.arm.compute.extensions;
 
+import static com.google.common.base.Functions.compose;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
-import static org.jclouds.util.Closeables2.closeQuietly;
 
 import java.net.URI;
-import java.util.List;
 import java.util.concurrent.Callable;
 
 import javax.annotation.Resource;
 
 import org.jclouds.Constants;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.ImageAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.VirtualMachineInStatePredicateFactory;
-import org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage;
-import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources;
+import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
+import org.jclouds.azurecompute.arm.domain.IdReference;
+import org.jclouds.azurecompute.arm.domain.ImageProperties;
 import org.jclouds.azurecompute.arm.domain.RegionAndId;
-import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
-import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VMImage;
-import org.jclouds.azurecompute.arm.util.BlobHelper;
+import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.compute.domain.CloneImageTemplate;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.ImageTemplate;
@@ -48,6 +47,7 @@ import org.jclouds.compute.extensions.ImageExtension;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.logging.Logger;
 
+import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.cache.LoadingCache;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -56,7 +56,6 @@ import com.google.inject.Inject;
 import com.google.inject.name.Named;
 
 public class AzureComputeImageExtension implements ImageExtension {
-   public static final String CONTAINER_NAME = "jclouds";
    public static final String CUSTOM_IMAGE_OFFER = "custom";
 
    @Resource
@@ -65,26 +64,29 @@ public class AzureComputeImageExtension implements ImageExtension {
 
    private final AzureComputeApi api;
    private final ListeningExecutorService userExecutor;
-   private final Predicate<URI> imageAvailablePredicate;
+   private final ImageAvailablePredicateFactory imageAvailablePredicate;
    private final VirtualMachineInStatePredicateFactory nodeSuspendedPredicate;
-   private final ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage;
-   private final CleanupResources cleanupResources;
    private final LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private final Function<VMImage, Image> vmImageToImage;
+   private final Predicate<URI> resourceDeleted;
+   private final CustomImageToVMImage customImagetoVmImage;
 
    @Inject
    AzureComputeImageExtension(AzureComputeApi api,
-         @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> imageAvailablePredicate,
+         ImageAvailablePredicateFactory imageAvailablePredicate,
          @Named(TIMEOUT_NODE_SUSPENDED) VirtualMachineInStatePredicateFactory nodeSuspendedPredicate,
          @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
-         ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage, CleanupResources cleanupResources,
-         LoadingCache<String, ResourceGroup> resourceGroupMap) {
+         Function<VMImage, Image> vmImageToImage, LoadingCache<String, ResourceGroup> resourceGroupMap,
+         @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
+         CustomImageToVMImage customImagetoVmImage) {
       this.api = api;
       this.imageAvailablePredicate = imageAvailablePredicate;
       this.nodeSuspendedPredicate = nodeSuspendedPredicate;
       this.userExecutor = userExecutor;
-      this.resourceDefinitionToImage = resourceDefinitionToImage;
-      this.cleanupResources = cleanupResources;
+      this.vmImageToImage = vmImageToImage;
       this.resourceGroupMap = resourceGroupMap;
+      this.resourceDeleted = resourceDeleted;
+      this.customImagetoVmImage = customImagetoVmImage;
    }
 
    @Override
@@ -95,11 +97,13 @@ public class AzureComputeImageExtension implements ImageExtension {
    @Override
    public ListenableFuture<Image> createImage(ImageTemplate template) {
       final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
-
       final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId());
       ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
       final String resourceGroupName = resourceGroup.name();
 
+      final VirtualMachine vm = api.getVirtualMachineApi(resourceGroupName).get(regionAndId.id());
+      final IdReference vmIdRef = IdReference.create(vm.id());
+
       logger.debug(">> stopping node %s...", regionAndId.slashEncode());
       api.getVirtualMachineApi(resourceGroupName).stop(regionAndId.id());
       checkState(nodeSuspendedPredicate.create(resourceGroupName).apply(regionAndId.id()),
@@ -109,23 +113,17 @@ public class AzureComputeImageExtension implements ImageExtension {
          @Override
          public Image call() throws Exception {
             logger.debug(">> generalizing virtal machine %s...", regionAndId.id());
+
             api.getVirtualMachineApi(resourceGroupName).generalize(regionAndId.id());
 
-            logger.debug(">> capturing virtual machine %s to container %s...", regionAndId.id(), CONTAINER_NAME);
-            URI uri = api.getVirtualMachineApi(resourceGroupName)
-                  .capture(regionAndId.id(), cloneTemplate.getName(), CONTAINER_NAME);
-            checkState(uri != null && imageAvailablePredicate.apply(uri),
-                  "Image for node %s was not created within the configured time limit", cloneTemplate.getName());
+            org.jclouds.azurecompute.arm.domain.Image imageFromVM = api.getVirtualMachineImageApi(resourceGroupName)
+                  .createOrUpdate(cloneTemplate.getName(), regionAndId.region(),
+                        ImageProperties.builder().sourceVirtualMachine(vmIdRef).build());
 
-            List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
-            checkState(definitions.size() == 1,
-                  "Expected one resource definition after creating the image but %s were returned", definitions.size());
+            checkState(imageAvailablePredicate.create(resourceGroupName).apply(imageFromVM.name()),
+                  "Image for node %s was not created within the configured time limit", cloneTemplate.getName());
 
-            Image image = resourceDefinitionToImage.create(cloneTemplate.getSourceNodeId(), cloneTemplate.getName())
-                  .apply(definitions.get(0));
-            checkState(image != null, "Image for node %s was not created", cloneTemplate.getSourceNodeId());
-            logger.debug(">> created %s", image);
-            return image;
+            return compose(vmImageToImage, customImagetoVmImage).apply(imageFromVM);
          }
       });
    }
@@ -137,25 +135,8 @@ public class AzureComputeImageExtension implements ImageExtension {
 
       logger.debug(">> deleting image %s", id);
 
-      StorageServiceKeys keys = api.getStorageAccountApi(image.group()).getKeys(image.storage());
-      BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1());
-
-      try {
-         // This removes now all the images in this storage. At least in theory,
-         // there should be just one and if there is
-         // more, they should be copies of each other.
-         blobHelper.deleteContainerIfExists("system");
-         boolean result = !blobHelper.customImageExists();
-
-         if (!blobHelper.hasContainers()) {
-            logger.debug(">> storage account is empty after deleting the custom image. Deleting the storage account...");
-            api.getStorageAccountApi(image.group()).delete(image.storage());
-            cleanupResources.deleteResourceGroupIfEmpty(image.group());
-         }
-
-         return result;
-      } finally {
-         closeQuietly(blobHelper);
-      }
+      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(image.location());
+      URI uri = api.getVirtualMachineImageApi(resourceGroup.name()).delete(image.name());
+      return resourceDeleted.apply(uri);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java
new file mode 100644
index 0000000..9cb2188
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.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.compute.functions;
+
+import org.jclouds.azurecompute.arm.domain.Image;
+import org.jclouds.azurecompute.arm.domain.VMImage;
+
+import com.google.common.base.Function;
+
+public class CustomImageToVMImage implements Function<Image, VMImage> {
+
+   @Override
+   public VMImage apply(Image input) {
+      return VMImage.customImage().customImageId(input.id()).location(input.location()).name(input.name())
+            .offer(input.properties().storageProfile().osDisk().osType()).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
deleted file mode 100644
index c27f584..0000000
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azurecompute.arm.compute.functions;
-
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
-
-import java.util.Map;
-
-import javax.inject.Inject;
-
-import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.domain.RegionAndId;
-import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
-import org.jclouds.azurecompute.arm.domain.VMImage;
-import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName;
-import org.jclouds.compute.domain.Image;
-
-import com.google.common.base.Function;
-import com.google.common.cache.LoadingCache;
-import com.google.inject.assistedinject.Assisted;
-
-public class ResourceDefinitionToCustomImage implements Function<ResourceDefinition, Image> {
-
-   public interface Factory {
-      ResourceDefinitionToCustomImage create(@Assisted("nodeId") String nodeId, @Assisted("imageName") String imageName);
-   }
-
-   private final Function<VMImage, Image> vmImageToImage;
-   private final String imageName;
-   private final String nodeId;
-   private final AzureComputeApi api;
-   private final StorageProfileToStorageAccountName storageProfileToStorageAccountName;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
-
-   @Inject
-   ResourceDefinitionToCustomImage(AzureComputeApi api,
-         StorageProfileToStorageAccountName storageProfileToStorageAccountName,
-         Function<VMImage, Image> vmImageToImage, LoadingCache<String, ResourceGroup> resourceGroupMap,
-         @Assisted("nodeId") String nodeId, @Assisted("imageName") String imageName) {
-      this.api = api;
-      this.vmImageToImage = vmImageToImage;
-      this.nodeId = nodeId;
-      this.imageName = imageName;
-      this.storageProfileToStorageAccountName = storageProfileToStorageAccountName;
-      this.resourceGroupMap = resourceGroupMap;
-   }
-
-   @SuppressWarnings("unchecked")
-   @Override
-   public Image apply(ResourceDefinition input) {
-      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(nodeId);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
-      
-      VirtualMachine vm = api.getVirtualMachineApi(resourceGroup.name()).get(regionAndId.id());
-      if (vm == null) {
-         return null;
-      }
-      String storageAccountName = storageProfileToStorageAccountName.apply(vm.properties().storageProfile());
-
-      VMImage.Builder builder = VMImage.customImage().group(resourceGroup.name()).storage(storageAccountName)
-            .name(imageName).offer(CUSTOM_IMAGE_OFFER).location(vm.location());
-
-      Map<String, String> properties = (Map<String, String>) input.properties();
-
-      Object storageObject = properties.get("storageProfile");
-      Map<String, String> storageProperties = (Map<String, String>) storageObject;
-
-      Object osDiskObject = storageProperties.get("osDisk");
-      Map<String, String> osProperties = (Map<String, String>) osDiskObject;
-      builder.vhd1(osProperties.get("name"));
-
-      return vmImageToImage.apply(builder.build());
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
index 1416872..2732b6e 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
@@ -87,7 +87,8 @@ public class TemplateToAvailabilitySet implements Function<Template, Availabilit
             logger.debug(">> creating availability set [%s]", options.getAvailabilitySet().name());
 
             availabilitySet = api.getAvailabilitySetApi(resourceGroup).createOrUpdate(
-                  options.getAvailabilitySet().name(), location, tags, options.getAvailabilitySet().properties());
+                  options.getAvailabilitySet().name(), options.getAvailabilitySet().sku(), location, tags,
+                  options.getAvailabilitySet().properties());
          }
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
index 25bcc3b..4f02100 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
@@ -19,6 +19,7 @@ package org.jclouds.azurecompute.arm.compute.functions;
 import java.util.Map;
 import java.util.Set;
 
+import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
 import org.jclouds.azurecompute.arm.domain.ImageReference;
 import org.jclouds.azurecompute.arm.domain.Plan;
 import org.jclouds.azurecompute.arm.domain.VMImage;
@@ -55,20 +56,25 @@ public class VMImageToImage implements Function<VMImage, Image> {
 
    private final Supplier<Set<? extends org.jclouds.domain.Location>> locations;
 
-   public static String encodeFieldsToUniqueId(boolean globallyAvailable, String locatioName,
+   public static String encodeFieldsToUniqueId(boolean globallyAvailable, String locationName,
          ImageReference imageReference) {
-      return (globallyAvailable ? "global" : locatioName) + "/" + imageReference.publisher() + "/"
+      return (globallyAvailable ? "global" : locationName) + "/" + imageReference.publisher() + "/"
             + imageReference.offer() + "/" + imageReference.sku();
    }
 
+   public static String encodeFieldsToUniqueIdCustom(boolean globallyAvailable, String locationName,
+         ImageReference imageReference) {
+      return (globallyAvailable ? "global" : locationName) + "/" + imageReference.customImageId()
+            .substring(imageReference.customImageId().lastIndexOf("/") + 1);
+   }
+
    public static String encodeFieldsToUniqueId(VMImage imageReference) {
       return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/"
             + imageReference.publisher() + "/" + imageReference.offer() + "/" + imageReference.sku();
    }
 
    public static String encodeFieldsToUniqueIdCustom(VMImage imageReference) {
-      return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.group()
-            + "/" + imageReference.storage() + "/" + imageReference.offer() + "/" + imageReference.name();
+      return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.name();
    }
 
    public static VMImage decodeFieldsFromUniqueId(final String id) {
@@ -76,17 +82,13 @@ public class VMImageToImage implements Function<VMImage, Image> {
       String[] fields = checkNotNull(id, "id").split("/");
       if (isCustom(id)) {
          /* id fields indexes
-         0: imageReference.location) + "/" +
-         1: imageReference.group + "/" +
-         2: imageReference.storage + "/" +
-         3: imageReference.offer + "/" +
-         4: imageReference.name
+         0: imageReference.location + "/" +
+         1: imageReference.name
          */
-         vmImage = VMImage.customImage().location(fields[0]).group(fields[1]).storage(fields[2]).vhd1(fields[3])
-               .offer(fields[4]).build();
+         vmImage = VMImage.customImage().location(fields[0]).name(fields[1]).build();
       } else {
          /* id fields indexes
-         0: imageReference.location) + "/" +
+         0: imageReference.location + "/" +
          1: imageReference.publisher + "/" +
          2: imageReference.offer + "/" +
          3: imageReference.sku + "/" +
@@ -98,7 +100,7 @@ public class VMImageToImage implements Function<VMImage, Image> {
    }
 
    @Inject
-   VMImageToImage(@Memoized final Supplier<Set<? extends Location>> locations) {
+   VMImageToImage(@Memoized Supplier<Set<? extends Location>> locations) {
       this.locations = locations;
    }
 
@@ -110,7 +112,7 @@ public class VMImageToImage implements Function<VMImage, Image> {
          builder.location(
                      FluentIterable.from(locations.get()).firstMatch(LocationPredicates.idEquals(image.location()))
                            .get()).name(image.name()).description(image.group()).status(Image.Status.AVAILABLE)
-               .version("latest").providerId(image.vhd1()).id(encodeFieldsToUniqueIdCustom(image));
+               .version("latest").providerId(image.customImageId()).id(encodeFieldsToUniqueIdCustom(image));
 
          final OperatingSystem.Builder osBuilder = osFamily().apply(image);
          builder.operatingSystem(osBuilder.build());
@@ -165,7 +167,7 @@ public class VMImageToImage implements Function<VMImage, Image> {
 
             // only 64bit OS images are supported by Azure ARM
             return OperatingSystem.builder().family(family).is64Bit(true)
-                  .description(image.custom() ? image.vhd1() : image.sku())
+                  .description(image.custom() ? AzureComputeImageExtension.CUSTOM_IMAGE_OFFER : image.sku())
                   .version(image.custom() ? "latest" : image.sku());
          }
       };

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
index cb40a14..9bad6e5 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
@@ -16,6 +16,15 @@
  */
 package org.jclouds.azurecompute.arm.compute.functions;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Strings.nullToEmpty;
+import static com.google.common.collect.Iterables.find;
+import static org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.GROUP_KEY;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
+import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
+import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
+import static org.jclouds.location.predicates.LocationPredicates.idEquals;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -33,11 +42,7 @@ import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
-import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
-import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName;
-import org.jclouds.azurecompute.arm.util.BlobHelper;
 import org.jclouds.collect.Memoized;
 import org.jclouds.compute.domain.Hardware;
 import org.jclouds.compute.domain.Image;
@@ -59,18 +64,6 @@ import com.google.common.cache.LoadingCache;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Strings.nullToEmpty;
-import static com.google.common.collect.Iterables.find;
-import static com.google.common.collect.Iterables.tryFind;
-import static org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.GROUP_KEY;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
-import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
-import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
-import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
-import static org.jclouds.location.predicates.LocationPredicates.idEquals;
-import static org.jclouds.util.Closeables2.closeQuietly;
-
 public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> {
 
    @Resource
@@ -81,8 +74,6 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
    private final GroupNamingConvention nodeNamingConvention;
    private final Supplier<Set<? extends Location>> locations;
    private final Supplier<Map<String, ? extends Hardware>> hardwares;
-   private final Function<VMImage, Image> vmImageToImge;
-   private final StorageProfileToStorageAccountName storageProfileToStorageAccountName;
    private final LoadingCache<String, ResourceGroup> resourceGroupMap;
    private final ImageCacheSupplier imageCache;
    private final VirtualMachineToStatus virtualMachineToStatus;
@@ -90,16 +81,12 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
    @Inject
    VirtualMachineToNodeMetadata(AzureComputeApi api, GroupNamingConvention.Factory namingConvention,
          Supplier<Map<String, ? extends Hardware>> hardwares, @Memoized Supplier<Set<? extends Location>> locations,
-         Map<String, Credentials> credentialStore, Function<VMImage, Image> vmImageToImge,
-         StorageProfileToStorageAccountName storageProfileToStorageAccountName,
-         LoadingCache<String, ResourceGroup> resourceGroupMap, @Memoized Supplier<Set<? extends Image>> imageCache,
-         VirtualMachineToStatus virtualMachineToStatus) {
+         Map<String, Credentials> credentialStore, LoadingCache<String, ResourceGroup> resourceGroupMap,
+         @Memoized Supplier<Set<? extends Image>> imageCache, VirtualMachineToStatus virtualMachineToStatus) {
       this.api = api;
       this.nodeNamingConvention = namingConvention.createWithoutPrefix();
       this.locations = locations;
       this.hardwares = hardwares;
-      this.vmImageToImge = vmImageToImge;
-      this.storageProfileToStorageAccountName = storageProfileToStorageAccountName;
       this.resourceGroupMap = resourceGroupMap;
       this.virtualMachineToStatus = virtualMachineToStatus;
       checkArgument(imageCache instanceof ImageCacheSupplier,
@@ -207,29 +194,14 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
    protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName,
          String azureGroup) {
       if (storageProfile.imageReference() != null) {
-         String imageId = encodeFieldsToUniqueId(false, locatioName, storageProfile.imageReference());
+         // FIXME check this condition
+         String imageId = storageProfile.imageReference().customImageId() != null ?
+               encodeFieldsToUniqueIdCustom(false, locatioName, storageProfile.imageReference()) :
+               encodeFieldsToUniqueId(false, locatioName, storageProfile.imageReference());
          return imageCache.get(imageId);
       } else {
-         String storageAccountName = storageProfileToStorageAccountName.apply(storageProfile);
-         StorageServiceKeys keys = api.getStorageAccountApi(azureGroup).getKeys(storageAccountName);
-         BlobHelper blobHelper = new BlobHelper(storageAccountName, keys.key1());
-
-         try {
-            // Custom image. Let's find it by uri
-            List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER,
-                  locatioName);
-            Optional<VMImage> customImage = tryFind(customImagesInStorage, new Predicate<VMImage>() {
-               @Override
-               public boolean apply(VMImage input) {
-                  return input.vhd1().equals(storageProfile.osDisk().image().uri());
-               }
-            });
-
-            return customImage.isPresent() ? Optional.of(vmImageToImge.apply(customImage.get())) : Optional
-                  .<Image> absent();
-         } finally {
-            closeQuietly(blobHelper);
-         }
+         logger.warn("could not find image for storage profile %s", storageProfile);
+         return Optional.absent();
       }
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
index 481f695..fb635aa 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
@@ -16,6 +16,11 @@
  */
 package org.jclouds.azurecompute.arm.compute.strategy;
 
+import static com.google.common.base.Predicates.notNull;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+
 import java.net.URI;
 import java.util.List;
 
@@ -32,11 +37,8 @@ import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
-import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
-import org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName;
-import org.jclouds.azurecompute.arm.util.BlobHelper;
 import org.jclouds.compute.functions.GroupNamingConvention;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.logging.Logger;
@@ -48,12 +50,6 @@ import com.google.common.cache.LoadingCache;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
-import static com.google.common.base.Predicates.notNull;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.transform;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
-import static org.jclouds.util.Closeables2.closeQuietly;
-
 @Singleton
 public class CleanupResources {
 
@@ -63,17 +59,14 @@ public class CleanupResources {
 
    private final AzureComputeApi api;
    private final Predicate<URI> resourceDeleted;
-   private final StorageProfileToStorageAccountName storageProfileToStorageAccountName;
    private final LoadingCache<String, ResourceGroup> resourceGroupMap;
    private final GroupNamingConvention.Factory namingConvention;
 
    @Inject
    CleanupResources(AzureComputeApi azureComputeApi, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
-         StorageProfileToStorageAccountName storageProfileToStorageAccountName,
          LoadingCache<String, ResourceGroup> resourceGroupMap, GroupNamingConvention.Factory namingConvention) {
       this.api = azureComputeApi;
       this.resourceDeleted = resourceDeleted;
-      this.storageProfileToStorageAccountName = storageProfileToStorageAccountName;
       this.resourceGroupMap = resourceGroupMap;
       this.namingConvention = namingConvention;
    }
@@ -95,7 +88,6 @@ public class CleanupResources {
       // group. It will be deleted when the resource group is deleted
 
       cleanupVirtualMachineNICs(resourceGroupName, virtualMachine);
-      cleanupVirtualMachineStorage(resourceGroupName, virtualMachine);
       cleanupAvailabilitySetIfOrphaned(resourceGroupName, virtualMachine);
 
       return vmDeleted;
@@ -117,28 +109,6 @@ public class CleanupResources {
       }
    }
 
-   public void cleanupVirtualMachineStorage(String group, VirtualMachine virtualMachine) {
-      String storageAccountName = storageProfileToStorageAccountName
-            .apply(virtualMachine.properties().storageProfile());
-      StorageServiceKeys keys = api.getStorageAccountApi(group).getKeys(storageAccountName);
-
-      // Remove the virtual machine files
-      logger.debug(">> deleting virtual machine disk storage...");
-      BlobHelper blobHelper = new BlobHelper(storageAccountName, keys.key1());
-      try {
-         blobHelper.deleteContainerIfExists("vhds");
-
-         if (!blobHelper.customImageExists()) {
-            logger.debug(">> deleting storage account %s...", storageAccountName);
-            api.getStorageAccountApi(group).delete(storageAccountName);
-         } else {
-            logger.debug(">> the storage account contains custom images. Will not delete it!");
-         }
-      } finally {
-         closeQuietly(blobHelper);
-      }
-   }
-
    public boolean cleanupSecurityGroupIfOrphaned(String resourceGroup, String group) {
       String name = namingConvention.create().sharedNameForGroup(group);
       NetworkSecurityGroupApi sgapi = api.getNetworkSecurityGroupApi(resourceGroup);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/AvailabilitySet.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/AvailabilitySet.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/AvailabilitySet.java
index 624c664..4c4720e 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/AvailabilitySet.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/AvailabilitySet.java
@@ -90,6 +90,47 @@ public abstract class AvailabilitySet {
          }
       }
    }
+   
+   public static enum AvailabilitySetType {
+      MANAGED("Aligned"),
+      CLASSIC("Classic");
+      
+      private final String value;
+
+      AvailabilitySetType(String value) {
+         this.value = value;
+      }
+
+      public static AvailabilitySetType fromString(String value) {
+         AvailabilitySetType[] items = AvailabilitySetType.values();
+         for (AvailabilitySetType item : items) {
+            if (item.toString().equalsIgnoreCase(value)) {
+               return item;
+            }
+         }
+         throw new IllegalArgumentException("Unexpected type: " + value);
+      }
+
+      @Override
+      public String toString() {
+         return this.value;
+      }
+   }
+   
+   @AutoValue
+   public abstract static class SKU {
+      
+      public abstract AvailabilitySetType type();
+      
+      @SerializedNames({ "name" })
+      public static SKU create(final String type) {
+         return create(AvailabilitySetType.fromString(type));
+      }
+      
+      public static SKU create(AvailabilitySetType type) {
+         return new AutoValue_AvailabilitySet_SKU(type);
+      }
+   }
 
    /**
     * The id of the availability set
@@ -116,30 +157,44 @@ public abstract class AvailabilitySet {
    public abstract String location();
 
    /**
+    * Specifies the type of the availability set
+    */
+   @Nullable
+   public abstract SKU sku();
+   
+   /**
     * Specifies the tags of the availability set
     */
    @Nullable
    public abstract Map<String, String> tags();
-
+   
    /**
     * Specifies the properties of the availability set
     */
    @Nullable
    public abstract AvailabilitySetProperties properties();
 
-
-   @SerializedNames({"id", "name", "type", "location", "tags", "properties"})
+   @SerializedNames({ "id", "name", "type", "location", "sku", "tags", "properties" })
    public static AvailabilitySet create(final String id, final String name, final String type, final String location,
-                                        final Map<String, String> tags, AvailabilitySetProperties properties) {
-      return builder().id(id).name(name).type(type).location(location).tags(tags).properties(properties).build();
+         SKU sku, final Map<String, String> tags, AvailabilitySetProperties properties) {
+      return builder().id(id).name(name).type(type).location(location).sku(sku).tags(tags).properties(properties)
+            .build();
    }
    
    public abstract Builder toBuilder();
    
-   public static Builder builder() {
+   private static Builder builder() {
       return new AutoValue_AvailabilitySet.Builder();
    }
    
+   public static Builder managed() {
+      return builder().managed();
+   }
+   
+   public static Builder classic() {
+      return builder().classic();
+   }
+   
    @AutoValue.Builder
    public abstract static class Builder {
       public abstract Builder id(String id);
@@ -149,6 +204,14 @@ public abstract class AvailabilitySet {
       public abstract Builder tags(Map<String, String> tags);
       public abstract Builder properties(AvailabilitySetProperties properties);
       
+      abstract Builder sku(SKU sku);
+      public Builder managed() {
+         return sku(SKU.create(AvailabilitySetType.MANAGED));
+      }
+      public Builder classic() {
+         return sku(SKU.create(AvailabilitySetType.CLASSIC));
+      }
+      
       abstract Map<String, String> tags();
       abstract AvailabilitySet autoBuild();
       

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Image.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Image.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Image.java
index 5d9226b..b442617 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Image.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Image.java
@@ -26,6 +26,18 @@ import com.google.common.collect.ImmutableMap;
 
 @AutoValue
 public abstract class Image {
+   
+   /**
+    * The id of the image
+    */
+   @Nullable
+   public abstract String id();
+
+   /**
+    * The name of the image
+    */
+   @Nullable
+   public abstract String name();
 
    /**
     * The location of the image
@@ -42,9 +54,10 @@ public abstract class Image {
     */
    @Nullable public abstract Map<String, String> tags();
 
-   @SerializedNames({"location", "properties", "tags"})
-   public static Image create(final String location, final ImageProperties properties, final Map<String, String> tags) {
-      return builder().location(location).properties(properties).tags(tags).build();
+   @SerializedNames({"id", "name", "location", "properties", "tags"})
+   public static Image create(final String id, final String name, final String location,
+         final ImageProperties properties, final Map<String, String> tags) {
+      return builder().id(id).name(name).location(location).properties(properties).tags(tags).build();
    }
 
    public abstract Builder toBuilder();
@@ -55,10 +68,10 @@ public abstract class Image {
 
    @AutoValue.Builder
    public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder name(String name);
       public abstract Builder location(String location);
-
       public abstract Builder properties(ImageProperties properties);
-
       public abstract Builder tags(Map<String, String> tags);
 
       abstract Map<String, String> tags();

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
index ef877be..44cb16e 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
@@ -24,17 +24,8 @@ import com.google.auto.value.AutoValue;
 @AutoValue
 public abstract class ImageProperties implements Provisionable {
 
-   @AutoValue
-   public abstract static class SourceVirtualMachine {
-      public abstract String id();
-
-      @SerializedNames({"id"})
-      public static SourceVirtualMachine create(final String id) {
-         return new AutoValue_ImageProperties_SourceVirtualMachine(id);
-      }
-   }
-   
-   public abstract SourceVirtualMachine sourceVirtualMachine();
+   @Nullable
+   public abstract IdReference sourceVirtualMachine();
    
    @Nullable
    public abstract StorageProfile storageProfile();
@@ -43,7 +34,7 @@ public abstract class ImageProperties implements Provisionable {
    public abstract String provisioningState();
    
    @SerializedNames({ "sourceVirtualMachine", "storageProfile", "provisioningState"})
-   public static ImageProperties create(final SourceVirtualMachine sourceVirtualMachine, 
+   public static ImageProperties create(final IdReference sourceVirtualMachine, 
                                         final StorageProfile storageProfile,
                                         final String provisioningState) {
       return builder()
@@ -61,7 +52,7 @@ public abstract class ImageProperties implements Provisionable {
 
    @AutoValue.Builder
    public abstract static class Builder {
-      public abstract Builder sourceVirtualMachine(SourceVirtualMachine sourceVirtualMachine);
+      public abstract Builder sourceVirtualMachine(IdReference sourceVirtualMachine);
       public abstract Builder storageProfile(StorageProfile storageProfile);
       public abstract Builder provisioningState(String provisioningState);
       public abstract ImageProperties build();

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
index 443e054..d9b43cd 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
@@ -25,11 +25,12 @@ import com.google.auto.value.AutoValue;
 public abstract class ImageReference {
 
    /**
-    * The id of the image reference.
+    * Specifies the resource identifier of a virtual machine image in your subscription. This element is only used
+    * for virtual machine images, not platform images or marketplace images.
     */
    @Nullable
-   public abstract String id();
-   
+   public abstract String customImageId();
+
    /**
     * The publisher of the image reference.
     */
@@ -53,6 +54,10 @@ public abstract class ImageReference {
     */
    @Nullable
    public abstract String version();
+   
+   ImageReference() {
+      
+   }
 
    @SerializedNames({"id", "publisher", "offer", "sku", "version"})
    public static ImageReference create(final String id,
@@ -61,8 +66,7 @@ public abstract class ImageReference {
                                        final String sku,
                                        final String version) {
 
-      return builder()
-              .id(id)
+      return builder().customImageId(id)
               .publisher(publisher)
               .offer(offer)
               .sku(sku)
@@ -78,7 +82,7 @@ public abstract class ImageReference {
 
    @AutoValue.Builder
    public abstract static class Builder {
-      public abstract Builder id(String id);
+      public abstract Builder customImageId(String ids);
       public abstract Builder publisher(String publisher);
       public abstract Builder offer(String offer);
       public abstract Builder sku(String sku);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
index 84cbab1..a8a0ae3 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
@@ -24,42 +24,13 @@ import com.google.auto.value.AutoValue;
 @AutoValue
 public abstract class ManagedDiskParameters {
 
-   public enum StorageAccountTypes {
-      /** Enum value Standard_LRS. */
-      STANDARD_LRS("Standard_LRS"),
-
-      /** Enum value Premium_LRS. */
-      PREMIUM_LRS("Premium_LRS");
-
-      /** The actual serialized value for a StorageAccountTypes instance. */
-      private String value;
-
-      StorageAccountTypes(String value) {
-         this.value = value;
-      }
-
-      public static StorageAccountTypes fromString(String value) {
-         StorageAccountTypes[] items = StorageAccountTypes.values();
-         for (StorageAccountTypes item : items) {
-            if (item.toString().equalsIgnoreCase(value)) {
-               return item;
-            }
-         }
-         return null;
-      }
-
-      @Override
-      public String toString() {
-         return this.value;
-      }
-   }
-
    @Nullable public abstract String id();
 
-   public abstract StorageAccountTypes storageAccountType();
+   // Might be null in custom images. In that case the API returns it in the OSDisk object.
+   @Nullable public abstract StorageAccountType storageAccountType();
 
    @SerializedNames({"id", "storageAccountType"})
    public static ManagedDiskParameters create(final String id, final String storageAccountType) {
-      return new AutoValue_ManagedDiskParameters(id, StorageAccountTypes.fromString(storageAccountType));
+      return new AutoValue_ManagedDiskParameters(id, StorageAccountType.fromString(storageAccountType));
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
index c87fe75..20392a0 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
@@ -64,21 +64,20 @@ public abstract class OSDisk {
     */
    @Nullable public abstract ManagedDiskParameters managedDiskParameters();
    
-   @SerializedNames({"osType", "name", "vhd", "caching", "createOption", "image", "managedDisk"})
-   public static OSDisk create(final String osType, final String name, final VHD vhd,
-                               final String caching, final String createOption, final VHD image, 
-                               final ManagedDiskParameters managedDiskParamenters) {
-      return builder()
-            .osType(osType)
-            .name(name)
-            .vhd(vhd)
-            .caching(caching)
-            .createOption(createOption)
-            .image(image)
-              .managedDiskParameters(managedDiskParamenters)
-              .build();
+   /**
+    * The storage account type. This field is returned in custom images.
+    */
+   @Nullable public abstract StorageAccountType storageAccountType();
+
+   @SerializedNames({ "osType", "name", "vhd", "caching", "createOption", "image", "managedDisk", "storageAccountType" })
+   public static OSDisk create(final String osType, final String name, final VHD vhd, final String caching,
+         final String createOption, final VHD image, final ManagedDiskParameters managedDiskParamenters,
+         final String storageAccountType) {
+      return builder().osType(osType).name(name).vhd(vhd).caching(caching).createOption(createOption).image(image)
+            .managedDiskParameters(managedDiskParamenters)
+            .storageAccountType(StorageAccountType.fromString(storageAccountType)).build();
    }
-   
+
    public abstract Builder toBuilder();
 
    public static Builder builder() {
@@ -94,6 +93,7 @@ public abstract class OSDisk {
       public abstract Builder vhd(VHD vhd);
       public abstract Builder image(VHD image);
       public abstract Builder managedDiskParameters(ManagedDiskParameters managedDiskParameters);
+      public abstract Builder storageAccountType(StorageAccountType storageAccountType);
       public abstract OSDisk build();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageAccountType.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageAccountType.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageAccountType.java
new file mode 100644
index 0000000..33e1109
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageAccountType.java
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+public enum StorageAccountType {
+   /** Enum value Standard_LRS. */
+   STANDARD_LRS("Standard_LRS"),
+
+   /** Enum value Premium_LRS. */
+   PREMIUM_LRS("Premium_LRS");
+
+   /** The actual serialized value for a StorageAccountTypes instance. */
+   private String value;
+
+   StorageAccountType(String value) {
+      this.value = value;
+   }
+
+   public static StorageAccountType fromString(String value) {
+      StorageAccountType[] items = StorageAccountType.values();
+      for (StorageAccountType item : items) {
+         if (item.toString().equalsIgnoreCase(value)) {
+            return item;
+         }
+      }
+      return null;
+   }
+
+   @Override
+   public String toString() {
+      return this.value;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cc13cfed/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
index 04863ad..a01ed23 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
@@ -87,12 +87,18 @@ public abstract class VMImage {
     */
    @Nullable
    public abstract String name();
-
+   
    /**
     * True if custom image
     */
    public abstract boolean custom();
-   
+
+   /**
+    * The id of the custom image template.
+    */
+   @Nullable
+   public abstract String customImageId();
+
    /**
     * Extended version properties.
     */
@@ -104,18 +110,23 @@ public abstract class VMImage {
    }
    
    public static Builder azureImage() {
-      return new AutoValue_VMImage.Builder().globallyAvailable(false).custom(false);
+      return builder().globallyAvailable(false).custom(false);
    }
    
    public static Builder customImage() {
-      return new AutoValue_VMImage.Builder().globallyAvailable(false).custom(true);
+      return builder().globallyAvailable(false).custom(true);
+   }
+   
+   VMImage() {
+      
    }
    
    public abstract Builder toBuilder();
    
    @AutoValue.Builder
    public abstract static class Builder {
-      
+
+      public abstract Builder customImageId(String id);
       public abstract Builder publisher(String published);
       public abstract Builder offer(String offer);
       public abstract Builder sku(String sku);


[19/50] [abbrv] jclouds git commit: Azurecompute ARM - proper tests for disks

Posted by na...@apache.org.
Azurecompute ARM - proper tests for disks

- Fix DataDisk.CachingTypes.fromValue to recognize values properly
- Fix tests which had blob disks and managed disks at the same time
- At this point managed disks are used by default and should be tested.


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

Branch: refs/heads/master
Commit: 9718bec43916b45b8f4a53042fd04be6dee60214
Parents: 50ae019
Author: Valentin Aitken <bo...@gmail.com>
Authored: Fri May 26 17:56:41 2017 +0300
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon May 29 10:29:34 2017 +0200

----------------------------------------------------------------------
 .../azurecompute/arm/domain/DataDisk.java       |  15 ++-
 .../arm/features/VirtualMachineApiMockTest.java |  75 +++++++++---
 .../resources/createvirtualmachineresponse.json |   9 +-
 .../src/test/resources/image.json               |   4 +-
 .../src/test/resources/virtualmachine.json      |  12 +-
 .../src/test/resources/virtualmachines.json     | 113 +++++++++++++++++--
 6 files changed, 188 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/9718bec4/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DataDisk.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DataDisk.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DataDisk.java
index 40189c3..2d61509 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DataDisk.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DataDisk.java
@@ -49,7 +49,12 @@ public abstract class DataDisk implements Provisionable {
       UNRECOGNIZED;
 
       public static CachingTypes fromValue(final String text) {
-         return (CachingTypes) GetEnumValue.fromValueOrDefault(text, UNRECOGNIZED);
+         for (CachingTypes type : CachingTypes.values()) {
+            if (type.toString().equals(text)) {
+               return type;
+            }
+         }
+         return UNRECOGNIZED;
       }
 
       @Override
@@ -108,13 +113,15 @@ public abstract class DataDisk implements Provisionable {
    public static DataDisk create(final String name, final String diskSizeGB, final Integer lun,
                                  final VHD vhd, final VHD image, final String createOption, final String caching, 
                                  final ManagedDiskParameters managedDiskParamenters, final String provisioningState) {
-      return builder()
-              .name(name)
+      final Builder builder = builder();
+      if (caching != null) {
+         builder.caching(CachingTypes.fromValue(caching));
+      }
+      return builder.name(name)
               .diskSizeGB(diskSizeGB)
               .lun(lun)
               .vhd(vhd)
               .image(image)
-              .caching(CachingTypes.fromValue(caching))
               .createOption(DiskCreateOptionTypes.fromValue(createOption))
               .managedDiskParameters(managedDiskParamenters)
               .provisioningState(provisioningState)

http://git-wip-us.apache.org/repos/asf/jclouds/blob/9718bec4/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
index 83e5ef2..258ae1a 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
@@ -42,9 +42,9 @@ import org.jclouds.azurecompute.arm.domain.OSProfile;
 import org.jclouds.azurecompute.arm.domain.OSProfile.LinuxConfiguration;
 import org.jclouds.azurecompute.arm.domain.OSProfile.WindowsConfiguration.AdditionalUnattendContent;
 import org.jclouds.azurecompute.arm.domain.OSProfile.WindowsConfiguration.WinRM.Protocol;
-import org.jclouds.azurecompute.arm.domain.Secrets.SourceVault;
 import org.jclouds.azurecompute.arm.domain.Plan;
 import org.jclouds.azurecompute.arm.domain.Secrets;
+import org.jclouds.azurecompute.arm.domain.Secrets.SourceVault;
 import org.jclouds.azurecompute.arm.domain.Status;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
 import org.jclouds.azurecompute.arm.domain.VHD;
@@ -123,7 +123,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       Plan plan = Plan.create("thinkboxsoftware", "deadline-slave-7-2", "deadline7-2");
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
       VirtualMachine vm = vmAPI
-            .createOrUpdate("windowsmachine", "westus", getProperties(), ImmutableMap.of("foo", "bar"), plan);
+            .createOrUpdate("windowsmachine", "westus", getVMWithManagedDisksProperties(), ImmutableMap.of("foo", "bar"), plan);
       assertEquals(vm, getVM(plan));
       assertSent(
             server,
@@ -137,9 +137,9 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
                   + "\"storageProfile\":{\"imageReference\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/westus/publishers/MicrosoftWindowsServerEssentials/artifactype/vmimage/offers/OFFER/skus/OFFER/versions/latest\","
                   + "\"publisher\":\"publisher\",\"offer\":\"OFFER\",\"sku\":\"sku\",\"version\":\"ver\"},"
                   + "\"osDisk\":{\"osType\":\"Windows\",\"name\":\"windowsmachine\","
-                  + "\"vhd\":{\"uri\":\"https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd\"},\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\","
+                  + "\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\","
                   + "\"managedDisk\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk\",\"storageAccountType\":\"Standard_LRS\"}},"
-                  + "\"dataDisks\":[{\"name\":\"mydatadisk1\",\"diskSizeGB\":\"1\",\"lun\":0,\"vhd\":{\"uri\":\"http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd\"},\"createOption\":\"Empty\",\"caching\":\"Unrecognized\"}]},"
+                  + "\"dataDisks\":[{\"name\":\"mydatadisk1\",\"diskSizeGB\":\"1\",\"lun\":0,\"createOption\":\"Empty\",\"caching\":\"ReadWrite\",\"managedDisk\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk\",\"storageAccountType\":\"Standard_LRS\"}}]},"
                   + "\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"adminPassword\":\"password\",\"customData\":\"\",\"windowsConfiguration\":{\"provisionVMAgent\":false,"
                   + "\"winRM\":{\"listeners\":[{\"protocol\":\"https\",\"certificateUrl\":\"url-to-certificate\"}]},\"additionalUnattendContent\":[{\"pass\":\"oobesystem\",\"component\":\"Microsoft-Windows-Shell-Setup\",\"settingName\":\"FirstLogonCommands\",\"content\":\"<XML unattend content>\"}],"
                   + "\"enableAutomaticUpdates\":true},"
@@ -158,7 +158,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
       server.enqueue(jsonResponse("/createvirtualmachineresponse.json"));
 
       final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
-      VirtualMachine vm = vmAPI.createOrUpdate("windowsmachine", "westus", getProperties(), ImmutableMap.of("foo", "bar"), null);
+      VirtualMachine vm = vmAPI.createOrUpdate("windowsmachine", "westus", getVMWithManagedDisksProperties(), ImmutableMap.of("foo", "bar"), null);
       assertEquals(vm, getVM());
       assertSent(
             server,
@@ -172,9 +172,9 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
                   + "\"storageProfile\":{\"imageReference\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/westus/publishers/MicrosoftWindowsServerEssentials/artifactype/vmimage/offers/OFFER/skus/OFFER/versions/latest\","
                   + "\"publisher\":\"publisher\",\"offer\":\"OFFER\",\"sku\":\"sku\",\"version\":\"ver\"},"
                   + "\"osDisk\":{\"osType\":\"Windows\",\"name\":\"windowsmachine\","
-                  + "\"vhd\":{\"uri\":\"https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd\"},\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\","
+                  + "\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\","
                   + "\"managedDisk\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk\",\"storageAccountType\":\"Standard_LRS\"}},"
-                  + "\"dataDisks\":[{\"name\":\"mydatadisk1\",\"diskSizeGB\":\"1\",\"lun\":0,\"vhd\":{\"uri\":\"http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd\"},\"createOption\":\"Empty\",\"caching\":\"Unrecognized\"}]},"
+                  + "\"dataDisks\":[{\"name\":\"mydatadisk1\",\"diskSizeGB\":\"1\",\"lun\":0,\"createOption\":\"Empty\",\"caching\":\"ReadWrite\",\"managedDisk\":{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk\",\"storageAccountType\":\"Standard_LRS\"}}]},"
                   + "\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"adminPassword\":\"password\",\"customData\":\"\",\"windowsConfiguration\":{\"provisionVMAgent\":false,"
                   + "\"winRM\":{\"listeners\":[{\"protocol\":\"https\",\"certificateUrl\":\"url-to-certificate\"}]},\"additionalUnattendContent\":[{\"pass\":\"oobesystem\",\"component\":\"Microsoft-Windows-Shell-Setup\",\"settingName\":\"FirstLogonCommands\",\"content\":\"<XML unattend content>\"}],"
                   + "\"enableAutomaticUpdates\":true},"
@@ -275,7 +275,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
             "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\",\"overwriteVhds\":\"true\"}");
    }
 
-   private VirtualMachineProperties getProperties() {
+   private VirtualMachineProperties getVMWithBlobDisksProperties() {
       String licenseType = "Windows_Server";
       IdReference availabilitySet = IdReference.create("/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/availabilitySets/myAVSet");
       HardwareProfile hwProf = HardwareProfile.create("Standard_D1");
@@ -284,7 +284,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
             .build();
       VHD vhd = VHD.create("https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd");
       List<DataDisk> dataDisks = ImmutableList.of(
-            DataDisk.create("mydatadisk1", "1", 0, VHD.create("http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd"), 
+            DataDisk.create("mydatadisk1", "1", 0, VHD.create("http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd"),
                   null, "Empty", null, null, null));
       ManagedDiskParameters managedDiskParameters = ManagedDiskParameters.create("/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
             "Standard_LRS");
@@ -298,6 +298,44 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
             AdditionalUnattendContent.create("oobesystem", "Microsoft-Windows-Shell-Setup", "FirstLogonCommands", "<XML unattend content>"));
       OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, winrm, additionalUnattendContent, true);
       List<Secrets> secrets =  ImmutableList.of(
+            Secrets.create(SourceVault.create("/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/Microsoft.KeyVault/vaults/myvault1"),
+                  ImmutableList.of(VaultCertificate.create("https://myvault1.vault.azure.net/secrets/SECRETNAME/SECRETVERSION", "CERTIFICATESTORENAME"))));
+      OSProfile osProfile = OSProfile.create("windowsmachine", "azureuser", "password", "", linuxConfig, windowsConfig, secrets);
+      NetworkInterface networkInterface = NetworkInterface.create("/subscriptions/SUBSCRIPTIONID"
+            + "/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/" + "windowsmachine167", null);
+      List<NetworkInterface> networkInterfaces = new ArrayList<NetworkInterface>();
+      networkInterfaces.add(networkInterface);
+      NetworkProfile networkProfile = NetworkProfile.create(networkInterfaces);
+      DiagnosticsProfile.BootDiagnostics bootDiagnostics = DiagnosticsProfile.BootDiagnostics.create(true,
+            "https://groupname2760.blob.core.windows.net/");
+      DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics);
+      VirtualMachineProperties properties = VirtualMachineProperties.create("27ee085b-d707-xxxx-yyyy-2370e2eb1cc1",
+            licenseType, availabilitySet, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile,
+            VirtualMachineProperties.ProvisioningState.CREATING);
+      return properties;
+   }
+
+   private VirtualMachineProperties getVMWithManagedDisksProperties() {
+      String licenseType = "Windows_Server";
+      IdReference availabilitySet = IdReference.create("/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/availabilitySets/myAVSet");
+      HardwareProfile hwProf = HardwareProfile.create("Standard_D1");
+      ImageReference imgRef = ImageReference.builder().publisher("publisher").offer("OFFER").sku("sku").version("ver")
+            .customImageId("/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/westus/publishers/MicrosoftWindowsServerEssentials/artifactype/vmimage/offers/OFFER/skus/OFFER/versions/latest")
+            .build();
+      ManagedDiskParameters managedDiskParameters = ManagedDiskParameters.create("/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
+            "Standard_LRS");
+      List<DataDisk> dataDisks = ImmutableList.of(
+              DataDisk.builder().name("mydatadisk1").diskSizeGB("1").lun(0).managedDiskParameters(managedDiskParameters).createOption(DataDisk.DiskCreateOptionTypes.EMPTY).caching(DataDisk.CachingTypes.READ_WRITE).build());
+      OSDisk osDisk = OSDisk.builder().osType("Windows").name("windowsmachine").caching("ReadWrite").createOption("FromImage").managedDiskParameters(managedDiskParameters).build();
+      StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk, dataDisks);
+      LinuxConfiguration linuxConfig = null;
+      OSProfile.WindowsConfiguration.WinRM winrm = OSProfile.WindowsConfiguration.WinRM.create(
+            ImmutableList.of(
+                  OSProfile.WindowsConfiguration.WinRM.ProtocolListener.create(Protocol.HTTPS, "url-to-certificate")));
+      List<AdditionalUnattendContent> additionalUnattendContent = ImmutableList.of(
+            AdditionalUnattendContent.create("oobesystem", "Microsoft-Windows-Shell-Setup", "FirstLogonCommands", "<XML unattend content>"));
+      OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, winrm, additionalUnattendContent, true);
+      List<Secrets> secrets =  ImmutableList.of(
             Secrets.create(SourceVault.create("/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/Microsoft.KeyVault/vaults/myvault1"), 
                   ImmutableList.of(VaultCertificate.create("https://myvault1.vault.azure.net/secrets/SECRETNAME/SECRETVERSION", "CERTIFICATESTORENAME"))));
       OSProfile osProfile = OSProfile.create("windowsmachine", "azureuser", "password", "", linuxConfig, windowsConfig, secrets);
@@ -316,7 +354,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
    }
 
    private VirtualMachine getVM() {
-      VirtualMachineProperties properties = getProperties();
+      VirtualMachineProperties properties = getVMWithManagedDisksProperties();
       VirtualMachine machine = VirtualMachine.create("/subscriptions/SUBSCRIPTIONID/" + ""
             + "resourceGroups/groupname/providers/Microsoft.Compute/virtualMachines/windowsmachine", "windowsmachine",
             "Microsoft.Compute/virtualMachines", "westus", ImmutableMap.of("foo", "bar"), properties,
@@ -325,7 +363,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
    }
    
    private VirtualMachine getVM(Plan plan) {
-      VirtualMachineProperties properties = getProperties();
+      VirtualMachineProperties properties = getVMWithManagedDisksProperties();
       VirtualMachine machine = VirtualMachine.create("/subscriptions/SUBSCRIPTIONID/" + ""
             + "resourceGroups/groupname/providers/Microsoft.Compute/virtualMachines/windowsmachine", "windowsmachine",
             "Microsoft.Compute/virtualMachines", "westus", ImmutableMap.of("foo", "bar"), properties, plan);
@@ -355,12 +393,17 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
    }
 
    private List<VirtualMachine> getVMList() {
-      VirtualMachineProperties properties = getProperties();
-      VirtualMachine machine = VirtualMachine.create("/subscriptions/SUBSCRIPTIONID/" + ""
-            + "resourceGroups/groupname/providers/Microsoft.Compute/virtualMachines/windowsmachine", "windowsmachine",
-            "Microsoft.Compute/virtualMachines", "westus", null, properties, null);
       List<VirtualMachine> list = new ArrayList<VirtualMachine>();
-      list.add(machine);
+      VirtualMachineProperties propertiesWithManagedDisks = getVMWithManagedDisksProperties();
+      VirtualMachine machineWithManagedDisks = VirtualMachine.create("/subscriptions/SUBSCRIPTIONID/" + ""
+            + "resourceGroups/groupname/providers/Microsoft.Compute/virtualMachines/windowsmachine", "windowsmachine",
+            "Microsoft.Compute/virtualMachines", "westus", null, propertiesWithManagedDisks, null);
+      list.add(machineWithManagedDisks);
+      VirtualMachineProperties propertiesWithBlobDisks = getVMWithBlobDisksProperties();
+      VirtualMachine machineWithBlobDisks = VirtualMachine.create("/subscriptions/SUBSCRIPTIONID/" + ""
+                      + "resourceGroups/groupname/providers/Microsoft.Compute/virtualMachines/windowsmachine", "windowsmachine",
+              "Microsoft.Compute/virtualMachines", "westus", null, propertiesWithBlobDisks, null);
+      list.add(machineWithBlobDisks);
       return list;
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/9718bec4/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json b/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
index bc8ca2d..4279f83 100644
--- a/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
+++ b/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json
@@ -24,9 +24,6 @@
           "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
           "storageAccountType": "Standard_LRS"
         },
-        "vhd": {
-          "uri": "https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd"
-        },
         "caching": "ReadWrite"
       },
       "dataDisks":[
@@ -34,9 +31,11 @@
           "name":"mydatadisk1",
           "diskSizeGB":"1",
           "lun": 0,
-          "vhd": {
-            "uri" : "http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd"
+          "managedDisk": {
+            "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
+            "storageAccountType": "Standard_LRS"
           },
+          "caching": "ReadWrite",
           "createOption":"Empty"
         }
       ]

http://git-wip-us.apache.org/repos/asf/jclouds/blob/9718bec4/providers/azurecompute-arm/src/test/resources/image.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/image.json b/providers/azurecompute-arm/src/test/resources/image.json
index 3dbdf11..0c7b54c 100644
--- a/providers/azurecompute-arm/src/test/resources/image.json
+++ b/providers/azurecompute-arm/src/test/resources/image.json
@@ -18,7 +18,7 @@
           "id": "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk1"
         },
         "osState": "generalized",
-        "hostCaching": "readwrite",
+        "hostCaching": "ReadWrite",
         "storageAccountType": "Standard_LRS",
         "diskSizeGB": 20
       },
@@ -32,7 +32,7 @@
           "managedDisk": {
             "id": "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk2"
           },
-          "hostCaching": "readwrite",
+          "hostCaching": "ReadWrite",
           "storageAccountType": "Standard_LRS",
           "diskSizeInGB": 20
         }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/9718bec4/providers/azurecompute-arm/src/test/resources/virtualmachine.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachine.json b/providers/azurecompute-arm/src/test/resources/virtualmachine.json
index 70e7f4a..51ad1fb 100644
--- a/providers/azurecompute-arm/src/test/resources/virtualmachine.json
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachine.json
@@ -24,9 +24,6 @@
           "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
           "storageAccountType": "Standard_LRS"
         },
-        "vhd": {
-          "uri": "https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd"
-        },
         "caching": "ReadWrite"
       },
       "dataDisks":[
@@ -34,10 +31,13 @@
           "name":"mydatadisk1",
           "diskSizeGB":"1",
           "lun": 0,
-          "vhd": {
-            "uri" : "http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd"
+          "createOption":"Empty",
+          "managedDisk": {
+            "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
+            "storageAccountType": "Standard_LRS"
           },
-          "createOption":"Empty"
+          "createOption":"Empty",
+          "caching": "ReadWrite"
         }
       ]
     },

http://git-wip-us.apache.org/repos/asf/jclouds/blob/9718bec4/providers/azurecompute-arm/src/test/resources/virtualmachines.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachines.json b/providers/azurecompute-arm/src/test/resources/virtualmachines.json
index 758a109..27ee602 100644
--- a/providers/azurecompute-arm/src/test/resources/virtualmachines.json
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachines.json
@@ -26,9 +26,6 @@
               "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
               "storageAccountType": "Standard_LRS" 
             },
-            "vhd": {
-              "uri": "https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd"
-            },
             "caching": "ReadWrite"
           },
           "dataDisks":[
@@ -36,10 +33,12 @@
               "name":"mydatadisk1",
               "diskSizeGB":"1",
               "lun": 0,
-              "vhd": {
-                "uri" : "http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd"
-              },
-              "createOption":"Empty"
+              "createOption":"Empty",
+              "caching":"ReadWrite",
+              "managedDisk": {
+                "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
+                "storageAccountType": "Standard_LRS"
+              }
             }
           ]    
         },
@@ -99,6 +98,106 @@
       "name": "windowsmachine",
       "type": "Microsoft.Compute/virtualMachines",
       "location": "westus"
+    },
+    {
+      "properties": {
+        "vmId": "27ee085b-d707-xxxx-yyyy-2370e2eb1cc1",
+        "licenseType": "Windows_Server",
+        "availabilitySet":{
+          "id":"/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/availabilitySets/myAVSet"
+        },
+        "hardwareProfile": {
+          "vmSize": "Standard_D1"
+        },
+        "storageProfile": {
+          "imageReference": {
+            "publisher": "publisher",
+            "offer": "OFFER",
+            "sku": "sku",
+            "version": "ver",
+            "id": "/subscriptions/SUBSCRIPTIONID/providers/Microsoft.Compute/locations/westus/publishers/MicrosoftWindowsServerEssentials/artifactype/vmimage/offers/OFFER/skus/OFFER/versions/latest"
+          },
+          "osDisk": {
+            "osType": "Windows",
+            "name": "windowsmachine",
+            "createOption": "FromImage",
+            "managedDisk": {
+              "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
+              "storageAccountType": "Standard_LRS"
+            },
+            "vhd": {
+              "uri": "https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd"
+            },
+            "caching": "ReadWrite"
+          },
+          "dataDisks":[
+            {
+              "name":"mydatadisk1",
+              "diskSizeGB":"1",
+              "lun": 0,
+              "vhd": {
+                "uri" : "http://mystorage1.blob.core.windows.net/vhds/mydatadisk1.vhd"
+              },
+              "createOption":"Empty"
+            }
+          ]
+        },
+        "osProfile": {
+          "computerName": "windowsmachine",
+          "adminUsername": "azureuser",
+          "adminPassword":"password",
+          "customData":"",
+          "windowsConfiguration": {
+            "provisionVMAgent": false,
+            "enableAutomaticUpdates": true,
+            "winRM": {
+              "listeners":[{
+                "protocol": "https",
+                "certificateUrl": "url-to-certificate"
+              }]
+            },
+            "additionalUnattendContent":[
+              {
+                "pass":"oobesystem",
+                "component":"Microsoft-Windows-Shell-Setup",
+                "settingName":"FirstLogonCommands",
+                "content":"<XML unattend content>"
+              }
+            ]
+          },
+          "secrets":[
+            {
+              "sourceVault": {
+                "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/Microsoft.KeyVault/vaults/myvault1"
+              },
+              "vaultCertificates": [
+                {
+                  "certificateUrl": "https://myvault1.vault.azure.net/secrets/SECRETNAME/SECRETVERSION",
+                  "certificateStore": "CERTIFICATESTORENAME"
+                }
+              ]
+            }
+          ]
+        },
+        "networkProfile": {
+          "networkInterfaces": [
+            {
+              "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167"
+            }
+          ]
+        },
+        "diagnosticsProfile": {
+          "bootDiagnostics": {
+            "enabled": true,
+            "storageUri": "https://groupname2760.blob.core.windows.net/"
+          }
+        },
+        "provisioningState": "Creating"
+      },
+      "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute/virtualMachines/windowsmachine",
+      "name": "windowsmachine",
+      "type": "Microsoft.Compute/virtualMachines",
+      "location": "westus"
     }
   ]
 }


[44/50] [abbrv] jclouds git commit: Add Azure KeyVault support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiMockTest.java
new file mode 100644
index 0000000..7459f48
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiMockTest.java
@@ -0,0 +1,1619 @@
+/*
+ * 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 org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+import org.jclouds.azurecompute.arm.domain.Certificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.AdministrationDetails;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateAttributes;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateIssuer;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateOperation;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificatePolicy;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contact;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contacts;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerCredentials;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerParameters;
+import org.jclouds.azurecompute.arm.domain.Certificate.KeyProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.OrganizationDetails;
+import org.jclouds.azurecompute.arm.domain.Certificate.SecretProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.X509CertificateProperties;
+import org.jclouds.azurecompute.arm.domain.Key;
+import org.jclouds.azurecompute.arm.domain.Key.DeletedKeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.JsonWebKey;
+import org.jclouds.azurecompute.arm.domain.Key.KeyAttributes;
+import org.jclouds.azurecompute.arm.domain.Key.KeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.KeyOperationResult;
+import org.jclouds.azurecompute.arm.domain.SKU;
+import org.jclouds.azurecompute.arm.domain.Secret;
+import org.jclouds.azurecompute.arm.domain.Secret.DeletedSecretBundle;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretAttributes;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretBundle;
+import org.jclouds.azurecompute.arm.domain.Vault;
+import org.jclouds.azurecompute.arm.domain.Vault.DeletedVault;
+import org.jclouds.azurecompute.arm.domain.VaultProperties;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.jclouds.rest.ResourceNotFoundException;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+
+@Test(groups = "unit", testName = "VaultApiMockTest", singleThreaded = true)
+public class VaultApiMockTest extends BaseAzureComputeApiMockTest {
+   private final String subscriptionId = "SUBSCRIPTIONID";
+   private final String resourceGroup = "myresourcegroup";
+   private final String tenantId = "myTenantId";
+   private final String identityObjId = "myIdentityObjectId";
+   private final String vaultName = "kvvaultapimocktest";
+   private final String apiVersion = "api-version=2016-10-01";
+   private final String location = "westeurope";
+   private URI vaultUri;
+
+   private static String KEY_NAME = "myKey";
+   private static String TEMP_KEY_NAME = "myTempKey";
+   private static String IMPORT_KEY_NAME = "myImportKey";
+   private static String RECOVERABLE_KEY_NAME = "myRecoverableKey";
+   private static String SECRET_NAME = "mySecret";
+   private static String RECOVERABLE_SECRET_NAME = "myRecoverableSecret";
+   private static String CERTIFICATE_NAME = "myCertificate";
+   private static String TEMP_CERTIFICATE_NAME = "myTempCertificate";
+   private static String RECOVERABLE_CERTIFICATE_NAME = "myRecoverableCertificate";
+   private static String IMPORTABLE_CERTIFICATE_NAME = "myImportableCertificate";
+   private static String CERTIFICATE_ISSUER_NAME = "globalsign01";
+   private String IMPORTABLE_CERTIFICATE_PEM = stringFromResource("/vaultimportablecert.txt");
+   private String sampleSecret = stringFromResource("/vaultsamplesecret.txt");
+   private String keyBackup = stringFromResource("/vaultkeybackup.txt");
+   private String secretBackup = stringFromResource("/vaultsecretbackup.txt");
+   private String[] mergeX5C = {
+           stringFromResource("/vaultmergex5c-1.txt"),
+           stringFromResource("/vaultmergex5c-2.txt"),
+           stringFromResource("/vaultmergex5c-3.txt")
+   };
+   private static String cryptoText = "R29sZCUyNTIxJTJCR29sZCUyNTIxJTJCR2" +
+           "9sZCUyQmZyb20lMkJ0aGUlMkJBbWVyaWNhbiUyQlJpdmVyJTI1MjE";
+   private static String cryptoAlgorithm = "RSA-OAEP";
+   private static String hashToSign = "FvabKT6qGwpml59iHUJ72DZ4XyJcJ8bgpgFA4_8JFmM";
+   private static String signatureAlgorithm = "RS256";
+   private static String contentEncryptionKey = "YxzoHR65aFwD2_IOiZ5rD08jMSALA1y7b_yYW0G3hyI";
+   private static String keyDecryptData = "0_S8pyjjnGRlcbDa-Lt0jYjMXpXrf9Fat3elx-fSO" +
+           "g3dj6mYgEEs6kt79OMD4MFmVyOt6umeWAfdDIkNVnqb5fgyWceveh9wN-37jc5CFgG2PF3XI" +
+           "A6RII-HF2BkBcVa9KcAX3_di4KQE70PXgHf-dlz_RgLOJILeG50wzFeBFCLsjEEPp3itmoai" +
+           "E6vfDidCRm5At8Vjka0G-N_afwkIijfQZLT0VaXvL39cIJE2QN3HJPZM8YPUlkFlYnY4GIRy" +
+           "RWSBpK_KYuVufzUGtDi6Sh8pUa67ppa7DHVZlixlmnVqI3Oeg6XUvMqbFFqVSrcNbRQDwVGL" +
+           "3cUtK-KB1PfKg";
+   private static String keySignedData = "uO0r4P1cB-fKsDZ8cj5ahiNw8Tdsudt5zLCeEKOt29" +
+           "LAlPDpeGx9Q1SOFNaR7JlRYVelxsohdzvydwX8ao6MLnqlpdEj0Xt5Aadp-kN84AXW238gab" +
+           "S1AUyiWILCmdsBFeRU4wTRSxz2qGS_0ztHkaNln32P_9GJC72ZRlgZoVA4C_fowZolUoCWGj" +
+           "4V7fAzcSoiNYipWP0HkFe3xmuz-cSQg3CCAs-MclHHfMeSagLJZZQ9bpl5LIr-Ik89bNtqEq" +
+           "yP7Jb_fCgHajAx2lUFcRZhSIKuCfrLPMl6wzejQ2rQXX-ixEkDa73dYaPIrVW4IL3iC0Ufxn" +
+           "fxYffHJ7QCRw";
+   private static String keyWrappedData = "1jcTlu3KJNDBYydhaH9POWOo0tAPGkpsZVizCkHpC" +
+           "3g_9Kg91Q3HKK-rfZynn5W5nVPM-SVFHA3JTankcXX8gx8GycwUh4pMoyil_DV35m2QjyuiT" +
+           "ln83OJXw-nMvRXyKdVfF7nyRcs256kW7gthAOsYUVBrfFS7DFFxsXqLNREsA8j85IqIXIm8p" +
+           "AB3C9uvl1I7SQhLvrwZZXXqjeCWMfseVJwWgsQFyyqH2P0f3-xnngV7cvik2k3Elrk3G_2Cu" +
+           "JCozIIrANg9zG9Z8DrwSNNm9YooxWkSu0ZeDLOJ0bMdhcPGGm5OvKz3oZqX-39yv5klNlCRb" +
+           "r0q7gqmI0x25w";
+
+   @BeforeMethod
+   public void start() throws IOException, URISyntaxException {
+      super.start();
+      vaultUri = server.getUrl("").toURI();
+   }
+
+   public void createVault() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultcreate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Vault vault = vaultApi.createOrUpdateVault(vaultName, location, VaultProperties.builder()
+              .tenantId(this.tenantId)
+              .sku(SKU.create(location, "standard", null, "A"))
+              .accessPolicies(ImmutableList.of(VaultProperties.AccessPolicyEntry.create(null, this.identityObjId, this.tenantId,
+                      VaultProperties.Permissions.create(
+                              ImmutableList.of( // certificates
+                                      "Get",
+                                      "List",
+                                      "Update",
+                                      "Create",
+                                      "Import",
+                                      "Delete",
+                                      "ManageContacts",
+                                      "ManageIssuers",
+                                      "GetIssuers",
+                                      "ListIssuers",
+                                      "SetIssuers",
+                                      "DeleteIssuers",
+                                      "Purge",
+                                      "Recover"
+                              ),
+                              ImmutableList.of( // keys
+                                      "Get",
+                                      "List",
+                                      "Update",
+                                      "Create",
+                                      "Import",
+                                      "Delete",
+                                      "Recover",
+                                      "Backup",
+                                      "Restore",
+                                      "Purge",
+                                      "Encrypt",
+                                      "Decrypt",
+                                      "Sign",
+                                      "Verify",
+                                      "WrapKey",
+                                      "UnwrapKey"
+                              ),
+                              ImmutableList.of( // secrets
+                                      "Get",
+                                      "List",
+                                      "Set",
+                                      "Delete",
+                                      "Recover",
+                                      "Backup",
+                                      "Restore",
+                                      "Purge"
+                              ),
+                              ImmutableList.<String>of()
+                      ))))
+              .build(),
+              null);
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults/%s?%s",
+              subscriptionId, resourceGroup, vaultName, apiVersion
+      );
+      assertSent(server, "PUT", path, stringFromResource("/vaultcreaterequestbody.json"));
+
+      assertNotNull(vault);
+      assertNotNull(vault.properties().vaultUri());
+      assertTrue(!vault.name().isEmpty());
+   }
+
+   public void listVaults() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlist.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Vault> vaults = vaultApi.listVaults();
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults?%s",
+              subscriptionId, resourceGroup, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNotNull(vaults);
+      assertTrue(vaults.size() > 0);
+      assertTrue(!vaults.get(0).name().isEmpty());
+   }
+
+   public void listVaultsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Vault> vaults = vaultApi.listVaults();
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults?%s",
+              subscriptionId, resourceGroup, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertTrue(vaults.isEmpty());
+   }
+
+   public void getVault() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultget.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Vault vault = vaultApi.getVault(vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults/%s?%s",
+              subscriptionId, resourceGroup, vaultName, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNotNull(vault);
+      assertTrue(!vault.name().isEmpty());
+   }
+
+   public void getVaultReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Vault vault = vaultApi.getVault(vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults/%s?%s",
+              subscriptionId, resourceGroup, vaultName, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNull(vault);
+   }
+
+   public void deleteVault() throws InterruptedException {
+      server.enqueue(response200());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.deleteVault(vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults/%s?%s",
+              subscriptionId, resourceGroup, vaultName, apiVersion
+      );
+      assertSent(server, "DELETE", path);
+
+      assertTrue(status);
+   }
+
+   public void deleteVaultReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.deleteVault(vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults/%s?%s",
+              subscriptionId, resourceGroup, vaultName, apiVersion
+      );
+      assertSent(server, "DELETE", path);
+
+      assertFalse(status);
+   }
+
+   public void purgeDeletedVault() throws InterruptedException {
+      server.enqueue(response200());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeVault(location, vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/locations/%s/deletedVaults/%s/purge?%s",
+              subscriptionId, location, vaultName, apiVersion
+      );
+      assertSent(server, "POST", path);
+
+      assertTrue(status);
+   }
+
+   public void purgeDeletedVaultReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeVault(location, vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/locations/%s/deletedVaults/%s/purge?%s",
+              subscriptionId, location, vaultName, apiVersion
+      );
+      assertSent(server, "POST", path);
+
+      assertFalse(status);
+   }
+
+   public void listDeletedVaults() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistdeleted.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedVault> vaults = vaultApi.listDeletedVaults();
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/deletedVaults?%s",
+              subscriptionId, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNotNull(vaults);
+      assertTrue(vaults.size() > 0);
+   }
+
+   public void listDeletedVaultsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedVault> vaults = vaultApi.listDeletedVaults();
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/deletedVaults?%s",
+              subscriptionId, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertTrue(vaults.isEmpty());
+   }
+
+   public void getDeletedVault() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetdeleted.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedVault vault = vaultApi.getDeletedVault(location, vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/locations/%s/deletedVaults/%s?%s",
+              subscriptionId, location, vaultName, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNotNull(vault);
+      assertTrue(!vault.name().isEmpty());
+      assertTrue(!vault.properties().deletionDate().toString().isEmpty());
+   }
+
+   public void getDeletedVaultReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedVault vault = vaultApi.getDeletedVault(location, vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/locations/%s/deletedVaults/%s?%s",
+              subscriptionId, location, vaultName, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNull(vault);
+   }
+
+
+   // Key mock tests
+   public void listKeys() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistkeys.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Key> keys = vaultApi.listKeys(vaultUri);
+
+      String path = String.format("/keys?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(keys);
+      assertTrue(keys.size() > 0);
+   }
+
+   public void listKeysReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Key> keys = vaultApi.listKeys(vaultUri);
+
+      String path = String.format("/keys?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(keys.isEmpty());
+   }
+
+   public void createKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultcreatekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyAttributes keyAttr = KeyAttributes.create(true, null, null, null, null, null);
+      KeyBundle keyBundle = vaultApi.createKey(vaultUri,
+              KEY_NAME,
+              keyAttr,
+              null,
+              null,
+              2048,
+              "RSA",
+              null
+      );
+
+      String path = String.format("/keys/%s/create?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultcreatekeyrequestbody.json"));
+
+      assertNotNull(keyBundle);
+      assertNotNull(keyBundle.attributes().created());
+   }
+
+   public void importKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultcreatekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyAttributes keyAttr = KeyAttributes.create(true, null, null, null, null, null);
+      List<String> keyOps = new ArrayList<String>();
+      keyOps.add("encrypt");
+      JsonWebKey keyInfo = JsonWebKey.create(
+              null,
+              "DjU54mYvHpICXHjc5-JiFqiH8NkUgOG8LL4kwt3DeBp9bP0-5hSJH8vmzwJkeGG9L79EWG4b_bfxgYdeNX7cFFagmW" +
+                      "PRFrlxbd64VRYFawZHRJt-2cbzMVI6DL8EK4bu5Ux5qTiV44Jw19hoD9nDzCTfPzSTSGrKD3iLPdnREYaIGDVxcjB" +
+                      "v3Tx6rrv3Z2lhHHKhEHb0RRjATcjAVKV9NZhMajJ4l9pqJ3A4IQrCBl95ux6Xm1oXP0i6aR78cjchsCpcMXdP3WMs" +
+                      "vHgTlsZT0RZLFHrvkiNHlPiil4G2_eHkwvT__CrcbO6SmI_zCtMmypuHJqcr-Xb7GPJoa64WoQ",
+              "DB9nGuHplY_7Xv5a5UCs5YgxkWPtJFfbIZ1Zr-XHCCY09JIWReOGQG226OhjwixKtOK_OqmAKtMKM9OmKviJRHNbD" +
+                      "hbTxumN3u7cL8dftjXpSryiEQlPmWyW94MneI2WNIrvh4wruQuDt8EztgOiDFxwcnUgey8iend7WmZnE7E",
+              "O-bSTUQ4N_UuQezgkF3TDrnBraO67leDGwRbfiE_U0ghQvqh5DA0QSPVzlWDZc9KUitvj8vxsR9o1PW9GS0an17GJ" +
+                      "EYuetLnkShKK3NWOhBBX6d1yP9rVdH6JhgIJEy_g0Suz7TAFiFc8i7JF8u4QJ05C8bZAMhOLotqftQeVOM",
+              "AQAB",
+              null,
+              null,
+              keyOps,
+              null,
+              "RSA",
+              "33TqqLR3eeUmDtHS89qF3p4MP7Wfqt2Zjj3lZjLjjCGDvwr9cJNlNDiuKboODgUiT4ZdPWbOiMAfDcDzlOxA04DDnEF" +
+                      "GAf-kDQiNSe2ZtqC7bnIc8-KSG_qOGQIVaay4Ucr6ovDkykO5Hxn7OU7sJp9TP9H0JH8zMQA6YzijYH9LsupTerrY" +
+                      "3U6zyihVEDXXOv08vBHk50BMFJbE9iwFwnxCsU5-UZUZYw87Uu0n4LPFS9BT8tUIvAfnRXIEWCha3KbFWmdZQZlyr" +
+                      "Fw0buUEf0YN3_Q0auBkdbDR_ES2PbgKTJdkjc_rEeM0TxvOUf7HuUNOhrtAVEN1D5uuxE1WSw",
+              "8K33pX90XX6PZGiv26wZm7tfvqlqWFT03nUMvOAytqdxhO2HysiPn4W58OaJd1tY4372Qpiv6enmUeI4MidCie-s-d0" +
+                      "_B6A0xfhU5EeeaDN0xDOOl8yN-kaaVj9b4HDR3c91OAwKpDJQIeJVZtxoijxl-SRx3u7Vs_7meeSpOfE",
+              "7a5KnUs1pTo72A-JquJvIz4Eu794Yh3ftTk_Et-83aE_FVc6Nk-EhfnwYSNpVmM6UKdrAoy5gsCvZPxrq-eR9pEwU8M" +
+                      "5UOlki03vWY_nqDBpJSIqwPvGHUB16zvggsPQUyQBfnN3N8XlDi12n88ltvWwEhn1LQOwMUALEfka9_s",
+              "InfGmkb2jNkPGuNiZ-mU0-ZrOgLza_fLL9ErZ35jUPhGFzdGxJNobklvsNoTd-E2GAU41YkJh24bncMLvJVYxHHA5iF" +
+                      "7FBWx1SvpEyKVhhnIcuXGD7N5PbNZzEdmr9C6I7cPVkWO-sUV7zfFukexIcANmsd_oBBGKRoYzP5Tti4",
+              null,
+              null
+      );
+      KeyBundle importedKey = vaultApi.importKey(vaultUri, IMPORT_KEY_NAME, false, keyAttr, keyInfo, null);
+
+      String path = String.format("/keys/%s?%s", IMPORT_KEY_NAME, apiVersion);
+      assertSent(server, "PUT", path, stringFromResource("/vaultimportkeyrequestbody.json"));
+
+      assertNotNull(importedKey);
+      assertNotNull(importedKey.attributes().created());
+   }
+
+   public void getKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetkey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyBundle key = vaultApi.getKey(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s?%s", KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(key);
+      assertNotNull(key.attributes().created());
+   }
+
+   public void getKeyReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyBundle key = vaultApi.getKey(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s?%s", KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(key);
+   }
+
+   public void deleteKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedKeyBundle key = vaultApi.deleteKey(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s?%s", KEY_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(key);
+      assertNotNull(key.attributes().created());
+   }
+
+   public void deleteKeyReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedKeyBundle key = vaultApi.deleteKey(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s?%s", KEY_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(key);
+   }
+
+   public void getKeyVersions() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetkeyversions.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Key> keys = vaultApi.getKeyVersions(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s/versions?%s", KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(keys);
+      assertTrue(keys.size() > 0);
+      assertNotNull(keys.get(0).attributes().created());
+   }
+
+   public void getKeyVersionsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Key> keys = vaultApi.getKeyVersions(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s/versions?%s", KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(keys.isEmpty());
+   }
+
+   public void updateKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing");
+      KeyBundle updatedKey = vaultApi.updateKey(vaultUri, KEY_NAME, null, null, null, tags);
+
+      String path = String.format("/keys/%s?%s", KEY_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatekeyrequestbody.json"));
+
+      assertNotNull(updatedKey);
+      assertNotNull(updatedKey.attributes().created());
+   }
+
+   public void updateKeyWithVersion() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatekeywithversion.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      String keyVersion = "bd6566ec707e4ad89f4ab9577d9d0bef";
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing");
+      KeyBundle updatedKey = vaultApi.updateKey(vaultUri, KEY_NAME, keyVersion, null, null, tags);
+
+      String path = String.format("/keys/%s/%s?%s", KEY_NAME, keyVersion, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatekeyrequestbody.json"));
+
+      assertNotNull(updatedKey);
+      assertNotNull(updatedKey.attributes().created());
+   }
+
+   public void backupKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultbackupkey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      String keyBackup = vaultApi.backupKey(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s/backup?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path);
+
+      assertNotNull(keyBackup);
+      assertTrue(keyBackup.length() > 0);
+   }
+
+   public void restoreKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultrestorekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyBundle restoredKey = vaultApi.restoreKey(vaultUri, keyBackup);
+
+      String path = String.format("/keys/restore?%s", apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultrestorekeyrequestbody.json"));
+
+      assertNotNull(restoredKey);
+      assertNotNull(restoredKey.attributes().created());
+   }
+
+   public void listDeletedKeys() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistdeletedkeys.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedKeyBundle> keys = vaultApi.listDeletedKeys(vaultUri);
+
+      String path = String.format("/deletedkeys?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(keys);
+      assertTrue(keys.size() > 0);
+   }
+
+   public void listDeletedKeysReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedKeyBundle> keys = vaultApi.listDeletedKeys(vaultUri);
+
+      String path = String.format("/deletedkeys?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(keys.isEmpty());
+   }
+
+   public void getDeletedKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetdeletedkey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedKeyBundle key = vaultApi.getDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+
+      String path = String.format("/deletedkeys/%s?%s", RECOVERABLE_KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(key);
+      assertTrue(!key.deletedDate().isEmpty());
+   }
+
+   public void getDeletedKeyReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedKeyBundle key = vaultApi.getDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+
+      String path = String.format("/deletedkeys/%s?%s", RECOVERABLE_KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(key);
+   }
+
+   public void recoverDeletedKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultrecoverdeletedkey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyBundle key = vaultApi.recoverDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+
+      String path = String.format("/deletedkeys/%s/recover?%s", RECOVERABLE_KEY_NAME, apiVersion);
+      assertSent(server, "POST", path);
+
+      assertNotNull(key);
+      assertNotNull(key.attributes().created());
+   }
+
+   public void purgeDeletedKey() throws InterruptedException {
+      server.enqueue(response200());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+
+      String path = String.format("/deletedkeys/%s?%s", RECOVERABLE_KEY_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertTrue(status);
+   }
+
+   public void purgeDeletedKeyReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+
+      String path = String.format("/deletedkeys/%s?%s", RECOVERABLE_KEY_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertFalse(status);
+   }
+
+   public void encrypt() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeyencrypt.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyOperationResult encryptResult = vaultApi.encrypt(vaultUri,
+              KEY_NAME,
+              null,
+              cryptoAlgorithm,
+              cryptoText
+      );
+
+      String path = String.format("/keys/%s/encrypt?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeyencryptrequestbody.json"));
+
+      assertNotNull(encryptResult);
+      assertTrue(!encryptResult.value().isEmpty());
+   }
+
+   public void decrypt() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeydecrypt.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyOperationResult decryptResult = vaultApi.decrypt(vaultUri,
+              KEY_NAME,
+              null,
+              cryptoAlgorithm,
+              keyDecryptData
+      );
+
+      String path = String.format("/keys/%s/decrypt?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeydecryptrequestbody.json"));
+
+      assertNotNull(decryptResult);
+      assertTrue(!decryptResult.value().isEmpty());
+   }
+
+   public void sign() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeysign.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyOperationResult signResult = vaultApi.sign(vaultUri,
+              KEY_NAME,
+              null,
+              signatureAlgorithm,
+              hashToSign
+      );
+
+      String path = String.format("/keys/%s/sign?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeysignrequestbody.json"));
+
+      assertNotNull(signResult);
+      assertTrue(!signResult.value().isEmpty());
+   }
+
+   public void verify() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeyverify.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean verifyResult = vaultApi.verify(vaultUri,
+              KEY_NAME,
+              null,
+              signatureAlgorithm,
+              hashToSign,
+              keySignedData
+      );
+
+      String path = String.format("/keys/%s/verify?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeyverifyrequestbody.json"));
+
+      assertTrue(verifyResult);
+   }
+
+   public void wrap() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeywrap.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyOperationResult wrapResult = vaultApi.wrap(vaultUri,
+              KEY_NAME,
+              null,
+              cryptoAlgorithm,
+              contentEncryptionKey
+      );
+
+      String path = String.format("/keys/%s/wrapkey?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeywraprequestbody.json"));
+
+      assertNotNull(wrapResult);
+      assertTrue(!wrapResult.value().isEmpty());
+   }
+
+   public void unwrap() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeyunwrap.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyOperationResult unwrapResult = vaultApi.unwrap(vaultUri,
+              KEY_NAME,
+              null,
+              cryptoAlgorithm,
+              keyWrappedData
+      );
+
+      String path = String.format("/keys/%s/unwrapkey?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeyunwraprequestbody.json"));
+
+      assertNotNull(unwrapResult);
+      assertTrue(!unwrapResult.value().isEmpty());
+   }
+
+   // Secret mock tests
+   public void listSecrets() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistsecrets.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Secret> secrets = vaultApi.listSecrets(vaultUri);
+
+      String path = String.format("/secrets?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(secrets);
+      assertTrue(secrets.size() > 0);
+   }
+
+   public void listSecretsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Secret> secrets = vaultApi.listSecrets(vaultUri);
+
+      String path = String.format("/secrets?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(secrets.isEmpty());
+   }
+
+   public void setSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultsetsecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      SecretAttributes attributes = SecretAttributes.create(true, null, null, null, null, null);
+      SecretBundle secretBundle = vaultApi.setSecret(vaultUri,
+              SECRET_NAME,
+              attributes,
+              "testSecretKey",
+              null,
+              sampleSecret
+      );
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "PUT", path, stringFromResource("/vaultsetsecretrequestbody.json"));
+
+      assertNotNull(secretBundle);
+      assertTrue(!secretBundle.id().isEmpty());
+   }
+
+   public void getSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetsecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      SecretBundle secret = vaultApi.getSecret(vaultUri, SECRET_NAME, null);
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(secret);
+      assertNotNull(secret.attributes().created());
+   }
+
+   public void getSecretReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      SecretBundle secret = vaultApi.getSecret(vaultUri, SECRET_NAME, null);
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(secret);
+   }
+
+   public void deleteSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletesecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedSecretBundle secret = vaultApi.deleteSecret(vaultUri, SECRET_NAME);
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(secret);
+      assertNotNull(secret.attributes().created());
+   }
+
+   public void deleteSecretReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedSecretBundle secret = vaultApi.deleteSecret(vaultUri, SECRET_NAME);
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(secret);
+   }
+
+   public void getSecretVersions() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetsecretversions.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Secret> secrets = vaultApi.getSecretVersions(vaultUri, SECRET_NAME);
+
+      String path = String.format("/secrets/%s/versions?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(secrets);
+      assertTrue(secrets.size() > 0);
+      assertNotNull(secrets.get(0).attributes().created());
+   }
+
+   public void getSecretVersionsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Secret> secrets = vaultApi.getSecretVersions(vaultUri, SECRET_NAME);
+
+      String path = String.format("/secrets/%s/versions?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(secrets.isEmpty());
+   }
+
+   public void updateSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing");
+      SecretBundle updatedSecret = vaultApi.updateSecret(vaultUri, SECRET_NAME, null, null, null, tags);
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatesecretrequestbody.json"));
+
+      assertNotNull(updatedSecret);
+      assertNotNull(updatedSecret.attributes().created());
+   }
+
+   public void updateSecretWithVersion() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatesecretwithversion.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      String secretVersion = "b936ececbc674f3bb1367ae50d28ada0";
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing again");
+      SecretBundle updatedSecret = vaultApi.updateSecret(vaultUri, SECRET_NAME,  secretVersion, null, null, tags);
+
+      String path = String.format("/secrets/%s/%s?%s", SECRET_NAME, secretVersion, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatesecretwithversionrequestbody.json"));
+
+      assertNotNull(updatedSecret);
+      assertNotNull(updatedSecret.attributes().created());
+   }
+
+   public void backupSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultbackupsecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      String secretBackup = vaultApi.backupSecret(vaultUri, SECRET_NAME);
+
+      String path = String.format("/secrets/%s/backup?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "POST", path);
+
+      assertNotNull(secretBackup);
+      assertTrue(secretBackup.length() > 0);
+   }
+
+   public void restoreSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultrestoresecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      SecretBundle restoredSecret = vaultApi.restoreSecret(vaultUri, secretBackup);
+
+      String path = String.format("/secrets/restore?%s", apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultrestoresecretrequestbody.json"));
+
+      assertNotNull(restoredSecret);
+      assertNotNull(restoredSecret.attributes().created());
+   }
+
+   public void listDeletedSecrets() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistdeletedsecrets.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedSecretBundle> secrets = vaultApi.listDeletedSecrets(vaultUri);
+
+      String path = String.format("/deletedsecrets?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(secrets);
+      assertTrue(secrets.size() > 0);
+   }
+
+   public void listDeletedSecretsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedSecretBundle> secrets = vaultApi.listDeletedSecrets(vaultUri);
+
+      String path = String.format("/deletedsecrets?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(secrets.isEmpty());
+   }
+
+   public void getDeletedSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetdeletedsecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedSecretBundle secret = vaultApi.getDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+
+      String path = String.format("/deletedsecrets/%s?%s", RECOVERABLE_SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(secret);
+      assertTrue(!secret.deletedDate().isEmpty());
+   }
+
+   public void getDeletedSecretReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedSecretBundle secret = vaultApi.getDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+
+      String path = String.format("/deletedsecrets/%s?%s", RECOVERABLE_SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(secret);
+   }
+
+   public void recoverDeletedSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultrecoverdeletedsecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      SecretBundle secret = vaultApi.recoverDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+
+      String path = String.format("/deletedsecrets/%s/recover?%s", RECOVERABLE_SECRET_NAME, apiVersion);
+      assertSent(server, "POST", path);
+
+      assertNotNull(secret);
+      assertNotNull(secret.attributes().created());
+   }
+
+   public void purgeDeletedSecret() throws InterruptedException {
+      server.enqueue(response200());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+
+      String path = String.format("/deletedsecrets/%s?%s", RECOVERABLE_SECRET_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertTrue(status);
+   }
+
+   public void purgeDeletedSecretReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+
+      String path = String.format("/deletedsecrets/%s?%s", RECOVERABLE_SECRET_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertFalse(status);
+   }
+
+   public void createCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultcreatecertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificatePolicy policy = CertificatePolicy.create(null,
+              CERTIFICATE_NAME,
+              IssuerParameters.create(null, "Self"),
+              KeyProperties.create(false, 2048, "RSA", false),
+              null,
+              null,
+              X509CertificateProperties.create(null, null, null, "CN=mycertificate.foobar.com", 12)
+      );
+      CertificateOperation certOp = vaultApi.createCertificate(vaultUri,
+              CERTIFICATE_NAME,
+              null,
+              policy,
+              null
+      );
+
+      String path = String.format("/certificates/%s/create?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultcreatecertificaterequestbody.json"));
+
+      assertNotNull(certOp);
+      assertTrue(!certOp.id().isEmpty());
+   }
+
+   public void getCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetcertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateBundle cert = vaultApi.getCertificate(vaultUri, CERTIFICATE_NAME, null);
+
+      String path = String.format("/certificates/%s?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(cert);
+      assertTrue(!cert.id().isEmpty());
+   }
+
+   public void getCertificateReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateBundle cert = vaultApi.getCertificate(vaultUri, CERTIFICATE_NAME, null);
+
+      String path = String.format("/certificates/%s?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(cert);
+   }
+
+   public void deleteCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletecertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedCertificateBundle cert = vaultApi.deleteCertificate(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(cert);
+      assertTrue(!cert.id().isEmpty());
+   }
+
+   public void deleteCertificateReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedCertificateBundle cert = vaultApi.deleteCertificate(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(cert);
+   }
+
+   public void listCertificates() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistcertificates.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Certificate> certs = vaultApi.getCertificates(vaultUri);
+
+      String path = String.format("/certificates?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(certs);
+      assertTrue(certs.size() > 0);
+   }
+
+   public void listCertificatesReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Certificate> certs = vaultApi.getCertificates(vaultUri);
+
+      String path = String.format("/certificates?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(certs.isEmpty());
+   }
+
+   public void listDeletedCertificates() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistdeletedcertificates.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedCertificate> certs = vaultApi.getDeletedCertificates(vaultUri);
+
+      String path = String.format("/deletedcertificates?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(certs);
+      assertTrue(certs.size() > 0);
+   }
+
+   public void listDeletedCertificatesReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedCertificate> certs = vaultApi.getDeletedCertificates(vaultUri);
+
+      String path = String.format("/deletedcertificates?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(certs.isEmpty());
+   }
+
+   public void getDeletedCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetdeletedcertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedCertificateBundle cert = vaultApi.getDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+
+      String path = String.format("/deletedcertificates/%s?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(cert);
+      assertTrue(!cert.id().isEmpty());
+   }
+
+   public void getDeletedCertificateReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedCertificateBundle cert = vaultApi.getDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+
+      String path = String.format("/deletedcertificates/%s?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(cert);
+   }
+
+   public void recoverDeletedCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultrecoverdeletedcertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateBundle cert = vaultApi.recoverDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+
+      String path = String.format("/deletedcertificates/%s/recover?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "POST", path);
+
+      assertNotNull(cert);
+      assertTrue(!cert.id().isEmpty());
+   }
+
+   public void purgeDeletedCertificate() throws InterruptedException {
+      server.enqueue(response200());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+
+      String path = String.format("/deletedcertificates/%s?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertTrue(status);
+   }
+
+   public void purgeDeletedCertificateReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+
+      String path = String.format("/deletedcertificates/%s?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertFalse(status);
+   }
+
+   public void listCertificateVersions() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistcertificateversions.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Certificate> certs = vaultApi.getCertificateVersions(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/versions?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(certs);
+      assertTrue(certs.size() > 0);
+   }
+
+   public void listCertificateVersionsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Certificate> certs = vaultApi.getCertificateVersions(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/versions?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(certs.isEmpty());
+   }
+
+   public void updateCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatecertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("selfsigned", "true");
+      CertificatePolicy policy = CertificatePolicy.create(null,
+              CERTIFICATE_NAME,
+              IssuerParameters.create(null, "Self"),
+              KeyProperties.create(false, 2048, "RSA", false),
+              null,
+              null,
+              X509CertificateProperties.create(null, null, null, "CN=mycertificate.foobar.com", 12)
+      );
+      CertificateBundle certBundle = vaultApi.updateCertificate(
+              vaultUri,
+              CERTIFICATE_NAME,
+              null,
+              null,
+              policy,
+              tags
+      );
+
+      String path = String.format("/certificates/%s?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatecertificaterequestbody.json"));
+
+      assertNotNull(certBundle);
+      assertTrue(!certBundle.id().isEmpty());
+   }
+
+   public void updateCertificateVersion() {
+      // Update the specific version of a certificate
+
+        /*
+         * XXX -- update using version complains about needing policy (required input), yet
+         * passing in the same policy results in the error:
+         *
+         * Policy cannot be updated with a specific version of a certificate
+         *
+         * Will uncomment/fix once this issue is resolved.
+         *
+         */
+      throw new SkipException("azure bug - update using version complains about needing policy");
+   }
+
+   public void importCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultimportcertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      String certPem = IMPORTABLE_CERTIFICATE_PEM;
+      CertificateBundle certBundle = null;
+      try {
+         certBundle = vaultApi.importCertificate(
+                 vaultUri,
+                 RECOVERABLE_CERTIFICATE_NAME,
+                 null,
+                 CertificatePolicy.create(
+                         null,
+                         null,
+                         null,
+                         null,
+                         null,
+                         SecretProperties.create("application/x-pem-file"),
+                         null
+                 ),
+                 null,
+                 null,
+                 certPem);
+      } catch (ResourceNotFoundException rnf) {
+         assertNotNull(rnf);
+      }
+
+      String path = String.format("/certificates/%s/import?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultimportcertificaterequestbody.json"));
+
+      assertNotNull(certBundle);
+      assertTrue(!certBundle.id().isEmpty());
+   }
+
+   public void mergeCertificate() throws InterruptedException {
+      // Merging a certificate is for when a CSR is signed by an external CA
+      server.enqueue(jsonResponse("/vaultmergecertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateAttributes attributes = CertificateAttributes.create(null, true, null, null, null, null);
+      CertificateBundle certBundle = vaultApi.mergeCertificate(
+              vaultUri,
+              CERTIFICATE_NAME,
+              attributes,
+              null,
+              Arrays.asList(mergeX5C)
+      );
+
+      String path = String.format("/certificates/%s/pending/merge?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultmergecertificaterequestbody.json"));
+
+      assertNotNull(certBundle);
+      assertTrue(!certBundle.attributes().created().toString().isEmpty());
+   }
+
+   public void getCertificateOperation() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetcertificateoperation.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateOperation certOp = vaultApi.getCertificateOperation(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/pending?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(certOp);
+      assertTrue(!certOp.id().isEmpty());
+   }
+
+   public void getCertificateOperationReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateOperation certOp = vaultApi.getCertificateOperation(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/pending?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(certOp);
+   }
+
+   public void updateCertificateOperation() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatecertificateoperation.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateOperation certOp = vaultApi.updateCertificateOperation(vaultUri, CERTIFICATE_NAME, true);
+
+      String path = String.format("/certificates/%s/pending?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatecertificateoperationrequestbody.json"));
+
+      assertNotNull(certOp);
+      assertTrue(!certOp.id().isEmpty());
+   }
+
+   public void deleteCertificateOperation() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletecertificateoperation.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateOperation certOp = vaultApi.deleteCertificateOperation(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/pending?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(certOp);
+      assertTrue(!certOp.id().isEmpty());
+   }
+
+   public void deleteCertificateOperationReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateOperation certOp = vaultApi.deleteCertificateOperation(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/pending?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(certOp);
+   }
+
+   public void setCertificateIssuer() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultsetcertificateissuer.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      AdministrationDetails adminDetail = AdministrationDetails.create(
+              "adminguy@certsforme.com",
+              "Admin",
+              "Guy",
+              "867-5309"
+      );
+      List<AdministrationDetails> adminDetails = new ArrayList<AdministrationDetails>();
+      adminDetails.add(adminDetail);
+      OrganizationDetails orgDetails = OrganizationDetails.create(
+              adminDetails,
+              null
+      );
+      IssuerBundle issuer = null;
+      try {
+         issuer = vaultApi.setCertificateIssuer(
+                 vaultUri,
+                 CERTIFICATE_ISSUER_NAME,
+                 null,
+                 IssuerCredentials.create("imauser", "This1sMyPa55wurD!"),
+                 orgDetails,
+                 "GlobalSign"
+         );
+      } catch (ResourceNotFoundException rnf) {
+         assertNotNull(rnf);
+      }
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "PUT", path, stringFromResource("/vaultsetcertificateissuerrequestbody.json"));
+
+      assertNotNull(issuer);
+      assertTrue(!issuer.id().isEmpty());
+   }
+
+   public void listCertificateIssuers() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistcertificateissuers.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<CertificateIssuer> issuers = vaultApi.getCertificateIssuers(vaultUri);
+
+      String path = String.format("/certificates/issuers?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(issuers);
+      assertTrue(issuers.size() > 0);
+   }
+
+   public void listCertificateIssuersReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<CertificateIssuer> issuers = vaultApi.getCertificateIssuers(vaultUri);
+
+      String path = String.format("/certificates/issuers?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(issuers.isEmpty());
+   }
+
+   public void getCertificateIssuer() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetcertificateissuer.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      IssuerBundle issuer = vaultApi.getCertificateIssuer(vaultUri, CERTIFICATE_ISSUER_NAME);
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(issuer);
+      assertTrue(!issuer.id().isEmpty());
+   }
+
+   public void getCertificateIssuerReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      IssuerBundle issuer = vaultApi.getCertificateIssuer(vaultUri, CERTIFICATE_ISSUER_NAME);
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(issuer);
+   }
+
+   public void updateCertificateIssuer() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatecertificateissuer.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      AdministrationDetails adminDetail = AdministrationDetails.create(
+              "adminguy@certsforme.com",
+              "Admin",
+              "Guy",
+              "867-5309"
+      );
+      List<AdministrationDetails> adminDetails = new ArrayList<AdministrationDetails>();
+      adminDetails.add(adminDetail);
+      OrganizationDetails orgDetails = OrganizationDetails.create(
+              adminDetails,
+              null
+      );
+      IssuerBundle issuer = vaultApi.updateCertificateIssuer(
+              vaultUri,
+              "globalsign01",
+              null,
+              IssuerCredentials.create("imauser", "CanHa5P455wuRd!"),
+              orgDetails,
+              "GlobalSign"
+      );
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatecertificateissuerrequestbody.json"));
+
+      assertNotNull(issuer);
+      assertTrue(!issuer.id().isEmpty());
+   }
+
+   public void deleteCertificateIssuer() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletecertificateissuer.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      IssuerBundle issuer = vaultApi.deleteCertificateIssuer(vaultUri, CERTIFICATE_ISSUER_NAME);
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(issuer);
+      assertTrue(!issuer.id().isEmpty());
+   }
+
+   public void deleteCertificateIssuerReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      IssuerBundle issuer = vaultApi.deleteCertificateIssuer(vaultUri, CERTIFICATE_ISSUER_NAME);
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(issuer);
+   }
+
+   public void getCertificateContacts() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetcertificatecontacts.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Contacts contacts = vaultApi.getCertificateContacts(vaultUri);
+
+      String path = String.format("/certificates/contacts?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(contacts);
+      assertTrue(!contacts.id().isEmpty());
+      assertTrue(contacts.contacts().size() > 0);
+   }
+
+   public void getCertificateContactsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      IssuerBundle issuer = null;
+      try {
+         issuer = vaultApi.getCertificateIssuer(vaultUri, CERTIFICATE_ISSUER_NAME);
+      } catch (ResourceNotFoundException rnf) {
+         assertNotNull(rnf);
+      }
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(issuer);
+   }
+
+   public void setCertificateContacts() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultsetcertificatecontacts.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Contact> contactsIn = new ArrayList<Contact>();
+      contactsIn.add(Contact.create("foo@bar.com", "Foo bar", "867-5309"));
+      Contacts contacts = vaultApi.setCertificateContacts(vaultUri, contactsIn);
+
+      String path = String.format("/certificates/contacts?%s", apiVersion);
+      assertSent(server, "PUT", path, stringFromResource("/vaultsetcertificatecontactsrequestbody.json"));
+
+      assertNotNull(contacts);
+      assertTrue(!contacts.id().isEmpty());
+      assertTrue(contacts.contacts().size() > 0);
+   }
+
+   public void deleteCertificateContacts() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletecertificatecontacts.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Contacts contacts = vaultApi.deleteCertificateContacts(vaultUri);
+
+      String path = String.format("/certificates/contacts?%s", apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(contacts);
+      assertTrue(!contacts.id().isEmpty());
+      assertTrue(contacts.contacts().size() > 0);
+   }
+
+   public void deleteCertificateContactsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Contacts contacts = vaultApi.deleteCertificateContacts(vaultUri);
+
+      String path = String.format("/certificates/contacts?%s", apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(contacts);
+   }
+
+   public void getCertificatePolicy() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetcertificatepolicy.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificatePolicy policy = vaultApi.getCertificatePolicy(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/policy?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(policy);
+      assertTrue(!policy.id().isEmpty());
+   }
+
+   public void getCertificatePolicyReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificatePolicy policy = vaultApi.getCertificatePolicy(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/policy?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(policy);
+   }
+
+   public void updateCertificatePolicy() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatecertificatepolicy.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificatePolicy policy = vaultApi.updateCertificatePolicy(
+              vaultUri,
+              CERTIFICATE_NAME,
+              null,
+              null,
+              KeyProperties.create(true, 3072, "RSA", false),
+              null,
+              null,
+              null
+      );
+
+      String path = String.format("/certificates/%s/policy?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatecertificatepolicyrequestbody.json"));
+
+      assertNotNull(policy);
+      assertTrue(!policy.id().isEmpty());
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
index f439315..78d5425 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
@@ -17,21 +17,42 @@
 package org.jclouds.azurecompute.arm.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
 import static org.jclouds.util.Predicates2.retry;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
-
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_SECRET_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_SECRET_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_KEY_DELETED_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_KEY_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_OPERATION_STATUS;
+
+import java.io.IOException;
 import java.net.URI;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Properties;
 import java.util.Random;
 
+import com.google.common.base.Charsets;
+import com.google.common.base.Throwables;
+import com.google.common.io.Resources;
 import org.jclouds.apis.BaseApiLiveTest;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.config.Tenant;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultPredicates.DeletedVaultStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultKeyPredicates.DeletedKeyStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultKeyPredicates.RecoverableKeyStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultSecretPredicates.DeletedSecretStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultSecretPredicates.RecoverableSecretStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultCertificatePredicates.CertificateOperationStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultCertificatePredicates.DeletedCertificateStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultCertificatePredicates.RecoverableCertificateStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.PublicIpAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
@@ -47,11 +68,11 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
+import com.google.inject.name.Names;
 import com.google.inject.Injector;
-import com.google.inject.Key;
 import com.google.inject.Module;
+import com.google.inject.Key;
 import com.google.inject.TypeLiteral;
-import com.google.inject.name.Names;
 
 public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi> {
 
@@ -64,12 +85,22 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
    protected Predicate<URI> resourceDeleted;
    protected PublicIpAvailablePredicateFactory publicIpAvailable;
    protected Predicate<Supplier<Provisionable>> resourceAvailable;
-   
+   protected DeletedVaultStatusPredicateFactory deletedVaultStatus;
+   protected DeletedKeyStatusPredicateFactory deletedKeyStatus;
+   protected RecoverableKeyStatusPredicateFactory recoverableKeyStatus;
+   protected DeletedSecretStatusPredicateFactory deletedSecretStatus;
+   protected RecoverableSecretStatusPredicateFactory recoverableSecretStatus;
+   protected DeletedCertificateStatusPredicateFactory deletedCertificateStatus;
+   protected RecoverableCertificateStatusPredicateFactory recoverableCertificateStatus;
+   protected CertificateOperationStatusPredicateFactory certificateOperationStatus;
+
+
    protected String resourceGroupName;
    
    protected String vaultResourceGroup;
    protected String vaultName;
    protected String vaultCertificateUrl;
+   protected String tenantId;
 
    public BaseAzureComputeApiLiveTest() {
       provider = "azurecompute-arm";
@@ -110,6 +141,16 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
       publicIpAvailable = injector.getInstance(PublicIpAvailablePredicateFactory.class);
       resourceAvailable = injector.getInstance(Key.get(new TypeLiteral<Predicate<Supplier<Provisionable>>>() {
       }));
+      deletedVaultStatus = injector.getInstance(Key.get(DeletedVaultStatusPredicateFactory.class, Names.named(VAULT_DELETE_STATUS)));
+      deletedKeyStatus = injector.getInstance(Key.get(DeletedKeyStatusPredicateFactory.class, Names.named(VAULT_KEY_DELETED_STATUS)));
+      recoverableKeyStatus = injector.getInstance(Key.get(RecoverableKeyStatusPredicateFactory.class, Names.named(VAULT_KEY_RECOVERABLE_STATUS)));
+      deletedSecretStatus = injector.getInstance(Key.get(DeletedSecretStatusPredicateFactory.class, Names.named(VAULT_SECRET_DELETE_STATUS)));
+      recoverableSecretStatus = injector.getInstance(Key.get(RecoverableSecretStatusPredicateFactory.class, Names.named(VAULT_SECRET_RECOVERABLE_STATUS)));
+      deletedCertificateStatus = injector.getInstance(Key.get(DeletedCertificateStatusPredicateFactory.class, Names.named(VAULT_CERTIFICATE_DELETE_STATUS)));
+      recoverableCertificateStatus = injector.getInstance(Key.get(RecoverableCertificateStatusPredicateFactory.class, Names.named(VAULT_CERTIFICATE_RECOVERABLE_STATUS)));
+      certificateOperationStatus = injector.getInstance(Key.get(CertificateOperationStatusPredicateFactory.class, Names.named(VAULT_CERTIFICATE_OPERATION_STATUS)));
+
+      tenantId = injector.getInstance(Key.get(String.class, Tenant.class));
       return injector.getInstance(AzureComputeApi.class);
    }
 
@@ -198,4 +239,11 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
       return subscriptionId;
    }
 
+   protected String stringFromResource(String resourceName) {
+      try {
+         return Resources.toString(getClass().getResource(resourceName), Charsets.UTF_8);
+      } catch (IOException e) {
+         throw Throwables.propagate(e);
+      }
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
index 9d5eab0..8a0efd4 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
@@ -26,6 +26,7 @@ import static org.testng.Assert.assertEquals;
 
 import java.io.IOException;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.Properties;
 import java.util.Set;
 
@@ -71,7 +72,7 @@ public class BaseAzureComputeApiMockTest {
    private final JsonParser parser = new JsonParser();
 
    @BeforeMethod
-   public void start() throws IOException {
+   public void start() throws IOException, URISyntaxException {
       server = new MockWebServer();
       server.play();
       
@@ -148,10 +149,19 @@ public class BaseAzureComputeApiMockTest {
                   "https://management.azure.com/subscriptions/SUBSCRIPTIONID/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1SVEVTVC1DRU5UUkFMVVMiLCJqb2JMb2NhdGlvbiI6ImNlbnRyYWx1cyJ9?api-version=2014-04-01");
    }
 
+   protected MockResponse response200WithHeader() {
+      return new MockResponse()
+              .setStatus("HTTP/1.1 200 O")
+              .addHeader("Location", "https://management.azure.com/subscriptions/SUBSCRIPTIONID/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1SVEVTVC1DRU5UUkFMVVMiLCJqb2JMb2NhdGlvbiI6ImNlbnRyYWx1cyJ9?api-version=2014-04-01");
+   }
+
    protected String stringFromResource(String resourceName) {
       try {
-         return Resources.toString(getClass().getResource(resourceName), Charsets.UTF_8).replace(DEFAULT_ENDPOINT,
-               url(""));
+         String rsrc = Resources.toString(getClass().getResource(resourceName), Charsets.UTF_8);
+         if (rsrc.contains(DEFAULT_ENDPOINT)) {
+            rsrc = rsrc.replace(DEFAULT_ENDPOINT, url(""));
+         }
+         return rsrc;
       } catch (IOException e) {
          throw Throwables.propagate(e);
       }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/getvault.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/getvault.json b/providers/azurecompute-arm/src/test/resources/getvault.json
new file mode 100644
index 0000000..53bee7d
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/getvault.json
@@ -0,0 +1,60 @@
+{
+  "id": "/subscriptions/012e832d-7b27-4c30-9f21-22cdd9159d12/resourceGroups/rg-vaultapilivetest-andrea/providers/Microsoft.KeyVault/vaults/vaultapilivetest-andrea",
+  "name": "vaultapilivetest-andrea",
+  "type": "Microsoft.KeyVault/vaults",
+  "location": "westeurope",
+  "tags": {},
+  "properties": {
+    "sku": {
+      "family": "A",
+      "name": "Standard"
+    },
+    "tenantId": "ba85e8cd-8c83-486e-a7e3-0d7666169d34",
+    "accessPolicies": [
+      {
+        "tenantId": "ba85e8cd-8c83-486e-a7e3-0d7666169d34",
+        "objectId": "b025a8c0-d7fa-42fd-8e62-d988a3f12791",
+        "permissions": {
+          "keys": [
+            "Get",
+            "List",
+            "Update",
+            "Create",
+            "Import",
+            "Delete",
+            "Recover",
+            "Backup",
+            "Restore"
+          ],
+          "secrets": [
+            "Get",
+            "List",
+            "Set",
+            "Delete",
+            "Recover",
+            "Backup",
+            "Restore"
+          ],
+          "certificates": [
+            "Get",
+            "List",
+            "Update",
+            "Create",
+            "Import",
+            "Delete",
+            "ManageContacts",
+            "ManageIssuers",
+            "GetIssuers",
+            "ListIssuers",
+            "SetIssuers",
+            "DeleteIssuers"
+          ]
+        }
+      }
+    ],
+    "enabledForDeployment": false,
+    "enabledForDiskEncryption": false,
+    "enabledForTemplateDeployment": false,
+    "vaultUri": "https://vaultapilivetest-andrea.vault.azure.net/"
+  }
+}


[48/50] [abbrv] jclouds git commit: JCLOUDS-1362: Proper password generation with custom constraints for each cloud

Posted by na...@apache.org.
JCLOUDS-1362: Proper password generation with custom constraints for each cloud


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

Branch: refs/heads/master
Commit: eebcc0017fbf7b1f1d0d2920cd8f891e1ec36e38
Parents: a2dee2f
Author: Ignasi Barrera <na...@apache.org>
Authored: Thu Jan 4 01:44:14 2018 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon Jan 8 08:48:37 2018 +0100

----------------------------------------------------------------------
 .../config/AzureComputeServiceContextModule.java    | 16 ++++++++++++++++
 .../strategy/CreateResourcesThenCreateNodes.java    |  9 ++++++---
 .../CreateResourcesThenCreateNodesTest.java         |  3 ++-
 3 files changed, 24 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/eebcc001/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
index de33fdf..0a81ecb 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
@@ -53,6 +53,7 @@ import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatementWithoutPub
 import org.jclouds.compute.options.TemplateOptions;
 import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
 import org.jclouds.net.domain.IpPermission;
+import org.jclouds.util.PasswordGenerator;
 
 import com.google.common.base.Function;
 import com.google.common.cache.CacheBuilder;
@@ -102,6 +103,21 @@ public class AzureComputeServiceContextModule extends
       bind(new TypeLiteral<SecurityGroupExtension>() {
       }).to(AzureComputeSecurityGroupExtension.class);
    }
+   
+   @Provides
+   @Singleton
+   protected PasswordGenerator.Config providePasswordGenerator() {
+      // Guest passwords must be between 6-72 characters long.
+      // Must contain an upper case character.
+      // Must contain a lower case character.
+      // Must contain a numeric digit.
+      // Must contain a special character. Control characters are not allowed.
+      return new PasswordGenerator()
+            .lower().min(2).max(10)
+            .upper().min(2).max(10)
+            .numbers().min(2).max(10)
+            .symbols().min(2).max(10);
+   }
 
    @Provides
    @Singleton

http://git-wip-us.apache.org/repos/asf/jclouds/blob/eebcc001/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
index e5d38fb..511d531 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
@@ -52,7 +52,7 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
 import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
 import org.jclouds.domain.Location;
 import org.jclouds.logging.Logger;
-import org.jclouds.util.Passwords;
+import org.jclouds.util.PasswordGenerator;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
@@ -84,6 +84,7 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
    private final String defaultVnetAddressPrefix;
    private final String defaultSubnetAddressPrefix;
    private final TemplateToAvailabilitySet templateToAvailabilitySet;
+   private final PasswordGenerator.Config passwordGenerator;
 
    @Inject
    protected CreateResourcesThenCreateNodes(
@@ -95,7 +96,8 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
          AzureComputeApi api, @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX) String defaultVnetAddressPrefix,
          @Named(DEFAULT_SUBNET_ADDRESS_PREFIX) String defaultSubnetAddressPrefix,
          LoadingCache<ResourceGroupAndNameAndIngressRules, String> securityGroupMap,
-         TemplateToAvailabilitySet templateToAvailabilitySet) {
+         TemplateToAvailabilitySet templateToAvailabilitySet,
+         PasswordGenerator.Config passwordGenerator) {
       super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
             customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
       this.api = api;
@@ -103,6 +105,7 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
       this.defaultVnetAddressPrefix = defaultVnetAddressPrefix;
       this.defaultSubnetAddressPrefix = defaultSubnetAddressPrefix;
       this.templateToAvailabilitySet = templateToAvailabilitySet;
+      this.passwordGenerator = passwordGenerator;
    }
 
    @Override
@@ -141,7 +144,7 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
       TemplateOptions options = template.getOptions();
       if (options.getLoginPassword() == null) {
          Optional<String> passwordOptional = template.getImage().getDefaultCredentials().getOptionalPassword();
-         options.overrideLoginPassword(passwordOptional.or(Passwords.generate()));
+         options.overrideLoginPassword(passwordOptional.or(passwordGenerator.generate()));
       }
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/eebcc001/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java
index 51a45af..45c56a3 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java
@@ -24,6 +24,7 @@ import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
 import org.jclouds.azurecompute.arm.domain.Subnet;
 import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
+import org.jclouds.util.PasswordGenerator;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableList;
@@ -101,7 +102,7 @@ public class CreateResourcesThenCreateNodesTest {
    }
 
    private static CreateResourcesThenCreateNodes strategy(AzureComputeApi api) {
-      return new CreateResourcesThenCreateNodes(null, null, null, null, null, api, null, null, null, null);
+      return new CreateResourcesThenCreateNodes(null, null, null, null, null, api, null, null, null, null, new PasswordGenerator().lower());
    }
 
    private static String netResource(String resource) {


[36/50] [abbrv] jclouds git commit: JCLOUDS-1342 : Azure-ARM Virtual Machine Scale Set Support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApi.java
new file mode 100644
index 0000000..f6a237f
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApi.java
@@ -0,0 +1,88 @@
+/*
+ * 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.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSet;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetProperties;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetSKU;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.azurecompute.arm.functions.URIParser;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+import java.io.Closeable;
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The Virtual Machine Scale Set API includes operations for managing the virtual machines in your subscription.
+ *
+ * @see <a href="https://docs.microsoft.com/en-us/rest/api/virtualmachinescalesets/">docs</a>
+ */
+@Path("/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/VirtualMachineScaleSets")
+@RequestFilters({OAuthFilter.class, ApiVersionFilter.class})
+@Consumes(MediaType.APPLICATION_JSON)
+public interface VirtualMachineScaleSetApi extends Closeable {
+
+   @Named("virtualmachinescaleset:list")
+   @GET
+   @SelectJson("value")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<VirtualMachineScaleSet> list();
+
+   @Named("virtualmachinescaleset:get")
+   @Path("/{name}")
+   @GET
+   @Fallback(NullOnNotFoundOr404.class)
+   VirtualMachineScaleSet get(@PathParam("name") String name);
+
+   @Named("virtualmachinescaleset:createOrUpdate")
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/{name}")
+   @PUT
+   VirtualMachineScaleSet createOrUpdate(@PathParam("name") String name,
+                                         @PayloadParam("location") String location,
+                                         @PayloadParam("sku") VirtualMachineScaleSetSKU sku,
+                                         @Nullable @PayloadParam("tags") Map<String, String> tags,
+                                         @PayloadParam("properties") VirtualMachineScaleSetProperties properties);
+
+   @Named("virtualmachinescaleset:delete")
+   @Path("/{name}")
+   @DELETE
+   @ResponseParser(URIParser.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   URI delete(@PathParam("name") String name);
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiLiveTest.java
new file mode 100644
index 0000000..d827d70
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiLiveTest.java
@@ -0,0 +1,297 @@
+/*
+ * 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.collect.ImmutableMap;
+import org.jclouds.azurecompute.arm.domain.DataDisk;
+import org.jclouds.azurecompute.arm.domain.Extension;
+import org.jclouds.azurecompute.arm.domain.ExtensionProfile;
+import org.jclouds.azurecompute.arm.domain.ExtensionProfileSettings;
+import org.jclouds.azurecompute.arm.domain.ExtensionProperties;
+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.ManagedDiskParameters;
+import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
+import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
+import org.jclouds.azurecompute.arm.domain.NetworkInterfaceConfiguration;
+import org.jclouds.azurecompute.arm.domain.NetworkInterfaceConfigurationProperties;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile;
+import org.jclouds.azurecompute.arm.domain.OSDisk;
+import org.jclouds.azurecompute.arm.domain.StorageProfile;
+import org.jclouds.azurecompute.arm.domain.Subnet;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSet;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetDNSSettings;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetIpConfiguration;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetIpConfigurationProperties;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetNetworkProfile;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetNetworkSecurityGroup;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetOSProfile;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetProperties;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetPublicIPAddressConfiguration;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetPublicIPAddressProperties;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetSKU;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetUpgradePolicy;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetVirtualMachineProfile;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+@Test(groups = "live", testName = "VirtualMachineScaleSetApiLiveTest")
+public class VirtualMachineScaleSetApiLiveTest extends BaseAzureComputeApiLiveTest {
+
+   private String subscriptionid;
+   private String vmssName;
+   private VirtualMachineScaleSetSKU SKU;
+   private String nicName;
+   private String virtualNetworkName;
+   private String subnetId;
+   private Subnet subnet;
+
+   @BeforeClass
+   @Override
+   public void setup() {
+      super.setup();
+      subscriptionid = getSubscriptionId();
+
+      createTestResourceGroup();  //BASE: Creates a random resource group using the properties location
+
+      virtualNetworkName = String.format("vn-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
+
+      // Subnets belong to a virtual network so that needs to be created first
+      assertNotNull(createDefaultVirtualNetwork(resourceGroupName, virtualNetworkName, "10.2.0.0/16", LOCATION));
+
+      //Subnet needs to be up & running before NIC can be created
+      String subnetName = String.format("s-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
+      this.subnet = createDefaultSubnet(resourceGroupName, subnetName, virtualNetworkName, "10.2.0.0/23");
+      assertNotNull(subnet);
+      assertNotNull(subnet.id());
+      this.subnetId = subnet.id();
+
+
+      vmssName = String.format("%3.24s", System.getProperty("user.name") + RAND + this.getClass().getSimpleName()).toLowerCase().substring(0, 15);
+   }
+
+   private VirtualMachineScaleSetApi api() {
+      return api.getVirtualMachineScaleSetApi(resourceGroupName);
+   }
+
+   @Test
+   public void testCreate() {
+      VirtualMachineScaleSet vmss = api().createOrUpdate(vmssName, LOCATIONDESCRIPTION, getSKU(),
+         Collections.<String, String>emptyMap(), getProperties());
+      assertTrue(!vmss.name().isEmpty());
+//      waitUntilReady(vmssName);
+   }
+
+   @Test(dependsOnMethods = "testCreate")
+   public void testList() throws InterruptedException {
+      final VirtualMachineScaleSetApi vmssAPI = api.getVirtualMachineScaleSetApi(resourceGroupName);
+      assertEquals(vmssAPI.list().size(), 1);
+   }
+
+   @Test(dependsOnMethods = "testList")
+   public void testGet()  {
+      final VirtualMachineScaleSetApi vmssAPI = api.getVirtualMachineScaleSetApi(resourceGroupName);
+      assertEquals(vmssAPI.get(vmssName).name(), vmssName);
+   }
+
+   @Test(dependsOnMethods = "testGet", alwaysRun = true)
+   public void testDelete() throws Exception {
+      final VirtualMachineScaleSetApi vmssAPI = api.getVirtualMachineScaleSetApi(resourceGroupName);
+      URI uri = vmssAPI.delete(vmssName);
+      assertResourceDeleted(uri);
+   }
+
+   protected void assertResourceDeleted(URI uri) {
+      if (uri != null) {
+         assertTrue(resourceDeleted.apply(uri),
+                 String.format("Resource %s was not terminated in the configured timeout", uri));
+      }
+   }
+
+
+   /**
+    * Create a standard SKU
+    *
+    * @return VirtualMachineScaleSetSKU
+    */
+   public VirtualMachineScaleSetSKU getSKU() {
+      return VirtualMachineScaleSetSKU.create("Standard_A1", "Standard", 10);
+   }
+
+   private VirtualMachineScaleSetUpgradePolicy getUpgradePolicy() {
+      return VirtualMachineScaleSetUpgradePolicy.create("Manual");
+   }
+
+   private List<DataDisk> getDataDisks() {
+      List<DataDisk> datadisks = new ArrayList<DataDisk>();
+
+      datadisks.add(DataDisk.create(null, "10", 1, null,
+         null, "FromImage",
+         "None", getManagedDiskParameters(),
+         null));
+
+      return datadisks;
+   }
+
+   private StorageProfile getStorageProfile() {
+      return StorageProfile.create(getWindowsImageReference(), getWindowsOSDisk(), getDataDisks());
+   }
+
+   private StorageProfile getWindowsStorageProfile_Default() {
+      return StorageProfile.create(getWindowsImageReference(), getWindowsOSDisk(), null);
+   }
+
+   private StorageProfile getLinuxStorageProfile_Default() {
+      return StorageProfile.create(getLinuxImageReference(), getLinuxOSDisk(), null);
+   }
+
+   private ManagedDiskParameters getManagedDiskParameters() {
+      return ManagedDiskParameters.create(null, "Standard_LRS");
+   }
+
+   private OSDisk getWindowsOSDisk() {
+      return OSDisk.create("Windows", null, null, null, "FromImage",
+         null, getManagedDiskParameters(), null);
+   }
+
+   private OSDisk getLinuxOSDisk() {
+      return OSDisk.create("Linux", null, null, null, "FromImage",
+         null, getManagedDiskParameters(), null);
+   }
+
+   private ImageReference getWindowsImageReference() {
+      return ImageReference.create(null, "Microsoft.Windows", "Windows2016",
+         "Enterprise", "latest");
+   }
+
+   private ImageReference getLinuxImageReference() {
+      return ImageReference.create(null, "Canonical", "UbuntuServer",
+         "16.04-LTS", "latest");
+   }
+
+   private VirtualMachineScaleSetOSProfile getOSProfile() {
+      VirtualMachineScaleSetOSProfile.LinuxConfiguration linuxConfiguration =
+         VirtualMachineScaleSetOSProfile.LinuxConfiguration.create(false, null);
+      VirtualMachineScaleSetOSProfile.WindowsConfiguration windowsConfiguration = null;
+
+      return VirtualMachineScaleSetOSProfile.create(vmssName, "jclouds", "jClouds1!",
+         linuxConfiguration, windowsConfiguration, null);
+   }
+
+
+   private VirtualMachineScaleSetNetworkProfile getNetworkProfile() {
+      List<NetworkProfile.NetworkInterface> networkInterfacesList = new ArrayList<NetworkProfile.NetworkInterface>();
+
+      NetworkInterfaceCard nic = createNetworkInterfaceCard(resourceGroupName, "jc-nic-" + RAND, LOCATION, "ipConfig-" + RAND);
+      assertNotNull(nic);
+      networkInterfacesList.add(NetworkProfile.NetworkInterface.create(nic.id(), NetworkProfile.NetworkInterface.NetworkInterfaceProperties.create(true)));
+
+      List<NetworkInterfaceConfiguration> networkInterfaceConfigurations = new ArrayList<NetworkInterfaceConfiguration>();
+      List<VirtualMachineScaleSetIpConfiguration> virtualMachineScaleSetIpConfigurations = new ArrayList<VirtualMachineScaleSetIpConfiguration>();
+
+
+      VirtualMachineScaleSetPublicIPAddressConfiguration publicIPAddressConfiguration =
+         VirtualMachineScaleSetPublicIPAddressConfiguration.create("pub1", VirtualMachineScaleSetPublicIPAddressProperties.create(15));
+
+
+      VirtualMachineScaleSetIpConfigurationProperties virtualMachineScaleSetIpConfigurationProperties =
+         VirtualMachineScaleSetIpConfigurationProperties.create(publicIPAddressConfiguration,
+            this.subnet, "IPv4", null,
+            null, null);
+
+      VirtualMachineScaleSetIpConfiguration virtualMachineScaleSetIpConfiguration =
+         VirtualMachineScaleSetIpConfiguration.create("ipconfig1", virtualMachineScaleSetIpConfigurationProperties);
+
+      virtualMachineScaleSetIpConfigurations.add(virtualMachineScaleSetIpConfiguration);
+
+      VirtualMachineScaleSetNetworkSecurityGroup networkSecurityGroup = null;
+
+      ArrayList<String> dnsList = new ArrayList<String>();
+      dnsList.add("8.8.8.8");
+      VirtualMachineScaleSetDNSSettings dnsSettings =  VirtualMachineScaleSetDNSSettings.create(dnsList);
+
+      NetworkInterfaceConfigurationProperties networkInterfaceConfigurationProperties =
+         NetworkInterfaceConfigurationProperties.create(true, false, networkSecurityGroup, dnsSettings, virtualMachineScaleSetIpConfigurations);
+      NetworkInterfaceConfiguration networkInterfaceConfiguration = NetworkInterfaceConfiguration.create("nicconfig1", networkInterfaceConfigurationProperties);
+      networkInterfaceConfigurations.add(networkInterfaceConfiguration);
+
+      return VirtualMachineScaleSetNetworkProfile.create(networkInterfaceConfigurations);
+   }
+
+
+   private ExtensionProfile getExtensionProfile() {
+      List<Extension> extensions = new ArrayList<Extension>();
+
+      List<String> uris = new ArrayList<String>();
+      uris.add("https://mystorage1.blob.core.windows.net/winvmextekfacnt/SampleCmd_1.cmd");
+      ExtensionProfileSettings extensionProfileSettings = ExtensionProfileSettings.create(uris, "SampleCmd_1.cmd");
+
+      Map<String, String> protectedSettings = new HashMap<String, String>();
+      protectedSettings.put("StorageAccountKey", "jclouds-accountkey");
+
+      ExtensionProperties extensionProperties = ExtensionProperties.create("Microsoft.compute", "CustomScriptExtension",
+         "1.1", false, extensionProfileSettings,
+         protectedSettings);
+
+      Extension extension = Extension.create("extensionName", extensionProperties);
+      extensions.add(extension);
+
+      return ExtensionProfile.create(extensions);
+   }
+
+
+   private VirtualMachineScaleSetVirtualMachineProfile getVirtualMachineProfile() {
+      return VirtualMachineScaleSetVirtualMachineProfile.create(getLinuxStorageProfile_Default(), getOSProfile(), getNetworkProfile(), getExtensionProfile());
+   }
+
+   public VirtualMachineScaleSetProperties getProperties() {
+
+      return VirtualMachineScaleSetProperties.create(null, null, getUpgradePolicy(), null, getVirtualMachineProfile());
+   }
+
+   private NetworkInterfaceCard createNetworkInterfaceCard(final String resourceGroupName, String networkInterfaceCardName, String locationName, String ipConfigurationName) {
+      //Create properties object
+      final NetworkInterfaceCardProperties networkInterfaceCardProperties = NetworkInterfaceCardProperties
+         .builder()
+         .ipConfigurations(
+            Arrays.asList(IpConfiguration.create(ipConfigurationName, null, null, null, IpConfigurationProperties
+               .create(null, null, "Dynamic", IdReference.create(subnetId), null, null, null)))).build();
+
+      final Map<String, String> tags = ImmutableMap.of("jclouds", "livetest");
+      return api.getNetworkInterfaceCardApi(resourceGroupName).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, tags);
+   }
+
+   public String getSubscriptionid() {
+      return subscriptionid;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiMockTest.java
new file mode 100644
index 0000000..e0420fa
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiMockTest.java
@@ -0,0 +1,453 @@
+/*
+ * 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.collect.ImmutableMap;
+import org.jclouds.azurecompute.arm.domain.DataDisk;
+import org.jclouds.azurecompute.arm.domain.Extension;
+import org.jclouds.azurecompute.arm.domain.ExtensionProfile;
+import org.jclouds.azurecompute.arm.domain.ExtensionProfileSettings;
+import org.jclouds.azurecompute.arm.domain.ExtensionProperties;
+import org.jclouds.azurecompute.arm.domain.IdReference;
+import org.jclouds.azurecompute.arm.domain.ImageReference;
+import org.jclouds.azurecompute.arm.domain.ManagedDiskParameters;
+import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
+import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
+import org.jclouds.azurecompute.arm.domain.NetworkInterfaceConfiguration;
+import org.jclouds.azurecompute.arm.domain.NetworkInterfaceConfigurationProperties;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile;
+import org.jclouds.azurecompute.arm.domain.OSDisk;
+import org.jclouds.azurecompute.arm.domain.Secrets;
+import org.jclouds.azurecompute.arm.domain.StorageProfile;
+import org.jclouds.azurecompute.arm.domain.Subnet;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSet;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetDNSSettings;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetIpConfiguration;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetIpConfigurationProperties;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetNetworkProfile;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetOSProfile;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetProperties;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetPublicIPAddressConfiguration;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetPublicIPAddressProperties;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetSKU;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetUpgradePolicy;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineScaleSetVirtualMachineProfile;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+
+@Test(groups = "unit", testName = "VirtualMachineScaleSetAPIMockTest", singleThreaded = true)
+public class VirtualMachineScaleSetApiMockTest extends BaseAzureComputeApiMockTest {
+
+   private final String resourcegroup = "myresourcegroup";
+   private final String vmssname = "jclouds-vmssname";
+
+   public void testGet() throws InterruptedException {
+      server.enqueue(jsonResponse("/virtualmachinescalesetget.json").setResponseCode(200));
+      final VirtualMachineScaleSetApi vmssAPI = api.getVirtualMachineScaleSetApi(resourcegroup);
+      assertEquals(vmssAPI.get(vmssname).name(), vmssname);
+      assertSent(server,
+              "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/" +
+                      "providers/Microsoft.Compute"
+            + "/VirtualMachineScaleSets/jclouds-vmssname?api-version=2017-03-30");
+   }
+
+   public void testGetWhen404() throws InterruptedException {
+      server.enqueue(jsonResponse("/virtualmachinescalesetgetwhen404.json").setResponseCode(404));
+      final VirtualMachineScaleSetApi vmssAPI = api.getVirtualMachineScaleSetApi(resourcegroup);
+      VirtualMachineScaleSet vmss = vmssAPI.get(vmssname + 1);
+      assertSent(server,
+              "GET",
+              "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers/" +
+                      "Microsoft.Compute/VirtualMachineScaleSets/" +
+                      vmssname + "1?api-version=2017-03-30");
+      assertNull(vmss);
+   }
+
+   public void testCreateOrUpdate() throws InterruptedException {
+      server.enqueue(
+              jsonResponse(
+                      "/virtualmachinescalesetresponsecreateorupdate.json").setResponseCode(200));
+      final VirtualMachineScaleSetApi vmssAPI = api.getVirtualMachineScaleSetApi(resourcegroup);
+      VirtualMachineScaleSet vmss = CreateOrUpdateVMSS(vmssAPI);
+
+      assertNotNull(vmss);
+      assertSent(server,
+              "PUT",
+              "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers/" +
+                      "Microsoft.Compute"
+                      + "/VirtualMachineScaleSets/" + vmssname + "?api-version=2017-03-30",
+              "{\n" +
+                      "  \"location\": \"eastus\",\n" +
+                      "  \"sku\": {\n" +
+                      "    \"name\": \"Standard_A1\",\n" +
+                      "    \"tier\": \"Standard\",\n" +
+                      "    \"capacity\": 10\n" +
+                      "  },\n" +
+                      "  \"properties\": {\n" +
+                      "    \"singlePlacementGroup\": true,\n" +
+                      "    \"overProvision\": true,\n" +
+                      "    \"upgradePolicy\": {\n" +
+                      "      \"mode\": \"Manual\"\n" +
+                      "    },\n" +
+                      "    \"virtualMachineProfile\": {\n" +
+                      "      \"storageProfile\": {\n" +
+                      "        \"imageReference\": {\n" +
+                      "          \"publisher\": \"Canonical\",\n" +
+                      "          \"offer\": \"UbuntuServer\",\n" +
+                      "          \"sku\": \"16.04-LTS\",\n" +
+                      "          \"version\": \"latest\"\n" +
+                      "        },\n" +
+                      "        \"osDisk\": {\n" +
+                      "          \"osType\": \"Windows\",\n" +
+                      "          \"createOption\": \"FromImage\",\n" +
+                      "          \"managedDisk\": {\n" +
+                      "            \"storageAccountType\": \"Standard_LRS\"\n" +
+                      "          }\n" +
+                      "        },\n" +
+                      "        \"dataDisks\": [{\n" +
+                      "          \"diskSizeGB\": \"10\",\n" +
+                      "          \"lun\": 1,\n" +
+                      "          \"createOption\": \"Unrecognized\",\n" +
+                      "          \"caching\": \"None\",\n" +
+                      "          \"managedDisk\": {\n" +
+                      "            \"storageAccountType\": \"Standard_LRS\"\n" +
+                      "          }\n" +
+                      "        }\n" +
+                      "        ]\n" +
+                      "      },\n" +
+                      "      \"osProfile\": {\n" +
+                      "        \"computerNamePrefix\": \"jclouds-vmssname\",\n" +
+                      "        \"adminUsername\": \"admin\",\n" +
+                      "        \"adminPassword\": \"password\",\n" +
+                      "        \"linuxConfiguration\": {\n" +
+                      "          \"disablePasswordAuthentication\": false\n" +
+                      "        },\n" +
+                      "        \"secrets\": []\n" +
+                      "      },\n" +
+                      "      \"networkProfile\": {\n" +
+                      "        \"networkInterfaceConfigurations\": [{\n" +
+                      "          \"name\": \"nicconfig1\",\n" +
+                      "          \"properties\": {\n" +
+                      "            \"primary\": true,\n" +
+                      "            \"enableAcceleratedNetworking\": false,\n" +
+                      "            \"dnsSettings\": {\n" +
+                      "              \"dnsServers\": [\"8.8.8.8\"]\n" +
+                      "            },\n" +
+                      "            \"ipConfigurations\": [{\n" +
+                      "              \"name\": \"ipconfig1\",\n" +
+                      "              \"properties\": {\n" +
+                      "                \"publicIPAddressConfiguration\": {\n" +
+                      "                  \"name\": \"pub1\",\n" +
+                      "                  \"properties\": {\n" +
+                      "                    \"idleTimeoutInMinutes\": 15\n" +
+                      "                  }\n" +
+                      "                },\n" +
+                      "                \"subnet\": {\n" +
+                      "                  \"name\": \"virtualNetworkName\",\n" +
+                      "                  \"id\": \"/subscriptions/xxxxx-xxxx-xxxx-xxxx-xxxxxx/resourceGroups/" +
+                      "jcloud-eastus/providers/Microsoft.Network/virtualNetworks/" +
+                      "jclouds-eastus-virtualNetworkName/subnets/jclouds-eastus-subnet\",\n" +
+                      "                  \"properties\": {}\n" +
+                      "                },\n" +
+                      "                \"privateIPAddressVersion\": \"IPv4\",\n" +
+                      "                \"loadBalancerBackendAddressPools\": [],\n" +
+                      "                \"loadBalancerInboundNatPools\": []\n" +
+                      "              }\n" +
+                      "            }\n" +
+                      "            ]\n" +
+                      "          }\n" +
+                      "        }\n" +
+                      "        ]\n" +
+                      "      },\n" +
+                      "      \"extensionProfile\": {\n" +
+                      "        \"extensions\": [{\n" +
+                      "          \"name\": \"extensionName\",\n" +
+                      "          \"properties\": {\n" +
+                      "            \"publisher\": \"Microsoft.compute\",\n" +
+                      "            \"type\": \"CustomScriptExtension\",\n" +
+                      "            \"typeHandlerVersion\": \"1.1\",\n" +
+                      "            \"autoUpgradeMinorVersion\": false,\n" +
+                      "            \"settings\": {\n" +
+                      "              \"fileUris\": [\"https://mystorage1.blob.core.windows.net/winvmextekfacnt/" +
+                      "SampleCmd_1.cmd\"],\n" +
+                      "              \"commandToExecute\": \"SampleCmd_1.cmd\"\n" +
+                      "            },\n" +
+                      "            \"protectedSettings\": {\n" +
+                      "              \"StorageAccountKey\": \"jclouds-accountkey\"\n" +
+                      "            }\n" +
+                      "          }\n" +
+                      "        }\n" +
+                      "        ]\n" +
+                      "      }\n" +
+                      "    }\n" +
+                      "  }\n" +
+                      "}\n"
+              );
+   }
+
+   private VirtualMachineScaleSet CreateOrUpdateVMSS(VirtualMachineScaleSetApi vmssAPI) {
+      return vmssAPI.createOrUpdate(
+              vmssname,
+              "eastus",
+              VirtualMachineScaleSetSKU.create(
+                      "Standard_A1",
+                      "Standard",
+                      10),
+              null,
+              VirtualMachineScaleSetProperties.create(
+                      true,
+                      true,
+                      VirtualMachineScaleSetUpgradePolicy.create("Manual"),
+                      null,
+                      VirtualMachineScaleSetVirtualMachineProfile.create(
+                              StorageProfile.create(
+                                      ImageReference.create(
+                                              null,
+                                              "Canonical",
+                                              "UbuntuServer",
+                                              "16.04-LTS",
+                                              "latest"),
+                                      OSDisk.create(
+                                              "Windows",
+                                              null,
+                                              null,
+                                              null,
+                                              "FromImage",
+                                              null,
+                                              ManagedDiskParameters.create(
+                                                      null,
+                                                      "Standard_LRS"),
+                                              null),
+                                      Arrays.asList(DataDisk.create(
+                                              null,
+                                              "10",
+                                              1,
+                                              null,
+                                              null,
+                                              "FromImage",
+                                              "None",
+                                              ManagedDiskParameters.create(
+                                                      null,
+                                                      "Standard_LRS"),
+                                              null))),
+                              VirtualMachineScaleSetOSProfile.create(
+                                      "jclouds-vmssname",
+                                      "admin",
+                                      "password",
+                                      VirtualMachineScaleSetOSProfile.LinuxConfiguration.create(
+                                              false,
+                                              null),
+                                      null,
+                                      new ArrayList<Secrets>()),
+                              getNetworkProfile(),
+                              getExtensionProfile()
+
+                      )
+              ));
+   }
+
+
+   private VirtualMachineScaleSetNetworkProfile getNetworkProfile() {
+      List<NetworkProfile.NetworkInterface> networkInterfacesList =
+              new ArrayList<NetworkProfile.NetworkInterface>();
+
+      NetworkInterfaceCard nic =
+              createNetworkInterfaceCard(
+                      "jc-nic-" + 123,
+                      "eastus");
+      networkInterfacesList.add(NetworkProfile.NetworkInterface.create(
+              nic.id(),
+              NetworkProfile.NetworkInterface.NetworkInterfaceProperties.create(true)));
+
+      List<NetworkInterfaceConfiguration> networkInterfaceConfigurations =
+              new ArrayList<NetworkInterfaceConfiguration>();
+      List<VirtualMachineScaleSetIpConfiguration> virtualMachineScaleSetIpConfigurations =
+              new ArrayList<VirtualMachineScaleSetIpConfiguration>();
+
+
+      VirtualMachineScaleSetPublicIPAddressConfiguration publicIPAddressConfiguration =
+              VirtualMachineScaleSetPublicIPAddressConfiguration.create(
+                      "pub1",
+                      VirtualMachineScaleSetPublicIPAddressProperties.create(15));
+
+
+      VirtualMachineScaleSetIpConfigurationProperties virtualMachineScaleSetIpConfigurationProperties =
+              VirtualMachineScaleSetIpConfigurationProperties.create(
+                      publicIPAddressConfiguration,
+                      createDefaultSubnet(
+                              "virtualNetworkName"
+                      ),
+                      "IPv4",
+                      null,
+                      null,
+                      null);
+
+      VirtualMachineScaleSetIpConfiguration virtualMachineScaleSetIpConfiguration =
+              VirtualMachineScaleSetIpConfiguration.create(
+                      "ipconfig1",
+                      virtualMachineScaleSetIpConfigurationProperties);
+
+      virtualMachineScaleSetIpConfigurations.add(virtualMachineScaleSetIpConfiguration);
+
+      ArrayList<String> dnsList = new ArrayList<String>();
+      dnsList.add("8.8.8.8");
+      VirtualMachineScaleSetDNSSettings dnsSettings =  VirtualMachineScaleSetDNSSettings.create(dnsList);
+
+      NetworkInterfaceConfigurationProperties networkInterfaceConfigurationProperties =
+              NetworkInterfaceConfigurationProperties.create(
+                      true,
+                      false,
+                      null,
+                      dnsSettings,
+                      virtualMachineScaleSetIpConfigurations);
+      NetworkInterfaceConfiguration networkInterfaceConfiguration =
+              NetworkInterfaceConfiguration.create(
+                      "nicconfig1",
+                      networkInterfaceConfigurationProperties);
+      networkInterfaceConfigurations.add(networkInterfaceConfiguration);
+
+      return VirtualMachineScaleSetNetworkProfile.create(networkInterfaceConfigurations);
+   }
+
+
+   private NetworkInterfaceCard createNetworkInterfaceCard(
+           String networkInterfaceCardName, String locationName) {
+      //Create properties object
+      NetworkInterfaceCardProperties networkInterfaceCardProperties =
+              NetworkInterfaceCardProperties.create(
+                      null,
+                      null,
+                      false,
+                      null,
+                      IdReference.create(
+                              "/subscriptions/xxxxx-xxxx-xxxx-xxxx-xxxxxx/resourceGroups/" +
+                                      "jcloud-eastus/providers/" +
+                                      "Microsoft.Network/virtualNetworks/" +
+                                      "jclouds-eastus-virtualNetworkName/subnets/" +
+                                      "jclouds-eastus-subnet")
+              );
+
+      Map<String, String> tags = ImmutableMap.of("jclouds", "livetest");
+      return NetworkInterfaceCard.create(
+              networkInterfaceCardName,
+              "",
+              null,
+              locationName,
+              networkInterfaceCardProperties, tags);
+   }
+
+   protected Subnet createDefaultSubnet(final String subnetName) {
+      Subnet.SubnetProperties properties = Subnet.SubnetProperties.create(
+              null,
+              null,
+              null);
+      return Subnet.create(
+              subnetName,
+              "/subscriptions/xxxxx-xxxx-xxxx-xxxx-xxxxxx/resourceGroups/jcloud-eastus/providers/" +
+                      "Microsoft.Network/virtualNetworks/jclouds-eastus-virtualNetworkName/subnets/" +
+                      "jclouds-eastus-subnet",
+              null,
+              properties);
+   }
+
+   private ExtensionProfile getExtensionProfile() {
+      List<Extension> extensions = new ArrayList<Extension>();
+
+      List<String> uris = new ArrayList<String>();
+      uris.add("https://mystorage1.blob.core.windows.net/winvmextekfacnt/SampleCmd_1.cmd");
+
+      Map<String, String> protectedSettings = new HashMap<String, String>();
+      protectedSettings.put("StorageAccountKey", "jclouds-accountkey");
+
+      Extension extension = Extension.create(
+              "extensionName",
+              ExtensionProperties.create(
+                      "Microsoft.compute",
+                      "CustomScriptExtension",
+                      "1.1",
+                      false,
+                      ExtensionProfileSettings.create(
+                              uris,
+                              "SampleCmd_1.cmd"),
+                      protectedSettings));
+      extensions.add(extension);
+
+      return ExtensionProfile.create(extensions);
+   }
+
+   public void testList() throws InterruptedException {
+      server.enqueue(jsonResponse("/virtualmachinescalesetlist.json").setResponseCode(200));
+      final VirtualMachineScaleSetApi vmssAPI = api.getVirtualMachineScaleSetApi(resourcegroup);
+      assertEquals(vmssAPI.list().size(), 1);
+      assertSent(server,
+              "GET",
+              "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers/" +
+                      "Microsoft.Compute"
+              + "/VirtualMachineScaleSets?api-version=2017-03-30");
+   }
+
+   public void testListWhen404() throws InterruptedException {
+      server.enqueue(
+              jsonResponse("/virtualmachinescalesetlistwhen404.json").setResponseCode(404));
+      final VirtualMachineScaleSetApi vmssAPI = api.getVirtualMachineScaleSetApi(
+              resourcegroup + "1");
+      List<VirtualMachineScaleSet> vmssList = vmssAPI.list();
+      assertSent(server,
+              "GET",
+              "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup1/providers/" +
+                      "Microsoft.Compute"
+              + "/VirtualMachineScaleSets?api-version=2017-03-30");
+      assertTrue(isEmpty(vmssList));
+   }
+
+
+   public void testDeleteWhen404() throws InterruptedException {
+      server.enqueue(jsonResponse("/virtualmachinescalesetlist.json").setResponseCode(404));
+      final VirtualMachineScaleSetApi vmssAPI = api.getVirtualMachineScaleSetApi(resourcegroup);
+      assertNull(vmssAPI.delete(vmssname));
+      assertSent(server,
+              "DELETE",
+              "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers/" +
+                      "Microsoft.Compute"
+              + "/VirtualMachineScaleSets/" + vmssname + "?api-version=2017-03-30");
+
+   }
+
+   public void testDelete() throws InterruptedException {
+      server.enqueue(response202WithHeader());
+      final VirtualMachineScaleSetApi vmssAPI = api.getVirtualMachineScaleSetApi(resourcegroup);
+      assertNotNull(vmssAPI.delete(vmssname));
+      assertSent(server,
+              "DELETE",
+              "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers/" +
+                      "Microsoft.Compute"
+              + "/VirtualMachineScaleSets/jclouds-vmssname?api-version=2017-03-30");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
index f704e5f..1a83407 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
@@ -75,6 +75,7 @@ public class BaseAzureComputeApiMockTest {
    
    protected Properties setupProperties() {
       Properties properties = new Properties();
+
       properties.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString());
       properties.put("oauth.endpoint", "https://login.microsoftonline.com/tenant-id/oauth2/token");
       return properties;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/test/resources/virtualmachine.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachine.json b/providers/azurecompute-arm/src/test/resources/virtualmachine.json
index 17d89b5..e3e8d6b 100644
--- a/providers/azurecompute-arm/src/test/resources/virtualmachine.json
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachine.json
@@ -36,7 +36,6 @@
             "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/osDisk",
             "storageAccountType": "Standard_LRS"
           },
-          "createOption":"Empty",
           "caching": "ReadWrite"
         }
       ]

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetget.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetget.json b/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetget.json
new file mode 100644
index 0000000..c99eb39
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetget.json
@@ -0,0 +1,64 @@
+{
+  "sku": {
+    "name": "Standard_A1",
+    "tier": "Standard",
+    "capacity": 4
+  },
+  "properties": {
+    "singlePlacementGroup": true,
+    "upgradePolicy": {
+      "mode": "Manual"
+    },
+    "virtualMachineProfile": {
+      "osProfile": {
+        "computerNamePrefix": "vmmsprefix",
+        "adminUsername": "jclouds",
+        "linuxConfiguration": {
+          "disablePasswordAuthentication": false
+        },
+        "secrets": []
+      },
+      "storageProfile": {
+        "osDisk": {
+          "createOption": "FromImage",
+          "caching": "None",
+          "managedDisk": {
+            "storageAccountType": "Standard_LRS"
+          }
+        },
+        "imageReference": {
+          "publisher": "Canonical",
+          "offer": "UbuntuServer",
+          "sku": "16.04-LTS",
+          "version": "latest"
+        }
+      },
+      "networkProfile": {"networkInterfaceConfigurations":[{"name":"nicconfig1","properties":{"primary":true,"enableAcceleratedNetworking":false,"dnsSettings":{"dnsServers":["8.8.8.8"]},"ipConfigurations":[{"name":"ipconfig1","properties":{"publicIPAddressConfiguration":{"name":"pub1","properties":{"idleTimeoutInMinutes":15}},"subnet":{"id":"/subscriptions/xxxxx-xxxx-xxxx-xxxx-xxxxxx/resourceGroups/jcloud-eastus/providers/Microsoft.Network/virtualNetworks/jclouds-eastus-virtualNetworkName/subnets/jclouds-eastus-subnet"},"privateIPAddressVersion":"IPv4"}}]}}]},
+      "extensionProfile": {
+        "extensions": [
+          {
+            "properties": {
+              "publisher": "Microsoft.compute",
+              "type": "CustomScriptExtension",
+              "typeHandlerVersion": "1.1",
+              "autoUpgradeMinorVersion": false,
+              "settings": {"fileUris":["https://mystorage1.blob.core.windows.net/winvmextekfacnt/SampleCmd_1.cmd"],"commandToExecute":"SampleCmd_1.cmd"}
+            },
+            "name": "extensionName"
+          }
+        ]
+      }
+    },
+    "provisioningState": "Creating",
+    "overprovision": true,
+    "uniqueId": "xxxxx-xxxx-xxxx-xxxx-xxxxxx"
+  },
+  "type": "Microsoft.Compute/virtualMachineScaleSets",
+  "location": "eastus",
+  "tags": {
+    "test": "test"
+  },
+  "id": "/subscriptions/xxxxx-xxxx-xxxx-xxxx-xxxxxx/resourceGroups/jcloud-eastus/providers/Microsoft.Compute/virtualMachineScaleSets/jclouds-vmssname",
+  "name": "jclouds-vmssname"
+}
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetgetwhen404.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetgetwhen404.json b/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetgetwhen404.json
new file mode 100644
index 0000000..b6fbeaa
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetgetwhen404.json
@@ -0,0 +1,6 @@
+{
+  "error": {
+    "code": "ResourceNotFound",
+    "message": "The Resource 'Microsoft.Compute/virtualMachineScaleSets/jclouds-vmssname1' under resource group 'jcloud-eastus' was not found."
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetlist.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetlist.json b/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetlist.json
new file mode 100644
index 0000000..b5bd063
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetlist.json
@@ -0,0 +1,93 @@
+{
+  "value": [{
+    "sku": {
+      "name": "Standard_A1",
+      "tier": "Standard",
+      "capacity": 4
+    },
+    "properties": {
+      "singlePlacementGroup": true,
+      "upgradePolicy": {
+        "mode": "Manual",
+        "automaticOSUpgrade": false
+      },
+      "virtualMachineProfile": {
+        "osProfile": {
+          "computerNamePrefix": "vmmsprefix",
+          "adminUsername": "jclouds",
+          "linuxConfiguration": {
+            "disablePasswordAuthentication": false
+          },
+          "secrets": []
+        },
+        "storageProfile": {
+          "osDisk": {
+            "createOption": "FromImage",
+            "caching": "None",
+            "managedDisk": {
+              "storageAccountType": "Standard_LRS"
+            }
+          },
+          "imageReference": {
+            "publisher": "Canonical",
+            "offer": "UbuntuServer",
+            "sku": "16.04-LTS",
+            "version": "latest"
+          }
+        },
+        "networkProfile": {
+          "networkInterfaceConfigurations": [{
+            "name": "nicconfig1",
+            "properties": {
+              "primary": true,
+              "enableAcceleratedNetworking": false,
+              "dnsSettings": {
+                "dnsServers": ["8.8.8.8"]
+              },
+              "ipConfigurations": [{
+                "name": "ipconfig1",
+                "properties": {
+                  "publicIPAddressConfiguration": {
+                    "name": "pub1",
+                    "properties": {
+                      "idleTimeoutInMinutes": 15
+                    }
+                  },
+                  "subnet": {
+                    "id": "/subscriptions/xxxxx-xxxx-xxxx-xxxx-xxxxxx/resourceGroups/jcloud-eastus/providers/Microsoft.Network/virtualNetworks/jclouds-eastus-virtualNetworkName/subnets/jclouds-eastus-subnet"
+                  },
+                  "privateIPAddressVersion": "IPv4"
+                }
+              }]
+            }
+          }]
+        },
+        "extensionProfile": {
+          "extensions": [{
+            "properties": {
+              "publisher": "Microsoft.compute",
+              "type": "CustomScriptExtension",
+              "typeHandlerVersion": "1.1",
+              "autoUpgradeMinorVersion": false,
+              "settings": {
+                "fileUris": ["https://mystorage1.blob.core.windows.net/winvmextekfacnt/SampleCmd_1.cmd"],
+                "commandToExecute": "SampleCmd_1.cmd"
+              }
+            },
+            "name": "extensionName"
+          }]
+        }
+      },
+      "provisioningState": "Failed",
+      "overprovision": true,
+      "uniqueId": "xxxxx-xxxx-xxxx-xxxx-xxxxxx"
+    },
+    "type": "Microsoft.Compute/virtualMachineScaleSets",
+    "location": "eastus",
+    "tags": {
+      "test": "test"
+    },
+    "id": "/subscriptions/xxxxx-xxxx-xxxx-xxxx-xxxxxx/resourceGroups/jcloud-eastus/providers/Microsoft.Compute/virtualMachineScaleSets/jclouds-vmssname",
+    "name": "jclouds-vmssname"
+  }]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetlistwhen404.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetlistwhen404.json b/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetlistwhen404.json
new file mode 100644
index 0000000..635083c
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetlistwhen404.json
@@ -0,0 +1,6 @@
+{
+  "error": {
+    "code": "ResourceGroupNotFound",
+    "message": "Resource group 'jcloud-eastus1' could not be found."
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7368d58a/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetresponsecreateorupdate.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetresponsecreateorupdate.json b/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetresponsecreateorupdate.json
new file mode 100644
index 0000000..20ecd71
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/virtualmachinescalesetresponsecreateorupdate.json
@@ -0,0 +1,103 @@
+{
+  "location": "eastus",
+  "sku": {
+    "name": "Standard_A1",
+    "tier": "Standard",
+    "capacity": 10
+  },
+  "properties": {
+    "singlePlacementGroup": true,
+    "overProvision": true,
+    "upgradePolicy": {
+      "mode": "Manual"
+    },
+    "virtualMachineProfile": {
+      "storageProfile": {
+        "imageReference": {
+          "publisher": "Canonical",
+          "offer": "UbuntuServer",
+          "sku": "16.04-LTS",
+          "version": "latest"
+        },
+        "osDisk": {
+          "osType": "Windows",
+          "createOption": "FromImage",
+          "managedDisk": {
+            "storageAccountType": "Standard_LRS"
+          }
+        },
+        "dataDisks": [{
+          "diskSizeGB": "10",
+          "lun": 1,
+          "createOption": "Unrecognized",
+          "caching": "None",
+          "managedDisk": {
+            "storageAccountType": "Standard_LRS"
+          }
+        }
+        ]
+      },
+      "osProfile": {
+        "computerNamePrefix": "jclouds-vmssname",
+        "adminUsername": "jclouds",
+        "adminPassword": "jClouds1!",
+        "linuxConfiguration": {
+          "disablePasswordAuthentication": "False"
+        },
+        "secrets": []
+      },
+      "networkProfile": {
+        "networkInterfaceConfigurations": [{
+          "name": "nicconfig1",
+          "properties": {
+            "primary": true,
+            "enableAcceleratedNetworking": false,
+            "dnsSettings": {
+              "dnsServers": ["8.8.8.8"]
+            },
+            "ipConfigurations": [{
+              "name": "ipconfig1",
+              "properties": {
+                "publicIPAddressConfiguration": {
+                  "name": "pub1",
+                  "properties": {
+                    "idleTimeoutInMinutes": 15
+                  }
+                },
+                "subnet": {
+                  "name": "virtualNetworkName",
+                  "id": "/subscriptions/xxxxx-xxxx-xxxx-xxxx-xxxxxx/resourceGroups/jcloud-eastus/providers/Microsoft.Network/virtualNetworks/jclouds-eastus-virtualNetworkName/subnets/jclouds-eastus-subnet",
+                  "properties": {}
+                },
+                "privateIPAddressVersion": "IPv4",
+                "loadBalancerBackendAddressPools": [],
+                "loadBalancerInboundNatPools": []
+              }
+            }
+            ]
+          }
+        }
+        ]
+      },
+      "extensionProfile": {
+        "extensions": [{
+          "name": "extensionName",
+          "properties": {
+            "publisher": "Microsoft.compute",
+            "type": "CustomScriptExtension",
+            "typeHandlerVersion": "1.1",
+            "autoUpgradeMinorVersion": false,
+            "settings": {
+              "fileUris": ["https://mystorage1.blob.core.windows.net/winvmextekfacnt/SampleCmd_1.cmd"],
+              "commandToExecute": "SampleCmd_1.cmd"
+            },
+            "protectedSettings": {
+              "StorageAccountKey": "jclouds-accountkey"
+            }
+          }
+        }
+        ]
+      }
+    }
+  }
+}


[25/50] [abbrv] jclouds git commit: Re-use the just added Passwords from jclouds-core

Posted by na...@apache.org.
Re-use the just added Passwords from jclouds-core


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

Branch: refs/heads/master
Commit: 7100e811b5a93b05274afee908847d33cbb6f33a
Parents: c705075
Author: Svetoslav Neykov <sv...@neykov.name>
Authored: Fri Jul 21 09:28:06 2017 +0300
Committer: Svetoslav Neykov <sv...@neykov.name>
Committed: Tue Aug 1 14:41:06 2017 +0300

----------------------------------------------------------------------
 .../CreateResourcesThenCreateNodes.java         |  2 +-
 .../azurecompute/arm/util/Passwords.java        | 32 --------------------
 2 files changed, 1 insertion(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/7100e811/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
index e1d346c..4c712d0 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
@@ -50,7 +50,7 @@ import org.jclouds.azurecompute.arm.domain.Subnet;
 import org.jclouds.azurecompute.arm.domain.Subnet.SubnetProperties;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork.AddressSpace;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork.VirtualNetworkProperties;
-import org.jclouds.azurecompute.arm.util.Passwords;
+import org.jclouds.util.Passwords;
 import org.jclouds.compute.config.CustomizationResponse;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.Template;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7100e811/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/Passwords.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/Passwords.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/Passwords.java
deleted file mode 100644
index 9bc189e..0000000
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/Passwords.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azurecompute.arm.util;
-
-import com.google.common.io.BaseEncoding;
-
-import java.util.Random;
-
-// Seems to be a common theme between providers, perhaps should be provided by core (see other 'Passwords' classes)
-public class Passwords {
-    private static final Random random = new Random();
-
-    public static String generate() {
-        final byte[] buffer = new byte[15];
-        random.nextBytes(buffer);
-        return BaseEncoding.base64Url().omitPadding().encode(buffer);
-    }
-}


[11/50] [abbrv] jclouds git commit: Properly honor the configured regions in all list methods (list nodes, images and security groups)

Posted by na...@apache.org.
Properly honor the configured regions in all list methods (list nodes, images and security groups)


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

Branch: refs/heads/master
Commit: 3d274239a1058e91cc61f74b91d6f0c0b0c298dd
Parents: 83c0a3c
Author: Ignasi Barrera <na...@apache.org>
Authored: Tue Apr 25 10:05:46 2017 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Apr 26 00:12:57 2017 +0200

----------------------------------------------------------------------
 .../arm/compute/AzureComputeServiceAdapter.java | 28 ++++++++-------
 .../AzureComputeSecurityGroupExtension.java     | 37 +++++++++++++-------
 2 files changed, 40 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/3d274239/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 2e9e0f6..73ecda9 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -220,8 +220,14 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    }
    
    private List<VMImage> listCustomImagesByResourceGroup(String resourceGroup) {
-      List<org.jclouds.azurecompute.arm.domain.Image> customImages = api.getVirtualMachineImageApi(resourceGroup).list();
-      return Lists.transform(customImages, customImagetoVmImage);
+      List<org.jclouds.azurecompute.arm.domain.Image> customImgs = api.getVirtualMachineImageApi(resourceGroup).list();
+      return ImmutableList.copyOf(transform(
+            filter(customImgs, new Predicate<org.jclouds.azurecompute.arm.domain.Image>() {
+               @Override
+               public boolean apply(org.jclouds.azurecompute.arm.domain.Image input) {
+                  return regionIds.get().contains(input.location());
+               }
+            }), customImagetoVmImage));
    }
 
    @Override
@@ -241,15 +247,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       }
 
       // We need to look for custom images in all resource groups
-      Iterable<ResourceGroup> resourceGroupsInLocation = filter(api.getResourceGroupApi().list(),
-            new Predicate<ResourceGroup>() {
-               @Override
-               public boolean apply(ResourceGroup input) {
-                  return availableLocationNames.contains(input.location());
-               }
-            });
-      
-      for (ResourceGroup resourceGroup : resourceGroupsInLocation) {
+      for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
          osImages.addAll(listCustomImagesByResourceGroup(resourceGroup.name()));
       }
 
@@ -345,7 +343,13 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    public Iterable<VirtualMachine> listNodes() {
       ImmutableList.Builder<VirtualMachine> nodes = builder();
       for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
-         nodes.addAll(api.getVirtualMachineApi(resourceGroup.name()).list());
+         List<VirtualMachine> vms = api.getVirtualMachineApi(resourceGroup.name()).list();
+         nodes.addAll(filter(vms, new Predicate<VirtualMachine>() {
+            @Override
+            public boolean apply(VirtualMachine input) {
+               return regionIds.get().contains(input.location());
+            }
+         }));
       }
       return nodes.build();
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3d274239/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
index eafb4f1..59608a4 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
@@ -23,7 +23,6 @@ import static com.google.common.collect.Iterables.any;
 import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.transform;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
-import static org.jclouds.compute.predicates.NodePredicates.locationId;
 
 import java.net.URI;
 import java.util.ArrayList;
@@ -55,6 +54,7 @@ import org.jclouds.compute.domain.SecurityGroupBuilder;
 import org.jclouds.compute.extensions.SecurityGroupExtension;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.domain.Location;
+import org.jclouds.location.Region;
 import org.jclouds.logging.Logger;
 import org.jclouds.net.domain.IpPermission;
 import org.jclouds.net.domain.IpProtocol;
@@ -62,6 +62,7 @@ import org.jclouds.net.domain.IpProtocol;
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
 import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
 import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Multimap;
@@ -77,43 +78,53 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
    private final SecurityGroupAvailablePredicateFactory securityGroupAvailable;
    private final Predicate<URI> resourceDeleted;
    private final LoadingCache<String, ResourceGroup> defaultResourceGroup;
+   private final Supplier<Set<String>> regionIds;
 
    @Inject
    AzureComputeSecurityGroupExtension(AzureComputeApi api,
          Function<NetworkSecurityGroup, SecurityGroup> groupConverter,
          SecurityGroupAvailablePredicateFactory securityRuleAvailable,
          @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
-         LoadingCache<String, ResourceGroup> defaultResourceGroup) {
+         LoadingCache<String, ResourceGroup> defaultResourceGroup,
+         @Region Supplier<Set<String>> regionIds) {
       this.api = api;
       this.securityGroupConverter = groupConverter;
       this.securityGroupAvailable = securityRuleAvailable;
       this.resourceDeleted = resourceDeleted;
       this.defaultResourceGroup = defaultResourceGroup;
+      this.regionIds = regionIds;
+   }
+
+   @Override
+   public Set<SecurityGroup> listSecurityGroupsInLocation(Location location) {
+      return securityGroupsInLocations(ImmutableSet.of(location.getId()));
    }
 
    @Override
    public Set<SecurityGroup> listSecurityGroups() {
-      ImmutableSet.Builder<SecurityGroup> securityGroups = ImmutableSet.builder();
+      return securityGroupsInLocations(regionIds.get());
+   }
+
+   private Set<SecurityGroup> securityGroupsInLocations(final Set<String> locations) {
+      List<SecurityGroup> securityGroups = new ArrayList<SecurityGroup>();
       for (ResourceGroup rg : api.getResourceGroupApi().list()) {
          securityGroups.addAll(securityGroupsInResourceGroup(rg.name()));
       }
-      return securityGroups.build();
+      
+      return ImmutableSet.copyOf(filter(securityGroups, new Predicate<SecurityGroup>() {
+         @Override
+         public boolean apply(SecurityGroup input) {
+            return locations.contains(input.getLocation().getId());
+         }
+      }));
    }
-   
+
    private Set<SecurityGroup> securityGroupsInResourceGroup(String resourceGroup) {
       List<NetworkSecurityGroup> networkGroups = api.getNetworkSecurityGroupApi(resourceGroup).list();
       return ImmutableSet.copyOf(transform(filter(networkGroups, notNull()), securityGroupConverter));
    }
 
    @Override
-   public Set<SecurityGroup> listSecurityGroupsInLocation(Location location) {
-      // Even though the resource groups are in a location, each security group
-      // can be in a different resource group, so we need to inspect all teh
-      // existing resource groups, and filter afterwards
-      return ImmutableSet.copyOf(filter(listSecurityGroups(), locationId(location.getId())));
-   }
-
-   @Override
    public Set<SecurityGroup> listSecurityGroupsForNode(String nodeId) {
       logger.debug(">> getting security groups for node %s...", nodeId);
 


[46/50] [abbrv] jclouds git commit: Add Azure KeyVault support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Certificate.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Certificate.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Certificate.java
new file mode 100644
index 0000000..65de40c
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Certificate.java
@@ -0,0 +1,638 @@
+/*
+ * 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.Map;
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+
+@AutoValue
+public abstract class Certificate {
+   @AutoValue
+   public abstract static class CertificateAttributes {
+      @Nullable
+      public abstract Integer created();
+
+      public abstract boolean enabled();
+
+      @Nullable
+      public abstract Integer expiry();
+
+      @Nullable
+      public abstract Integer notBefore();
+
+      @Nullable
+      public abstract String recoveryLevel();
+
+      @Nullable
+      public abstract Integer updated();
+
+      @SerializedNames({"created", "enabled", "exp", "nbf", "recoveryLevel", "updated"})
+      public static CertificateAttributes create(final Integer created,
+                                                 final boolean enabled,
+                                                 final Integer expiry,
+                                                 final Integer notBefore,
+                                                 final String recoveryLevel,
+                                                 final Integer updated) {
+         return new AutoValue_Certificate_CertificateAttributes(created, enabled, expiry, notBefore, recoveryLevel, updated);
+      }
+   }
+
+   @AutoValue
+   public abstract static class IssuerParameters {
+      @Nullable
+      public abstract String certType();
+
+      @Nullable
+      public abstract String name();
+
+      @SerializedNames({"cty", "name"})
+      public static IssuerParameters create(final String certType,
+                                            final String name) {
+         return new AutoValue_Certificate_IssuerParameters(certType, name);
+      }
+   }
+
+   @AutoValue
+   public abstract static class KeyProperties {
+      @Nullable
+      public abstract Boolean exportable();
+
+      @Nullable
+      public abstract Integer keySize();
+
+      @Nullable
+      public abstract String keyType();
+
+      @Nullable
+      public abstract Boolean reuseKey();
+
+      @SerializedNames({"exportable", "key_size", "kty", "reuse_key"})
+      public static KeyProperties create(final boolean exportable,
+                                         final Integer keySize,
+                                         final String keyType,
+                                         final boolean reuseKey) {
+         return new AutoValue_Certificate_KeyProperties(exportable, keySize, keyType, reuseKey);
+      }
+   }
+
+   @AutoValue
+   public abstract static class LifetimeActionTrigger {
+      @Nullable
+      public abstract Integer daysBeforeExpiry();
+
+      @Nullable
+      public abstract Integer lifetimePercentage();
+
+      @SerializedNames({"days_before_expiry", "lifetime_percentage"})
+      public static LifetimeActionTrigger create(final Integer daysBeforeExpiry,
+                                                 final Integer lifetimePercentage) {
+         return new AutoValue_Certificate_LifetimeActionTrigger(daysBeforeExpiry, lifetimePercentage);
+      }
+   }
+
+   @AutoValue
+   public abstract static class LifetimeActionAction {
+      public abstract String actionType();
+
+      @SerializedNames({"action_type"})
+      public static LifetimeActionAction create(final String actionType) {
+         return new AutoValue_Certificate_LifetimeActionAction(actionType);
+      }
+   }
+
+   @AutoValue
+   public abstract static class LifetimeAction {
+      public abstract LifetimeActionAction action();
+
+      public abstract LifetimeActionTrigger trigger();
+
+      @SerializedNames({"action", "trigger"})
+      public static LifetimeAction create(final LifetimeActionAction action,
+                                          final LifetimeActionTrigger trigger) {
+         return new AutoValue_Certificate_LifetimeAction(action, trigger);
+      }
+   }
+
+   @AutoValue
+   public abstract static class SecretProperties {
+      public abstract String contentType();
+
+      @SerializedNames({"contentType"})
+      public static SecretProperties create(final String contentType) {
+         return new AutoValue_Certificate_SecretProperties(contentType);
+      }
+   }
+
+   @AutoValue
+   public abstract static class SubjectAlternativeNames {
+      public abstract List<String> dnsNames();
+
+      public abstract List<String> emails();
+
+      public abstract List<String> upns();
+
+      @SerializedNames({"dns_names", "emails", "upns"})
+      public static SubjectAlternativeNames create(final List<String> dnsNames,
+                                                   final List<String> emails,
+                                                   final List<String> upns) {
+         return new AutoValue_Certificate_SubjectAlternativeNames(
+                 dnsNames != null ? ImmutableList.copyOf(dnsNames) : ImmutableList.<String> of(),
+                 emails != null ? ImmutableList.copyOf(emails) : ImmutableList.<String> of(),
+                 upns != null ? ImmutableList.copyOf(upns) : ImmutableList.<String> of()
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class X509CertificateProperties {
+      public abstract List<String> enhancedKeyUsage();
+
+      public abstract List<String> keyUsage();
+
+      @Nullable
+      public abstract SubjectAlternativeNames subjectAltNames();
+
+      @Nullable
+      public abstract String subject();
+
+      @Nullable
+      public abstract Integer validityMonths();
+
+      @SerializedNames({"ekus", "key_usage", "sans", "subject", "validity_months"})
+      public static X509CertificateProperties create(final List<String> enhancedKeyUsage,
+                                                     final List<String> keyUsage,
+                                                     final SubjectAlternativeNames subjectAltNames,
+                                                     final String subject,
+                                                     final Integer validityMonths) {
+         return new AutoValue_Certificate_X509CertificateProperties(
+                 enhancedKeyUsage != null ? ImmutableList.copyOf(enhancedKeyUsage) : ImmutableList.<String> of(),
+                 keyUsage != null ? ImmutableList.copyOf(keyUsage) : ImmutableList.<String> of(),
+                 subjectAltNames,
+                 subject,
+                 validityMonths
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class CertificatePolicy {
+      @Nullable
+      public abstract CertificateAttributes attributes();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract IssuerParameters issuer();
+
+      @Nullable
+      public abstract KeyProperties keyProps();
+
+      public abstract List<LifetimeAction> lifetimeActions();
+
+      @Nullable
+      public abstract SecretProperties secretProps();
+
+      @Nullable
+      public abstract X509CertificateProperties x509props();
+
+      @SerializedNames({"attributes", "id", "issuer", "key_props", "lifetime_actions", "secret_props", "x509_props"})
+      public static CertificatePolicy create(final CertificateAttributes attributes,
+                                             final String id,
+                                             final IssuerParameters issuer,
+                                             final KeyProperties keyProps,
+                                             final List<LifetimeAction> lifetimeActions,
+                                             final SecretProperties secretProperties,
+                                             final X509CertificateProperties x509Props) {
+         return new AutoValue_Certificate_CertificatePolicy(
+                 attributes,
+                 id,
+                 issuer,
+                 keyProps,
+                 lifetimeActions != null ? ImmutableList.copyOf(lifetimeActions) : ImmutableList.<LifetimeAction>of(),
+                 secretProperties,
+                 x509Props
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class CertificateError {
+      @Nullable
+      public abstract String code();
+
+      @Nullable
+      public abstract String message();
+
+      @SerializedNames({"code", "message"})
+      public static CertificateError create(final String code,
+                                            final String message) {
+         return new AutoValue_Certificate_CertificateError(code, message);
+      }
+   }
+
+   @AutoValue
+   public abstract static class CertificateOperation {
+      @Nullable
+      public abstract Boolean cancellationRequested();
+
+      @Nullable
+      public abstract String csr();
+
+      @Nullable
+      public abstract CertificateError error();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract IssuerParameters issuer();
+
+      @Nullable
+      public abstract String requestId();
+
+      @Nullable
+      public abstract String status();
+
+      @Nullable
+      public abstract String statusDetails();
+
+      @Nullable
+      public abstract String target();
+
+      @SerializedNames({"cancellation_requested", "csr", "error", "id", "issuer", "request_id", "status", "status_details", "target"})
+      public static CertificateOperation create(final boolean cancellationRequested,
+                                                final String csr,
+                                                final CertificateError error,
+                                                final String id,
+                                                final IssuerParameters issuer,
+                                                final String requestId,
+                                                final String status,
+                                                final String statusDetails,
+                                                final String target) {
+         return new AutoValue_Certificate_CertificateOperation(
+                 cancellationRequested,
+                 csr,
+                 error,
+                 id,
+                 issuer,
+                 requestId,
+                 status,
+                 statusDetails,
+                 target);
+      }
+   }
+
+   @AutoValue
+   public abstract static class CertificateBundle {
+      @Nullable
+      public abstract CertificateAttributes attributes();
+
+      @Nullable
+      public abstract String certificate();
+
+      @Nullable
+      public abstract String contentType();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String keyId();
+
+      @Nullable
+      public abstract CertificatePolicy policy();
+
+      @Nullable
+      public abstract String secretId();
+
+      @Nullable
+      public abstract Map<String, String> tags();
+
+      @Nullable
+      public abstract String thumbprint();
+
+      @SerializedNames({"attributes", "cer", "contentType", "id", "kid", "policy", "sid", "tags", "x5t"})
+      public static CertificateBundle create(final CertificateAttributes attributes,
+                                             final String certificate,
+                                             final String contentType,
+                                             final String id,
+                                             final String keyId,
+                                             final CertificatePolicy policy,
+                                             final String secretId,
+                                             final Map<String, String> tags,
+                                             final String thumbprint) {
+         return new AutoValue_Certificate_CertificateBundle(attributes,
+                 certificate,
+                 contentType,
+                 id,
+                 keyId,
+                 policy,
+                 secretId,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 thumbprint
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class CertificateIssuer {
+      public abstract String id();
+
+      public abstract String provider();
+
+      @SerializedNames({"id", "provider"})
+      public static CertificateIssuer create(final String id,
+                                             final String provider) {
+         return new AutoValue_Certificate_CertificateIssuer(id, provider);
+      }
+   }
+
+   @AutoValue
+   public abstract static class IssuerAttributes {
+      @Nullable
+      public abstract Integer created();
+
+      @Nullable
+      public abstract Boolean enabled();
+
+      @Nullable
+      public abstract Integer updated();
+
+      @SerializedNames({"created", "enabled", "updated"})
+      public static IssuerAttributes create(final Integer created,
+                                            final Boolean enabled,
+                                            final Integer updated) {
+         return new AutoValue_Certificate_IssuerAttributes(created, enabled, updated);
+      }
+   }
+
+   @AutoValue
+   public abstract static class IssuerCredentials {
+      @Nullable
+      public abstract String accountId();
+
+      @Nullable
+      public abstract String password();
+
+      @SerializedNames({"account_id", "pwd"})
+      public static IssuerCredentials create(final String accountId,
+                                             final String password) {
+         return new AutoValue_Certificate_IssuerCredentials(accountId, password);
+      }
+   }
+
+   @AutoValue
+   public abstract static class OrganizationDetails {
+      public abstract List<AdministrationDetails> adminDetails();
+
+      @Nullable
+      public abstract String id();
+
+      @SerializedNames({"admin_details", "id"})
+      public static OrganizationDetails create(final List<AdministrationDetails> adminDetails,
+                                               final String id) {
+         return new AutoValue_Certificate_OrganizationDetails(
+                 adminDetails != null ? ImmutableList.copyOf(adminDetails) : ImmutableList.<AdministrationDetails> of(),
+                 id
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class AdministrationDetails {
+      @Nullable
+      public abstract String email();
+
+      @Nullable
+      public abstract String firstName();
+
+      @Nullable
+      public abstract String lastName();
+
+      @Nullable
+      public abstract String phoneNumber();
+
+      @SerializedNames({"email", "first_name", "last_name", "phone"})
+      public static AdministrationDetails create(final String email,
+                                                 final String firstName,
+                                                 final String lastName,
+                                                 final String phoneNumber) {
+         return new AutoValue_Certificate_AdministrationDetails(email, firstName, lastName, phoneNumber);
+      }
+   }
+
+   @AutoValue
+   public abstract static class IssuerBundle {
+      @Nullable
+      public abstract IssuerAttributes attributes();
+
+      @Nullable
+      public abstract IssuerCredentials credentials();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract OrganizationDetails organizationDetails();
+
+      @Nullable
+      public abstract String provider();
+
+      @SerializedNames({"attributes", "credentials", "id", "org_details", "provider"})
+      public static IssuerBundle create(final IssuerAttributes attributes,
+                                        final IssuerCredentials credentials,
+                                        final String id,
+                                        final OrganizationDetails orgDetails,
+                                        final String provider) {
+         return new AutoValue_Certificate_IssuerBundle(attributes, credentials, id, orgDetails, provider);
+      }
+   }
+
+   @AutoValue
+   public abstract static class Contact {
+      @Nullable
+      public abstract String email();
+
+      @Nullable
+      public abstract String name();
+
+      @Nullable
+      public abstract String phone();
+
+      @SerializedNames({"email", "name", "phone"})
+      public static Contact create(final String email,
+                                   final String name,
+                                   final String phone) {
+         return new AutoValue_Certificate_Contact(email, name, phone);
+      }
+   }
+
+   @AutoValue
+   public abstract static class Contacts {
+      public abstract List<Contact> contacts();
+
+      @Nullable
+      public abstract String id();
+
+      @SerializedNames({"contacts", "id"})
+      public static Contacts create(final List<Contact> contacts,
+                                    final String id) {
+         return new AutoValue_Certificate_Contacts(
+                 contacts != null ? ImmutableList.copyOf(contacts) : ImmutableList.<Contact> of(),
+                 id
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class DeletedCertificateBundle {
+      @Nullable
+      public abstract CertificateAttributes attributes();
+
+      @Nullable
+      public abstract String bytes();
+
+      @Nullable
+      public abstract Integer deletedDate();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String keyId();
+
+      @Nullable
+      public abstract String recoveryId();
+
+      @Nullable
+      public abstract Integer scheduledPurgeDate();
+
+      @Nullable
+      public abstract String secredId();
+
+      @Nullable
+      public abstract Map<String, String> tags();
+
+      @Nullable
+      public abstract String thumbprint();
+
+      @SerializedNames({"attributes", "cer", "deletedDate", "id", "kid", "recoveryId", "scheduledPurgeDate", "sid", "tags", "x5t"})
+      public static DeletedCertificateBundle create(final CertificateAttributes attributes,
+                                                    final String bytes,
+                                                    final Integer deletedDate,
+                                                    final String id,
+                                                    final String keyId,
+                                                    final String recoveryId,
+                                                    final Integer scheduledPurgeDate,
+                                                    final String secretId,
+                                                    final Map<String, String> tags,
+                                                    final String thumbprint) {
+         return new AutoValue_Certificate_DeletedCertificateBundle(
+                 attributes,
+                 bytes,
+                 deletedDate,
+                 id,
+                 keyId,
+                 recoveryId,
+                 scheduledPurgeDate,
+                 secretId,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 thumbprint
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class DeletedCertificate {
+      @Nullable
+      public abstract CertificateAttributes attributes();
+
+      @Nullable
+      public abstract Integer deletedDate();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String recoveryId();
+
+      @Nullable
+      public abstract Integer scheduledPurgeDate();
+
+      @Nullable
+      public abstract Map<String, String> tags();
+
+      @Nullable
+      public abstract String thumbprint();
+
+      @SerializedNames({"attributes", "deletedDate", "id", "recoveryId", "scheduledPurgeDate", "tags", "x5t"})
+      public static DeletedCertificate create(final CertificateAttributes attributes,
+                                              final Integer deletedDate,
+                                              final String id,
+                                              final String recoveryId,
+                                              final Integer scheduledPurgeDate,
+                                              final Map<String, String> tags,
+                                              final String thumbprint) {
+         return new AutoValue_Certificate_DeletedCertificate(
+                 attributes,
+                 deletedDate,
+                 id,
+                 recoveryId,
+                 scheduledPurgeDate,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 thumbprint
+         );
+      }
+   }
+
+   @Nullable
+   public abstract CertificateAttributes attributes();
+
+   @Nullable
+   public abstract String id();
+
+   @Nullable
+   public abstract Map<String, String> tags();
+
+   @Nullable
+   public abstract String thumbprint();
+
+   @SerializedNames({"attributes", "id", "tags", "x5t"})
+   public static Certificate create(final CertificateAttributes attributes,
+                                    final String id,
+                                    final Map<String, String> tags,
+                                    final String thumbprint) {
+      return new AutoValue_Certificate(
+              attributes,
+              id,
+              tags != null ? ImmutableMap.copyOf(tags) : null,
+              thumbprint
+      );
+   }
+
+   Certificate() {
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Key.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Key.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Key.java
new file mode 100644
index 0000000..ed9b778
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Key.java
@@ -0,0 +1,229 @@
+/*
+ * 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.Map;
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Key {
+    @AutoValue
+    public abstract static class JsonWebKey {
+        @Nullable
+        public abstract String crv();
+
+        @Nullable
+        public abstract String d();
+
+        @Nullable
+        public abstract String dp();
+
+        @Nullable
+        public abstract String dq();
+
+        @Nullable
+        public abstract String e();
+
+        @Nullable
+        public abstract String k();
+
+        @Nullable
+        public abstract String keyHsm();
+
+        public abstract List<String> keyOps();
+
+        @Nullable
+        public abstract String kid();
+
+        @Nullable
+        public abstract String kty();
+
+        @Nullable
+        public abstract String n();
+
+        @Nullable
+        public abstract String p();
+
+        @Nullable
+        public abstract String q();
+
+        @Nullable
+        public abstract String qi();
+
+        @Nullable
+        public abstract String x();
+
+        @Nullable
+        public abstract String y();
+
+        @SerializedNames({"crv", "d", "dp", "dq", "e", "k", "key_hsm", "key_ops", "kid", "kty", "n", "p", "q", "qi", "x", "y"})
+        public static JsonWebKey create(final String crv, final String d, final String dp, final String dq,
+                                        final String e, final String k, final String keyHsm, final List<String> keyOps,
+                                        final String kid, final String kty, final String n, final String p,
+                                        final String q, final String qi, final String x, final String y) {
+            return new AutoValue_Key_JsonWebKey(
+                    crv, d, dp, dq, e, k, keyHsm,
+                    keyOps != null ? ImmutableList.copyOf(keyOps) : ImmutableList.<String> of(),
+                    kid, kty, n, p, q, qi, x, y);
+        }
+    }
+
+    @AutoValue
+    public abstract static class KeyAttributes {
+        @Nullable
+        public abstract Boolean enabled();
+
+        @Nullable
+        public abstract Integer created();
+
+        @Nullable
+        public abstract Integer expires();
+
+        @Nullable
+        public abstract Integer notBefore();
+
+        @Nullable
+        public abstract String recoveryLevel();
+
+        @Nullable
+        public abstract Integer updated();
+
+        @SerializedNames({"enabled", "created", "expires", "notBefore", "recoveryLevel", "updated"})
+        public static KeyAttributes create(final Boolean enabled,
+                                           final Integer created,
+                                           final Integer expires,
+                                           final Integer notBefore,
+                                           final String recoveryLevel,
+                                           final Integer updated) {
+            return new AutoValue_Key_KeyAttributes(enabled, created, expires, notBefore, recoveryLevel, updated);
+        }
+
+        KeyAttributes() {
+        }
+    }
+
+    @AutoValue
+    public abstract static class KeyBundle {
+        @Nullable
+        public abstract KeyAttributes attributes();
+
+        @Nullable
+        public abstract JsonWebKey key();
+
+        @Nullable
+        public abstract Boolean managed();
+
+        @Nullable
+        public abstract Map<String, String> tags();
+
+        @SerializedNames({"attributes", "key", "managed", "tags"})
+        public static KeyBundle create(final KeyAttributes attributes, final JsonWebKey key, final boolean managed, final Map<String, String> tags) {
+            return new AutoValue_Key_KeyBundle(
+                    attributes,
+                    key,
+                    managed,
+                    tags != null ? ImmutableMap.copyOf(tags) : null
+            );
+        }
+    }
+
+    @AutoValue
+    public abstract static class DeletedKeyBundle {
+        @Nullable
+        public abstract KeyAttributes attributes();
+
+        @Nullable
+        public abstract String deletedDate();
+
+        @Nullable
+        public abstract JsonWebKey key();
+
+        @Nullable
+        public abstract Boolean managed();
+
+        @Nullable
+        public abstract String recoveryId();
+
+        @Nullable
+        public abstract String scheduledPurgeDate();
+
+        @Nullable
+        public abstract Map<String, String> tags();
+
+        @SerializedNames({"attributes", "deletedDate", "key", "managed", "recoveryId", "scheduledPurgeDate", "tags"})
+        public static DeletedKeyBundle create(final KeyAttributes attributes, final String deletedDate, final JsonWebKey key, final boolean managed, final String recoveryId, final String scheduledPurgeDate, final Map<String, String> tags) {
+            return new AutoValue_Key_DeletedKeyBundle(
+                    attributes,
+                    deletedDate,
+                    key,
+                    managed,
+                    recoveryId,
+                    scheduledPurgeDate,
+                    tags != null ? ImmutableMap.copyOf(tags) : null
+
+            );
+        }
+    }
+
+    @AutoValue
+    public abstract static class KeyOperationResult {
+        @Nullable
+        public abstract String keyId();
+
+        @Nullable
+        public abstract String value();
+
+        @SerializedNames({"kid", "value"})
+        public static KeyOperationResult create(final String keyId, final String value) {
+            return new AutoValue_Key_KeyOperationResult(
+                    keyId,
+                    value
+            );
+        }
+    }
+
+    @Nullable
+    public abstract String kid();
+
+    public abstract KeyAttributes attributes();
+
+    @Nullable
+    public abstract Boolean managed();
+
+    @Nullable
+    public abstract Map<String, String> tags();
+
+    @SerializedNames({"kid", "attributes", "managed", "tags"})
+    public static Key create(final String kid, final KeyAttributes attributes, final boolean managed, final Map<String, String> tags) {
+        return new AutoValue_Key(
+                kid,
+                attributes,
+                managed,
+                tags != null ? ImmutableMap.copyOf(tags) : null
+        );
+    }
+
+    Key() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java
index 4c414e5..6af4406 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java
@@ -16,36 +16,25 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
-/**
- * SKU
- */
+import com.google.auto.value.AutoValue;
+
 @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();
+   @Nullable
+   public abstract String family();
+   
+   @SerializedNames({"location", "name", "id", "family"})
+   public static SKU create(final String location, final String name, final String id, final String family) {
 
-   @SerializedNames({"location", "name", "id"})
-   public static SKU create(final String location, final String name, final String id) {
-
-      return new AutoValue_SKU(location, name, id);
+      return new AutoValue_SKU(location, name, id, family);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secret.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secret.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secret.java
new file mode 100644
index 0000000..789a71c
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secret.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.domain;
+
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import java.util.Map;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Secret {
+
+   @AutoValue
+   public abstract static class SecretAttributes {
+      @Nullable
+      public abstract Boolean enabled();
+
+      @Nullable
+      public abstract Integer created();
+
+      @Nullable
+      public abstract Integer expires();
+
+      @Nullable
+      public abstract Integer notBefore();
+
+      @Nullable
+      public abstract String recoveryLevel();
+
+      @Nullable
+      public abstract Integer updated();
+
+      @SerializedNames({"enabled", "created", "expires", "notBefore", "recoveryLevel", "updated"})
+      public static SecretAttributes create(final Boolean enabled,
+                                            final Integer created,
+                                            final Integer expires,
+                                            final Integer notBefore,
+                                            final String recoveryLevel,
+                                            final Integer updated) {
+         return new AutoValue_Secret_SecretAttributes(enabled, created, expires, notBefore, recoveryLevel, updated);
+      }
+
+      SecretAttributes() {
+      }
+   }
+
+   @AutoValue
+   public abstract static class DeletedSecretBundle {
+      @Nullable
+      public abstract SecretAttributes attributes();
+
+      @Nullable
+      public abstract String contentType();
+
+      @Nullable
+      public abstract String deletedDate();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String kid();
+
+      @Nullable
+      public abstract Boolean managed();
+
+      @Nullable
+      public abstract String recoveryId();
+
+      @Nullable
+      public abstract String scheduledPurgeDate();
+
+      @Nullable
+      public abstract Map<String, String> tags();
+
+      @Nullable
+      public abstract String value();
+
+      @SerializedNames({"attributes", "contentType", "deletedDate", "id", "kid", "managed", "recoveryId", "scheduledPurgeDate", "tags", "value"})
+      public static DeletedSecretBundle create(final SecretAttributes attributes,
+                                               final String contentType,
+                                               final String deletedDate,
+                                               final String id,
+                                               final String kid,
+                                               final Boolean managed,
+                                               final String recoveryId,
+                                               final String scheduledPurgeDate,
+                                               final Map<String, String> tags,
+                                               String value) {
+         return new AutoValue_Secret_DeletedSecretBundle(
+                 attributes, contentType, deletedDate,
+                 id, kid, managed, recoveryId, scheduledPurgeDate,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 value);
+      }
+   }
+
+   @AutoValue
+   public abstract static class SecretBundle {
+      @Nullable
+      public abstract SecretAttributes attributes();
+
+      @Nullable
+      public abstract String contentType();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String kid();
+
+      @Nullable
+      public abstract Boolean managed();
+
+      @Nullable
+      public abstract Map<String, String> tags();
+
+      @Nullable
+      public abstract String value();
+
+      @SerializedNames({"attributes", "contentType", "id", "kid", "managed", "tags", "value"})
+      public static SecretBundle create(final SecretAttributes attributes,
+                                        final String contentType,
+                                        final String id,
+                                        final String kid,
+                                        final Boolean managed,
+                                        final Map<String, String> tags,
+                                        String value) {
+         return new AutoValue_Secret_SecretBundle(
+                 attributes, contentType, id,
+                 kid, managed,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 value);
+      }
+   }
+
+   @Nullable
+   public abstract SecretAttributes attributes();
+
+   @Nullable
+   public abstract String contentType();
+
+   @Nullable
+   public abstract String id();
+
+   @Nullable
+   public abstract Boolean managed();
+
+   @Nullable
+   public abstract Map<String, String> tags();
+
+   @SerializedNames({"attributes", "contentType", "id", "managed", "tags"})
+   public static Secret create(final SecretAttributes attributes,
+                               final String contentType,
+                               final String id,
+                               final Boolean managed,
+                               final Map<String, String> tags) {
+      return new AutoValue_Secret(
+              attributes,
+              contentType,
+              id,
+              managed,
+              tags != null ? ImmutableMap.copyOf(tags) : null
+      );
+   }
+
+   Secret() {
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Vault.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Vault.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Vault.java
new file mode 100644
index 0000000..3683df6
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Vault.java
@@ -0,0 +1,112 @@
+/*
+ * 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.Date;
+import java.util.Map;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
+
+@AutoValue
+public abstract class Vault {
+
+   @AutoValue
+   public abstract static class DeletedVault {
+      @Nullable public abstract String id();
+      @Nullable public abstract String name();
+      @Nullable public abstract String type();
+      @Nullable public abstract DeletedVaultProperties properties();
+
+      @SerializedNames({"id", "name", "type", "properties"})
+      public static DeletedVault create(final String id, final String name,
+                                        final String type, final DeletedVaultProperties properties) {
+         return new AutoValue_Vault_DeletedVault(id, name, type, properties);
+      }
+   }
+
+   @AutoValue
+   public abstract static class DeletedVaultProperties {
+      @Nullable public abstract Date deletionDate();
+      @Nullable public abstract String location();
+      @Nullable public abstract Date scheduledPurgeDate();
+      @Nullable public abstract Map<String, String> tags();
+      @Nullable public abstract String vaultId();
+
+      @SerializedNames({"deletionDate", "location", "scheduledPurgeDate", "tags", "vaultId"})
+      public static DeletedVaultProperties create (final Date deletionDate, final String location,
+                                           final Date scheduledPurgeDate, final Map<String, String> tags,
+                                           final String vaultId) {
+         return new AutoValue_Vault_DeletedVaultProperties(
+                 deletionDate,
+                 location,
+                 scheduledPurgeDate,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 vaultId
+         );
+      }
+   }
+
+   @Nullable public abstract String id();
+   @Nullable public abstract String type();
+   public abstract String location();
+   @Nullable public abstract Map<String, String> tags();
+   @Nullable public abstract String name();
+   public abstract VaultProperties properties();
+
+   @SerializedNames({"id", "name", "type", "location", "properties", "tags"})
+   public static Vault create(final String id, final String name, final String type,
+                              final String location,
+                              final VaultProperties properties, final Map<String, String> tags) {
+      return builder()
+              .id(id)
+              .name(name)
+              .type(type)
+              .location(location)
+              .properties(properties)
+              .tags(tags != null ? ImmutableMap.copyOf(tags) : null)
+              .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_Vault.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder name(String name);
+      public abstract Builder type(String type);
+      public abstract Builder location(String location);
+      public abstract Builder properties(VaultProperties properties);
+      public abstract Builder tags(Map<String, String> tags);
+
+      abstract Map<String, String> tags();
+      abstract Vault autoBuild();
+
+      public Vault build() {
+         tags(tags() != null ? ImmutableMap.copyOf(tags()) : null);
+         return autoBuild();
+      }
+      
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultProperties.java
new file mode 100644
index 0000000..5e97cf3
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultProperties.java
@@ -0,0 +1,131 @@
+/*
+ * 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.net.URI;
+import java.util.List;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+
+@AutoValue
+public abstract class VaultProperties {
+
+   @AutoValue
+   public abstract static class Permissions {
+
+      public abstract List<String> certificates();
+      public abstract List<String> keys();
+      public abstract List<String> secrets();
+      public abstract List<String> storage();
+
+      @SerializedNames({ "certificates", "keys", "secrets", "storage"})
+      public static Permissions create(final List<String> certificates, final List<String> keys, final List<String> secrets, final List<String> storage) {
+         return new AutoValue_VaultProperties_Permissions(
+                 certificates != null ? ImmutableList.copyOf(certificates) : ImmutableList.<String> of(),
+                 keys != null ? ImmutableList.copyOf(keys) : ImmutableList.<String> of(),
+                 secrets != null ? ImmutableList.copyOf(secrets) : ImmutableList.<String> of(),
+                 storage != null ? ImmutableList.copyOf(storage) : ImmutableList.<String> of()
+         );
+      }
+
+      Permissions() {
+
+      }
+   }
+   
+   @AutoValue
+   public abstract static class AccessPolicyEntry {
+
+      @Nullable public abstract String applicationId();
+      public abstract String objectId();
+      public abstract String tenantId();
+      @Nullable public abstract Permissions permissions();
+
+      @SerializedNames({"applicationId", "objectId", "tenantId", "permissions"})
+      public static AccessPolicyEntry create(final String applicationId, final String objectId, final String tenantId, final Permissions permissions) {
+         return new AutoValue_VaultProperties_AccessPolicyEntry(applicationId, objectId, tenantId, permissions);
+      }
+
+      AccessPolicyEntry() {
+
+      }
+   }
+   
+   @Nullable
+   public abstract String tenantId();
+   @Nullable
+   public abstract URI vaultUri();
+   @Nullable
+   public abstract Boolean enabledForDeployment();
+   @Nullable
+   public abstract Boolean enabledForTemplateDeployment();
+   @Nullable
+   public abstract Boolean enableSoftDelete();
+   @Nullable
+   public abstract String createMode();
+   @Nullable
+   public abstract SKU sku();
+   @Nullable
+   public abstract List<AccessPolicyEntry> accessPolicies();
+
+   @SerializedNames({"tenantId", "vaultUri", "enabledForDeployment", "enabledForTemplateDeployment", "enableSoftDelete", "createMode", "sku", "accessPolicies" })
+   public static VaultProperties create(final String tenantId, final URI vaultUri, final Boolean enabledForDeployment, final Boolean enabledForTemplateDeployment, final Boolean enableSoftDelete, final String createMode,
+                                        final SKU sku, final List<AccessPolicyEntry> accessPolicies) {
+      return builder()
+              .tenantId(tenantId)
+              .vaultUri(vaultUri)
+              .enabledForDeployment(enabledForDeployment)
+              .enabledForTemplateDeployment(enabledForTemplateDeployment)
+              .enableSoftDelete(enableSoftDelete)
+              .createMode(createMode)
+              .sku(sku)
+              .accessPolicies(accessPolicies)
+              .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_VaultProperties.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder tenantId(String tenantId);
+      public abstract Builder vaultUri(URI vaultUri);
+      public abstract Builder enabledForDeployment(Boolean enabledForDeployment);
+      public abstract Builder enabledForTemplateDeployment(Boolean enabledForTemplateDeployment);
+      public abstract Builder enableSoftDelete(Boolean enableSoftDelete);
+      public abstract Builder createMode(String createMode);
+      public abstract Builder sku(SKU sku);
+      public abstract Builder accessPolicies(List<AccessPolicyEntry> accessPolicies);
+      
+      abstract List<AccessPolicyEntry> accessPolicies();
+
+      abstract VaultProperties autoBuild();
+
+      public VaultProperties build() {
+         return accessPolicies(accessPolicies() != null ? ImmutableList.copyOf(accessPolicies()) : ImmutableList.<AccessPolicyEntry>of())
+                 .autoBuild();
+      }
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VaultApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VaultApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VaultApi.java
new file mode 100644
index 0000000..5ae39ba
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VaultApi.java
@@ -0,0 +1,635 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import com.google.common.base.Function;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.azurecompute.arm.config.OAuthResource;
+import org.jclouds.azurecompute.arm.domain.Certificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateAttributes;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateIssuer;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateOperation;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificatePolicy;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contact;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contacts;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerAttributes;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerCredentials;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerParameters;
+import org.jclouds.azurecompute.arm.domain.Certificate.KeyProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.LifetimeAction;
+import org.jclouds.azurecompute.arm.domain.Certificate.OrganizationDetails;
+import org.jclouds.azurecompute.arm.domain.Certificate.SecretProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.X509CertificateProperties;
+import org.jclouds.azurecompute.arm.domain.Key;
+import org.jclouds.azurecompute.arm.domain.Key.DeletedKeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.JsonWebKey;
+import org.jclouds.azurecompute.arm.domain.Key.KeyAttributes;
+import org.jclouds.azurecompute.arm.domain.Key.KeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.KeyOperationResult;
+import org.jclouds.azurecompute.arm.domain.Secret;
+import org.jclouds.azurecompute.arm.domain.Secret.DeletedSecretBundle;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretAttributes;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretBundle;
+import org.jclouds.azurecompute.arm.domain.Vault;
+import org.jclouds.azurecompute.arm.domain.Vault.DeletedVault;
+import org.jclouds.azurecompute.arm.domain.VaultProperties;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.binders.BindToJsonPayload;
+import org.jclouds.rest.annotations.ParamParser;
+
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
+@Consumes(MediaType.APPLICATION_JSON)
+public interface VaultApi {
+   static class PrependSlashOrEmptyString implements Function<Object, String> {
+      public String apply(Object from) {
+         if ((from == null) || (from.toString().length() == 0)) {
+            return "";
+         } else {
+            return "/" + from.toString();
+         }
+      }
+   }
+
+   // Vault operations
+   @Named("vault:list")
+   @SelectJson("value")
+   @GET
+   @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.KeyVault/vaults")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Vault> listVaults();
+
+   @Named("vault:create_or_update")
+   @PUT
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.KeyVault/vaults/{vaultName}")
+   Vault createOrUpdateVault(@PathParam("vaultName") String vaultName, @PayloadParam("location") String location,
+         @PayloadParam("properties") VaultProperties properties, @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("vault:get")
+   @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.KeyVault/vaults/{vaultName}")
+   @GET
+   @Fallback(NullOnNotFoundOr404.class)
+   Vault getVault(@PathParam("vaultName") String vaultName);
+
+   @Named("vault:delete")
+   @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.KeyVault/vaults/{vaultName}")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean deleteVault(@PathParam("vaultName") String vaultName);
+
+   @Named("vault:list_deleted_vaults")
+   @Path("/providers/Microsoft.KeyVault/deletedVaults")
+   @GET
+   @SelectJson("value")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<DeletedVault> listDeletedVaults();
+
+   @Named("vault:get_deleted")
+   @GET
+   @Path("/providers/Microsoft.KeyVault/locations/{location}/deletedVaults/{vaultName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   DeletedVault getDeletedVault(@PathParam("location") String location, @PathParam("vaultName") String vaultName);
+
+   @Named("vault:purge")
+   @POST
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Path("/providers/Microsoft.KeyVault/locations/{location}/deletedVaults/{vaultName}/purge")
+   boolean purgeVault(@PathParam("location") String location, @PathParam("vaultName") String vaultName);
+
+   // Key operations
+   @Named("key:list")
+   @SelectJson("value")
+   @GET
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @Path("/keys")
+   @OAuthResource("https://vault.azure.net")
+   List<Key> listKeys(@EndpointParam URI keyVaultUri);
+
+   @Named("key:create")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/keys/{keyName}/create")
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle createKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName,
+         @Nullable @PayloadParam("attributes") KeyAttributes attributes,
+         @Nullable @PayloadParam("crv") String curveName, @Nullable @PayloadParam("key_ops") List<String> keyOps,
+         @PayloadParam("key_size") int keySize, @PayloadParam("kty") String keyType,
+         @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("key:import")
+   @PUT
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/keys/{keyName}")
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle importKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName,
+         @PayloadParam("Hsm") boolean hsm, @Nullable @PayloadParam("attributes") KeyAttributes attributes,
+         @Nullable @PayloadParam("key") JsonWebKey key, @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("key:get")
+   @GET
+   @Path("/keys/{keyName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle getKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:delete")
+   @DELETE
+   @Path("/keys/{keyName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedKeyBundle deleteKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:get_versions")
+   @GET
+   @SelectJson("value")
+   @Path("/keys/{keyName}/versions")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<Key> getKeyVersions(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:update")
+   @PATCH
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/keys/{keyName}{keyVersion}")
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle updateKey(@EndpointParam URI vaultBaseUrl,
+                       @PathParam("keyName") String keyName,
+                       @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                       @Nullable @PayloadParam("attributes") KeyAttributes attributes,
+                       @Nullable @PayloadParam("key_ops") List<String> keyOps,
+                       @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("key:backup")
+   @POST
+   @SelectJson("value")
+   @Path("/keys/{keyName}/backup")
+   @OAuthResource("https://vault.azure.net")
+   String backupKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:restore")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/keys/restore")
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle restoreKey(@EndpointParam URI vaultBaseUrl, @PayloadParam("value") String keyInfo);
+
+   // Soft-delete key operations
+   @Named("key:list_deleted")
+   @GET
+   @SelectJson("value")
+   @Path("/deletedkeys")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<DeletedKeyBundle> listDeletedKeys(@EndpointParam URI vaultBaseUrl);
+
+   @Named("key:get_deleted")
+   @GET
+   @Path("/deletedkeys/{keyName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedKeyBundle getDeletedKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:recover_deleted")
+   @POST
+   @Path("/deletedkeys/{keyName}/recover")
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle recoverDeletedKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:purge_deleted")
+   @DELETE
+   @Path("/deletedkeys/{keyName}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   boolean purgeDeletedKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   // Key cryptographic operations
+   @Named("key:crypto_encrypt")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/encrypt")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyOperationResult encrypt(@EndpointParam URI vaultBaseUrl,
+                              @PathParam("keyName") String keyName,
+                              @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                              @PayloadParam("alg") String algorithm,
+                              @PayloadParam("value") String value);
+
+   @Named("key:crypto_decrypt")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/decrypt")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyOperationResult decrypt(@EndpointParam URI vaultBaseUrl,
+                              @PathParam("keyName") String keyName,
+                              @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                              @PayloadParam("alg") String algorithm,
+                              @PayloadParam("value") String value);
+
+   @Named("key:crypto_sign")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/sign")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyOperationResult sign(@EndpointParam URI vaultBaseUrl,
+                           @PathParam("keyName") String keyName,
+                           @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                           @PayloadParam("alg") String algorithm,
+                           @PayloadParam("value") String value);
+
+   @Named("key:crypto_verify")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/verify")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   boolean verify(@EndpointParam URI vaultBaseUrl,
+                  @PathParam("keyName") String keyName,
+                  @Nullable @PathParam("keyVersion")  @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                  @PayloadParam("alg") String algorithm,
+                  @PayloadParam("digest") String digest,
+                  @PayloadParam("value") String value);
+
+   @Named("key:crypto_wrap")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/wrapkey")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyOperationResult wrap(@EndpointParam URI vaultBaseUrl,
+                           @PathParam("keyName") String keyName,
+                           @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                           @PayloadParam("alg") String algorithm,
+                           @PayloadParam("value") String value);
+
+   @Named("key:crypto_unwrap")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/unwrapkey")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyOperationResult unwrap(@EndpointParam URI vaultBaseUrl,
+                             @PathParam("keyName") String keyName,
+                             @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                             @PayloadParam("alg") String algorithm,
+                             @PayloadParam("value") String value);
+
+   // Secret operations
+   @Named("secret:list")
+   @SelectJson("value")
+   @GET
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @Path("/secrets")
+   @OAuthResource("https://vault.azure.net")
+   List<Secret> listSecrets(@EndpointParam URI keyVaultUri);
+
+   @Named("secret:set")
+   @PUT
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/secrets/{secretName}")
+   @OAuthResource("https://vault.azure.net")
+   SecretBundle setSecret(@EndpointParam URI keyVaultUri, @PathParam("secretName") String secretName,
+         @Nullable @PayloadParam("attributes") SecretAttributes attributes,
+         @Nullable @PayloadParam("contentType") String contentType,
+         @Nullable @PayloadParam("tags") Map<String, String> tags, @PayloadParam("value") String value);
+
+   @Named("secret:get")
+   @GET
+   @Path("/secrets/{secretName}{secretVersion}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   SecretBundle getSecret(@EndpointParam URI vaultBaseUrl,
+                          @PathParam("secretName") String secretName,
+                          @Nullable @PathParam("secretVersion") @ParamParser(PrependSlashOrEmptyString.class) String secretVersion);
+
+   @Named("secret:delete")
+   @DELETE
+   @Path("/secrets/{secretName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedSecretBundle deleteSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   @Named("secret:get_versions")
+   @GET
+   @SelectJson("value")
+   @Path("/secrets/{secretName}/versions")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<Secret> getSecretVersions(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   @Named("secret:update")
+   @PATCH
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/secrets/{secretName}{secretVersion}")
+   @OAuthResource("https://vault.azure.net")
+   SecretBundle updateSecret(@EndpointParam URI vaultBaseUrl,
+                             @PathParam("secretName") String secretName,
+                             @Nullable @PathParam("secretVersion") @ParamParser(PrependSlashOrEmptyString.class) String secretVersion,
+                             @Nullable @PayloadParam("attributes") SecretAttributes attributes,
+                             @Nullable @PayloadParam("contentType") String contentType,
+                             @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("secret:backup")
+   @POST
+   @SelectJson("value")
+   @Path("/secrets/{secretName}/backup")
+   @OAuthResource("https://vault.azure.net")
+   String backupSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   @Named("secret:restore")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/secrets/restore")
+   @OAuthResource("https://vault.azure.net")
+   SecretBundle restoreSecret(@EndpointParam URI vaultBaseUrl, @PayloadParam("value") String secretInfo);
+
+   // Soft-delete secret operations
+   @Named("secret:list_deleted")
+   @GET
+   @SelectJson("value")
+   @Path("/deletedsecrets")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<DeletedSecretBundle> listDeletedSecrets(@EndpointParam URI vaultBaseUrl);
+
+   @Named("secret:get_deleted")
+   @GET
+   @Path("/deletedsecrets/{secretName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedSecretBundle getDeletedSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   @Named("secret:recover_deleted")
+   @POST
+   @Path("/deletedsecrets/{secretName}/recover")
+   @OAuthResource("https://vault.azure.net")
+   SecretBundle recoverDeletedSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   @Named("secret:purge_deleted")
+   @DELETE
+   @Path("/deletedsecrets/{secretName}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   boolean purgeDeletedSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   // Certificate operations
+   @Named("certificate:create")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/certificates/{certificateName}/create")
+   @OAuthResource("https://vault.azure.net")
+   CertificateOperation createCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName,
+         @Nullable @PayloadParam("attributes") CertificateAttributes attributes,
+         @Nullable @PayloadParam("policy") CertificatePolicy policy,
+         @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("certificate:get")
+   @GET
+   @Path("/certificates/{certificateName}{certificateVersion}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   CertificateBundle getCertificate(@EndpointParam URI vaultBaseUrl,
+                                    @PathParam("certificateName") String certificateName,
+                                    @Nullable @PathParam("certificateVersion") @ParamParser(PrependSlashOrEmptyString.class) String certificateVersion);
+
+   @Named("certificate:delete")
+   @DELETE
+   @Path("/certificates/{certificateName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedCertificateBundle deleteCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:list")
+   @GET
+   @SelectJson("value")
+   @Path("/certificates")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<Certificate> getCertificates(@EndpointParam URI vaultBaseUrl);
+
+   @Named("certificate:list_deleted")
+   @GET
+   @SelectJson("value")
+   @Path("/deletedcertificates")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<DeletedCertificate> getDeletedCertificates(@EndpointParam URI vaultBaseUrl);
+
+   @Named("certificate:get_deleted")
+   @GET
+   @Path("/deletedcertificates/{certificateName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedCertificateBundle getDeletedCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:recover_deleted")
+   @POST
+   @Path("/deletedcertificates/{certificateName}/recover")
+   @OAuthResource("https://vault.azure.net")
+   CertificateBundle recoverDeletedCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:purge_deleted")
+   @DELETE
+   @Path("/deletedcertificates/{certificateName}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   boolean purgeDeletedCertificate(@EndpointParam URI vaultBaseUrl, @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:get_versions")
+   @GET
+   @SelectJson("value")
+   @Path("/certificates/{certificateName}/versions")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<Certificate> getCertificateVersions(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:update")
+   @PATCH
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/certificates/{certificateName}{certificateVersion}")
+   @OAuthResource("https://vault.azure.net")
+   CertificateBundle updateCertificate(@EndpointParam URI vaultBaseUrl,
+                                       @PathParam("certificateName") String certificateName,
+                                       @Nullable @PathParam("certificateVersion") @ParamParser(PrependSlashOrEmptyString.class) String certificateVersion,
+                                       @Nullable @PayloadParam("attributes") CertificateAttributes attributes,
+                                       @Nullable @PayloadParam("policy") CertificatePolicy policy,
+                                       @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("certificate:import")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/certificates/{certificateName}/import")
+   @OAuthResource("https://vault.azure.net")
+   CertificateBundle importCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName,
+         @Nullable @PayloadParam("attributes") CertificateAttributes attributes,
+         @Nullable @PayloadParam("policy") CertificatePolicy policy, @Nullable @PayloadParam("pwd") String password,
+         @Nullable @PayloadParam("tags") Map<String, String> tags, @PayloadParam("value") String value);
+
+   @Named("certificate:merge")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/certificates/{certificateName}/pending/merge")
+   @OAuthResource("https://vault.azure.net")
+   CertificateBundle mergeCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName,
+         @Nullable @PayloadParam("attributes") CertificateAttributes attributes,
+         @Nullable @PayloadParam("tags") Map<String, String> tags, @PayloadParam("x5c") List<String> value);
+
+   @Named("certificate:get_operation")
+   @GET
+   @Path("/certificates/{certificateName}/pending")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   CertificateOperation getCertificateOperation(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:update_operation")
+   @PATCH
+   @Path("/certificates/{certificateName}/pending")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   CertificateOperation updateCertificateOperation(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName,
+         @PayloadParam("cancellation_requested") boolean cancellationRequested);
+
+   @Named("certificate:delete_operation")
+   @DELETE
+   @Path("/certificates/{certificateName}/pending")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   CertificateOperation deleteCertificateOperation(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:set_issuer")
+   @PUT
+   @Path("/certificates/issuers/{issuerName}")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   IssuerBundle setCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName,
+         @Nullable @PayloadParam("attributes") IssuerAttributes attributes,
+         @Nullable @PayloadParam("credentials") IssuerCredentials credentials,
+         @Nullable @PayloadParam("org_details") OrganizationDetails orgDetails,
+         @PayloadParam("provider") String provider);
+
+   @Named("certificate:get_issuers")
+   @GET
+   @SelectJson("value")
+   @Path("/certificates/issuers")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<CertificateIssuer> getCertificateIssuers(@EndpointParam URI vaultBaseUrl);
+
+   @Named("certificate:get_issuer")
+   @GET
+   @Path("/certificates/issuers/{issuerName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   IssuerBundle getCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName);
+
+   @Named("certificate:update_issuer")
+   @PATCH
+   @Path("/certificates/issuers/{issuerName}")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   IssuerBundle updateCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName,
+         @Nullable @PayloadParam("attributes") IssuerAttributes attributes,
+         @Nullable @PayloadParam("credentials") IssuerCredentials credentials,
+         @Nullable @PayloadParam("org_details") OrganizationDetails orgDetails,
+         @PayloadParam("provider") String provider);
+
+   @Named("certificate:delete_issuer")
+   @DELETE
+   @Path("/certificates/issuers/{issuerName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   IssuerBundle deleteCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName);
+
+   @Named("certificate:get_contacts")
+   @GET
+   @Path("/certificates/contacts")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   Contacts getCertificateContacts(@EndpointParam URI vaultBaseUrl);
+
+   @Named("certificate:set_contacts")
+   @PUT
+   @Path("/certificates/contacts")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   Contacts setCertificateContacts(@EndpointParam URI vaultBaseUrl, @PayloadParam("contacts") List<Contact> contacts);
+
+   @Named("certificate:delete_contacts")
+   @DELETE
+   @Path("/certificates/contacts")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   Contacts deleteCertificateContacts(@EndpointParam URI vaultBaseUrl);
+
+   @Named("certificate:get_policy")
+   @GET
+   @Path("/certificates/{certificateName}/policy")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   CertificatePolicy getCertificatePolicy(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:update_policy")
+   @PATCH
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/certificates/{certificateName}/policy")
+   @OAuthResource("https://vault.azure.net")
+   CertificatePolicy updateCertificatePolicy(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName,
+         @Nullable @PayloadParam("attributes") CertificateAttributes attributes,
+         @Nullable @PayloadParam("issuer") IssuerParameters issuer,
+         @Nullable @PayloadParam("key_props") KeyProperties keyProps,
+         @Nullable @PayloadParam("lifetime_actions") List<LifetimeAction> lifetimeActions,
+         @Nullable @PayloadParam("secret_props") SecretProperties secretProps,
+         @Nullable @PayloadParam("x509_props") X509CertificateProperties x509Props);
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
index 5cf4239..adcde2b 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
@@ -39,7 +39,7 @@ import java.util.Properties;
 import java.util.Set;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.PublicIpAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetProperties;


[14/50] [abbrv] jclouds git commit: JCLOUDS-1274: Delete managed disks when cleaning up VM resources

Posted by na...@apache.org.
JCLOUDS-1274: Delete managed disks when cleaning up VM resources


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

Branch: refs/heads/master
Commit: ec67fdea32cf6ffe96939e8a722bd21cbc215852
Parents: 3a9f578
Author: Ignasi Barrera <na...@apache.org>
Authored: Wed Apr 26 17:54:23 2017 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Thu Apr 27 22:54:08 2017 +0200

----------------------------------------------------------------------
 .../arm/compute/strategy/CleanupResources.java  | 50 ++++++++++++++++++--
 1 file changed, 46 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/ec67fdea/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
index 79f2cd0..1f1a37d 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
@@ -16,13 +16,18 @@
  */
 package org.jclouds.azurecompute.arm.compute.strategy;
 
+import static com.google.common.base.Predicates.not;
 import static com.google.common.base.Predicates.notNull;
 import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Maps.filterValues;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 
 import java.net.URI;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import javax.annotation.Resource;
 import javax.inject.Inject;
@@ -32,17 +37,22 @@ import javax.inject.Singleton;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
+import org.jclouds.azurecompute.arm.domain.DataDisk;
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.IpConfiguration;
+import org.jclouds.azurecompute.arm.domain.ManagedDiskParameters;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
+import org.jclouds.azurecompute.arm.domain.OSDisk;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
 import org.jclouds.compute.functions.GroupNamingConvention;
 import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.logging.Logger;
 
 import com.google.common.base.Function;
+import com.google.common.base.Joiner;
 import com.google.common.base.Predicate;
 
 @Singleton
@@ -80,12 +90,14 @@ public class CleanupResources {
       // group. It will be deleted when the resource group is deleted
 
       cleanupVirtualMachineNICs(virtualMachine);
+      cleanupManagedDisks(virtualMachine);
       cleanupAvailabilitySetIfOrphaned(virtualMachine);
 
       return vmDeleted;
    }
 
-   public void cleanupVirtualMachineNICs(VirtualMachine virtualMachine) {
+   public boolean cleanupVirtualMachineNICs(VirtualMachine virtualMachine) {
+      boolean deleted = true;
       for (IdReference nicRef : virtualMachine.properties().networkProfile().networkInterfaces()) {
          String nicResourceGroup = nicRef.resourceGroup();
          String nicName = nicRef.name();
@@ -95,14 +107,44 @@ public class CleanupResources {
 
          logger.debug(">> destroying nic %s...", nicName);
          URI nicDeletionURI = api.getNetworkInterfaceCardApi(nicResourceGroup).delete(nicName);
-         resourceDeleted.apply(nicDeletionURI);
+         deleted &= nicDeletionURI == null || resourceDeleted.apply(nicDeletionURI);
 
          for (IdReference publicIp : publicIps) {
             String publicIpResourceGroup = publicIp.resourceGroup();
             String publicIpName = publicIp.name();
             
             logger.debug(">> deleting public ip nic %s...", publicIpName);
-            api.getPublicIPAddressApi(publicIpResourceGroup).delete(publicIpName);
+            deleted &= api.getPublicIPAddressApi(publicIpResourceGroup).delete(publicIpName);
+         }
+      }
+      return deleted;
+   }
+
+   public boolean cleanupManagedDisks(VirtualMachine virtualMachine) {
+      Map<String, URI> deleteJobs = new HashMap<String, URI>();
+
+      OSDisk osDisk = virtualMachine.properties().storageProfile().osDisk();
+      deleteManagedDisk(osDisk.managedDiskParameters(), deleteJobs);
+
+      for (DataDisk dataDisk : virtualMachine.properties().storageProfile().dataDisks()) {
+         deleteManagedDisk(dataDisk.managedDiskParameters(), deleteJobs);
+      }
+      
+      Set<String> nonDeletedDisks = filterValues(deleteJobs, not(resourceDeleted)).keySet();
+      if (!nonDeletedDisks.isEmpty()) {
+         logger.warn(">> could not delete disks: %s", Joiner.on(',').join(nonDeletedDisks));
+      }
+      
+      return nonDeletedDisks.isEmpty();
+   }
+   
+   private void deleteManagedDisk(@Nullable ManagedDiskParameters managedDisk, Map<String, URI> deleteJobs) {
+      if (managedDisk != null) {
+         IdReference diskRef = IdReference.create(managedDisk.id());
+         logger.debug(">> deleting managed disk %s...", diskRef.name());
+         URI uri = api.getDiskApi(diskRef.resourceGroup()).delete(diskRef.name());
+         if (uri != null) {
+            deleteJobs.put(diskRef.name(), uri);
          }
       }
    }
@@ -134,7 +176,7 @@ public class CleanupResources {
    }
 
    public boolean cleanupAvailabilitySetIfOrphaned(VirtualMachine virtualMachine) {
-      boolean deleted = false;
+      boolean deleted = true;
       IdReference availabilitySetRef = virtualMachine.properties().availabilitySet();
 
       if (availabilitySetRef != null) {


[09/50] [abbrv] jclouds git commit: JCLOUDS-1273/JCLOUDS-1226: Support multiple resource groups in ARM

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
index 0ff96d8..bb5dc09 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
@@ -28,7 +28,7 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.domain.RegionAndIdAndIngressRules;
+import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
@@ -36,32 +36,27 @@ import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Access;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Direction;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Protocol;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.logging.Logger;
 
 import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
 
 @Singleton
-public class CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndIdAndIngressRules, String> {
+public class CreateSecurityGroupIfNeeded extends CacheLoader<ResourceGroupAndNameAndIngressRules, String> {
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
 
    private final AzureComputeApi api;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
 
    @Inject
-   CreateSecurityGroupIfNeeded(AzureComputeApi api, LoadingCache<String, ResourceGroup> resourceGroupMap) {
+   CreateSecurityGroupIfNeeded(AzureComputeApi api) {
       this.api = api;
-      this.resourceGroupMap = resourceGroupMap;
    }
 
    @Override
-   public String load(RegionAndIdAndIngressRules key) throws Exception {
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(key.region());
-      return createSecurityGroup(key.region(), resourceGroup.name(), key.id(), key.inboundPorts());
+   public String load(ResourceGroupAndNameAndIngressRules key) throws Exception {
+      return createSecurityGroup(key.location(), key.resourceGroup(), key.name(), key.inboundPorts());
    }
 
    private String createSecurityGroup(String location, String resourceGroup, String name, int[] inboundPorts) {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/DefaultResourceGroup.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/DefaultResourceGroup.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/DefaultResourceGroup.java
new file mode 100644
index 0000000..7caec25
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/DefaultResourceGroup.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.compute.loaders;
+
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName;
+import org.jclouds.azurecompute.arm.domain.ResourceGroup;
+import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+
+import com.google.common.cache.CacheLoader;
+import com.google.common.collect.ImmutableMap;
+
+@Singleton
+public class DefaultResourceGroup extends CacheLoader<String, ResourceGroup> {
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final ResourceGroupApi api;
+   private final LocationToResourceGroupName locationToResourceGroupName;
+
+   @Inject
+   DefaultResourceGroup(AzureComputeApi api, LocationToResourceGroupName locationToResourceGroupName) {
+      this.api = api.getResourceGroupApi();
+      this.locationToResourceGroupName = locationToResourceGroupName;
+   }
+
+   @Override
+   public ResourceGroup load(String locationId) throws Exception {
+      String azureGroupName = locationToResourceGroupName.apply(locationId);
+      ResourceGroup resourceGroup = api.get(azureGroupName);
+      if (resourceGroup == null) {
+         logger.debug(">> creating resource group %s", azureGroupName);
+         final Map<String, String> tags = ImmutableMap.of("description", "jclouds default resource group");
+         resourceGroup = api.create(azureGroupName, locationId, tags);
+      }
+      return resourceGroup;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/ResourceGroupForLocation.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/ResourceGroupForLocation.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/ResourceGroupForLocation.java
deleted file mode 100644
index ddbbb26..0000000
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/ResourceGroupForLocation.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azurecompute.arm.compute.loaders;
-
-import java.util.Map;
-
-import javax.annotation.Resource;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
-import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
-import org.jclouds.compute.reference.ComputeServiceConstants;
-import org.jclouds.logging.Logger;
-
-import com.google.common.cache.CacheLoader;
-import com.google.common.collect.ImmutableMap;
-
-@Singleton
-public class ResourceGroupForLocation extends CacheLoader<String, ResourceGroup> {
-   @Resource
-   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
-   protected Logger logger = Logger.NULL;
-
-   private final ResourceGroupApi api;
-   private final LocationToResourceGroupName locationToResourceGroupName;
-
-   @Inject
-   ResourceGroupForLocation(AzureComputeApi api, LocationToResourceGroupName locationToResourceGroupName) {
-      this.api = api.getResourceGroupApi();
-      this.locationToResourceGroupName = locationToResourceGroupName;
-   }
-
-   @Override
-   public ResourceGroup load(String locationId) throws Exception {
-      String azureGroupName = locationToResourceGroupName.apply(locationId);
-      ResourceGroup resourceGroup = api.get(azureGroupName);
-      if (resourceGroup == null) {
-         logger.debug(">> creating resource group %s", azureGroupName);
-         final Map<String, String> tags = ImmutableMap.of("description", "jclouds managed VMs");
-         resourceGroup = api.create(azureGroupName, locationId, tags);
-      }
-      return resourceGroup;
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
index 5566ecf..d211421 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
@@ -34,10 +34,10 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
 
    private String virtualNetworkName;
    private String subnetId;
-   private String blob;
    private AvailabilitySet availabilitySet;
    private String availabilitySetName;
    private List<DataDisk> dataDisks = ImmutableList.of();
+   private String resourceGroup;
 
    /**
     * Sets the virtual network name
@@ -54,14 +54,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       this.subnetId = subnetId;
       return this;
    }
-
-   /**
-    * Sets the blob name
-    */
-   public  AzureTemplateOptions blob(String blob) {
-      this.blob = blob;
-      return this;
-   }
    
    /**
     * Sets the availability set where the nodes will be configured. If it does
@@ -80,6 +72,14 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       this.availabilitySetName = availabilitySetName;
       return this;
    }
+   
+   /**
+    * The resource group where the new resources will be created.
+    */
+   public AzureTemplateOptions resourceGroup(String resourceGroup) {
+      this.resourceGroup = resourceGroup;
+      return this;
+   }
 
    public AzureTemplateOptions dataDisks(Iterable<DataDisk> dataDisks) {
       for (DataDisk dataDisk : checkNotNull(dataDisks, "dataDisks"))
@@ -94,12 +94,10 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
    
    public String getVirtualNetworkName() { return virtualNetworkName; }
    public String getSubnetId() { return subnetId; }
-   public String getBlob() { return blob; }
    public AvailabilitySet getAvailabilitySet() { return availabilitySet; }
    public String getAvailabilitySetName() { return availabilitySetName; }
-   public List<DataDisk> getDataDisks() {
-      return dataDisks;
-   }
+   public List<DataDisk> getDataDisks() { return dataDisks; }
+   public String getResourceGroup() { return resourceGroup; }
 
    @Override
    public AzureTemplateOptions clone() {
@@ -115,10 +113,10 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          AzureTemplateOptions eTo = AzureTemplateOptions.class.cast(to);
          eTo.virtualNetworkName(virtualNetworkName);
          eTo.subnetId(subnetId);
-         eTo.blob(blob);
          eTo.availabilitySet(availabilitySet);
          eTo.availabilitySet(availabilitySetName);
          eTo.dataDisks(dataDisks);
+         eTo.resourceGroup(resourceGroup);
       }
    }
 
@@ -129,28 +127,19 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       if (!super.equals(o)) return false;
 
       AzureTemplateOptions that = (AzureTemplateOptions) o;
-
-      if (virtualNetworkName != null ? !virtualNetworkName.equals(that.virtualNetworkName) : that.virtualNetworkName != null)
-         return false;
-      if (subnetId != null ? !subnetId.equals(that.subnetId) : that.subnetId != null) return false;
-      if (blob != null ? !blob.equals(that.blob) : that.blob != null) return false;
-      if (availabilitySet != null ? !availabilitySet.equals(that.availabilitySet) : that.availabilitySet != null)
-         return false;
-      if (availabilitySetName != null ? !availabilitySetName.equals(that.availabilitySetName) : that.availabilitySetName != null)
-         return false;
-      return dataDisks != null ? dataDisks.equals(that.dataDisks) : that.dataDisks == null;
+      
+      return Objects.equal(virtualNetworkName, that.virtualNetworkName) &&
+            Objects.equal(subnetId, that.subnetId) &&
+            Objects.equal(availabilitySet, that.availabilitySet) &&
+            Objects.equal(availabilitySetName, that.availabilitySetName) &&
+            Objects.equal(dataDisks, that.dataDisks) &&
+            Objects.equal(resourceGroup, that.resourceGroup);
    }
 
    @Override
    public int hashCode() {
-      int result = super.hashCode();
-      result = 31 * result + (virtualNetworkName != null ? virtualNetworkName.hashCode() : 0);
-      result = 31 * result + (subnetId != null ? subnetId.hashCode() : 0);
-      result = 31 * result + (blob != null ? blob.hashCode() : 0);
-      result = 31 * result + (availabilitySet != null ? availabilitySet.hashCode() : 0);
-      result = 31 * result + (availabilitySetName != null ? availabilitySetName.hashCode() : 0);
-      result = 31 * result + (dataDisks != null ? dataDisks.hashCode() : 0);
-      return result;
+      return Objects.hashCode(virtualNetworkName, subnetId, availabilitySet, availabilitySetName, dataDisks,
+            resourceGroup);
    }
 
    @Override
@@ -160,14 +149,14 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          toString.add("virtualNetworkName", virtualNetworkName);
       if (subnetId != null)
          toString.add("subnetId", subnetId);
-      if (blob != null)
-         toString.add("blob", blob);
       if (availabilitySet != null)
          toString.add("availabilitySet", availabilitySet);
       if (availabilitySetName != null)
          toString.add("availabilitySetName", availabilitySetName);
       if (!dataDisks.isEmpty())
          toString.add("dataDisks", dataDisks);
+      if (resourceGroup != null)
+         toString.add("resourceGroup", resourceGroup);
       return toString;
    }
 
@@ -188,14 +177,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          AzureTemplateOptions options = new AzureTemplateOptions();
          return options.subnetId(subnetId);
       }
-
-      /**
-       * @see AzureTemplateOptions#blob(String)
-       */
-      public static AzureTemplateOptions blob(String blob) {
-         AzureTemplateOptions options = new AzureTemplateOptions();
-         return options.blob(blob);
-      }
       
       /**
        * @see AzureTemplateOptions#availabilitySet(AvailabilitySet)
@@ -214,16 +195,27 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       }
 
       /**
-       * @see AzureTemplateOptions#dataDisks
+       * @see AzureTemplateOptions#dataDisks(DataDisk...)
        */
       public static AzureTemplateOptions dataDisks(DataDisk... dataDisks) {
          AzureTemplateOptions options = new AzureTemplateOptions();
          return options.dataDisks(dataDisks);
       }
 
+      /**
+       * @see AzureTemplateOptions#dataDisks(Iterable)
+       */
       public static AzureTemplateOptions dataDisks(Iterable<DataDisk> dataDisks) {
          AzureTemplateOptions options = new AzureTemplateOptions();
          return options.dataDisks(dataDisks);
       }
+      
+      /**
+       * @see AzureTemplateOptions#resourceGroup(String)
+       */
+      public static AzureTemplateOptions resourceGroup(String resourceGroup) {
+         AzureTemplateOptions options = new AzureTemplateOptions();
+         return options.resourceGroup(resourceGroup);
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
index fb635aa..79f2cd0 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
@@ -30,13 +30,12 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.IpConfiguration;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
-import org.jclouds.azurecompute.arm.domain.RegionAndId;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
 import org.jclouds.compute.functions.GroupNamingConvention;
@@ -45,10 +44,6 @@ import org.jclouds.logging.Logger;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
-import com.google.common.base.Splitter;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
 
 @Singleton
 public class CleanupResources {
@@ -59,52 +54,55 @@ public class CleanupResources {
 
    private final AzureComputeApi api;
    private final Predicate<URI> resourceDeleted;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
    private final GroupNamingConvention.Factory namingConvention;
 
    @Inject
    CleanupResources(AzureComputeApi azureComputeApi, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
-         LoadingCache<String, ResourceGroup> resourceGroupMap, GroupNamingConvention.Factory namingConvention) {
+         GroupNamingConvention.Factory namingConvention) {
       this.api = azureComputeApi;
       this.resourceDeleted = resourceDeleted;
-      this.resourceGroupMap = resourceGroupMap;
       this.namingConvention = namingConvention;
    }
 
    public boolean cleanupNode(final String id) {
-      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
-      String resourceGroupName = resourceGroup.name();
+      ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
+      String resourceGroupName = resourceGroupAndName.resourceGroup();
 
-      VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).get(regionAndId.id());
+      VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).get(resourceGroupAndName.name());
       if (virtualMachine == null) {
          return true;
       }
 
-      logger.debug(">> destroying %s ...", regionAndId.slashEncode());
+      logger.debug(">> destroying %s ...", id);
       boolean vmDeleted = deleteVirtualMachine(resourceGroupName, virtualMachine);
 
       // We don't delete the network here, as it is global to the resource
       // group. It will be deleted when the resource group is deleted
 
-      cleanupVirtualMachineNICs(resourceGroupName, virtualMachine);
-      cleanupAvailabilitySetIfOrphaned(resourceGroupName, virtualMachine);
+      cleanupVirtualMachineNICs(virtualMachine);
+      cleanupAvailabilitySetIfOrphaned(virtualMachine);
 
       return vmDeleted;
    }
 
-   public void cleanupVirtualMachineNICs(String group, VirtualMachine virtualMachine) {
-      for (String nicName : getNetworkCardInterfaceNames(virtualMachine)) {
-         NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(group).get(nicName);
-         Iterable<String> publicIps = getPublicIps(group, nic);
+   public void cleanupVirtualMachineNICs(VirtualMachine virtualMachine) {
+      for (IdReference nicRef : virtualMachine.properties().networkProfile().networkInterfaces()) {
+         String nicResourceGroup = nicRef.resourceGroup();
+         String nicName = nicRef.name();
+         NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(nicRef.resourceGroup()).get(nicName);
+         
+         Iterable<IdReference> publicIps = getPublicIps(nic);
 
          logger.debug(">> destroying nic %s...", nicName);
-         URI nicDeletionURI = api.getNetworkInterfaceCardApi(group).delete(nicName);
+         URI nicDeletionURI = api.getNetworkInterfaceCardApi(nicResourceGroup).delete(nicName);
          resourceDeleted.apply(nicDeletionURI);
 
-         for (String publicIp : publicIps) {
-            logger.debug(">> deleting public ip nic %s...", publicIp);
-            api.getPublicIPAddressApi(group).delete(publicIp);
+         for (IdReference publicIp : publicIps) {
+            String publicIpResourceGroup = publicIp.resourceGroup();
+            String publicIpName = publicIp.name();
+            
+            logger.debug(">> deleting public ip nic %s...", publicIpName);
+            api.getPublicIPAddressApi(publicIpResourceGroup).delete(publicIpName);
          }
       }
    }
@@ -135,12 +133,13 @@ public class CleanupResources {
       return deleted;
    }
 
-   public boolean cleanupAvailabilitySetIfOrphaned(String resourceGroup, VirtualMachine virtualMachine) {
+   public boolean cleanupAvailabilitySetIfOrphaned(VirtualMachine virtualMachine) {
       boolean deleted = false;
       IdReference availabilitySetRef = virtualMachine.properties().availabilitySet();
 
       if (availabilitySetRef != null) {
-         String name = Iterables.getLast(Splitter.on("/").split(availabilitySetRef.id()));
+         String name = availabilitySetRef.name();
+         String resourceGroup = availabilitySetRef.resourceGroup();
          AvailabilitySet availabilitySet = api.getAvailabilitySetApi(resourceGroup).get(name);
 
          if (isOrphanedJcloudsAvailabilitySet(availabilitySet)) {
@@ -162,19 +161,13 @@ public class CleanupResources {
       return deleted;
    }
 
-   private Iterable<String> getPublicIps(String group, NetworkInterfaceCard nic) {
-      return transform(
-            filter(transform(nic.properties().ipConfigurations(), new Function<IpConfiguration, IdReference>() {
-               @Override
-               public IdReference apply(IpConfiguration input) {
-                  return input.properties().publicIPAddress();
-               }
-            }), notNull()), new Function<IdReference, String>() {
-               @Override
-               public String apply(IdReference input) {
-                  return Iterables.getLast(Splitter.on("/").split(input.id()));
-               }
-            });
+   private Iterable<IdReference> getPublicIps(NetworkInterfaceCard nic) {
+      return filter(transform(nic.properties().ipConfigurations(), new Function<IpConfiguration, IdReference>() {
+         @Override
+         public IdReference apply(IpConfiguration input) {
+            return input.properties().publicIPAddress();
+         }
+      }), notNull());
    }
 
    private static boolean isOrphanedJcloudsAvailabilitySet(AvailabilitySet availabilitySet) {
@@ -187,14 +180,6 @@ public class CleanupResources {
                   .virtualMachines().isEmpty());
    }
 
-   private List<String> getNetworkCardInterfaceNames(VirtualMachine virtualMachine) {
-      List<String> nics = Lists.newArrayList();
-      for (IdReference idReference : virtualMachine.properties().networkProfile().networkInterfaces()) {
-         nics.add(Iterables.getLast(Splitter.on("/").split(idReference.id())));
-      }
-      return nics;
-   }
-
    private boolean deleteVirtualMachine(String group, VirtualMachine virtualMachine) {
       return resourceDeleted.apply(api.getVirtualMachineApi(group).delete(virtualMachine.name()));
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
deleted file mode 100644
index 5f6d88f..0000000
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azurecompute.arm.compute.strategy;
-
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.Resource;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-import org.jclouds.Constants;
-import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.domain.RegionAndIdAndIngressRules;
-import org.jclouds.azurecompute.arm.compute.functions.TemplateToAvailabilitySet;
-import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
-import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
-import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
-import org.jclouds.azurecompute.arm.domain.RegionAndId;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
-import org.jclouds.azurecompute.arm.domain.Subnet;
-import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
-import org.jclouds.azurecompute.arm.features.SubnetApi;
-import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
-import org.jclouds.compute.config.CustomizationResponse;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.functions.GroupNamingConvention;
-import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.compute.reference.ComputeServiceConstants;
-import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
-import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
-import org.jclouds.compute.strategy.ListNodesStrategy;
-import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
-import org.jclouds.domain.Location;
-import org.jclouds.logging.Logger;
-
-import com.google.common.base.Optional;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.Multimap;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
-
-@Singleton
-public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEncodedIntoNameThenAddToSet {
-
-   @Resource
-   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
-   protected Logger logger = Logger.NULL;
-
-   private final AzureComputeApi api;
-   private final LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
-   private final String defaultVnetAddressPrefix;
-   private final String defaultSubnetAddressPrefix;
-   private final TemplateToAvailabilitySet templateToAvailabilitySet;
-
-   @Inject
-   protected CreateResourceGroupThenCreateNodes(
-         CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy,
-         ListNodesStrategy listNodesStrategy,
-         GroupNamingConvention.Factory namingConvention,
-         @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
-         CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
-         AzureComputeApi api, @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX) String defaultVnetAddressPrefix,
-         @Named(DEFAULT_SUBNET_ADDRESS_PREFIX) String defaultSubnetAddressPrefix,
-         LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap,
-         LoadingCache<String, ResourceGroup> resourceGroupMap, 
-         TemplateToAvailabilitySet templateToAvailabilitySet) {
-      super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
-            customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
-      this.api = checkNotNull(api, "api cannot be null");
-      checkNotNull(userExecutor, "userExecutor cannot be null");
-      this.securityGroupMap = securityGroupMap;
-      this.resourceGroupMap = resourceGroupMap;
-      this.defaultVnetAddressPrefix = defaultVnetAddressPrefix;
-      this.defaultSubnetAddressPrefix = defaultSubnetAddressPrefix;
-      this.templateToAvailabilitySet = templateToAvailabilitySet;
-   }
-
-   @Override
-   public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template,
-         Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
-         Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
-
-      AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class);
-
-      // If there is a script to be run on the node and public key
-      // authentication has been configured, warn users if the private key
-      // is not present
-      if (hasRunScriptWithKeyAuthAndNoPrivateKey(template)) {
-         logger.warn(">> a runScript was configured but no SSH key has been provided. "
-               + "Authentication will delegate to the ssh-agent");
-      }
-
-      // This sill create the resource group if it does not exist
-      String location = template.getLocation().getId();
-      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location);
-      String azureGroupName = resourceGroup.name();
-
-      getOrCreateVirtualNetworkWithSubnet(location, options, azureGroupName);
-      configureSecurityGroupForOptions(group, azureGroupName, template.getLocation(), options);
-      configureAvailabilitySetForTemplate(template);
-
-      return super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
-   }
-
-   protected synchronized void getOrCreateVirtualNetworkWithSubnet(final String location, AzureTemplateOptions options,
-         final String azureGroupName) {
-      String virtualNetworkName = Optional.fromNullable(options.getVirtualNetworkName()).or(
-            azureGroupName + "virtualnetwork");
-      String subnetName = azureGroupName + "subnet";
-
-      // Subnets belong to a virtual network so that needs to be created first
-      VirtualNetworkApi vnApi = api.getVirtualNetworkApi(azureGroupName);
-      VirtualNetwork vn = vnApi.get(virtualNetworkName);
-
-      if (vn == null) {
-         Subnet subnet = Subnet.create(subnetName, null, null,
-               Subnet.SubnetProperties.builder().addressPrefix(defaultSubnetAddressPrefix).build());
-
-         VirtualNetwork.VirtualNetworkProperties virtualNetworkProperties = VirtualNetwork.VirtualNetworkProperties
-               .builder().addressSpace(VirtualNetwork.AddressSpace.create(Arrays.asList(defaultVnetAddressPrefix)))
-               .subnets(Arrays.asList(subnet)).build();
-
-         vn = vnApi.createOrUpdate(virtualNetworkName, location, virtualNetworkProperties);
-      }
-
-      SubnetApi subnetApi = api.getSubnetApi(azureGroupName, virtualNetworkName);
-      Subnet subnet = subnetApi.get(subnetName);
-
-      options.virtualNetworkName(virtualNetworkName);
-      options.subnetId(subnet.id());
-   }
-
-   private static boolean hasRunScriptWithKeyAuthAndNoPrivateKey(Template template) {
-      return template.getOptions().getRunScript() != null && template.getOptions().getPublicKey() != null
-            && !template.getOptions().hasLoginPrivateKeyOption();
-   }
-
-   private void configureSecurityGroupForOptions(String group, String resourceGroup, Location location,
-         TemplateOptions options) {
-
-      checkArgument(options.getGroups().size() <= 1,
-            "Only one security group can be configured for each network interface");
-
-      if (!options.getGroups().isEmpty()) {
-         String groupName = getOnlyElement(options.getGroups());
-         String groupNameWithourRegion = groupName.indexOf('/') == -1 ? groupName : RegionAndId.fromSlashEncoded(
-               groupName).id();
-         NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(resourceGroup).get(groupNameWithourRegion);
-         checkArgument(securityGroup != null, "Security group %s was not found", groupName);
-         options.securityGroups(securityGroup.id());
-      } else if (options.getInboundPorts().length > 0) {
-         String name = namingConvention.create().sharedNameForGroup(group);
-         RegionAndIdAndIngressRules regionAndIdAndIngressRules = RegionAndIdAndIngressRules.create(location.getId(),
-               name, options.getInboundPorts());
-         // this will create if not yet exists.
-         String securityGroupId = securityGroupMap.getUnchecked(regionAndIdAndIngressRules);
-         options.securityGroups(securityGroupId);
-      }
-   }
-   
-   private void configureAvailabilitySetForTemplate(Template template) {
-      AvailabilitySet availabilitySet = templateToAvailabilitySet.apply(template);
-      if (availabilitySet != null) {
-         logger.debug(">> configuring nodes in availability set [%s]", availabilitySet.name());
-         template.getOptions().as(AzureTemplateOptions.class).availabilitySet(availabilitySet);
-      }
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
new file mode 100644
index 0000000..c3bdbdd
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.compute.strategy;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.Constants;
+import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
+import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
+import org.jclouds.azurecompute.arm.compute.functions.TemplateToAvailabilitySet;
+import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
+import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
+import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
+import org.jclouds.azurecompute.arm.domain.ResourceGroup;
+import org.jclouds.azurecompute.arm.domain.Subnet;
+import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
+import org.jclouds.azurecompute.arm.features.SubnetApi;
+import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
+import org.jclouds.compute.config.CustomizationResponse;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
+import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
+import org.jclouds.compute.strategy.ListNodesStrategy;
+import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
+import org.jclouds.domain.Location;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Optional;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+@Singleton
+public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedIntoNameThenAddToSet {
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final AzureComputeApi api;
+   private final LoadingCache<ResourceGroupAndNameAndIngressRules, String> securityGroupMap;
+   private final String defaultVnetAddressPrefix;
+   private final String defaultSubnetAddressPrefix;
+   private final TemplateToAvailabilitySet templateToAvailabilitySet;
+
+   @Inject
+   protected CreateResourcesThenCreateNodes(
+         CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy,
+         ListNodesStrategy listNodesStrategy,
+         GroupNamingConvention.Factory namingConvention,
+         @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
+         CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
+         AzureComputeApi api, @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX) String defaultVnetAddressPrefix,
+         @Named(DEFAULT_SUBNET_ADDRESS_PREFIX) String defaultSubnetAddressPrefix,
+         LoadingCache<ResourceGroupAndNameAndIngressRules, String> securityGroupMap,
+         TemplateToAvailabilitySet templateToAvailabilitySet) {
+      super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
+            customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
+      this.api = checkNotNull(api, "api cannot be null");
+      checkNotNull(userExecutor, "userExecutor cannot be null");
+      this.securityGroupMap = securityGroupMap;
+      this.defaultVnetAddressPrefix = defaultVnetAddressPrefix;
+      this.defaultSubnetAddressPrefix = defaultSubnetAddressPrefix;
+      this.templateToAvailabilitySet = templateToAvailabilitySet;
+   }
+
+   @Override
+   public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template,
+         Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
+         Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
+
+      AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class);
+
+      // If there is a script to be run on the node and public key
+      // authentication has been configured, warn users if the private key
+      // is not present
+      if (hasRunScriptWithKeyAuthAndNoPrivateKey(template)) {
+         logger.warn(">> a runScript was configured but no SSH key has been provided. "
+               + "Authentication will delegate to the ssh-agent");
+      }
+
+      // This sill create the resource group if it does not exist
+      String location = template.getLocation().getId();
+
+      createResourceGroupIfNeeded(group, location, options);
+      getOrCreateVirtualNetworkWithSubnet(location, options);
+      configureSecurityGroupForOptions(group, template.getLocation(), options);
+      configureAvailabilitySetForTemplate(template);
+
+      return super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
+   }
+
+   protected synchronized void getOrCreateVirtualNetworkWithSubnet(final String location, AzureTemplateOptions options) {
+      String virtualNetworkName = Optional.fromNullable(options.getVirtualNetworkName()).or(
+            options.getResourceGroup() + "virtualnetwork");
+      String subnetName = options.getResourceGroup() + "subnet";
+
+      // Subnets belong to a virtual network so that needs to be created first
+      VirtualNetworkApi vnApi = api.getVirtualNetworkApi(options.getResourceGroup());
+      VirtualNetwork vn = vnApi.get(virtualNetworkName);
+
+      if (vn == null) {
+         Subnet subnet = Subnet.create(subnetName, null, null,
+               Subnet.SubnetProperties.builder().addressPrefix(defaultSubnetAddressPrefix).build());
+
+         VirtualNetwork.VirtualNetworkProperties virtualNetworkProperties = VirtualNetwork.VirtualNetworkProperties
+               .builder().addressSpace(VirtualNetwork.AddressSpace.create(Arrays.asList(defaultVnetAddressPrefix)))
+               .subnets(Arrays.asList(subnet)).build();
+
+         vn = vnApi.createOrUpdate(virtualNetworkName, location, virtualNetworkProperties);
+      }
+
+      SubnetApi subnetApi = api.getSubnetApi(options.getResourceGroup(), virtualNetworkName);
+      Subnet subnet = subnetApi.get(subnetName);
+
+      options.virtualNetworkName(virtualNetworkName);
+      options.subnetId(subnet.id());
+   }
+
+   private static boolean hasRunScriptWithKeyAuthAndNoPrivateKey(Template template) {
+      return template.getOptions().getRunScript() != null && template.getOptions().getPublicKey() != null
+            && !template.getOptions().hasLoginPrivateKeyOption();
+   }
+
+   private void configureSecurityGroupForOptions(String group, Location location, AzureTemplateOptions options) {
+
+      checkArgument(options.getGroups().size() <= 1,
+            "Only one security group can be configured for each network interface");
+
+      if (!options.getGroups().isEmpty()) {
+         ResourceGroupAndName securityGroupId = ResourceGroupAndName.fromSlashEncoded(getOnlyElement(options.getGroups()));
+         NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(securityGroupId.resourceGroup()).get(
+               securityGroupId.name());
+         checkArgument(securityGroup != null, "Security group %s was not found", securityGroupId.slashEncode());
+         options.securityGroups(securityGroup.id());
+      } else if (options.getInboundPorts().length > 0) {
+         String name = namingConvention.create().sharedNameForGroup(group);
+         ResourceGroupAndNameAndIngressRules regionAndIdAndIngressRules = ResourceGroupAndNameAndIngressRules.create(
+               options.getResourceGroup(), location.getId(), name, options.getInboundPorts());
+         // this will create if not yet exists.
+         String securityGroupId = securityGroupMap.getUnchecked(regionAndIdAndIngressRules);
+         options.securityGroups(securityGroupId);
+      }
+   }
+   
+   private void configureAvailabilitySetForTemplate(Template template) {
+      AvailabilitySet availabilitySet = templateToAvailabilitySet.apply(template);
+      if (availabilitySet != null) {
+         logger.debug(">> configuring nodes in availability set [%s]", availabilitySet.name());
+         template.getOptions().as(AzureTemplateOptions.class).availabilitySet(availabilitySet);
+      }
+   }
+   
+   private void createResourceGroupIfNeeded(String group, String location, AzureTemplateOptions options) {
+      if (options.getResourceGroup() == null) {
+         options.resourceGroup(group);
+      }
+      logger.debug(">> using resource group [%s]", options.getResourceGroup());
+      ResourceGroup rg = api.getResourceGroupApi().get(options.getResourceGroup());
+      if (rg == null) {
+         logger.debug(">> resource group [%s] does not exist. Creating!", options.getResourceGroup());
+         api.getResourceGroupApi().create(options.getResourceGroup(), location,
+               ImmutableMap.of("description", "jclouds default resource group"));
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/IdReference.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/IdReference.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/IdReference.java
index 1854897..f73e3e4 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/IdReference.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/IdReference.java
@@ -16,19 +16,56 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
+import com.google.auto.value.AutoValue;
+
 // Simple helper class to serialize / deserialize id reference.
 
 @AutoValue
 public abstract class IdReference {
+   
+   private static final Pattern RESOURCE_GROUP_PATTERN = Pattern.compile("^.*/resourceGroups/([^/]+)(/.*)?$");
+   
    @Nullable
    public abstract String id();
+   
+   @Nullable
+   public String resourceGroup() {
+      return extractResourceGroup(id());
+   }
+   
+   @Nullable
+   public String name() {
+      return extractName(id());
+   }
 
    @SerializedNames({"id"})
    public static IdReference create(final String id) {
       return new AutoValue_IdReference(id);
    }
+   
+   /**
+    * Extracts the name from the given URI.
+    */
+   public static String extractName(String uri) {
+      if (uri == null)
+         return null;
+      String noSlashAtEnd = uri.replaceAll("/+$", "");
+      return noSlashAtEnd.substring(noSlashAtEnd.lastIndexOf('/') + 1);
+   }
+   
+   /**
+    * Extracts the resource group name from the given URI.
+    */
+   public static String extractResourceGroup(String uri) {
+      if (uri == null)
+         return null;
+      Matcher m = RESOURCE_GROUP_PATTERN.matcher(uri);
+      return m.matches() ? m.group(1) : null;
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java
deleted file mode 100644
index 4105ee3..0000000
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azurecompute.arm.domain;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterables;
-
-@AutoValue
-public abstract class RegionAndId {
-
-   public abstract String region();
-   public abstract String id();
-   
-   protected RegionAndId() {
-      
-   }
-   
-   public static RegionAndId fromSlashEncoded(String id) {
-      Iterable<String> parts = Splitter.on('/').split(checkNotNull(id, "id"));
-      checkArgument(Iterables.size(parts) == 2, "id must be in format regionId/id");
-      return new AutoValue_RegionAndId(Iterables.get(parts, 0), Iterables.get(parts, 1));
-   }
-
-   public static RegionAndId fromRegionAndId(String region, String id) {
-      return new AutoValue_RegionAndId(region, id);
-   }
-
-   public String slashEncode() {
-      return region() + "/" + id();
-   }
-   
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMHardware.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMHardware.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMHardware.java
index f0aa77e..e771903 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMHardware.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMHardware.java
@@ -62,14 +62,9 @@ public abstract class VMHardware {
     */
    public abstract String location();
 
-   /**
-    * Specifies if this HW is globally available
-    */
-   public abstract boolean globallyAvailable();
-
-   @SerializedNames({ "name", "numberOfCores", "osDiskSizeInMB", "resourceDiskSizeInMB", "memoryInMB", "maxDataDiskCount", "location", "globallyAvailable"})
-   public static VMHardware create(String name, Integer numberOfCores, Integer osDiskSizeInMB, Integer resourceDiskSizeInMB, Integer memoryInMB, Integer maxDataDiskCount, String location, boolean globallyAvailable) {
+   @SerializedNames({ "name", "numberOfCores", "osDiskSizeInMB", "resourceDiskSizeInMB", "memoryInMB", "maxDataDiskCount", "location"})
+   public static VMHardware create(String name, Integer numberOfCores, Integer osDiskSizeInMB, Integer resourceDiskSizeInMB, Integer memoryInMB, Integer maxDataDiskCount, String location) {
 
-      return new AutoValue_VMHardware(name, numberOfCores, osDiskSizeInMB, resourceDiskSizeInMB, memoryInMB, maxDataDiskCount, location, globallyAvailable);
+      return new AutoValue_VMHardware(name, numberOfCores, osDiskSizeInMB, resourceDiskSizeInMB, memoryInMB, maxDataDiskCount, location);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
index a01ed23..91ca818 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
@@ -98,6 +98,13 @@ public abstract class VMImage {
     */
    @Nullable
    public abstract String customImageId();
+   
+   /**
+    * The resource group for the image in case of custom images.
+    * @return
+    */
+   @Nullable
+   public abstract String resourceGroup();
 
    /**
     * Extended version properties.
@@ -127,6 +134,7 @@ public abstract class VMImage {
    public abstract static class Builder {
 
       public abstract Builder customImageId(String id);
+      public abstract Builder resourceGroup(String resourceGroup);
       public abstract Builder publisher(String published);
       public abstract Builder offer(String offer);
       public abstract Builder sku(String sku);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
index 5a01e90..a854fed 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 package org.jclouds.azurecompute.arm.features;
+
 import java.io.Closeable;
 import java.net.URI;
 import java.util.List;
@@ -37,7 +38,6 @@ import org.jclouds.rest.annotations.SelectJson;
 /**
  * The Azure Resource Manager API checks for job status and progress.
  */
-
 @RequestFilters(OAuthFilter.class)
 @Consumes(MediaType.APPLICATION_JSON)
 public interface JobApi extends Closeable {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
index a5944ec..238832e 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
@@ -21,7 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 public class VMImages {
 
    public static boolean isCustom(String imageId) {
-      return checkNotNull(imageId, "id").split("/").length == 2;
+      return checkNotNull(imageId, "id").split("/").length == 3;
    }
   
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
index 7c5c97f..46f4ed4 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
@@ -16,8 +16,8 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
+import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.resourceGroup;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
-import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
 import static org.testng.Assert.assertTrue;
 
 import java.net.URI;
@@ -25,7 +25,6 @@ import java.util.Properties;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.domain.TemplateBuilder;
@@ -42,7 +41,6 @@ import org.testng.annotations.AfterClass;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Predicate;
-import com.google.common.cache.LoadingCache;
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.TypeLiteral;
@@ -54,19 +52,17 @@ import com.google.inject.name.Names;
 @Test(groups = "live", singleThreaded = true, testName = "AzureComputeServiceLiveTest")
 public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
    
-   private LoadingCache<String, ResourceGroup> resourceGroupMap;
    private Predicate<URI> resourceDeleted;
+   private String resourceGroupName;
 
    public AzureComputeServiceLiveTest() {
       provider = "azurecompute-arm";
+      resourceGroupName = getClass().getSimpleName().toLowerCase();
    }
 
    @Override
    public void initializeContext() {
       super.initializeContext();
-      resourceGroupMap = context.utils().injector()
-            .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
-            }));
       resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
       }, Names.named(TIMEOUT_RESOURCE_DELETED)));
    }
@@ -75,16 +71,10 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
    @AfterClass(groups = "live", alwaysRun = true)
    protected void tearDownContext() {
       try {
-         if (template != null) {
-            ResourceGroup rg = resourceGroupMap.getIfPresent(template.getLocation().getId());
-            if (rg != null) {
-               AzureComputeApi api = view.unwrapApi(AzureComputeApi.class);
-               URI uri = api.getResourceGroupApi().delete(rg.name());
-               if (uri != null) {
-                  assertTrue(resourceDeleted.apply(uri),
-                        String.format("Resource %s was not terminated in the configured timeout", uri));
-               }
-            }
+         URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(resourceGroupName);
+         if (uri != null) {
+            assertTrue(resourceDeleted.apply(uri),
+                  String.format("Resource %s was not terminated in the configured timeout", uri));
          }
       } finally {
          super.tearDownContext();
@@ -109,7 +99,7 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
+      AzureLiveTestUtils.defaultProperties(properties);
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
@@ -117,7 +107,8 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
    @Override
    protected TemplateBuilder templateBuilder() {
       return super.templateBuilder().options(
-            authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(keyPair.get("private")));
+            resourceGroup(resourceGroupName).authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(
+                  keyPair.get("private")));
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
index d4cbdb0..b00aa05 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
@@ -56,7 +56,7 @@ public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
+      AzureLiveTestUtils.defaultProperties(properties);
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
index d708723..885269d 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
@@ -16,7 +16,7 @@
  */
 package org.jclouds.azurecompute.arm.compute.extensions;
 
-import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
+import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.resourceGroup;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
 import static org.testng.Assert.assertEquals;
@@ -28,7 +28,6 @@ import java.util.Properties;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
 import org.jclouds.compute.ComputeTestUtils;
 import org.jclouds.compute.domain.ExecResponse;
@@ -43,7 +42,6 @@ import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Predicate;
-import com.google.common.cache.LoadingCache;
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.TypeLiteral;
@@ -56,30 +54,27 @@ import com.google.inject.name.Names;
 @Test(groups = "live", singleThreaded = true, testName = "AzureComputeImageExtensionLiveTest")
 public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTest {
 
-   private LoadingCache<String, ResourceGroup> resourceGroupMap;
    private Predicate<URI> resourceDeleted;
-   private ResourceGroup testResourceGroup;
+   private String resourceGroupName;
    
    public AzureComputeImageExtensionLiveTest() {
       provider = "azurecompute-arm";
+      resourceGroupName = getClass().getSimpleName().toLowerCase();
    }
    
    @BeforeClass(groups = { "integration", "live" })
    public void setupContext() {
       super.setupContext();
-      resourceGroupMap = context.utils().injector()
-            .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
-            }));
       resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
       }, Names.named(TIMEOUT_RESOURCE_DELETED)));
-      createResourceGroup();
+      createResourceGroup(resourceGroupName);
    }
    
    @AfterClass(groups = { "integration", "live" })
    @Override
    protected void tearDownContext() {
       try {
-         URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name());
+         URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(resourceGroupName);
          if (uri != null) {
             assertTrue(resourceDeleted.apply(uri),
                   String.format("Resource %s was not terminated in the configured timeout", uri));
@@ -108,7 +103,7 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
+      AzureLiveTestUtils.defaultProperties(properties);
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
@@ -122,11 +117,12 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
    public TemplateBuilder getNodeTemplate() {
       Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
       return super.getNodeTemplate().options(
-            authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(keyPair.get("private")));
+            resourceGroup(resourceGroupName).authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(
+                  keyPair.get("private")));
    }
 
-   private void createResourceGroup() {
+   private void createResourceGroup(String name) {
       Location location = getNodeTemplate().build().getLocation();
-      testResourceGroup = resourceGroupMap.getUnchecked(location.getId());
+      view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(name, location.getId(), null);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java
index e00880b..153df29 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java
@@ -18,9 +18,8 @@ package org.jclouds.azurecompute.arm.compute.extensions;
 
 import static com.google.common.collect.Iterables.get;
 import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.resourceGroup;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
-import static org.jclouds.compute.options.TemplateOptions.Builder.inboundPorts;
-import static org.jclouds.compute.options.TemplateOptions.Builder.securityGroups;
 import static org.jclouds.compute.predicates.NodePredicates.inGroup;
 import static org.jclouds.net.domain.IpProtocol.TCP;
 import static org.testng.Assert.assertEquals;
@@ -34,12 +33,13 @@ import java.util.concurrent.ExecutionException;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
+import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
 import org.jclouds.compute.ComputeService;
 import org.jclouds.compute.RunNodesException;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.SecurityGroup;
+import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.extensions.SecurityGroupExtension;
 import org.jclouds.compute.extensions.internal.BaseSecurityGroupExtensionLiveTest;
 import org.jclouds.domain.Location;
@@ -52,7 +52,6 @@ import org.testng.annotations.Test;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
-import com.google.common.cache.LoadingCache;
 import com.google.inject.Key;
 import com.google.inject.TypeLiteral;
 import com.google.inject.name.Names;
@@ -64,23 +63,20 @@ import com.google.inject.name.Names;
 @Test(groups = "live", singleThreaded = true, testName = "AzureComputeSecurityGroupExtensionLiveTest")
 public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGroupExtensionLiveTest {
 
-   private LoadingCache<String, ResourceGroup> resourceGroupMap;
    private Predicate<URI> resourceDeleted;
-   private ResourceGroup testResourceGroup;
+   private String resourceGroupName;
 
    public AzureComputeSecurityGroupExtensionLiveTest() {
       provider = "azurecompute-arm";
+      resourceGroupName = "sgelivetest";
    }
 
    @BeforeClass(groups = { "integration", "live" })
    public void setupContext() {
       super.setupContext();
-      resourceGroupMap = context.utils().injector()
-            .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
-            }));
       resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
       }, Names.named(TIMEOUT_RESOURCE_DELETED)));
-      createResourceGroup();
+      createResourceGroup(resourceGroupName);
    }
 
    @Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testAddIpPermissionsFromSpec")
@@ -104,7 +100,8 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
       Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
       assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
 
-      NodeMetadata node = getOnlyElement(computeService.createNodesInGroup(nodeGroup, 1, securityGroups(groupId)));
+      NodeMetadata node = getOnlyElement(computeService.createNodesInGroup(nodeGroup, 1,
+            options().securityGroups(groupId)));
 
       try {
          Set<SecurityGroup> groups = securityGroupExtension.get().listSecurityGroupsForNode(node.getId());
@@ -121,8 +118,8 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
       Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
       assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
 
-      NodeMetadata node = getOnlyElement(computeService
-            .createNodesInGroup(nodeGroup, 1, inboundPorts(22, 23, 24, 8000)));
+      NodeMetadata node = getOnlyElement(computeService.createNodesInGroup(nodeGroup, 1,
+            options().inboundPorts(22, 23, 24, 8000)));
 
       try {
          Set<SecurityGroup> groups = securityGroupExtension.get().listSecurityGroupsForNode(node.getId());
@@ -141,7 +138,7 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
    @Override
    protected void tearDownContext() {
       try {
-         URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name());
+         URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(resourceGroupName);
          if (uri != null) {
             assertTrue(resourceDeleted.apply(uri),
                   String.format("Resource %s was not terminated in the configured timeout", uri));
@@ -154,7 +151,7 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties, "sgelivetest");
+      AzureLiveTestUtils.defaultProperties(properties);
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
@@ -163,9 +160,18 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
    protected ProviderMetadata createProviderMetadata() {
       return AzureComputeProviderMetadata.builder().build();
    }
+   
+   private AzureTemplateOptions options() {
+      return resourceGroup(resourceGroupName);
+   }
+   
+   @Override
+   public Template getNodeTemplate() {
+      return view.getComputeService().templateBuilder().options(options()).build();
+   }
 
-   private void createResourceGroup() {
+   private void createResourceGroup(String name) {
       Location location = getNodeTemplate().getLocation();
-      testResourceGroup = resourceGroupMap.getUnchecked(location.getId());
+      view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(name, location.getId(), null);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/IdReferenceTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/IdReferenceTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/IdReferenceTest.java
new file mode 100644
index 0000000..e5426d7
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/IdReferenceTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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 org.jclouds.azurecompute.arm.domain.IdReference.extractName;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.Test;
+
+public class IdReferenceTest {
+
+   @Test
+   public void testExtractResourceGroup() {
+      assertEquals(extractResourceGroup(null), null);
+      assertEquals(extractResourceGroup(""), null);
+      assertEquals(
+            extractResourceGroup("/subscriptions/subscription/resourceGroups/jclouds-northeurope/providers/Microsoft.Compute/virtualMachines/resources-8c5"),
+            "jclouds-northeurope");
+      assertEquals(extractResourceGroup("/subscriptions/subscription/resourceGroups/jclouds-west"), "jclouds-west");
+      assertEquals(extractResourceGroup("/resourceGroups/jclouds-west2"), "jclouds-west2");
+      assertEquals(
+            extractResourceGroup("/resourceGroups/jclouds-northeurope2/providers/Microsoft.Compute/virtualMachines/resources-8c5"),
+            "jclouds-northeurope2");
+      assertEquals(extractResourceGroup("resourceGroups/jclouds-west2"), null);
+      assertEquals(
+            extractResourceGroup("resourceGroups/jclouds-northeurope2/providers/Microsoft.Compute/virtualMachines/resources-8c5"),
+            null);
+      assertEquals(
+            extractResourceGroup("/subscriptions/subscription/providers/Microsoft.Compute/virtualMachines/resources-8c5"),
+            null);
+      assertEquals(
+            extractResourceGroup("/subscriptions/subscription/resourceGroups//jclouds-northeurope/providers/Microsoft.Compute/virtualMachines/resources-8c5"),
+            null);
+   }
+
+   @Test
+   public void testExtractName() {
+      assertEquals(extractName(null), null);
+      assertEquals(extractName(""), "");
+      assertEquals(extractName("foo"), "foo");
+      assertEquals(extractName("/foo/bar"), "bar");
+      assertEquals(extractName("/foo/bar/"), "bar");
+      assertEquals(extractName("/foo/bar////"), "bar");
+      assertEquals(extractName("/foo///bar////"), "bar");
+      assertEquals(extractName("////bar"), "bar");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/83c0a3c7/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
index d976258..15231fd 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
@@ -24,7 +24,7 @@ import static org.jclouds.compute.predicates.NodePredicates.inGroup;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
-
+import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.resourceGroup;
 import java.net.URI;
 import java.util.Properties;
 
@@ -32,18 +32,15 @@ import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.Image;
 import org.jclouds.azurecompute.arm.domain.ImageProperties;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
 import org.jclouds.compute.RunNodesException;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.domain.Location;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Predicate;
-import com.google.common.cache.LoadingCache;
 import com.google.inject.Key;
 import com.google.inject.TypeLiteral;
 import com.google.inject.name.Names;
@@ -54,11 +51,9 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
 
    private static final String imageName = "imageFromRest";
 
-   private LoadingCache<String, ResourceGroup> resourceGroupMap;
    private Predicate<URI> resourceDeleted;
    private AzureComputeApi api;
 
-   private String resourceGroupName;
    private String location;
    private ImageApi imageApi;
    private Image image;
@@ -73,7 +68,7 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
+      AzureLiveTestUtils.defaultProperties(properties);
       checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
       return properties;
    }
@@ -83,9 +78,6 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
       super.initializeContext();
       resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
       }, Names.named(TIMEOUT_RESOURCE_DELETED)));
-      resourceGroupMap = context.utils().injector()
-            .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
-            }));
       api = view.unwrapApi(AzureComputeApi.class);
    }
 
@@ -94,10 +86,9 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
    public void setupContext() {
       super.setupContext();
       // Use the resource name conventions used in the abstraction
-      ResourceGroup resourceGroup = createResourceGroup();
-      resourceGroupName = resourceGroup.name();
-      location = resourceGroup.location();
-      imageApi = api.getVirtualMachineImageApi(resourceGroupName);
+      location = view.getComputeService().templateBuilder().build().getLocation().getId();
+      view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(group, location, null);
+      imageApi = api.getVirtualMachineImageApi(group);
    }
 
    @Override
@@ -107,7 +98,7 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
          view.getComputeService().destroyNodesMatching(inGroup(group));
       } finally {
          try {
-            URI uri = api.getResourceGroupApi().delete(resourceGroupName);
+            URI uri = api.getResourceGroupApi().delete(group);
             assertResourceDeleted(uri);
          } finally {
             super.tearDownContext();
@@ -122,11 +113,11 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
 
    @Test
    public void testCreateImage() throws RunNodesException {
-      NodeMetadata node = getOnlyElement(view.getComputeService().createNodesInGroup(group, 1));
+      NodeMetadata node = getOnlyElement(view.getComputeService().createNodesInGroup(group, 1, resourceGroup(group)));
       IdReference vmIdRef = IdReference.create(node.getProviderId());
       view.getComputeService().suspendNode(node.getId());
 
-      api.getVirtualMachineApi(resourceGroupName).generalize(node.getName());
+      api.getVirtualMachineApi(group).generalize(node.getName());
 
       image = imageApi.createOrUpdate(imageName, location, ImageProperties.builder()
             .sourceVirtualMachine(vmIdRef).build());
@@ -161,9 +152,4 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
       }
    }
 
-   private ResourceGroup createResourceGroup() {
-      Location location = view.getComputeService().templateBuilder().build().getLocation();
-      return resourceGroupMap.getUnchecked(location.getId());
-   }
-
 }


[30/50] [abbrv] jclouds git commit: [ARM] IpOption will allocate a public ip when a network is specified

Posted by na...@apache.org.
[ARM] IpOption will allocate a public ip when a network is specified


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

Branch: refs/heads/master
Commit: b0abfa4b9a2ce825ddef1ee82d1028fbed625ab0
Parents: 79daee3
Author: Andrea Turli <an...@gmail.com>
Authored: Wed Sep 13 11:59:37 2017 +0200
Committer: Andrea Turli <an...@gmail.com>
Committed: Wed Sep 13 14:10:19 2017 +0200

----------------------------------------------------------------------
 .../CreateResourcesThenCreateNodes.java         | 29 ++++++++++----------
 .../CreateResourcesThenCreateNodesTest.java     | 19 +++++++------
 2 files changed, 24 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/b0abfa4b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
index 4c712d0..fb832c1 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
@@ -16,15 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.compute.strategy;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
-import static org.jclouds.azurecompute.arm.domain.IdReference.extractName;
-import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
-import static org.jclouds.azurecompute.arm.domain.Subnet.extractVirtualNetwork;
-
 import java.util.Arrays;
 import java.util.Map;
 import java.util.Set;
@@ -34,7 +25,6 @@ import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
-import com.google.common.base.Optional;
 import org.jclouds.Constants;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
@@ -50,7 +40,6 @@ import org.jclouds.azurecompute.arm.domain.Subnet;
 import org.jclouds.azurecompute.arm.domain.Subnet.SubnetProperties;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork.AddressSpace;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork.VirtualNetworkProperties;
-import org.jclouds.util.Passwords;
 import org.jclouds.compute.config.CustomizationResponse;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.Template;
@@ -63,8 +52,10 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
 import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
 import org.jclouds.domain.Location;
 import org.jclouds.logging.Logger;
+import org.jclouds.util.Passwords;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
 import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -72,6 +63,15 @@ import com.google.common.collect.Multimap;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractName;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
+import static org.jclouds.azurecompute.arm.domain.Subnet.extractVirtualNetwork;
+
 @Singleton
 public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedIntoNameThenAddToSet {
 
@@ -219,14 +219,14 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
          throw new IllegalArgumentException("The options.networks and options.ipOptions are exclusive");
       }
       
-      if (!options.getNetworks().isEmpty() && options.getIpOptions().isEmpty()) {
+      if (!options.getNetworks().isEmpty()) {
          // The portable interface allows to configure network IDs (subnet IDs),
          // but we don't know the type of the IP configurations to be applied
          // when attaching nodes to those networks. We'll assume private IPs
-         // with Dynamic allocation and no public ip address associated.
+         // with Dynamic allocation and new public ip address allocated.
          ImmutableList.Builder<IpOptions> ipOptions = ImmutableList.builder();
          for (String subnetId : options.getNetworks()) {
-            ipOptions.add(IpOptions.builder().subnet(subnetId).build());
+            ipOptions.add(IpOptions.builder().subnet(subnetId).allocateNewPublicIp(true).build());
          }
          options.ipOptions(ipOptions.build());
       }
@@ -241,7 +241,6 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
             String resourceGroup = extractResourceGroup(ipConfig.subnet());
             String networkName = extractVirtualNetwork(ipConfig.subnet());
             String subnetName = extractName(ipConfig.subnet());
-            
             Subnet subnet = api.getSubnetApi(resourceGroup, networkName).get(subnetName);
             checkState(subnet != null, "Configured subnet %s does not exist", ipConfig.subnet());
             

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b0abfa4b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java
index f95430c..51a45af 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java
@@ -16,13 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.compute.strategy;
 
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import static org.testng.Assert.assertEquals;
-
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.compute.options.IpOptions;
@@ -35,6 +28,13 @@ import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableList;
 
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.testng.Assert.assertEquals;
+
 @Test(groups = "unit", testName = "CreateResourcesThenCreateNodesTest")
 public class CreateResourcesThenCreateNodesTest {
 
@@ -67,8 +67,9 @@ public class CreateResourcesThenCreateNodesTest {
       strategy(api).normalizeNetworkOptions(options);
 
       assertEquals(options.getIpOptions(), ImmutableList.of(
-            IpOptions.builder().subnet(netResource("/virtualNetworks/vn/subnets/foo")).build(), IpOptions.builder()
-                  .subnet(netResource("/virtualNetworks/vn/subnets/bar")).build()));
+              IpOptions.builder().subnet(netResource("/virtualNetworks/vn/subnets/foo")).allocateNewPublicIp(true).build(), 
+              IpOptions.builder().subnet(netResource("/virtualNetworks/vn/subnets/bar")).allocateNewPublicIp(true).build())
+      );
 
       // Verify that the code has validated that the subnets exist
       verify(api, subnetApi);


[38/50] [abbrv] jclouds git commit: Injectable current service principal

Posted by na...@apache.org.
Injectable current service principal


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

Branch: refs/heads/master
Commit: 6c759930d77f91376ac02923ca4e5b36468ac85b
Parents: 7368d58
Author: Ignasi Barrera <na...@apache.org>
Authored: Fri Dec 1 11:54:58 2017 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Fri Dec 1 14:21:22 2017 +0100

----------------------------------------------------------------------
 .../azurecompute/arm/AzureComputeApi.java       | 40 ++++++----
 .../arm/AzureComputeProviderMetadata.java       | 20 ++---
 .../arm/config/AzureComputeHttpApiModule.java   | 83 +++++++++++++++++++-
 .../arm/config/AzureOAuthConfigFactory.java     | 60 ++++++++++++++
 .../azurecompute/arm/config/GraphRBAC.java      | 35 +++++++++
 .../azurecompute/arm/config/OAuthResource.java  | 35 +++++++++
 .../jclouds/azurecompute/arm/config/Tenant.java | 34 ++++++++
 .../arm/domain/ServicePrincipal.java            | 66 ++++++++++++++++
 ...achineScaleSetIpConfigurationProperties.java | 38 +++------
 .../domain/VirtualMachineScaleSetOSProfile.java |  8 +-
 .../CurrentServicePrincipalApiLiveTest.java     | 34 ++++++++
 11 files changed, 396 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/6c759930/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index 8623580..afc8413 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -20,30 +20,34 @@ import java.io.Closeable;
 
 import javax.ws.rs.PathParam;
 
+import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
+import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
+import org.jclouds.azurecompute.arm.features.DeploymentApi;
+import org.jclouds.azurecompute.arm.features.DiskApi;
+import org.jclouds.azurecompute.arm.features.ImageApi;
 import org.jclouds.azurecompute.arm.features.JobApi;
+import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
 import org.jclouds.azurecompute.arm.features.LocationApi;
+import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
+import org.jclouds.azurecompute.arm.features.MetricsApi;
+import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
+import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
+import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
+import org.jclouds.azurecompute.arm.features.OSImageApi;
+import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
 import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
+import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
 import org.jclouds.azurecompute.arm.features.StorageAccountApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
-import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
-import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
-import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
+import org.jclouds.azurecompute.arm.features.VMSizeApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineScaleSetApi;
-import org.jclouds.azurecompute.arm.features.VMSizeApi;
-import org.jclouds.azurecompute.arm.features.OSImageApi;
-import org.jclouds.azurecompute.arm.features.DeploymentApi;
-import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
-import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
-import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
-import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
-import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
-import org.jclouds.azurecompute.arm.features.DiskApi;
-import org.jclouds.azurecompute.arm.features.ImageApi;
-import org.jclouds.azurecompute.arm.features.MetricsApi;
-import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
+import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
 import org.jclouds.rest.annotations.Delegate;
 
+import com.google.common.base.Supplier;
+import com.google.inject.Provides;
+
 /**
  * The Azure Resource Manager API is a REST API for managing your services and deployments.
  * <p>
@@ -237,4 +241,10 @@ public interface AzureComputeApi extends Closeable {
     */
    @Delegate
    MetricDefinitionsApi getMetricsDefinitionsApi(@PathParam("resourceid") String resourceid);
+   
+   /**
+    * Returns the information about the current service principal.
+    */
+   @Provides
+   Supplier<ServicePrincipal> getServicePrincipal();
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6c759930/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index 8849a1f..6848167 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -37,28 +37,29 @@ import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
 import java.net.URI;
 import java.util.Properties;
 
+import org.jclouds.azurecompute.arm.config.AzureComputeHttpApiModule.CurrentServicePrincipal;
 import org.jclouds.azurecompute.arm.domain.Region;
+import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
 import org.jclouds.azurecompute.arm.features.DeploymentApi;
+import org.jclouds.azurecompute.arm.features.DiskApi;
+import org.jclouds.azurecompute.arm.features.ImageApi;
+import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
 import org.jclouds.azurecompute.arm.features.LocationApi;
+import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
+import org.jclouds.azurecompute.arm.features.MetricsApi;
 import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
 import org.jclouds.azurecompute.arm.features.OSImageApi;
-import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
 import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
+import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
 import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
 import org.jclouds.azurecompute.arm.features.StorageAccountApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
-import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
 import org.jclouds.azurecompute.arm.features.VMSizeApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
-import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
-import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
-import org.jclouds.azurecompute.arm.features.DiskApi;
-import org.jclouds.azurecompute.arm.features.ImageApi;
-import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
-import org.jclouds.azurecompute.arm.features.MetricsApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineScaleSetApi;
+import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.providers.internal.BaseProviderMetadata;
 
@@ -124,7 +125,8 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(API_VERSION_PREFIX + MetricDefinitionsApi.class.getSimpleName(), "2017-05-01-preview");
       properties.put(API_VERSION_PREFIX + MetricsApi.class.getSimpleName(), "2016-09-01");
       properties.put(API_VERSION_PREFIX + VirtualMachineScaleSetApi.class.getSimpleName(), "2017-03-30");
-
+      properties.put(API_VERSION_PREFIX + CurrentServicePrincipal.class.getSimpleName(), "1.6");
+      
       return properties;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6c759930/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
index 991c738..8d417ca 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
@@ -16,7 +16,24 @@
  */
 package org.jclouds.azurecompute.arm.config;
 
+import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
+import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+
+import java.net.URI;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.handlers.AzureComputeErrorHandler;
 import org.jclouds.http.HttpErrorHandler;
 import org.jclouds.http.annotation.ClientError;
@@ -24,15 +41,31 @@ import org.jclouds.http.annotation.Redirection;
 import org.jclouds.http.annotation.ServerError;
 import org.jclouds.location.suppliers.ImplicitLocationSupplier;
 import org.jclouds.location.suppliers.implicit.FirstRegion;
+import org.jclouds.oauth.v2.config.OAuthConfigFactory;
 import org.jclouds.oauth.v2.config.OAuthScopes;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.AuthorizationException;
 import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.annotations.Endpoint;
+import org.jclouds.rest.annotations.OnlyElement;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.config.HttpApiModule;
+import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
 
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.inject.Provides;
 import com.google.inject.Scopes;
+import com.google.inject.name.Named;
 
 @ConfiguresHttpApi
 public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
 
+   private static final Pattern OAUTH_TENANT_PATTERN = Pattern
+         .compile("https://login.microsoftonline.com/([^/]+)/oauth2/token");
+
    @Override
    protected void bindErrorHandlers() {
       bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(AzureComputeErrorHandler.class);
@@ -46,10 +79,58 @@ public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
       bind(ImplicitLocationSupplier.class).to(FirstRegion.class).in(Scopes.SINGLETON);
    }
 
-
    @Override
    protected void configure() {
       super.configure();
+      bindHttpApi(binder(), CurrentServicePrincipal.class);
       bind(OAuthScopes.class).toInstance(OAuthScopes.NoScopes.create());
+      bind(OAuthConfigFactory.class).to(AzureOAuthConfigFactory.class).in(Scopes.SINGLETON);
+   }
+
+   @Provides
+   @Singleton
+   @Tenant
+   protected String provideTenant(@Named("oauth.endpoint") final String oauthEndpoint) {
+      Matcher m = OAUTH_TENANT_PATTERN.matcher(oauthEndpoint);
+      if (!m.matches()) {
+         throw new IllegalArgumentException("Could not parse tenantId from: " + oauthEndpoint);
+      }
+      return m.group(1);
+   }
+
+   @Provides
+   @Singleton
+   @GraphRBAC
+   protected Supplier<URI> graphRBACEndpoint(@Tenant String tenantId) {
+      return Suppliers.ofInstance(URI.create(GraphRBAC.ENDPOINT + tenantId));
+   }
+
+   @Provides
+   @Singleton
+   protected Supplier<ServicePrincipal> provideServicePrincipal(final CurrentServicePrincipal currentServicePrincipal,
+         AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
+      // This supplier must be defensive against any auth exception.
+      return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+            new Supplier<ServicePrincipal>() {
+               @Override
+               public ServicePrincipal get() {
+                  return currentServicePrincipal.get();
+               }
+            }, seconds, TimeUnit.SECONDS);
+   }
+
+   @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Endpoint(GraphRBAC.class)
+   @OAuthResource(GraphRBAC.ENDPOINT)
+   public interface CurrentServicePrincipal {
+
+      @Named("servicePrincipal:get")
+      @GET
+      @Path("/servicePrincipals")
+      @QueryParams(keys = "$filter", values = "appId eq '{jclouds.identity}'")
+      @SelectJson("value")
+      @OnlyElement
+      ServicePrincipal get();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6c759930/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureOAuthConfigFactory.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureOAuthConfigFactory.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureOAuthConfigFactory.java
new file mode 100644
index 0000000..9128b59
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureOAuthConfigFactory.java
@@ -0,0 +1,60 @@
+/*
+ * 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.config;
+
+import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
+import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.oauth.v2.config.OAuthConfigFactory;
+import org.jclouds.oauth.v2.config.OAuthScopes;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+public class AzureOAuthConfigFactory implements OAuthConfigFactory {
+   private final OAuthScopes scopes;
+   
+   @Named(AUDIENCE)
+   @Inject(optional = true)
+   private String audience;
+   
+   @Named(RESOURCE)
+   @Inject(optional = true)
+   private String resource;
+
+   @Inject
+   AzureOAuthConfigFactory(OAuthScopes scopes) {
+      this.scopes = scopes;
+   }
+
+   @Override
+   public OAuthConfig forRequest(HttpRequest input) {
+      OAuthResource customResource = null;
+      if (input instanceof GeneratedHttpRequest) {
+         GeneratedHttpRequest request = (GeneratedHttpRequest) input;
+         customResource = request.getInvocation().getInvokable().getAnnotation(OAuthResource.class);
+         if (customResource == null) {
+            customResource = request.getInvocation().getInvokable().getDeclaringClass()
+                  .getAnnotation(OAuthResource.class);
+         }
+      }
+      String oauthResource = customResource != null ? customResource.value() : resource;
+      return OAuthConfig.create(scopes.forRequest(input), audience, oauthResource);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6c759930/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/GraphRBAC.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/GraphRBAC.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/GraphRBAC.java
new file mode 100644
index 0000000..6853782
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/GraphRBAC.java
@@ -0,0 +1,35 @@
+/*
+ * 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.config;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Provides the Graph RBAC API endpoint for the current tenant.
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
+@Qualifier
+public @interface GraphRBAC {
+
+   String ENDPOINT = "https://graph.windows.net/";
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6c759930/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/OAuthResource.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/OAuthResource.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/OAuthResource.java
new file mode 100644
index 0000000..6e5a2df
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/OAuthResource.java
@@ -0,0 +1,35 @@
+/*
+ * 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.config;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Configures a custom OAuth resource for certain APIs and methods.
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.TYPE, ElementType.METHOD })
+@Qualifier
+public @interface OAuthResource {
+   
+   String value();
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6c759930/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/Tenant.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/Tenant.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/Tenant.java
new file mode 100644
index 0000000..5524361
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/Tenant.java
@@ -0,0 +1,34 @@
+/*
+ * 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.config;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Qualifies an object that describes the current tenant.
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
+@Qualifier
+public @interface Tenant {
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6c759930/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ServicePrincipal.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ServicePrincipal.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ServicePrincipal.java
new file mode 100644
index 0000000..2faba3f
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ServicePrincipal.java
@@ -0,0 +1,66 @@
+/*
+ * 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.Date;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+
+@AutoValue
+public abstract class ServicePrincipal {
+   
+   @Nullable public abstract String appId();
+   @Nullable public abstract Date deletionTimestamp();
+   @Nullable public abstract String displayName();
+   public abstract String objectId();
+   public abstract String objectType();
+   public abstract List<String> servicePrincipalNames();
+
+   @SerializedNames({ "appId", "deletionTimestamp", "displayName", "objectId", "objectType", "servicePrincipalNames" })
+   public static ServicePrincipal create(String appId, Date deletionTimestamp, String displayName, String objectId,
+         String objectType, List<String> servicePrincipalNames) {
+      List<String> servicePrincipals = servicePrincipalNames != null ? ImmutableList.copyOf(servicePrincipalNames)
+            : ImmutableList.<String> of();
+      return builder().appId(appId).deletionTimestamp(deletionTimestamp).displayName(displayName).objectId(objectId)
+            .objectType(objectType).servicePrincipalNames(servicePrincipals).build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_ServicePrincipal.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      
+      public abstract Builder appId(String appId);
+      public abstract Builder deletionTimestamp(Date deletionTimestamp);
+      public abstract Builder displayName(String displayName);
+      public abstract Builder objectId(String objectId);
+      public abstract Builder objectType(String objectType);
+      public abstract Builder servicePrincipalNames(List<String> servicePrincipalNames);
+
+      public abstract ServicePrincipal build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6c759930/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfigurationProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfigurationProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfigurationProperties.java
index ee23152..739dadf 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfigurationProperties.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetIpConfigurationProperties.java
@@ -70,49 +70,35 @@ public abstract class VirtualMachineScaleSetIpConfigurationProperties {
       final String applicationGatewayBackendAddressPools)
 
    {
-
       return builder()
-         .publicIPAddressConfiguration(publicIPAddressConfiguration)
-         .subnet(subnet)
-         .privateIPAddressVersion(privateIPAddressVersion)
-         .lbBackendAddressPools(loadBalancerBackendAddressPools)
-         .lbInboundNatPools(loadBalancerInboundNatPools)
-         .applicationGatewayBackendAddressPools(applicationGatewayBackendAddressPools)
-         .build();
+            .publicIPAddressConfiguration(publicIPAddressConfiguration)
+            .subnet(subnet)
+            .privateIPAddressVersion(privateIPAddressVersion)
+            .loadBalancerBackendAddressPools(
+                  loadBalancerBackendAddressPools != null ? ImmutableList.copyOf(loadBalancerBackendAddressPools)
+                        : ImmutableList.<IdReference> of())
+            .loadBalancerInboundNatPools(
+                  loadBalancerInboundNatPools != null ? ImmutableList.copyOf(loadBalancerInboundNatPools)
+                        : ImmutableList.<IdReference> of())
+            .applicationGatewayBackendAddressPools(applicationGatewayBackendAddressPools).build();
    }
 
    public abstract Builder toBuilder();
 
    public static Builder builder() {
-      return new AutoValue_VirtualMachineScaleSetIpConfigurationProperties.Builder()
-              .lbBackendAddressPools(null)
-              .lbInboundNatPools(null);
+      return new AutoValue_VirtualMachineScaleSetIpConfigurationProperties.Builder();
    }
 
    @AutoValue.Builder
    public abstract static class Builder {
       public abstract Builder publicIPAddressConfiguration(VirtualMachineScaleSetPublicIPAddressConfiguration publicIPAddressConfiguration);
-
       public abstract Builder subnet(Subnet subnet);
-
       public abstract Builder loadBalancerBackendAddressPools(List<IdReference> loadBalancerBackendAddressPools);
-
       public abstract Builder loadBalancerInboundNatPools(List<IdReference> loadBalancerInboundNatPools);
-
       public abstract Builder privateIPAddressVersion(String privateIPAddressVersion);
-
-      public Builder lbBackendAddressPools(List<IdReference> loadBalancerBackendAddressPools) {
-         return loadBalancerBackendAddressPools(loadBalancerBackendAddressPools != null ? ImmutableList
-                 .copyOf(loadBalancerBackendAddressPools) : ImmutableList.<IdReference>of());
-      }
-      public Builder lbInboundNatPools(List<IdReference> loadBalancerInboundNatPools) {
-         return loadBalancerInboundNatPools(loadBalancerInboundNatPools != null ? ImmutableList
-         .copyOf(loadBalancerInboundNatPools) : ImmutableList.<IdReference>of());
-      }
-
       public abstract Builder applicationGatewayBackendAddressPools(String applicationGatewayBackendAddressPools);
+      
       public abstract VirtualMachineScaleSetIpConfigurationProperties build();
-
    }
 }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6c759930/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetOSProfile.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetOSProfile.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetOSProfile.java
index 5593457..e417d5a 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetOSProfile.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineScaleSetOSProfile.java
@@ -249,14 +249,14 @@ public abstract class VirtualMachineScaleSetOSProfile {
          .adminPassword(adminPassword)
          .linuxConfiguration(linuxConfiguration)
          .windowsConfiguration(windowsConfiguration)
-         ._secrets(secrets)
+         .secrets(secrets != null ? ImmutableList.copyOf(secrets) : ImmutableList.<Secrets> of())
          .build();
    }
 
    public abstract Builder toBuilder();
 
    public static Builder builder() {
-      return new AutoValue_VirtualMachineScaleSetOSProfile.Builder()._secrets(null);
+      return new AutoValue_VirtualMachineScaleSetOSProfile.Builder();
    }
 
    @AutoValue.Builder
@@ -268,10 +268,6 @@ public abstract class VirtualMachineScaleSetOSProfile {
       public abstract Builder windowsConfiguration(WindowsConfiguration windowsConfiguration);
       public abstract Builder secrets(List<Secrets> secrets);
 
-      public Builder _secrets(List<Secrets> secrets) {
-         return secrets(secrets != null ? ImmutableList.copyOf(secrets) : ImmutableList.<Secrets>of());
-      }
-
       public abstract VirtualMachineScaleSetOSProfile build();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6c759930/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/CurrentServicePrincipalApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/CurrentServicePrincipalApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/CurrentServicePrincipalApiLiveTest.java
new file mode 100644
index 0000000..50a1e11
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/CurrentServicePrincipalApiLiveTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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 org.testng.Assert.assertEquals;
+
+import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "CurrentServicePrincipalApiLiveTest", singleThreaded = true)
+public class CurrentServicePrincipalApiLiveTest extends BaseAzureComputeApiLiveTest {
+
+   @Test
+   public void testGetCurrentServicePrincipal() {
+      ServicePrincipal currentUser = api.getServicePrincipal().get();
+      assertEquals(currentUser.appId(), identity);
+   }
+
+}


[39/50] [abbrv] jclouds git commit: Configure the Graph RBAC API and allow mocking service endpoints

Posted by na...@apache.org.
Configure the Graph RBAC API and allow mocking service endpoints


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

Branch: refs/heads/master
Commit: 3efce9a3a5bcbcb83a0abc79999fa8228f79f84c
Parents: 6c75993
Author: Ignasi Barrera <na...@apache.org>
Authored: Mon Dec 4 10:06:21 2017 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon Dec 4 10:12:16 2017 +0100

----------------------------------------------------------------------
 .../azurecompute/arm/AzureComputeApi.java       | 10 +++
 .../arm/AzureComputeProviderMetadata.java       |  4 +-
 .../arm/AzureManagementApiMetadata.java         | 10 ++-
 .../arm/config/AzureComputeHttpApiModule.java   | 52 ++++----------
 .../azurecompute/arm/config/GraphRBAC.java      | 19 +++++
 .../azurecompute/arm/features/GraphRBACApi.java | 50 ++++++++++++++
 .../arm/config/ParseTenantIdTest.java           | 50 ++++++++++++++
 .../arm/features/GraphRBACApiMockTest.java      | 39 +++++++++++
 .../VirtualMachineScaleSetApiLiveTest.java      | 32 ---------
 .../internal/BaseAzureComputeApiMockTest.java   | 73 ++++++++++++++++----
 .../src/test/resources/serviceprincipals.json   | 53 ++++++++++++++
 11 files changed, 302 insertions(+), 90 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/3efce9a3/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index afc8413..1f6b726 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -24,6 +24,7 @@ import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
 import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
 import org.jclouds.azurecompute.arm.features.DeploymentApi;
 import org.jclouds.azurecompute.arm.features.DiskApi;
+import org.jclouds.azurecompute.arm.features.GraphRBACApi;
 import org.jclouds.azurecompute.arm.features.ImageApi;
 import org.jclouds.azurecompute.arm.features.JobApi;
 import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
@@ -243,6 +244,15 @@ public interface AzureComputeApi extends Closeable {
    MetricDefinitionsApi getMetricsDefinitionsApi(@PathParam("resourceid") String resourceid);
    
    /**
+    * The Azure Active Directory Graph API provides programmatic access to Azure
+    * AD through REST API endpoints.
+    *
+    * @see <a href="https://docs.microsoft.com/en-us/rest/api/graphrbac/">docs</a>
+    */
+   @Delegate
+   GraphRBACApi getGraphRBACApi();
+   
+   /**
     * Returns the information about the current service principal.
     */
    @Provides

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3efce9a3/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index 6848167..335de98 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -37,11 +37,11 @@ import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
 import java.net.URI;
 import java.util.Properties;
 
-import org.jclouds.azurecompute.arm.config.AzureComputeHttpApiModule.CurrentServicePrincipal;
 import org.jclouds.azurecompute.arm.domain.Region;
 import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
 import org.jclouds.azurecompute.arm.features.DeploymentApi;
 import org.jclouds.azurecompute.arm.features.DiskApi;
+import org.jclouds.azurecompute.arm.features.GraphRBACApi;
 import org.jclouds.azurecompute.arm.features.ImageApi;
 import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
 import org.jclouds.azurecompute.arm.features.LocationApi;
@@ -125,7 +125,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(API_VERSION_PREFIX + MetricDefinitionsApi.class.getSimpleName(), "2017-05-01-preview");
       properties.put(API_VERSION_PREFIX + MetricsApi.class.getSimpleName(), "2016-09-01");
       properties.put(API_VERSION_PREFIX + VirtualMachineScaleSetApi.class.getSimpleName(), "2017-03-30");
-      properties.put(API_VERSION_PREFIX + CurrentServicePrincipal.class.getSimpleName(), "1.6");
+      properties.put(API_VERSION_PREFIX + GraphRBACApi.class.getSimpleName(), "1.6");
       
       return properties;
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3efce9a3/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
index d0c3e21..9c73e99 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.azurecompute.arm;
 
+import static org.jclouds.reflect.Reflection2.typeToken;
+
 import java.net.URI;
 import java.util.Properties;
 
@@ -32,8 +34,6 @@ import org.jclouds.rest.internal.BaseHttpApiMetadata;
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.Module;
 
-import static org.jclouds.reflect.Reflection2.typeToken;
-
 /**
  * Implementation of {@link ApiMetadata} for Microsoft Azure Resource Manager REST API
  */
@@ -43,9 +43,13 @@ public class AzureManagementApiMetadata extends BaseHttpApiMetadata<AzureCompute
    public Builder toBuilder() {
       return new Builder().fromApiMetadata(this);
    }
+   
+   public static Builder builder() {
+      return new Builder();
+   }
 
    public AzureManagementApiMetadata() {
-      this(new Builder());
+      this(builder());
    }
 
    protected AzureManagementApiMetadata(final Builder builder) {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3efce9a3/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
index 8d417ca..7ba23db 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeHttpApiModule.java
@@ -17,7 +17,6 @@
 package org.jclouds.azurecompute.arm.config;
 
 import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
 
 import java.net.URI;
 import java.util.concurrent.TimeUnit;
@@ -26,14 +25,10 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.inject.Singleton;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.core.MediaType;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.config.GraphRBAC.GraphRBACForTenant;
 import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
-import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.handlers.AzureComputeErrorHandler;
 import org.jclouds.http.HttpErrorHandler;
 import org.jclouds.http.annotation.ClientError;
@@ -43,28 +38,22 @@ import org.jclouds.location.suppliers.ImplicitLocationSupplier;
 import org.jclouds.location.suppliers.implicit.FirstRegion;
 import org.jclouds.oauth.v2.config.OAuthConfigFactory;
 import org.jclouds.oauth.v2.config.OAuthScopes;
-import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.AuthorizationException;
 import org.jclouds.rest.ConfiguresHttpApi;
-import org.jclouds.rest.annotations.Endpoint;
-import org.jclouds.rest.annotations.OnlyElement;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.config.HttpApiModule;
 import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
 
 import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
 import com.google.inject.Provides;
 import com.google.inject.Scopes;
+import com.google.inject.TypeLiteral;
 import com.google.inject.name.Named;
 
 @ConfiguresHttpApi
 public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
 
    private static final Pattern OAUTH_TENANT_PATTERN = Pattern
-         .compile("https://login.microsoftonline.com/([^/]+)/oauth2/token");
+         .compile("https://login.microsoft(?:online)?.com/([^/]+)/oauth2/token");
 
    @Override
    protected void bindErrorHandlers() {
@@ -82,15 +71,20 @@ public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
    @Override
    protected void configure() {
       super.configure();
-      bindHttpApi(binder(), CurrentServicePrincipal.class);
       bind(OAuthScopes.class).toInstance(OAuthScopes.NoScopes.create());
       bind(OAuthConfigFactory.class).to(AzureOAuthConfigFactory.class).in(Scopes.SINGLETON);
+      bindServiceEndpoints();
+   }
+
+   protected void bindServiceEndpoints() {
+      bind(new TypeLiteral<Supplier<URI>>() {
+      }).annotatedWith(GraphRBAC.class).to(GraphRBACForTenant.class).in(Scopes.SINGLETON);
    }
 
    @Provides
    @Singleton
    @Tenant
-   protected String provideTenant(@Named("oauth.endpoint") final String oauthEndpoint) {
+   protected final String provideTenant(@Named("oauth.endpoint") final String oauthEndpoint) {
       Matcher m = OAUTH_TENANT_PATTERN.matcher(oauthEndpoint);
       if (!m.matches()) {
          throw new IllegalArgumentException("Could not parse tenantId from: " + oauthEndpoint);
@@ -100,37 +94,15 @@ public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
 
    @Provides
    @Singleton
-   @GraphRBAC
-   protected Supplier<URI> graphRBACEndpoint(@Tenant String tenantId) {
-      return Suppliers.ofInstance(URI.create(GraphRBAC.ENDPOINT + tenantId));
-   }
-
-   @Provides
-   @Singleton
-   protected Supplier<ServicePrincipal> provideServicePrincipal(final CurrentServicePrincipal currentServicePrincipal,
+   protected final Supplier<ServicePrincipal> provideServicePrincipal(final AzureComputeApi api,
          AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
       // This supplier must be defensive against any auth exception.
       return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
             new Supplier<ServicePrincipal>() {
                @Override
                public ServicePrincipal get() {
-                  return currentServicePrincipal.get();
+                  return api.getGraphRBACApi().getCurrentServicePrincipal();
                }
             }, seconds, TimeUnit.SECONDS);
    }
-
-   @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Endpoint(GraphRBAC.class)
-   @OAuthResource(GraphRBAC.ENDPOINT)
-   public interface CurrentServicePrincipal {
-
-      @Named("servicePrincipal:get")
-      @GET
-      @Path("/servicePrincipals")
-      @QueryParams(keys = "$filter", values = "appId eq '{jclouds.identity}'")
-      @SelectJson("value")
-      @OnlyElement
-      ServicePrincipal get();
-   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3efce9a3/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/GraphRBAC.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/GraphRBAC.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/GraphRBAC.java
index 6853782..a7f8b4f 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/GraphRBAC.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/GraphRBAC.java
@@ -20,9 +20,13 @@ import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
+import java.net.URI;
 
+import javax.inject.Inject;
 import javax.inject.Qualifier;
 
+import com.google.common.base.Supplier;
+
 /**
  * Provides the Graph RBAC API endpoint for the current tenant.
  */
@@ -32,4 +36,19 @@ import javax.inject.Qualifier;
 public @interface GraphRBAC {
 
    String ENDPOINT = "https://graph.windows.net/";
+
+   static class GraphRBACForTenant implements Supplier<URI> {
+      private final String tenantId;
+
+      @Inject
+      GraphRBACForTenant(@Tenant String tenantId) {
+         this.tenantId = tenantId;
+      }
+
+      @Override
+      public URI get() {
+         return URI.create(GraphRBAC.ENDPOINT + tenantId);
+      }
+
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3efce9a3/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/GraphRBACApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/GraphRBACApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/GraphRBACApi.java
new file mode 100644
index 0000000..fe2bccc
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/GraphRBACApi.java
@@ -0,0 +1,50 @@
+/*
+ * 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.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.azurecompute.arm.config.GraphRBAC;
+import org.jclouds.azurecompute.arm.config.OAuthResource;
+import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.Endpoint;
+import org.jclouds.rest.annotations.OnlyElement;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+
+import com.google.inject.name.Named;
+
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
+@Consumes(MediaType.APPLICATION_JSON)
+@Endpoint(GraphRBAC.class)
+@OAuthResource(GraphRBAC.ENDPOINT)
+public interface GraphRBACApi {
+
+   @Named("servicePrincipal:get")
+   @GET
+   @Path("/servicePrincipals")
+   @QueryParams(keys = "$filter", values = "appId eq '{jclouds.identity}'")
+   @SelectJson("value")
+   @OnlyElement
+   ServicePrincipal getCurrentServicePrincipal();
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3efce9a3/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/config/ParseTenantIdTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/config/ParseTenantIdTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/config/ParseTenantIdTest.java
new file mode 100644
index 0000000..5894505
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/config/ParseTenantIdTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.config;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "ParseTenantIdTest")
+public class ParseTenantIdTest {
+
+   @Test
+   public void testParseTenantId() {
+      AzureComputeHttpApiModule module = new AzureComputeHttpApiModule();
+
+      assertEquals(module.provideTenant("https://login.microsoftonline.com/tenantId/oauth2/token"), "tenantId");
+      assertEquals(module.provideTenant("https://login.microsoft.com/tenant2/oauth2/token"), "tenant2");
+      
+      assertInvalid(module, "https://login.microsoftonline.com/a/b/c/oauth2/token");
+      assertInvalid(module, "https://login.microsoft.com/a/b/c/oauth2/token");
+      assertInvalid(module, "https://login.microsoftonline.com//oauth2/token");
+      assertInvalid(module, "https://login.microsoft.com//oauth2/token");
+      assertInvalid(module, "https://login.microsoftabc.com/tenant/oauth2/token");
+   }
+
+   private static void assertInvalid(AzureComputeHttpApiModule module, String endpoint) {
+      try {
+         module.provideTenant(endpoint);
+         fail("Expected an IllegalArgumentException for endpoint: " + endpoint);
+      } catch (IllegalArgumentException ex) {
+         assertEquals(ex.getMessage(), "Could not parse tenantId from: " + endpoint);
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3efce9a3/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/GraphRBACApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/GraphRBACApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/GraphRBACApiMockTest.java
new file mode 100644
index 0000000..20b95e2
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/GraphRBACApiMockTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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 org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "GraphRBACApiMockTest", singleThreaded = true)
+public class GraphRBACApiMockTest extends BaseAzureComputeApiMockTest {
+
+   public void testGetCurrentServicePrincipal() throws IOException, InterruptedException {
+      server.enqueue(jsonResponse("/serviceprincipals.json"));
+
+      ServicePrincipal sp = api.getGraphRBACApi().getCurrentServicePrincipal();
+
+      assertEquals(sp.appId(), "applicationId");
+      assertSent(server, "GET", "/graphrbac/tenant-id/servicePrincipals?$filter=appId%20eq%20%27mock%27&api-version=1.6");
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3efce9a3/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiLiveTest.java
index d827d70..ff93998 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineScaleSetApiLiveTest.java
@@ -17,7 +17,6 @@
 package org.jclouds.azurecompute.arm.features;
 
 import com.google.common.collect.ImmutableMap;
-import org.jclouds.azurecompute.arm.domain.DataDisk;
 import org.jclouds.azurecompute.arm.domain.Extension;
 import org.jclouds.azurecompute.arm.domain.ExtensionProfile;
 import org.jclouds.azurecompute.arm.domain.ExtensionProfileSettings;
@@ -69,8 +68,6 @@ public class VirtualMachineScaleSetApiLiveTest extends BaseAzureComputeApiLiveTe
 
    private String subscriptionid;
    private String vmssName;
-   private VirtualMachineScaleSetSKU SKU;
-   private String nicName;
    private String virtualNetworkName;
    private String subnetId;
    private Subnet subnet;
@@ -151,25 +148,6 @@ public class VirtualMachineScaleSetApiLiveTest extends BaseAzureComputeApiLiveTe
       return VirtualMachineScaleSetUpgradePolicy.create("Manual");
    }
 
-   private List<DataDisk> getDataDisks() {
-      List<DataDisk> datadisks = new ArrayList<DataDisk>();
-
-      datadisks.add(DataDisk.create(null, "10", 1, null,
-         null, "FromImage",
-         "None", getManagedDiskParameters(),
-         null));
-
-      return datadisks;
-   }
-
-   private StorageProfile getStorageProfile() {
-      return StorageProfile.create(getWindowsImageReference(), getWindowsOSDisk(), getDataDisks());
-   }
-
-   private StorageProfile getWindowsStorageProfile_Default() {
-      return StorageProfile.create(getWindowsImageReference(), getWindowsOSDisk(), null);
-   }
-
    private StorageProfile getLinuxStorageProfile_Default() {
       return StorageProfile.create(getLinuxImageReference(), getLinuxOSDisk(), null);
    }
@@ -178,21 +156,11 @@ public class VirtualMachineScaleSetApiLiveTest extends BaseAzureComputeApiLiveTe
       return ManagedDiskParameters.create(null, "Standard_LRS");
    }
 
-   private OSDisk getWindowsOSDisk() {
-      return OSDisk.create("Windows", null, null, null, "FromImage",
-         null, getManagedDiskParameters(), null);
-   }
-
    private OSDisk getLinuxOSDisk() {
       return OSDisk.create("Linux", null, null, null, "FromImage",
          null, getManagedDiskParameters(), null);
    }
 
-   private ImageReference getWindowsImageReference() {
-      return ImageReference.create(null, "Microsoft.Windows", "Windows2016",
-         "Enterprise", "latest");
-   }
-
    private ImageReference getLinuxImageReference() {
       return ImageReference.create(null, "Canonical", "UbuntuServer",
          "16.04-LTS", "latest");

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3efce9a3/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
index 1a83407..9d5eab0 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
@@ -15,30 +15,44 @@
  * limitations under the License.
  */
 package org.jclouds.azurecompute.arm.internal;
+
+import static com.google.common.base.Predicates.not;
+import static com.google.common.collect.Iterables.filter;
 import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
+import static org.assertj.core.util.Sets.newHashSet;
 import static org.jclouds.oauth.v2.config.CredentialType.BEARER_TOKEN_CREDENTIALS;
 import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
 import static org.testng.Assert.assertEquals;
 
 import java.io.IOException;
+import java.net.URI;
 import java.util.Properties;
 import java.util.Set;
 
 import org.jclouds.ContextBuilder;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
+import org.jclouds.azurecompute.arm.AzureManagementApiMetadata;
+import org.jclouds.azurecompute.arm.config.AzureComputeHttpApiModule;
+import org.jclouds.azurecompute.arm.config.GraphRBAC;
 import org.jclouds.concurrent.config.ExecutorServiceModule;
 import org.jclouds.date.DateService;
+import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.rest.ApiContext;
+import org.jclouds.rest.ConfiguresHttpApi;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 
 import com.google.common.base.Charsets;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.io.Resources;
 import com.google.gson.JsonParser;
 import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
 import com.squareup.okhttp.mockwebserver.MockResponse;
 import com.squareup.okhttp.mockwebserver.MockWebServer;
 import com.squareup.okhttp.mockwebserver.RecordedRequest;
@@ -48,8 +62,6 @@ public class BaseAzureComputeApiMockTest {
    private static final String MOCK_BEARER_TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSIsImtpZCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSJ9";
    private static final String DEFAULT_ENDPOINT = new AzureComputeProviderMetadata().getEndpoint();
 
-   private final Set<Module> modules = ImmutableSet.<Module> of(new ExecutorServiceModule(sameThreadExecutor()));
-
    protected MockWebServer server;
    protected AzureComputeApi api;
    protected ApiContext<AzureComputeApi> context;
@@ -62,25 +74,42 @@ public class BaseAzureComputeApiMockTest {
    public void start() throws IOException {
       server = new MockWebServer();
       server.play();
-      AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
-      context = ContextBuilder.newBuilder(pm)
-              .credentials("", MOCK_BEARER_TOKEN)
+      
+      context = ContextBuilder.newBuilder(testProviderMetadata())
+              .credentials("mock", MOCK_BEARER_TOKEN)
               .endpoint(server.getUrl("/").toString() + "subscriptions/SUBSCRIPTIONID")
-              .modules(modules)
+              .modules(setupModules())
               .overrides(setupProperties())
               .build();
       api = context.getApi();
       dateService = context.utils().injector().getInstance(DateService.class);
    }
    
+   protected ProviderMetadata testProviderMetadata() {
+      // Omit the default HTTP API modules to allow overriding
+      Set<Class<? extends Module>> defaultModules = newHashSet(filter(
+            new AzureManagementApiMetadata().getDefaultModules(),
+            not(Predicates.<Class<? extends Module>> equalTo(AzureComputeHttpApiModule.class))));
+      return AzureComputeProviderMetadata.builder()
+            .apiMetadata(AzureManagementApiMetadata.builder().defaultModules(defaultModules).build()).build();
+   }
+
    protected Properties setupProperties() {
       Properties properties = new Properties();
-
       properties.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString());
       properties.put("oauth.endpoint", "https://login.microsoftonline.com/tenant-id/oauth2/token");
       return properties;
    }
 
+   protected Set<Module> setupModules() {
+      ImmutableSet.Builder<Module> modules = ImmutableSet.builder();
+      modules.add(new ExecutorServiceModule(sameThreadExecutor()));
+      // Override the default HTTP module to accomodate custom bindings for the
+      // hardcoded endpoints such as the Graph RBAC API one.
+      modules.add(new TestAzureComputeHttpApiModule(server));
+      return modules.build();
+   }
+   
    @AfterMethod(alwaysRun = true)
    public void stop() throws IOException {
       server.shutdown();
@@ -107,21 +136,22 @@ public class BaseAzureComputeApiMockTest {
       return new MockResponse().setStatus("HTTP/1.1 202 Accepted");
    }
 
-
    protected MockResponse response204() {
       return new MockResponse().setStatus("HTTP/1.1 204 No Content");
    }
 
    protected MockResponse response202WithHeader() {
       return new MockResponse()
-              .setStatus("HTTP/1.1 202 Accepted")
-              .addHeader("Location", "https://management.azure.com/subscriptions/SUBSCRIPTIONID/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1SVEVTVC1DRU5UUkFMVVMiLCJqb2JMb2NhdGlvbiI6ImNlbnRyYWx1cyJ9?api-version=2014-04-01");
+            .setStatus("HTTP/1.1 202 Accepted")
+            .addHeader(
+                  "Location",
+                  "https://management.azure.com/subscriptions/SUBSCRIPTIONID/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1SVEVTVC1DRU5UUkFMVVMiLCJqb2JMb2NhdGlvbiI6ImNlbnRyYWx1cyJ9?api-version=2014-04-01");
    }
 
    protected String stringFromResource(String resourceName) {
       try {
-         return Resources.toString(getClass().getResource(resourceName), Charsets.UTF_8)
-                 .replace(DEFAULT_ENDPOINT, url(""));
+         return Resources.toString(getClass().getResource(resourceName), Charsets.UTF_8).replace(DEFAULT_ENDPOINT,
+               url(""));
       } catch (IOException e) {
          throw Throwables.propagate(e);
       }
@@ -137,10 +167,27 @@ public class BaseAzureComputeApiMockTest {
    }
 
    protected RecordedRequest assertSent(MockWebServer server, String method, String path, String json)
-           throws InterruptedException {
+         throws InterruptedException {
       RecordedRequest request = assertSent(server, method, path);
       assertEquals(request.getHeader("Content-Type"), "application/json");
       assertEquals(parser.parse(new String(request.getBody(), Charsets.UTF_8)), parser.parse(json));
       return request;
    }
+   
+   @ConfiguresHttpApi
+   private static class TestAzureComputeHttpApiModule extends AzureComputeHttpApiModule {
+      private final MockWebServer server;
+      
+      public TestAzureComputeHttpApiModule(MockWebServer server) {
+         this.server = server;
+      }
+
+      @Override
+      protected void bindServiceEndpoints() {
+         // Override the hardcoded service URIs to allow mocking service endpoints
+         bind(new TypeLiteral<Supplier<URI>>() {
+         }).annotatedWith(GraphRBAC.class).toInstance(
+               Suppliers.ofInstance(URI.create(server.getUrl("/graphrbac").toString() + "/tenant-id")));
+      }
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/3efce9a3/providers/azurecompute-arm/src/test/resources/serviceprincipals.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/serviceprincipals.json b/providers/azurecompute-arm/src/test/resources/serviceprincipals.json
new file mode 100644
index 0000000..cdeefa6
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/serviceprincipals.json
@@ -0,0 +1,53 @@
+{
+  "odata.metadata": "https://graph.windows.net/tenantId/$metadata#directoryObjects/Microsoft.DirectoryServices.ServicePrincipal",
+  "value": [
+    {
+      "odata.type": "Microsoft.DirectoryServices.ServicePrincipal",
+      "objectType": "ServicePrincipal",
+      "objectId": "objectId",
+      "deletionTimestamp": null,
+      "accountEnabled": true,
+      "addIns": [],
+      "alternativeNames": [],
+      "appDisplayName": "jclouds",
+      "appId": "applicationId",
+      "appOwnerTenantId": "tenantId",
+      "appRoleAssignmentRequired": false,
+      "appRoles": [],
+      "displayName": "jclouds",
+      "errorUrl": null,
+      "homepage": "https://jclouds.apache.org",
+      "keyCredentials": [],
+      "logoutUrl": null,
+      "oauth2Permissions": [
+        {
+          "adminConsentDescription": "Allow the application to access jclouds on behalf of the signed-in user.",
+          "adminConsentDisplayName": "Access jclouds",
+          "id": "id",
+          "isEnabled": true,
+          "type": "User",
+          "userConsentDescription": "Allow the application to access jclouds on your behalf.",
+          "userConsentDisplayName": "Access jclouds",
+          "value": "user_impersonation"
+        }
+      ],
+      "passwordCredentials": [],
+      "preferredTokenSigningKeyThumbprint": null,
+      "publisherName": "Default Directory",
+      "replyUrls": [
+        "https://jclouds.apache.org"
+      ],
+      "samlMetadataUrl": null,
+      "servicePrincipalNames": [
+        "https://jclouds.onmicrosoft.com/jcloudsid",
+        "applicationId"
+      ],
+      "servicePrincipalType": "Application",
+      "tags": [
+        "WindowsAzureActiveDirectoryIntegratedApp"
+      ],
+      "tokenEncryptionKeyId": null
+    }
+  ]
+}
+


[41/50] [abbrv] jclouds git commit: Add Azure KeyVault support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultsamplesecret.txt
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultsamplesecret.txt b/providers/azurecompute-arm/src/test/resources/vaultsamplesecret.txt
new file mode 100644
index 0000000..d0d159e
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultsamplesecret.txt
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAvZiOgV6b4EmGiasBskXYnTaRyWzBHBGnWB11BzFN3FGigfWx
+VvjI7Ox1SHTx+vGsnjbqQPvIP4JnPEsNcWLyHa6tNAcnj/M7BuyIwdD5+Hvs6kOe
+PuSOJUf8dRjPMUpr6rcUcBmmOwTnKOH4rdpb6jXNnuCIHP+lgXCeRWveZ62TjEB+
+9aB8W8UHH854FGebiUd/aY0tpCFC7wkWz3KbgmjmY2vSe2U98Yj4+l/IWydIZ7ON
+LicteEEIGbNM0o2QSYhQBCJSw5RixDpPlrUUB094qgqUOyW0k8PvjibGxxTh0LYy
+WqWydPF0XaqFRQ6v36UvEiVGwzVsLwsJL/QVtQIDAQABAoIBAEJ6790lE3s9zNMR
+B3M/UoktzUjXvY7eEdOv4I05GJgcd+MiB6D7c1jAQQ+7Ee5wN5rynolSwBCk5RYb
+KweLLmKCEXGg4Jp1K0luPzXW1Q/wRE6Qjzh2Y/FmoHtey6f49IZE1AHKvKMNQRDw
+y4YKfxhM7WC8Un34lkwg9R5aiI3JkOG9/yNkOGrJfQnGUKt+AOAdu6fNYsRLWAPo
+G3vWSNIgwaG5WL5cKd1gacbGBlc6tLB7+LrZuNrqln5ibTtN6QJvRF9KfOrMSvxy
+L/xiHRpyzec/jrxJxAIIwFHiw2jbLdxNqDaVPFA6X1Cks4fvY40KymOS8Ecmkgx4
+C6/ZqLECgYEA38rL8zmbJRRWgrxSoROucaN/9DyvE8Hd97s1zf3I0LIF+GI3JdcN
+DV5O5VDIgQ7QZ55lOaTqJ0f2fOQZF1UbTU1gBUHVF6j1nv6Xic3OV+ZmhTMbt0Op
+WxPaKup6dkNEAe/Xg0p308r8xw/psh4/gjL1ICHwycjUlz9FQz8FLGsCgYEA2OHc
+/F4vAdK04U4w6AyivuJdIsDAks1ikl+3TqgzyesPg+DpKVNSy6DhraDFKdRqWhbK
+DqigTud8TVk9kmyF3WIb1BDf4IrxlTK08s6Jf25QA/lBlwIst3rejqWwRBY2fJp4
+O8hU31xNLd8nZq8tKYaP+yvyI6fSC+9ZIgyATl8CgYBtTlYzZG2cvMRMcsNBHaXU
+p3E1z/YLhmNuPqhXBp/xHyK/YOliuBkN8IREiSKFtsCf+8OhViVwLjv8YETJGq6N
+IT/HEZKNTd86W0uU6UrhsA1e/cmJx6iObbHfyEssPEqZT5ZJ8DN65Oh2KhWRBCks
+5MrJeQps5ITBowunfr5+JQKBgBln09goPD9tbEzcOPRlzoanw5s3kxdfQcW9up5X
+K8HibC3ZodZ6cT9zOBx7sbzlqhOlicPP0v+LNE9nPcQyPDgjrvjXhTIrdIMyrmmm
+8gpgZLUidKF42r4fgYSaOhyvsXBFNAJkxDRp/ox6EIaBzLuJjMIycqnklcFaJ0nK
+xxjnAoGAU/3jRok74Yn0MY183UCXICf/WxVYzwEi3cyRWVh6gAo2ExNye97rau/B
+Y2woAcVxEN9h1HNirq8Z2AwrZKd/BcBnvulZqECeH5zBQ0W56ADX72r+lzOAxTJa
+U1AIlNCIkfsQ5CpIoYsVoNEM8P+GyS8B9kaEmk/FVKldRTKJqkI=
+-----END RSA PRIVATE KEY-----
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultsecretbackup.txt
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultsecretbackup.txt b/providers/azurecompute-arm/src/test/resources/vaultsecretbackup.txt
new file mode 100644
index 0000000..877d28c
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultsecretbackup.txt
@@ -0,0 +1 @@
+KUF6dXJlS2V5VmF1bHRTZWNyZXRCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLlFLelA2anZVR0Y5X1M3UU8tRkZDTHIyNGp0RXJuandkQThNZUtsSGE1MmhvS01rNjdiOHQyckZhNTJ6dGR2and1d1I3VWh4RldRLUpuOHk3YlJiNlYtcTlUYl9iV3E5clplUlhpUy1jdUhPak9ONHB1bHd1cVVmQkJOU2V3NlJGUXpOUzRrQks3RmxQSGZpQVRRaUUtLTc1cnZIM0dMTEdDd25KTkxIUDNTR0FtWlR1dXo0bTN6X1owR3RsZUU5XzFZT3pqczU1UmJFNEdOTC0tWDhDWnlRWmVFNGdGRXZ2WmFrYkRXTk5hOWd6SnBUNlNOTm5tcGtpMFZocGxaNGdzWmNmR29xQktZNF8wTS1WTmpIbkZ5QUlySXdsSTNjZkIzWUVCbHJ3X1A1QXhQVFFvNDJNa1pETmNKYjFwaGh0c1phaTNLcWRxT0E0ZEVWNVZWQ1VNZy5fTkN5eTNJSS1VV1VtWDB4UXhTVnNRLjJkbEFpUEpSa3NlenNVTEZocTE3ZmdCWm11XzBBaU5GUWkyTU8zMnlVanpEMjMxQlY0bHhwU21ZMmI1bGdsTXlYQzNtYy1PT2VmcVNseXdqMlcwTllOYzJKOUg4MzFHc0VCdXZ1SS1BWEQ3dzdocGRNTG5VaG5DQ0RUQTJYY0ZTZ2lXTWMzMFFISHUzRi1KcDh2VGU1QUk5R1ljelEzSFVPRjJOREpjRERoLU9CNFFJRlZWMS0zWEJkeS1uOWR5MjlSY0FwNEo4WHRPMjZxN2dJa3BDT1JxMTVuOXZHd3ViV
 lZhdGhfMlZwM3p1ZEJPX3k5SlFTVVYxMW1jZFVIQXNCVGxFMU5xYkZaU0lfX093NTl6ZktGRTVTMnZrYWl6a1RFbXFVQi1EcTVnMnMxQ05PcUdUNk1wQWNiSEtUNTNSajNZN2RlOFlBckZIMlNSZF9udUV6Q09PMnAxeFpFUjh4c2RIRjlDM1Nnc3ZRQzIzX3BfeDBIR1RfbWY5V3B4amZOWF9Bd1E5NWNLZ0JOdU1ENEZ1TTdWTmpKc1JaSGtvM2tNTlJ5N3BybkhhaVd5aHRiVV9ic0w3X3FRa1JGNEl3eGFzUlh6M3RtZzYyT2tCWl82MEMyRE11Q0pIZWtqSnI5SGJDeGp6Z1lGMjVmRDhDTk00YmNaRV9ma1Z4Y2lVVklWU2lvemREX3owTFBMY09paVp6dTNIWGIxekplZkJsVXduc1NBT0RZa2lWbjJPMjFOMHpkRGwwMjNPSnJTdWQycWo1UkEtVTlsVWRxU0w1QUltN1ZaMTFSVzh5clpkWXc4NFJTejVySldRSm1sVW54RzJHb3lMMTFaQkJacXY5bEJ5Wnd3SDN6ZGNDZWFRQWM0LVZJWjQ5NzBfTC1tT2paNUFwdXI4UERHVDIydkNKdEw1cVVaNGJabThBeXQ0NDFEX2o2cG16NzRUWWlIU210ZnlJcnNvRTMzbG9QM0xGdTFKMklXLXJTdk9HUElveEx1ai1ZMkNKMENYTk1lR0UyQVNhOEY5RmY3enhVLVRkbVZneWpfYi1EY05XUmVJZUMyTEF4OV9EWDY0QlRJV0pNSFc3a2plbjRkem9kajMzbjM1aFU0UUVmRVM0a2pmUUtMVENrYnRlWXliVUlQWmhaa3BDRzRpTVBQSVpTRVdqU2RMckl6NlRYN3FJZHFHcE1UYk9zeld3eWc2dzI1WTd4aDFvelY2RjJEOFpKR3FiZjhQZTVDRWtIcE5LeC1kNExUTzNsOWZlZVd6RFRwTzRnTWpBZ1RNdHBqdX
 RqT2xhSEYyN1JLaVNGWU82eFNQY0ZVb3JGMlZKRERlQUxZSk9Pb0JOMkhpalJ1Y0R5bWR3NUtzNHBZTmZvV3dCeHVnbjBPenJoNVFIS2Q3dWpoUll1XzhkLWd2RVNKQzNJY3JZWFI1aFhxaUp5WGVNMGtULWlnRUFQRFVmSXE0cjJiRW5iZ0RhdUZrN2syekZzXzZzeGZ4Ty1TNEp0alp2UkJia0lnZm1WdVB5OXZTQy02QUl0aEctMW5OUE9PNG1oak9ON2EzVUdzQVpvREg0T1RFczA3ajJMQ092VGdqX05PN1pJcEt6LWhyU0daSXdCdjlRdHJ5NjY4US1kTUpRZzAzRi1UXzZlX1htc1BWRWt1RWdaSzdnS092STNzdjk4Y0VVODFiVEZfNjQ3cmE5bjN6NHdnbmZwVE1lWEhMQ1JWeGpKbHJURmxJcW9wbkdZeHlQdm5iVXBzb3A2NktHbVAtTEpTeERjNlJJckpuQ2drbjN1OGN0c25NZWxuWHZSeGZFdFRsNnkyendUV3ZSdnVEcVR1UFphQXdNVmllbTdaaXZqNTdMYjNHT3RUcjBxQXNrMC15dHN2TkpmY19tYTEydVlUWll1b2RCM2ZoVFBITjFaclFoQzdiWDVHdXFDUFFDQXFuenJjT0lESDIweTFlZHAxam1ZdTFyZThPaG9yMDRiVWhLa2stcUVVdEVsZTFqYzFTckNuWkEyMlRZMFNVYkxkVm1hb2dyaUJfckpackVaM0tneGFaSjNnZ3FQd2NhSW0wNUVoMDQwYUpUa20xOWdzRzVCNEExQ2dDWHRMOGhUMFl4TmNneW9tT0dnRzd2Q2FzdW43WGhtdjJZLWROWVNrZzRZbzlfdkktWWlmZEp2MnhJVWY3eGFvS1RRRzY4NkNzaE0zTkVubFRWb1FjaWxjaXllaHc3RkpiMnYyTDFNV0tlamRWM2dPNjIyVjZ3QXV4MW9GdXJhdWZORzh2cnkyS2NwczF
 OUzBWeFJObU9mNDFkbFRhSkljUmFJM2tSbUg5UkpTakJZcnA1Y1ZzZWh5WGVaQXpnU2JzUlg0eGp6LURJSGVPa1dRS05HMlZvTnloZ3BZS05FVnlNN2dkdFBWTUo3TmlkVE9PM3BaYTBMeV9GaUhHLXc0dkUwTTR0X1ZpOFhvRzBFbWhJcjBWdmRvN0RGUXVUbmdoblRGVnpreEtyRlJSZzRMWkhCNzR2Z1BycTVTNGxTV2hlZGRfekRad2JVeUxJY1NXWmk3QzlpWDctczNHeGp2UjNGekxJT3NuSXUxVHpaQ3B4a0d4ZGkzU1VyS1c0NGlTaDM3eGNmaEpsNDVDcTQ5N1pQQmo1eVA0UmYwazVTS3djM1JvOUJoUXN0aUdzVk5qMlIzcmpHTHZfOEwtUHNxOG1IYTZKZHVvaEtRbEVQT1hYNzZ5aDdab05KUUZhemRNRWV3eVJNOGQ3eUZIcFc0M3RTZTA4Mi1BUmRjcW55OXFZRmJLMFJfV3dNTDlOQkFpNWxjQldUSms2ZHJXN1RPRmJ2eDFyZ0p5cUcza2w4TEdwRExheFNfaFhXZVRxSy1YS3pVRk9zNjA4WEp6U2NhVE1xay1QTVZIdkN5c3Vjci1mOFN3SF9wdks0bTNQYWprcGVOMjl3dmVZdUp1X1ZKZHlPNE9yY043cnRYVXR3VWNSblBzNUNXYWF0N1RfUWhnZ1VTdHBZczBJTlVuNXU2Rm5oNGVsUUxTTEhvdWZDdE9RekpDV0VVd3N2TWdkdkc2cEUzU2FZU244OFd6YzdMbGctZEVMeERLQXE1dmI1bXFleXAyem9hZFhJa20wWks5amlwdnBZdmQyRlFnNE50NF9nOUo3WTRoeVp3TjFWdXlqQ2YyUkFpMzJXZlNid1B4ZmdVdjhVVkktcUlKWjc5TjNQOTFnWnB4X2xxdF9aNFB0bzIwTTZqamw0MGkwUXRwMUdaRU5hbHoxN00zbFRBUl81WkY5Ql81
 dTIwN1FGbGh3UDYzbFRNMF8td1lCOVBzV2VtdGJUTEZYZmJFU0t6VGVzckVzQWwzQkVDMFotSndhMno3cEc3VHhvQWhON21hWDdKajVjbWtzdmJjVk05MENSNTVwbmtwOUM0Tm1BRWM2amw1dXRBSGlGOEdaV1A1V2lGVFFwVTBpYktXLUVycEMyblVvRVBmbFRPbVowM2lzaFNLbnZTSUFUQjBMSW95S1lhYm9tcU5NWkZhWDV5OWVjTGtFdmlmYS04dW8zRzNYSWFhQWk3TE5YRXpqQm9iZWlVSzBFeGJxaGd0VzNvbE85V1o1MGxqOWw5UXpGV3FWOGRiUThOeTdkdzRnT2wzNl93ZVNrbHJ3b19VVDA0Sm9Oc0IzOWFrUnJaWkdzaXJuamR1T0F4RWZaaXRLdHdTdkpZSzRtV0huSk5uRENMVlo2cVpzVG50NThjVjQ2cFY3T1FxckNpVnlQREU3Y1N0RW5neXhEbzRZdlpibDNrNndkaGxYOXAwZXNaOUdXbHNxcXlGVUJCc19QbVN2UUd6djZ3bDlWSnk4WnNKYmpIdlkwclZOUFJnN2FYTjlNOElsVWpia3B6RmdqY0VPZVVrZ1M5UFp5RURLYUw5U2NjeFJFbjI1OUR3MDFJZFJPS2U5Mnp3U1hSQUJlbVhBcVRaSGZPd1Z2VDBUS2JnWkwxcE5vb242NWRMR0hKZ2dYWmt6SjVHT3dvbFRkYkEwczVkaXRQZllxU3ZwQmpmVHpfQTZhTWl3bmFnamlET0QzT2doeTQxc1Q2UDdTWTFxanpfWkxjZ1puc1djWDlkOWc4TkpzZ1had184d2dUY3hRdW1TM3oxVTYxX2dlbndBNzNPaEs5MWl5YW90Z2ZySWNzOWxodm1taEcwRC1KX3lkQUxfdXNROWc0dHRlN1ptN0hMZDZOb1pCYnJFTkZ0ODRmejdJbjJxMXItM1lsYk9kMm1xRXIxZUdZMmtCTlh1eFc0XzlVZ
 VFOZER5UHZPRFR0Ni1mR3FuMF9sd2dYOXJldUxsRzY1UjFKY29yMnczWmZBLWU3SEN3Y2tCTTBEcmhjZmwxdmhtcVY4WXpMcHBxUUhPa1F2YUpMNHE2ZG1ZS0thZmhGbXcxVk1qSnp5UWswUVNzazFWUGdzUmpta3l0YmpjZjRoenJNdVRMU0VQTGZVWGVPOEYzbEdLNE03bWlhblRPQ0xXSmRNWnc5dFlKSHVTQ0g3SjhZOUVwNS1XWTRBeUZlaFJfaDVSNHVYdlBPUmUzSzZQcWJibHlaMEJuclpCcDZnTUNvNVcwZkd5ZEdiQ1N6dzUzVndsY3FEWnJlb0p0Rk5pZFNzdTBtLUFub1g0SWxsSFFnYVB4SnlLYWRPSWpvalNKMnZTTTZCYXRkci1pR3VTbDJSZmswLXkyX3FFeDZRakNOQWFXaWNvM2RsS3VIY0h6TU13YzVXT1J4bzdweXdWYmtOUmpoOUVPZlkxSW51Tk11SjdfYWt2T0V5MGpMVXlCc04zR0hrTzlEUExFLTk2bVlIMWd6R19IbGQ5aVRpOWcxZTB5WjdBVkNEQzBoaVRZMXB5V0pVanpGVE91clJaYW5qOWl5MWdjcFdpeFVPN2xiWjl2aHFhdHg0VUh4VFRneS1IbUcydmRTYjhJbGl2bHNqLXVpM3dxUjBYeVNXRDFVYmVJUFVIZk15bTR2bXkzdkIyWEJKMEJnTF80bkx2VWQ2MEpFdXI1Z0ZOSUUtR0RSY0JwSkdPZXN4b1lyQktYU1I2QUd1UG84b2ptemFudUFIaF83OTI5OWg2aDdtN3JRZ0NxYzJ0Wjg1dU9YVHNzZzRYSW1kVjdCN3ZrcHRlUmt5WjZEQ1RFYW5GRmNvWEJzSThYMVFZeFFDRzgtdzltYlppTHNiRGN6bVV5Z3RiRkNQUXludjByclNiRzFUUWtmZnk4UGVfT0tRYkxSdWJNNG55dmZxWG81X21FcXA0T1dzMlJSMDhiSE
 9YTWpDU0FlYUwyaC1RRjg2MmRrLUNpV05ZSVVuUHhTYWkyWTEzeGVqVklwYkI1YkZzaVUzTWJmY2pyNnduRUVuMmhzWGx1aGpWVXFtUzNIOEZwZDFkS0pSa1lzM2NWZWRHTEhaRFZRM0hTWHlBWk1FbXNzX01kTUlGMFZhUjU0WTU3QXhhcnR5QUFmZy1OWWtkNVhtVkxPQWJnRFdCMzdrbEVPVEZCYXV4SGg4dXJjVk9neVF6Z1RNcTIwTWpEUzhzaDlZLUNHNUxSRHJiYVlRU2ZoR0VSYVFYcFpuVEdWX20tcDFpWU1zMEMzRFBJanMxSWIxZVR4X0lJbTFPRlBGOWcwWVJsbXFCdkx2bGtGeExqM0t2SGxQVEUwaUYyZ1JaMmN4NUMtckJGZ0dXaU1hRUQzdjcxTW0xQlFJeklaY1lfUUI5V3FsWEVaSmJWZHNZc0FmNm93eW9XckpVQUszTEswclRPaEdNS2VaUzlzUGxvZWU4T0x2OTluc2wxRUM0Z3F2MHJqdk9JQ0pVR0kwb1R1dXV5enhSbU41cHJtX2VycHNLbkM3QmRXV3VaLXRab0g0c2ZDeExiYVppeW8tQU1xdVRhMzB0ckFOV21rSUtuTHFubFRvcXJXZ1JiQjF3Q0hlVjA4WXR1ak9sQUdKc0dHRTRLVjc0X2QwSXZ2NXA3RUxQZlJJcU51cGVLdlpTZ0pxU19tQmU0eG5wTFZsWDhmaHRIOE9aSUxKQ25ZQUt5VHZyNGFoZG9jd0NrOE9JX0xVOG5wQ1Rpc1VFdEo1MXpON2dqUEs2eGhCazZ1YnNNeE9oalhNSjhUd01sWHZvMjcwSXdYV08wVm1lN3pGbnp2S3dnWjV0UlB4c1hwTjlySDBlLUxIZU9uNHIzWWtHeHlpRDFrMkUyM0s4ay02RmxhM2JwMV9DQktfdkM0VUhBU3NqQnJjd21kOHVvYzdJTDRsQmRfeldQbEtyUXp6bmxyZVlMV2w3S1R
 mdG5ELXF0STlLMlFpWm9Ib3E4anZSYUJTTjZqUTk3RXhEb0E5dUk1LVRFc21UYlpCV3pGemdoOS1mbXBKZmQ1R3VNUXVhblJDN2VPbzh4bkJrVnI2UVVnZjVhYzV6Um0zc1ZBaktBVDJ5djc0dTNyOEJjUEJMcTBsc1gwTUpza3FlNEZhN193NXB5Q0Y4dS1RbVFkN2dmeUdPSW1OdTgySGJPSk5yMHg4Vm9NZU9uUExsVUhyY2cxNk43czY5ekU3SEM2UExpcHJobHdmY2JvMXlaZDZYVUxYNGI5MXJ4ME5SU0VpYURISGV1QS1LNWFQb1F6VVZiSFJ0cExvdHpwTEFTZkhwMWFhSEoyakRQUElfcVllbzkwWjVrR3RiV2plSTBYVDlzMy1TMk5pcW16Z2Q5WEMxNEJaUTM0UWpNdksyNUpJYXpqWW5FdGQzYUFYRWFZNU9CdGZ5R2NIcV96UmRaZlVQdDdDNk1LTFdRbnpzTXNWZHJ4cnpCcWRMMVV0NzlIQnZ5M3RlWDZ0RmJuYjR2ZkgxY3NZUl82a041T205VndHelRZYWNGM1dDTkNuOHljMk13N1Y4b25ZOXFLU0VLS1hRYk5KYlB1cEJsT29qLV9tV1drTkdmSy1TUHJoRmFGNF9LaDFTd25TelBydHRVVU9WMXg4ejNmUVFXZml5eVllcGd0VHVGSEZheHE0YXNCUjRQVndfUnBJN3c4QTNiSGR5ODQteWprZU0wU0k4WE5CdkRmVThRXzA2aVZjWkg1UWhwU2VENVpZNWotcDNzN3c4X2MtRXo3RHRZaHgyQzducWU2OFNVYmt3dmd4d2RUOFhaYzcySTJwSUFwYklPTzN0SEFIVmpvVHdVX3dsSHctSVZKbzZfSlBvRE5JbEdZcHdDZ21oMV9rb2FCLXFvMGdQd0UyeG1sRmdNeVVCd3lfWHNEdVRUcVJfT3pYVHBQbWdhTWNZMXJldEgzVjBDZ3BHaTBqYVZo
 N2NJSUpoVWNRcXRIVHl6S1hDTWVMRVBXYzJuVV9oXzB5U0tTanJMUmR1cHpkMTZ6V2sxdTRzdDRDak9CR1AxbloxVU14X3lGQ3ZsVVlESGY5OHhBelJNbUg0c1YxMnVMYmlCS2l0eTEwSG83X2N6T0htQ09LeE1oaFlhRmVrS19veUU3X3pWbTRjUzhHbEJiMUo2UVZMeHpGMXlORnlqeHdITEtnNURXUzN1T0JfSGpNdHlMOHh4WXhNR2FjNTh1X2g5ZEM5QThtVGJ5bEF6Wll6eTUtU3pvSVJYZHhVOGtBN1c0QzFWYmI1VGgyVHZmemF1Vk1mNVg0SWc1WTU4NzMtd3oxNVpHZW5xU3JreFVqU0tVUWVlZkI2eEg1aGtKeWs1cDZWY1JJNzF6SkVEVEU2LWZHSGsxTlNRd2QtS2tTaWlwMjI2d0JCOHZSVWdGQ1VZcy1EZC10TXF1aDdKZjlaRTU5amNzR0ZkTDJhamFRcjc4Z21VZEFVYS1HRHpQeHp3YkM0b1FKS29ObkNEZGc5WV94S3NHeEtDWnRVT1VjM0Z4MlptZFpfM292ZGExaHdyVDZpYVJLM0MxZnh0ZVpheE9IWkNvdW5MeU8wZUkzZ1Nnd2dkVERxODZ3TzY2U3pHdGRxYmo0bGZrT3NkRUYtUDNhQU1yOGNuclh3b2NOdGVpaVJ0YnVqLXhfNlVQUk5hWHJCV0lHRk1Mc2x3b1VlRXE1ZUpuOUhSYmdvd25vU3psOUdDWWdtdnRsb1ZIVHFVLXpNWk9TcmxPejA2aU1ZZjBjakliUDJtdHUyWHlDS3dkRnFsZHJqUWs3VmNUUEJkczluRjR2Z3lmOU1nSFVTeVpHTHFubHNtdG5ER1p4VTN0UmR1eXZfTFRLcDgxYVVQVVprb0EtTkMzdEFncHdQbUtodzVnY3M4U19aSC16VVNFd1BjLVR6NGtJSzhrSFVxQ2ZFY0pfMmhpX2RTWHRKbFB3TG9EeU95R
 1hTWkp5ZGIzb2hjblk3Z3RneGpQaU82Vmlwd1NZMXRVVUV1YmFKbHkzTGFwRjN0cXlEZXBBdHMxc2JDdzNSSm1HcE92WjlfaTk5SXZ6WjY1WDZPSDB1YUpDTWl6bFpzdGQwZ1FRMXl2ZTNQRDRaVHZPdzlMMm9Na0ZDQlFvQzBUalU5b0tPTHNpdlAzbTZOWjROLVpiaWFaNTIxbWU1ZjBWV1loRkN3RENxajRyUDZ5WmloOXVPTW5rWnNhZ3BtS0RlaVV6d1RpaENKdlRkZnBfbG1GQ3cyc0Jyd0lIVWJfdkxWY1RWNDd4NVNwSnhuS2dpWHpZUG8weElnYnY1bmZGWTJvM1NBWkZpSlNlNEJQbmFsX2FQLUFnNDdWM2h5NmNzT0xCM3l0VlNCRDdlNjFpU1VGWVhBUmZJVEVXa0VRaHBIWWJyRTlvemdldzdOLU5HaXdtWndOUy04SUFSbmRFS0tXSXRXb01fMllXVmYxS1ZoME8xQ2wwR0ZDV2NCNzFDLWxMazVJbkpKUm5Wd2dPQ1M2YUFKaEM2T2pIVVYydTR3TTdndFI1c1Y2Snk1NUxQcjFUbVpZQXAyVFNSMG0zUWMyN0ZKRnhxaFU2R20tZGtVNXZKbGtnSjUwY2xTUVVGcVl4Z0pDX1hSdWVpOXNzdkNmbnZVOW1ZSEFQZTU2Q2dXNWFiVGhSOEJCcTc2aTlxUjBlRVV4eFVWUUtCemFhVlB3TmVqaFRVYnpWcHZnNGlqSFRocFBlRzdDZ3hwQ00zT0pCaHFnS2k3RzVTeHFHYjdNVEhoclp2Q3I2WHZtZGdFc3NxWW9RdUQyYUQ4TlhjdVU0Mm1NVGwyZS1sY2pwU1E5R29hdlRHSjFCeFp2YWlYZzRNS1FGUjBjRDQzYkxsaXo2Y2NCeEEwZnJTU2dqbUhRNERxdHhjYkFiNFlPTDFlYkFQNFNSQnJwa3hGQW5fc1l6ci1aR0F0R0l3R1JfUHRRbjVLQ05yaX
 BueDRITVBmS2UtTHg4MzBIWFNxVGV5c0hRbGtuRlRSeFdwLXdNcUxPMlFhTHJnMlUzdnBDekloRmh4dG1tWnpPSE8zZmY2YTAySk9BaDVDek9GcG9oTDFXakl5a1RMd0dNMDZMQ25uNmhGeDVOZEhmVTlqaTdKNGZuT2RkcVh2ZnZ4TDhSN0wtM1d6SThIUVI4TkRHRzl6ZGtHZDUyQVlkNTBqUTZPN29qNUdkZldGMDdQTVY3WWFETjhGc1YwT19wZDM5bFpiUnM0SlV1Y0xWMzBXNGpqVGdselZGeXBaZEFxQXU0d2pWTVd5T1I0X1RSMnh6YW0wemx0ZXc1bm01TUk4NTlZYVhCVE95bkV5T18yRndDR2hzdmxQR2t5SHZuc050NFVya3pjRGswX0JaYUlYYWFNbUhxMUJQUWdiR0d6bUxNV0FXcFY0OUszdnBkN250WHFBZEVyN25VUnVpS2RSckVTYnpEUnAxclh2NExOMUdGNXRnRUFCZFhwYTVQVG9nVDM3cHUwb1BNNW5FZXFDeklRbmtjemMzUVk5SEZwY1J6bWFmbV9fSngxRFd0ak5qR1J0cVM4aHVUcVNKOG5ORl90ZXZsV2dwOU5uZU9KSUZwZkVMMnhYMTc2dnkyQ1FONTBFRzZZWmM4dXZreHFNUmk3OFNjdENEeXQ0WS5Sc3FFM1dad19XclIxRmtQc1RtWW1B
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultsetcertificatecontacts.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultsetcertificatecontacts.json b/providers/azurecompute-arm/src/test/resources/vaultsetcertificatecontacts.json
new file mode 100644
index 0000000..ca89576
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultsetcertificatecontacts.json
@@ -0,0 +1,8 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/contacts",
+	"contacts": [{
+		"email": "foo@bar.com",
+		"name": "Foo bar",
+		"phone": "867-5309"
+	}]
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultsetcertificatecontactsrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultsetcertificatecontactsrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultsetcertificatecontactsrequestbody.json
new file mode 100644
index 0000000..eefa904
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultsetcertificatecontactsrequestbody.json
@@ -0,0 +1,7 @@
+{
+	"contacts": [{
+		"email": "foo@bar.com",
+		"name": "Foo bar",
+		"phone": "867-5309"
+	}]
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultsetcertificateissuer.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultsetcertificateissuer.json b/providers/azurecompute-arm/src/test/resources/vaultsetcertificateissuer.json
new file mode 100644
index 0000000..dd08fe9
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultsetcertificateissuer.json
@@ -0,0 +1,21 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/issuers/globalsign01",
+	"provider": "GlobalSign",
+	"credentials": {
+		"account_id": "imauser"
+	},
+	"org_details": {
+		"zip": 0,
+		"admin_details": [{
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"email": "adminguy@certsforme.com",
+			"phone": "867-5309"
+		}]
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346474,
+		"updated": 1509346474
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultsetcertificateissuerrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultsetcertificateissuerrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultsetcertificateissuerrequestbody.json
new file mode 100644
index 0000000..4d2d25a
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultsetcertificateissuerrequestbody.json
@@ -0,0 +1,15 @@
+{
+	"credentials": {
+		"account_id": "imauser",
+		"pwd": "This1sMyPa55wurD!"
+	},
+	"org_details": {
+		"admin_details": [{
+			"email": "adminguy@certsforme.com",
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"phone": "867-5309"
+		}]
+	},
+	"provider": "GlobalSign"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultsetsecret.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultsetsecret.json b/providers/azurecompute-arm/src/test/resources/vaultsetsecret.json
new file mode 100644
index 0000000..9f1e929
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultsetsecret.json
@@ -0,0 +1,11 @@
+{
+	"value": "-----BEGIN RSA PRIVATE KEY-----\\nMIIEogIBAAKCAQEAvZiOgV6b4EmGiasBskXYnTaRyWzBHBGnWB11BzFN3FGigfWx\\nVvjI7Ox1SHTx+vGsnjbqQPvIP4JnPEsNcWLyHa6tNAcnj/M7BuyIwdD5+Hvs6kOe\\nPuSOJUf8dRjPMUpr6rcUcBmmOwTnKOH4rdpb6jXNnuCIHP+lgXCeRWveZ62TjEB+\\n9aB8W8UHH854FGebiUd/aY0tpCFC7wkWz3KbgmjmY2vSe2U98Yj4+l/IWydIZ7ON\\nLicteEEIGbNM0o2QSYhQBCJSw5RixDpPlrUUB094qgqUOyW0k8PvjibGxxTh0LYy\\nWqWydPF0XaqFRQ6v36UvEiVGwzVsLwsJL/QVtQIDAQABAoIBAEJ6790lE3s9zNMR\\nB3M/UoktzUjXvY7eEdOv4I05GJgcd+MiB6D7c1jAQQ+7Ee5wN5rynolSwBCk5RYb\\nKweLLmKCEXGg4Jp1K0luPzXW1Q/wRE6Qjzh2Y/FmoHtey6f49IZE1AHKvKMNQRDw\\ny4YKfxhM7WC8Un34lkwg9R5aiI3JkOG9/yNkOGrJfQnGUKt+AOAdu6fNYsRLWAPo\\nG3vWSNIgwaG5WL5cKd1gacbGBlc6tLB7+LrZuNrqln5ibTtN6QJvRF9KfOrMSvxy\\nL/xiHRpyzec/jrxJxAIIwFHiw2jbLdxNqDaVPFA6X1Cks4fvY40KymOS8Ecmkgx4\\nC6/ZqLECgYEA38rL8zmbJRRWgrxSoROucaN/9DyvE8Hd97s1zf3I0LIF+GI3JdcN\\nDV5O5VDIgQ7QZ55lOaTqJ0f2fOQZF1UbTU1gBUHVF6j1nv6Xic3OV+ZmhTMbt0Op\\nWxPaKup6dkNEAe/Xg0p308r8xw/psh4/gjL1ICHwycjUlz9FQz8FLGsCgYEA2OHc\\n/F4vAdK04U4w6A
 yivuJdIsDAks1ikl+3TqgzyesPg+DpKVNSy6DhraDFKdRqWhbK\\nDqigTud8TVk9kmyF3WIb1BDf4IrxlTK08s6Jf25QA/lBlwIst3rejqWwRBY2fJp4\\nO8hU31xNLd8nZq8tKYaP+yvyI6fSC+9ZIgyATl8CgYBtTlYzZG2cvMRMcsNBHaXU\\np3E1z/YLhmNuPqhXBp/xHyK/YOliuBkN8IREiSKFtsCf+8OhViVwLjv8YETJGq6N\\nIT/HEZKNTd86W0uU6UrhsA1e/cmJx6iObbHfyEssPEqZT5ZJ8DN65Oh2KhWRBCks\\n5MrJeQps5ITBowunfr5+JQKBgBln09goPD9tbEzcOPRlzoanw5s3kxdfQcW9up5X\\nK8HibC3ZodZ6cT9zOBx7sbzlqhOlicPP0v+LNE9nPcQyPDgjrvjXhTIrdIMyrmmm\\n8gpgZLUidKF42r4fgYSaOhyvsXBFNAJkxDRp/ox6EIaBzLuJjMIycqnklcFaJ0nK\\nxxjnAoGAU/3jRok74Yn0MY183UCXICf/WxVYzwEi3cyRWVh6gAo2ExNye97rau/B\\nY2woAcVxEN9h1HNirq8Z2AwrZKd/BcBnvulZqECeH5zBQ0W56ADX72r+lzOAxTJa\\nU1AIlNCIkfsQ5CpIoYsVoNEM8P+GyS8B9kaEmk/FVKldRTKJqkI=\\n-----END RSA PRIVATE KEY-----\\n",
+	"contentType": "testSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/b936ececbc674f3bb1367ae50d28ada0",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335932,
+		"updated": 1509335932,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultsetsecretrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultsetsecretrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultsetsecretrequestbody.json
new file mode 100644
index 0000000..52dc431
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultsetsecretrequestbody.json
@@ -0,0 +1,7 @@
+{
+	"attributes": {
+		"enabled": true
+	},
+	"contentType": "testSecretKey",
+	"value": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAvZiOgV6b4EmGiasBskXYnTaRyWzBHBGnWB11BzFN3FGigfWx\nVvjI7Ox1SHTx+vGsnjbqQPvIP4JnPEsNcWLyHa6tNAcnj/M7BuyIwdD5+Hvs6kOe\nPuSOJUf8dRjPMUpr6rcUcBmmOwTnKOH4rdpb6jXNnuCIHP+lgXCeRWveZ62TjEB+\n9aB8W8UHH854FGebiUd/aY0tpCFC7wkWz3KbgmjmY2vSe2U98Yj4+l/IWydIZ7ON\nLicteEEIGbNM0o2QSYhQBCJSw5RixDpPlrUUB094qgqUOyW0k8PvjibGxxTh0LYy\nWqWydPF0XaqFRQ6v36UvEiVGwzVsLwsJL/QVtQIDAQABAoIBAEJ6790lE3s9zNMR\nB3M/UoktzUjXvY7eEdOv4I05GJgcd+MiB6D7c1jAQQ+7Ee5wN5rynolSwBCk5RYb\nKweLLmKCEXGg4Jp1K0luPzXW1Q/wRE6Qjzh2Y/FmoHtey6f49IZE1AHKvKMNQRDw\ny4YKfxhM7WC8Un34lkwg9R5aiI3JkOG9/yNkOGrJfQnGUKt+AOAdu6fNYsRLWAPo\nG3vWSNIgwaG5WL5cKd1gacbGBlc6tLB7+LrZuNrqln5ibTtN6QJvRF9KfOrMSvxy\nL/xiHRpyzec/jrxJxAIIwFHiw2jbLdxNqDaVPFA6X1Cks4fvY40KymOS8Ecmkgx4\nC6/ZqLECgYEA38rL8zmbJRRWgrxSoROucaN/9DyvE8Hd97s1zf3I0LIF+GI3JdcN\nDV5O5VDIgQ7QZ55lOaTqJ0f2fOQZF1UbTU1gBUHVF6j1nv6Xic3OV+ZmhTMbt0Op\nWxPaKup6dkNEAe/Xg0p308r8xw/psh4/gjL1ICHwycjUlz9FQz8FLGsCgYEA2OHc\n/F4vAdK04U4w6AyivuJdIsDAks1ik
 l+3TqgzyesPg+DpKVNSy6DhraDFKdRqWhbK\nDqigTud8TVk9kmyF3WIb1BDf4IrxlTK08s6Jf25QA/lBlwIst3rejqWwRBY2fJp4\nO8hU31xNLd8nZq8tKYaP+yvyI6fSC+9ZIgyATl8CgYBtTlYzZG2cvMRMcsNBHaXU\np3E1z/YLhmNuPqhXBp/xHyK/YOliuBkN8IREiSKFtsCf+8OhViVwLjv8YETJGq6N\nIT/HEZKNTd86W0uU6UrhsA1e/cmJx6iObbHfyEssPEqZT5ZJ8DN65Oh2KhWRBCks\n5MrJeQps5ITBowunfr5+JQKBgBln09goPD9tbEzcOPRlzoanw5s3kxdfQcW9up5X\nK8HibC3ZodZ6cT9zOBx7sbzlqhOlicPP0v+LNE9nPcQyPDgjrvjXhTIrdIMyrmmm\n8gpgZLUidKF42r4fgYSaOhyvsXBFNAJkxDRp/ox6EIaBzLuJjMIycqnklcFaJ0nK\nxxjnAoGAU/3jRok74Yn0MY183UCXICf/WxVYzwEi3cyRWVh6gAo2ExNye97rau/B\nY2woAcVxEN9h1HNirq8Z2AwrZKd/BcBnvulZqECeH5zBQ0W56ADX72r+lzOAxTJa\nU1AIlNCIkfsQ5CpIoYsVoNEM8P+GyS8B9kaEmk/FVKldRTKJqkI\u003d\n-----END RSA PRIVATE KEY-----"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatecertificate.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatecertificate.json b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificate.json
new file mode 100644
index 0000000..4998d29
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificate.json
@@ -0,0 +1,58 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"x5t": "K7HXO6YIK6xwCX8W1InUKsJV9Rk",
+	"cer": "MIIDTDCCAjSgAwIBAgIQVA+XomvgS56ybBWv2MnacjANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wHhcNMTcxMDMwMDY0NDI3WhcNMTgxMDMwMDY1NDI3WjAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCusjC1A7rQEjW9SRL9XHRNDl0EuNYEV9AVQcAEmgpcJ6WgusdataeFrHKPmO8RUZgXk4sE14d3o9HjduYcqfOre+FBdQDWwoFHEAlq9Iz1r4woGk3f1oq9KepE12cRMTyTA214iluYNUx7XxSca3KFFswqonvcekbLJF2IPydNL0XrlIJFCUoAs3PRWLfPnYuijqRGhk8B9xGQMBtuDsnEi4wQRxusFHR1JxHSbY65xi1Hc9Ds9RAxdKwvBmYYC7V78q6qNM0LpenFGlZJMd/eRLVDguM1d17yyTX/lei/Oj8yVVDsva23ilUrv1mR549sv1lIqxNzdOGLsb6jykJ7AgMBAAGjfDB6MA4GA1UdDwEB/wQEAwIFoDAJBgNVHRMEAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBRnlX51KtyJ/m/V8I/3il4cAW/HOzAdBgNVHQ4EFgQUZ5V+dSrcif5v1fCP94peHAFvxzswDQYJKoZIhvcNAQELBQADggEBAAbSFuMRMbXyH80iA/jU7vuUCYe0Ra/wTTB1qVHTBuqQ/W8RI01mdqI9+GAPOTyN94XPPYVpSz9ZQ3P0/dhgcsahW5bZQkC0CcUSE5R7JUOKI5Up6n8zZM/unHlC6ZcEpNA/scObPKhQXdZayxgf2/p30bii4CiyS7ADEH92xMnzo1Eu9Dckxh1MRDypfxMY9YIzggks
 iY78BxoNsRDyxNjeRHVUxAIJ3n9TUv+WG31r7rMOIs6ZPsWc96AzUHHAZREVTEh2kiKKIenbMXn1tCpF6/GJKGfp7rt5ObUoQAlnn7kgAceteKZHEMgRZ4c4EQq+yqBw3hJrz4dOabJcmcU=",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509345867,
+		"exp": 1540882467,
+		"created": 1509346467,
+		"updated": 1509346472,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"selfsigned": "true"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/policy",
+		"key_props": {
+			"exportable": false,
+			"kty": "RSA",
+			"key_size": 2048,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pkcs12"
+		},
+		"x509_props": {
+			"subject": "CN=mycertificate.foobar.com",
+			"ekus": ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 12,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "AutoRenew"
+			}
+		}],
+		"issuer": {
+			"name": "Self"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346452,
+			"updated": 1509346472
+		}
+	},
+	"pending": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/pending"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateissuer.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateissuer.json b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateissuer.json
new file mode 100644
index 0000000..4960ce5
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateissuer.json
@@ -0,0 +1,21 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/issuers/globalsign01",
+	"provider": "GlobalSign",
+	"credentials": {
+		"account_id": "imauser"
+	},
+	"org_details": {
+		"zip": 0,
+		"admin_details": [{
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"email": "adminguy@certsforme.com",
+			"phone": "867-5309"
+		}]
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346474,
+		"updated": 1509346654
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateissuerrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateissuerrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateissuerrequestbody.json
new file mode 100644
index 0000000..658610e
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateissuerrequestbody.json
@@ -0,0 +1,15 @@
+{
+	"credentials": {
+		"account_id": "imauser",
+		"pwd": "CanHa5P455wuRd!"
+	},
+	"org_details": {
+		"admin_details": [{
+			"email": "adminguy@certsforme.com",
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"phone": "867-5309"
+		}]
+	},
+	"provider": "GlobalSign"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateoperation.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateoperation.json b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateoperation.json
new file mode 100644
index 0000000..800f399
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateoperation.json
@@ -0,0 +1,11 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myTempCertificate/pending",
+	"issuer": {
+		"name": "Self"
+	},
+	"csr": "MIIEtzCCAp8CAQAwJzElMCMGA1UEAxMcbXl0ZW1wY2VydGlmaWNhdGUuZm9vYmFyLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMmt2TbL1ndbSggTwx2l3k/ZUzt0IGO/FMB/oqpmc5izy2KGi0/uSoEdFA9cSqfctL3FGx2J1cFVTz287cvLB8HB3A4svAoPnKsZmKpXuYbF4fK2wQGXm/iNk+JVq1KL0lfoqW2g52lHDM85XURMn8YCkAGIKeTlOVyEn7EMBuBumcJbszj0g56Ij+VKmxoua/Ja4ONmIGsKdyZRBEuvFQ1GTnJUvCWHwyo1pT0M5EY/VL9ikc283DSvpQcfvNelQgQfWCpTRX1Q7nTUHk14DD4d/Y6OdbjcVuqE0Jdqdw6MXfU2zrkPo/nZBf5GHsUChiaxzVeEafPjWKvqVDzhEYXpmMB5SDAELaQtV6PoX+kxcjAO4K//BQtwneHHVF/Sh+7ke3nNUlSf4Mjn541wS7LdkBDOlTnKdYu+DhfbdkRD4E9LPiDduWDWHZs051uFBecR93JaZmX2b376RORQygDkBRga/MNENoEEnsz4zmoMYCGspZhRXEC9Uts1hzYEtwM1hyLqJlfadX/sct20N4JkhDkM8NG2V43R8jcnKFmzjfv6Yc1tuiQ1GQpYNFPJWh+fakAZkt7IwYsvy1CQg92Yvi3ne9zRTBn00enDpBTWaGCZ84gYYaT7Yfyo7/WRTjinYt6R0+u8l0AmZb0xkgxEACIQoyrg+oWQZI4YrneRAgMBAAGgSzBJBgkqhkiG9w0BCQ4xPDA6MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAgEAr8RMKLLpGG31Mq4Dor6Tf11AoiHCLH33MUqblF1VfDiw0++qBZ1dgm0D
 +uzQph/bZ6jKe/PUWpS1bErfaOt3iaVNOHom8jP/U3kZiYWvc/YHetU03prm1Qb+izNZA97NNeZRsuCXMAkNAHQnXa/rz/zG6BmGXFigh55wglX6aB8PnfKZb7N6RCct8BsKSV8uPpxXzRWPKrv7TA2RKfMifUD/Dzt7FSDuYJ8FGkvQNX012RXb2DqHp8tbZgUSj7iXdoZMZ1jfwlh6P61yhfItbF4SYvtBd9PTWIxP6SkCfDjJ7f0/ofwoV2DvAiwfH7URdQIMC+B8dPCqbjya3Ku+B2fWXXhdG7gJqa1zRY066QTIsHwfwd3WbeLQxCcBUEQUG0u23gj9fDX81fvKsgHtN9Nod5wXsdLtjjpHpJQJlDanII4H3fvDxAOlqSnxxEhjL9uA3YXUERMGGjExXA5kCOqKrdfGT5x4yosuNutylvF8YYn8r+mvMgegtVl8XmKnyP+uESSE2krVVmnSM2gveq7ILxBvanq70LmQVeYQB4AlLtUsxPUPIPiOryDI39KrlqWKdl3/oC7Gx+WbVzXxs37NEwt/tx8E+r1Nq/jRFxP0QlyyUdjpiPXjUpuCdn4y6erpCuahbMP+CZNCNgeEh1v2pNljuaGCIB+VA2Fz/oU=",
+	"cancellation_requested": true,
+	"status": "inProgress",
+	"status_details": "Pending certificate created. Certificate request is in progress. This may take some time based on the issuer provider. Please check again later.",
+	"request_id": "32051e4e4ac947c5b9ad1b6737bee7c0"
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateoperationrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateoperationrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateoperationrequestbody.json
new file mode 100644
index 0000000..5d370b3
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificateoperationrequestbody.json
@@ -0,0 +1,3 @@
+{
+    "cancellation_requested": true
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicy.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicy.json b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicy.json
new file mode 100644
index 0000000..97e126a
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicy.json
@@ -0,0 +1,37 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/policy",
+	"key_props": {
+		"exportable": false,
+		"kty": "RSA",
+		"key_size": 2048,
+		"reuse_key": false
+	},
+	"secret_props": {
+		"contentType": "application/x-pkcs12"
+	},
+	"x509_props": {
+		"subject": "CN=mycertificate.foobar.com",
+		"ekus": ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"],
+		"key_usage": ["digitalSignature", "keyEncipherment"],
+		"validity_months": 12,
+		"basic_constraints": {
+			"ca": false
+		}
+	},
+	"lifetime_actions": [{
+		"trigger": {
+			"lifetime_percentage": 80
+		},
+		"action": {
+			"action_type": "AutoRenew"
+		}
+	}],
+	"issuer": {
+		"name": "Self"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346452,
+		"updated": 1509346452
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicyrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicyrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicyrequestbody.json
new file mode 100644
index 0000000..4424614
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicyrequestbody.json
@@ -0,0 +1,8 @@
+{
+	"key_props": {
+		"exportable": true,
+		"key_size": 3072,
+		"kty": "RSA",
+		"reuse_key": false
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatecertificaterequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatecertificaterequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificaterequestbody.json
new file mode 100644
index 0000000..747f02f
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatecertificaterequestbody.json
@@ -0,0 +1 @@
+{"policy":{"id":"myCertificate","issuer":{"name":"Self"},"key_props":{"exportable":false,"key_size":2048,"kty":"RSA","reuse_key":false},"lifetime_actions":[],"x509_props":{"ekus":[],"key_usage":[],"subject":"CN=mycertificate.foobar.com","validity_months":12}},"tags":{"selfsigned":"true"}}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatekey.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatekey.json b/providers/azurecompute-arm/src/test/resources/vaultupdatekey.json
new file mode 100644
index 0000000..cd208a1
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatekey.json
@@ -0,0 +1,18 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/bd6566ec707e4ad89f4ab9577d9d0bef",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "2ZWsir4hwVxFTQXfWN7Vy1zA33jg1kxUMHmkmEFtVjGDByzmMfEXpnPziNCtYppBtpNT4AJEVQ60aIgSLNrUYBMoeiI2HCf2NM0NTdwYp7wq5tImtbGDASdDXQ1v3Bv3hXGh3CVmN2VLRf0OmoXnZUG_2UZZ05iPXOY6lNFfq8L81v0ZCMiXwFvNVhZ_fzppzhnwuHQf-X6Lnvrd1ocFqF8IFjV3663eumAfZmBLPP6tmiAZYW3G68_G0I2CHLtTPFX05aN51Jn42RITgcs63HFMT_iVW5556YR0BwtqkCXIUgTD714Fipz7EKGqhHsqND7YUSKpiRVQhfoZEckAkQ",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335902,
+		"updated": 1509335923,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"purpose": "testing"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatekeyrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatekeyrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultupdatekeyrequestbody.json
new file mode 100644
index 0000000..9ce289f
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatekeyrequestbody.json
@@ -0,0 +1,5 @@
+{
+  "tags": {
+    "purpose": "testing"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatekeywithversion.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatekeywithversion.json b/providers/azurecompute-arm/src/test/resources/vaultupdatekeywithversion.json
new file mode 100644
index 0000000..337b33b
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatekeywithversion.json
@@ -0,0 +1,18 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/bd6566ec707e4ad89f4ab9577d9d0bef",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "2ZWsir4hwVxFTQXfWN7Vy1zA33jg1kxUMHmkmEFtVjGDByzmMfEXpnPziNCtYppBtpNT4AJEVQ60aIgSLNrUYBMoeiI2HCf2NM0NTdwYp7wq5tImtbGDASdDXQ1v3Bv3hXGh3CVmN2VLRf0OmoXnZUG_2UZZ05iPXOY6lNFfq8L81v0ZCMiXwFvNVhZ_fzppzhnwuHQf-X6Lnvrd1ocFqF8IFjV3663eumAfZmBLPP6tmiAZYW3G68_G0I2CHLtTPFX05aN51Jn42RITgcs63HFMT_iVW5556YR0BwtqkCXIUgTD714Fipz7EKGqhHsqND7YUSKpiRVQhfoZEckAkQ",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335902,
+		"updated": 1509335927,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"purpose": "testing again"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatesecret.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatesecret.json b/providers/azurecompute-arm/src/test/resources/vaultupdatesecret.json
new file mode 100644
index 0000000..3f96107
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatesecret.json
@@ -0,0 +1,13 @@
+{
+	"contentType": "testSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/b936ececbc674f3bb1367ae50d28ada0",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335932,
+		"updated": 1509335934,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"purpose": "testing"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatesecretrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatesecretrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultupdatesecretrequestbody.json
new file mode 100644
index 0000000..06c614f
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatesecretrequestbody.json
@@ -0,0 +1,5 @@
+{
+	"tags": {
+		"purpose": "testing"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatesecretwithversion.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatesecretwithversion.json b/providers/azurecompute-arm/src/test/resources/vaultupdatesecretwithversion.json
new file mode 100644
index 0000000..e6d8f46
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatesecretwithversion.json
@@ -0,0 +1,13 @@
+{
+	"contentType": "testSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/b936ececbc674f3bb1367ae50d28ada0",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335932,
+		"updated": 1509335946,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"purpose": "testing again"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a2dee2f8/providers/azurecompute-arm/src/test/resources/vaultupdatesecretwithversionrequestbody.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/vaultupdatesecretwithversionrequestbody.json b/providers/azurecompute-arm/src/test/resources/vaultupdatesecretwithversionrequestbody.json
new file mode 100644
index 0000000..a9c6db9
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/vaultupdatesecretwithversionrequestbody.json
@@ -0,0 +1,5 @@
+{
+	"tags": {
+		"purpose": "testing again"
+	}
+}


[16/50] [abbrv] jclouds git commit: JCLOUDS-1278: Allow to configure virtual machine NICs

Posted by na...@apache.org.
JCLOUDS-1278: Allow to configure virtual machine NICs


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

Branch: refs/heads/master
Commit: df300573863c7716759c1bfef56fa382ba73d705
Parents: ec67fde
Author: Ignasi Barrera <na...@apache.org>
Authored: Wed Apr 26 15:42:36 2017 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Fri Apr 28 09:03:40 2017 +0200

----------------------------------------------------------------------
 .../arm/AzureComputeProviderMetadata.java       |   4 +-
 .../arm/compute/AzureComputeServiceAdapter.java | 166 ++++++++++++++-----
 .../AzureComputeSecurityGroupExtension.java     |  21 ++-
 .../functions/VirtualMachineToNodeMetadata.java |  18 +-
 .../loaders/CreateSecurityGroupIfNeeded.java    |   9 +-
 .../compute/options/AzureTemplateOptions.java   |  98 +++++------
 .../arm/compute/options/IpOptions.java          |  76 +++++++++
 .../arm/compute/strategy/CleanupResources.java  |  30 ++--
 .../CreateResourcesThenCreateNodes.java         | 108 ++++++++----
 .../domain/NetworkInterfaceCardProperties.java  |  37 ++---
 .../azurecompute/arm/domain/NetworkProfile.java |  44 ++++-
 .../arm/domain/PublicIPAddress.java             |  53 ++++--
 .../jclouds/azurecompute/arm/domain/Subnet.java |  74 ++++++---
 .../arm/features/PublicIPAddressApi.java        |   3 +-
 .../CreateResourcesThenCreateNodesTest.java     | 114 +++++++++++++
 .../arm/domain/IdReferenceTest.java             |   1 +
 .../azurecompute/arm/domain/SubnetTest.java     |  47 ++++++
 .../arm/features/LoadBalancerApiLiveTest.java   |   3 +-
 .../NetworkInterfaceCardApiMockTest.java        |   5 +-
 .../arm/features/SubnetApiMockTest.java         |   2 +-
 .../arm/features/VirtualMachineApiLiveTest.java |  11 +-
 .../arm/features/VirtualMachineApiMockTest.java |  20 +--
 22 files changed, 705 insertions(+), 239 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index 9d3f05d..c35455c 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -99,7 +99,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       // Api versions used in each API
       properties.put(API_VERSION_PREFIX + DeploymentApi.class.getSimpleName(), "2016-02-01");
       properties.put(API_VERSION_PREFIX + LocationApi.class.getSimpleName(), "2015-11-01");
-      properties.put(API_VERSION_PREFIX + NetworkInterfaceCardApi.class.getSimpleName(), "2015-06-15");
+      properties.put(API_VERSION_PREFIX + NetworkInterfaceCardApi.class.getSimpleName(), "2017-03-01");
       properties.put(API_VERSION_PREFIX + NetworkSecurityGroupApi.class.getSimpleName(), "2016-03-30");
       properties.put(API_VERSION_PREFIX + NetworkSecurityRuleApi.class.getSimpleName(), "2016-03-30");
       properties.put(API_VERSION_PREFIX + OSImageApi.class.getSimpleName(), "2015-06-15");
@@ -107,7 +107,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(API_VERSION_PREFIX + ResourceGroupApi.class.getSimpleName(), "2015-01-01");
       properties.put(API_VERSION_PREFIX + ResourceProviderApi.class.getSimpleName(), "2015-01-01");
       properties.put(API_VERSION_PREFIX + StorageAccountApi.class.getSimpleName(), "2015-06-15");
-      properties.put(API_VERSION_PREFIX + SubnetApi.class.getSimpleName(), "2015-06-15");
+      properties.put(API_VERSION_PREFIX + SubnetApi.class.getSimpleName(), "2017-03-01");
       properties.put(API_VERSION_PREFIX + VirtualNetworkApi.class.getSimpleName(), "2015-06-15");
       properties.put(API_VERSION_PREFIX + VMSizeApi.class.getSimpleName(), "2015-06-15");
       properties.put(API_VERSION_PREFIX + VirtualMachineApi.class.getSimpleName(), "2016-04-30-preview");

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index d01d6ec..02e69fa 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -27,9 +27,14 @@ import static org.jclouds.azurecompute.arm.compute.domain.LocationAndName.fromSl
 import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
 import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractName;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
 import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
 import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -44,6 +49,7 @@ import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextMod
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
+import org.jclouds.azurecompute.arm.compute.options.IpOptions;
 import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
 import org.jclouds.azurecompute.arm.domain.CreationData;
@@ -62,6 +68,7 @@ import org.jclouds.azurecompute.arm.domain.OSDisk;
 import org.jclouds.azurecompute.arm.domain.OSProfile;
 import org.jclouds.azurecompute.arm.domain.Offer;
 import org.jclouds.azurecompute.arm.domain.Plan;
+import org.jclouds.azurecompute.arm.domain.Provisionable;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
@@ -75,13 +82,15 @@ import org.jclouds.azurecompute.arm.domain.VMSize;
 import org.jclouds.azurecompute.arm.domain.Version;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface.NetworkInterfaceProperties;
+import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
 import org.jclouds.azurecompute.arm.features.OSImageApi;
-import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
 import org.jclouds.compute.ComputeServiceAdapter;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.OsFamily;
 import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.functions.GroupNamingConvention;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.location.Region;
 import org.jclouds.logging.Logger;
@@ -105,6 +114,7 @@ import com.google.common.collect.Lists;
 public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location> {
 
    public static final String GROUP_KEY = "jclouds_group";
+   public static final String AUTOGENERATED_IP_KEY = "jclouds-autogenerated";
 
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
@@ -116,40 +126,40 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
    private final Supplier<Set<String>> regionIds;
    private final PublicIpAvailablePredicateFactory publicIpAvailable;
    private final CustomImageToVMImage customImagetoVmImage;
+   private final GroupNamingConvention namingConvention;
+   private Predicate<Supplier<Provisionable>> resourceAvailable;
 
    @Inject
    AzureComputeServiceAdapter(final AzureComputeApi api, @Named(IMAGE_PUBLISHERS) String imagePublishers,
          CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
-         PublicIpAvailablePredicateFactory publicIpAvailable,
-         CustomImageToVMImage customImagetoVmImage) {
+         PublicIpAvailablePredicateFactory publicIpAvailable, CustomImageToVMImage customImagetoVmImage,
+         GroupNamingConvention.Factory namingConvention, Predicate<Supplier<Provisionable>> resourceAvailable) {
       this.api = api;
       this.imagePublishers = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(imagePublishers);
       this.cleanupResources = cleanupResources;
       this.regionIds = regionIds;
       this.publicIpAvailable = publicIpAvailable;
       this.customImagetoVmImage = customImagetoVmImage;
+      this.namingConvention = namingConvention.create();
+      this.resourceAvailable = resourceAvailable;
    }
 
    @Override
    public NodeAndInitialCredentials<VirtualMachine> createNodeWithGroupEncodedIntoName(final String group, final String name, final Template template) {
-      // TODO network ids => create one nic in each network
-
       String locationName = template.getLocation().getId();
       Image image = template.getImage();
       String hardwareId = fromSlashEncoded(template.getHardware().getId()).name();
-      // TODO ARM specific options
       AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class);
-      String subnetId = templateOptions.getSubnetId();
       String resourceGroupName = templateOptions.getResourceGroup();
       
       IdReference availabilitySet = getAvailabilitySetIdReference(templateOptions.getAvailabilitySet());
+      NetworkProfile networkProfile = createNetworkProfile(createNetworkInterfaceCards(name, locationName,
+            templateOptions));
       StorageProfile storageProfile = createStorageProfile(image, templateOptions.getDataDisks());
-      NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName, resourceGroupName, template.getOptions());
       HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(hardwareId).build();
       OSProfile osProfile = createOsProfile(name, template);
-      NetworkProfile networkProfile = NetworkProfile.builder().networkInterfaces(of(IdReference.create(nic.id()))).build();
+      
       VirtualMachineProperties virtualMachineProperties = VirtualMachineProperties.builder()
-              .licenseType(null) // TODO
               .availabilitySet(availabilitySet)
               .hardwareProfile(hardwareProfile)
               .storageProfile(storageProfile)
@@ -159,11 +169,11 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
 
       // Store group apart from the name to be able to identify nodes with
       // custom names in the configured group
-      template.getOptions().getUserMetadata().put(GROUP_KEY, group);
-      Map<String, String> metadataAndTags = metadataAndTagsAsCommaDelimitedValue(template.getOptions());
-      Plan plan = getMarketplacePlanFromImageMetadata(template.getImage());
+      templateOptions.getUserMetadata().put(GROUP_KEY, group);
+      Map<String, String> metadataAndTags = metadataAndTagsAsCommaDelimitedValue(templateOptions);
+      Plan plan = getMarketplacePlanFromImageMetadata(image);
 
-      VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).createOrUpdate(name, template.getLocation().getId(),
+      VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).createOrUpdate(name, locationName,
             virtualMachineProperties, metadataAndTags, plan);
 
       // Safe to pass null credentials here, as jclouds will default populate
@@ -383,39 +393,113 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
       return builder.build();
    }
 
-   private NetworkInterfaceCard createNetworkInterfaceCard(String subnetId, String name, String locationName,
-                                                           String azureGroup, TemplateOptions options) {
-      final PublicIPAddressApi ipApi = api.getPublicIPAddressApi(azureGroup);
+   private List<NetworkInterfaceCard> createNetworkInterfaceCards(final String nodeName, final String location,
+         AzureTemplateOptions options) {
+      // Prefer a sorted list of NICs with the ones with public IPs first, to
+      // make sure the primary NIC is the public one
+      final String securityGroup = getOnlyElement(options.getGroups(), null);
+      return Lists.transform(publicIpsFirst(options.getIpOptions()), new Function<IpOptions, NetworkInterfaceCard>() {
+         @Override
+         public NetworkInterfaceCard apply(IpOptions input) {
+            return createNetworkInterfaceCard(input, nodeName, location, securityGroup);
+         }
+      });
+   }
+   
+   private NetworkInterfaceCard createNetworkInterfaceCard(IpOptions ipConfig, String nodeName, String location,
+         String securityGroup) {
+      String resourceGroup = extractResourceGroup(ipConfig.subnet());
+      String subnetName = extractName(ipConfig.subnet());
 
-      PublicIPAddressProperties properties = PublicIPAddressProperties.builder().publicIPAllocationMethod("Static")
-              .idleTimeoutInMinutes(4).build();
+      IpConfigurationProperties.Builder ipProperties = IpConfigurationProperties.builder()
+            .subnet(IdReference.create(ipConfig.subnet()))
+            .privateIPAllocationMethod(ipConfig.address().isPresent() ? "Static" : "Dynamic")
+            .privateIPAddress(ipConfig.address().orNull());
 
-      String publicIpAddressName = "public-address-" + name;
-      PublicIPAddress ip = ipApi.createOrUpdate(publicIpAddressName, locationName, ImmutableMap.of("jclouds", name),
-              properties);
+      configurePublicIP(ipConfig, ipProperties, resourceGroup, location, nodeName);
 
-      checkState(publicIpAvailable.create(azureGroup).apply(publicIpAddressName),
-              "Public IP was not provisioned in the configured timeout");
+      String ipName = namingConvention.uniqueNameForGroup(subnetName);
+      final String nicName = namingConvention.uniqueNameForGroup(subnetName);
+
+      IpConfiguration config = IpConfiguration.builder().name(ipName).properties(ipProperties.build()).build();
+
+      NetworkInterfaceCardProperties.Builder nicProperties = NetworkInterfaceCardProperties.builder().ipConfigurations(
+            ImmutableList.of(config));
 
-      final NetworkInterfaceCardProperties.Builder networkInterfaceCardProperties = NetworkInterfaceCardProperties
-              .builder()
-              .ipConfigurations(
-                      of(IpConfiguration
-                              .builder()
-                              .name("ipConfig-" + name)
-                              .properties(
-                                      IpConfigurationProperties.builder().privateIPAllocationMethod("Dynamic")
-                                              .publicIPAddress(IdReference.create(ip.id())).subnet(IdReference.create(subnetId))
-                                              .build()).build()));
-
-      String securityGroup = getOnlyElement(options.getGroups(), null);
       if (securityGroup != null) {
-         networkInterfaceCardProperties.networkSecurityGroup(IdReference.create(securityGroup));
+         nicProperties.networkSecurityGroup(IdReference.create(securityGroup));
       }
 
-      String networkInterfaceCardName = "jc-nic-" + name;
-      return api.getNetworkInterfaceCardApi(azureGroup).createOrUpdate(networkInterfaceCardName, locationName,
-              networkInterfaceCardProperties.build(), ImmutableMap.of("jclouds", name));
+      logger.debug(">> creating nic %s(%s) with security groups (%s)", nicName, config,
+            securityGroup != null ? securityGroup : "");
+
+      final NetworkInterfaceCardApi nicApi = api.getNetworkInterfaceCardApi(resourceGroup);
+      NetworkInterfaceCard nic = nicApi.createOrUpdate(nicName, location, nicProperties.build(),
+            ImmutableMap.of("jclouds", nodeName));
+
+      resourceAvailable.apply(new Supplier<Provisionable>() {
+         @Override
+         public Provisionable get() {
+            NetworkInterfaceCard updated = nicApi.get(nicName);
+            return updated == null ? null : updated.properties();
+         }
+      });
+
+      return nic;
+   }
+   
+   private void configurePublicIP(IpOptions ipConfig, IpConfigurationProperties.Builder ipProperties,
+         String resourceGroup, String location, String nodeName) {
+      if (ipConfig.publicIpId() != null) {
+         logger.debug(">> configuring public ip: %s",  extractName(ipConfig.publicIpId()));
+         PublicIPAddress publicIp = api.getPublicIPAddressApi(extractResourceGroup(ipConfig.publicIpId())).get(
+               extractName(ipConfig.publicIpId()));
+         ipProperties.publicIPAddress(IdReference.create(publicIp.id()));
+      } else if (ipConfig.allocateNewPublicIp()) {
+         PublicIPAddress publicIp = createPublicIp(resourceGroup, location, nodeName);
+         ipProperties.publicIPAddress(IdReference.create(publicIp.id()));
+      }
+   }
+   
+   /**
+    * Create the network profile and configure the first NIC as primary.
+    */
+   private NetworkProfile createNetworkProfile(List<NetworkInterfaceCard> nics) {
+      List<NetworkInterface> nicAttachments = new ArrayList<NetworkInterface>(nics.size());
+      for (int i = 0; i < nics.size(); i++) {
+         nicAttachments.add(NetworkInterface.create(nics.get(i).id(), NetworkInterfaceProperties.create(i == 0)));
+      }
+      return NetworkProfile.create(nicAttachments);
+   }
+   
+   private static List<IpOptions> publicIpsFirst(List<IpOptions> ipOptions) {
+      List<IpOptions> sorted = new ArrayList<IpOptions>(ipOptions);
+      Collections.sort(sorted, new Comparator<IpOptions>() {
+         @Override
+         public int compare(IpOptions o1, IpOptions o2) {
+            return o1.allocateNewPublicIp() == o2.allocateNewPublicIp() ? 0 : o1.allocateNewPublicIp() ? -1 : 1;
+         }
+      });
+      return sorted;
+   }
+   
+   private PublicIPAddress createPublicIp(String resourceGroup, String location, String nodeName) {
+      String name = namingConvention.uniqueNameForGroup(nodeName);
+      
+      PublicIPAddressProperties properties = PublicIPAddressProperties.builder()
+            .publicIPAllocationMethod("Static")
+            .idleTimeoutInMinutes(4)
+            .build();
+      
+      logger.debug(">> allocating new public ip address: %s", name);
+
+      PublicIPAddress ip = api.getPublicIPAddressApi(resourceGroup).createOrUpdate(name, location,
+            ImmutableMap.of("jclouds", nodeName, AUTOGENERATED_IP_KEY, "true"), properties);
+
+      checkState(publicIpAvailable.create(resourceGroup).apply(name),
+              "Public IP was not provisioned in the configured timeout");
+      
+      return ip;
    }
 
    private StorageProfile createStorageProfile(Image image, List<DataDisk> dataDisks) {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
index 59608a4..50cb75a 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
@@ -23,6 +23,8 @@ import static com.google.common.collect.Iterables.any;
 import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.transform;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractName;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
 
 import java.net.URI;
 import java.util.ArrayList;
@@ -36,8 +38,8 @@ import javax.inject.Named;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.SecurityGroupAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
-import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
@@ -135,12 +137,12 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
       if (vm == null) {
          throw new IllegalArgumentException("Node " + nodeId + " was not found");
       }
-      List<IdReference> networkInterfacesIdReferences = vm.properties().networkProfile().networkInterfaces();
+      List<NetworkInterface> networkInterfaces = vm.properties().networkProfile().networkInterfaces();
       List<NetworkSecurityGroup> networkGroups = new ArrayList<NetworkSecurityGroup>();
 
-      for (IdReference networkInterfaceCardIdReference : networkInterfacesIdReferences) {
-         String nicName = networkInterfaceCardIdReference.name();
-         String nicResourceGroup = networkInterfaceCardIdReference.resourceGroup();
+      for (NetworkInterface networkInterfaceCardIdReference : networkInterfaces) {
+         String nicName = extractName(networkInterfaceCardIdReference.id());
+         String nicResourceGroup = extractResourceGroup(networkInterfaceCardIdReference.id());
          NetworkInterfaceCard card = api.getNetworkInterfaceCardApi(nicResourceGroup).get(nicName);
          if (card != null && card.properties().networkSecurityGroup() != null) {
             String secGroupName = card.properties().networkSecurityGroup().name();
@@ -171,9 +173,14 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
       SecurityGroupBuilder builder = new SecurityGroupBuilder();
       builder.name(name);
       builder.location(location);
+      
+      NetworkSecurityGroup sg = api.getNetworkSecurityGroupApi(resourceGroup.name()).createOrUpdate(name,
+            location.getId(), null, NetworkSecurityGroupProperties.builder().build());
+      
+      checkState(securityGroupAvailable.create(resourceGroup.name()).apply(name),
+            "Security group was not created in the configured timeout");
 
-      return securityGroupConverter.apply(api.getNetworkSecurityGroupApi(resourceGroup.name()).createOrUpdate(name,
-            location.getId(), null, NetworkSecurityGroupProperties.builder().build()));
+      return securityGroupConverter.apply(sg);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
index e4b7da8..af43cbb 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
@@ -22,6 +22,7 @@ import static com.google.common.collect.Iterables.find;
 import static org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.GROUP_KEY;
 import static org.jclouds.azurecompute.arm.compute.domain.LocationAndName.fromLocationAndName;
 import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractName;
 import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
 import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
 import static org.jclouds.location.predicates.LocationPredicates.idEquals;
@@ -40,6 +41,7 @@ import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToStatus.Sta
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.IpConfiguration;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
@@ -136,9 +138,9 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
       return builder.build();
    }
 
-   private Iterable<String> getPrivateIpAddresses(List<IdReference> idReferences) {
+   private Iterable<String> getPrivateIpAddresses(List<NetworkInterface> networkInterfaces) {
       List<String> privateIpAddresses = Lists.newArrayList();
-      for (IdReference networkInterfaceCardIdReference : idReferences) {
+      for (NetworkInterface networkInterfaceCardIdReference : networkInterfaces) {
          NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference);
          if (networkInterfaceCard != null && networkInterfaceCard.properties() != null
                && networkInterfaceCard.properties().ipConfigurations() != null) {
@@ -152,21 +154,21 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
       return privateIpAddresses;
    }
 
-   private NetworkInterfaceCard getNetworkInterfaceCard(IdReference nic) {
-      return api.getNetworkInterfaceCardApi(nic.resourceGroup()).get(nic.name());
+   private NetworkInterfaceCard getNetworkInterfaceCard(NetworkInterface nic) {
+      return api.getNetworkInterfaceCardApi(extractResourceGroup(nic.id())).get(extractName(nic.id()));
    }
 
-   private Iterable<String> getPublicIpAddresses(List<IdReference> idReferences) {
+   private Iterable<String> getPublicIpAddresses(List<NetworkInterface> networkInterfaces) {
       List<String> publicIpAddresses = Lists.newArrayList();
-      for (IdReference networkInterfaceCardIdReference : idReferences) {
+      for (NetworkInterface networkInterfaceCardIdReference : networkInterfaces) {
          NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference);
          if (networkInterfaceCard != null && networkInterfaceCard.properties() != null
                && networkInterfaceCard.properties().ipConfigurations() != null) {
-            String resourceGroup = networkInterfaceCardIdReference.resourceGroup();
             for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) {
                if (ipConfiguration.properties().publicIPAddress() != null) {
                   IdReference publicIpId = ipConfiguration.properties().publicIPAddress();
-                  PublicIPAddress publicIp = api.getPublicIPAddressApi(resourceGroup).get(publicIpId.name());
+                  PublicIPAddress publicIp = api.getPublicIPAddressApi(publicIpId.resourceGroup()).get(
+                        publicIpId.name());
                   if (publicIp != null && publicIp.properties().ipAddress() != null) {
                      publicIpAddresses.add(publicIp.properties().ipAddress());
                   }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
index bb5dc09..98732d2 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.azurecompute.arm.compute.loaders;
 
+import static com.google.common.base.Preconditions.checkState;
 import static org.jclouds.compute.util.ComputeServiceUtils.getPortRangesFromList;
 
 import java.util.ArrayList;
@@ -28,6 +29,7 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.SecurityGroupAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
@@ -48,10 +50,12 @@ public class CreateSecurityGroupIfNeeded extends CacheLoader<ResourceGroupAndNam
    protected Logger logger = Logger.NULL;
 
    private final AzureComputeApi api;
+   private final SecurityGroupAvailablePredicateFactory securityGroupAvailable;
 
    @Inject
-   CreateSecurityGroupIfNeeded(AzureComputeApi api) {
+   CreateSecurityGroupIfNeeded(AzureComputeApi api, SecurityGroupAvailablePredicateFactory securityRuleAvailable) {
       this.api = api;
+      this.securityGroupAvailable = securityRuleAvailable;
    }
 
    @Override
@@ -86,6 +90,9 @@ public class CreateSecurityGroupIfNeeded extends CacheLoader<ResourceGroupAndNam
 
       NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(resourceGroup).createOrUpdate(name, location,
             null, NetworkSecurityGroupProperties.builder().securityRules(rules).build());
+      
+      checkState(securityGroupAvailable.create(resourceGroup).apply(name),
+            "Security group was not created in the configured timeout");
 
       return securityGroup.id();
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
index d211421..c3140dd 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java
@@ -32,28 +32,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
  */
 public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
 
-   private String virtualNetworkName;
-   private String subnetId;
    private AvailabilitySet availabilitySet;
    private String availabilitySetName;
    private List<DataDisk> dataDisks = ImmutableList.of();
    private String resourceGroup;
-
-   /**
-    * Sets the virtual network name
-    */
-   public  AzureTemplateOptions virtualNetworkName(String virtualNetworkName) {
-      this.virtualNetworkName = virtualNetworkName;
-      return this;
-   }
-
-   /**
-    * Sets the subnet name
-    */
-   public  AzureTemplateOptions subnetId(String subnetId) {
-      this.subnetId = subnetId;
-      return this;
-   }
+   private List<IpOptions> ipOptions = ImmutableList.of();
    
    /**
     * Sets the availability set where the nodes will be configured. If it does
@@ -92,12 +75,35 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       return dataDisks(ImmutableList.copyOf(checkNotNull(dataDisks, "dataDisks")));
    }
    
-   public String getVirtualNetworkName() { return virtualNetworkName; }
-   public String getSubnetId() { return subnetId; }
+   /**
+    * Configure the NICs that will be attached to the created nodes.
+    * <p>
+    * Note that the number of NICs that can be attached depends on the size of
+    * the virtual machine, and that the guest operating system needs to be
+    * prepared to set up all the configured interfaces.
+    * <p>
+    * Depending on the image being used, a cloud-init or bootstrap script might
+    * be needed to make the interface setup.
+    */
+   public AzureTemplateOptions ipOptions(Iterable<IpOptions> ipOptions) {
+      for (IpOptions ipOption : checkNotNull(ipOptions, "ipOptions"))
+         checkNotNull(ipOption, "all ipOptions must be non-empty");
+      this.ipOptions = ImmutableList.copyOf(ipOptions);
+      return this;
+   }
+
+   /**
+    * @see {@link AzureTemplateOptions#ipOptions(Iterable)
+    */
+   public AzureTemplateOptions ipOptions(IpOptions... ipOptions) {
+      return ipOptions(ImmutableList.copyOf(checkNotNull(ipOptions, "ipOptions")));
+   }
+   
    public AvailabilitySet getAvailabilitySet() { return availabilitySet; }
    public String getAvailabilitySetName() { return availabilitySetName; }
    public List<DataDisk> getDataDisks() { return dataDisks; }
    public String getResourceGroup() { return resourceGroup; }
+   public List<IpOptions> getIpOptions() { return ipOptions; }
 
    @Override
    public AzureTemplateOptions clone() {
@@ -111,12 +117,11 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
       super.copyTo(to);
       if (to instanceof AzureTemplateOptions) {
          AzureTemplateOptions eTo = AzureTemplateOptions.class.cast(to);
-         eTo.virtualNetworkName(virtualNetworkName);
-         eTo.subnetId(subnetId);
          eTo.availabilitySet(availabilitySet);
          eTo.availabilitySet(availabilitySetName);
          eTo.dataDisks(dataDisks);
          eTo.resourceGroup(resourceGroup);
+         eTo.ipOptions(ipOptions);
       }
    }
 
@@ -128,27 +133,22 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
 
       AzureTemplateOptions that = (AzureTemplateOptions) o;
       
-      return Objects.equal(virtualNetworkName, that.virtualNetworkName) &&
-            Objects.equal(subnetId, that.subnetId) &&
+      return Objects.equal(availabilitySetName, that.availabilitySetName) &&
+            Objects.equal(resourceGroup, that.resourceGroup) &&
             Objects.equal(availabilitySet, that.availabilitySet) &&
-            Objects.equal(availabilitySetName, that.availabilitySetName) &&
             Objects.equal(dataDisks, that.dataDisks) &&
-            Objects.equal(resourceGroup, that.resourceGroup);
+            Objects.equal(ipOptions, that.ipOptions);
    }
 
    @Override
    public int hashCode() {
-      return Objects.hashCode(virtualNetworkName, subnetId, availabilitySet, availabilitySetName, dataDisks,
-            resourceGroup);
+      return Objects.hashCode(availabilitySet, availabilitySetName, dataDisks,
+            resourceGroup, ipOptions);
    }
 
    @Override
    public Objects.ToStringHelper string() {
       Objects.ToStringHelper toString = super.string();
-      if (virtualNetworkName != null)
-         toString.add("virtualNetworkName", virtualNetworkName);
-      if (subnetId != null)
-         toString.add("subnetId", subnetId);
       if (availabilitySet != null)
          toString.add("availabilitySet", availabilitySet);
       if (availabilitySetName != null)
@@ -157,26 +157,12 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          toString.add("dataDisks", dataDisks);
       if (resourceGroup != null)
          toString.add("resourceGroup", resourceGroup);
+      if (!ipOptions.isEmpty())
+         toString.add("ipOptions", ipOptions);
       return toString;
    }
 
    public static class Builder {
-
-      /**
-       * @see AzureTemplateOptions#virtualNetworkName(String)
-       */
-      public static AzureTemplateOptions virtualNetworkName(String virtualNetworkName) {
-         AzureTemplateOptions options = new AzureTemplateOptions();
-         return options.virtualNetworkName(virtualNetworkName);
-      }
-
-      /**
-       * @see AzureTemplateOptions#subnetId(String)
-       */
-      public static AzureTemplateOptions subnetId(String subnetId) {
-         AzureTemplateOptions options = new AzureTemplateOptions();
-         return options.subnetId(subnetId);
-      }
       
       /**
        * @see AzureTemplateOptions#availabilitySet(AvailabilitySet)
@@ -217,5 +203,21 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
          AzureTemplateOptions options = new AzureTemplateOptions();
          return options.resourceGroup(resourceGroup);
       }
+      
+      /**
+       * @see AzureTemplateOptions#ipOptions(IpOptions...)
+       */
+      public static AzureTemplateOptions ipOptions(IpOptions... ipOptions) {
+         AzureTemplateOptions options = new AzureTemplateOptions();
+         return options.ipOptions(ipOptions);
+      }
+
+      /**
+       * @see AzureTemplateOptions#ipOptions(Iterable)
+       */
+      public static AzureTemplateOptions ipOptions(Iterable<IpOptions> ipOptions) {
+         AzureTemplateOptions options = new AzureTemplateOptions();
+         return options.ipOptions(ipOptions);
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/IpOptions.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/IpOptions.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/IpOptions.java
new file mode 100644
index 0000000..73c4c6c
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/IpOptions.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.compute.options;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Optional;
+
+/**
+ * Configures the ip addresses to be configured for the created nodes.
+ */
+@AutoValue
+public abstract class IpOptions {
+
+   /**
+    * The subnet where the NIC will be attached.
+    */
+   public abstract String subnet();
+
+   /**
+    * The IP address to be configured, in case of static allocation, or absent
+    * for dynamic assignment.
+    */
+   public abstract Optional<String> address();
+
+   /**
+    * Flag to indicate if a public ip address should be allocated and bound to
+    * this NIC.
+    */
+   public abstract boolean allocateNewPublicIp();
+   
+   /**
+    * ID of the public IP to associate with the NIC.
+    */
+   @Nullable
+   public abstract String publicIpId();
+   
+   IpOptions() {
+      
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_IpOptions.Builder().address((String) null).allocateNewPublicIp(false);
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder subnet(String subnet);
+      public abstract Builder allocateNewPublicIp(boolean allocatePublicIp);
+      public abstract Builder publicIpId(String publicIpId);
+      
+      abstract Builder address(Optional<String> address);
+      public Builder address(String address) {
+         return address(Optional.fromNullable(address));
+      }
+      
+      public abstract IpOptions build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
index 1f1a37d..3ca1a5d 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
@@ -21,7 +21,10 @@ import static com.google.common.base.Predicates.notNull;
 import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.transform;
 import static com.google.common.collect.Maps.filterValues;
+import static org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.AUTOGENERATED_IP_KEY;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractName;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
 
 import java.net.URI;
 import java.util.HashMap;
@@ -42,8 +45,10 @@ import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.IpConfiguration;
 import org.jclouds.azurecompute.arm.domain.ManagedDiskParameters;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
+import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.OSDisk;
+import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
 import org.jclouds.compute.functions.GroupNamingConvention;
@@ -98,11 +103,11 @@ public class CleanupResources {
 
    public boolean cleanupVirtualMachineNICs(VirtualMachine virtualMachine) {
       boolean deleted = true;
-      for (IdReference nicRef : virtualMachine.properties().networkProfile().networkInterfaces()) {
-         String nicResourceGroup = nicRef.resourceGroup();
-         String nicName = nicRef.name();
-         NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(nicRef.resourceGroup()).get(nicName);
-         
+      for (NetworkInterface nicRef : virtualMachine.properties().networkProfile().networkInterfaces()) {
+         String nicResourceGroup = extractResourceGroup(nicRef.id());
+         String nicName = extractName(nicRef.id());
+         NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(nicResourceGroup).get(nicName);
+
          Iterable<IdReference> publicIps = getPublicIps(nic);
 
          logger.debug(">> destroying nic %s...", nicName);
@@ -112,9 +117,12 @@ public class CleanupResources {
          for (IdReference publicIp : publicIps) {
             String publicIpResourceGroup = publicIp.resourceGroup();
             String publicIpName = publicIp.name();
-            
-            logger.debug(">> deleting public ip nic %s...", publicIpName);
-            deleted &= api.getPublicIPAddressApi(publicIpResourceGroup).delete(publicIpName);
+
+            PublicIPAddress ip = api.getPublicIPAddressApi(publicIpResourceGroup).get(publicIpName);
+            if (ip.tags() != null && Boolean.parseBoolean(ip.tags().get(AUTOGENERATED_IP_KEY))) {
+               logger.debug(">> deleting public ip %s...", publicIpName);
+               deleted &= api.getPublicIPAddressApi(publicIpResourceGroup).delete(publicIpName);
+            }
          }
       }
       return deleted;
@@ -129,15 +137,15 @@ public class CleanupResources {
       for (DataDisk dataDisk : virtualMachine.properties().storageProfile().dataDisks()) {
          deleteManagedDisk(dataDisk.managedDiskParameters(), deleteJobs);
       }
-      
+
       Set<String> nonDeletedDisks = filterValues(deleteJobs, not(resourceDeleted)).keySet();
       if (!nonDeletedDisks.isEmpty()) {
          logger.warn(">> could not delete disks: %s", Joiner.on(',').join(nonDeletedDisks));
       }
-      
+
       return nonDeletedDisks.isEmpty();
    }
-   
+
    private void deleteManagedDisk(@Nullable ManagedDiskParameters managedDisk, Map<String, URI> deleteJobs) {
       if (managedDisk != null) {
          IdReference diskRef = IdReference.create(managedDisk.id());

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
index c3bdbdd..2ddb340 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java
@@ -17,10 +17,13 @@
 package org.jclouds.azurecompute.arm.compute.strategy;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractName;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
+import static org.jclouds.azurecompute.arm.domain.Subnet.extractVirtualNetwork;
 
 import java.util.Arrays;
 import java.util.Map;
@@ -37,13 +40,15 @@ import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
 import org.jclouds.azurecompute.arm.compute.functions.TemplateToAvailabilitySet;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
+import org.jclouds.azurecompute.arm.compute.options.IpOptions;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
+import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.Subnet;
-import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
-import org.jclouds.azurecompute.arm.features.SubnetApi;
-import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
+import org.jclouds.azurecompute.arm.domain.Subnet.SubnetProperties;
+import org.jclouds.azurecompute.arm.domain.VirtualNetwork.AddressSpace;
+import org.jclouds.azurecompute.arm.domain.VirtualNetwork.VirtualNetworkProperties;
 import org.jclouds.compute.config.CustomizationResponse;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.Template;
@@ -56,8 +61,9 @@ import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThen
 import org.jclouds.domain.Location;
 import org.jclouds.logging.Logger;
 
-import com.google.common.base.Optional;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Multimap;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -89,8 +95,7 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
          TemplateToAvailabilitySet templateToAvailabilitySet) {
       super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
             customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
-      this.api = checkNotNull(api, "api cannot be null");
-      checkNotNull(userExecutor, "userExecutor cannot be null");
+      this.api = api;
       this.securityGroupMap = securityGroupMap;
       this.defaultVnetAddressPrefix = defaultVnetAddressPrefix;
       this.defaultSubnetAddressPrefix = defaultSubnetAddressPrefix;
@@ -103,7 +108,7 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
          Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
 
       AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class);
-
+      
       // If there is a script to be run on the node and public key
       // authentication has been configured, warn users if the private key
       // is not present
@@ -112,42 +117,38 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
                + "Authentication will delegate to the ssh-agent");
       }
 
-      // This sill create the resource group if it does not exist
       String location = template.getLocation().getId();
 
       createResourceGroupIfNeeded(group, location, options);
-      getOrCreateVirtualNetworkWithSubnet(location, options);
+      
+      normalizeNetworkOptions(options);
+      createDefaultNetworkIfNeeded(group, location, options);
+      
       configureSecurityGroupForOptions(group, template.getLocation(), options);
       configureAvailabilitySetForTemplate(template);
 
       return super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
    }
 
-   protected synchronized void getOrCreateVirtualNetworkWithSubnet(final String location, AzureTemplateOptions options) {
-      String virtualNetworkName = Optional.fromNullable(options.getVirtualNetworkName()).or(
-            options.getResourceGroup() + "virtualnetwork");
-      String subnetName = options.getResourceGroup() + "subnet";
-
-      // Subnets belong to a virtual network so that needs to be created first
-      VirtualNetworkApi vnApi = api.getVirtualNetworkApi(options.getResourceGroup());
-      VirtualNetwork vn = vnApi.get(virtualNetworkName);
-
-      if (vn == null) {
-         Subnet subnet = Subnet.create(subnetName, null, null,
-               Subnet.SubnetProperties.builder().addressPrefix(defaultSubnetAddressPrefix).build());
-
-         VirtualNetwork.VirtualNetworkProperties virtualNetworkProperties = VirtualNetwork.VirtualNetworkProperties
-               .builder().addressSpace(VirtualNetwork.AddressSpace.create(Arrays.asList(defaultVnetAddressPrefix)))
+   protected synchronized void createDefaultNetworkIfNeeded(String group, String location, AzureTemplateOptions options) {
+      if (options.getIpOptions().isEmpty()) {
+         String name = namingConvention.create().sharedNameForGroup(group);
+         
+         Subnet subnet = Subnet.builder().name(name)
+               .properties(SubnetProperties.builder().addressPrefix(defaultSubnetAddressPrefix).build()).build();
+         
+         VirtualNetworkProperties properties = VirtualNetworkProperties.builder()
+               .addressSpace(AddressSpace.create(Arrays.asList(defaultVnetAddressPrefix)))
                .subnets(Arrays.asList(subnet)).build();
-
-         vn = vnApi.createOrUpdate(virtualNetworkName, location, virtualNetworkProperties);
+         
+         logger.debug(">> network options have not been configured. Creating network %s(%s) and subnet %s(%s)", name,
+               defaultVnetAddressPrefix, name, defaultSubnetAddressPrefix);
+         
+         api.getVirtualNetworkApi(options.getResourceGroup()).createOrUpdate(name, location, properties);
+         Subnet createdSubnet = api.getSubnetApi(options.getResourceGroup(), name).get(name);
+         
+         options.ipOptions(IpOptions.builder().subnet(createdSubnet.id()).allocateNewPublicIp(true).build());
       }
-
-      SubnetApi subnetApi = api.getSubnetApi(options.getResourceGroup(), virtualNetworkName);
-      Subnet subnet = subnetApi.get(subnetName);
-
-      options.virtualNetworkName(virtualNetworkName);
-      options.subnetId(subnet.id());
    }
 
    private static boolean hasRunScriptWithKeyAuthAndNoPrivateKey(Template template) {
@@ -196,4 +197,45 @@ public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedI
                ImmutableMap.of("description", "jclouds default resource group"));
       }
    }
+   
+   @VisibleForTesting
+   void normalizeNetworkOptions(AzureTemplateOptions options) {
+      if (!options.getNetworks().isEmpty() && !options.getIpOptions().isEmpty()) {
+         throw new IllegalArgumentException("The options.networks and options.ipOptions are exclusive");
+      }
+      
+      if (!options.getNetworks().isEmpty() && options.getIpOptions().isEmpty()) {
+         // The portable interface allows to configure network IDs (subnet IDs),
+         // but we don't know the type of the IP configurations to be applied
+         // when attaching nodes to those networks. We'll assume private IPs
+         // with Dynamic allocation and no public ip address associated.
+         ImmutableList.Builder<IpOptions> ipOptions = ImmutableList.builder();
+         for (String subnetId : options.getNetworks()) {
+            ipOptions.add(IpOptions.builder().subnet(subnetId).build());
+         }
+         options.ipOptions(ipOptions.build());
+      }
+      
+      if (!options.getIpOptions().isEmpty()) {
+         // Eagerly validate that all configured subnets exist.
+         for (IpOptions ipConfig : options.getIpOptions()) {
+            if (ipConfig.allocateNewPublicIp() && ipConfig.publicIpId() != null) {
+               throw new IllegalArgumentException("The allocateNewPublicIps and publicIpId are exclusive");
+            }
+            
+            String resourceGroup = extractResourceGroup(ipConfig.subnet());
+            String networkName = extractVirtualNetwork(ipConfig.subnet());
+            String subnetName = extractName(ipConfig.subnet());
+            
+            Subnet subnet = api.getSubnetApi(resourceGroup, networkName).get(subnetName);
+            checkState(subnet != null, "Configured subnet %s does not exist", ipConfig.subnet());
+            
+            if (ipConfig.publicIpId() != null) {
+               PublicIPAddress publicIp = api.getPublicIPAddressApi(extractResourceGroup(ipConfig.publicIpId())).get(
+                     extractName(ipConfig.publicIpId()));
+               checkState(publicIp != null, "Configured public ip %s does not exist", ipConfig.publicIpId());               
+            }
+         }
+      }
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java
index d1976f1..84c8ca2 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java
@@ -26,23 +26,16 @@ import java.util.List;
 @AutoValue
 public abstract class NetworkInterfaceCardProperties implements Provisionable {
 
-   @Nullable
-   public abstract String provisioningState();
-
-   @Nullable
-   public abstract String resourceGuid();
-
-   @Nullable
-   public abstract Boolean enableIPForwarding();
-
-   @Nullable
-   public abstract List<IpConfiguration> ipConfigurations();
-
-   @Nullable
-   public abstract IdReference networkSecurityGroup();
+   @Nullable public abstract String provisioningState();
+   @Nullable public abstract String resourceGuid();
+   @Nullable public abstract Boolean enableIPForwarding();
+   @Nullable public abstract List<IpConfiguration> ipConfigurations();
+   @Nullable public abstract IdReference networkSecurityGroup();
 
    @SerializedNames({"provisioningState", "resourceGuid", "enableIPForwarding", "ipConfigurations", "networkSecurityGroup"})
-   public static NetworkInterfaceCardProperties create(final String provisioningState, final String resourceGuid, final Boolean enableIPForwarding, final List<IpConfiguration> ipConfigurations, final IdReference networkSecurityGroup) {
+   public static NetworkInterfaceCardProperties create(final String provisioningState, final String resourceGuid,
+         final Boolean enableIPForwarding, final List<IpConfiguration> ipConfigurations,
+         final IdReference networkSecurityGroup) {
       NetworkInterfaceCardProperties.Builder builder = NetworkInterfaceCardProperties.builder()
               .provisioningState(provisioningState)
               .resourceGuid(resourceGuid)
@@ -52,28 +45,26 @@ public abstract class NetworkInterfaceCardProperties implements Provisionable {
 
       return builder.build();
    }
-   
+
+   NetworkInterfaceCardProperties() {
+
+   }
+
    public abstract Builder toBuilder();
 
    public static Builder builder() {
-
       return new AutoValue_NetworkInterfaceCardProperties.Builder();
    }
 
    @AutoValue.Builder
    public abstract static class Builder {
       public abstract Builder provisioningState(String provisioningState);
-
       public abstract Builder resourceGuid(String resourceGuid);
-
       public abstract Builder enableIPForwarding(Boolean enableIPForwarding);
-
       public abstract Builder ipConfigurations(List<IpConfiguration> ipConfigurations);
-
-      abstract List<IpConfiguration> ipConfigurations();
-
       public abstract Builder networkSecurityGroup(IdReference networkSecurityGroup);
 
+      abstract List<IpConfiguration> ipConfigurations();
       abstract NetworkInterfaceCardProperties autoBuild();
 
       public NetworkInterfaceCardProperties build() {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkProfile.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkProfile.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkProfile.java
index b26305f..cdb6d51 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkProfile.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkProfile.java
@@ -19,6 +19,7 @@ package org.jclouds.azurecompute.arm.domain;
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableList;
 
+import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
 import java.util.List;
@@ -26,16 +27,49 @@ import java.util.List;
 @AutoValue
 public abstract class NetworkProfile {
 
+   @AutoValue
+   public abstract static class NetworkInterface {
+      public abstract String id();
+      @Nullable public abstract NetworkInterfaceProperties properties();
+      
+      @AutoValue
+      public abstract static class NetworkInterfaceProperties {
+         public abstract boolean primary();
+         
+         NetworkInterfaceProperties() {
+            
+         }
+         
+         @SerializedNames({"primary"})
+         public static NetworkInterfaceProperties create(boolean primary) {
+            return new AutoValue_NetworkProfile_NetworkInterface_NetworkInterfaceProperties(primary);
+         }
+      }
+      
+      NetworkInterface() {
+         
+      }
+      
+      @SerializedNames({"id", "properties"})
+      public static NetworkInterface create(String id, NetworkInterfaceProperties properties) {
+         return new AutoValue_NetworkProfile_NetworkInterface(id, properties);
+      }
+   }
+   
    /**
     * List of network interfaces
     */
-   public abstract List<IdReference> networkInterfaces();
+   public abstract List<NetworkInterface> networkInterfaces();
 
    @SerializedNames({"networkInterfaces"})
-   public static NetworkProfile create(final List<IdReference> networkInterfaces) {
+   public static NetworkProfile create(final List<NetworkInterface> networkInterfaces) {
       return builder().networkInterfaces(networkInterfaces).build();
    }
    
+   NetworkProfile() {
+      
+   }
+   
    public abstract Builder toBuilder();
 
    public static Builder builder() {
@@ -44,14 +78,14 @@ public abstract class NetworkProfile {
 
    @AutoValue.Builder
    public abstract static class Builder {
-      public abstract Builder networkInterfaces(List<IdReference> networkInterfaces);
+      public abstract Builder networkInterfaces(List<NetworkInterface> networkInterfaces);
 
-      abstract List<IdReference> networkInterfaces();
+      abstract List<NetworkInterface> networkInterfaces();
 
       abstract NetworkProfile autoBuild();
 
       public NetworkProfile build() {
-         networkInterfaces(networkInterfaces() != null ? ImmutableList.copyOf(networkInterfaces()) : ImmutableList.<IdReference>of());
+         networkInterfaces(networkInterfaces() != null ? ImmutableList.copyOf(networkInterfaces()) : ImmutableList.<NetworkInterface>of());
          return autoBuild();
       }
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/PublicIPAddress.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/PublicIPAddress.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/PublicIPAddress.java
index a08fadd..8d0cb2b 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/PublicIPAddress.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/PublicIPAddress.java
@@ -17,36 +17,55 @@
 
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
-import java.util.Map;
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
 
 @AutoValue
 public abstract class PublicIPAddress {
 
    public abstract String name();
-
    public abstract String id();
-
    public abstract String etag();
-
    public abstract String location();
+   @Nullable public abstract Map<String, String> tags();
+   public abstract PublicIPAddressProperties properties();
+
+   @SerializedNames({ "name", "id", "etag", "location", "tags", "properties" })
+   public static PublicIPAddress create(String name, String id, String etag, String location, Map<String, String> tags,
+         PublicIPAddressProperties properties) {
+      return builder().name(name).id(id).etag(etag).location(location).tags(tags).properties(properties).build();
+   }
+   
+   PublicIPAddress() {
+      
+   }
+   
+   public abstract Builder toBuilder();
 
-   @Nullable
-   public abstract Map<String, String> tags();
+   public static Builder builder() {
+      return new AutoValue_PublicIPAddress.Builder();
+   }
 
-   public abstract PublicIPAddressProperties properties();
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder name(String name);
+      public abstract Builder id(String id);
+      public abstract Builder etag(String etag);
+      public abstract Builder location(String location);
+      public abstract Builder tags(Map<String, String> tags);
+      public abstract Builder properties(PublicIPAddressProperties properties);
+      
+      abstract Map<String, String> tags();
+      abstract PublicIPAddress autoBuild();
 
-   @SerializedNames({"name", "id", "etag", "location", "tags", "properties"})
-   public static PublicIPAddress create(final String name,
-                                        final String id,
-                                        final String etag,
-                                        final String location,
-                                        final Map<String, String> tags,
-                                        final PublicIPAddressProperties properties) {
-      return new AutoValue_PublicIPAddress(name, id, etag, location, tags == null ? null : ImmutableMap.copyOf(tags), properties);
+      public PublicIPAddress build() {
+         tags(tags() != null ? ImmutableMap.copyOf(tags()) : null);
+         return autoBuild();
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Subnet.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Subnet.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Subnet.java
index 6830438..80460b8 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Subnet.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Subnet.java
@@ -19,6 +19,8 @@ package org.jclouds.azurecompute.arm.domain;
 import static com.google.common.collect.ImmutableList.copyOf;
 
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import com.google.common.collect.ImmutableList;
 
@@ -29,6 +31,8 @@ import org.jclouds.json.SerializedNames;
 @AutoValue
 public abstract class Subnet {
 
+   private static final Pattern NETWORK_PATTERN = Pattern.compile("^.*/virtualNetworks/([^/]+)(/.*)?$");
+   
    @AutoValue
    public abstract static class IpConfiguration {
 
@@ -38,19 +42,18 @@ public abstract class Subnet {
       public static IpConfiguration create(final String id) {
          return new AutoValue_Subnet_IpConfiguration(id);
       }
+      
+      IpConfiguration() {
+         
+      }
    }
 
    @AutoValue
    public abstract static class SubnetProperties implements Provisionable {
 
-      @Nullable
-      public abstract String provisioningState();
-
-      @Nullable
-      public abstract String addressPrefix();
-
-      @Nullable
-      public abstract List<IpConfiguration> ipConfigurations();
+      @Nullable public abstract String provisioningState();
+      @Nullable public abstract String addressPrefix();
+      @Nullable public abstract List<IpConfiguration> ipConfigurations();
 
       @SerializedNames({"provisioningState", "addressPrefix", "ipConfigurations"})
       public static SubnetProperties create(final String provisioningState, final String addressPrefix, final List<IpConfiguration> ipConfigurations) {
@@ -61,6 +64,10 @@ public abstract class Subnet {
                  .build();
       }
       
+      SubnetProperties() {
+         
+      }
+      
       public abstract Builder toBuilder();
 
       public static Builder builder() {
@@ -70,13 +77,10 @@ public abstract class Subnet {
       @AutoValue.Builder
       public abstract static class Builder {
          public abstract Builder provisioningState(String provisioningState);
-
          public abstract Builder addressPrefix(String addressPrefix);
-
          public abstract Builder ipConfigurations(List<IpConfiguration> ipConfigurations);
 
          abstract List<IpConfiguration> ipConfigurations();
-
          abstract SubnetProperties autoBuild();
 
          public SubnetProperties build() {
@@ -86,23 +90,47 @@ public abstract class Subnet {
       }
    }
 
-   @Nullable
-   public abstract String name();
-
-   @Nullable
-   public abstract String id();
-
-   @Nullable
-   public abstract String etag();
-
-   @Nullable
-   public abstract SubnetProperties properties();
+   @Nullable public abstract String name();
+   @Nullable public abstract String id();
+   @Nullable public abstract String etag();
+   @Nullable public abstract SubnetProperties properties();
+   
+   @Nullable public String virtualNetwork() {
+      return extractVirtualNetwork(id());
+   }
+   
+   public static String extractVirtualNetwork(String id) {
+      if (id == null)
+         return null;
+      Matcher m = NETWORK_PATTERN.matcher(id);
+      m.matches();
+      return m.group(1);
+   }
 
    @SerializedNames({"name", "id", "etag", "properties"})
    public static Subnet create(final String name,
                                final String id,
                                final String etag,
                                final SubnetProperties properties) {
-      return new AutoValue_Subnet(name, id, etag, properties);
+      return builder().name(name).id(id).etag(etag).properties(properties).build();
+   }
+   
+   Subnet() {
+      
+   }
+   
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_Subnet.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder name(String name);
+      public abstract Builder id(String id);
+      public abstract Builder etag(String etag);
+      public abstract Builder properties(SubnetProperties properties);
+      public abstract Subnet build();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApi.java
index 2693753..75af4ff 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/PublicIPAddressApi.java
@@ -34,6 +34,7 @@ import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
 import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.functions.FalseOn204;
+import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.MapBinder;
@@ -60,7 +61,7 @@ public interface PublicIPAddressApi {
    @PUT
    PublicIPAddress createOrUpdate(@PathParam("publicipaddressname") String publicipaddressname,
                                                  @PayloadParam("location") String location,
-                                                 @PayloadParam("tags") Map<String, String> tags,
+                                                 @Nullable @PayloadParam("tags") Map<String, String> tags,
                                                  @PayloadParam("properties") PublicIPAddressProperties properties);
 
    @Named("publicipaddress:get")

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java
new file mode 100644
index 0000000..f95430c
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodesTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.compute.strategy;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
+import org.jclouds.azurecompute.arm.compute.options.IpOptions;
+import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
+import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
+import org.jclouds.azurecompute.arm.domain.Subnet;
+import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
+import org.jclouds.azurecompute.arm.features.SubnetApi;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+@Test(groups = "unit", testName = "CreateResourcesThenCreateNodesTest")
+public class CreateResourcesThenCreateNodesTest {
+
+   @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "The options.networks and options.ipOptions are exclusive")
+   public void testNormalizeNetworkOptionsWithConflictingConfig() {
+      AzureTemplateOptions options = new AzureTemplateOptions();
+      options.ipOptions(IpOptions.builder().subnet(netResource("/virtualNetworks/vn/subnets/foo")).build());
+      options.networks(netResource("/virtualNetworks/vn/subnets/bar"));
+      strategy(null).normalizeNetworkOptions(options);
+   }
+   
+   @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "The allocateNewPublicIps and publicIpId are exclusive")
+   public void testNormalizeNetworkOptionsExclusivePublicIps() {
+      AzureTemplateOptions options = new AzureTemplateOptions();
+      options.ipOptions(IpOptions.builder().subnet(netResource("/virtualNetworks/vn/subnets/foo"))
+            .allocateNewPublicIp(true).publicIpId(netResource("/publicIPAddresses/pub")).build());
+      strategy(null).normalizeNetworkOptions(options);
+   }
+
+   public void testPortableNetworkOptions() {
+      AzureComputeApi api = createMock(AzureComputeApi.class);
+      SubnetApi subnetApi = createMock(SubnetApi.class);
+
+      expect(api.getSubnetApi(anyObject(String.class), anyObject(String.class))).andReturn(subnetApi).times(2);
+      expect(subnetApi.get(anyObject(String.class))).andReturn(Subnet.builder().build()).times(2);
+      replay(api, subnetApi);
+
+      AzureTemplateOptions options = new AzureTemplateOptions();
+      options.networks(netResource("/virtualNetworks/vn/subnets/foo"), netResource("/virtualNetworks/vn/subnets/bar"));
+      strategy(api).normalizeNetworkOptions(options);
+
+      assertEquals(options.getIpOptions(), ImmutableList.of(
+            IpOptions.builder().subnet(netResource("/virtualNetworks/vn/subnets/foo")).build(), IpOptions.builder()
+                  .subnet(netResource("/virtualNetworks/vn/subnets/bar")).build()));
+
+      // Verify that the code has validated that the subnets exist
+      verify(api, subnetApi);
+   }
+
+   public void testProviderSpecificNetworkOptions() {
+      AzureComputeApi api = createMock(AzureComputeApi.class);
+      SubnetApi subnetApi = createMock(SubnetApi.class);
+      PublicIPAddressApi publicIpApi = createMock(PublicIPAddressApi.class);
+
+      expect(api.getSubnetApi(anyObject(String.class), anyObject(String.class))).andReturn(subnetApi).times(2);
+      expect(api.getPublicIPAddressApi(anyObject(String.class))).andReturn(publicIpApi);
+      expect(subnetApi.get(anyObject(String.class))).andReturn(Subnet.builder().build()).times(2);
+      expect(publicIpApi.get(anyObject(String.class))).andReturn(mockAddress());
+      replay(api, subnetApi, publicIpApi);
+
+      IpOptions publicOpts = IpOptions.builder().subnet(netResource("/virtualNetworks/vn/subnets/foo"))
+            .publicIpId(netResource("/publicIPAddresses/pub")).address("10.0.0.2").build();
+      IpOptions privateOpts = IpOptions.builder().subnet(netResource("/virtualNetworks/vn/subnets/bar")).build();
+
+      AzureTemplateOptions options = new AzureTemplateOptions();
+      options.ipOptions(publicOpts, privateOpts);
+      strategy(api).normalizeNetworkOptions(options);
+
+      assertEquals(options.getIpOptions(), ImmutableList.of(publicOpts, privateOpts));
+
+      // Verify that the code has validated that the subnets exist
+      verify(api, subnetApi, publicIpApi);
+   }
+
+   private static CreateResourcesThenCreateNodes strategy(AzureComputeApi api) {
+      return new CreateResourcesThenCreateNodes(null, null, null, null, null, api, null, null, null, null);
+   }
+
+   private static String netResource(String resource) {
+      return "/subscriptions/subs/resourceGroups/rg/providers/Microsoft.Network" + resource;
+   }
+
+   private static PublicIPAddress mockAddress() {
+      return PublicIPAddress.builder().name("name").id("id").etag("etag").location("location")
+            .properties(PublicIPAddressProperties.builder().publicIPAllocationMethod("Dynamic").build()).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/IdReferenceTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/IdReferenceTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/IdReferenceTest.java
index e5426d7..e2a56e1 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/IdReferenceTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/IdReferenceTest.java
@@ -22,6 +22,7 @@ import static org.testng.Assert.assertEquals;
 
 import org.testng.annotations.Test;
 
+@Test(groups = "unit", testName = "IdReferenceTest")
 public class IdReferenceTest {
 
    @Test

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/SubnetTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/SubnetTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/SubnetTest.java
new file mode 100644
index 0000000..a5ef44c
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/SubnetTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "SubnetTest")
+public class SubnetTest {
+
+   @Test
+   public void testExtractVirtualNetwork() {
+
+      assertEquals(Subnet.builder().build().virtualNetwork(), null);
+      assertEquals(
+            Subnet.builder()
+                  .id("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/virtualNetworks/vn/subnets/subnet")
+                  .build().virtualNetwork(), "vn");
+      assertInvalidId("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/virtualNetworks");
+      assertInvalidId("virtualNetworks/vn");
+   }
+
+   private static void assertInvalidId(String id) {
+      try {
+         Subnet.builder().id(id).build().virtualNetwork();
+         fail("The given ID " + id + "should not match a valid virtual network");
+      } catch (IllegalStateException ex) {
+         // Expected
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
index c5b836b..5cf4239 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
@@ -23,6 +23,7 @@ import static com.google.common.collect.Iterables.transform;
 import static com.google.common.collect.Lists.newArrayList;
 import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.availabilitySet;
 import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.azurecompute.arm.domain.IdReference.extractName;
 import static org.jclouds.azurecompute.arm.domain.InboundNatRuleProperties.Protocol.Tcp;
 import static org.jclouds.compute.predicates.NodePredicates.inGroup;
 import static org.testng.Assert.assertEquals;
@@ -360,7 +361,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
          VirtualMachine vm = api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).get(
                resourceGroupAndName.name());
 
-         String nicName = vm.properties().networkProfile().networkInterfaces().get(0).name();
+         String nicName = extractName(vm.properties().networkProfile().networkInterfaces().get(0).id());
          nicNames.add(nicName);
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiMockTest.java
index e0f0ed4..dd10046 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/NetworkInterfaceCardApiMockTest.java
@@ -40,7 +40,7 @@ public class NetworkInterfaceCardApiMockTest extends BaseAzureComputeApiMockTest
 
    private final String subscriptionid = "SUBSCRIPTIONID";
    private final String resourcegroup = "myresourcegroup";
-   private final String apiVersion = "api-version=2015-06-15";
+   private final String apiVersion = "api-version=2017-03-01";
    private final String location = "northeurope";
    private final String nicName = "myNic";
 
@@ -65,7 +65,8 @@ public class NetworkInterfaceCardApiMockTest extends BaseAzureComputeApiMockTest
 
       assertNull(nicApi.get(nicName));
 
-      assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourcegroups/myresourcegroup/providers/Microsoft.Network/networkInterfaces/myNic?api-version=2015-06-15");
+      String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Network/networkInterfaces/%s?%s", subscriptionid, resourcegroup, nicName, apiVersion);
+      assertSent(server, "GET", path);
    }
 
    public void listNetworkInterfaceCards() throws InterruptedException {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/df300573/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/SubnetApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/SubnetApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/SubnetApiMockTest.java
index 0113201..3d58591 100644
--- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/SubnetApiMockTest.java
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/SubnetApiMockTest.java
@@ -36,7 +36,7 @@ public class SubnetApiMockTest extends BaseAzureComputeApiMockTest {
    private final String resourcegroup = "myresourcegroup";
    private final String virtualNetwork = "myvirtualnetwork";
    private final String subnetName = "mysubnet";
-   private final String apiVersion = "api-version=2015-06-15";
+   private final String apiVersion = "api-version=2017-03-01";
 
    public void createSubnet() throws InterruptedException {
 


[27/50] [abbrv] jclouds git commit: Cleanup extraneous resources

Posted by na...@apache.org.
Cleanup extraneous resources

This was not being called as doDestroyNode returns once node deleted.

Change based on similar code on gce compute provider


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

Branch: refs/heads/master
Commit: 4e6642099748c9ab190aced95f6386a128ea41f0
Parents: b38ce8d
Author: Duncan Grant <du...@cloudsoftcorp.com>
Authored: Thu Aug 24 13:11:47 2017 +0100
Committer: Andrea Turli <an...@gmail.com>
Committed: Fri Aug 25 09:09:44 2017 +0200

----------------------------------------------------------------------
 .../arm/compute/AzureComputeService.java        | 27 ++++++++++++++++++++
 1 file changed, 27 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/4e664209/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
index dcb9c44..e82110a 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java
@@ -16,9 +16,12 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Sets.newHashSet;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static org.jclouds.compute.predicates.NodePredicates.all;
 
 import java.util.Map;
 import java.util.Map.Entry;
@@ -124,4 +127,28 @@ public class AzureComputeService extends BaseComputeService {
          cleanupResources.deleteResourceGroupIfEmpty(resourceGroup);
       }
    }
+
+   @Override
+   public void destroyNode(String id) {
+      // Azure ARM does not return TERMINATED nodes, so in practice no node will never reach the TERMINATED
+      // state, and the deleted nodes will never be returned.
+      // In order to be able to clean up the resources associated to the deleted nodes, we have to retrieve
+      // the details of the nodes before deleting them.
+      NodeMetadata nodeMetadataBeforeDelete = getNodeMetadata(id);
+      super.destroyNode(id);
+      //Node metadata is null after deletion but we still need to clean up incidental resources
+      cleanUpIncidentalResourcesOfDeadNodes(ImmutableSet.of(nodeMetadataBeforeDelete));
+   }
+
+   @Override
+   public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<? super NodeMetadata> filter) {
+      // Azure ARM does not return TERMINATED nodes, so in practice no node will never reach the TERMINATED
+      // state, and the deleted nodes will never be returned.
+      // In order to be able to clean up the resources associated to the deleted nodes, we have to retrieve
+      // the details of the nodes before deleting them.
+      Set<? extends NodeMetadata> nodes = newHashSet(filter(listNodesDetailsMatching(all()), filter));
+      super.destroyNodesMatching(filter); // This returns an empty list (a list of null elements) in Azure ARM, as the api does not return deleted nodes
+      cleanUpIncidentalResourcesOfDeadNodes(nodes);
+      return nodes;
+   }
 }


[20/50] [abbrv] jclouds git commit: Implements metrics and metricdefinitions API

Posted by na...@apache.org.
Implements metrics and metricdefinitions API


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

Branch: refs/heads/master
Commit: b2cc647ff220df6129eb8b508325a34c8ce5a44c
Parents: 9718bec
Author: Dani Estevez <co...@danielestevez.com>
Authored: Fri Jun 2 16:23:20 2017 -0400
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Jun 28 08:58:54 2017 +0200

----------------------------------------------------------------------
 .../azurecompute/arm/AzureComputeApi.java       |  20 +++
 .../arm/AzureComputeProviderMetadata.java       |   4 +
 .../jclouds/azurecompute/arm/domain/Metric.java |  51 +++++++
 .../azurecompute/arm/domain/MetricData.java     |  74 ++++++++++
 .../arm/domain/MetricDefinition.java            |  97 +++++++++++++
 .../azurecompute/arm/domain/MetricName.java     |  38 +++++
 .../arm/features/MetricDefinitionsApi.java      |  52 +++++++
 .../azurecompute/arm/features/MetricsApi.java   |  51 +++++++
 .../features/MetricDefinitionsApiLiveTest.java  | 131 +++++++++++++++++
 .../features/MetricDefinitionsApiMockTest.java  |  65 +++++++++
 .../arm/features/MetricsApiLiveTest.java        | 143 +++++++++++++++++++
 .../arm/features/MetricsApiMockTest.java        |  72 ++++++++++
 .../src/test/resources/metricdefinitions.json   |  25 ++++
 .../src/test/resources/metrics.json             |  19 +++
 14 files changed, 842 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index a25690f..123f6e3 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -27,6 +27,8 @@ import org.jclouds.azurecompute.arm.features.ImageApi;
 import org.jclouds.azurecompute.arm.features.JobApi;
 import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
 import org.jclouds.azurecompute.arm.features.LocationApi;
+import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
+import org.jclouds.azurecompute.arm.features.MetricsApi;
 import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
@@ -208,4 +210,22 @@ public interface AzureComputeApi extends Closeable {
     */
    @Delegate
    ImageApi getVirtualMachineImageApi(@PathParam("resourcegroup") String resourcegroup);
+
+   /**
+    * The metrics API includes operations to get insights into entities within your
+    * subscription.
+    *
+    * @see <a href="https://docs.microsoft.com/en-us/rest/api/monitor/metrics">docs</a>
+    */
+   @Delegate
+   MetricsApi getMetricsApi(@PathParam("resourceid") String resourceid);
+
+   /**
+    * The metric definitions API includes operations to get insights available for entities within your
+    * subscription.
+    *
+    * @see <a href="https://docs.microsoft.com/en-us/rest/api/monitor/metricdefinitions">docs</a>
+    */
+   @Delegate
+   MetricDefinitionsApi getMetricsDefinitionsApi(@PathParam("resourceid") String resourceid);
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index c35455c..6a5c587 100644
--- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -44,6 +44,8 @@ import org.jclouds.azurecompute.arm.features.ImageApi;
 import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
 import org.jclouds.azurecompute.arm.features.LocationApi;
 import org.jclouds.azurecompute.arm.features.DiskApi;
+import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
+import org.jclouds.azurecompute.arm.features.MetricsApi;
 import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
@@ -115,6 +117,8 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(API_VERSION_PREFIX + AvailabilitySetApi.class.getSimpleName(), "2016-04-30-preview");
       properties.put(API_VERSION_PREFIX + DiskApi.class.getSimpleName(), "2017-03-30");
       properties.put(API_VERSION_PREFIX + ImageApi.class.getSimpleName(), "2016-04-30-preview");
+      properties.put(API_VERSION_PREFIX + MetricDefinitionsApi.class.getSimpleName(), "2017-05-01-preview");
+      properties.put(API_VERSION_PREFIX + MetricsApi.class.getSimpleName(), "2016-09-01");
       
       return properties;
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Metric.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Metric.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Metric.java
new file mode 100644
index 0000000..0320db2
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Metric.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 java.util.List;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * A Metric with its values for a resource
+ */
+@AutoValue
+public abstract class Metric {
+
+   public abstract List<MetricData> data();
+
+   public abstract String id();
+
+   @Nullable
+   public abstract MetricName name();
+
+   public abstract String type();
+
+   public abstract String unit();
+
+   @SerializedNames({ "data", "id", "name", "type", "unit" })
+   public static Metric create(final List<MetricData> data, final String id, final MetricName name, final String type,
+         final String unit) {
+      return new AutoValue_Metric(data == null ? ImmutableList.<MetricData> of() : ImmutableList.copyOf(data), id, name,
+            type, unit);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricData.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricData.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricData.java
new file mode 100644
index 0000000..29e810e
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricData.java
@@ -0,0 +1,74 @@
+/*
+ * 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.Date;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+/**
+ *
+ */
+@AutoValue
+public abstract class MetricData
+{
+
+    /**
+     * The timestamp for the metric value in ISO 8601 format.
+     */
+    public abstract Date timeStamp();
+
+    /**
+     * The average value in the time range
+     */
+    @Nullable
+    public abstract Double total();
+
+    /**
+     * The sum of all of the values in the time range.
+     */
+    @Nullable
+    public abstract Double average();
+
+    /**
+     * The least value in the time range.
+     */
+    @Nullable
+    public abstract Double minimum();
+
+    /**
+     * The greatest value in the time range.
+     */
+    @Nullable
+    public abstract Double maximum();
+
+    /**
+     * The number of samples in the time range.
+     */
+    @Nullable
+    public abstract Long count();
+
+    @SerializedNames({"timeStamp", "total", "average", "minimum", "maximum", "count"})
+    public static MetricData create(final Date timeStamp, final Double total, final Double average,
+        final Double minimum, final Double maximum, final Long count)
+    {
+        return new AutoValue_MetricData(timeStamp, total, average, minimum, maximum, count);
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricDefinition.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricDefinition.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricDefinition.java
new file mode 100644
index 0000000..95f8d47
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricDefinition.java
@@ -0,0 +1,97 @@
+/*
+ * 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;
+
+import org.jclouds.azurecompute.arm.util.GetEnumValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * A Metric definition for a resource
+ */
+@AutoValue
+public abstract class MetricDefinition {
+
+   public enum AggregationType {
+      None("None"), Average("Average"), Count("Count"), Total("Total"), Minimum("Minimum"), Maximum(
+            "Maximum"), UNRECOGNIZED("Unrecognized");
+
+      private final String label;
+
+      AggregationType(String label) {
+         this.label = label;
+      }
+
+      public static AggregationType fromValue(final String text) {
+         return (AggregationType) GetEnumValue.fromValueOrDefault(text, AggregationType.UNRECOGNIZED);
+      }
+
+      @Override
+      public String toString() {
+         return label;
+      }
+   }
+
+   @Nullable
+   public abstract String resourceId();
+
+   public abstract MetricName name();
+
+   @Nullable
+   public abstract Boolean isDimensionRequired();
+
+   public abstract String unit();
+
+   public abstract AggregationType primaryAggregationType();
+
+   public abstract List<MetricDefinition.MetricAvailability> metricAvailabilities();
+
+   public abstract String id();
+
+   @SerializedNames({ "resourceId", "name", "isDimensionRequired", "unit", "primaryAggregationType",
+         "metricAvailabilities", "id" })
+   public static MetricDefinition create(final String resourceId, final MetricName name,
+         final Boolean isDimensionRequired, final String unit, final AggregationType primaryAggregationType,
+         List<MetricAvailability> metricAvailabilities, final String id) {
+      return new AutoValue_MetricDefinition(resourceId, name, isDimensionRequired, unit, primaryAggregationType,
+            metricAvailabilities == null ?
+                  ImmutableList.<MetricAvailability> of() :
+                  ImmutableList.copyOf(metricAvailabilities), id);
+   }
+
+   @AutoValue
+   public abstract static class MetricAvailability {
+
+      public abstract String timeGrain();
+
+      public abstract String retention();
+
+      MetricAvailability() {
+
+      }
+
+      @SerializedNames({ "timeGrain", "retention" })
+      public static MetricDefinition.MetricAvailability create(String timeGrain, String retention) {
+         return new AutoValue_MetricDefinition_MetricAvailability(timeGrain, retention);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricName.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricName.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricName.java
new file mode 100644
index 0000000..7caf52e
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/MetricName.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.domain;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+/**
+ * A Metric with its values for a resource
+ */
+@AutoValue
+public abstract class MetricName {
+
+   public abstract String value();
+
+   public abstract String localizedValue();
+
+   @SerializedNames({ "value", "localizedValue" })
+   public static MetricName create(String value, String localizedValue) {
+      return new AutoValue_MetricName(value, localizedValue);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApi.java
new file mode 100644
index 0000000..ba62a28
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApi.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.features;
+
+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.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.azurecompute.arm.domain.MetricDefinition;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+
+/**
+ * This Azure Resource Manager API provides all the metric definitions available for a given resource
+ * <p/>
+ *
+ * @see <a href="https://docs.microsoft.com/en-us/rest/api/monitor/metricdefinitions">docs</a>
+ */
+@Path("/{resourceid}")
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
+@Consumes(MediaType.APPLICATION_JSON)
+public interface MetricDefinitionsApi {
+   @Named("metrics:list")
+   @Path("/providers/microsoft.insights/metricdefinitions")
+   @GET
+   @SelectJson("value")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<MetricDefinition> list(@Nullable @QueryParam("$filter") String filter);
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/MetricsApi.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/MetricsApi.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/MetricsApi.java
new file mode 100644
index 0000000..03d19a1
--- /dev/null
+++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/MetricsApi.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.features;
+
+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.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.azurecompute.arm.domain.Metric;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+
+/**
+ * This Azure Resource Manager API provides all the metric data available for a given resource
+ * <p/>
+ *
+ * @see <a href="https://docs.microsoft.com/en-us/rest/api/monitor/metricdefinitions">docs</a>
+ */
+@Path("/{resourceid}")
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
+@Consumes(MediaType.APPLICATION_JSON)
+public interface MetricsApi {
+   @Named("metrics:list")
+   @Path("/providers/microsoft.insights/metrics")
+   @GET
+   @SelectJson("value")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Metric> list(@QueryParam("$filter") String filter);
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApiLiveTest.java
new file mode 100644
index 0000000..cb8027f
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApiLiveTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.resourceGroup;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.compute.predicates.NodePredicates.inGroup;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Properties;
+
+import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.domain.IdReference;
+import org.jclouds.azurecompute.arm.domain.MetricDefinition;
+import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
+
+@Test(groups = "live", singleThreaded = true)
+public class MetricDefinitionsApiLiveTest extends BaseComputeServiceContextLiveTest {
+
+   private Predicate<URI> resourceDeleted;
+   private AzureComputeApi api;
+
+   private String location;
+   private MetricDefinitionsApi metricDefinitionsApi;
+
+   private String group;
+
+   public MetricDefinitionsApiLiveTest() {
+      provider = "azurecompute-arm";
+      group = getClass().getSimpleName().toLowerCase();
+   }
+
+   @Override
+   protected Properties setupProperties() {
+      Properties properties = super.setupProperties();
+      AzureLiveTestUtils.defaultProperties(properties);
+      checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
+      return properties;
+   }
+
+   @Override
+   protected void initializeContext() {
+      super.initializeContext();
+      resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
+      }, Names.named(TIMEOUT_RESOURCE_DELETED)));
+      api = view.unwrapApi(AzureComputeApi.class);
+   }
+
+   @Override
+   @BeforeClass
+   public void setupContext() {
+      super.setupContext();
+      NodeMetadata node = null;
+      try {
+         node = getOnlyElement(view.getComputeService().createNodesInGroup(group, 1, resourceGroup(group)));
+      } catch (RunNodesException e) {
+         fail();
+      }
+      String resourceId = String.format("/resourceGroups/%s/providers/Microsoft.Compute/virtualMachines/%s",
+            IdReference.extractResourceGroup(node.getProviderId()), IdReference.extractName(node.getProviderId()));
+
+      location = view.getComputeService().templateBuilder().build().getLocation().getId();
+      view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(group, location, null);
+      metricDefinitionsApi = api.getMetricsDefinitionsApi(resourceId);
+   }
+
+   @Override
+   @AfterClass(alwaysRun = true)
+   protected void tearDownContext() {
+      try {
+         view.getComputeService().destroyNodesMatching(inGroup(group));
+      } finally {
+         try {
+            URI uri = api.getResourceGroupApi().delete(group);
+            assertResourceDeleted(uri);
+         } finally {
+            super.tearDownContext();
+         }
+      }
+   }
+
+   public void listVirtualMachineMetricDefinitions() {
+      List<MetricDefinition> result = metricDefinitionsApi.list("name.value eq 'Percentage CPU'");
+
+      // verify we have something
+      assertNotNull(result);
+      assertTrue(result.size() > 1);
+      assertEquals(result.get(0).name().value(), "Percentage CPU");
+   }
+
+   private void assertResourceDeleted(final URI uri) {
+      if (uri != null) {
+         assertTrue(resourceDeleted.apply(uri),
+               String.format("Resource %s was not deleted in the configured timeout", uri));
+      }
+   }
+
+}
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApiMockTest.java
new file mode 100644
index 0000000..8fd06b8
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricDefinitionsApiMockTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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 org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.azurecompute.arm.domain.MetricDefinition;
+import org.jclouds.azurecompute.arm.domain.MetricName;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+
+@Test(groups = "unit", testName = "MetricDefinitionsApiMockTest", singleThreaded = true)
+public class MetricDefinitionsApiMockTest extends BaseAzureComputeApiMockTest {
+
+   private final String resourceId = "resourceGroups/myresourceGroup/providers/Microsoft.Compute/virtualMachines/myvm";
+   private final String filter = "(name.value eq 'Percentage CPU')";
+
+   public void testList() throws Exception {
+      server.enqueue(jsonResponse("/metricdefinitions.json"));
+      final MetricDefinitionsApi metricDefinitionsApi = api.getMetricsDefinitionsApi(resourceId);
+      assertEquals(metricDefinitionsApi.list(filter), ImmutableList.of(MetricDefinition.create(
+            "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers/Microsoft"
+                  + ".Compute/virtualMachines/myvm", MetricName.create("Percentage CPU", "Percentage CPU"),
+            Boolean.FALSE, "Percent", MetricDefinition.AggregationType.Average,
+            ImmutableList.<MetricDefinition.MetricAvailability> of(
+                  MetricDefinition.MetricAvailability.create("PT1M", "P30D"),
+                  MetricDefinition.MetricAvailability.create("PT1H", "P30D")),
+            "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers"
+                  + "/Microsoft.Compute/virtualMachines/myvm/providers/microsoft"
+                  + ".insights/metricdefinitions/Percentage " + "CPU")));
+      assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourceGroup/providers/Microsoft"
+            + ".Compute/virtualMachines/myvm/providers/microsoft.insights/metricdefinitions?$filter=%28name"
+            + ".value%20eq%20%27Percentage%20CPU%27%29&api-version=2017-05-01-preview");
+   }
+
+   public void testEmptyList() throws Exception {
+      server.enqueue(new MockResponse().setResponseCode(404));
+
+      final MetricDefinitionsApi metricDefinitionsApi = api.getMetricsDefinitionsApi(resourceId);
+
+      assertTrue(metricDefinitionsApi.list(filter).isEmpty());
+
+      assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourceGroup/providers/Microsoft"
+            + ".Compute/virtualMachines/myvm/providers/microsoft.insights/metricdefinitions?$filter=%28name"
+            + ".value%20eq%20%27Percentage%20CPU%27%29&api-version=2017-05-01-preview");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiLiveTest.java
new file mode 100644
index 0000000..5fe19db
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiLiveTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.resourceGroup;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.compute.predicates.NodePredicates.inGroup;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.net.URI;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+
+import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.domain.IdReference;
+import org.jclouds.azurecompute.arm.domain.Metric;
+import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
+
+@Test(groups = "live", singleThreaded = true)
+public class MetricsApiLiveTest extends BaseComputeServiceContextLiveTest {
+
+   private Predicate<URI> resourceDeleted;
+   private AzureComputeApi api;
+
+   private String location;
+   private MetricsApi metricsApi;
+
+   private String group;
+
+   private String startTime;
+   private SimpleDateFormat dateFormat;
+
+   public MetricsApiLiveTest() {
+      provider = "azurecompute-arm";
+      group = getClass().getSimpleName().toLowerCase();
+   }
+
+   @Override
+   protected Properties setupProperties() {
+      Properties properties = super.setupProperties();
+      AzureLiveTestUtils.defaultProperties(properties);
+      checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
+      return properties;
+   }
+
+   @Override
+   protected void initializeContext() {
+      super.initializeContext();
+      resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
+      }, Names.named(TIMEOUT_RESOURCE_DELETED)));
+      api = view.unwrapApi(AzureComputeApi.class);
+   }
+
+   @Override
+   @BeforeClass
+   public void setupContext() {
+      super.setupContext();
+
+      dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+      startTime = dateFormat.format(new Date());
+
+      NodeMetadata node = null;
+      try {
+         node = getOnlyElement(view.getComputeService().createNodesInGroup(group, 1, resourceGroup(group)));
+      } catch (RunNodesException e) {
+         fail();
+      }
+      String resourceId = String.format("/resourceGroups/%s/providers/Microsoft.Compute/virtualMachines/%s",
+            IdReference.extractResourceGroup(node.getProviderId()), IdReference.extractName(node.getProviderId()));
+
+      location = view.getComputeService().templateBuilder().build().getLocation().getId();
+      view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(group, location, null);
+      metricsApi = api.getMetricsApi(resourceId);
+   }
+
+   @Override
+   @AfterClass(alwaysRun = true)
+   protected void tearDownContext() {
+      try {
+         view.getComputeService().destroyNodesMatching(inGroup(group));
+      } finally {
+         try {
+            URI uri = api.getResourceGroupApi().delete(group);
+            assertResourceDeleted(uri);
+         } finally {
+            super.tearDownContext();
+         }
+      }
+   }
+
+   public void listVirtualMachineMetrics() throws RunNodesException {
+      List<Metric> result = metricsApi
+            .list("(name.value eq 'Percentage CPU') and startTime eq " + startTime + " and endTime eq " + dateFormat
+                  .format(new Date()) + " and timeGrain eq duration'PT1M'");
+
+      // verify we have something
+      assertNotNull(result);
+      assertEquals(result.size(), 1);
+      assertEquals(result.get(0).name().value(), "Percentage CPU");
+      assertTrue(result.get(0).data().size() > 1);
+   }
+
+   private void assertResourceDeleted(final URI uri) {
+      if (uri != null) {
+         assertTrue(resourceDeleted.apply(uri),
+               String.format("Resource %s was not deleted in the configured timeout", uri));
+      }
+   }
+
+}
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiMockTest.java
new file mode 100644
index 0000000..c6e30c1
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/MetricsApiMockTest.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+import org.jclouds.azurecompute.arm.domain.Metric;
+import org.jclouds.azurecompute.arm.domain.MetricData;
+import org.jclouds.azurecompute.arm.domain.MetricName;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+
+@Test(groups = "unit", testName = "MetricsApiMockTest", singleThreaded = true)
+public class MetricsApiMockTest extends BaseAzureComputeApiMockTest {
+
+   private final String resourceId = "resourceGroups/myresourceGroup/providers/Microsoft.Compute/virtualMachines/myvm";
+   private final String filter = "(name.value eq 'Percentage CPU') and startTime eq 2017-06-01T11:14:00Z and "
+         + "endTime eq 2017-06-01T11:23:00Z and timeGrain eq duration'PT1M'";
+
+   public void testList() throws Exception {
+      server.enqueue(jsonResponse("/metrics.json"));
+      final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);
+      final MetricsApi metricsApi = api.getMetricsApi(resourceId);
+      assertEquals(metricsApi.list(filter), ImmutableList.of(Metric.create(ImmutableList.of(MetricData
+                .create(dateFormat.parse("2017-06-01T07:14:00", new ParsePosition(0)), null,
+                    Double.valueOf(0.295), null, null, null)),
+            "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers"
+                  + "/Microsoft.Compute/virtualMachines/myvm/providers/Microsoft.Insights/metrics/Percentage CPU",
+            MetricName.create("Percentage CPU", "Percentage CPU"), "Microsoft.Insights/metrics", "Percent")));
+      assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourceGroup/providers/Microsoft"
+            + ".Compute/virtualMachines/myvm/providers/microsoft.insights/metrics?$filter=%28name"
+            + ".value%20eq%20%27Percentage%20CPU%27%29%20and%20startTime%20eq%202017-06-01T11%3A14%3A00Z%20and"
+            + "%20endTime%20eq%202017-06-01T11%3A23%3A00Z%20and%20timeGrain%20eq%20duration%27PT1M%27&api-version"
+            + "=2016-09-01");
+   }
+
+   public void testEmptyList() throws Exception {
+      server.enqueue(new MockResponse().setResponseCode(404));
+
+      final MetricsApi metricsAPI = api.getMetricsApi(resourceId);
+
+      assertTrue(metricsAPI.list(filter).isEmpty());
+
+      assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourceGroup/providers/Microsoft"
+            + ".Compute/virtualMachines/myvm/providers/microsoft.insights/metrics?$filter=%28name"
+            + ".value%20eq%20%27Percentage%20CPU%27%29%20and%20startTime%20eq%202017-06-01T11%3A14%3A00Z%20and"
+            + "%20endTime%20eq%202017-06-01T11%3A23%3A00Z%20and%20timeGrain%20eq%20duration%27PT1M%27&api-version"
+            + "=2016-09-01");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/test/resources/metricdefinitions.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/metricdefinitions.json b/providers/azurecompute-arm/src/test/resources/metricdefinitions.json
new file mode 100644
index 0000000..3df0a84
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/metricdefinitions.json
@@ -0,0 +1,25 @@
+{
+  "value": [
+    {
+      "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers/Microsoft.Compute/virtualMachines/myvm/providers/microsoft.insights/metricdefinitions/Percentage CPU",
+      "resourceId": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers/Microsoft.Compute/virtualMachines/myvm",
+      "name": {
+        "value": "Percentage CPU",
+        "localizedValue": "Percentage CPU"
+      },
+      "isDimensionRequired": false,
+      "unit": "Percent",
+      "primaryAggregationType": "Average",
+      "metricAvailabilities": [
+        {
+          "timeGrain": "PT1M",
+          "retention": "P30D"
+        },
+        {
+          "timeGrain": "PT1H",
+          "retention": "P30D"
+        }
+      ]
+    }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b2cc647f/providers/azurecompute-arm/src/test/resources/metrics.json
----------------------------------------------------------------------
diff --git a/providers/azurecompute-arm/src/test/resources/metrics.json b/providers/azurecompute-arm/src/test/resources/metrics.json
new file mode 100644
index 0000000..754e5d1
--- /dev/null
+++ b/providers/azurecompute-arm/src/test/resources/metrics.json
@@ -0,0 +1,19 @@
+{
+  "value": [
+    {
+      "data": [
+        {
+          "timeStamp": "2017-06-01T11:14:00Z",
+          "average": 0.295
+        }
+      ],
+      "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/myresourcegroup/providers/Microsoft.Compute/virtualMachines/myvm/providers/Microsoft.Insights/metrics/Percentage CPU",
+      "name": {
+        "value": "Percentage CPU",
+        "localizedValue": "Percentage CPU"
+      },
+      "type": "Microsoft.Insights/metrics",
+      "unit": "Percent"
+    }
+  ]
+}