Refactored Azure ARM to not use Deployments

* Simplified ImageExtension
* Fixed access to deployed VMS
* Made api-version configurable for all apis"
* Fixed all feature live tests
* Fixed the AzureComputeServiceLiveTest
* Fixed the AzureTemplateBuilderLiveTest
* Fixed the AzureComputeImageExtensionLiveTest
This commit is contained in:
Andrea Turli 2016-09-28 18:20:26 +02:00 committed by Ignasi Barrera
parent 8df58654b8
commit cd16826dca
60 changed files with 1912 additions and 2635 deletions

View File

@ -32,8 +32,7 @@ azure ad app create --name <name> --password <password> --home-page <home-page>
# Create a Service Principal
azure ad sp create <Application-id>
# Output will include a value for `Object Id`
# Output will include a value for `Object Id`, to be used in the next step
```
Run the following commands to assign roles to the service principal
@ -58,7 +57,8 @@ mvn -Dtest=<name of the live test> \
-Dtest.azurecompute-arm.identity="<Application-id>" \
-Dtest.azurecompute-arm.credential="<password>" \
-Dtest.azurecompute-arm.endpoint="https://management.azure.com/subscriptions/<Subscription-id>" \
-Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test
-Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token"
integration-test -Plive
```

View File

@ -46,7 +46,7 @@
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.parent.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>
@ -76,11 +76,6 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>

View File

@ -16,28 +16,27 @@
*/
package org.jclouds.azurecompute.arm;
import java.io.Closeable;
import javax.ws.rs.PathParam;
import org.jclouds.azurecompute.arm.features.DeploymentApi;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.azurecompute.arm.features.JobApi;
import org.jclouds.azurecompute.arm.features.LocationApi;
import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
import org.jclouds.azurecompute.arm.features.OSImageApi;
import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
import org.jclouds.azurecompute.arm.features.StorageAccountApi;
import org.jclouds.azurecompute.arm.features.SubnetApi;
import org.jclouds.azurecompute.arm.features.VMSizeApi;
import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
import org.jclouds.azurecompute.arm.features.VMSizeApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
import org.jclouds.rest.annotations.Delegate;
import com.google.inject.Provides;
import javax.ws.rs.PathParam;
import java.io.Closeable;
/**
* The Azure Resource Manager API is a REST API for managing your services and deployments.
* <p>
@ -165,6 +164,4 @@ public interface AzureComputeApi extends Closeable {
@Delegate
ResourceProviderApi getResourceProviderApi();
@Provides
DeploymentTemplateBuilder.Factory deploymentTemplateFactory();
}

View File

@ -17,31 +17,47 @@
package org.jclouds.azurecompute.arm;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN;
import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_AUTHENTICATE_SUDO;
import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER;
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
import java.net.URI;
import java.util.Properties;
import org.jclouds.azurecompute.arm.domain.Region;
import org.jclouds.azurecompute.arm.features.DeploymentApi;
import org.jclouds.azurecompute.arm.features.LocationApi;
import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
import org.jclouds.azurecompute.arm.features.OSImageApi;
import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
import org.jclouds.azurecompute.arm.features.StorageAccountApi;
import org.jclouds.azurecompute.arm.features.SubnetApi;
import org.jclouds.azurecompute.arm.features.VMSizeApi;
import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
import org.jclouds.compute.config.ComputeServiceProperties;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadata;
import org.jclouds.compute.config.ComputeServiceProperties;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import com.google.auto.service.AutoService;
@ -72,13 +88,37 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
properties.setProperty(TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
properties.put(RESOURCE, "https://management.azure.com/");
properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
properties.put(RESOURCE_GROUP_NAME, "jcloudsgroup");
properties.put(RESOURCE_GROUP_NAME, "jclouds");
properties.put(DEFAULT_VNET_ADDRESS_SPACE_PREFIX, "10.0.0.0/16");
properties.put(DEFAULT_SUBNET_ADDRESS_PREFIX, "10.0.0.0/24");
properties.put(DEFAULT_DATADISKSIZE, "100");
properties.put(IMAGE_PUBLISHERS, "Canonical,RedHat");
properties.put(DEFAULT_IMAGE_LOGIN, "jclouds:Password1!");
// Default credentials for all images
properties.put(IMAGE_LOGIN_USER, "jclouds:Password12345!");
properties.put(IMAGE_AUTHENTICATE_SUDO, "true");
properties.put(TEMPLATE, "imageNameMatches=UbuntuServer,osVersionMatches=1[45]\\.[01][04]\\.[0-9]-LTS");
properties.put(TIMEOUT_NODE_TERMINATED, 60 * 10 * 1000);
// Api versions used in each API
properties.put(API_VERSION_PREFIX + DeploymentApi.class.getSimpleName(), "2016-02-01");
properties.put(API_VERSION_PREFIX + LocationApi.class.getSimpleName(), "2015-11-01");
properties.put(API_VERSION_PREFIX + NetworkInterfaceCardApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + NetworkSecurityGroupApi.class.getSimpleName(), "2016-03-30");
properties.put(API_VERSION_PREFIX + NetworkSecurityRuleApi.class.getSimpleName(), "2016-03-30");
properties.put(API_VERSION_PREFIX + OSImageApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + PublicIPAddressApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + ResourceGroupApi.class.getSimpleName(), "2015-01-01");
properties.put(API_VERSION_PREFIX + ResourceProviderApi.class.getSimpleName(), "2015-01-01");
properties.put(API_VERSION_PREFIX + StorageAccountApi.class.getSimpleName(), STORAGE_API_VERSION);
properties.put(API_VERSION_PREFIX + SubnetApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + VirtualNetworkApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + VMSizeApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + VirtualMachineApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + "GetVirtualMachine", "2016-03-30");
properties.put(API_VERSION_PREFIX + "GetVirtualMachineInstance", "2016-03-30");
properties.put(API_VERSION_PREFIX + "CreateVirtualMachine", "2016-03-30");
properties.put(API_VERSION_PREFIX + "ListVirtualMachines", "2015-06-15");
properties.put(API_VERSION_PREFIX + "DeleteVirtualMachine", "2016-03-30");
return properties;
}

View File

@ -17,164 +17,139 @@
package org.jclouds.azurecompute.arm.compute;
import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.util.Predicates2.retry;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
import static org.jclouds.util.Closeables2.closeQuietly;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
import org.jclouds.azurecompute.arm.compute.functions.DeploymentToVMDeployment;
import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
import org.jclouds.azurecompute.arm.compute.predicates.IsDeploymentInRegions;
import org.jclouds.azurecompute.arm.domain.Deployment;
import org.jclouds.azurecompute.arm.domain.DeploymentBody;
import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.DataDisk;
import org.jclouds.azurecompute.arm.domain.HardwareProfile;
import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.ImageReference;
import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
import org.jclouds.azurecompute.arm.domain.Location;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.domain.NetworkProfile;
import org.jclouds.azurecompute.arm.domain.OSDisk;
import org.jclouds.azurecompute.arm.domain.OSProfile;
import org.jclouds.azurecompute.arm.domain.Offer;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
import org.jclouds.azurecompute.arm.domain.SKU;
import org.jclouds.azurecompute.arm.domain.StorageProfile;
import org.jclouds.azurecompute.arm.domain.StorageService;
import org.jclouds.azurecompute.arm.domain.VMDeployment;
import org.jclouds.azurecompute.arm.domain.StorageService.Status;
import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
import org.jclouds.azurecompute.arm.domain.VHD;
import org.jclouds.azurecompute.arm.domain.VMHardware;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VMSize;
import org.jclouds.azurecompute.arm.domain.Value;
import org.jclouds.azurecompute.arm.domain.Version;
import org.jclouds.azurecompute.arm.features.DeploymentApi;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.features.OSImageApi;
import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
import org.jclouds.azurecompute.arm.functions.CleanupResources;
import org.jclouds.azurecompute.arm.util.BlobHelper;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.location.Region;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.net.UrlEscapers;
/**
* Defines the connection between the {@link AzureComputeApi} implementation and the jclouds
* {@link org.jclouds.compute.ComputeService}.
*/
@Singleton
public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeployment, VMHardware, VMImage, Location> {
public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location> {
private String azureGroup;
protected final CleanupResources cleanupResources;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
private Logger logger = Logger.NULL;
private final String azureGroup;
private final CleanupResources cleanupResources;
private final AzureComputeApi api;
private final AzureComputeConstants azureComputeConstants;
private final Supplier<Set<String>> regionIds;
private final IsDeploymentInRegions isDeploymentInRegions;
private final DeploymentToVMDeployment deploymentToVMDeployment;
private final Predicate<String> publicIpAvailable;
@Inject
AzureComputeServiceAdapter(final AzureComputeApi api, final AzureComputeConstants azureComputeConstants,
CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
IsDeploymentInRegions isDeploymentInRegions, DeploymentToVMDeployment deploymentToVMDeployment) {
@Named("PublicIpAvailable") Predicate<String> publicIpAvailable) {
this.api = api;
this.azureComputeConstants = azureComputeConstants;
this.azureGroup = azureComputeConstants.azureResourceGroup();
logger.debug("AzureComputeServiceAdapter set azuregroup to: " + azureGroup);
this.cleanupResources = cleanupResources;
this.regionIds = regionIds;
this.isDeploymentInRegions = isDeploymentInRegions;
this.deploymentToVMDeployment = deploymentToVMDeployment;
this.publicIpAvailable = publicIpAvailable;
}
@Override
public NodeAndInitialCredentials<VMDeployment> createNodeWithGroupEncodedIntoName(
public NodeAndInitialCredentials<VirtualMachine> createNodeWithGroupEncodedIntoName(
final String group, final String name, final Template template) {
DeploymentTemplateBuilder deploymentTemplateBuilder = api.deploymentTemplateFactory().create(group, name, template);
AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class);
final String loginUser = DeploymentTemplateBuilder.getLoginUserUsername();
final String loginPassword = DeploymentTemplateBuilder.getLoginPassword();
// TODO Store group apart from the name to be able to identify nodes with custom names in the configured group
// TODO ARM specific options
// TODO user metadata and tags
// TODO network ids => create one nic in each network
// TODO inbound ports
String locationName = template.getLocation().getId();
String subnetId = templateOptions.getSubnetId();
NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName);
StorageProfile storageProfile = createStorageProfile(name, template.getImage(), templateOptions.getBlob());
HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(template.getHardware().getId()).build();
OSProfile osProfile = createOsProfile(name, template);
NetworkProfile networkProfile = NetworkProfile.builder().networkInterfaces(ImmutableList.of(IdReference.create(nic.id()))).build();
VirtualMachineProperties virtualMachineProperties = VirtualMachineProperties.builder()
.licenseType(null) // TODO
.availabilitySet(null) // TODO
.hardwareProfile(hardwareProfile)
.storageProfile(storageProfile)
.osProfile(osProfile)
.networkProfile(networkProfile)
.build();
DeploymentBody deploymentTemplateBody = deploymentTemplateBuilder.getDeploymentTemplate();
VirtualMachine virtualMachine = api.getVirtualMachineApi(azureGroup).create(name, template.getLocation().getId(), virtualMachineProperties);
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
final String deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplateBuilder.getDeploymentTemplateJson(properties));
logger.debug("Deployment created with name: %s group: %s", name, group);
final Set<VMDeployment> deployments = Sets.newHashSet();
final DeploymentApi deploymentApi = api.getDeploymentApi(azureGroup);
if (!retry(new Predicate<String>() {
@Override
public boolean apply(final String name) {
Deployment deployment = deploymentApi.create(name, deploymentTemplate);
if (deployment != null) {
VMDeployment vmDeployment = VMDeployment.create(deployment);
deployments.add(vmDeployment);
} else {
logger.debug("Failed to create deployment!");
}
return !deployments.isEmpty();
}
}, azureComputeConstants.operationTimeout(), 1, SECONDS).apply(name)) {
final String illegalStateExceptionMessage = format("Deployment %s was not created within %sms so it will be destroyed.",
name, azureComputeConstants.operationTimeout());
logger.warn(illegalStateExceptionMessage);
destroyNode(name);
throw new IllegalStateException(illegalStateExceptionMessage);
}
final VMDeployment deployment = deployments.iterator().next();
NodeAndInitialCredentials<VMDeployment> credential;
if (template.getOptions().getPublicKey() != null){
String privateKey = template.getOptions().getPrivateKey();
credential = new NodeAndInitialCredentials<VMDeployment>(deployment, name,
LoginCredentials.builder().user(loginUser).privateKey(privateKey).authenticateSudo(true).build());
} else {
credential = new NodeAndInitialCredentials<VMDeployment>(deployment, name,
LoginCredentials.builder().user(loginUser).password(loginPassword).authenticateSudo(true).build());
}
return credential;
// 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.
return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, name, null);
}
@Override
public Iterable<VMHardware> listHardwareProfiles() {
final List<VMHardware> hwProfiles = Lists.newArrayList();
final List<String> locationIds = Lists.newArrayList();
Iterable<Location> locations = listLocations();
for (Location location : locations){
locationIds.add(location.name());
for (Location location : listLocations()) {
Iterable<VMSize> vmSizes = api.getVMSizeApi(location.name()).list();
for (VMSize vmSize : vmSizes){
VMHardware hwProfile = VMHardware.create(
vmSize.name(),
@ -188,22 +163,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
hwProfiles.add(hwProfile);
}
}
checkAndSetHwAvailability(hwProfiles, Sets.newHashSet(locationIds));
return hwProfiles;
}
private void checkAndSetHwAvailability(List<VMHardware> hwProfiles, Collection<String> locations) {
Multimap<String, String> hwMap = ArrayListMultimap.create();
for (VMHardware hw : hwProfiles) {
hwMap.put(hw.name(), hw.location());
}
/// TODO
// for (VMHardware hw : hwProfiles) {
// hw.globallyAvailable() = hwMap.get(hw.name()).containsAll(locations);
// }
}
private List<VMImage> getImagesFromPublisher(String publisherName, String location) {
List<VMImage> osImagesRef = Lists.newArrayList();
@ -216,7 +177,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
for (SKU sku : skuList) {
Iterable<Version> versionList = osImageApi.listVersions(publisherName, offer.name(), sku.name());
for (Version version : versionList) {
VMImage vmImage = VMImage.create(publisherName, offer.name(), sku.name(), version.name(), location);
VMImage vmImage = VMImage.azureImage().publisher(publisherName).offer(offer.name()).sku(sku.name())
.version(version.name()).location(location).build();
osImagesRef.add(vmImage);
}
}
@ -235,7 +197,6 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
@Override
public Iterable<VMImage> listImages() {
final List<VMImage> osImages = Lists.newArrayList();
for (Location location : listLocations()){
@ -245,24 +206,51 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
List<StorageService> storages = api.getStorageAccountApi(azureGroup).list();
for (StorageService storage : storages) {
String name = storage.name();
String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1();
List<VMImage> images = BlobHelper.getImages("jclouds", azureGroup, storage.name(), key,
"custom", storage.location());
osImages.addAll(images);
StorageService storageService = api.getStorageAccountApi(azureGroup).get(name);
if (storageService != null
&& Status.Succeeded == storageService.storageServiceProperties().provisioningState()) {
String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1();
BlobHelper blobHelper = new BlobHelper(storage.name(), key);
try {
List<VMImage> images = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER,
storage.location());
osImages.addAll(images);
} finally {
closeQuietly(blobHelper);
}
}
}
return osImages;
}
@Override
public VMImage getImage(final String id) {
VMImage image = VMImageToImage.decodeFieldsFromUniqueId(id);
VMImage image = decodeFieldsFromUniqueId(id);
if (image.custom()) {
String key = api.getStorageAccountApi(azureGroup).getKeys(image.storage()).key1();
if (BlobHelper.customImageExists(image.storage(), key))
return image;
else
VMImage customImage = null;
StorageServiceKeys keys = api.getStorageAccountApi(azureGroup).getKeys(image.storage());
if (keys == null) {
// If the storage account for the image does not exist, it means the image was deleted
return null;
}
BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1());
try {
if (blobHelper.customImageExists()) {
List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, azureGroup,
CUSTOM_IMAGE_OFFER, image.location());
customImage = find(customImagesInStorage, new Predicate<VMImage>() {
@Override
public boolean apply(VMImage input) {
return id.equals(encodeFieldsToUniqueIdCustom(input));
}
}, null);
}
} finally {
closeQuietly(blobHelper);
}
return customImage;
}
String location = image.location();
@ -273,7 +261,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
OSImageApi osImageApi = api.getOSImageApi(location);
List<Version> versions = osImageApi.listVersions(publisher, offer, sku);
if (!versions.isEmpty()) {
return VMImage.create(publisher, offer, sku, versions.get(0).name(), location);
return VMImage.azureImage().publisher(publisher).offer(offer).sku(sku).version(versions.get(0).name())
.location(location).build();
}
return null;
}
@ -313,13 +302,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
}
@Override
public VMDeployment getNode(final String id) {
Deployment deployment = api.getDeploymentApi(azureGroup).get(id);
if (deployment == null) return null;
if (isDeploymentInRegions.apply(deployment)) {
return deploymentToVMDeployment.apply(deployment);
}
return null;
public VirtualMachine getNode(final String id) {
return api.getVirtualMachineApi(azureGroup).get(id);
}
@Override
@ -343,29 +327,99 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
}
@Override
public Iterable<VMDeployment> listNodes() {
return FluentIterable.from(api.getDeploymentApi(azureGroup).list())
.filter(isDeploymentInRegions)
.filter(new Predicate<Deployment>() {
@Override
public boolean apply(Deployment deployment) {
Value storageAccountNameValue = deployment.properties().parameters().get("storageAccountName");
String storageAccountName = storageAccountNameValue.value();
String key = api.getStorageAccountApi(azureGroup).getKeys(storageAccountName).key1();
return !BlobHelper.customImageExists(storageAccountName, key);
}
})
.transform(deploymentToVMDeployment)
.toList();
public Iterable<VirtualMachine> listNodes() {
return api.getVirtualMachineApi(azureGroup).list();
}
@Override
public Iterable<VMDeployment> listNodesByIds(final Iterable<String> ids) {
return Iterables.filter(listNodes(), new Predicate<VMDeployment>() {
public Iterable<VirtualMachine> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<VirtualMachine>() {
@Override
public boolean apply(final VMDeployment input) {
return Iterables.contains(ids, input.deployment().name());
public boolean apply(VirtualMachine virtualMachine) {
return contains(ids, virtualMachine.id());
}
});
}
private OSProfile createOsProfile(String computerName, Template template) {
String defaultLoginUser = template.getImage().getDefaultCredentials().getUser();
String defaultLoginPassword = template.getImage().getDefaultCredentials().getOptionalPassword().get();
String adminUsername = Objects.firstNonNull(template.getOptions().getLoginUser(), defaultLoginUser);
String adminPassword = Objects.firstNonNull(template.getOptions().getLoginPassword(), defaultLoginPassword);
OSProfile.Builder builder = OSProfile.builder().adminUsername(adminUsername).computerName(computerName);
// prefer public key over password
if (template.getOptions().getPublicKey() != null) {
OSProfile.LinuxConfiguration linuxConfiguration = OSProfile.LinuxConfiguration.create("true",
OSProfile.LinuxConfiguration.SSH.create(ImmutableList.of(
OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create(
String.format("/home/%s/.ssh/authorized_keys", adminUsername),
template.getOptions().getPublicKey())
))
);
builder.linuxConfiguration(linuxConfiguration);
} else {
builder.adminPassword(adminPassword);
}
return builder.build();
}
private NetworkInterfaceCard createNetworkInterfaceCard(String subnetId, String name, String locationName) {
final PublicIPAddressApi ipApi = api.getPublicIPAddressApi(azureGroup);
PublicIPAddressProperties properties =
PublicIPAddressProperties.builder()
.publicIPAllocationMethod("Static")
.idleTimeoutInMinutes(4)
.build();
String publicIpAddressName = "public-address-" + name;
PublicIPAddress ip = ipApi.createOrUpdate(publicIpAddressName, locationName, ImmutableMap.of("jclouds", name), properties);
checkState(publicIpAvailable.apply(publicIpAddressName),
"Public IP was not provisioned in the configured timeout");
final NetworkInterfaceCardProperties networkInterfaceCardProperties =
NetworkInterfaceCardProperties.builder()
.ipConfigurations(ImmutableList.of(
IpConfiguration.builder()
.name("ipConfig-" + name)
.properties(IpConfigurationProperties.builder()
.privateIPAllocationMethod("Dynamic")
.publicIPAddress(IdReference.create(ip.id()))
.subnet(IdReference.create(subnetId))
.build())
.build()))
.build();
String networkInterfaceCardName = "jc-nic-" + name;
return api.getNetworkInterfaceCardApi(azureGroup).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, ImmutableMap.of("jclouds", name));
}
private StorageProfile createStorageProfile(String name, Image image, String blob) {
VMImage imageRef = decodeFieldsFromUniqueId(image.getId());
ImageReference imageReference = null;
VHD sourceImage = null;
String osType = null;
if (!imageRef.custom()) {
imageReference = ImageReference.builder()
.publisher(image.getProviderId())
.offer(image.getName())
.sku(image.getVersion())
.version("latest")
.build();
} else {
sourceImage = VHD.create(image.getProviderId());
// TODO: read the ostype from the image blob
OsFamily osFamily = image.getOperatingSystem().getFamily();
osType = osFamily == OsFamily.WINDOWS ? "Windows" : "Linux";
}
VHD vhd = VHD.create(blob + "vhds/" + name + ".vhd");
OSDisk osDisk = OSDisk.create(osType, name, vhd, "ReadWrite", "FromImage", sourceImage);
return StorageProfile.create(imageReference, osDisk, ImmutableList.<DataDisk>of());
}
}

View File

@ -16,55 +16,8 @@
*/
package org.jclouds.azurecompute.arm.compute.config;
import java.net.URI;
import java.util.List;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.AzureComputeService;
import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter;
import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
import org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata;
import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation;
import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware;
import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.compute.strategy.AzurePopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes;
import org.jclouds.azurecompute.arm.domain.Location;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.domain.VMDeployment;
import org.jclouds.azurecompute.arm.domain.VMHardware;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
@ -76,38 +29,87 @@ import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RUL
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.util.Predicates2.retry;
public class AzureComputeServiceContextModule
extends ComputeServiceAdapterContextModule<VMDeployment, VMHardware, VMImage, Location> {
import java.net.URI;
import java.util.List;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.AzureComputeService;
import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter;
import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation;
import org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage;
import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware;
import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes;
import org.jclouds.azurecompute.arm.domain.Location;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.domain.VMHardware;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement;
import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatementWithoutPublicKey;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryModuleBuilder;
public class AzureComputeServiceContextModule
extends ComputeServiceAdapterContextModule<VirtualMachine, VMHardware, VMImage, Location> {
@Override
protected void configure() {
super.configure();
bind(new TypeLiteral<ComputeServiceAdapter<VMDeployment, VMHardware, VMImage, Location>>() {
bind(new TypeLiteral<ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location>>() {
}).to(AzureComputeServiceAdapter.class);
bind(new TypeLiteral<Function<VMImage, org.jclouds.compute.domain.Image>>() {
}).to(VMImageToImage.class);
bind(new TypeLiteral<Function<VMHardware, Hardware>>() {
}).to(VMHardwareToHardware.class);
bind(new TypeLiteral<Function<VMDeployment, NodeMetadata>>() {
}).to(DeploymentToNodeMetadata.class);
bind(new TypeLiteral<Function<VirtualMachine, NodeMetadata>>() {
}).to(VirtualMachineToNodeMetadata.class);
bind(new TypeLiteral<Function<Location, org.jclouds.domain.Location>>() {
}).to(LocationToLocation.class);
bind(ComputeService.class).to(AzureComputeService.class);
install(new LocationsFromComputeServiceAdapterModule<VMDeployment, VMHardware, VMImage, Location>() {
install(new LocationsFromComputeServiceAdapterModule<VirtualMachine, VMHardware, VMImage, Location>() {
});
install(new FactoryModuleBuilder().build(ResourceDefinitionToCustomImage.Factory.class));
bind(TemplateOptions.class).to(AzureTemplateOptions.class);
bind(PopulateDefaultLoginCredentialsForImageStrategy.class).to(AzurePopulateDefaultLoginCredentialsForImageStrategy.class);
//bind(TemplateOptionsToStatement.class).to(TemplateOptionsToStatementWithoutPublicKey.class);
bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class);
bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class);
bind(new TypeLiteral<ImageExtension>() {
}).to(AzureComputeImageExtension.class);
}
@ -143,10 +145,6 @@ public class AzureComputeServiceContextModule
@Inject
private String azureImagePublishersProperty;
@Named(DEFAULT_IMAGE_LOGIN)
@Inject
private String azureDefaultImageLoginProperty;
@Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX)
@Inject
private String azureDefaultVnetAddressPrefixProperty;
@ -171,10 +169,6 @@ public class AzureComputeServiceContextModule
return azureImagePublishersProperty;
}
public String azureDefaultImageLogin() {
return azureDefaultImageLoginProperty;
}
public String azureDefaultVnetAddressPrefixProperty() {
return azureDefaultVnetAddressPrefixProperty;
}
@ -204,6 +198,14 @@ public class AzureComputeServiceContextModule
}
}
@Provides
@com.google.inject.name.Named(TIMEOUT_NODE_RUNNING)
protected Predicate<String> provideVirtualMachineRunningPredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, Timeouts timeouts, PollPeriod pollPeriod) {
String azureGroup = azureComputeConstants.azureResourceGroup();
return retry(new VirtualMachineInStatePredicate(api, azureGroup, PowerState.RUNNING), timeouts.nodeRunning,
pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
}
@Provides
@Named(TIMEOUT_NODE_TERMINATED)
protected Predicate<URI> provideNodeTerminatedPredicate(final AzureComputeApi api, Timeouts timeouts, PollPeriod pollPeriod) {
@ -230,7 +232,17 @@ public class AzureComputeServiceContextModule
protected Predicate<String> provideNodeSuspendedPredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
Timeouts timeouts, PollPeriod pollPeriod) {
String azureGroup = azureComputeConstants.azureResourceGroup();
return retry(new NodeSuspendedPredicate(api, azureGroup), timeouts.nodeSuspended, pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
return retry(new VirtualMachineInStatePredicate(api, azureGroup, PowerState.STOPPED), timeouts.nodeTerminated,
pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
}
@Provides
@Named("PublicIpAvailable")
protected Predicate<String> providePublicIpAvailablePredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
Timeouts timeouts, PollPeriod pollPeriod) {
String azureGroup = azureComputeConstants.azureResourceGroup();
return retry(new PublicIpAvailablePredicate(api, azureGroup), azureComputeConstants.operationTimeout(),
azureComputeConstants.operationPollInitialPeriod(), azureComputeConstants.operationPollMaxPeriod());
}
@VisibleForTesting
@ -269,12 +281,34 @@ public class AzureComputeServiceContextModule
}
@VisibleForTesting
static class NodeSuspendedPredicate implements Predicate<String> {
static class VirtualMachineInStatePredicate implements Predicate<String> {
private final AzureComputeApi api;
private final String azureGroup;
private final PowerState powerState;
public VirtualMachineInStatePredicate(AzureComputeApi api, String azureGroup, PowerState powerState) {
this.api = checkNotNull(api, "api must not be null");
this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be null");
this.powerState = checkNotNull(powerState, "powerState must not be null");
}
@Override
public boolean apply(String name) {
checkNotNull(name, "name cannot be null");
VirtualMachineInstance vmInstance = api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name);
if (vmInstance == null) return false;
return powerState == vmInstance.powerState();
}
}
@VisibleForTesting
static class PublicIpAvailablePredicate implements Predicate<String> {
private final AzureComputeApi api;
private final String azureGroup;
public NodeSuspendedPredicate(AzureComputeApi api, String azureGroup) {
public PublicIpAvailablePredicate(AzureComputeApi api, String azureGroup) {
this.api = checkNotNull(api, "api must not be null");
this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be null");
}
@ -282,17 +316,10 @@ public class AzureComputeServiceContextModule
@Override
public boolean apply(String name) {
checkNotNull(name, "name cannot be null");
String status = "";
VirtualMachineInstance virtualMachineInstance = api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name);
if (virtualMachineInstance == null) return false;
List<VirtualMachineInstance.VirtualMachineStatus> statuses = virtualMachineInstance.statuses();
for (int c = 0; c < statuses.size(); c++) {
if (statuses.get(c).code().substring(0, 10).equals("PowerState")) {
status = statuses.get(c).displayStatus();
break;
}
}
return status.equals("VM stopped");
PublicIPAddress publicIp = api.getPublicIPAddressApi(azureGroup).get(name);
if (publicIp == null) return false;
return publicIp.properties().provisioningState().equalsIgnoreCase("Succeeded");
}
}
}

