diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java index 02e69fa4ae..ccb748a956 100644 --- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java @@ -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 dataDisks = ImmutableList.of(); private String resourceGroup; private List ipOptions = ImmutableList.of(); + private WindowsConfiguration windowsConfiguration; + private List 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 docs + */ + public AzureTemplateOptions windowsConfiguration(WindowsConfiguration windowsConfiguration) { + this.windowsConfiguration = windowsConfiguration; + return this; + } + + /** + * Import certificates in the Windows Certificate Store + * + * @see docs + */ + public AzureTemplateOptions secrets(Iterable 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 getDataDisks() { return dataDisks; } public String getResourceGroup() { return resourceGroup; } public List getIpOptions() { return ipOptions; } + public WindowsConfiguration getWindowsConfiguration() { return windowsConfiguration; } + public List 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 secrets) { + AzureTemplateOptions options = new AzureTemplateOptions(); + return options.secrets(secrets); + } } } diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java index 5592b4c389..b77dc9e5fc 100644 --- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSProfile.java @@ -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 listeners(); + public abstract List listeners(); @SerializedNames({"listeners"}) - public static WinRM create(final Map listeners) { - return new AutoValue_OSProfile_WindowsConfiguration_WinRM(listeners == null ? ImmutableMap.of() : ImmutableMap.copyOf(listeners)); + public static WinRM create(final List listeners) { + return new AutoValue_OSProfile_WindowsConfiguration_WinRM(listeners == null ? ImmutableList.of() : ImmutableList.copyOf(listeners)); } } @@ -139,27 +175,20 @@ public abstract class OSProfile { * unattend content */ @Nullable - public abstract AdditionalUnattendContent additionalUnattendContent(); + public abstract List additionalUnattendContent(); /** * is automatic updates enabled */ public abstract boolean enableAutomaticUpdates(); - /** - * list of certificates - */ - @Nullable - public abstract List 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 secrets) { + final List 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(); + @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) { 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); + public abstract OSProfile build(); } } diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secrets.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secrets.java new file mode 100644 index 0000000000..5fcf7048a5 --- /dev/null +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secrets.java @@ -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 vaultCertificates(); + + @SerializedNames({"sourceVault", "vaultCertificates"}) + public static Secrets create(final SourceVault sourceVault, final List vaultCertificates) { + return new AutoValue_Secrets(sourceVault, vaultCertificates); + } +} diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultCertificate.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultCertificate.java new file mode 100644 index 0000000000..dd35eb6393 --- /dev/null +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultCertificate.java @@ -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); + } +} diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java index f3f6aacb1f..34b289e6c8 100644 --- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java +++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java @@ -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 = null; + OSProfile.WindowsConfiguration.WinRM winRm = null; + if (!isNullOrEmpty(vaultResourceGroup) && !isNullOrEmpty(vaultName) && !isNullOrEmpty(vaultCertificateUrl)) { + List 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/" diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java index 95d967e3ac..83e5ef210d 100644 --- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java +++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java @@ -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\":\"\"}]," + + "\"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\":\"\"}]," + + "\"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 dataDisks = new ArrayList(); - OSDisk osDisk = OSDisk.create("Windows", "windowsmachine", vhd, "ReadWrite", "FromImage", null, null, null); + List 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 = ImmutableList.of( + AdditionalUnattendContent.create("oobesystem", "Microsoft-Windows-Shell-Setup", "FirstLogonCommands", "")); + OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, winrm, additionalUnattendContent, true); + List 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 networkInterfaces = new ArrayList(); @@ -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; } diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java index 10406b8679..90502fe8e0 100644 --- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java +++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java @@ -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 modules) { Injector injector = newBuilder().modules(modules).overrides(props).buildInjector(); imageAvailablePredicate = injector.getInstance(Key.get(new TypeLiteral>() { diff --git a/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json b/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json index 2963100b0a..bc8ca2d11b 100644 --- a/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json +++ b/providers/azurecompute-arm/src/test/resources/createvirtualmachineresponse.json @@ -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":"" + } + ] }, - "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" } -} \ No newline at end of file +} diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachine.json b/providers/azurecompute-arm/src/test/resources/virtualmachine.json index 874227d00b..70e7f4a3bd 100644 --- a/providers/azurecompute-arm/src/test/resources/virtualmachine.json +++ b/providers/azurecompute-arm/src/test/resources/virtualmachine.json @@ -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":"" + } + ] }, - "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, diff --git a/providers/azurecompute-arm/src/test/resources/virtualmachines.json b/providers/azurecompute-arm/src/test/resources/virtualmachines.json index cd0e24b5ec..758a109ec0 100644 --- a/providers/azurecompute-arm/src/test/resources/virtualmachines.json +++ b/providers/azurecompute-arm/src/test/resources/virtualmachines.json @@ -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":"" + } + ] }, - "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": [