From 83c0a3c7b255ec744c6150ce76c40e8301280c79 Mon Sep 17 00:00:00 2001 From: Ignasi Barrera Date: Mon, 24 Apr 2017 14:49:57 +0200 Subject: [PATCH] JCLOUDS-1273/JCLOUDS-1226: Support multiple resource groups in ARM --- .../azurecompute/arm/AzureComputeApi.java | 8 +- .../arm/compute/AzureComputeService.java | 15 ++- .../compute/AzureComputeServiceAdapter.java | 88 ++++++++------- .../AzureComputeServiceContextModule.java | 18 ++-- .../domain/LocationAndName.java} | 22 ++-- .../compute/domain/ResourceGroupAndName.java | 50 +++++++++ ... ResourceGroupAndNameAndIngressRules.java} | 33 +++--- .../AzureComputeImageExtension.java | 39 +++---- .../AzureComputeSecurityGroupExtension.java | 100 +++++++++--------- .../functions/CustomImageToVMImage.java | 4 +- .../NetworkSecurityGroupToSecurityGroup.java | 7 +- .../functions/TemplateToAvailabilitySet.java | 8 +- .../functions/VMHardwareToHardware.java | 22 ++-- .../arm/compute/functions/VMImageToImage.java | 25 +++-- .../VirtualMachineToNodeMetadata.java | 50 ++++----- .../functions/VirtualMachineToStatus.java | 11 +- .../loaders/CreateSecurityGroupIfNeeded.java | 15 +-- ...ocation.java => DefaultResourceGroup.java} | 6 +- .../compute/options/AzureTemplateOptions.java | 78 ++++++-------- .../compute/strategy/CleanupResources.java | 79 ++++++-------- ...va => CreateResourcesThenCreateNodes.java} | 76 +++++++------ .../azurecompute/arm/domain/IdReference.java | 39 ++++++- .../azurecompute/arm/domain/VMHardware.java | 11 +- .../azurecompute/arm/domain/VMImage.java | 8 ++ .../azurecompute/arm/features/JobApi.java | 2 +- .../azurecompute/arm/util/VMImages.java | 2 +- .../compute/AzureComputeServiceLiveTest.java | 29 ++--- .../compute/AzureTemplateBuilderLiveTest.java | 2 +- .../AzureComputeImageExtensionLiveTest.java | 24 ++--- ...ComputeSecurityGroupExtensionLiveTest.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 +- 35 files changed, 577 insertions(+), 488 deletions(-) rename providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/{domain/RegionAndId.java => compute/domain/LocationAndName.java} (69%) create mode 100644 providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndName.java rename providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/{RegionAndIdAndIngressRules.java => ResourceGroupAndNameAndIngressRules.java} (56%) rename providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/{ResourceGroupForLocation.java => DefaultResourceGroup.java} (91%) rename providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/{CreateResourceGroupThenCreateNodes.java => CreateResourcesThenCreateNodes.java} (77%) create mode 100644 providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/domain/IdReferenceTest.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 7081486861..a25690f52a 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 doc */ 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(); 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 f566a69c53..dcb9c442d8 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 resourceGroupMap; @Inject protected AzureComputeService(ComputeServiceContext context, Map 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, - Optional securityGroupExtension, LoadingCache resourceGroupMap) { + Optional 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 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 { 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 8f9b67c883..2e9e0f6ba4 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 imagePublishers; private final Supplier> regionIds; private final PublicIpAvailablePredicateFactory publicIpAvailable; - private final LoadingCache resourceGroupMap; private final CustomImageToVMImage customImagetoVmImage; @Inject AzureComputeServiceAdapter(final AzureComputeApi api, @Named(IMAGE_PUBLISHERS) String imagePublishers, CleanupResources cleanupResources, @Region Supplier> regionIds, - PublicIpAvailablePredicateFactory publicIpAvailable, LoadingCache 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 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, regionAndId.slashEncode(), null); + ResourceGroupAndName resourceGroupAndName = fromResourceGroupAndName(resourceGroupName, name); + return new NodeAndInitialCredentials(virtualMachine, resourceGroupAndName.slashEncode(), null); } @Override @@ -183,8 +182,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter listCustomImagesByLocation(String location) { - ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location); - List customImages = api.getVirtualMachineImageApi(resourceGroup.name()).list(); + private List listCustomImagesByResourceGroup(String resourceGroup) { + List customImages = api.getVirtualMachineImageApi(resourceGroup).list(); return Lists.transform(customImages, customImagetoVmImage); } @@ -231,16 +228,29 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter listImages() { final ImmutableList.Builder osImages = ImmutableList.builder(); - Iterable availableLocationNames = transform(listLocations(), new Function() { - @Override - public String apply(Location location) { - return location.name(); - } - }); + final List availableLocationNames = newArrayList(transform(listLocations(), + new Function() { + @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 resourceGroupsInLocation = filter(api.getResourceGroupApi().list(), + new Predicate() { + @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 listNodesByIds(final Iterable ids) { - return filter(listNodes(), new Predicate() { + return transform(ids, new Function() { @Override - public boolean apply(VirtualMachine virtualMachine) { - return contains(ids, virtualMachine.id()); + public VirtualMachine apply(String input) { + return getNode(input); } }); } 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 cf3c90c58b..11d3ab141f 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>() { + bind(new TypeLiteral>() { }).to(CreateSecurityGroupIfNeeded.class); bind(new TypeLiteral>() { - }).to(ResourceGroupForLocation.class); + }).to(DefaultResourceGroup.class); bind(new TypeLiteral() { }).to(AzureComputeImageExtension.class); @@ -131,14 +131,14 @@ public class AzureComputeServiceContextModule extends @Provides @Singleton - protected final LoadingCache securityGroupMap( - CacheLoader in) { + protected final LoadingCache securityGroupMap( + CacheLoader in) { return CacheBuilder.newBuilder().build(in); } @Provides @Singleton - protected final LoadingCache resourceGroupMap(CacheLoader in) { + protected final LoadingCache defaultResourceGroup(CacheLoader in) { return CacheBuilder.newBuilder().build(in); } 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/compute/domain/LocationAndName.java similarity index 69% rename from providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java rename to providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/LocationAndName.java index 4105ee3dc9..014244882a 100644 --- 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/compute/domain/LocationAndName.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jclouds.azurecompute.arm.domain; +package org.jclouds.azurecompute.arm.compute.domain; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -24,27 +24,27 @@ import com.google.common.base.Splitter; import com.google.common.collect.Iterables; @AutoValue -public abstract class RegionAndId { +public abstract class LocationAndName { - public abstract String region(); - public abstract String id(); + public abstract String location(); + public abstract String name(); - protected RegionAndId() { + protected LocationAndName() { } - public static RegionAndId fromSlashEncoded(String id) { + public static LocationAndName fromSlashEncoded(String id) { Iterable 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)); + 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 RegionAndId fromRegionAndId(String region, String id) { - return new AutoValue_RegionAndId(region, id); + public static LocationAndName fromLocationAndName(String location, String name) { + return new AutoValue_LocationAndName(location, name); } public String slashEncode() { - return region() + "/" + id(); + return location() + "/" + name(); } } 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 0000000000..c06056ecc4 --- /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 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(); + } + +} 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/ResourceGroupAndNameAndIngressRules.java similarity index 56% rename from providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/RegionAndIdAndIngressRules.java rename to providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java index fa9730d183..2b07406e45 100644 --- 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/ResourceGroupAndNameAndIngressRules.java @@ -16,31 +16,36 @@ */ package org.jclouds.azurecompute.arm.compute.domain; -import org.jclouds.azurecompute.arm.domain.RegionAndId; +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 RegionAndIdAndIngressRules { +public abstract class ResourceGroupAndNameAndIngressRules { + + abstract ResourceGroupAndName resourceGroupAndName(); // Intentionally hidden + + public abstract String location(); - abstract RegionAndId regionAndId(); // Intentionally hidden public abstract int[] inboundPorts(); - RegionAndIdAndIngressRules() { + ResourceGroupAndNameAndIngressRules() { } - public static RegionAndIdAndIngressRules create(String region, String id, int[] inboundPorts) { - return new AutoValue_RegionAndIdAndIngressRules(RegionAndId.fromRegionAndId(region, id), inboundPorts); + public static ResourceGroupAndNameAndIngressRules create(String resourceGroup, String location, String name, + int[] inboundPorts) { + return new AutoValue_ResourceGroupAndNameAndIngressRules(fromResourceGroupAndName(resourceGroup, name), location, + inboundPorts); } - public String id() { - return regionAndId().id(); + public String name() { + return resourceGroupAndName().name(); } - public String region() { - return regionAndId().region(); + public String resourceGroup() { + return resourceGroupAndName().resourceGroup(); } // Intentionally delegate equals and hashcode to the fields in the parent @@ -48,7 +53,7 @@ public abstract class RegionAndIdAndIngressRules { @Override public int hashCode() { - return Objects.hashCode(region(), id()); + return Objects.hashCode(resourceGroup(), name()); } @Override @@ -56,11 +61,11 @@ public abstract class RegionAndIdAndIngressRules { if (obj == this) { return true; } - if (!(obj instanceof RegionAndId)) { + if (!(obj instanceof ResourceGroupAndName)) { return false; } - RegionAndId that = (RegionAndId) obj; - return Objects.equal(region(), that.region()) && Objects.equal(id(), that.id()); + ResourceGroupAndName that = (ResourceGroupAndName) obj; + return Objects.equal(resourceGroup(), that.resourceGroup()) && Objects.equal(name(), that.name()); } } 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 4bfa449fac..7d654d56a1 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 resourceGroupMap; private final Function vmImageToImage; private final Predicate 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 vmImageToImage, LoadingCache resourceGroupMap, - @Named(TIMEOUT_RESOURCE_DELETED) Predicate resourceDeleted, + Function vmImageToImage, @Named(TIMEOUT_RESOURCE_DELETED) Predicate 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 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() { @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); } } 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 f23cfd83c9..eafb4f1409 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 securityGroupConverter; - private final Supplier> locations; private final SecurityGroupAvailablePredicateFactory securityGroupAvailable; private final Predicate resourceDeleted; - private final LoadingCache resourceGroupMap; + private final LoadingCache defaultResourceGroup; @Inject - AzureComputeSecurityGroupExtension(AzureComputeApi api, @Memoized Supplier> locations, + AzureComputeSecurityGroupExtension(AzureComputeApi api, Function groupConverter, SecurityGroupAvailablePredicateFactory securityRuleAvailable, @Named(TIMEOUT_RESOURCE_DELETED) Predicate resourceDeleted, - LoadingCache resourceGroupMap) { + LoadingCache 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 listSecurityGroups() { - return ImmutableSet.copyOf(concat(transform(locations.get(), new Function>() { - @Override - public Set apply(Location input) { - return listSecurityGroupsInLocation(input); - } - }))); + ImmutableSet.Builder securityGroups = ImmutableSet.builder(); + for (ResourceGroup rg : api.getResourceGroupApi().list()) { + securityGroups.addAll(securityGroupsInResourceGroup(rg.name())); + } + return securityGroups.build(); + } + + private Set securityGroupsInResourceGroup(String resourceGroup) { + List networkGroups = api.getNetworkSecurityGroupApi(resourceGroup).list(); + return ImmutableSet.copyOf(transform(filter(networkGroups, notNull()), securityGroupConverter)); } @Override public Set listSecurityGroupsInLocation(Location location) { - logger.debug(">> getting security groups for %s...", location); - ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location.getId()); - List 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 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 networkInterfacesIdReferences = vm.properties().networkProfile().networkInterfaces(); List networkGroups = new ArrayList(); 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 rules = filter(ruleApi.list(), new Predicate() { @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"); } 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 9cb21882c7..222053555a 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 { @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(); } } 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 65f5b0d8aa..71d51aae70 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 { @@ -46,12 +44,10 @@ public class TemplateToAvailabilitySet implements Function resourceGroupMap; @Inject - TemplateToAvailabilitySet(AzureComputeApi api, LoadingCache resourceGroupMap) { + TemplateToAvailabilitySet(AzureComputeApi api) { this.api = api; - this.resourceGroupMap = resourceGroupMap; } @Nullable @@ -62,7 +58,7 @@ public class TemplateToAvailabilitySet implements Function { @@ -49,10 +51,10 @@ public class VMHardwareToHardware implements Function { 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()); 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 4f021002b3..2a5075ce98 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 { private static final Map OTHER_OS_MAP = ImmutableMap. builder() @@ -64,8 +65,8 @@ public class VMImageToImage implements Function { 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 { } 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 { 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 + "/" + 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 9bad6e57e1..bcfd4fee03 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 { @@ -74,20 +73,18 @@ public class VirtualMachineToNodeMetadata implements Function> locations; private final Supplier> hardwares; - private final LoadingCache resourceGroupMap; private final ImageCacheSupplier imageCache; private final VirtualMachineToStatus virtualMachineToStatus; @Inject VirtualMachineToNodeMetadata(AzureComputeApi api, GroupNamingConvention.Factory namingConvention, Supplier> hardwares, @Memoized Supplier> locations, - Map credentialStore, LoadingCache resourceGroupMap, - @Memoized Supplier> imageCache, VirtualMachineToStatus virtualMachineToStatus) { + Map credentialStore, @Memoized Supplier> 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 image = findImage(virtualMachine.properties().storageProfile(), locationName, - resourceGroup.name()); + Optional image = findImage(virtualMachine.properties().storageProfile(), locationName); if (image.isPresent()) { builder.imageId(image.get().getId()); @@ -137,7 +132,8 @@ public class VirtualMachineToNodeMetadata implements Function getPublicIpAddresses(List idReferences) { @@ -172,11 +164,11 @@ public class VirtualMachineToNodeMetadata implements Function findImage(final StorageProfile storageProfile, String locatioName, - String azureGroup) { + protected Optional 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() { + protected Hardware getHardware(final LocationAndName hardwareId) { + final String slashEncoded = hardwareId.slashEncode(); + return find(hardwares.get().values(), new Predicate() { @Override public boolean apply(Hardware input) { - return input.getId().equals(vmSize); + return input.getId().equals(slashEncoded); } }); } 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 c0e333e3b1..9669f50b70 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 resourceGroupMap; @Inject - VirtualMachineToStatus(AzureComputeApi api, LoadingCache 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 { +public class CreateSecurityGroupIfNeeded extends CacheLoader { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; private final AzureComputeApi api; - private final LoadingCache resourceGroupMap; @Inject - CreateSecurityGroupIfNeeded(AzureComputeApi api, LoadingCache 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) { 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/DefaultResourceGroup.java similarity index 91% rename from providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/ResourceGroupForLocation.java rename to providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/DefaultResourceGroup.java index ddbbb26ef2..7caec25e90 100644 --- 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/DefaultResourceGroup.java @@ -34,7 +34,7 @@ import com.google.common.cache.CacheLoader; import com.google.common.collect.ImmutableMap; @Singleton -public class ResourceGroupForLocation extends CacheLoader { +public class DefaultResourceGroup extends CacheLoader { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; @@ -43,7 +43,7 @@ public class ResourceGroupForLocation extends CacheLoader private final LocationToResourceGroupName locationToResourceGroupName; @Inject - ResourceGroupForLocation(AzureComputeApi api, LocationToResourceGroupName locationToResourceGroupName) { + DefaultResourceGroup(AzureComputeApi api, LocationToResourceGroupName locationToResourceGroupName) { this.api = api.getResourceGroupApi(); this.locationToResourceGroupName = locationToResourceGroupName; } @@ -54,7 +54,7 @@ public class ResourceGroupForLocation extends CacheLoader ResourceGroup resourceGroup = api.get(azureGroupName); if (resourceGroup == null) { logger.debug(">> creating resource group %s", azureGroupName); - final Map tags = ImmutableMap.of("description", "jclouds managed VMs"); + final Map tags = ImmutableMap.of("description", "jclouds default resource group"); resourceGroup = api.create(azureGroupName, locationId, tags); } return resourceGroup; 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 5566ecfb33..d211421bc6 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 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 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 getDataDisks() { - return dataDisks; - } + public List 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 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); + } } } 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 fb635aa67d..79f2cd0bb0 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 resourceDeleted; - private final LoadingCache resourceGroupMap; private final GroupNamingConvention.Factory namingConvention; @Inject CleanupResources(AzureComputeApi azureComputeApi, @Named(TIMEOUT_RESOURCE_DELETED) Predicate resourceDeleted, - LoadingCache 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 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 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 getPublicIps(String group, NetworkInterfaceCard nic) { - return transform( - filter(transform(nic.properties().ipConfigurations(), new Function() { - @Override - public IdReference apply(IpConfiguration input) { - return input.properties().publicIPAddress(); - } - }), notNull()), new Function() { - @Override - public String apply(IdReference input) { - return Iterables.getLast(Splitter.on("/").split(input.id())); - } - }); + private Iterable getPublicIps(NetworkInterfaceCard nic) { + return filter(transform(nic.properties().ipConfigurations(), new Function() { + @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 getNetworkCardInterfaceNames(VirtualMachine virtualMachine) { - List 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())); } 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/CreateResourcesThenCreateNodes.java similarity index 77% rename from providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java rename to providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourcesThenCreateNodes.java index 5f6d88f86a..c3bdbdd07e 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/CreateResourcesThenCreateNodes.java @@ -16,6 +16,12 @@ */ 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; @@ -27,12 +33,12 @@ 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.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.RegionAndId; import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.domain.Subnet; import org.jclouds.azurecompute.arm.domain.VirtualNetwork; @@ -42,7 +48,6 @@ 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; @@ -53,32 +58,26 @@ 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; -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 { +public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedIntoNameThenAddToSet { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; private final AzureComputeApi api; - private final LoadingCache securityGroupMap; - private final LoadingCache resourceGroupMap; + private final LoadingCache securityGroupMap; private final String defaultVnetAddressPrefix; private final String defaultSubnetAddressPrefix; private final TemplateToAvailabilitySet templateToAvailabilitySet; @Inject - protected CreateResourceGroupThenCreateNodes( + protected CreateResourcesThenCreateNodes( CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy, ListNodesStrategy listNodesStrategy, GroupNamingConvention.Factory namingConvention, @@ -86,15 +85,13 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory, AzureComputeApi api, @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX) String defaultVnetAddressPrefix, @Named(DEFAULT_SUBNET_ADDRESS_PREFIX) String defaultSubnetAddressPrefix, - LoadingCache securityGroupMap, - LoadingCache resourceGroupMap, + LoadingCache 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.resourceGroupMap = resourceGroupMap; this.defaultVnetAddressPrefix = defaultVnetAddressPrefix; this.defaultSubnetAddressPrefix = defaultSubnetAddressPrefix; this.templateToAvailabilitySet = templateToAvailabilitySet; @@ -117,24 +114,22 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco // 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); + 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, - final String azureGroupName) { + protected synchronized void getOrCreateVirtualNetworkWithSubnet(final String location, AzureTemplateOptions options) { String virtualNetworkName = Optional.fromNullable(options.getVirtualNetworkName()).or( - azureGroupName + "virtualnetwork"); - String subnetName = azureGroupName + "subnet"; + 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(azureGroupName); + VirtualNetworkApi vnApi = api.getVirtualNetworkApi(options.getResourceGroup()); VirtualNetwork vn = vnApi.get(virtualNetworkName); if (vn == null) { @@ -148,7 +143,7 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco vn = vnApi.createOrUpdate(virtualNetworkName, location, virtualNetworkProperties); } - SubnetApi subnetApi = api.getSubnetApi(azureGroupName, virtualNetworkName); + SubnetApi subnetApi = api.getSubnetApi(options.getResourceGroup(), virtualNetworkName); Subnet subnet = subnetApi.get(subnetName); options.virtualNetworkName(virtualNetworkName); @@ -160,23 +155,21 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco && !template.getOptions().hasLoginPrivateKeyOption(); } - private void configureSecurityGroupForOptions(String group, String resourceGroup, Location location, - TemplateOptions options) { + 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()) { - 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); + 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); - RegionAndIdAndIngressRules regionAndIdAndIngressRules = RegionAndIdAndIngressRules.create(location.getId(), - name, options.getInboundPorts()); + 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); @@ -190,4 +183,17 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco 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")); + } + } } 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 1854897e65..f73e3e4e55 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; + } } 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 f0aa77e943..e7719038cd 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"}) + public static VMHardware create(String name, Integer numberOfCores, Integer osDiskSizeInMB, Integer resourceDiskSizeInMB, Integer memoryInMB, Integer maxDataDiskCount, String location) { - @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) { - - return new AutoValue_VMHardware(name, numberOfCores, osDiskSizeInMB, resourceDiskSizeInMB, memoryInMB, maxDataDiskCount, location, globallyAvailable); + return new AutoValue_VMHardware(name, numberOfCores, osDiskSizeInMB, resourceDiskSizeInMB, memoryInMB, maxDataDiskCount, location); } } 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 a01ed23467..91ca8189b9 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); 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 5a01e90f4d..a854fed657 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 { 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 a5944ecd8e..238832e384 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; } } 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 7c5c97fa63..46f4ed4bb9 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 resourceGroupMap; private Predicate 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>() { - })); resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral>() { }, 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 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 d4cbdb07e7..b00aa0533c 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; } 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 d708723afb..885269d33b 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 resourceGroupMap; private Predicate 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>() { - })); resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral>() { }, 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 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); } } 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 e00880be90..153df2964a 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 resourceGroupMap; private Predicate 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>() { - })); resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral>() { }, 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 = 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 groups = securityGroupExtension.get().listSecurityGroupsForNode(node.getId()); @@ -121,8 +118,8 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou Optional 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 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); } } 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 0000000000..e5426d7aa0 --- /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"); + } +} 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 d976258c4a..15231fd871 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 resourceGroupMap; private Predicate 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>() { }, Names.named(TIMEOUT_RESOURCE_DELETED))); - resourceGroupMap = context.utils().injector() - .getInstance(Key.get(new TypeLiteral>() { - })); 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()); - } - } 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 5799093089..d267912a54 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 resourceGroupMap; private Predicate resourceDeleted; private PublicIpAvailablePredicateFactory publicIpAvailable; private Predicate> 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>() { }, Names.named(TIMEOUT_RESOURCE_DELETED))); - resourceGroupMap = context.utils().injector() - .getInstance(Key.get(new TypeLiteral>() { - })); publicIpAvailable = context.utils().injector().getInstance(PublicIpAvailablePredicateFactory.class); resourceAvailable = context.utils().injector() .getInstance(Key.get(new TypeLiteral>>() { @@ -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 nodes = view.getComputeService() - .createNodesInGroup(group, count, availabilitySet(as)); + Set nodes = view.getComputeService().createNodesInGroup(group, count, + availabilitySet(as).resourceGroup(this.group)); List nicNames = new ArrayList(); 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() { 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 754f5fe86a..4d101ca455 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); 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 cf6546227d..10406b8679 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