View File

@ -16,141 +16,137 @@
*/
package org.jclouds.azurecompute.arm.compute.extensions;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.UncheckedTimeoutException;
import com.google.gson.internal.LinkedTreeMap;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import static org.jclouds.util.Closeables2.closeQuietly;
import java.net.URI;
import java.util.List;
import java.util.concurrent.Callable;
import javax.annotation.Resource;
import org.jclouds.Constants;
import org.jclouds.View;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
import org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import static java.lang.String.format;
import org.jclouds.azurecompute.arm.functions.CleanupResources;
import org.jclouds.azurecompute.arm.util.BlobHelper;
import org.jclouds.compute.domain.CloneImageTemplate;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageTemplate;
import org.jclouds.compute.domain.ImageTemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
import com.google.inject.name.Named;
public class AzureComputeImageExtension implements ImageExtension {
public static final String CONTAINER_NAME = "jclouds";
public static final String CUSTOM_IMAGE_OFFER = "custom";
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final AzureComputeApi api;
private final ListeningExecutorService userExecutor;
private final Supplier<View> blobstore = null;
private final String group;
private final ListeningExecutorService userExecutor;
private final Predicate<URI> imageAvailablePredicate;
private final Predicate<String> nodeSuspendedPredicate;
private final AzureComputeConstants azureComputeConstants;
private final VMImageToImage imageReferenceToImage;
public static final String CONTAINER_NAME = "jclouds";
public static final String CUSTOM_IMAGE_PREFIX = "#";
private final ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage;
private final CleanupResources cleanupResources;
@Inject
AzureComputeImageExtension(AzureComputeApi api,
@Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> imageAvailablePredicate,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> nodeSuspendedPredicate,
final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
VMImageToImage imageReferenceToImage) {
this.userExecutor = userExecutor;
this.group = azureComputeConstants.azureResourceGroup();
this.imageReferenceToImage = imageReferenceToImage;
@Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> imageAvailablePredicate,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> nodeSuspendedPredicate,
AzureComputeConstants azureComputeConstants,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage, CleanupResources cleanupResources) {
this.api = api;
this.imageAvailablePredicate = imageAvailablePredicate;
this.nodeSuspendedPredicate = nodeSuspendedPredicate;
this.azureComputeConstants = azureComputeConstants;
this.api = api;
this.group = azureComputeConstants.azureResourceGroup();
this.userExecutor = userExecutor;
this.resourceDefinitionToImage = resourceDefinitionToImage;
this.cleanupResources = cleanupResources;
}
@Override
public ImageTemplate buildImageTemplateFromNode(String name, String id) {
String nameLowerCase = name.toLowerCase();
return new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(nameLowerCase).build();
return new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(name.toLowerCase()).build();
}
@Override
public ListenableFuture<Image> createImage(ImageTemplate template) {
final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
final String id = cloneTemplate.getSourceNodeId();
final String name = cloneTemplate.getName();
final String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + "stor";
logger.debug(">> stopping node %s...", id);
api.getVirtualMachineApi(group).stop(id);
if (nodeSuspendedPredicate.apply(id)) {
return userExecutor.submit(new Callable<Image>() {
@Override
public Image call() throws Exception {
api.getVirtualMachineApi(group).generalize(id);
checkState(nodeSuspendedPredicate.apply(id), "Node %s was not suspended within the configured time limit", id);
final String[] disks = new String[2];
URI uri = api.getVirtualMachineApi(group).capture(id, cloneTemplate.getName(), CONTAINER_NAME);
if (uri != null) {
if (imageAvailablePredicate.apply(uri)) {
List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
if (definitions != null) {
for (ResourceDefinition definition : definitions) {
LinkedTreeMap<String, String> properties = (LinkedTreeMap<String, String>) definition.properties();
Object storageObject = properties.get("storageProfile");
LinkedTreeMap<String, String> properties2 = (LinkedTreeMap<String, String>) storageObject;
Object osDiskObject = properties2.get("osDisk");
LinkedTreeMap<String, String> osProperties = (LinkedTreeMap<String, String>) osDiskObject;
Object dataDisksObject = properties2.get("dataDisks");
ArrayList<Object> dataProperties = (ArrayList<Object>) dataDisksObject;
LinkedTreeMap<String, String> datadiskObject = (LinkedTreeMap<String, String>) dataProperties.get(0);
return userExecutor.submit(new Callable<Image>() {
@Override
public Image call() throws Exception {
logger.debug(">> generalizing virtal machine %s...", id);
api.getVirtualMachineApi(group).generalize(id);
disks[0] = osProperties.get("name");
disks[1] = datadiskObject.get("name");
logger.debug(">> capturing virtual machine %s to container %s...", id, CONTAINER_NAME);
URI uri = api.getVirtualMachineApi(group).capture(id, cloneTemplate.getName(), CONTAINER_NAME);
checkState(uri != null && imageAvailablePredicate.apply(uri),
"Image %s was not created within the configured time limit", cloneTemplate.getName());
VirtualMachine vm = api.getVirtualMachineApi(group).get(id);
final VMImage ref = VMImage.create(group, storageAccountName, disks[0], disks[1], name, "custom", vm.location());
return imageReferenceToImage.apply(ref);
}
}
}
}
throw new UncheckedTimeoutException("Image was not created within the time limit: "
+ cloneTemplate.getName());
}
});
} else {
final String illegalStateExceptionMessage = format("Node %s was not suspended within %sms.",
id, azureComputeConstants.operationTimeout());
throw new IllegalStateException(illegalStateExceptionMessage);
}
List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
checkState(definitions.size() == 1,
"Expected one resource definition after creating the image but %s were returned", definitions.size());
Image image = resourceDefinitionToImage.create(id, name).apply(definitions.get(0));
logger.debug(">> created %s", image);
return image;
}
});
}
@Override
public boolean deleteImage(String id) {
VMImage image = decodeFieldsFromUniqueId(id);
checkArgument(image.custom(), "Only custom images can be deleted");
VMImage image = VMImageToImage.decodeFieldsFromUniqueId(id);
if (image.custom()) {
StorageServiceKeys keys = api.getStorageAccountApi(image.group()).getKeys(image.storage());
logger.debug(">> deleting image %s", id);
// This removes now all the images in this storage. At least in theory, there should be just one and if there is
StorageServiceKeys keys = api.getStorageAccountApi(image.group()).getKeys(image.storage());
BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1());
try {
// This removes now all the images in this storage. At least in theory,
// there should be just one and if there is
// more, they should be copies of each other.
BlobHelper.deleteContainerIfExists(image.storage(), keys.key1(), "system");
return !BlobHelper.customImageExists(image.storage(), keys.key1());
}
blobHelper.deleteContainerIfExists("system");
boolean result = !blobHelper.customImageExists();
return false;
if (!blobHelper.hasContainers()) {
logger.debug(">> storage account is empty after deleting the custom image. Deleting the storage account...");
api.getStorageAccountApi(image.group()).delete(image.storage());
cleanupResources.deleteResourceGroupIfEmpty(image.group());
}
return result;
} finally {
closeQuietly(blobHelper);
}
}
}

View File

@ -1,244 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.compute.functions;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import com.google.common.collect.Sets;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.domain.ComputeNode;
import org.jclouds.azurecompute.arm.domain.Deployment;
import org.jclouds.azurecompute.arm.domain.ImageReference;
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.VMDeployment;
import org.jclouds.azurecompute.arm.domain.VMHardware;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VMSize;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.azurecompute.arm.util.GetEnumValue;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Hardware;
public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMetadata> {
public static final String JCLOUDS_DEFAULT_USERNAME = "root";
public static final String AZURE_LOGIN_USERNAME = DeploymentTemplateBuilder.getLoginUserUsername();
public static final String AZURE_LOGIN_PASSWORD = DeploymentTemplateBuilder.getLoginPassword();
private static final Map<ComputeNode.Status, NodeMetadata.Status> INSTANCESTATUS_TO_NODESTATUS =
ImmutableMap.<ComputeNode.Status, NodeMetadata.Status>builder().
put(ComputeNode.Status.GOOD, NodeMetadata.Status.RUNNING).
put(ComputeNode.Status.BAD, NodeMetadata.Status.ERROR).
put(ComputeNode.Status.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).
build();
// When using the Deployment API to deploy an ARM template, the deployment goes through
// stages. Accepted -> Running -> Succeeded. Only when the deployment has SUCCEEDED is
// the resource deployed using the template actually ready.
//
// To get details about the resource(s) deployed via template, one needs to query the
// various resources after the deployment has "SUCCEEDED".
private static final Map<Deployment.ProvisioningState, NodeMetadata.Status> STATUS_TO_NODESTATUS =
ImmutableMap.<Deployment.ProvisioningState, NodeMetadata.Status>builder().
put(Deployment.ProvisioningState.ACCEPTED, NodeMetadata.Status.PENDING).
put(Deployment.ProvisioningState.READY, NodeMetadata.Status.PENDING).
put(Deployment.ProvisioningState.RUNNING, NodeMetadata.Status.PENDING).
put(Deployment.ProvisioningState.CANCELED, NodeMetadata.Status.TERMINATED).
put(Deployment.ProvisioningState.FAILED, NodeMetadata.Status.ERROR).
put(Deployment.ProvisioningState.DELETED, NodeMetadata.Status.TERMINATED).
put(Deployment.ProvisioningState.SUCCEEDED, NodeMetadata.Status.RUNNING).
put(Deployment.ProvisioningState.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).
build();
public static Deployment.ProvisioningState provisioningStateFromString(final String text) {
return (Deployment.ProvisioningState) GetEnumValue.fromValueOrDefault(text, Deployment.ProvisioningState.UNRECOGNIZED);
}
private final AzureComputeApi api;
private final LocationToLocation locationToLocation;
private final GroupNamingConvention nodeNamingConvention;
private final VMImageToImage vmImageToImage;
private final VMHardwareToHardware vmHardwareToHardware;
private final Map<String, Credentials> credentialStore;
@Inject
DeploymentToNodeMetadata(
AzureComputeApi api,
LocationToLocation locationToLocation,
GroupNamingConvention.Factory namingConvention, VMImageToImage vmImageToImage,
VMHardwareToHardware vmHardwareToHardware, Map<String, Credentials> credentialStore) {
this.nodeNamingConvention = namingConvention.createWithoutPrefix();
this.locationToLocation = locationToLocation;
this.vmImageToImage = vmImageToImage;
this.vmHardwareToHardware = vmHardwareToHardware;
this.credentialStore = credentialStore;
this.api = api;
}
@Override
public NodeMetadata apply(final VMDeployment from) {
final NodeMetadataBuilder builder = new NodeMetadataBuilder();
final Deployment deployment = from.deployment();
builder.id(deployment.name());
builder.providerId(deployment.name());
builder.name(deployment.name());
String group = this.nodeNamingConvention.extractGroup(deployment.name());
builder.group(group);
if (from.tags() != null)
builder.tags(from.tags());
if (from.userMetaData() != null)
builder.userMetadata(from.userMetaData());
NodeMetadata.Status status = STATUS_TO_NODESTATUS.get(provisioningStateFromString(deployment.properties().provisioningState()));
if (status == NodeMetadata.Status.RUNNING && from.vm() != null && from.vm().statuses() != null) {
List<VirtualMachineInstance.VirtualMachineStatus> statuses = from.vm().statuses();
for (int c = 0; c < statuses.size(); c++) {
if (statuses.get(c).code().substring(0, 10).equals("PowerState")) {
if (statuses.get(c).displayStatus().equals("VM running")) {
status = NodeMetadata.Status.RUNNING;
} else if (statuses.get(c).displayStatus().equals("VM stopped")) {
status = NodeMetadata.Status.SUSPENDED;
}
break;
}
}
}
builder.status(status);
if (from.vm() != null) {
builder.hostname(deployment.name() + "pc");
}
Credentials credentials = credentialStore.get("node#" + from.deployment().name());
if (credentials != null && credentials.identity.equals(JCLOUDS_DEFAULT_USERNAME)) {
credentials = new Credentials(AZURE_LOGIN_USERNAME, credentials.credential);
}
else if (credentials == null) {
String username = AZURE_LOGIN_USERNAME;
String password = AZURE_LOGIN_PASSWORD;
if (username == null) {
username = "jclouds";
}
if (password == null) {
password = "Password1!";
}
credentials = new Credentials(username, password);
}
builder.credentials(LoginCredentials.fromCredentials(credentials));
final Set<String> publicIpAddresses = Sets.newLinkedHashSet();
if (from.ipAddressList() != null) {
for (int c = 0; c < from.ipAddressList().size(); c++) {
PublicIPAddress ip = from.ipAddressList().get(c);
if (ip != null && ip.properties() != null && ip.properties().ipAddress() != null)
{
publicIpAddresses.add(ip.properties().ipAddress());
break;
}
}
if (publicIpAddresses.size() > 0)
builder.publicAddresses(publicIpAddresses);
}
final Set<String> privateIpAddresses = Sets.newLinkedHashSet();
if (from.networkInterfaceCards() != null) {
for (NetworkInterfaceCard nic : from.networkInterfaceCards()) {
if (nic != null && nic.properties() != null && nic.properties().ipConfigurations() != null) {
for (IpConfiguration ip : nic.properties().ipConfigurations()) {
if (ip != null && ip.properties() != null && ip.properties().privateIPAddress() != null) {
privateIpAddresses.add(ip.properties().privateIPAddress());
}
}
}
}
if (!privateIpAddresses.isEmpty()) {
builder.privateAddresses(privateIpAddresses);
}
}
org.jclouds.azurecompute.arm.domain.Location myLocation = null;
if (from.virtualMachine() != null) {
String locationName = from.virtualMachine().location();
List<org.jclouds.azurecompute.arm.domain.Location> locations = api.getLocationApi().list();
for (org.jclouds.azurecompute.arm.domain.Location location : locations) {
if (location.name().equals(locationName)) {
myLocation = location;
break;
}
}
Location jLocation = this.locationToLocation.apply(myLocation);
builder.location(jLocation);
ImageReference imageReference = from.virtualMachine().properties().storageProfile().imageReference();
if (imageReference != null) {
VMImage vmImage = VMImage.create(imageReference.publisher(), imageReference.offer(), imageReference.sku(),
imageReference.version(), locationName);
Image image = vmImageToImage.apply(vmImage);
builder.imageId(image.getId());
}
VMSize myVMSize = null;
String vmSizeName = from.virtualMachine().properties().hardwareProfile().vmSize();
List<VMSize> vmSizes = api.getVMSizeApi(locationName).list();
for (VMSize vmSize : vmSizes) {
if (vmSize.name().equals(vmSizeName)) {
myVMSize = vmSize;
break;
}
}
VMHardware hwProfile = VMHardware.create(
myVMSize.name(),
myVMSize.numberOfCores(),
myVMSize.osDiskSizeInMB(),
myVMSize.resourceDiskSizeInMB(),
myVMSize.memoryInMB(),
myVMSize.maxDataDiskCount(),
locationName,
false);
Hardware hardware = vmHardwareToHardware.apply(hwProfile);
builder.hardware(hardware);
}
return builder.build();
}
}

