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 3914bc027c..b971931ec4 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,12 +16,6 @@ */ 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 static org.jclouds.util.Closeables2.closeQuietly; - import java.net.URI; import java.util.List; @@ -53,6 +47,12 @@ 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 { @@ -165,10 +165,7 @@ public class CleanupResources { public boolean deleteResourceGroupIfEmpty(String group) { boolean deleted = false; - if (api.getVirtualMachineApi(group).list().isEmpty() && api.getStorageAccountApi(group).list().isEmpty() - && api.getNetworkInterfaceCardApi(group).list().isEmpty() - && api.getPublicIPAddressApi(group).list().isEmpty() - && api.getNetworkSecurityGroupApi(group).list().isEmpty()) { + if (api.getResourceGroupApi().resources(group).isEmpty()) { logger.debug(">> the resource group %s is empty. Deleting...", group); deleted = resourceDeleted.apply(api.getResourceGroupApi().delete(group)); } diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Resource.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Resource.java new file mode 100644 index 0000000000..f04823478b --- /dev/null +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Resource.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.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 Resource { + + @AutoValue + public abstract static class Identity { + + public abstract String principalId(); + public abstract String tenantId(); + public abstract String type(); + + @SerializedNames({"principalId", "tenantId", "type" }) + public static Identity create(String principalId, String tenantId, String type) { + return new AutoValue_Resource_Identity(principalId, tenantId, type); + } + } + + @AutoValue + public abstract static class ResourceProperties{ + @Nullable + public abstract String provisioningState(); + + @SerializedNames({"provisioningState"}) + public static ResourceProperties create(final String provisioningState) { + return new AutoValue_Resource_ResourceProperties(provisioningState); + } + } + + public abstract String id(); + public abstract String name(); + public abstract String type(); + public abstract String location(); + @Nullable public abstract Map tags(); + @Nullable public abstract Identity identity(); + @Nullable public abstract SKU sku(); + @Nullable public abstract String managedBy(); + @Nullable public abstract String kind(); + @Nullable public abstract Plan plan(); + @Nullable public abstract ResourceProperties properties(); + + @SerializedNames({"id", "name", "type", "location", "tags", "identity", "sku", "managedBy", "kind", "plan", "properties"}) + public static Resource create(String id, String name, String type, String location, Map tags, + Identity identity, SKU sku, String managedBy, String kind, Plan plan, ResourceProperties properties) { + return new AutoValue_Resource(id, name, type, location, tags == null ? null : ImmutableMap.copyOf(tags), + identity, sku, managedBy, kind, plan, properties); + } +} 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 6f718a59e3..2c6a8b3904 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 @@ -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; @@ -32,6 +33,7 @@ import javax.ws.rs.core.MediaType; import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.azurecompute.arm.domain.Resource; import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.filters.ApiVersionFilter; import org.jclouds.azurecompute.arm.functions.URIParser; @@ -67,7 +69,7 @@ public interface ResourceGroupApi extends Closeable{ @Path("/{name}") @Produces(MediaType.APPLICATION_JSON) @MapBinder(BindToJsonPayload.class) - ResourceGroup create(@PathParam("name") String name, @PayloadParam("location") String location, @Nullable @PayloadParam("tags")Map tags); + ResourceGroup create(@PathParam("name") String name, @PayloadParam("location") String location, @Nullable @PayloadParam("tags") Map tags); @Named("resourcegroup:get") @GET @@ -76,12 +78,19 @@ public interface ResourceGroupApi extends Closeable{ @Nullable ResourceGroup get(@PathParam("name") String name); + @Named("resourcegroup:resources") + @GET + @Path("/{name}/resources") + @SelectJson("value") + @Fallback(EmptyListOnNotFoundOr404.class) + List resources(@PathParam("name") String name); + @Named("resourcegroup:update") @PATCH @Produces(MediaType.APPLICATION_JSON) @Path("/{name}") @MapBinder(BindToJsonPayload.class) - ResourceGroup update(@PathParam("name") String name, @Nullable @PayloadParam("tags")Map tags); + ResourceGroup update(@PathParam("name") String name, @Nullable @PayloadParam("tags") Map tags); @Named("resourcegroup:delete") @DELETE diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiLiveTest.java index 3a0c134343..2dd8097e53 100644 --- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiLiveTest.java +++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiLiveTest.java @@ -19,6 +19,7 @@ package org.jclouds.azurecompute.arm.features; import java.net.URI; import java.util.List; +import org.jclouds.azurecompute.arm.domain.Resource; import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest; import org.testng.annotations.AfterClass; @@ -42,6 +43,15 @@ public class ResourceGroupApiLiveTest extends BaseAzureComputeApiLiveTest { return api.getResourceGroupApi(); } + @Test(dependsOnMethods = "testCreate") + public void testResources() { + List resources = api().resources(RESOURCE_GROUP_NAME); + assertTrue(resources.isEmpty()); + for (Resource resource : resources) { + assertNotNull(resource); + } + } + @Test(dependsOnMethods = "testCreate") public void testList() { final List resourceGroups = api().list(); @@ -66,7 +76,6 @@ public class ResourceGroupApiLiveTest extends BaseAzureComputeApiLiveTest { } public void testCreate() { - final ResourceGroup resourceGroup = api().create(RESOURCE_GROUP_NAME, LOCATION, null); assertEquals(resourceGroup.name(), RESOURCE_GROUP_NAME); assertEquals(resourceGroup.location(), LOCATION); diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiMockTest.java index 0c03c756aa..acac271c71 100644 --- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiMockTest.java +++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ResourceGroupApiMockTest.java @@ -16,20 +16,22 @@ */ package org.jclouds.azurecompute.arm.features; -import static com.google.common.collect.Iterables.isEmpty; -import static com.google.common.collect.Iterables.size; -import static org.testng.Assert.assertNotNull; - import java.net.URI; import java.util.List; -import com.google.common.collect.ImmutableMap; +import org.jclouds.azurecompute.arm.domain.Resource; import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest; import org.testng.annotations.Test; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.assertNull; + +import com.google.common.collect.ImmutableMap; + +import static com.google.common.collect.Iterables.isEmpty; +import static com.google.common.collect.Iterables.size; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; @Test(groups = "unit", testName = "ResourceGroupApiMockTest", singleThreaded = true) public class ResourceGroupApiMockTest extends BaseAzureComputeApiMockTest { @@ -147,4 +149,25 @@ public class ResourceGroupApiMockTest extends BaseAzureComputeApiMockTest { assertSent(server, "DELETE", requestUrl + "/jcloudstest" + version); } + public void testListResourceGroupResources() throws InterruptedException { + server.enqueue(jsonResponse("/resourcegroup-resources.json")); + + List resources = api.getResourceGroupApi().resources("jcloudstest"); + + assertEquals(size(resources), 6); + + assertSent(server, "GET", requestUrl + "/jcloudstest/resources" + version); + } + + public void testListResourceGroupResourcesReturns404() throws InterruptedException { + server.enqueue(response404()); + + List resources = api.getResourceGroupApi().resources("jcloudstest"); + + assertTrue(isEmpty(resources)); + + assertEquals(server.getRequestCount(), 1); + assertSent(server, "GET", requestUrl + "/jcloudstest/resources" + version); + } + } diff --git a/providers/azurecompute-arm/src/test/resources/resourcegroup-resources.json b/providers/azurecompute-arm/src/test/resources/resourcegroup-resources.json new file mode 100644 index 0000000000..cae1a189a0 --- /dev/null +++ b/providers/azurecompute-arm/src/test/resources/resourcegroup-resources.json @@ -0,0 +1,46 @@ +{ + "value": [ + { + "id": "/subscriptions/610bba05-d7a7-4567-96af-48ecbd09453b/resourceGroups/test/providers/Microsoft.Compute/virtualMachines/test", + "name": "test", + "type": "Microsoft.Compute/virtualMachines", + "location": "northeurope" + }, + { + "id": "/subscriptions/610bba05-d7a7-4567-96af-48ecbd09453b/resourceGroups/test/providers/Microsoft.Network/networkInterfaces/test641", + "name": "test641", + "type": "Microsoft.Network/networkInterfaces", + "location": "northeurope" + }, + { + "id": "/subscriptions/610bba05-d7a7-4567-96af-48ecbd09453b/resourceGroups/test/providers/Microsoft.Network/networkSecurityGroups/test-nsg", + "name": "test-nsg", + "type": "Microsoft.Network/networkSecurityGroups", + "location": "northeurope" + }, + { + "id": "/subscriptions/610bba05-d7a7-4567-96af-48ecbd09453b/resourceGroups/test/providers/Microsoft.Network/publicIPAddresses/test-ip", + "name": "test-ip", + "type": "Microsoft.Network/publicIPAddresses", + "location": "northeurope" + }, + { + "id": "/subscriptions/610bba05-d7a7-4567-96af-48ecbd09453b/resourceGroups/test/providers/Microsoft.Network/virtualNetworks/test-vnet", + "name": "test-vnet", + "type": "Microsoft.Network/virtualNetworks", + "location": "northeurope" + }, + { + "id": "/subscriptions/610bba05-d7a7-4567-96af-48ecbd09453b/resourceGroups/test/providers/Microsoft.Storage/storageAccounts/testjclo", + "name": "testjclo", + "type": "Microsoft.Storage/storageAccounts", + "sku": { + "name": "Premium_LRS", + "tier": "Premium" + }, + "kind": "Storage", + "location": "northeurope", + "tags": {} + } + ] +}