You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2016/04/19 16:34:23 UTC
jclouds-labs git commit: JCLOUDS-664 Azurecompute-arm
StorageAccountApi
Repository: jclouds-labs
Updated Branches:
refs/heads/master b1752c9a0 -> b82378c2b
JCLOUDS-664 Azurecompute-arm StorageAccountApi
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/b82378c2
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/b82378c2
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/b82378c2
Branch: refs/heads/master
Commit: b82378c2be69467fcae7197c6dfe0ea1571fd8fd
Parents: b1752c9
Author: Rita Zhang <ri...@gmail.com>
Authored: Wed Apr 13 15:07:19 2016 -0700
Committer: Ignasi Barrera <na...@apache.org>
Committed: Tue Apr 19 16:28:09 2016 +0200
----------------------------------------------------------------------
.../azurecompute/arm/AzureComputeApi.java | 12 +
.../azurecompute/arm/domain/Availability.java | 32 ++
.../azurecompute/arm/domain/ResourceGroup.java | 4 +-
.../azurecompute/arm/domain/StorageService.java | 183 ++++++++++
.../arm/domain/StorageServiceKeys.java | 39 +++
.../arm/domain/StorageServiceUpdateParams.java | 64 ++++
.../arm/features/StorageAccountApi.java | 166 +++++++++
.../azurecompute/arm/functions/FalseOn204.java | 40 +++
.../arm/functions/ParseJobStatus.java | 12 +-
.../azurecompute/arm/util/GetEnumValue.java | 36 ++
.../arm/features/StorageAccountApiLiveTest.java | 133 +++++++
.../arm/features/StorageAccountApiMockTest.java | 347 +++++++++++++++++++
.../internal/BaseAzureComputeApiLiveTest.java | 60 ++++
.../internal/BaseAzureComputeApiMockTest.java | 5 +
.../resources/isavailablestorageservice.json | 3 +
.../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 ++
20 files changed, 1265 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index 1e7cb91..4204328 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -21,8 +21,11 @@ import java.io.Closeable;
import org.jclouds.azurecompute.arm.features.JobApi;
import org.jclouds.azurecompute.arm.features.LocationApi;
import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
+import org.jclouds.azurecompute.arm.features.StorageAccountApi;
import org.jclouds.rest.annotations.Delegate;
+import javax.ws.rs.PathParam;
+
/**
* The Azure Resource Manager API is a REST API for managing your services and deployments.
* <p/>
@@ -49,4 +52,13 @@ public interface AzureComputeApi extends Closeable {
*/
@Delegate
LocationApi getLocationApi();
+
+ /**
+ * The Azure Resource Manager API includes operations for managing the storage accounts in your subscription.
+ *
+ * @see <https://msdn.microsoft.com/en-us/library/mt163683.aspx">docs</a>
+ */
+ @Delegate
+ StorageAccountApi getStorageAccountApi(@PathParam("resourceGroup") String resourceGroup);
+
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Availability.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Availability.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Availability.java
new file mode 100644
index 0000000..eb8c341
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Availability.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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class Availability {
+
+ public abstract String nameAvailable();
+
+ @SerializedNames({"nameAvailable"})
+ public static Availability create(final String nameAvailable) {
+ return new AutoValue_Availability(nameAvailable);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ResourceGroup.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ResourceGroup.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ResourceGroup.java
index 1be93ab..08c4185 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ResourceGroup.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ResourceGroup.java
@@ -40,12 +40,12 @@ public abstract class ResourceGroup {
public abstract String id();
public abstract String name();
public abstract String location();
- @Nullable
+
public abstract Map<String, String> tags();
public abstract ResourceGroupProperties properties();
@SerializedNames({"id", "name", "location", "tags", "properties"})
- public static ResourceGroup create(String id, String name, String location, @Nullable Map<String, String> tags, ResourceGroupProperties properties) {
+ public static ResourceGroup create(String id, String name, String location, Map<String, String> tags, ResourceGroupProperties properties) {
return new AutoValue_ResourceGroup(id, name, location, tags == null ? ImmutableMap.<String, String>builder().build() : ImmutableMap.copyOf(tags), properties);
}
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageService.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageService.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageService.java
new file mode 100644
index 0000000..08709d8
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageService.java
@@ -0,0 +1,183 @@
+/*
+ * 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 java.util.Date;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import org.jclouds.azurecompute.arm.util.GetEnumValue;
+
+@AutoValue
+public abstract class StorageService {
+
+ public enum AccountType {
+
+ Standard_LRS,
+ Standard_ZRS,
+ Standard_GRS,
+ Standard_RAGRS,
+ Premium_LRS,
+ UNRECOGNIZED;
+
+ public static AccountType fromValue(final String text) {
+ return (AccountType) GetEnumValue.fromValueOrDefault(text, AccountType.UNRECOGNIZED);
+ }
+ }
+
+ public enum RegionStatus {
+
+ Available,
+ Unavailable,
+ UNRECOGNIZED;
+
+ public static RegionStatus fromValue(final String text) {
+ return (RegionStatus) GetEnumValue.fromValueOrDefault(text, RegionStatus.UNRECOGNIZED);
+ }
+
+ }
+
+ public enum Status {
+
+ Creating,
+ Created,
+ Deleting,
+ Deleted,
+ Changing,
+ ResolvingDns,
+ Succeeded,
+ UNRECOGNIZED;
+
+ public static Status fromValue(final String text) {
+ return (Status) GetEnumValue.fromValueOrDefault(text, Status.UNRECOGNIZED);
+ }
+ }
+
+ @AutoValue
+ public abstract static class StorageServiceProperties {
+
+ /**
+ * Specifies whether the account supports locally-redundant storage, geo-redundant storage, zone-redundant
+ * storage, or read access geo-redundant storage.
+ */
+ public abstract AccountType accountType();
+
+ /**
+ * Specifies the time that the storage account was created.
+ */
+ public abstract Date creationTime();
+
+ /**
+ * Specifies the endpoints of the storage account.
+ */
+ public abstract Map<String, String> primaryEndpoints();
+
+ /**
+ * A primaryLocation for the storage account.
+ */
+ @Nullable
+ public abstract String primaryLocation();
+
+ /**
+ * provisioningState for the storage group
+ */
+ @Nullable
+ public abstract Status provisioningState();
+
+ /**
+ * Specifies the secondary endpoints of the storage account.
+ */
+ public abstract Map<String, String> secondaryEndpoints();
+
+ /**
+ * Secondary location for the storage group
+ */
+ @Nullable
+ public abstract String secondaryLocation();
+
+ /**
+ * The status of primary endpoints
+ */
+ @Nullable
+ public abstract RegionStatus statusOfPrimary();
+
+ /**
+ * The secondary status of the storage account.
+ */
+ @Nullable
+ public abstract RegionStatus statusOfSecondary();
+
+
+ @SerializedNames({"accountType", "creationTime", "primaryEndpoints", "primaryLocation",
+ "provisioningState", "secondaryEndpoints", "secondaryLocation", "statusOfPrimary", "statusOfSecondary"})
+ public static StorageServiceProperties create(final AccountType accountType, final Date creationTime,
+ final Map<String, String> primaryEndpoints, final String primaryLocation, final Status provisioningState,
+ final Map<String, String> secondaryEndpoints, final String secondaryLocation,
+ final RegionStatus statusOfPrimary, final RegionStatus statusOfSecondary) {
+
+ return new AutoValue_StorageService_StorageServiceProperties(accountType, creationTime,
+ primaryEndpoints == null ? ImmutableMap.<String, String>builder().build() : ImmutableMap.copyOf(primaryEndpoints), primaryLocation, provisioningState,
+ secondaryEndpoints == null ? ImmutableMap.<String, String>builder().build() : ImmutableMap.copyOf(secondaryEndpoints), secondaryLocation, statusOfPrimary, statusOfSecondary);
+ }
+ }
+
+ /**
+ * Specifies the id of the storage account.
+ */
+ @Nullable
+ public abstract String id();
+
+ /**
+ * Specifies the name of the storage account. This name is the DNS prefix name and can be used to access blobs,
+ * queues, and tables in the storage account.
+ */
+ @Nullable
+ public abstract String name();
+
+ /**
+ * Specifies the location of the storage account.
+ */
+ public abstract String location();
+
+ /**
+ * Specifies the tags of the storage account.
+ */
+ public abstract Map<String, String> tags();
+
+ /**
+ * Specifies the type of the storage account.
+ */
+ @Nullable
+ public abstract String type();
+
+ /**
+ * Specifies the properties of the storage account.
+ */
+ public abstract StorageServiceProperties storageServiceProperties();
+
+
+ @SerializedNames({"id", "name", "location", "tags", "type", "properties"})
+ public static StorageService create(final String id, final String name, final String location,
+ final Map<String, String> tags, final String type,
+ final StorageServiceProperties storageServiceProperties) {
+ return new AutoValue_StorageService(id, name, location, tags == null ? ImmutableMap.<String, String>builder().build() : ImmutableMap.copyOf(tags), type, storageServiceProperties);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageServiceKeys.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageServiceKeys.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageServiceKeys.java
new file mode 100644
index 0000000..63cb70b
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageServiceKeys.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.json.SerializedNames;
+
+@AutoValue
+public abstract class StorageServiceKeys {
+
+ /**
+ * The primary access key for the storage account.
+ */
+ public abstract String key1();
+
+ /**
+ * The secondary access key for the storage account.
+ */
+ public abstract String key2();
+
+ @SerializedNames({"key1", "key2"})
+ public static StorageServiceKeys create(final String key1, final String key2) {
+ return new AutoValue_StorageServiceKeys(key1, key2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageServiceUpdateParams.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageServiceUpdateParams.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageServiceUpdateParams.java
new file mode 100644
index 0000000..85b8b6d
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageServiceUpdateParams.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+@AutoValue
+public abstract class StorageServiceUpdateParams {
+
+ @AutoValue
+ public abstract static class StorageServiceUpdateProperties {
+
+ /**
+ * Specifies whether the account supports locally-redundant storage, geo-redundant storage, zone-redundant
+ * storage, or read access geo-redundant storage.
+ * Note: This implementation is for version 2015-10-01 and earlier.
+ * For version 2016-01-01 or later, refer to https://msdn.microsoft.com/en-us/library/mt163639.aspx
+ */
+ @Nullable
+ public abstract StorageService.AccountType accountType();
+
+
+ @SerializedNames({"accountType"})
+ public static StorageServiceUpdateProperties create(final StorageService.AccountType accountType) {
+
+ return new AutoValue_StorageServiceUpdateParams_StorageServiceUpdateProperties(accountType);
+ }
+ }
+
+ /**
+ * Specifies the tags of the storage account.
+ */
+ public abstract Map<String, String> tags();
+
+ /**
+ * Specifies the properties of the storage account.
+ */
+ public abstract StorageServiceUpdateProperties storageServiceProperties();
+
+
+ @SerializedNames({"tags", "properties"})
+ public static StorageServiceUpdateParams create(final Map<String, String> tags,
+ final StorageServiceUpdateProperties storageServiceProperties) {
+ return new AutoValue_StorageServiceUpdateParams(tags == null ? ImmutableMap.<String, String>builder().build() : ImmutableMap.copyOf(tags), storageServiceProperties);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
new file mode 100644
index 0000000..8ebfc82
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import javax.inject.Named;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.POST;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks;
+import org.jclouds.azurecompute.arm.domain.Availability;
+import org.jclouds.azurecompute.arm.domain.StorageService;
+import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
+import org.jclouds.azurecompute.arm.domain.StorageServiceUpdateParams;
+import org.jclouds.azurecompute.arm.functions.FalseOn204;
+import org.jclouds.azurecompute.arm.functions.URIParser;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+import java.util.List;
+import java.util.Map;
+import java.net.URI;
+
+/**
+ * The Azure Resource Management API includes operations for managing the storage accounts in your subscription.
+ *
+ * @see <a href="https://msdn.microsoft.com/en-us/library/mt163683.aspx">docs</a>
+ */
+@Path("/")
+@RequestFilters(OAuthFilter.class)
+@QueryParams(keys = "api-version", values = "2015-06-15")
+@Consumes(MediaType.APPLICATION_JSON)
+public interface StorageAccountApi {
+
+ /**
+ * The List Storage Accounts operation lists the storage accounts that are available in the specified subscription
+ * and resource group.
+ * https://msdn.microsoft.com/en-us/library/mt163559.aspx
+ */
+ @Named("storageaccount:list")
+ @Path("/resourcegroups/{resourceGroup}/providers/Microsoft.Storage/storageAccounts")
+ @GET
+ @SelectJson("value")
+ @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
+ List<StorageService> list();
+
+ /**
+ * The Create Storage Account asynchronous operation creates a new storage account in Microsoft Azure.
+ * https://msdn.microsoft.com/en-us/library/mt163564.aspx
+ * 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
+ URI create(@PathParam("storageAccountName") String storageAccountName,
+ @PayloadParam("location") String location,
+ @Nullable @PayloadParam("tags") Map<String, String> tags,
+ @PayloadParam("properties") Map<String, String> properties);
+
+ /**
+ * The Check Storage Account Name Availability operation checks to see if the specified storage account name is
+ * available, or if it has already been taken. https://msdn.microsoft.com/en-us/library/mt163642.aspx
+ * POST
+ */
+ @Named("CheckStorageAccountNameAvailability")
+ @POST
+ @Payload("%7B\"name\":\"{name}\",\"type\":\"Microsoft.Storage/storageAccounts\"%7D")
+ @Path("/providers/Microsoft.Storage/checkNameAvailability")
+ @Produces(MediaType.APPLICATION_JSON)
+ Availability isAvailable(@PayloadParam("name") String storageAccountName);
+
+ /**
+ * The Get Storage Account Properties operation returns system properties for the specified storage account.
+ * https://msdn.microsoft.com/en-us/library/mt163553.aspx
+ */
+ @Named("storageaccountproperty:get")
+ @GET
+ @Path("/resourcegroups/{resourceGroup}/providers/Microsoft.Storage/storageAccounts/{storageAccountName}")
+ @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+ StorageService get(@PathParam("storageAccountName") String storageAccountName);
+
+ /**
+ * The Get Storage Keys operation returns the primary and secondary access keys for the specified storage account.
+ * https://msdn.microsoft.com/en-us/library/mt163589.aspx
+ * POST
+ */
+ @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);
+
+ /**
+ * https://msdn.microsoft.com/en-us/library/mt163567.aspx
+ * POST
+ */
+ @Named("RegenerateStorageAccountKeys")
+ @POST
+ @Payload("%7B\"keyName\":\"{keyName}\"%7D")
+ @Path("/resourcegroups/{resourceGroup}/providers/Microsoft.Storage/storageAccounts/{storageAccount}/regenerateKey")
+ @Produces(MediaType.APPLICATION_JSON)
+ StorageServiceKeys regenerateKeys(@PathParam("storageAccount") String storageAccount,
+ @PayloadParam("keyName") String keyName);
+
+ /**
+ * The Update Storage Account asynchronous operation updates the label, the description, and enables or disables the
+ * geo-replication status for the specified storage account. https://msdn.microsoft.com/en-us/library/mt163639.aspx
+ * PATCH
+ */
+ @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,
+ @PayloadParam("properties") StorageServiceUpdateParams.StorageServiceUpdateProperties properties);
+
+ /**
+ * https://msdn.microsoft.com/en-us/library/mt163652.aspx
+ * DELETE
+ */
+ @Named("storageaccount:delete")
+ @DELETE
+ @ResponseParser(FalseOn204.class)
+ @Path("/resourcegroups/{resourceGroup}/providers/Microsoft.Storage/storageAccounts/{storageAccountName}")
+ boolean delete(@PathParam("storageAccountName") String storageAccountName);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/FalseOn204.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/FalseOn204.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/FalseOn204.java
new file mode 100644
index 0000000..34c6d56
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/FalseOn204.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.functions;
+import com.google.common.base.Function;
+import org.jclouds.http.HttpResponse;
+
+import javax.inject.Singleton;
+
+import static org.jclouds.http.HttpUtils.releasePayload;
+/**
+ * Parses an http response code from http responser
+ */
+@Singleton
+public class FalseOn204 implements Function<HttpResponse, Boolean> {
+ public Boolean apply(final HttpResponse from) {
+ releasePayload(from);
+ final int statusCode = from.getStatusCode();
+ if (statusCode == 200) {
+ return true;
+ }
+ if (statusCode == 204) {
+ return false;
+ }
+ throw new IllegalStateException("not expected response from: " + from);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/ParseJobStatus.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/ParseJobStatus.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/ParseJobStatus.java
index f39db90..5770582 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/ParseJobStatus.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/ParseJobStatus.java
@@ -16,6 +16,7 @@
*/
package org.jclouds.azurecompute.arm.functions;
import com.google.common.base.Function;
+import org.jclouds.azurecompute.arm.util.GetEnumValue;
import org.jclouds.http.HttpResponse;
import javax.inject.Singleton;
@@ -31,15 +32,8 @@ public class ParseJobStatus implements Function<HttpResponse, ParseJobStatus.Job
FAILED,
UNRECOGNIZED;
- public static JobStatus fromString(final String text) {
- if (text != null) {
- for (JobStatus status : JobStatus.values()) {
- if (text.equalsIgnoreCase(status.name())) {
- return status;
- }
- }
- }
- return UNRECOGNIZED;
+ public static JobStatus fromValue(final String text) {
+ return (JobStatus) GetEnumValue.fromValueOrDefault(text, JobStatus.UNRECOGNIZED);
}
}
public JobStatus apply(final HttpResponse from) {
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/GetEnumValue.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/GetEnumValue.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/GetEnumValue.java
new file mode 100644
index 0000000..4a61613
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/GetEnumValue.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.util;
+
+import java.util.EnumSet;
+
+public class GetEnumValue {
+
+ @SuppressWarnings("unchecked")
+ public static <T extends Enum<T>> Enum<T> fromValueOrDefault(String text, Enum<T> defaultValue) {
+ if (text != null) {
+ EnumSet<T> elements = EnumSet.allOf(defaultValue.getDeclaringClass());
+ for (Enum<T> element : elements) {
+ if (text.equalsIgnoreCase(element.name())) {
+ return element;
+ }
+ }
+ }
+ return defaultValue;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiLiveTest.java
new file mode 100644
index 0000000..9a13d77
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiLiveTest.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.azurecompute.arm.domain.StorageService;
+import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
+import org.jclouds.azurecompute.arm.domain.StorageServiceUpdateParams;
+import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
+import org.jclouds.util.Predicates2;
+import org.testng.annotations.Test;
+
+import java.net.URI;
+import java.util.List;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+@Test(groups = "live", testName = "StorageAccountApiLiveTest")
+public class StorageAccountApiLiveTest extends BaseAzureComputeApiLiveTest {
+
+ private static final String NAME = String.format("%3.24s",
+ RAND + StorageAccountApiLiveTest.class.getSimpleName().toLowerCase());
+
+ private void check(final StorageService storage) {
+ assertNotNull(storage.id());
+ assertNotNull(storage.name());
+ assertNotNull(storage.storageServiceProperties());
+ assertNotNull(storage.storageServiceProperties().accountType());
+ assertFalse(storage.storageServiceProperties().primaryEndpoints().isEmpty());
+ assertNotNull(storage.storageServiceProperties().creationTime());
+ }
+
+ @Test(dependsOnMethods = "testCreate")
+ public void testList() {
+ List<StorageService> storages = api().list();
+ assertTrue(storages.size() > 0);
+ for (StorageService storage : storages) {
+ check(storage);
+ }
+ }
+
+ @Test()
+ public void testIsAvailable() {
+ assertTrue(api().isAvailable(NAME).nameAvailable().equals("true"));
+ }
+
+ @Test(dependsOnMethods = "testIsAvailable")
+ public void testCreate() {
+ URI uri = api().create(NAME, 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 = Predicates2.retry(new Predicate<URI>() {
+ @Override public boolean apply(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");
+ }
+ final StorageService service = api().get(NAME);
+ assertNotNull(service);
+ assertEquals(service.location(), LOCATION);
+ assertNotNull(service.storageServiceProperties().creationTime());
+ }
+
+ @Test(dependsOnMethods = "testCreate")
+ public void testGet() {
+ final StorageService service = api().get(NAME);
+ assertNotNull(service);
+ assertEquals(service.name(), NAME);
+ assertEquals(service.storageServiceProperties().primaryLocation(), LOCATION);
+ assertEquals(service.storageServiceProperties().accountType(), StorageService.AccountType.Standard_LRS);
+ }
+
+ @Test(dependsOnMethods = "testCreate")
+ public void testGetKeys() {
+ final StorageServiceKeys keys = api().getKeys(NAME);
+ assertNotNull(keys);
+ assertNotNull(keys.key1());
+ assertNotNull(keys.key2());
+ }
+
+ @Test(dependsOnMethods = "testCreate")
+ public void testRegenerateKeys() {
+ StorageServiceKeys keys = api().regenerateKeys(NAME, "key1");
+ assertFalse(keys.key1().isEmpty());
+ assertFalse(keys.key2().isEmpty());
+ }
+
+ @Test(dependsOnMethods = "testCreate")
+ public void testUpdateTags() {
+ StorageServiceUpdateParams.StorageServiceUpdateProperties props =
+ StorageServiceUpdateParams.StorageServiceUpdateProperties.create(null);
+ final StorageServiceUpdateParams params = api().update(NAME,
+ ImmutableMap.of("another_property_name", "another_property_value"), props);
+ assertTrue(params.tags().containsKey("another_property_name"));
+ assertNull(params.storageServiceProperties().accountType());
+ }
+ @Test(dependsOnMethods = "testCreate")
+ public void testUpdateAccountType() {
+ StorageServiceUpdateParams.StorageServiceUpdateProperties props =
+ StorageServiceUpdateParams.StorageServiceUpdateProperties.create(StorageService.AccountType.Standard_GRS);
+ final StorageServiceUpdateParams params = api().update(NAME,
+ null, props);
+ assertTrue(params.tags().isEmpty());
+ assertEquals(params.storageServiceProperties().accountType(), StorageService.AccountType.Standard_GRS);
+ }
+
+ private StorageAccountApi api() {
+ return api.getStorageAccountApi(getResourceGroupName());
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiMockTest.java
new file mode 100644
index 0000000..39ecd2b
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/StorageAccountApiMockTest.java
@@ -0,0 +1,347 @@
+/*
+ * 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.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import org.jclouds.azurecompute.arm.domain.StorageService;
+import org.jclouds.azurecompute.arm.domain.Availability;
+import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
+import org.jclouds.azurecompute.arm.domain.StorageServiceUpdateParams;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.jclouds.date.DateService;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.testng.annotations.Test;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+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.assertTrue;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertFalse;
+
+
+@Test(groups = "unit", testName = "StorageAccountApiMockTest", singleThreaded = true)
+public class StorageAccountApiMockTest extends BaseAzureComputeApiMockTest {
+
+ private String subsriptionId = "SUBSCRIPTIONID";
+ private String resourceGroup = "resourceGroup";
+
+ public void testList() throws Exception {
+ server.enqueue(jsonResponse("/storageAccounts.json"));
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ List<StorageService> list = storageAPI.list();
+ assertEquals(list, expected());
+
+ assertSent(server, "GET", "/subscriptions/" + subsriptionId +
+ "/resourcegroups/resourceGroup/providers/Microsoft.Storage/storageAccounts?api-version=2015-06-15");
+ }
+
+ public void testListReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ List<StorageService> list = storageAPI.list();
+
+ assertTrue(isEmpty(list));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/subscriptions/" + subsriptionId +
+ "/resourcegroups/resourceGroup/providers/Microsoft.Storage/storageAccounts?api-version=2015-06-15");
+ }
+
+ public void testCreate() throws Exception {
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ server.enqueue(response202WithHeader());
+
+ URI uri = storageAPI.create("name-of-storage-account", "westus",
+ ImmutableMap.of("property_name", "property_value"),
+ ImmutableMap.of("accountType", StorageService.AccountType.Premium_LRS.toString()));
+ assertNotNull(uri);
+
+ assertSent(server, "PUT", "/subscriptions/" + subsriptionId +
+ "/resourcegroups/resourceGroup/providers/Microsoft.Storage/" +
+ "storageAccounts/name-of-storage-account?api-version=2015-06-15", String.format("{\"location\":\"westus\",\"tags\":{\"property_name\":\"property_value\"},\"properties\":{\"accountType\":\"Premium_LRS\"}}"));
+ }
+
+ public void testCreateWithNullTag() throws Exception {
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ server.enqueue(response202WithHeader());
+
+ URI uri = storageAPI.create("name-of-storage-account", "westus",
+ null,
+ ImmutableMap.of("accountType", StorageService.AccountType.Premium_LRS.toString()));
+ assertNotNull(uri);
+
+ assertSent(server, "PUT", "/subscriptions/" + subsriptionId +
+ "/resourcegroups/resourceGroup/providers/Microsoft.Storage/" +
+ "storageAccounts/name-of-storage-account?api-version=2015-06-15", String.format("{\"location\":\"westus\",\"properties\":{\"accountType\":\"Premium_LRS\"}}"));
+ }
+
+ public void testIsAvailable() throws Exception {
+ server.enqueue(jsonResponse("/isavailablestorageservice.json"));
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ assertEquals(storageAPI.isAvailable("TESTSTORAGE"),
+ Availability.create("true"));
+
+ assertSent(server, "POST", "/subscriptions/" + subsriptionId +
+ "/providers/Microsoft.Storage/checkNameAvailability?api-version=2015-06-15", String.format("{\"name\":\"TESTSTORAGE\",\"type\":\"Microsoft.Storage/storageAccounts\"}"));
+ }
+
+ public void testGet() throws Exception {
+ server.enqueue(jsonResponse("/storageservices.json"));
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ assertEquals(storageAPI.get("TESTSTORAGE"), expected().get(0));
+
+ assertSent(server, "GET", "/subscriptions/" + subsriptionId + "/resourcegroups/" + resourceGroup +
+ "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE?api-version=2015-06-15");
+ }
+
+ public void testNullGet() throws Exception {
+ server.enqueue(new MockResponse().setResponseCode(404));
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ assertNull(storageAPI.get("TESTSTORAGE"));
+
+ assertSent(server, "GET", "/subscriptions/" + subsriptionId + "/resourcegroups/" + resourceGroup +
+ "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE?api-version=2015-06-15");
+ }
+
+ public void testGetKeys() throws Exception {
+ server.enqueue(jsonResponse("/storageaccountkeys.json"));
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ assertEquals(storageAPI.getKeys("TESTSTORAGE"), StorageServiceKeys.create(
+ "bndO7lydwDkMo4Y0mFvmfLyi2f9aZY7bwfAVWoJWv4mOVK6E9c/exLnFsSm/NMWgifLCfxC/c6QBTbdEvWUA7w==",
+ "/jMLLT3kKqY4K+cUtJTbh7pCBdvG9EMKJxUvaJJAf6W6aUiZe1A1ulXHcibrqRVA2RJE0oUeXQGXLYJ2l85L7A=="));
+
+ assertSent(server, "POST", "/subscriptions/" + subsriptionId + "/resourcegroups/" + resourceGroup +
+ "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE/listKeys?api-version=2015-06-15");
+ }
+
+ public void testNullGetKeys() throws Exception {
+ server.enqueue(new MockResponse().setResponseCode(404));
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ assertNull(storageAPI.getKeys("TESTSTORAGE"));
+
+ assertSent(server, "POST", "/subscriptions/" + subsriptionId + "/resourcegroups/" + resourceGroup +
+ "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE/listKeys?api-version=2015-06-15");
+ }
+
+ public void testRegenerateKeys() throws Exception {
+ server.enqueue(jsonResponse("/storageaccountkeys.json"));
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ assertEquals(storageAPI.regenerateKeys("TESTSTORAGE", "key1"), StorageServiceKeys.create(
+ "bndO7lydwDkMo4Y0mFvmfLyi2f9aZY7bwfAVWoJWv4mOVK6E9c/exLnFsSm/NMWgifLCfxC/c6QBTbdEvWUA7w==",
+ "/jMLLT3kKqY4K+cUtJTbh7pCBdvG9EMKJxUvaJJAf6W6aUiZe1A1ulXHcibrqRVA2RJE0oUeXQGXLYJ2l85L7A=="));
+
+ assertSent(server, "POST", "/subscriptions/" + subsriptionId + "/resourcegroups/" + resourceGroup +
+ "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE/regenerateKey?api-version=2015-06-15", String.format("{\"keyName\":\"key1\"}"));
+ }
+
+ public void testUpdate() throws Exception {
+ server.enqueue(jsonResponse("/storageaccountupdate.json"));
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ StorageServiceUpdateParams.StorageServiceUpdateProperties props =
+ StorageServiceUpdateParams.StorageServiceUpdateProperties.create(StorageService.AccountType.Standard_LRS);
+
+ final StorageServiceUpdateParams params = storageAPI.update("TESTSTORAGE",
+ ImmutableMap.of("another_property_name", "another_property_value"), props);
+
+ assertTrue(params.tags().containsKey("another_property_name"));
+
+ assertSent(server, "PATCH", "/subscriptions/" + subsriptionId + "/resourcegroups/" + resourceGroup +
+ "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE?api-version=2015-06-15", String.format("{\"properties\":{ \"accountType\": \"Standard_LRS\" },\"tags\":{\"another_property_name\":\"another_property_value\"}}"));
+ }
+
+ public void testUpdateWithNullTagAndNullProperty() throws Exception {
+ server.enqueue(jsonResponse("/storageaccountupdate.json"));
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ StorageServiceUpdateParams.StorageServiceUpdateProperties props =
+ StorageServiceUpdateParams.StorageServiceUpdateProperties.create(null);
+
+ final StorageServiceUpdateParams params = storageAPI.update("TESTSTORAGE", null, props);
+
+ assertTrue(params.tags().containsKey("another_property_name"));
+
+ assertSent(server, "PATCH", "/subscriptions/" + subsriptionId + "/resourcegroups/" + resourceGroup +
+ "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE?api-version=2015-06-15", String.format("{\"properties\":{}}"));
+ }
+
+ public void testDelete() throws Exception {
+ server.enqueue(new MockResponse().setResponseCode(200));
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ boolean status = storageAPI.delete("TESTSTORAGE");
+ assertTrue(status);
+
+ assertSent(server, "DELETE", "/subscriptions/" + subsriptionId + "/resourcegroups/" + resourceGroup +
+ "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE?api-version=2015-06-15");
+ }
+
+ public void testDelete204() throws Exception {
+
+ server.enqueue(new MockResponse().setResponseCode(204));
+
+ final StorageAccountApi storageAPI = api.getStorageAccountApi(resourceGroup);
+
+ boolean status = storageAPI.delete("TESTSTORAGE");
+ assertFalse(status);
+
+ assertSent(server, "DELETE", "/subscriptions/" + subsriptionId + "/resourcegroups/" + resourceGroup +
+ "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE?api-version=2015-06-15");
+ }
+
+ private StorageService getStrorageAccount() {
+ DateService DATE_SERVICE = new SimpleDateFormatDateService();
+ Map<String, String> endpoints = new HashMap<String, String>();
+ endpoints.put("blob", "https://TESTSTORAGE.blob.core.windows.net/");
+ endpoints.put("file", "https://TESTSTORAGE.file.core.windows.net/");
+ endpoints.put("queue", "https://TESTSTORAGE.queue.core.windows.net/");
+ endpoints.put("table", "https://TESTSTORAGE.table.core.windows.net/");
+ Map<String, String> secondaryEndpoints = new HashMap<String, String>();
+ secondaryEndpoints.put("blob", "https://TESTSTORAGE-secondary.blob.core.windows.net/");
+ secondaryEndpoints.put("queue", "https://TESTSTORAGE-secondary.queue.core.windows.net/");
+ secondaryEndpoints.put("table", "https://TESTSTORAGE-secondary.table.core.windows.net/");
+
+
+ String location = "westus";
+ String secondaryLocation = "eastus";
+ final StorageService.StorageServiceProperties props = StorageService.StorageServiceProperties.create(
+ StorageService.AccountType.Standard_RAGRS,
+ DATE_SERVICE.iso8601DateOrSecondsDateParse("2016-02-24T13:04:45.0890883Z"),
+ endpoints,
+ location,
+ StorageService.Status.Succeeded,
+ secondaryEndpoints, secondaryLocation,
+ StorageService.RegionStatus.Available,
+ StorageService.RegionStatus.Available);
+
+ final Map<String, String> tags = ImmutableMap.of(
+ "key1", "value1",
+ "key2", "value2");
+
+ return StorageService.create(
+ "/subscriptions/SUBSCRIPTIONID/resourceGroups/resourceGroup" +
+ "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE",
+ "TESTSTORAGE", location, tags, null, props);
+ }
+
+ private List<StorageService> expected() throws MalformedURLException {
+ DateService DATE_SERVICE = new SimpleDateFormatDateService();
+ Map<String, String> endpoints = new HashMap<String, String>();
+ endpoints.put("blob", "https://TESTSTORAGE.blob.core.windows.net/");
+ endpoints.put("file", "https://TESTSTORAGE.file.core.windows.net/");
+ endpoints.put("queue", "https://TESTSTORAGE.queue.core.windows.net/");
+ endpoints.put("table", "https://TESTSTORAGE.table.core.windows.net/");
+ Map<String, String> secondaryEndpoints = new HashMap<String, String>();
+ secondaryEndpoints.put("blob", "https://TESTSTORAGE-secondary.blob.core.windows.net/");
+ secondaryEndpoints.put("queue", "https://TESTSTORAGE-secondary.queue.core.windows.net/");
+ secondaryEndpoints.put("table", "https://TESTSTORAGE-secondary.table.core.windows.net/");
+ Map<String, String> endpoints2 = new HashMap<String, String>();
+ endpoints2.put("blob", "https://TESTSTORAGE2.blob.core.windows.net/");
+ endpoints2.put("file", "https://TESTSTORAGE2.file.core.windows.net/");
+ endpoints2.put("queue", "https://TESTSTORAGE2.queue.core.windows.net/");
+ endpoints2.put("table", "https://TESTSTORAGE2.table.core.windows.net/");
+ Map<String, String> secondaryEndpoints2 = new HashMap<String, String>();
+ secondaryEndpoints2.put("blob", "https://TESTSTORAGE2-secondary.blob.core.windows.net/");
+ secondaryEndpoints2.put("queue", "https://TESTSTORAGE2-secondary.queue.core.windows.net/");
+ secondaryEndpoints2.put("table", "https://TESTSTORAGE2-secondary.table.core.windows.net/");
+ Map<String, String> endpoints3 = new HashMap<String, String>();
+ endpoints3.put("blob", "https://TESTSTORAGE3.blob.core.windows.net/");
+ endpoints3.put("file", "https://TESTSTORAGE3.file.core.windows.net/");
+ endpoints3.put("queue", "https://TESTSTORAGE3.queue.core.windows.net/");
+ endpoints3.put("table", "https://TESTSTORAGE3.table.core.windows.net/");
+ Map<String, String> secondaryEndpoints3 = new HashMap<String, String>();
+ secondaryEndpoints3.put("blob", "https://TESTSTORAGE3-secondary.blob.core.windows.net/");
+ secondaryEndpoints3.put("queue", "https://TESTSTORAGE3-secondary.queue.core.windows.net/");
+ secondaryEndpoints3.put("table", "https://TESTSTORAGE3-secondary.table.core.windows.net/");
+
+
+ String location = "westus";
+ String secondaryLocation = "eastus";
+ final StorageService.StorageServiceProperties props = StorageService.StorageServiceProperties.create(
+ StorageService.AccountType.Standard_RAGRS,
+ DATE_SERVICE.iso8601DateOrSecondsDateParse("2016-02-24T13:04:45.0890883Z"),
+ endpoints,
+ location,
+ StorageService.Status.Succeeded, secondaryEndpoints, secondaryLocation,
+ StorageService.RegionStatus.Available,
+ StorageService.RegionStatus.Available);
+ final StorageService.StorageServiceProperties props2 = StorageService.StorageServiceProperties.create(
+ StorageService.AccountType.Standard_RAGRS,
+ DATE_SERVICE.iso8601DateOrSecondsDateParse("2016-02-24T13:11:43.8265672Z"),
+ endpoints2, location,
+ StorageService.Status.Succeeded, secondaryEndpoints2, secondaryLocation,
+ StorageService.RegionStatus.Available,
+ StorageService.RegionStatus.Available);
+ final StorageService.StorageServiceProperties props3 = StorageService.StorageServiceProperties.create(
+ StorageService.AccountType.Standard_RAGRS,
+ DATE_SERVICE.iso8601DateOrSecondsDateParse("2016-02-24T14:12:59.5223315Z"),
+ endpoints3, location,
+ StorageService.Status.Succeeded, secondaryEndpoints3, secondaryLocation,
+ StorageService.RegionStatus.Available,
+ StorageService.RegionStatus.Available);
+
+ final Map<String, String> tags = ImmutableMap.of(
+ "key1", "value1",
+ "key2", "value2");
+
+ return ImmutableList.of(StorageService.create(
+ "/subscriptions/SUBSCRIPTIONID/resourceGroups/resourceGroup/" +
+ "providers/Microsoft.Storage/storageAccounts/TESTSTORAGE",
+ "TESTSTORAGE", location, tags, "Microsoft.Storage/storageAccounts", props),
+ StorageService.create(
+ "/subscriptions/SUBSCRIPTIONID/resourceGroups/resourceGroup/" +
+ "providers/Microsoft.Storage/storageAccounts/TESTSTORAGE2",
+ "TESTSTORAGE2", location, tags, "Microsoft.Storage/storageAccounts", props2),
+ StorageService.create(
+ "/subscriptions/SUBSCRIPTIONID/resourceGroups/resourceGroup/" +
+ "providers/Microsoft.Storage/storageAccounts/TESTSTORAGE3",
+ "TESTSTORAGE3", location, tags, "Microsoft.Storage/storageAccounts", props3));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
index fb2e42a..657ebf7 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
@@ -16,16 +16,41 @@
*/
package org.jclouds.azurecompute.arm.internal;
import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
+import org.jclouds.azurecompute.arm.domain.StorageService;
+import org.jclouds.azurecompute.arm.features.StorageAccountApi;
+import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
+import org.jclouds.util.Predicates2;
+import org.testng.Assert;
import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+
+import java.net.URI;
+import java.util.logging.Level;
+import java.util.logging.Logger;
public class BaseAzureComputeApiLiveTest extends AbstractAzureComputeApiLiveTest {
public static final String LOCATION = "westeurope";
private String resourceGroupName = null;
+ protected StorageService storageService;
+
+
+ private String storageServiceName = null;
+
+ protected String getStorageServiceName() {
+ if (storageServiceName == null) {
+ storageServiceName = String.format("%3.24s",
+ System.getProperty("user.name") + RAND + this.getClass().getSimpleName()).toLowerCase();
+ }
+ return storageServiceName;
+ }
+
protected String getEndpoint() {
String endpoint = null;
if (System.getProperty("test.azurecompute-arm.endpoint") != null) {
@@ -56,10 +81,45 @@ public class BaseAzureComputeApiLiveTest extends AbstractAzureComputeApiLiveTest
}
+ @BeforeClass
+ @Override
+ public void setup() {
+ super.setup();
+
+ storageService = getOrCreateStorageService(getStorageServiceName());
+ }
+
@AfterClass(alwaysRun = true)
@Override
protected void tearDown() {
super.tearDown();
+ Boolean status = api.getStorageAccountApi(getResourceGroupName()).delete(getStorageServiceName());
+ assertTrue(status.booleanValue());
deleteResourceGroup(getResourceGroupName());
}
+
+ protected StorageService getOrCreateStorageService(String storageServiceName) {
+ StorageAccountApi storageApi = api.getStorageAccountApi(getResourceGroupName());
+ StorageService ss = storageApi.get(storageServiceName);
+ if (ss != null) {
+ return ss;
+ }
+ URI uri = storageApi.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 = Predicates2.retry(new Predicate<URI>() {
+ @Override public boolean apply(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");
+ }
+ ss = storageApi.get(storageServiceName);
+ Assert.assertEquals(ss.location(), LOCATION);
+
+ Logger.getAnonymousLogger().log(Level.INFO, "created storageService: {0}", ss);
+ return ss;
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
index 5a228f4..82af978 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
@@ -96,6 +96,11 @@ 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")
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/test/resources/isavailablestorageservice.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/isavailablestorageservice.json b/azurecompute-arm/src/test/resources/isavailablestorageservice.json
new file mode 100644
index 0000000..b6f2459
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/isavailablestorageservice.json
@@ -0,0 +1,3 @@
+{
+ "nameAvailable": true
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/test/resources/storageAccounts.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/storageAccounts.json b/azurecompute-arm/src/test/resources/storageAccounts.json
new file mode 100644
index 0000000..f5841df
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/storageAccounts.json
@@ -0,0 +1,90 @@
+{
+ "value": [{
+ "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/resourceGroup/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE",
+ "location": "westus",
+ "name": "TESTSTORAGE",
+ "properties": {
+ "accountType": "Standard_RAGRS",
+ "creationTime": "2016-02-24T13:04:45.0890883Z",
+ "primaryEndpoints": {
+ "blob": "https://TESTSTORAGE.blob.core.windows.net/",
+ "file": "https://TESTSTORAGE.file.core.windows.net/",
+ "queue": "https://TESTSTORAGE.queue.core.windows.net/",
+ "table": "https://TESTSTORAGE.table.core.windows.net/"
+ },
+ "primaryLocation": "westus",
+ "provisioningState": "Succeeded",
+ "secondaryEndpoints": {
+ "blob": "https://TESTSTORAGE-secondary.blob.core.windows.net/",
+ "queue": "https://TESTSTORAGE-secondary.queue.core.windows.net/",
+ "table": "https://TESTSTORAGE-secondary.table.core.windows.net/"
+ },
+ "secondaryLocation": "eastus",
+ "statusOfPrimary": "available",
+ "statusOfSecondary": "available"
+ },
+ "tags": {
+ "key1": "value1",
+ "key2": "value2"
+ },
+ "type": "Microsoft.Storage/storageAccounts"
+ }, {
+ "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/resourceGroup/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE2",
+ "location": "westus",
+ "name": "TESTSTORAGE2",
+ "properties": {
+ "accountType": "Standard_RAGRS",
+ "creationTime": "2016-02-24T13:11:43.8265672Z",
+ "primaryEndpoints": {
+ "blob": "https://TESTSTORAGE2.blob.core.windows.net/",
+ "file": "https://TESTSTORAGE2.file.core.windows.net/",
+ "queue": "https://TESTSTORAGE2.queue.core.windows.net/",
+ "table": "https://TESTSTORAGE2.table.core.windows.net/"
+ },
+ "primaryLocation": "westus",
+ "provisioningState": "Succeeded",
+ "secondaryEndpoints": {
+ "blob": "https://TESTSTORAGE2-secondary.blob.core.windows.net/",
+ "queue": "https://TESTSTORAGE2-secondary.queue.core.windows.net/",
+ "table": "https://TESTSTORAGE2-secondary.table.core.windows.net/"
+ },
+ "secondaryLocation": "eastus",
+ "statusOfPrimary": "available",
+ "statusOfSecondary": "available"
+ },
+ "tags": {
+ "key1": "value1",
+ "key2": "value2"
+ },
+ "type": "Microsoft.Storage/storageAccounts"
+ }, {
+ "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/resourceGroup/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE3",
+ "location": "westus",
+ "name": "TESTSTORAGE3",
+ "properties": {
+ "accountType": "Standard_RAGRS",
+ "creationTime": "2016-02-24T14:12:59.5223315Z",
+ "primaryEndpoints": {
+ "blob": "https://TESTSTORAGE3.blob.core.windows.net/",
+ "file": "https://TESTSTORAGE3.file.core.windows.net/",
+ "queue": "https://TESTSTORAGE3.queue.core.windows.net/",
+ "table": "https://TESTSTORAGE3.table.core.windows.net/"
+ },
+ "primaryLocation": "westus",
+ "provisioningState": "Succeeded",
+ "secondaryEndpoints": {
+ "blob": "https://TESTSTORAGE3-secondary.blob.core.windows.net/",
+ "queue": "https://TESTSTORAGE3-secondary.queue.core.windows.net/",
+ "table": "https://TESTSTORAGE3-secondary.table.core.windows.net/"
+ },
+ "secondaryLocation": "eastus",
+ "statusOfPrimary": "available",
+ "statusOfSecondary": "available"
+ },
+ "tags": {
+ "key1": "value1",
+ "key2": "value2"
+ },
+ "type": "Microsoft.Storage/storageAccounts"
+ }]
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/test/resources/storageCreateResponse.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/storageCreateResponse.json b/azurecompute-arm/src/test/resources/storageCreateResponse.json
new file mode 100644
index 0000000..4fc9301
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/storageCreateResponse.json
@@ -0,0 +1,9 @@
+{
+ "location": "westus",
+ "tags": {
+ "property_name": "property_value"
+ },
+ "properties": {
+ "accountType": "Premium_LRS"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/test/resources/storageaccountkeys.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/storageaccountkeys.json b/azurecompute-arm/src/test/resources/storageaccountkeys.json
new file mode 100644
index 0000000..42de106
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/storageaccountkeys.json
@@ -0,0 +1,4 @@
+{
+ "key1": "bndO7lydwDkMo4Y0mFvmfLyi2f9aZY7bwfAVWoJWv4mOVK6E9c/exLnFsSm/NMWgifLCfxC/c6QBTbdEvWUA7w==",
+ "key2": "/jMLLT3kKqY4K+cUtJTbh7pCBdvG9EMKJxUvaJJAf6W6aUiZe1A1ulXHcibrqRVA2RJE0oUeXQGXLYJ2l85L7A=="
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/test/resources/storageaccountupdate.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/storageaccountupdate.json b/azurecompute-arm/src/test/resources/storageaccountupdate.json
new file mode 100644
index 0000000..dafe560
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/storageaccountupdate.json
@@ -0,0 +1,7 @@
+{
+ "properties": {
+ },
+ "tags": {
+ "another_property_name": "another_property_value"
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/b82378c2/azurecompute-arm/src/test/resources/storageservices.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/storageservices.json b/azurecompute-arm/src/test/resources/storageservices.json
new file mode 100644
index 0000000..b56a67b
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/storageservices.json
@@ -0,0 +1,30 @@
+{
+ "id": "/subscriptions/SUBSCRIPTIONID/resourceGroups/resourceGroup/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE",
+ "location": "westus",
+ "name": "TESTSTORAGE",
+ "properties": {
+ "accountType": "Standard_RAGRS",
+ "creationTime": "2016-02-24T13:04:45.0890883Z",
+ "primaryEndpoints": {
+ "blob": "https://TESTSTORAGE.blob.core.windows.net/",
+ "file": "https://TESTSTORAGE.file.core.windows.net/",
+ "queue": "https://TESTSTORAGE.queue.core.windows.net/",
+ "table": "https://TESTSTORAGE.table.core.windows.net/"
+ },
+ "primaryLocation": "westus",
+ "provisioningState": "Succeeded",
+ "secondaryEndpoints": {
+ "blob": "https://TESTSTORAGE-secondary.blob.core.windows.net/",
+ "queue": "https://TESTSTORAGE-secondary.queue.core.windows.net/",
+ "table": "https://TESTSTORAGE-secondary.table.core.windows.net/"
+ },
+ "secondaryLocation": "eastus",
+ "statusOfPrimary": "available",
+ "statusOfSecondary": "available"
+ },
+ "tags": {
+ "key1": "value1",
+ "key2": "value2"
+ },
+ "type": "Microsoft.Storage/storageAccounts"
+}
\ No newline at end of file