View File

@ -1,121 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.compute.functions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
import org.jclouds.azurecompute.arm.domain.Deployment;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.VMDeployment;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import com.google.common.base.Function;
/**
* Converts an Deployment into a VMDeployment.
*/
@Singleton
public class DeploymentToVMDeployment implements Function<Deployment, VMDeployment> {
private final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
private final AzureComputeApi api;
@Inject
DeploymentToVMDeployment(AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants) {
this.api = api;
this.azureComputeConstants = azureComputeConstants;
}
@Override
public VMDeployment apply(final Deployment deployment) {
String id = deployment.id();
List<PublicIPAddress> ipAddressList = getIPAddresses(deployment);
List<NetworkInterfaceCard> networkInterfaceCards = getNetworkInterfaceCards(deployment);
VirtualMachine vm = api.getVirtualMachineApi(azureComputeConstants.azureResourceGroup()).get(id);
VirtualMachineInstance vmInstanceDetails = api.getVirtualMachineApi(azureComputeConstants.azureResourceGroup()).getInstanceDetails(id);
Map<String, String> userMetaData = null;
Iterable<String> tags = null;
if (vm != null && vm.tags() != null) {
userMetaData = vm.tags();
String tagString = userMetaData.get("tags");
tags = Arrays.asList(tagString.split(","));
}
return VMDeployment.create(deployment, ipAddressList, vmInstanceDetails, vm, networkInterfaceCards, userMetaData, tags);
}
private List<PublicIPAddress> getIPAddresses(Deployment deployment) {
List<PublicIPAddress> list = new ArrayList<PublicIPAddress>();
String resourceGroup = getResourceGroupFromId(deployment.id());
if (deployment.properties() != null && deployment.properties().dependencies() != null) {
List<Deployment.Dependency> dependencies = deployment.properties().dependencies();
for (int d = 0; d < dependencies.size(); d++) {
if (dependencies.get(d).resourceType().equals("Microsoft.Network/networkInterfaces")) {
List<Deployment.Dependency> dependsOn = dependencies.get(d).dependsOn();
for (int e = 0; e < dependsOn.size(); e++) {
if (dependsOn.get(e).resourceType().equals("Microsoft.Network/publicIPAddresses")) {
String resourceName = dependsOn.get(e).resourceName();
PublicIPAddress ip = api.getPublicIPAddressApi(resourceGroup).get(resourceName);
list.add(ip);
break;
}
}
}
}
}
return list;
}
private String getResourceGroupFromId(String id) {
String searchStr = "/resourceGroups/";
int indexStart = id.lastIndexOf(searchStr) + searchStr.length();
searchStr = "/providers/";
int indexEnd = id.lastIndexOf(searchStr);
String resourceGroup = id.substring(indexStart, indexEnd);
return resourceGroup;
}
private List<NetworkInterfaceCard> getNetworkInterfaceCards(Deployment deployment) {
List<NetworkInterfaceCard> result = new ArrayList<NetworkInterfaceCard>();
String resourceGroup = getResourceGroupFromId(deployment.id());
if (deployment.properties() != null && deployment.properties().dependencies() != null) {
for (Deployment.Dependency dependency : deployment.properties().dependencies()) {
if (dependency.resourceType().equals("Microsoft.Network/networkInterfaces")) {
String resourceName = dependency.resourceName();
NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(resourceGroup).get(resourceName);
result.add(nic);
}
}
}
return result;
}
}

View File

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

View File

@ -16,58 +16,50 @@
*/
package org.jclouds.azurecompute.arm.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_PASSWORD;
import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_USERNAME;
import java.util.Set;
import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import org.jclouds.azurecompute.arm.domain.ImageReference;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import com.google.common.base.Function;
import com.google.inject.Inject;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.location.predicates.LocationPredicates;
import java.util.Set;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.inject.Inject;
import static com.google.common.base.Preconditions.checkNotNull;
public class VMImageToImage implements Function<VMImage, Image> {
private static final String UNRECOGNIZED = "UNRECOGNIZED";
private static final String UBUNTU = "Ubuntu";
private static final String WINDOWS = "Windows";
private static final String OPENLOGIC = "openLogic";
private static final String CENTOS = "CentOS";
private static final String COREOS = "CoreOS";
private static final String OPENSUSE = "openSUSE";
private static final String SUSE = "SUSE";
private static final String SQL_SERVER = "SQL Server";
private static final String ORACLE_lINUX = "Oracle Linux";
private static final String SLES = "SLES";
private static final String ORACLE_lINUX = "Oracle-Linux";
private static final String RHEL = "RHEL";
private final Supplier<Set<? extends org.jclouds.domain.Location>> locations;
public static String encodeFieldsToUniqueId(boolean globallyAvailable, String locatioName, ImageReference imageReference){
return (globallyAvailable ? "global" : locatioName) + "/" + imageReference.publisher() + "/" + imageReference.offer() + "/" + imageReference.sku();
}
public static String encodeFieldsToUniqueId(VMImage imageReference){
return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.publisher() + "/" + imageReference.offer() + "/" + imageReference.sku();
}
public static String encodeFieldsToUniqueIdCustom(VMImage imageReference){
return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.group() + "/" + imageReference.storage() + "/" + imageReference.vhd1() + "/" + imageReference.offer();
return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.group() + "/" + imageReference.storage() + "/" + imageReference.offer() + "/" + imageReference.name();
}
public static VMImage decodeFieldsFromUniqueId(final String id) {
@ -79,10 +71,10 @@ public class VMImageToImage implements Function<VMImage, Image> {
0: imageReference.location) + "/" +
1: imageReference.group + "/" +
2: imageReference.storage + "/" +
3: imageReference.vhd1 + "/" +
4: imageReference.offer
3: imageReference.offer + "/" +
4: imageReference.name
*/
vmImage = VMImage.create(fields[1], fields[2], fields[3], null, null, fields[4], fields[0]);
vmImage = VMImage.customImage().location(fields[0]).group(fields[1]).storage(fields[2]).vhd1(fields[3]).offer(fields[4]).build();
} else {
/* id fields indexes
0: imageReference.location) + "/" +
@ -90,7 +82,7 @@ public class VMImageToImage implements Function<VMImage, Image> {
2: imageReference.offer + "/" +
3: imageReference.sku + "/" +
*/
vmImage = VMImage.create(fields[1], fields[2], fields[3], null, fields[0]);
vmImage = VMImage.azureImage().location(fields[0]).publisher(fields[1]).offer(fields[2]).sku(fields[3]).build();
}
return vmImage;
}
@ -102,26 +94,21 @@ public class VMImageToImage implements Function<VMImage, Image> {
@Override
public Image apply(final VMImage image) {
Credentials credentials = new Credentials(AZURE_LOGIN_USERNAME, AZURE_LOGIN_PASSWORD);
if (image.custom()) {
final ImageBuilder builder = new ImageBuilder()
.location(FluentIterable.from(locations.get())
.firstMatch(LocationPredicates.idEquals(image.location()))
.get())
.name(image.name())
.description("#" + image.group())
.description(image.group())
.status(Image.Status.AVAILABLE)
.version(image.storage())
.version("latest")
.providerId(image.vhd1())
.id(encodeFieldsToUniqueIdCustom(image))
.defaultCredentials(LoginCredentials.fromCredentials(credentials));
.id(encodeFieldsToUniqueIdCustom(image));
final OperatingSystem.Builder osBuilder = osFamily().apply(image);
Image retimage = builder.operatingSystem(osBuilder.build()).build();
return retimage;
}
else {
final ImageBuilder builder = new ImageBuilder()
@ -130,7 +117,6 @@ public class VMImageToImage implements Function<VMImage, Image> {
.status(Image.Status.AVAILABLE)
.version(image.sku())
.id(encodeFieldsToUniqueId(image))
.defaultCredentials(LoginCredentials.fromCredentials(credentials))
.providerId(image.publisher())
.location(image.globallyAvailable() ? null : FluentIterable.from(locations.get())
.firstMatch(LocationPredicates.idEquals(image.location()))
@ -149,11 +135,11 @@ public class VMImageToImage implements Function<VMImage, Image> {
final String label = image.offer();
OsFamily family = OsFamily.UNRECOGNIZED;
if (label.contains(CENTOS)) {
if (label.contains(CENTOS) || label.contains(OPENLOGIC)) {
family = OsFamily.CENTOS;
} else if (label.contains(OPENLOGIC)) {
family = OsFamily.CENTOS;
} else if (label.contains(SUSE)) {
} else if (label.contains(COREOS)) {
family = OsFamily.COREOS;
} else if (label.contains(SUSE) || label.contains(SLES) || label.contains(OPENSUSE)) {
family = OsFamily.SUSE;
} else if (label.contains(UBUNTU)) {
family = OsFamily.UBUNTU;
@ -161,18 +147,16 @@ public class VMImageToImage implements Function<VMImage, Image> {
family = OsFamily.WINDOWS;
} else if (label.contains(ORACLE_lINUX)) {
family = OsFamily.OEL;
} else if (label.contains(RHEL)) {
family = OsFamily.RHEL;
}
String sku = image.sku();
if (image.custom())
sku = image.vhd1();
// only 64bit OS images are supported by Azure ARM
return OperatingSystem.builder().
family(family).
is64Bit(true).
description(sku).
version(sku);
description(image.custom() ? image.vhd1() : image.sku()).
version(image.custom() ? "latest" : image.sku());
}
};
}

View File

@ -0,0 +1,279 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Iterables.tryFind;
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
import static org.jclouds.util.Closeables2.closeQuietly;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
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.StorageProfile;
import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties.ProvisioningState;
import org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName;
import org.jclouds.azurecompute.arm.util.BlobHelper;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
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.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
// When using the Deployment API to deploy an ARM template, the deployment
// goes through
// stages. Accepted -> Running -> Succeeded. Only when the deployment has
// SUCCEEDED is
// the resource deployed using the template actually ready.
//
// To get details about the resource(s) deployed via template, one needs to
// query the
// various resources after the deployment has "SUCCEEDED".
private static final Function<VirtualMachineProperties.ProvisioningState, NodeMetadata.Status> PROVISIONINGSTATE_TO_NODESTATUS = Functions
.forMap(
ImmutableMap.<VirtualMachineProperties.ProvisioningState, NodeMetadata.Status> builder()
.put(VirtualMachineProperties.ProvisioningState.ACCEPTED, NodeMetadata.Status.PENDING)
.put(VirtualMachineProperties.ProvisioningState.READY, NodeMetadata.Status.PENDING)
.put(VirtualMachineProperties.ProvisioningState.CREATING, NodeMetadata.Status.PENDING)
.put(VirtualMachineProperties.ProvisioningState.RUNNING, NodeMetadata.Status.PENDING)
.put(VirtualMachineProperties.ProvisioningState.UPDATING, NodeMetadata.Status.PENDING)
.put(VirtualMachineProperties.ProvisioningState.SUCCEEDED, NodeMetadata.Status.RUNNING)
.put(VirtualMachineProperties.ProvisioningState.DELETED, NodeMetadata.Status.TERMINATED)
.put(VirtualMachineProperties.ProvisioningState.CANCELED, NodeMetadata.Status.TERMINATED)
.put(VirtualMachineProperties.ProvisioningState.FAILED, NodeMetadata.Status.ERROR)
.put(VirtualMachineProperties.ProvisioningState.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED)
.build(), NodeMetadata.Status.UNRECOGNIZED);
private static final Function<VirtualMachineStatus.PowerState, NodeMetadata.Status> POWERSTATE_TO_NODESTATUS = Functions
.forMap(
ImmutableMap.<PowerState, NodeMetadata.Status> builder()
.put(PowerState.RUNNING, NodeMetadata.Status.RUNNING)
.put(PowerState.STOPPED, NodeMetadata.Status.SUSPENDED)
.put(PowerState.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).build(),
NodeMetadata.Status.UNRECOGNIZED);
private final String azureGroup;
private final AzureComputeApi api;
private final GroupNamingConvention nodeNamingConvention;
private final Supplier<Map<String, ? extends Image>> images;
private final Supplier<Set<? extends Location>> locations;
private final Supplier<Map<String, ? extends Hardware>> hardwares;
private final Map<String, Credentials> credentialStore;
private final Function<VMImage, Image> vmImageToImge;
private final StorageProfileToStorageAccountName storageProfileToStorageAccountName;
@Inject
VirtualMachineToNodeMetadata(AzureComputeApi api, GroupNamingConvention.Factory namingConvention,
Supplier<Map<String, ? extends Image>> images, Supplier<Map<String, ? extends Hardware>> hardwares,
@Memoized Supplier<Set<? extends Location>> locations, Map<String, Credentials> credentialStore,
final AzureComputeConstants azureComputeConstants, Function<VMImage, Image> vmImageToImge,
StorageProfileToStorageAccountName storageProfileToStorageAccountName) {
this.api = api;
this.nodeNamingConvention = namingConvention.createWithoutPrefix();
this.images = checkNotNull(images, "images cannot be null");
this.locations = checkNotNull(locations, "locations cannot be null");
this.hardwares = checkNotNull(hardwares, "hardwares cannot be null");
this.credentialStore = credentialStore;
this.azureGroup = azureComputeConstants.azureResourceGroup();
this.vmImageToImge = vmImageToImge;
this.storageProfileToStorageAccountName = storageProfileToStorageAccountName;
}
@Override
public NodeMetadata apply(VirtualMachine virtualMachine) {
NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder.id(virtualMachine.name());
builder.providerId(virtualMachine.id());
builder.name(virtualMachine.name());
builder.hostname(virtualMachine.name());
String group = this.nodeNamingConvention.extractGroup(virtualMachine.name());
builder.group(group);
ProvisioningState provisioningState = virtualMachine.properties().provisioningState();
if (ProvisioningState.SUCCEEDED.equals(provisioningState)) {
// If the provisioning succeeded, we need to query the *real* status of
// the VM
VirtualMachineInstance instanceDetails = api.getVirtualMachineApi(azureGroup).getInstanceDetails(
virtualMachine.name());
builder.status(POWERSTATE_TO_NODESTATUS.apply(instanceDetails.powerState()));
builder.backendStatus(Joiner.on(',').join(
transform(instanceDetails.statuses(), new Function<VirtualMachineStatus, String>() {
@Override
public String apply(VirtualMachineStatus input) {
return input.code();
}
})));
} else {
builder.status(PROVISIONINGSTATE_TO_NODESTATUS.apply(provisioningState));
builder.backendStatus(provisioningState.name());
}
Credentials credentials = credentialStore.get("node#" + virtualMachine.name());
builder.credentials(LoginCredentials.fromCredentials(credentials));
builder.publicAddresses(getPublicIpAddresses(virtualMachine.properties().networkProfile().networkInterfaces()));
builder.privateAddresses(getPrivateIpAddresses(virtualMachine.properties().networkProfile().networkInterfaces()));
if (virtualMachine.tags() != null) {
Map<String, String> userMetaData = virtualMachine.tags();
builder.userMetadata(userMetaData);
builder.tags(Splitter.on(",").split(userMetaData.get("tags")));
}
String locationName = virtualMachine.location();
builder.location(getLocation(locationName));
Optional<? extends Image> image = findImage(virtualMachine.properties().storageProfile(), locationName);
if (image.isPresent()) {
builder.imageId(image.get().getId());
builder.operatingSystem(image.get().getOperatingSystem());
} else {
logger.info(">> image with id %s for virtualmachine %s was not found. "
+ "This might be because the image that was used to create the virtualmachine has a new id.",
virtualMachine.id(), virtualMachine.id());
}
builder.hardware(getHardware(virtualMachine.properties().hardwareProfile().vmSize()));
return builder.build();
}
private Iterable<String> getPrivateIpAddresses(List<IdReference> idReferences) {
List<String> privateIpAddresses = Lists.newArrayList();
for (IdReference networkInterfaceCardIdReference : idReferences) {
NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference);
for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) {
privateIpAddresses.add(ipConfiguration.properties().privateIPAddress());
}
}
return privateIpAddresses;
}
private NetworkInterfaceCard getNetworkInterfaceCard(IdReference networkInterfaceCardIdReference) {
Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 2);
String resourceGroup = Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 4);
String nicName = Iterables.getLast(Splitter.on("/").split(networkInterfaceCardIdReference.id()));
return api.getNetworkInterfaceCardApi(resourceGroup).get(nicName);
}
private Iterable<String> getPublicIpAddresses(List<IdReference> idReferences) {
List<String> publicIpAddresses = Lists.newArrayList();
for (IdReference networkInterfaceCardIdReference : idReferences) {
NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference);
String resourceGroup = Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 4);
for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) {
if (ipConfiguration.properties().publicIPAddress() != null) {
String publicIpId = ipConfiguration.properties().publicIPAddress().id();
publicIpAddresses.add(api.getPublicIPAddressApi(resourceGroup)
.get(Iterables.getLast(Splitter.on("/").split(publicIpId))).properties().ipAddress());
}
}
}
return publicIpAddresses;
}
protected Location getLocation(final String locationName) {
return find(locations.get(), new Predicate<Location>() {
@Override
public boolean apply(Location location) {
return locationName != null && locationName.equals(location.getId());
}
}, null);
}
protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName) {
if (storageProfile.imageReference() != null) {
return Optional.fromNullable(images.get().get(
encodeFieldsToUniqueId(false, locatioName, storageProfile.imageReference())));
} else {
String storageAccountName = storageProfileToStorageAccountName.apply(storageProfile);
StorageServiceKeys keys = api.getStorageAccountApi(azureGroup).getKeys(storageAccountName);
BlobHelper blobHelper = new BlobHelper(storageAccountName, keys.key1());
try {
// Custom image. Let's find it by uri
List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER,
locatioName);
Optional<VMImage> customImage = tryFind(customImagesInStorage, new Predicate<VMImage>() {
@Override
public boolean apply(VMImage input) {
return input.vhd1().equals(storageProfile.osDisk().image().uri());
}
});
return customImage.isPresent() ? Optional.of(vmImageToImge.apply(customImage.get())) : Optional
.<Image> absent();
} finally {
closeQuietly(blobHelper);
}
}
}
protected Hardware getHardware(final String vmSize) {
return Iterables.find(hardwares.get().values(), new Predicate<Hardware>() {
@Override
public boolean apply(Hardware input) {
return input.getId().equals(vmSize);
}
});
}
}

View File

