Adding support for provisioning of Windows VMs with enabled WinRM

- Provisioning using pre-existing KeyVault
- Enabling WinRM with pre-existing certificate
This commit is contained in:
Yavor Yanchev 2017-05-19 12:41:16 +03:00 committed by Svetoslav Neykov
parent 45480c4913
commit 50ae01985a
11 changed files with 513 additions and 73 deletions

View File

@ -64,6 +64,8 @@ import org.jclouds.azurecompute.arm.domain.ManagedDiskParameters;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.domain.NetworkProfile;
import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface.NetworkInterfaceProperties;
import org.jclouds.azurecompute.arm.domain.OSDisk;
import org.jclouds.azurecompute.arm.domain.OSProfile;
import org.jclouds.azurecompute.arm.domain.Offer;
@ -82,8 +84,6 @@ import org.jclouds.azurecompute.arm.domain.VMSize;
import org.jclouds.azurecompute.arm.domain.Version;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface.NetworkInterfaceProperties;
import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
import org.jclouds.azurecompute.arm.features.OSImageApi;
import org.jclouds.compute.ComputeServiceAdapter;
@ -390,6 +390,17 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
builder.linuxConfiguration(linuxConfiguration);
}
AzureTemplateOptions azureTemplateOptions = template.getOptions().as(AzureTemplateOptions.class);
if (azureTemplateOptions.getWindowsConfiguration() != null) {
builder.windowsConfiguration(azureTemplateOptions.getWindowsConfiguration());
}
if (azureTemplateOptions.getSecrets() != null) {
builder.secrets(azureTemplateOptions.getSecrets());
}
return builder.build();
}
@ -526,5 +537,4 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
private IdReference getAvailabilitySetIdReference(AvailabilitySet availabilitySet) {
return availabilitySet != null ? IdReference.create(availabilitySet.id()) : null;
}
}

View File

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

View File

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

View File

@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue;
import org.jclouds.json.SerializedNames;
import java.util.List;
/**
* Group of certificates stored in one and the same KeyVault
*/
@AutoValue
public abstract class Secrets {
@AutoValue
public abstract static class SourceVault {
public abstract String id();
@SerializedNames({"id"})
public static SourceVault create(final String id) {
return new AutoValue_Secrets_SourceVault(id);
}
}
/**
* Name of the KeyVault which contains all the certificates
*/
public abstract SourceVault sourceVault();
/**
* List of the certificates
*/
public abstract List<VaultCertificate> vaultCertificates();
@SerializedNames({"sourceVault", "vaultCertificates"})
public static Secrets create(final SourceVault sourceVault, final List<VaultCertificate> vaultCertificates) {
return new AutoValue_Secrets(sourceVault, vaultCertificates);
}
}

View File

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
/**
* Certificate stored in a Key Vault
*/
@AutoValue
public abstract class VaultCertificate {
/**
* The URL of the certificate
*/
public abstract String certificateUrl();
/**
* Certificate's store name
*/
@Nullable
public abstract String certificateStore();
@SerializedNames({"certificateUrl", "certificateStore"})
public static VaultCertificate create(final String certificateUrl, final String certificateStore) {
return new AutoValue_VaultCertificate(certificateUrl, certificateStore);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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