@ -16,10 +16,12 @@
*/
package org.jclouds.azurecompute.arm.compute.options;
import static com.google.common.base.Objects.equal;
import org.jclouds.compute.options.TemplateOptions;
import com.google.common.base.Objects;
import static com.google.common.base.Objects.equal;
/**
* Azure ARM custom options
*/
@ -31,7 +33,9 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
private String subnetAddressPrefix;
private String DNSLabelPrefix;
private String keyVaultIdAndSecret;
private String virtualNetworkName;
private String subnetId;
private String blob;
/**
* Custom options for the Azure ARM API
@ -40,9 +44,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
this.customData = customData;
return this;
}
private String virtualNetworkName;
private String subnetId;
/**
* Sets the CIDR block for virtual network
*/
@ -75,15 +77,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
return this;
}
public String getCustomData() { return customData; }
public String getVirtualNetworkAddressPrefix() { return virtualNetworkAddressPrefix; }
public String getSubnetAddressPrefix() { return subnetAddressPrefix; }
public String getDNSLabelPrefix() { return DNSLabelPrefix; }
public String getKeyVaultIdAndSecret() { return keyVaultIdAndSecret; }
public String getVirtualNetworkName() { return virtualNetworkName; }
public String getSubnetId() { return subnetId; }
/**
* Sets the virtual network name
*/
@ -100,6 +93,24 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
return this;
}
/**
* Sets the blob name
*/
public AzureTemplateOptions blob(String blob) {
this.blob = blob;
return this;
}
public String getCustomData() { return customData; }
public String getVirtualNetworkAddressPrefix() { return virtualNetworkAddressPrefix; }
public String getSubnetAddressPrefix() { return subnetAddressPrefix; }
public String getDNSLabelPrefix() { return DNSLabelPrefix; }
public String getKeyVaultIdAndSecret() { return keyVaultIdAndSecret; }
public String getVirtualNetworkName() { return virtualNetworkName; }
public String getSubnetId() { return subnetId; }
public String getBlob() { return blob; }
@Override
public AzureTemplateOptions clone() {
AzureTemplateOptions options = new AzureTemplateOptions();
@ -119,12 +130,13 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
eTo.keyVaultIdAndSecret(keyVaultIdAndSecret);
eTo.virtualNetworkName(virtualNetworkName);
eTo.subnetId(subnetId);
eTo.blob(blob);
}
}
@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), virtualNetworkAddressPrefix, subnetAddressPrefix, DNSLabelPrefix, customData, keyVaultIdAndSecret, virtualNetworkName, subnetId);
return Objects.hashCode(super.hashCode(), virtualNetworkAddressPrefix, subnetAddressPrefix, DNSLabelPrefix, customData, keyVaultIdAndSecret, virtualNetworkName, subnetId, blob);
}
@Override
@ -146,7 +158,8 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
&& equal(this.DNSLabelPrefix, other.DNSLabelPrefix)
&& equal(this.keyVaultIdAndSecret, other.keyVaultIdAndSecret)
&& equal(this.virtualNetworkName, other.virtualNetworkName)
&& equal(this.subnetId, other.subnetId);
&& equal(this.subnetId, other.subnetId)
&& equal(this.blob, other.blob);
}
@Override
@ -159,6 +172,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
toString.add("keyVaultIdAndSecret", keyVaultIdAndSecret);
toString.add("virtualNetworkName", virtualNetworkName);
toString.add("subnetId", subnetId);
toString.add("blob", blob);
return toString;
}
@ -219,5 +233,13 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
AzureTemplateOptions options = new AzureTemplateOptions();
return options.subnetId(subnetId);
}
/**
* @see AzureTemplateOptions#blob
*/
public static AzureTemplateOptions blob(String blob) {
AzureTemplateOptions options = new AzureTemplateOptions();
return options.blob(blob);
}
}
}

View File

@ -40,6 +40,7 @@ public class IsDeploymentInRegions implements Predicate<Deployment> {
@Override
public boolean apply(Deployment deployment) {
if (deployment.properties() == null || deployment.properties().parameters() == null || deployment.properties().parameters().get("location") == null) return false;
Value locationValue = deployment.properties().parameters().get("location");
return regionIds.get().contains(locationValue.value());
}

View File

@ -1,43 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.compute.strategy;
import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials;
import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_PASSWORD;
import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_USERNAME;
public class AzurePopulateDefaultLoginCredentialsForImageStrategy implements PopulateDefaultLoginCredentialsForImageStrategy {
@Override
public LoginCredentials apply(Object o) {
ImageImpl node = (ImageImpl)o;
String username = AZURE_LOGIN_USERNAME;
String password = AZURE_LOGIN_PASSWORD;
if (username == null) {
username = "jclouds";
}
if (password == null) {
password = "Password1!";
}
Credentials creds = new Credentials(username, password);
LoginCredentials credentials = LoginCredentials.fromCredentials(creds);
return credentials;
}
}

View File

@ -17,26 +17,36 @@
package org.jclouds.azurecompute.arm.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
import static org.jclouds.util.Predicates2.retry;
import java.net.URI;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import com.google.common.collect.ImmutableMap;
import org.jclouds.Constants;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.StorageService;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
import org.jclouds.azurecompute.arm.features.SubnetApi;
import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.functions.GroupNamingConvention;
@ -45,9 +55,11 @@ import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
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;
@ -81,7 +93,13 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template,
Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
// If there is a script to be run on the node and public key
// authentication has been configured, warn users if the private key
// is not present
if (hasRunScriptWithKeyAuthAndNoPrivateKey(template)) {
logger.warn(">> a runScript was configured but no SSH key has been provided. " +
"Authentication will delegate to the ssh-agent");
}
String azureGroupName = this.azureComputeConstants.azureResourceGroup();
AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class);
@ -91,7 +109,7 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
final String location = template.getLocation().getId();
if (resourceGroup == null){
final Map<String, String> tags = ImmutableMap.of("description", "jClouds managed VMs");
final Map<String, String> tags = ImmutableMap.of("description", "jclouds managed VMs");
resourceGroupApi.create(azureGroupName, location, tags).name();
}
@ -104,7 +122,10 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
this.getOrCreateVirtualNetworkWithSubnet(vnetName, subnetName, location, options, azureGroupName);
StorageService storageService = getOrCreateStorageService(group, azureGroupName, location, template.getImage());
String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
options.blob(blob);
Map<?, ListenableFuture<Void>> responses = super.execute(group, count, template, goodNodes, badNodes,
customizationResponses);
@ -135,6 +156,70 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
options.virtualNetworkName(virtualNetworkName);
options.subnetId(subnet.id());
}
private static boolean hasRunScriptWithKeyAuthAndNoPrivateKey(Template template) {
return template.getOptions().getRunScript() != null && template.getOptions().getPublicKey() != null
&& !template.getOptions().hasLoginPrivateKeyOption();
}
public StorageService getOrCreateStorageService(String name, String resourceGroupName, String locationName, Image image) {
String storageAccountName = null;
VMImage imageRef = decodeFieldsFromUniqueId(image.getId());
if (imageRef.custom()) {
storageAccountName = imageRef.storage();
}
if (Strings.isNullOrEmpty(storageAccountName)) {
storageAccountName = generateStorageAccountName(name);
}
StorageService storageService = api.getStorageAccountApi(resourceGroupName).get(storageAccountName);
if (storageService != null) return storageService;
URI uri = api.getStorageAccountApi(resourceGroupName).create(storageAccountName, locationName, ImmutableMap.of("jclouds",
name), ImmutableMap.of("accountType", StorageService.AccountType.Standard_LRS.toString()));
boolean starageAccountCreated = retry(new Predicate<URI>() {
@Override
public boolean apply(URI uri) {
return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri);
}
}, 60 * 2 * 1000 /* 2 minutes timeout */).apply(uri);
// TODO check provisioning state of the primary
checkState(starageAccountCreated, "Storage account %s was not created in the configured timeout",
storageAccountName);
return api.getStorageAccountApi(resourceGroupName).get(storageAccountName);
}
/**
* Generates a valid storage account
*
* Storage account names must be between 3 and 24 characters in length and may contain numbers and lowercase letters only.
*
* @param name the node name
* @return the storage account name starting from a sanitized name (with only numbers and lowercase letters only ).
* If sanitized name is between 3 and 24 characters, storage account name is equals to sanitized name.
* If sanitized name is less than 3 characters, storage account is sanitized name plus 4 random chars.
* If sanitized name is more than 24 characters, storage account is first 10 chars of sanitized name plus 4 random chars plus last 10 chars of sanitized name.
*/
public static String generateStorageAccountName(String name) {
String random = UUID.randomUUID().toString().substring(0, 4);
String storageAccountName = new StringBuilder().append(name).append(random).toString();
String sanitizedStorageAccountName = storageAccountName.replaceAll("[^a-z0-9]", "");
int nameLength = sanitizedStorageAccountName.length();
if (nameLength >= 3 && nameLength <= 24) {
return sanitizedStorageAccountName;
}
if (nameLength > 24) {
sanitizedStorageAccountName = shorten(storageAccountName, random);
}
return sanitizedStorageAccountName;
}
private static String shorten(String storageAccountName, String random) {
String prefix = storageAccountName.substring(0, 10);
String suffix = storageAccountName.substring(storageAccountName.length() - 10, storageAccountName.length());
return String.format("%s%s%s", prefix, random, suffix);
}
}

View File

@ -18,7 +18,6 @@ package org.jclouds.azurecompute.arm.config;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.handlers.AzureComputeErrorHandler;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
@ -30,7 +29,6 @@ import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.config.HttpApiModule;
import com.google.inject.Scopes;
import com.google.inject.assistedinject.FactoryModuleBuilder;
@ConfiguresHttpApi
public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
@ -51,7 +49,6 @@ public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
@Override
protected void configure() {
install(new FactoryModuleBuilder().build(DeploymentTemplateBuilder.Factory.class));
super.configure();
bind(OAuthScopes.class).toInstance(OAuthScopes.NoScopes.create());
}

View File

@ -17,10 +17,13 @@
package org.jclouds.azurecompute.arm.config;
/**
* Configuration properties and constants used in Azure Resource Manager connections.
* Configuration properties and constants used in Azure Resource Manager
* connections.
*/
public class AzureComputeProperties {
public static final String STORAGE_API_VERSION = "2015-06-15";
public static final String OPERATION_TIMEOUT = "jclouds.azurecompute.arm.operation.timeout";
public static final String OPERATION_POLL_INITIAL_PERIOD = "jclouds.azurecompute.arm.operation.poll.initial.period";
@ -31,8 +34,6 @@ public class AzureComputeProperties {
public static final String TCP_RULE_REGEXP = "jclouds.azurecompute.arm.tcp.rule.regexp";
public static final String STORAGE_API_VERSION = "2015-06-15";
public static final String RESOURCE_GROUP_NAME = "jclouds.azurecompute.arm.operation.resourcegroup";
public static final String IMAGE_PUBLISHERS = "jclouds.azurecompute.arm.publishers";
@ -47,4 +48,6 @@ public class AzureComputeProperties {
public static final String DEFAULT_DATADISKSIZE = "jclouds.azurecompute.arm.datadisksize";
public static final String API_VERSION_PREFIX = "jclouds.azurecompute.arm.apiversion.";
}

View File

@ -16,43 +16,29 @@
*/
package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue;
import java.util.List;
import org.jclouds.javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import com.google.auto.value.AutoValue;
@AutoValue
public abstract class VMDeployment {
public abstract Deployment deployment();
public abstract String deploymentId();
@Nullable
public abstract VirtualMachine virtualMachine();
@Nullable
public abstract List<PublicIPAddress> ipAddressList();
@Nullable
public abstract VirtualMachineInstance vm();
@Nullable
public abstract VirtualMachine virtualMachine();
@Nullable
public abstract List<NetworkInterfaceCard> networkInterfaceCards();
@Nullable
public abstract Map<String, String> userMetaData();
@Nullable
public abstract Iterable<String> tags();
public static VMDeployment create(Deployment deployment) {
return create(deployment, null, null, null, null, null, null);
}
public static VMDeployment create(Deployment deployment, List<PublicIPAddress> ipAddressList,
VirtualMachineInstance vm, VirtualMachine virtualMachine,
List<NetworkInterfaceCard> networkInterfaceCards, Map<String, String> userMetaData,
Iterable<String> tags) {
return new AutoValue_VMDeployment(deployment, ipAddressList, vm, virtualMachine, networkInterfaceCards, userMetaData, tags);
public static VMDeployment create(String deploymentId, VirtualMachine virtualMachine,
List<PublicIPAddress> ipAddressList,
List<NetworkInterfaceCard> networkInterfaceCards) {
return new AutoValue_VMDeployment(deploymentId, virtualMachine, ipAddressList, networkInterfaceCards);
}
}

View File

@ -16,9 +16,9 @@
*/
package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
@AutoValue
public abstract class VMImage {
@ -91,16 +91,35 @@ public abstract class VMImage {
* True if custom image
*/
public abstract boolean custom();
@SerializedNames({ "publisher", "offer", "sku", "version", "location"})
public static VMImage create(String publisher, String offer, String sku, String version, String location) {
return new AutoValue_VMImage(publisher, offer, sku, version, location, false, null, null, null, null, null, false);
public static Builder builder() {
return new AutoValue_VMImage.Builder();
}
@SerializedNames({ "group", "storage", "vhd1", "vhd2", "name", "offer", "location"})
public static VMImage create(String group, String storage, String vhd1, String vhd2, String name, String offer, String location) {
return new AutoValue_VMImage(null, offer, null, null, location, false, group, storage, vhd1, vhd2, name, true);
public static Builder azureImage() {
return new AutoValue_VMImage.Builder().globallyAvailable(false).custom(false);
}
public static Builder customImage() {
return new AutoValue_VMImage.Builder().globallyAvailable(false).custom(true);
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder publisher(String published);
public abstract Builder offer(String offer);
public abstract Builder sku(String sku);
public abstract Builder version(String version);
public abstract Builder location(String location);
public abstract Builder globallyAvailable(boolean globallyAvailable);
public abstract Builder group(String group);
public abstract Builder storage(String storage);
public abstract Builder vhd1(String vhd1);
public abstract Builder vhd2(String vhd2);
public abstract Builder name(String name);
public abstract Builder custom(boolean custom);
public abstract VMImage build();
}
}

View File

@ -16,12 +16,13 @@
*/
package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
import java.util.Map;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableMap;
/**
* A virtual machine that is valid for your subscription.

View File

@ -16,13 +16,23 @@
*/
package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getFirst;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.util.Predicates2.startsWith;
import java.util.Date;
import java.util.List;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties.ProvisioningState;
import org.jclouds.azurecompute.arm.util.GetEnumValue;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
import java.util.Date;
import com.google.auto.value.AutoValue;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
/**
* A virtual machine instance view that is valid for your subscription.
@ -30,8 +40,21 @@ import java.util.Date;
@AutoValue
public abstract class VirtualMachineInstance {
@AutoValue
@com.google.auto.value.AutoValue
public abstract static class VirtualMachineStatus {
public static final String PROVISIONING_STATE_PREFIX = "ProvisioningState/";
public static final String POWER_STATE_PREFIX = "PowerState/";
public enum PowerState {
RUNNING,
STOPPED,
UNRECOGNIZED;
public static PowerState fromValue(final String text) {
return (PowerState) GetEnumValue.fromValueOrDefault(text, PowerState.UNRECOGNIZED);
}
}
@Nullable
public abstract String code();
@ -61,6 +84,26 @@ public abstract class VirtualMachineInstance {
@Nullable
public abstract List<VirtualMachineStatus> statuses();
public ProvisioningState provisioningState() {
return ProvisioningState.fromValue(firstStatus(VirtualMachineStatus.PROVISIONING_STATE_PREFIX));
}
public PowerState powerState() {
return PowerState.fromValue(firstStatus(VirtualMachineStatus.POWER_STATE_PREFIX));
}
private String firstStatus(final String type) {
return getFirst(transform(filter(transform(statuses(), new Function<VirtualMachineStatus, String>() {
@Override public String apply(VirtualMachineStatus input) {
return input.code();
}
}), startsWith(type)), new Function<String, String>() {
@Override public String apply(String input) {
return input.substring(type.length());
}
}), null);
}
@SerializedNames({"platformUpdateDomain", "platformFaultDomain", "statuses"})

View File

@ -16,16 +16,35 @@
*/
package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue;
import org.jclouds.azurecompute.arm.util.GetEnumValue;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
/**
* A virtual machine properties for the virtual machine.
*/
@AutoValue
public abstract class VirtualMachineProperties {
public enum ProvisioningState {
ACCEPTED,
CREATING,
READY,
CANCELED,
FAILED,
DELETED,
SUCCEEDED,
RUNNING,
UPDATING,
UNRECOGNIZED;
public static ProvisioningState fromValue(final String text) {
return (ProvisioningState) GetEnumValue.fromValueOrDefault(text, ProvisioningState.UNRECOGNIZED);
}
}
/**
* The id of the virtual machine.
*/
@ -78,7 +97,7 @@ public abstract class VirtualMachineProperties {
* The provisioning state of the VM
*/
@Nullable
public abstract String provisioningState();
public abstract ProvisioningState provisioningState();
@SerializedNames({"vmId", "licenseType", "availabilitySet", "hardwareProfile", "storageProfile", "osProfile",
"networkProfile", "diagnosticsProfile", "provisioningState"})
@ -90,7 +109,7 @@ public abstract class VirtualMachineProperties {
final OSProfile osProfile,
final NetworkProfile networkProfile,
final DiagnosticsProfile diagnosticsProfile,
final String provisioningState) {
final ProvisioningState provisioningState) {
return builder()
.vmId(vmId)
.licenseType(licenseType)
@ -126,7 +145,7 @@ public abstract class VirtualMachineProperties {
public abstract Builder diagnosticsProfile(DiagnosticsProfile diagnosticsProfile);
public abstract Builder provisioningState(String provisioningState);
public abstract Builder provisioningState(ProvisioningState provisioningState);
public abstract VirtualMachineProperties build();
}

View File

@ -34,12 +34,12 @@ import org.jclouds.Fallbacks;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.Deployment;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
@ -50,8 +50,7 @@ import org.jclouds.rest.annotations.SelectJson;
* - get information about deployment
*/
@Path("/resourcegroups/{resourcegroup}/providers/microsoft.resources/deployments")
@QueryParams(keys = "api-version", values = "2016-02-01")
@RequestFilters(OAuthFilter.class)
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface DeploymentApi {

View File

@ -18,19 +18,20 @@ package org.jclouds.azurecompute.arm.features;
import java.io.Closeable;
import java.net.URI;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.GET;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus;
import org.jclouds.rest.annotations.SelectJson;
/**

View File

@ -27,11 +27,11 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.Location;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Fallback;
/**
* This Azure Resource Manager API provides all of the locations that are available for resource providers
@ -40,8 +40,7 @@ import org.jclouds.rest.annotations.Fallback;
* @see <a href="https://msdn.microsoft.com/en-US/library/azure/dn790540.aspx">docs</a>
*/
@Path("/locations")
@RequestFilters(OAuthFilter.class)
@QueryParams(keys = "api-version", values = "2015-11-01")
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public interface LocationApi {

View File

@ -16,20 +16,9 @@
*/
package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
import java.net.URI;
import java.util.List;
import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
@ -39,15 +28,25 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
import java.net.URI;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkInterfaces")
@QueryParams(keys = "api-version", values = "2015-06-15")
@RequestFilters(OAuthFilter.class)
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface NetworkInterfaceCardApi {
@Named("networkinterfacecard:list")

View File

@ -16,40 +16,38 @@
*/
package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Named;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.DELETE;
import javax.ws.rs.PUT;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import java.net.URI;
import java.util.List;
import java.util.Map;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkSecurityGroups")
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@QueryParams(keys = "api-version", values = "2016-03-30")
@RequestFilters(OAuthFilter.class)
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkSecurityGroups")
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface NetworkSecurityGroupApi {
@ -72,9 +70,8 @@ public interface NetworkSecurityGroupApi {
@MapBinder(BindToJsonPayload.class)
@Produces(MediaType.APPLICATION_JSON)
NetworkSecurityGroup createOrUpdate(@PathParam("networksecuritygroupname") String nsgName,
@PayloadParam("location") String location,
@Nullable @PayloadParam("tags") Map<String, String> tags,
@PayloadParam("properties")NetworkSecurityGroupProperties properties);
@PayloadParam("location") String location, @Nullable @PayloadParam("tags") Map<String, String> tags,
@PayloadParam("properties") NetworkSecurityGroupProperties properties);
@Named("networksecuritygroup:get")
@Path("/{networksecuritygroupname}")
@ -82,4 +79,3 @@ public interface NetworkSecurityGroupApi {
@Fallback(NullOnNotFoundOr404.class)
NetworkSecurityGroup get(@PathParam("networksecuritygroupname") String nsgName);
}

View File

@ -16,38 +16,36 @@
*/
package org.jclouds.azurecompute.arm.features;
import java.net.URI;
import java.util.List;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Named;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.DELETE;
import javax.ws.rs.PUT;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import java.util.List;
import java.net.URI;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkSecurityGroups/{networksecuritygroup}")
@QueryParams(keys = "api-version", values = "2016-03-30")
@RequestFilters(OAuthFilter.class)
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface NetworkSecurityRuleApi {
@Named("networksecurityrule:createOrUpdate")

View File

@ -31,17 +31,16 @@ import org.jclouds.azurecompute.arm.domain.Offer;
import org.jclouds.azurecompute.arm.domain.Publisher;
import org.jclouds.azurecompute.arm.domain.SKU;
import org.jclouds.azurecompute.arm.domain.Version;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
/**
* The Azure Resource Management API includes operations for managing the OS images in your subscription.
*/
@Path("/providers/Microsoft.Compute/locations/{location}")
@RequestFilters(OAuthFilter.class)
@QueryParams(keys = "api-version", values = "2015-06-15")
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(APPLICATION_JSON)
public interface OSImageApi {

View File

@ -16,20 +16,8 @@
*/
package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
import java.util.List;
import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
@ -39,14 +27,25 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/publicIPAddresses")
@QueryParams(keys = "api-version", values = "2015-06-15")
@RequestFilters(OAuthFilter.class)
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface PublicIPAddressApi {
@Named("publicipaddress:list")

View File

@ -19,32 +19,31 @@ import java.io.Closeable;
import java.net.URI;
import java.util.List;
import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.PATCH;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
/**
@ -53,9 +52,7 @@ import org.jclouds.rest.binders.BindToJsonPayload;
* @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn790546.aspx">docs</a>
*/
@Path("/resourcegroups")
@QueryParams(keys = "api-version", values = "2015-01-01")
@RequestFilters(OAuthFilter.class)
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface ResourceGroupApi extends Closeable{

View File

@ -17,14 +17,8 @@
package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import java.io.Closeable;
import java.util.List;
import javax.inject.Named;
import javax.ws.rs.Consumes;
@ -32,8 +26,15 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import java.io.Closeable;
import java.util.List;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
/**
* The Azure Resource Provider API provides information about a resource provider and its supported resource types.
@ -42,8 +43,7 @@ import java.util.List;
*/
@Path("/providers")
@QueryParams(keys = "api-version", values = "2015-01-01")
@RequestFilters(OAuthFilter.class)
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface ResourceProviderApi extends Closeable {

View File

@ -16,15 +16,19 @@
*/
package org.jclouds.azurecompute.arm.features;
import java.net.URI;
import java.util.List;
import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.PUT;
import javax.ws.rs.POST;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks;
@ -32,35 +36,28 @@ import org.jclouds.azurecompute.arm.domain.Availability;
import org.jclouds.azurecompute.arm.domain.StorageService;
import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
import org.jclouds.azurecompute.arm.domain.StorageServiceUpdateParams;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PATCH;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PATCH;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
import java.util.List;
import java.util.Map;
import java.net.URI;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION;
/**
* The Azure Resource Management API includes operations for managing the storage accounts in your subscription.
*
* @see <a href="https://msdn.microsoft.com/en-us/library/mt163683.aspx">docs</a>
*/
@Path("/")
@RequestFilters(OAuthFilter.class)
@QueryParams(keys = "api-version", values = STORAGE_API_VERSION)
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface StorageAccountApi {

View File

@ -16,20 +16,7 @@
*/
package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.binders.BindToJsonPayload;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.MapBinder;
import java.util.List;
import javax.inject.Named;
import javax.ws.rs.Consumes;
@ -39,12 +26,24 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import java.util.List;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/virtualNetworks/{virtualnetwork}/subnets")
@QueryParams(keys = "api-version", values = "2015-06-15")
@RequestFilters(OAuthFilter.class)
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface SubnetApi {

View File

@ -16,24 +16,24 @@
*/
package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.VMSize;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import java.util.List;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import java.util.List;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.VMSize;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
@Path("/providers/Microsoft.Compute/locations/{location}/vmSizes")
@QueryParams(keys = "api-version", values = "2015-06-15")
@RequestFilters(OAuthFilter.class)
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface VMSizeApi {

View File

@ -16,10 +16,25 @@
*/
package org.jclouds.azurecompute.arm.features;
import java.net.URI;
import java.util.List;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
@ -32,27 +47,13 @@ import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.net.URI;
import java.util.List;
/**
* The Virtual Machine API includes operations for managing the virtual machines in your subscription.
*
* @see <a href="https://msdn.microsoft.com/en-us/library/azure/mt163630.aspx">docs</a>
*/
@Path("/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines")
@RequestFilters(OAuthFilter.class)
@QueryParams(keys = "api-version", values = "2015-06-15")
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface VirtualMachineApi {
@ -66,14 +67,14 @@ public interface VirtualMachineApi {
VirtualMachine get(@PathParam("name") String name);
/**
* The Get Virtual Machine details
* Get information about the model view and instance view of a virtual machine:
*/
@Named("GetVirtualMachineInstance")
@GET
@Path("/{name}/instanceView")
@Fallback(Fallbacks.NullOnNotFoundOr404.class)
VirtualMachineInstance getInstanceDetails(@PathParam("name") String name);
/**
* The Create Virtual Machine
*/

View File

@ -15,22 +15,7 @@
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import java.util.List;
import javax.inject.Named;
import javax.ws.rs.Consumes;
@ -40,11 +25,23 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import java.util.List;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/virtualNetworks")
@QueryParams(keys = "api-version", values = "2015-06-15")
@RequestFilters(OAuthFilter.class)
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface VirtualNetworkApi {

View File

@ -0,0 +1,90 @@
/*
* 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.filters;
import static com.google.common.base.Preconditions.checkArgument;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
import static org.jclouds.util.Maps2.transformKeys;
import static org.jclouds.util.Predicates2.startsWith;
import java.util.Map;
import javax.inject.Inject;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.rest.config.InvocationConfig;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.reflect.Invokable;
/**
* Allow users to customize the api versions for each method call.
* <p>
* In Azure ARM, each method may have its own api version. This filter allows to
* configure the versions of each method, so there is no need to change the code
* when Azure deprecates old versions.
*/
public class ApiVersionFilter implements HttpRequestFilter {
private final InvocationConfig config;
private final Map<String, String> versions;
@Inject
ApiVersionFilter(InvocationConfig config, Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) {
this.config = config;
this.versions = versions(filterStringsBoundByName);
}
@Override
public HttpRequest filter(HttpRequest request) throws HttpException {
checkArgument(request instanceof GeneratedHttpRequest,
"This filter can only be applied to GeneratedHttpRequest objects");
GeneratedHttpRequest generatedRequest = (GeneratedHttpRequest) request;
// Look if there is a custom api version for the current method
String commandName = config.getCommandName(generatedRequest.getInvocation());
String customApiVersion = versions.get(commandName);
if (customApiVersion == null) {
// No custom config for the specific method. Let's look for custom
// config for the class
Invokable<?, ?> invoked = generatedRequest.getInvocation().getInvokable();
String className = invoked.getOwnerType().getRawType().getSimpleName();
customApiVersion = versions.get(className);
}
if (customApiVersion != null) {
return request.toBuilder().replaceQueryParam("api-version", customApiVersion).build();
}
return request;
}
private static Map<String, String> versions(Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) {
Map<String, String> stringBoundWithApiVersionPrefix = filterStringsBoundByName
.apply(startsWith(API_VERSION_PREFIX));
return transformKeys(stringBoundWithApiVersionPrefix, new Function<String, String>() {
public String apply(String input) {
return input.replaceFirst(API_VERSION_PREFIX, "");
}
});
}
}

View File

@ -14,127 +14,163 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.functions;
package org.jclouds.azurecompute.arm.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.util.Closeables2.closeQuietly;
import java.net.URI;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import com.google.common.base.Predicate;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
import org.jclouds.azurecompute.arm.domain.Deployment;
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.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.util.BlobHelper;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import java.net.URI;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@Singleton
public class CleanupResources implements Function<String, Boolean> {
private final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final AzureComputeApi api;
private Predicate<URI> nodeTerminated;
private Predicate<URI> resourceDeleted;
private final Predicate<URI> resourceDeleted;
private final StorageProfileToStorageAccountName storageProfileToStorageAccountName;
@Inject
public CleanupResources(AzureComputeApi azureComputeApi,
AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<URI> nodeTerminated,
@Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted) {
this.azureComputeConstants = azureComputeConstants;
CleanupResources(AzureComputeApi azureComputeApi, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
StorageProfileToStorageAccountName storageProfileToStorageAccountName) {
this.api = azureComputeApi;
this.nodeTerminated = nodeTerminated;
this.resourceDeleted = resourceDeleted;
this.storageProfileToStorageAccountName = storageProfileToStorageAccountName;
}
@Override
public Boolean apply(String id) {
public Boolean apply(final String id) {
logger.debug(">> destroying %s ...", id);
logger.debug("Destroying %s ...", id);
String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + "stor";
String group = azureComputeConstants.azureResourceGroup();
Map<String, VirtualMachine> resourceGroupNamesAndVirtualMachines = getResourceGroupNamesAndVirtualMachines(id);
if (resourceGroupNamesAndVirtualMachines.isEmpty())
return true;
VirtualMachine vm = api.getVirtualMachineApi(group).get(id);
if (vm != null) {
URI uri = api.getVirtualMachineApi(group).delete(id);
if (uri != null) {
boolean jobDone = nodeTerminated.apply(uri);
boolean storageAcctDeleteStatus = false;
boolean deploymentDeleteStatus = false;
String group = checkNotNull(resourceGroupNamesAndVirtualMachines.entrySet().iterator().next().getKey(),
"resourceGroup name must not be null");
VirtualMachine virtualMachine = checkNotNull(resourceGroupNamesAndVirtualMachines.get(group),
"virtualMachine must not be null");
if (jobDone) {
Deployment deployment = api.getDeploymentApi(group).get(id);
if (deployment != null) {
uri = api.getDeploymentApi(group).delete(id);
jobDone = resourceDeleted.apply(uri);
if (jobDone) {
deploymentDeleteStatus = true;
}
} else {
deploymentDeleteStatus = true;
}
NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(group).get(id + "nic");
if (nic != null) {
uri = api.getNetworkInterfaceCardApi(group).delete(id + "nic");
if (uri != null) {
jobDone = resourceDeleted.apply(uri);
if (jobDone) {
boolean ipDeleteStatus = false;
PublicIPAddress ip = api.getPublicIPAddressApi(group).get(id + "publicip");
if (ip != null) {
ipDeleteStatus = api.getPublicIPAddressApi(group).delete(id + "publicip");
} else {
ipDeleteStatus = true;
}
boolean vmDeleted = deleteVirtualMachine(group, 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
// Get NSG
boolean nsgDeleteStatus = false;
NetworkSecurityGroup nsg = api.getNetworkSecurityGroupApi(group).get(id + "nsg");
if (nsg != null) {
uri = api.getNetworkSecurityGroupApi(group).delete(id + "nsg");
jobDone = resourceDeleted.apply(uri);
if (jobDone) {
nsgDeleteStatus = true;
for (String nicName : getNetworkCardInterfaceNames(virtualMachine)) {
NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(group).get(nicName);
Iterable<String> publicIps = getPublicIps(group, nic);
}
}
else {
nsgDeleteStatus = true;
}
logger.debug(">> destroying nic %s...", nicName);
URI nicDeletionURI = api.getNetworkInterfaceCardApi(group).delete(nicName);
resourceDeleted.apply(nicDeletionURI);
return deploymentDeleteStatus && storageAcctDeleteStatus && ipDeleteStatus && nsgDeleteStatus;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
} else {
return false;
for (String publicIp : publicIps) {
logger.debug(">> deleting public ip nic %s...", publicIp);
api.getPublicIPAddressApi(group).delete(publicIp);
}
} else {
return false;
}
String storageAccountName = storageProfileToStorageAccountName.apply(virtualMachine.properties().storageProfile());
StorageServiceKeys keys = api.getStorageAccountApi(group).getKeys(storageAccountName);
// Remove the virtual machine files
logger.debug(">> deleting virtual machine disk storage...");
BlobHelper blobHelper = new BlobHelper(storageAccountName, keys.key1());
try {
blobHelper.deleteContainerIfExists("vhds");
if (!blobHelper.customImageExists()) {
logger.debug(">> deleting storage account %s...", storageAccountName);
api.getStorageAccountApi(group).delete(storageAccountName);
} else {
logger.debug(">> the storage account contains custom images. Will not delete it!");
}
} finally {
closeQuietly(blobHelper);
}
deleteResourceGroupIfEmpty(group);
return vmDeleted;
}
public void deleteResourceGroupIfEmpty(String group) {
if (api.getVirtualMachineApi(group).list().isEmpty()
&& api.getStorageAccountApi(group).list().isEmpty()
&& api.getNetworkInterfaceCardApi(group).list().isEmpty()
&& api.getPublicIPAddressApi(group).list().isEmpty()) {
logger.debug(">> the resource group %s is empty. Deleting...", group);
resourceDeleted.apply(api.getResourceGroupApi().delete(group));
}
}
private Iterable<String> getPublicIps(String group, NetworkInterfaceCard nic) {
return transform(
filter(transform(nic.properties().ipConfigurations(), new Function<IpConfiguration, IdReference>() {
@Override
public IdReference apply(IpConfiguration input) {
return input.properties().publicIPAddress();
}
}), notNull()), new Function<IdReference, String>() {
@Override
public String apply(IdReference input) {
return Iterables.getLast(Splitter.on("/").split(input.id()));
}
});
}
private List<String> getNetworkCardInterfaceNames(VirtualMachine virtualMachine) {
List<String> nics = Lists.newArrayList();
for (IdReference idReference : virtualMachine.properties().networkProfile().networkInterfaces()) {
nics.add(Iterables.getLast(Splitter.on("/").split(idReference.id())));
}
return nics;
}
private boolean deleteVirtualMachine(String group, VirtualMachine virtualMachine) {
return resourceDeleted.apply(api.getVirtualMachineApi(group).delete(virtualMachine.name()));
}
private Map<String, VirtualMachine> getResourceGroupNamesAndVirtualMachines(String id) {
for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
String group = resourceGroup.name();
VirtualMachine virtualMachine = api.getVirtualMachineApi(group).get(id);
if (virtualMachine != null) {
return ImmutableMap.of(group, virtualMachine);
}
}
return Maps.newHashMap();
}
}

View File

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

View File

@ -16,76 +16,68 @@
*/
package org.jclouds.azurecompute.arm.util;
import static org.jclouds.util.Closeables2.closeQuietly;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.jclouds.ContextBuilder;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azureblob.AzureBlobClient;
import org.jclouds.azureblob.domain.BlobProperties;
import org.jclouds.azureblob.domain.ContainerProperties;
import org.jclouds.azureblob.domain.ListBlobsResponse;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.util.Closeables2;
public class BlobHelper {
public class BlobHelper implements Closeable {
public static void deleteContainerIfExists(String storage, String key, String containerName) {
final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob")
.credentials(storage, key)
.buildApi(AzureBlobClient.class);
private final String storageAccount;
private final AzureBlobClient azureBlob;
try {
azureBlob.deleteContainer(containerName);
}
finally {
Closeables2.closeQuietly(azureBlob);
}
public BlobHelper(String storageAccount, String key) {
this.storageAccount = storageAccount;
this.azureBlob = ContextBuilder.newBuilder("azureblob").credentials(storageAccount, key)
.buildApi(AzureBlobClient.class);
}
public static boolean customImageExists(String storage, String key) {
final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob")
.credentials(storage, key)
.buildApi(AzureBlobClient.class);
try {
return azureBlob.containerExists("system");
}
finally {
Closeables2.closeQuietly(azureBlob);
}
@Override
public void close() throws IOException {
closeQuietly(azureBlob);
}
public static List<VMImage> getImages(String containerName, String group,
String storageAccountName, String key, String offer, String location) {
final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob")
.credentials(storageAccountName, key)
.buildApi(AzureBlobClient.class);
public void deleteContainerIfExists(String containerName) {
azureBlob.deleteContainer(containerName);
}
public boolean hasContainers() {
return !azureBlob.listContainers().isEmpty();
}
public boolean customImageExists() {
return azureBlob.containerExists("system");
}
public List<VMImage> getImages(String containerName, String group, String offer, String location) {
List<VMImage> list = new ArrayList<VMImage>();
try {
BoundedSet<ContainerProperties> containerList = azureBlob.listContainers();
for (ContainerProperties props : containerList) {
if (props.getName().equals("system")) {
ListBlobsResponse blobList = azureBlob.listBlobs("system");
String osDisk = "";
String dataDisk = "";
for (BlobProperties blob : blobList) {
String name = blob.getName();
ContainerProperties systemContainer = azureBlob.getContainerProperties("system");
if (systemContainer != null) {
ListBlobsResponse blobList = azureBlob.listBlobs(systemContainer.getName());
for (BlobProperties blob : blobList) {
String name = blob.getName();
if (dataDisk.length() == 0) dataDisk = name.substring(1 + name.lastIndexOf('/'));
else if (osDisk.length() == 0) osDisk = name.substring(1 + name.lastIndexOf('/'));
}
final VMImage ref = VMImage.create(group, storageAccountName, osDisk, dataDisk, "test-create-image", "custom", location);
list.add(ref);
if (name.contains("-osDisk")) {
String imageName = name.substring(name.lastIndexOf('/') + 1, name.indexOf("-osDisk"));
String imageUrl = blob.getUrl().toString();
list.add(VMImage.customImage().group(group).storage(storageAccount).vhd1(imageUrl).name(imageName)
.offer(offer).location(location).build());
}
}
}
finally {
Closeables2.closeQuietly(azureBlob);
}
return list;
}
}

View File

@ -1,573 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.DataDisk;
import org.jclouds.azurecompute.arm.domain.DeploymentBody;
import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
import org.jclouds.azurecompute.arm.domain.DeploymentTemplate;
import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
import org.jclouds.azurecompute.arm.domain.DnsSettings;
import org.jclouds.azurecompute.arm.domain.HardwareProfile;
import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.ImageReference;
import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
import org.jclouds.azurecompute.arm.domain.KeyVaultReference;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.domain.NetworkProfile;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
import org.jclouds.azurecompute.arm.domain.OSDisk;
import org.jclouds.azurecompute.arm.domain.OSProfile;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.domain.StorageProfile;
import org.jclouds.azurecompute.arm.domain.StorageService;
import org.jclouds.azurecompute.arm.domain.StorageService.StorageServiceProperties;
import org.jclouds.azurecompute.arm.domain.TemplateParameterType;
import org.jclouds.azurecompute.arm.domain.VHD;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.compute.domain.Template;
import org.jclouds.json.Json;
import org.jclouds.predicates.Validator;
import org.jclouds.predicates.validators.DnsNameValidator;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import static com.google.common.io.BaseEncoding.base64;
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION;
public class DeploymentTemplateBuilder {
public interface Factory {
DeploymentTemplateBuilder create(@Assisted("group") String group, @Assisted("name") String name, Template template);
}
private final String name;
private final String azureGroup;
private final String group;
private final Template template;
private final Json json;
private AzureTemplateOptions options;
private Iterable<String> tags;
private Map<String, String> userMetaData;
private List<ResourceDefinition> resources;
private Map<String, String> variables;
private static String loginUser;
private static String loginPassword;
private String location;
private AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
private static final String DEPLOYMENT_MODE = "Incremental";
@Inject
DeploymentTemplateBuilder(Json json, @Assisted("group") String group, @Assisted("name") String name, @Assisted Template template,
final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants) {
this.name = name;
this.group = group;
this.template = template;
this.options = template.getOptions().as(AzureTemplateOptions.class);
this.tags = template.getOptions().getTags();
this.userMetaData = template.getOptions().getUserMetadata();
this.variables = new HashMap<String, String>();
this.resources = new ArrayList<ResourceDefinition>();
this.location = template.getLocation().getId();
this.json = json;
this.azureComputeConstants = azureComputeConstants;
this.azureGroup = this.azureComputeConstants.azureResourceGroup();
String[] defaultLogin = this.azureComputeConstants.azureDefaultImageLogin().split(":");
String defaultUser = null;
String defaultPassword = null;
if (defaultLogin.length == 2) {
defaultUser = defaultLogin[0].trim();
defaultPassword = defaultLogin[1].trim();
}
loginUser = options.getLoginUser() == null ? defaultUser : options.getLoginUser();
loginPassword = options.getLoginPassword() == null ? defaultPassword : options.getLoginPassword();
}
public static String getLoginUserUsername() {
return loginUser;
}
public static String getLoginPassword() {
return loginPassword;
}
public Template getTemplate() {
return template;
}
public DeploymentBody getDeploymentTemplate() {
addStorageResource();
addPublicIpAddress();
addNetworkSecurityGroup();
addNetworkInterfaceCard();
addVirtualMachine();
DeploymentTemplate.TemplateParameters templateParameters = null;
DeploymentTemplate.Parameters parameters = null;
if (keyVaultInUse()){
String[] keyVaultInfo = options.getKeyVaultIdAndSecret().split(":");
Preconditions.checkArgument(keyVaultInfo.length == 2);
String vaultId = keyVaultInfo[0].trim();
String secretName = keyVaultInfo[1].trim();
templateParameters = DeploymentTemplate.TemplateParameters.create(TemplateParameterType.create("securestring"));
parameters = DeploymentTemplate.Parameters.create(KeyVaultReference.create(KeyVaultReference.Reference.create(IdReference.create(vaultId), secretName)));
} else {
templateParameters = DeploymentTemplate.TemplateParameters.create(null);
parameters = DeploymentTemplate.Parameters.create(null);
}
DeploymentTemplate template = DeploymentTemplate.builder()
.schema("https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#")
.contentVersion("1.0.0.0")
.resources(resources)
.variables(variables)
.parameters(templateParameters)
.build();
DeploymentBody body = DeploymentBody.create(template, DEPLOYMENT_MODE, parameters);
return body;
}
public String getDeploymentTemplateJson(DeploymentProperties properties) {
return json.toJson(properties);
}
private void addStorageResource() {
String storageAccountName = null;
String imageName = template.getImage().getName();
if (imageName.startsWith(CUSTOM_IMAGE_PREFIX)) {
storageAccountName = template.getImage().getVersion();
}
if (Strings.isNullOrEmpty(storageAccountName)) {
storageAccountName = generateStorageAccountName(name);
}
Validator<String> validator = new DnsNameValidator(3, 24);
validator.validate(storageAccountName);
variables.put("storageAccountName", storageAccountName);
ResourceDefinition storageAccount = ResourceDefinition.builder()
.name("[variables('storageAccountName')]")
.type("Microsoft.Storage/storageAccounts")
.location(location)
.apiVersion(STORAGE_API_VERSION)
.properties(
StorageServiceProperties.builder()
.accountType(StorageService.AccountType.Standard_LRS)
.build()
)
.build();
resources.add(storageAccount);
}
private void addPublicIpAddress() {
String publicIPAddressName = name + "publicip";
String dnsLabelPrefix = options.getDNSLabelPrefix();
PublicIPAddressProperties.Builder properties = PublicIPAddressProperties.builder();
if (!Strings.isNullOrEmpty(dnsLabelPrefix)) {
properties.dnsSettings(DnsSettings.builder().domainNameLabel(dnsLabelPrefix).build());
variables.put("dnsLabelPrefix", dnsLabelPrefix);
}
properties.publicIPAllocationMethod("Dynamic");
variables.put("publicIPAddressName", publicIPAddressName);
variables.put("publicIPAddressReference", "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]");
ResourceDefinition publicIpAddress = ResourceDefinition.builder()
.name("[variables('publicIPAddressName')]")
.type("Microsoft.Network/publicIPAddresses")
.location(location)
.apiVersion(STORAGE_API_VERSION)
.properties(properties.build())
.build();
resources.add(publicIpAddress);
}
private void addNetworkInterfaceCard() {
List<IpConfiguration> ipConfigurations = new ArrayList<IpConfiguration>();
String ipConfigurationName = name + "ipconfig";
String subnetId = options.getSubnetId();
String vnetName = options.getVirtualNetworkName();
variables.put("ipConfigurationName", ipConfigurationName);
variables.put("subnetReference", subnetId);
IpConfiguration ipConfig = IpConfiguration.create(ipConfigurationName, null, null, null,
IpConfigurationProperties.builder()
.privateIPAllocationMethod("Dynamic")
.publicIPAddress(IdReference.create("[variables('publicIPAddressReference')]"))
.subnet(IdReference.create("[variables('subnetReference')]"))
.build());
ipConfigurations.add(ipConfig);
// Check to see if we have defined a network security group
IdReference networkSecurityGroup = null;
int ports[] = options.getInboundPorts();
if ((ports != null) && (ports.length > 0)) {
networkSecurityGroup = IdReference.create("[variables('networkSecurityGroupNameReference')]");
}
ArrayList<String> depends = new ArrayList<String>(Arrays.asList("[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]"));
NetworkInterfaceCardProperties.Builder networkInterfaceCardPropertiesBuilder = NetworkInterfaceCardProperties.builder();
networkInterfaceCardPropertiesBuilder.ipConfigurations(ipConfigurations);
if (networkSecurityGroup != null) {
networkInterfaceCardPropertiesBuilder.networkSecurityGroup(networkSecurityGroup);
depends.add("[concat('Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]");
}
NetworkInterfaceCardProperties networkInterfaceCardProperties = networkInterfaceCardPropertiesBuilder.build();
String networkInterfaceCardName = name + "nic";
variables.put("networkInterfaceCardName", networkInterfaceCardName);
variables.put("networkInterfaceCardReference", "[resourceId('Microsoft.Network/networkInterfaces',variables('networkInterfaceCardName'))]");
ResourceDefinition networkInterfaceCard = ResourceDefinition.builder()
.name("[variables('networkInterfaceCardName')]")
.type("Microsoft.Network/networkInterfaces")
.location(location)
.apiVersion(STORAGE_API_VERSION)
.dependsOn(depends)
.properties(networkInterfaceCardProperties)
.build();
resources.add(networkInterfaceCard);
}
private void addNetworkSecurityGroup() {
int inboundPorts[] = options.getInboundPorts();
if ((inboundPorts != null) && (inboundPorts.length > 0)) {
variables.put("networkSecurityGroupName", name + "nsg");
variables.put("networkSecurityGroupNameReference", "[resourceId('Microsoft.Network/networkSecurityGroups',variables('networkSecurityGroupName'))]");
List<String> portRanges = simplifyPorts(inboundPorts);
List<NetworkSecurityRule> rules = new ArrayList<NetworkSecurityRule>();
int priority = 1234;
for (String portRange : portRanges) {
NetworkSecurityRuleProperties ruleProperties = NetworkSecurityRuleProperties.builder()
.description("default-allow-port-" + portRange)
.protocol(NetworkSecurityRuleProperties.Protocol.All)
.access(NetworkSecurityRuleProperties.Access.Allow)
.sourcePortRange("*")
.destinationPortRange(portRange)
.sourceAddressPrefix("*")
.destinationAddressPrefix("*")
.priority(priority)
.direction(NetworkSecurityRuleProperties.Direction.Inbound)
.build();
NetworkSecurityRule networkSecurityRule = NetworkSecurityRule.create(
"default-allow-port-" + portRange,
null,
null,
ruleProperties);
rules.add(networkSecurityRule);
priority++;
}
NetworkSecurityGroupProperties networkSecurityGroupProperties = NetworkSecurityGroupProperties.builder()
.securityRules(rules)
.build();
ResourceDefinition networkSecurityGroup = ResourceDefinition.builder()
.name("[variables('networkSecurityGroupName')]")
.type("Microsoft.Network/networkSecurityGroups").location(location)
.apiVersion(STORAGE_API_VERSION)
.properties(networkSecurityGroupProperties)
.build();
resources.add(networkSecurityGroup);
}
}
/**
* Helper function for simplifying an array of ports to a list of ranges as list of strings
* @param ports array of int
* @return list of strings representing ranges
*/
public static List<String> simplifyPorts(int[] ports) {
Preconditions.checkArgument(ports != null && ports.length != 0);
ArrayList<String> output = new ArrayList<String>();
Arrays.sort(ports);
int range_start = ports[0];
int range_end = ports[0];
for (int i = 1; i < ports.length; i++) {
if ((ports[i - 1] == ports[i] - 1) || (ports[i - 1] == ports[i])){
// Range continues.
range_end = ports[i];
}
else {
// Range ends.
output.add(formatRange(range_start, range_end));
range_start = ports[i];
range_end = ports[i];
}
}
// Make sure we get the last range.
output.add(formatRange(range_start, range_end));
return output;
}
private static String formatRange(int start, int finish) {
if (start == finish){
return Integer.toString(start);
}
else {
return String.format("%s-%s", Integer.toString(start), Integer.toString(finish));
}
}
private void addVirtualMachine() {
//Build OS Profile
final String computerName = name + "pc";
variables.put("loginUser", loginUser);
OSProfile.Builder profileBuilder = OSProfile.builder()
.adminUsername(loginUser)
.computerName(computerName);
profileBuilder.adminPassword(loginPassword);
//boolean usePublicKey = options.getPublicKey() != null;
if (keyVaultInUse()) {
OSProfile.LinuxConfiguration configuration = OSProfile.LinuxConfiguration.create("false",
OSProfile.LinuxConfiguration.SSH.create(Arrays.asList(
OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create(
"[concat('/home/',variables('loginUser'),'/.ssh/authorized_keys')]",
"[parameters('publicKeyFromAzureKeyVault')]"
))
));
profileBuilder.linuxConfiguration(configuration);
}
if (!Strings.isNullOrEmpty(options.getCustomData())){
String encodedCustomData = base64().encode(options.getCustomData().getBytes());
profileBuilder.customData(encodedCustomData);
}
OSProfile osProfile = profileBuilder.build();
//Build OsDisk
final String storageAccountContainerName = name + "vhds";
variables.put("storageAccountContainerName", storageAccountContainerName);
final String osDiskName = name + "osdisk";
variables.put("osDiskName", osDiskName);
boolean usingMarketplaceImage = true;
String cusotomImageUri = "";
// Handle custom image case if description starts with CUSTOM_IMAGE_PREFIX
String vhd1 = template.getImage().getProviderId();
String description = template.getImage().getDescription();
if (description.substring(0, CUSTOM_IMAGE_PREFIX.length()).equals(CUSTOM_IMAGE_PREFIX)) {
String storageName = template.getImage().getVersion();
cusotomImageUri = vhd1;
cusotomImageUri = "https://" + storageName + ".blob.core.windows.net/system/Microsoft.Compute/Images/" + AzureComputeImageExtension.CONTAINER_NAME + "/" + cusotomImageUri;
}
if (!cusotomImageUri.isEmpty()) {
usingMarketplaceImage = false;
}
OSDisk osDisk = getOsDisk("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net/',variables('storageAccountContainerName'),'/',variables('osDiskName'),'.vhd')]", cusotomImageUri);
//Create Data Disk(s) and add to list
final String dataDiskName = name + "datadisk";
variables.put("dataDiskName", dataDiskName);
List<DataDisk> dataDisks = new ArrayList<DataDisk>();
DataDisk dataDisk = DataDisk.builder()
.name("[variables('dataDiskName')]")
.diskSizeGB(azureComputeConstants.azureDefaultDataDiskSizeProperty())
.lun(0)
.vhd(
VHD.create("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net/',variables('storageAccountContainerName'),'/',variables('dataDiskName'),'.vhd')]")
)
.createOption("Empty")
.build();
dataDisks.add(dataDisk);
//Create Storage Profile
StorageProfile.Builder storageProfileBuilder = StorageProfile.builder()
.osDisk(osDisk)
.dataDisks(dataDisks);
if (usingMarketplaceImage) {
//Build Image Reference if marketplace image is used
ImageReference imageReference = getImageReference(template.getImage().getProviderId(),
template.getImage().getName(),
template.getImage().getVersion());
storageProfileBuilder.imageReference(imageReference);
}
StorageProfile storageProfile = storageProfileBuilder.build();
//Create Network Profile for this VM (links to network interface cards)
NetworkProfile networkProfile = NetworkProfile.create(
Arrays.asList(
IdReference.create("[variables('networkInterfaceCardReference')]")
));
//Boot Diagnostics
DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(
DiagnosticsProfile.BootDiagnostics.builder()
.enabled(true)
.storageUri("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net')]")
.build());
//Build VirtualMachine properties based on above properties.
final String vmSize = template.getHardware().getId();
HardwareProfile hw = HardwareProfile.create(vmSize);
VirtualMachineProperties properties = VirtualMachineProperties.builder()
.hardwareProfile(hw)
.osProfile(osProfile)
.storageProfile(storageProfile)
.networkProfile(networkProfile)
.diagnosticsProfile(diagnosticsProfile)
.build();
String tagString = Joiner.on(",").join(Lists.newArrayList(tags));
if (tagString.isEmpty())
tagString = "jclouds";
userMetaData.put("tags", tagString);
variables.put("virtualMachineName", name);
ResourceDefinition virtualMachine = ResourceDefinition.builder()
.name("[variables('virtualMachineName')]")
.type("Microsoft.Compute/virtualMachines")
.location(location)
.apiVersion("2015-06-15")
.dependsOn(Arrays.asList("[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
"[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceCardName'))]"))
.tags(userMetaData)
.properties(properties)
.build();
resources.add(virtualMachine);
}
private ImageReference getImageReference(String publisher, String offer, String sku) {
return ImageReference.builder()
.publisher(publisher)
.offer(offer)
.sku(sku)
.version("latest")
.build();
}
private OSDisk getOsDisk(String vhdUri, String imageUri) {
OSDisk.Builder builder = OSDisk.builder();
builder.name("[variables('osDiskName')]");
builder.caching("ReadWrite");
builder.createOption("FromImage");
builder.vhd(VHD.create(vhdUri));
if (!imageUri.isEmpty()) {
builder.osType("Linux");
builder.image(VHD.create(imageUri));
}
return builder.build();
}
private boolean keyVaultInUse(){
return !Strings.isNullOrEmpty(options.getKeyVaultIdAndSecret());
}
/**
* Generates a valid storage account
*
* Storage account names must be between 3 and 24 characters in length and may contain numbers and lowercase letters only.
*
* @param name the node name
* @return the storage account name starting from a sanitized name (with only numbers and lowercase letters only ).
* If sanitized name is between 3 and 24 characters, storage account name is equals to sanitized name.
* If sanitized name is less than 3 characters, storage account is sanitized name plus 4 random chars.
* If sanitized name is more than 24 characters, storage account is first 10 chars of sanitized name plus 4 random chars plus last 10 chars of sanitized name.
*/
private static String generateStorageAccountName(String name) {
String storageAccountName = name.replaceAll("[^a-z0-9]", "");
int nameLength = storageAccountName.length();
if (nameLength >= 3 && nameLength <= 24) {
return storageAccountName;
}
String random = UUID.randomUUID().toString().replaceAll("[^a-z0-9]", "").substring(0, 4);
if (nameLength < 3) {
storageAccountName = new StringBuilder().append(storageAccountName).append(random).toString();
}
if (nameLength > 24) {
storageAccountName = shorten(storageAccountName, random);
}
return storageAccountName;
}
private static String shorten(String storageAccountName, String random) {
String prefix = storageAccountName.substring(0, 10);
String suffix = storageAccountName.substring(storageAccountName.length() - 10, storageAccountName.length());
return String.format("%s%s%s", prefix, random, suffix);
}
}

View File

@ -20,7 +20,6 @@ import java.util.EnumSet;
public class GetEnumValue {
@SuppressWarnings("unchecked")
public static <T extends Enum<T>> Enum<T> fromValueOrDefault(String text, Enum<T> defaultValue) {
if (text != null) {
EnumSet<T> elements = EnumSet.allOf(defaultValue.getDeclaringClass());

View File

@ -16,21 +16,26 @@
*/
package org.jclouds.azurecompute.arm.compute;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.RunScriptOnNodesException;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.providers.ProviderMetadata;
@ -41,29 +46,18 @@ import org.jclouds.scriptbuilder.statements.login.AdminAccess;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
/**
* Live tests for the {@link org.jclouds.compute.ComputeService} integration.
*/
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeServiceLiveTest")
public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
protected int nonBlockDurationSeconds = 30;
public AzureComputeServiceLiveTest() {
provider = "azurecompute-arm";
nonBlockDurationSeconds = 300;
group = "az-u";
}
@Override
@ -78,21 +72,20 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Override
protected ProviderMetadata createProviderMetadata() {
AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
return pm;
return AzureComputeProviderMetadata.builder().build();
}
@Override
protected Properties setupProperties() {
Properties properties = super.setupProperties();
long scriptTimeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES);
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + "");
properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + "");
properties.setProperty(TIMEOUT_PORT_OPEN, scriptTimeout + "");
properties.setProperty(TIMEOUT_NODE_TERMINATED, scriptTimeout + "");
properties.setProperty(TIMEOUT_NODE_SUSPENDED, scriptTimeout + "");
properties.put(RESOURCE_GROUP_NAME, "a4");
properties.put(TEMPLATE, "locationId=westeurope");
String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout);
properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout);
properties.put(RESOURCE_GROUP_NAME, "jc");
properties.put(PROPERTY_REGIONS, "eastus");
properties.put(IMAGE_PUBLISHERS, "Canonical");
AzureLiveTestUtils.defaultProperties(properties);
@ -102,24 +95,27 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
}
@Override
protected Template refreshTemplate() {
return this.template = addRunScriptToTemplate(this.buildTemplate(this.client.templateBuilder()));
protected TemplateBuilder templateBuilder() {
return super.templateBuilder().options(
authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(keyPair.get("private")));
}
@Override
protected Template addRunScriptToTemplate(Template template) {
template.getOptions().runScript(Statements.newStatementList(new Statement[]{AdminAccess.standard(), Statements.exec("sleep 50"), InstallJDK.fromOpenJDK()}));
template.getOptions().runScript(
Statements.newStatementList(new Statement[] { AdminAccess.standard(), Statements.exec("sleep 50"),
InstallJDK.fromOpenJDK() }));
return template;
}
@Override
@Test( enabled = false)
protected void weCanCancelTasks(NodeMetadata node) throws InterruptedException, ExecutionException {
return;
protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
// User metadata not yet supported
}
@Override
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(String group, OperatingSystem os, LoginCredentials creds) throws RunScriptOnNodesException {
return this.client.runScriptOnNodesMatching(NodePredicates.runningInGroup(group), Statements.newStatementList(Statements.exec("sleep 50"), InstallJDK.fromOpenJDK()), org.jclouds.compute.options.TemplateOptions.Builder.overrideLoginCredentials(creds).nameTask("runScriptWithCreds"));
protected void checkTagsInNodeEquals(NodeMetadata node, ImmutableSet<String> tags) {
// Tags not yet supported
}
}

View File

@ -16,33 +16,30 @@
*/
package org.jclouds.azurecompute.arm.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.domain.Region;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
@Test(groups = "live", testName = "AzureTemplateBuilderLiveTest")
public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
public String azureGroup;
@Override
protected Set<String> getIso3166Codes() {
return ImmutableSet.of("US-IA", "US-VA", "US-IL", "US-TX", "US-CA", "IE", "NL", "HK", "SG", "JP-11", "JP-27", "BR", "AU-NSW", "AU-VIC", "IN-GA", "IN-TN", "IN-MH", "CN-SH", "CN-BJ", "CA-ON", "CA-QC");
}
public AzureTemplateBuilderLiveTest() {
provider = "azurecompute-arm";
@ -55,23 +52,33 @@ public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
@Override
protected ProviderMetadata createProviderMetadata() {
AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
return pm;
return AzureComputeProviderMetadata.builder().build();
}
@Override
protected Properties setupProperties() {
azureGroup = "jc" + System.getProperty("user.name").substring(0, 3);
Properties properties = super.setupProperties();
long scriptTimeout = TimeUnit.MILLISECONDS.convert(20, TimeUnit.MINUTES);
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + "");
properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + "");
properties.put(RESOURCE_GROUP_NAME, azureGroup);
properties.put(RESOURCE_GROUP_NAME, "jc");
AzureLiveTestUtils.defaultProperties(properties);
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
return properties;
}
@Override
@Test
public void testDefaultTemplateBuilder() throws IOException {
Template defaultTemplate = view.getComputeService().templateBuilder().build();
assertTrue(defaultTemplate.getImage().getOperatingSystem().getVersion().matches("1[45]\\.[01][04]\\.[0-9]-LTS"),
"Version mismatch, expected dd.dd.d-LTS, found: " + defaultTemplate.getImage().getOperatingSystem().getVersion());
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}
@Override
protected Set<String> getIso3166Codes() {
return Region.iso3166Codes();
}
}

View File

@ -16,29 +16,35 @@
*/
package org.jclouds.azurecompute.arm.compute.extensions;
import com.google.inject.Module;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.config.AzureComputeProperties;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.config.ComputeServiceProperties;
import org.jclouds.compute.extensions.internal.BaseImageExtensionLiveTest;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.ComputeTestUtils;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.internal.BaseImageExtensionLiveTest;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import com.google.inject.Module;
/**
* Live tests for the {@link org.jclouds.compute.extensions.ImageExtension} integration.
* Live tests for the {@link org.jclouds.compute.extensions.ImageExtension}
* integration.
*/
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeImageExtensionLiveTest")
public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTest {
@ -57,34 +63,33 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
@Override
protected Properties setupProperties() {
Properties properties = super.setupProperties();
long scriptTimeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES);
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + "");
properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + "");
properties.setProperty(TIMEOUT_PORT_OPEN, scriptTimeout + "");
properties.setProperty(TIMEOUT_NODE_TERMINATED, scriptTimeout + "");
properties.setProperty(TIMEOUT_NODE_SUSPENDED, scriptTimeout + "");
properties.put(RESOURCE_GROUP_NAME, "jcloudsgroup");
properties.put(ComputeServiceProperties.POLL_INITIAL_PERIOD, 1000);
properties.put(ComputeServiceProperties.POLL_MAX_PERIOD, 10000);
properties.setProperty(AzureComputeProperties.OPERATION_TIMEOUT, "46000000");
properties.setProperty(AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD, "5");
properties.setProperty(AzureComputeProperties.OPERATION_POLL_MAX_PERIOD, "15");
properties.setProperty(AzureComputeProperties.TCP_RULE_FORMAT, "tcp_%s-%s");
properties.setProperty(AzureComputeProperties.TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout);
properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout);
properties.put(RESOURCE_GROUP_NAME, "jc");
properties.put(PROPERTY_REGIONS, "eastus");
properties.put(IMAGE_PUBLISHERS, "Canonical");
AzureLiveTestUtils.defaultProperties(properties);
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
return properties;
}
@Override
protected ProviderMetadata createProviderMetadata() {
AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
return pm;
return AzureComputeProviderMetadata.builder().build();
}
@Override
public TemplateBuilder getNodeTemplate() {
Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
return super.getNodeTemplate().options(
authorizePublicKey(keyPair.get("public"))
.overrideLoginPrivateKey(keyPair.get("private")));
}
}

View File

@ -16,30 +16,19 @@
*/
package org.jclouds.azurecompute.arm.features;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import java.util.List;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.Deployment;
import org.jclouds.azurecompute.arm.domain.Deployment.ProvisioningState;
import org.jclouds.azurecompute.arm.domain.DeploymentBody;
import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.internal.TemplateImpl;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.util.Predicates2;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
@ -49,10 +38,6 @@ import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.net.UrlEscapers;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
@Test(testName = "DeploymentApiLiveTest", singleThreaded = true)
public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
@ -112,37 +97,6 @@ public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
return body;
}
private Template getTemplate(TemplateOptions options) {
Location provider = (new LocationBuilder()).scope(LocationScope.PROVIDER).id("azurecompute-arm").description("azurecompute-arm").build();
Location region = (new LocationBuilder()).scope(LocationScope.REGION).id(LOCATION).description("West Europe").parent(provider).build();
OperatingSystem os = OperatingSystem.builder()
.family(OsFamily.UBUNTU)
.description("14.04.3-LTS")
.is64Bit(true)
.build();
Image image = (new ImageBuilder())
.id("UbuntuServer14.04.3-LTS")
.providerId("Canonical")
.name("UbuntuServer")
.description("14.04.3-LTS")
.version("14.04.3-LTS")
.operatingSystem(os)
.status(Image.Status.AVAILABLE)
.location(region)
.build();
Hardware hardware = (new HardwareBuilder()).id("Standard_A0").build();
return new TemplateImpl(image, hardware, region, options);
}
private DeploymentTemplateBuilder getDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
Template template = getTemplate(options);
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroupName, deploymentName, template);
return templateBuilder;
}
@Test
public void testValidate(){
Deployment deploymentInvalid = null;
@ -168,12 +122,40 @@ public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
AzureTemplateOptions options = new AzureTemplateOptions();
options.authorizePublicKey(rsakey);
options.subnetId(subnetId);
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
String deploymentTemplate = "{\n" +
" \"id\": \"/subscriptions/04f7ec88-8e28-41ed-8537-5e17766001f5/resourceGroups/jims216group/providers/Microsoft.Resources/deployments/jcdep1458344383064\",\n" +
" \"name\": \"jcdep1458344383064\",\n" +
" \"properties\": {\n" +
" \"parameters\": {\n" +
" \"newStorageAccountName\": {\n" +
" \"type\": \"String\",\n" +
" \"value\": \"jcres1458344383064\"\n" +
" },\n" +
" \"storageAccountType\": {\n" +
" \"type\": \"String\",\n" +
" \"value\": \"Standard_LRS\"\n" +
" },\n" +
" \"location\": {\n" +
" \"type\": \"String\",\n" +
" \"value\": \"West US\"\n" +
" }\n" +
" },\n" +
" \"mode\": \"Incremental\",\n" +
" \"provisioningState\": \"Accepted\",\n" +
" \"timestamp\": \"2016-03-18T23:39:47.3048037Z\",\n" +
" \"duration\": \"PT2.4433028S\",\n" +
" \"correlationId\": \"8dee9711-8632-4948-9fe6-368bb75e6438\",\n" +
" \"providers\": [{\n" +
" \"namespace\": \"Microsoft.Storage\",\n" +
" \"resourceTypes\": [{\n" +
" \"resourceType\": \"storageAccounts\",\n" +
" \"locations\": [\"westus\"]\n" +
" }]\n" +
" }],\n" +
" \"dependencies\": []\n" +
" }\n" +
"}";
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
Deployment deploymentValid = api().validate(deploymentName, deploymentTemplate);

View File

@ -1,287 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.features;
import java.util.List;
import java.util.Map;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.DeploymentBody;
import org.jclouds.azurecompute.arm.domain.ImageReference;
import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.domain.StorageService;
import org.jclouds.azurecompute.arm.domain.StorageService.StorageServiceProperties;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.internal.TemplateImpl;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@Test(groups = "unit", testName = "DeploymentTemplateBuilderTest", singleThreaded = true)
public class DeploymentTemplateBuilderTest extends BaseAzureComputeApiMockTest {
final String group = "jcgroup";
final String vnetName = group + "virtualnetwork";
final String subnetId = "";
@Test
public void testResourceGroup() {
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
List<ResourceDefinition> resources = deploymentBody.template().resources();
Map<String, String> variables = deploymentBody.template().variables();
ResourceDefinition resource = getResourceByType(resources, "Microsoft.Storage/storageAccounts");
StorageServiceProperties properties = (StorageServiceProperties) resource.properties();
assertEquals(properties.accountType(), StorageService.AccountType.Standard_LRS);
assertTrue(variables.containsKey(parseVariableName(resource.name())));
}
@Test
void testPublicIpAddress() {
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
List<ResourceDefinition> resources = deploymentBody.template().resources();
Map<String, String> variables = deploymentBody.template().variables();
ResourceDefinition resource = getResourceByType(resources, "Microsoft.Network/publicIPAddresses");
PublicIPAddressProperties properties = (PublicIPAddressProperties) resource.properties();
assertEquals(properties.publicIPAllocationMethod(), "Dynamic");
assertTrue(variables.containsKey(parseVariableName(resource.name())));
}
@Test
void testNetworkInterfaceCard() {
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
List<ResourceDefinition> resources = deploymentBody.template().resources();
Map<String, String> variables = deploymentBody.template().variables();
ResourceDefinition resource = getResourceByType(resources, "Microsoft.Network/networkInterfaces");
NetworkInterfaceCardProperties properties = (NetworkInterfaceCardProperties) resource.properties();
List<IpConfiguration> ipConfigs = properties.ipConfigurations();
assertTrue(ipConfigs.size() > 0);
IpConfigurationProperties ipProperties = ipConfigs.get(0).properties();
assertEquals(ipProperties.privateIPAllocationMethod(), "Dynamic");
assertNotNull(ipProperties.publicIPAddress());
assertNotNull(ipProperties.subnet());
assertTrue(variables.containsKey(parseVariableName(resource.name())));
}
@Test
void testVirtualMachine() {
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
Template template = builder.getTemplate();
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
List<ResourceDefinition> resources = deploymentBody.template().resources();
Map<String, String> variables = deploymentBody.template().variables();
ResourceDefinition resource = getResourceByType(resources, "Microsoft.Compute/virtualMachines");
assertNotNull(resource);
VirtualMachineProperties properties = (VirtualMachineProperties) resource.properties();
assertEquals(properties.hardwareProfile().vmSize(), template.getHardware().getId());
ImageReference image = properties.storageProfile().imageReference();
assertEquals(image.publisher(), template.getImage().getProviderId());
assertEquals(image.offer(), template.getImage().getName());
assertEquals(image.sku(), template.getImage().getVersion());
assertEquals(image.version(), "latest");
assertTrue(variables.containsKey(parseVariableName(resource.name())));
}
@Test
void testAddStorageResourceWhenNameIsLongerThan24Chars() {
String name = "thishasmorethan24characters";
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions(name);
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
assertTrue(Iterables.contains(deploymentBody.template().variables().keySet(), "storageAccountName"));
String storageAccountName = deploymentBody.template().variables().get("storageAccountName");
assertEquals(storageAccountName.length(), 24);
assertEquals(storageAccountName.substring(0, 10), "thishasmor");
assertEquals(storageAccountName.substring(storageAccountName.length() - 10, storageAccountName.length()), "characters");
}
@Test
void testAddStorageResourceWhenNameIsExactly24Chars() {
String name = "ithasexactly24characters";
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions(name);
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
assertTrue(Iterables.contains(deploymentBody.template().variables().keySet(), "storageAccountName"));
assertEquals(deploymentBody.template().variables().get("storageAccountName").length(), 24);
assertEquals(deploymentBody.template().variables().get("storageAccountName"), name);
}
@Test
void testAddStorageResourceWhenNameIsLessThan3Chars() {
String name = "3c";
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions(name);
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
assertTrue(Iterables.contains(deploymentBody.template().variables().keySet(), "storageAccountName"));
assertEquals(deploymentBody.template().variables().get("storageAccountName").length(), 6);
assertEquals(deploymentBody.template().variables().get("storageAccountName").substring(0, 2), name);
}
@Test
void testCustomOptions(){
final String dnsLabelPrefix = "mydnslabel";
final String customData = "echo customData";
final String customData64 = "ZWNobyBjdXN0b21EYXRh";
final String keyvaultString = "/url/to/vault/:publickeysecret";
AzureTemplateOptions options = new AzureTemplateOptions()
.customData(customData)
.DNSLabelPrefix(dnsLabelPrefix)
.keyVaultIdAndSecret(keyvaultString);
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
assertEquals(options.as(AzureTemplateOptions.class).getCustomData(), customData);
assertEquals(options.getDNSLabelPrefix(), dnsLabelPrefix);
assertEquals(options.as(AzureTemplateOptions.class).getKeyVaultIdAndSecret(), keyvaultString);
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
List<ResourceDefinition> resources = deploymentBody.template().resources();
ResourceDefinition publicIpResource = getResourceByType(resources, "Microsoft.Network/publicIPAddresses");
assertNotNull(publicIpResource);
PublicIPAddressProperties ipProperties = (PublicIPAddressProperties) publicIpResource.properties();
assertEquals(ipProperties.dnsSettings().domainNameLabel(), dnsLabelPrefix);
ResourceDefinition vmResource = getResourceByType(resources, "Microsoft.Compute/virtualMachines");
assertNotNull(vmResource);
VirtualMachineProperties virtualMachineProperties = (VirtualMachineProperties) vmResource.properties();
assertEquals(virtualMachineProperties.osProfile().customData(), customData64);
//populated when keyvault is used to get public key.
assertNotNull(virtualMachineProperties.osProfile().linuxConfiguration().ssh().publicKeys());
}
@Test(expectedExceptions = IllegalArgumentException.class)
void testSimplifyPortsWithPortsNull() {
int[] ports = null;
DeploymentTemplateBuilder.simplifyPorts(ports);
}
@Test(expectedExceptions = IllegalArgumentException.class)
void testSimplifyPortsWithPortsEmpty() {
int[] ports = new int[0];
DeploymentTemplateBuilder.simplifyPorts(ports);
}
@Test
void testSimplifyPorts() {
int[] ports = {8084, 22, 8081, 8080, 8082};
List<String> ranges = DeploymentTemplateBuilder.simplifyPorts(ports);
assertEquals(ranges.size(), 3);
assertEquals(ranges.get(0), "22");
assertEquals(ranges.get(1), "8080-8082");
assertEquals(ranges.get(2), "8084");
}
private Template getMockTemplate(TemplateOptions options) {
((AzureTemplateOptions)options).virtualNetworkName(vnetName);
((AzureTemplateOptions)options).subnetId(subnetId);
Location provider = (new LocationBuilder()).scope(LocationScope.PROVIDER).id("azurecompute-arm").description("azurecompute-arm").build();
Location region = (new LocationBuilder()).scope(LocationScope.REGION).id("northeurope").description("North Europe").parent(provider).build();
OperatingSystem os = OperatingSystem.builder().name("osName").version("osVersion").description("osDescription").arch("X86_32").build();
//Note that version is set to "latest"
Image image = (new ImageBuilder()).id("imageId").providerId("imageId").name("imageName").description("imageDescription").version("sku").operatingSystem(os).status(Image.Status.AVAILABLE).location(region).build();
Hardware hardware = (new HardwareBuilder()).id("Standard_A0").build();
return new TemplateImpl(image, hardware, region, options);
}
private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithEmptyOptions() {
return getMockDeploymentTemplateBuilderWithEmptyOptions("mydeployment");
}
private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithEmptyOptions(String name) {
AzureTemplateOptions options = new AzureTemplateOptions();
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
Template template = getMockTemplate(options);
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(group, name, template);
return templateBuilder;
}
private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
return getMockDeploymentTemplateBuilderWithOptions("mydeployment", options);
}
private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithOptions(String name, TemplateOptions options) {
((AzureTemplateOptions)options).virtualNetworkName(vnetName);
((AzureTemplateOptions)options).subnetId(subnetId);
Template template = getMockTemplate(options);
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(group, name, template);
return templateBuilder;
}
private ResourceDefinition getResourceByType(List<ResourceDefinition> resources, String type) {
for (ResourceDefinition r : resources) {
if (r.type().equals(type)) {
return r;
}
}
Assert.fail("Resource with type: " + type + " not found");
return null;
}
private String parseVariableName(String variable) {
String[] parts = variable.split("\'");
assertTrue(parts.length == 3);
return parts[1];
}
}

View File

@ -83,8 +83,6 @@ public class NetworkSecurityGroupApiMockTest extends BaseAzureComputeApiMockTest
}
public void getNetworkSecurityGroup() throws InterruptedException {
NetworkSecurityGroup nsg = createGroup();
server.enqueue(jsonResponse("/networksecuritygroupget.json").setResponseCode(200));
final NetworkSecurityGroupApi nsgApi = api.getNetworkSecurityGroupApi(resourcegroup);

View File

@ -147,8 +147,7 @@ public class PublicIPAddressApiMockTest extends BaseAzureComputeApiMockTest {
PublicIPAddressProperties properties = PublicIPAddressProperties.create(null, null, "Static", 4, null,
DnsSettings.create("foobar", "foobar.northeurope.cloudapp.azure.com", null));
PublicIPAddress ip = ipApi.createOrUpdate(publicIpName, location, tags, properties);
ipApi.createOrUpdate(publicIpName, location, tags, properties);
}
public void deletePublicIPAddress() throws InterruptedException {

View File

@ -31,7 +31,6 @@ public class ResourceProviderAPIMockTest extends BaseAzureComputeApiMockTest {
final String apiVersion = "2015-01-01";
final String resource = "Microsoft.Compute";
private final String vm_resource = "virtualMachines";
public void getPublicIPAddressInfo() throws InterruptedException {
server.enqueue(jsonResponse("/getresourceprovidermetadata.json"));

View File

@ -235,41 +235,6 @@ public class StorageAccountApiMockTest extends BaseAzureComputeApiMockTest {
"/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE?api-version=2015-06-15");
}
private StorageService getStrorageAccount() {
DateService DATE_SERVICE = new SimpleDateFormatDateService();
Map<String, String> endpoints = new HashMap<String, String>();
endpoints.put("blob", "https://TESTSTORAGE.blob.core.windows.net/");
endpoints.put("file", "https://TESTSTORAGE.file.core.windows.net/");
endpoints.put("queue", "https://TESTSTORAGE.queue.core.windows.net/");
endpoints.put("table", "https://TESTSTORAGE.table.core.windows.net/");
Map<String, String> secondaryEndpoints = new HashMap<String, String>();
secondaryEndpoints.put("blob", "https://TESTSTORAGE-secondary.blob.core.windows.net/");
secondaryEndpoints.put("queue", "https://TESTSTORAGE-secondary.queue.core.windows.net/");
secondaryEndpoints.put("table", "https://TESTSTORAGE-secondary.table.core.windows.net/");
String location = "westus";
String secondaryLocation = "eastus";
final StorageService.StorageServiceProperties props = StorageService.StorageServiceProperties.create(
StorageService.AccountType.Standard_RAGRS,
DATE_SERVICE.iso8601DateOrSecondsDateParse("2016-02-24T13:04:45.0890883Z"),
endpoints,
location,
StorageService.Status.Succeeded,
secondaryEndpoints, secondaryLocation,
StorageService.RegionStatus.Available,
StorageService.RegionStatus.Available);
final Map<String, String> tags = ImmutableMap.of(
"key1", "value1",
"key2", "value2");
return StorageService.create(
"/subscriptions/SUBSCRIPTIONID/resourceGroups/resourceGroup" +
"/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE",
"TESTSTORAGE", location, tags, null, props);
}
private List<StorageService> expected() throws MalformedURLException {
DateService DATE_SERVICE = new SimpleDateFormatDateService();
Map<String, String> endpoints = new HashMap<String, String>();

View File

@ -16,18 +16,17 @@
*/
package org.jclouds.azurecompute.arm.features;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
import org.testng.annotations.Test;
import java.util.List;
import static com.google.common.collect.Iterables.isEmpty;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.util.List;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "SubnetApiMockTest", singleThreaded = true)
@ -135,6 +134,6 @@ public class SubnetApiMockTest extends BaseAzureComputeApiMockTest {
assertFalse(status);
String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Network/virtualNetworks/%s/subnets/%s?%s", subscriptionid, resourcegroup, virtualNetwork, subnetName, apiVersion);
RecordedRequest rr = assertSent(server, "DELETE", path);
assertSent(server, "DELETE", path);
}
}

View File

@ -1,281 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.features;
import java.net.URI;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.Deployment;
import org.jclouds.azurecompute.arm.domain.DeploymentBody;
import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.internal.TemplateImpl;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.net.UrlEscapers;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@Test(groups = "live", testName = "TemplateToDeploymentTemplateLiveTest", singleThreaded = true)
public class TemplateToDeploymentTemplateLiveTest extends BaseAzureComputeApiLiveTest {
private int maxTestDuration = 400;
private int pollingInterval = 3; // how frequently to poll for create status
private String resourceGroupName;
private String deploymentName;
private String vnetName;
private String subnetId;
private String virtualNetworkName;
@BeforeClass
@Override
public void setup() {
super.setup();
resourceGroupName = String.format("rg-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
assertNotNull(createResourceGroup(resourceGroupName));
virtualNetworkName = String.format("vn-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
//Subnets belong to a virtual network so that needs to be created first
VirtualNetwork vn = createDefaultVirtualNetwork(resourceGroupName, virtualNetworkName, "10.2.0.0/16", LOCATION);
assertNotNull(vn);
vnetName = vn.name();
//Subnet needs to be up & running before NIC can be created
String subnetName = String.format("s-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
Subnet subnet = createDefaultSubnet(resourceGroupName, subnetName, virtualNetworkName, "10.2.0.0/23");
assertNotNull(subnet);
assertNotNull(subnet.id());
subnetId = subnet.id();
}
@AfterClass
@Override
protected void tearDown() {
super.tearDown();
URI uri = deleteResourceGroup(resourceGroupName);
assertResourceDeleted(uri);
}
@Test
public void testValidateDeploymentTemplateLinuxNodeWithOptions() {
Long now = System.currentTimeMillis();
deploymentName = "jc" + now;
AzureTemplateOptions options = new AzureTemplateOptions();
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
options.inboundPorts(22, 8080);
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
//Validates that template is syntactically correct
Deployment deployment = api().validate(deploymentName, deploymentTemplate);
assertNotNull(deployment);
}
@Test
public void testValidateDeploymentTemplateLinuxNode() {
Long now = System.currentTimeMillis();
deploymentName = "jc" + now;
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithEmptyOptions();
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
//Validates that template is syntactically correct
Deployment deployment = api().validate(deploymentName, deploymentTemplate);
assertNotNull(deployment);
}
@Test
public void testValidateDeploymentTemplateWithCustomOptions() {
Long now = System.currentTimeMillis();
deploymentName = "jc" + now;
String rsakey = new String("ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmfk/QSF0pvnrpdz+Ah2KulGruKU+8FFBdlw938MpOysRdmp7uwpH6Z7+5VNGNdxFIAyc/W3UaZXF9hTsU8+78TlwkZpsr2mzU+ycu37XLAQ8Uv7hjsAN0DkKKPrZ9lgUUfZVKV/8E/JIAs03gIbL6zO3y7eYJQ5fNeZb+nji7tQT+YLpGq/FDegvraPKVMQbCSCZhsHyWhdPLyFlu9/30npZ0ahYOPI/KyZxFDtM/pHp88+ZAk9Icq5owaLRWcJQqrBGWqjbZnHtjdDqvHZ+C0wPhdJZPyfkHOrSYTwSQBXfX4JLRRCz3J1jf62MbQWT1o6Y4JEs1ZP1Skxu6zR96Q== mocktest");
TemplateOptions options = new AzureTemplateOptions()
.DNSLabelPrefix("mydnslabel")
.virtualNetworkAddressPrefix("10.0.0.0/20")
.subnetAddressPrefix("10.0.0.0/25")
.authorizePublicKey(rsakey);
((AzureTemplateOptions)options).virtualNetworkName(vnetName);
((AzureTemplateOptions)options).subnetId(subnetId);
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
Deployment deployment = api().validate(deploymentName, deploymentTemplate);
assertNotNull(deployment);
}
@Test
public void testValidateDeploymentTemplateLinuxNodeWithSSH() {
Long now = System.currentTimeMillis();
deploymentName = "jc" + now;
String rsakey = new String("ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmfk/QSF0pvnrpdz+Ah2KulGruKU+8FFBdlw938MpOysRdmp7uwpH6Z7+5VNGNdxFIAyc/W3UaZXF9hTsU8+78TlwkZpsr2mzU+ycu37XLAQ8Uv7hjsAN0DkKKPrZ9lgUUfZVKV/8E/JIAs03gIbL6zO3y7eYJQ5fNeZb+nji7tQT+YLpGq/FDegvraPKVMQbCSCZhsHyWhdPLyFlu9/30npZ0ahYOPI/KyZxFDtM/pHp88+ZAk9Icq5owaLRWcJQqrBGWqjbZnHtjdDqvHZ+C0wPhdJZPyfkHOrSYTwSQBXfX4JLRRCz3J1jf62MbQWT1o6Y4JEs1ZP1Skxu6zR96Q== mocktest");
AzureTemplateOptions options = new AzureTemplateOptions();
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
options.authorizePublicKey(rsakey);
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
Deployment deployment = api().validate(deploymentName, deploymentTemplate);
assertNotNull(deployment);
}
@Test
public void testCreateDeploymentTemplateLinuxNode() {
Long now = System.currentTimeMillis();
deploymentName = "jc" + now;
String rsakey = new String("ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmfk/QSF0pvnrpdz+Ah2KulGruKU+8FFBdlw938MpOysRdmp7uwpH6Z7+5VNGNdxFIAyc/W3UaZXF9hTsU8+78TlwkZpsr2mzU+ycu37XLAQ8Uv7hjsAN0DkKKPrZ9lgUUfZVKV/8E/JIAs03gIbL6zO3y7eYJQ5fNeZb+nji7tQT+YLpGq/FDegvraPKVMQbCSCZhsHyWhdPLyFlu9/30npZ0ahYOPI/KyZxFDtM/pHp88+ZAk9Icq5owaLRWcJQqrBGWqjbZnHtjdDqvHZ+C0wPhdJZPyfkHOrSYTwSQBXfX4JLRRCz3J1jf62MbQWT1o6Y4JEs1ZP1Skxu6zR96Q== mocktest");
AzureTemplateOptions options = new AzureTemplateOptions();
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
options.authorizePublicKey(rsakey);
options.inboundPorts(22, 8080);
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
//creates an actual VM using deployment template
Deployment deployment = api().create(deploymentName, deploymentTemplate);
Deployment.ProvisioningState state = Deployment.ProvisioningState.fromValue(deployment.properties().provisioningState());
int testTime = 0;
while (testTime < maxTestDuration) {
if ((state == Deployment.ProvisioningState.SUCCEEDED) ||
(state == Deployment.ProvisioningState.CANCELED) ||
(state == Deployment.ProvisioningState.DELETED) ||
(state == Deployment.ProvisioningState.FAILED)) {
break;
}
// sleep a little bit before polling, timeout after a fixed time
try {
Thread.sleep(pollingInterval * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
testTime += pollingInterval;
deployment = api().get(deploymentName);
assertNotNull(deployment);
state = Deployment.ProvisioningState.fromValue(deployment.properties().provisioningState());
}
assertTrue(state == Deployment.ProvisioningState.SUCCEEDED);
assertNotNull(deployment);
}
private Template getTemplate(TemplateOptions options) {
Location provider = (new LocationBuilder()).scope(LocationScope.PROVIDER).id("azurecompute-arm").description("azurecompute-arm").build();
Location region = (new LocationBuilder()).scope(LocationScope.REGION).id(LOCATION).description(LOCATIONDESCRIPTION).parent(provider).build();
OperatingSystem os = OperatingSystem.builder()
.family(OsFamily.UBUNTU)
.description("14.04.3-LTS")
.is64Bit(true)
.build();
Image image = (new ImageBuilder())
.id("UbuntuServer14.04.3-LTS")
.providerId("Canonical")
.name("UbuntuServer")
.description("14.04.3-LTS")
.version("14.04.3-LTS")
.operatingSystem(os)
.status(Image.Status.AVAILABLE)
.location(region)
.build();
Hardware hardware = (new HardwareBuilder()).id("Standard_A0").build();
return new TemplateImpl(image, hardware, region, options);
}
private DeploymentTemplateBuilder getDeploymentTemplateBuilderWithEmptyOptions() {
AzureTemplateOptions options = new AzureTemplateOptions();
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
Template template = getTemplate(options);
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroupName, deploymentName, template);
return templateBuilder;
}
private DeploymentTemplateBuilder getDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
Template template = getTemplate(options);
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroupName, deploymentName, template);
return templateBuilder;
}
private DeploymentApi api() {
return api.getDeploymentApi(resourceGroupName);
}
}

View File

@ -16,6 +16,10 @@
*/
package org.jclouds.azurecompute.arm.features;
import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
@ -41,6 +45,7 @@ import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.domain.VHD;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
import org.testng.Assert;
@ -48,16 +53,9 @@ 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.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.gson.internal.LinkedTreeMap;
import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@Test(groups = "live", testName = "VirtualMachineApiLiveTest")
public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
@ -125,7 +123,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
}, 60 * 20 * 1000).apply(vmName);
assertTrue(jobDone, "create operation did not complete in the configured timeout");
String status = api().get(vmName).properties().provisioningState();
VirtualMachineProperties.ProvisioningState status = api().get(vmName).properties().provisioningState();
// Cannot be creating anymore. Should be succeeded or running but not failed.
assertTrue(!status.equals("Creating"));
assertTrue(!status.equals("Failed"));
@ -146,21 +144,21 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
@Test(dependsOnMethods = "testStart")
public void testStop() {
api().stop(vmName);
assertTrue(stateReached("PowerState", "VM stopped"), "stop operation did not complete in the configured timeout");
assertTrue(stateReached(PowerState.STOPPED), "stop operation did not complete in the configured timeout");
}
@Test(dependsOnMethods = "testGet")
public void testStart() {
api().start(vmName);
assertTrue(stateReached("PowerState", "VM running"), "start operation did not complete in the configured timeout");
assertTrue(stateReached(PowerState.RUNNING), "start operation did not complete in the configured timeout");
}
@Test(dependsOnMethods = "testStop")
public void testRestart() {
api().start(vmName);
assertTrue(stateReached("PowerState", "VM running"), "start operation did not complete in the configured timeout");
assertTrue(stateReached(PowerState.RUNNING), "start operation did not complete in the configured timeout");
api().restart(vmName);
assertTrue(stateReached("PowerState", "VM running"), "restart operation did not complete in the configured timeout");
assertTrue(stateReached(PowerState.RUNNING), "restart operation did not complete in the configured timeout");
}
@Test(dependsOnMethods = "testCreate")
@ -180,10 +178,11 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
@Test(dependsOnMethods = "testRestart")
public void testGeneralize() throws IllegalStateException {
api().stop(vmName);
assertTrue(stateReached("PowerState", "VM stopped"), "restart operation did not complete in the configured timeout");
assertTrue(stateReached(PowerState.STOPPED), "restart operation did not complete in the configured timeout");
api().generalize(vmName);
}
@SuppressWarnings("unchecked")
@Test(dependsOnMethods = "testGeneralize")
public void testCapture() throws IllegalStateException {
URI uri = api().capture(vmName, vmName, vmName);
@ -192,17 +191,17 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
if (definitions != null) {
for (ResourceDefinition definition : definitions) {
LinkedTreeMap<String, String> properties = (LinkedTreeMap<String, String>) definition.properties();
Map<String, String> properties = (Map<String, String>) definition.properties();
Object storageObject = properties.get("storageProfile");
LinkedTreeMap<String, String> properties2 = (LinkedTreeMap<String, String>) storageObject;
Map<String, String> properties2 = (Map<String, String>) storageObject;
Object osDiskObject = properties2.get("osDisk");
LinkedTreeMap<String, String> osProperties = (LinkedTreeMap<String, String>) osDiskObject;
Map<String, String> osProperties = (Map<String, String>) osDiskObject;
Object dataDisksObject = properties2.get("dataDisks");
ArrayList<Object> dataProperties = (ArrayList<Object>) dataDisksObject;
LinkedTreeMap<String, String> datadiskObject = (LinkedTreeMap<String, String>) dataProperties.get(0);
List<Object> dataProperties = (List<Object>) dataDisksObject;
Map<String, String> datadiskObject = (Map<String, String>) dataProperties.get(0);
Assert.assertNotNull(osProperties.get("name"));
Assert.assertNotNull(datadiskObject.get("name"));
assertNotNull(osProperties.get("name"));
assertNotNull(datadiskObject.get("name"));
}
}
}
@ -245,7 +244,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
DiagnosticsProfile.BootDiagnostics.create(true, blob);
DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics);
VirtualMachineProperties properties = VirtualMachineProperties.create(null,
null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, "Creating");
null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, VirtualMachineProperties.ProvisioningState.CREATING);
return properties;
}
@ -261,37 +260,15 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
return api.getNetworkInterfaceCardApi(resourceGroupName).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, tags);
}
private boolean deleteStorageService(String resourceGroupName, String storageServiceName) {
return api.getStorageAccountApi(resourceGroupName).delete(storageServiceName);
private boolean waitForState(String name, final PowerState state) {
return api().getInstanceDetails(name).powerState().equals(state);
}
private boolean waitForState(String name, final String state, final String displayStatus) {
return FluentIterable.from(api().getInstanceDetails(name).statuses())
.filter(new Predicate<VirtualMachineInstance.VirtualMachineStatus>() {
@Override
public boolean apply(VirtualMachineInstance.VirtualMachineStatus input) {
return input.code().substring(0, 10).equals(state);
}
})
.transform(new Function<VirtualMachineInstance.VirtualMachineStatus, String>() {
@Override
public String apply(VirtualMachineInstance.VirtualMachineStatus input) {
return input.displayStatus();
}
})
.anyMatch(new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.equals(displayStatus);
}
});
}
private boolean stateReached(final String state, final String displayStatus) {
private boolean stateReached(final PowerState state) {
return retry(new Predicate<String>() {
@Override
public boolean apply(String name) {
return waitForState(name, state, displayStatus);
return waitForState(name, state);
}
}, 60 * 4 * 1000).apply(vmName);
}

View File

@ -16,35 +16,36 @@
*/
package org.jclouds.azurecompute.arm.features;
import com.google.common.collect.ImmutableList;
import com.squareup.okhttp.mockwebserver.MockResponse;
import java.net.URI;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.jclouds.azurecompute.arm.domain.DataDisk;
import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
import org.jclouds.azurecompute.arm.domain.HardwareProfile;
import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.ImageReference;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VHD;
import org.jclouds.azurecompute.arm.domain.NetworkProfile;
import org.jclouds.azurecompute.arm.domain.OSDisk;
import org.jclouds.azurecompute.arm.domain.OSProfile;
import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
import org.jclouds.azurecompute.arm.domain.NetworkProfile;
import org.jclouds.azurecompute.arm.domain.StorageProfile;
import org.jclouds.azurecompute.arm.domain.DataDisk;
import org.jclouds.azurecompute.arm.domain.VHD;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
import org.testng.annotations.Test;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import com.google.common.collect.ImmutableList;
import com.squareup.okhttp.mockwebserver.MockResponse;
import static com.google.common.collect.Iterables.isEmpty;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
@Test(groups = "unit", testName = "VirtualMachineApiMockTest", singleThreaded = true)
@ -55,14 +56,14 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
assertEquals(vmAPI.get("windowsmachine"), getVM());
assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine?api-version=2015-06-15");
"/virtualMachines/windowsmachine?api-version=2016-03-30");
}
public void testGetEmpty() throws Exception {
server.enqueue(new MockResponse().setResponseCode(404));
final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
assertNull(vmAPI.get("windowsmachine"));
assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine?api-version=2015-06-15");
"/virtualMachines/windowsmachine?api-version=2016-03-30");
}
public void testGetInstanceDetails() throws Exception {
@ -76,7 +77,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
assertEquals(actual.statuses().get(0).level(), expected.statuses().get(0).level());
//assertEquals(actual.statuses().get(0).time().toString(), expected.statuses().get(0).time().toString());
assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine/instanceView?api-version=2015-06-15");
"/virtualMachines/windowsmachine/instanceView?api-version=2016-03-30");
}
public void testGetInstanceDetailsEmpty() throws Exception {
@ -84,7 +85,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
assertNull(vmAPI.getInstanceDetails("windowsmachine"));
assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine/instanceView?api-version=2015-06-15");
"/virtualMachines/windowsmachine/instanceView?api-version=2016-03-30");
}
public void testList() throws Exception {
@ -109,7 +110,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
VirtualMachine vm = vmAPI.create("windowsmachine", "westus", getProperties());
assertEquals(vm, getVM());
assertSent(server, "PUT", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine?api-version=2015-06-15&validating=false",
"/virtualMachines/windowsmachine?validating=false&api-version=2016-03-30",
"{\"location\":\"westus\",\"properties\":" +
"{\"vmId\":\"27ee085b-d707-xxxx-yyyy-2370e2eb1cc1\"," +
"\"hardwareProfile\":{\"vmSize\":\"Standard_D1\"}," +
@ -118,7 +119,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
"\"vhd\":{\"uri\":\"https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd\"},\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\"},\"dataDisks\":[]}," +
"\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"windowsConfiguration\":{\"provisionVMAgent\":false,\"enableAutomaticUpdates\":true}}," +
"\"networkProfile\":{\"networkInterfaces\":[{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167\"}]}," +
"\"diagnosticsProfile\":{\"bootDiagnostics\":{\"enabled\":true,\"storageUri\":\"https://groupname2760.blob.core.windows.net/\"}},\"provisioningState\":\"Creating\"}}");
"\"diagnosticsProfile\":{\"bootDiagnostics\":{\"enabled\":true,\"storageUri\":\"https://groupname2760.blob.core.windows.net/\"}},\"provisioningState\":\"CREATING\"}}");
}
@ -133,7 +134,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
assertNull(uri);
assertSent(server, "DELETE", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine?api-version=2015-06-15");
"/virtualMachines/windowsmachine?api-version=2016-03-30");
}
public void testDelete() throws Exception {
server.enqueue(response202WithHeader());
@ -146,7 +147,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
assertNotNull(uri);
assertSent(server, "DELETE", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine?api-version=2015-06-15");
"/virtualMachines/windowsmachine?api-version=2016-03-30");
}
public void testStart() throws Exception {
@ -231,7 +232,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
"https://groupname2760.blob.core.windows.net/");
DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics);
VirtualMachineProperties properties = VirtualMachineProperties.create("27ee085b-d707-xxxx-yyyy-2370e2eb1cc1",
null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, "Creating");
null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, VirtualMachineProperties.ProvisioningState.CREATING);
return properties;
}

View File

@ -101,7 +101,7 @@ public class VirtualNetworkApiMockTest extends BaseAzureComputeApiMockTest {
VirtualNetwork.AddressSpace.create(Arrays.asList("10.2.0.0/16")), null);
VirtualNetwork vn = vnApi.createOrUpdate(virtualNetwork, location, virtualNetworkProperties);
vnApi.createOrUpdate(virtualNetwork, location, virtualNetworkProperties);
String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Network/virtualNetworks/%s?%s", subscriptionid, resourcegroup, virtualNetwork, apiVersion);
String json = String.format("{\"location\":\"%s\",\"properties\":{\"addressSpace\":{\"addressPrefixes\":[\"%s\"]}}}", location, "10.2.0.0/16");

View File

@ -0,0 +1,129 @@
/*
* 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.filters;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
import static org.jclouds.reflect.Reflection2.method;
import static org.testng.Assert.assertEquals;
import java.util.Properties;
import javax.inject.Named;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.config.InvocationConfig;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Names;
@Test(groups = "unit", testName = "ApiVersionFilterTest", singleThreaded = true)
public class ApiVersionFilterTest {
public interface VersionedApi {
HttpResponse noName();
@Named("named:get")
HttpResponse named();
}
private Invocation noName;
private Invocation named;
private InvocationConfig config;
@BeforeMethod
public void setup() {
noName = Invocation.create(method(VersionedApi.class, "noName"), ImmutableList.of());
named = Invocation.create(method(VersionedApi.class, "named"), ImmutableList.of());
config = createMock(InvocationConfig.class);
expect(config.getCommandName(noName)).andReturn("VersionedApi.noName");
expect(config.getCommandName(named)).andReturn("named:get");
replay(config);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testFailIfNoGeneratedHttpRequest() {
ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(new Properties()));
filter.filter(HttpRequest.builder().method("GET").endpoint("http://localhost").build());
}
@Test
public void testOverrideMethodVersion() {
Properties props = new Properties();
props.setProperty(API_VERSION_PREFIX + "named:get", "namedversion");
props.setProperty(API_VERSION_PREFIX + "VersionedApi.noName", "noNameversion");
ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(props));
HttpRequest request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost")
.invocation(noName).addQueryParam("api-version", "original", "original2").build();
HttpRequest filtered = filter.filter(request);
assertEquals(filtered.getEndpoint().getQuery(), "api-version=noNameversion");
request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost").invocation(named)
.addQueryParam("api-version", "original", "original2").build();
filtered = filter.filter(request);
assertEquals(filtered.getEndpoint().getQuery(), "api-version=namedversion");
}
@Test
public void testFallbackToClassName() {
Properties props = new Properties();
props.setProperty(API_VERSION_PREFIX + "VersionedApi", "classversion");
ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(props));
HttpRequest request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost")
.invocation(noName).addQueryParam("api-version", "original", "original2").build();
HttpRequest filtered = filter.filter(request);
assertEquals(filtered.getEndpoint().getQuery(), "api-version=classversion");
request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost").invocation(named)
.addQueryParam("api-version", "original", "original2").build();
filtered = filter.filter(request);
assertEquals(filtered.getEndpoint().getQuery(), "api-version=classversion");
}
@Test
public void testNothingChangesIfNoCustomVersion() {
ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(new Properties()));
HttpRequest request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost").invocation(named)
.addQueryParam("api-version", "foo").build();
HttpRequest filtered = filter.filter(request);
assertEquals(filtered.getEndpoint().getQuery(), "api-version=foo");
}
private FilterStringsBoundToInjectorByName filterStringsBoundToInjectorByName(final Properties props) {
Injector injector = Guice.createInjector(new AbstractModule() {
protected void configure() {
Names.bindProperties(binder(), props);
}
});
return new FilterStringsBoundToInjectorByName(injector);
}
}

View File

@ -28,6 +28,7 @@ import org.jclouds.ContextBuilder;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.rest.ApiContext;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@ -50,6 +51,7 @@ public class BaseAzureComputeApiMockTest {
protected MockWebServer server;
protected AzureComputeApi api;
protected ApiContext<AzureComputeApi> context;
// So that we can ignore formatting.
private final JsonParser parser = new JsonParser();
@ -58,16 +60,21 @@ public class BaseAzureComputeApiMockTest {
public void start() throws IOException {
server = new MockWebServer();
server.play();
Properties properties = new Properties();
properties.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString());
properties.put("oauth.endpoint", "https://login.microsoftonline.com/tenant-id/oauth2/token");
AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
api = ContextBuilder.newBuilder(pm)
context = ContextBuilder.newBuilder(pm)
.credentials("", MOCK_BEARER_TOKEN)
.endpoint(server.getUrl("/").toString() + "subscriptions/SUBSCRIPTIONID")
.modules(modules)
.overrides(properties)
.buildApi(AzureComputeApi.class);
.overrides(setupProperties())
.build();
api = context.getApi();
}
protected Properties setupProperties() {
Properties properties = new Properties();
properties.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString());
properties.put("oauth.endpoint", "https://login.microsoftonline.com/tenant-id/oauth2/token");
return properties;
}
@AfterMethod(alwaysRun = true)