diff --git a/sdk/resourcemanager/azure-resourcemanager-compute/assets.json b/sdk/resourcemanager/azure-resourcemanager-compute/assets.json index 721532f1127d6..363310917a95a 100644 --- a/sdk/resourcemanager/azure-resourcemanager-compute/assets.json +++ b/sdk/resourcemanager/azure-resourcemanager-compute/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/resourcemanager/azure-resourcemanager-compute", - "Tag": "java/resourcemanager/azure-resourcemanager-compute_f43c5950dd" + "Tag": "java/resourcemanager/azure-resourcemanager-compute_71ff791c94" } diff --git a/sdk/resourcemanager/azure-resourcemanager-compute/src/main/java/com/azure/resourcemanager/compute/implementation/VirtualMachineImpl.java b/sdk/resourcemanager/azure-resourcemanager-compute/src/main/java/com/azure/resourcemanager/compute/implementation/VirtualMachineImpl.java index 8450a0dd8d071..28d3ae3a8c283 100644 --- a/sdk/resourcemanager/azure-resourcemanager-compute/src/main/java/com/azure/resourcemanager/compute/implementation/VirtualMachineImpl.java +++ b/sdk/resourcemanager/azure-resourcemanager-compute/src/main/java/com/azure/resourcemanager/compute/implementation/VirtualMachineImpl.java @@ -87,6 +87,7 @@ import com.azure.resourcemanager.network.NetworkManager; import com.azure.resourcemanager.network.models.Network; import com.azure.resourcemanager.network.models.NetworkInterface; +import com.azure.resourcemanager.network.models.NicIpConfigurationBase; import com.azure.resourcemanager.network.models.PublicIPSkuType; import com.azure.resourcemanager.network.models.PublicIpAddress; import com.azure.resourcemanager.resources.fluentcore.arm.AvailabilityZoneId; @@ -94,6 +95,7 @@ import com.azure.resourcemanager.resources.fluentcore.arm.ResourceUtils; import com.azure.resourcemanager.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; import com.azure.resourcemanager.resources.fluentcore.model.Accepted; +import com.azure.resourcemanager.resources.fluentcore.model.Appliable; import com.azure.resourcemanager.resources.fluentcore.model.Creatable; import com.azure.resourcemanager.resources.fluentcore.model.Indexable; import com.azure.resourcemanager.resources.fluentcore.model.implementation.AcceptedImpl; @@ -2308,6 +2310,74 @@ public VirtualMachineImpl withDataDisksDeleteOptions(DeleteOptions deleteOptions return this; } + @Override + public VirtualMachineImpl withPrimaryNicPrimaryPipDeleteOption(DeleteOptions deleteOptions) { + if (this.innerModel().networkProfile() != null + && this.innerModel().networkProfile().networkInterfaces() != null) { + this.innerModel().networkProfile().networkInterfaces() + .stream().filter(NetworkInterfaceReference::primary) + .forEach(nicReference -> { + NetworkInterface nic = networkManager.networkInterfaces().getById(nicReference.id()); + nic.ipConfigurations().values() + .stream().filter(NicIpConfigurationBase::isPrimary) + .forEach(ipConfig -> { + PublicIpAddress publicIpAddress = networkManager.publicIpAddresses().getById(ipConfig.innerModel().publicIpAddress().id()); + Appliable appliable = nic.update().withSpecifiedNicSpecifiedPipDeleteOption(convertDeleteOptionType(deleteOptions), publicIpAddress, ipConfig.name()); + this.addDependency(appliable); + }); + }); + } + return this; + } + + @Override + public VirtualMachineImpl withSpecifiedNicPrimaryPIpDeleteOption(DeleteOptions deleteOptions, String... nicIds) { + if (this.innerModel().networkProfile() != null + && this.innerModel().networkProfile().networkInterfaces() != null) { + Set nicIdSet = Arrays.stream(nicIds).map(nicId -> nicId.toLowerCase(Locale.ROOT)).collect(Collectors.toSet()); + this.innerModel().networkProfile().networkInterfaces() + .stream().filter(nicReference -> nicIdSet.isEmpty() + || nicIdSet.contains(nicReference.id().toLowerCase(Locale.ROOT))) + .forEach(nicReference -> { + NetworkInterface nic = networkManager.networkInterfaces().getById(nicReference.id()); + nic.ipConfigurations().values() + .stream().filter(NicIpConfigurationBase::isPrimary) + .forEach(ipConfig -> { + PublicIpAddress publicIpAddress = networkManager.publicIpAddresses().getById(ipConfig.innerModel().publicIpAddress().id()); + Appliable appliable = + nic.update().withSpecifiedNicSpecifiedPipDeleteOption( + convertDeleteOptionType(deleteOptions), publicIpAddress, ipConfig.name()); + this.addDependency(appliable); + }); + }); + } + return this; + } + + @Override + public VirtualMachineImpl withSpecifiedNicSpecifiedPIpDeleteOption(DeleteOptions deleteOptions, String nicId, String... ipConfigIds) { + if (this.innerModel().networkProfile() != null + && this.innerModel().networkProfile().networkInterfaces() != null) { + this.innerModel().networkProfile().networkInterfaces() + .stream().filter(nicReference -> nicId.equalsIgnoreCase(nicReference.id())) + .forEach(nicReference -> { + NetworkInterface nic = networkManager.networkInterfaces().getById(nicReference.id()); + Set ipConfigIdSet = Arrays.stream(ipConfigIds).map(ipConfigId -> ipConfigId.toLowerCase(Locale.ROOT)).collect(Collectors.toSet()); + nic.ipConfigurations().values() + .stream().filter(ipConfig -> ipConfigIdSet.isEmpty() + || ipConfigIdSet.contains(ipConfig.innerModel().id().toLowerCase(Locale.ROOT))) + .forEach(ipConfig -> { + PublicIpAddress publicIpAddress = networkManager.publicIpAddresses().getById(ipConfig.innerModel().publicIpAddress().id()); + Appliable appliable = + nic.update().withSpecifiedNicSpecifiedPipDeleteOption( + convertDeleteOptionType(deleteOptions), publicIpAddress, ipConfig.name()); + this.addDependency(appliable); + }); + }); + } + return this; + } + @Override public VirtualMachineImpl withDataDisksDeleteOptions(DeleteOptions deleteOptions) { this.innerModel().storageProfile().dataDisks().forEach( @@ -2942,6 +3012,12 @@ public VirtualMachineImpl withoutEncryptionAtHost() { return this; } + @Override + public VirtualMachine.DefinitionStages.WithCreate withPublicIPAddressDeleteOptions(DeleteOptions deleteOptions) { + this.nicDefinitionWithCreate.withPublicIPAddressDeleteOptions(convertDeleteOptionType(deleteOptions)); + return this; + } + /** Class to manage Data disk collection. */ private class ManagedDataDiskCollection { private final Map newDisksToAttach = new HashMap<>(); @@ -3366,4 +3442,15 @@ private void enableDisable(boolean enable) { } } } + + private com.azure.resourcemanager.network.models.DeleteOptions convertDeleteOptionType(DeleteOptions deleteOptions) { + if (Objects.nonNull(deleteOptions)) { + if (DeleteOptions.DELETE.equals(deleteOptions)) { + return com.azure.resourcemanager.network.models.DeleteOptions.DELETE; + } else { + return com.azure.resourcemanager.network.models.DeleteOptions.DETACH; + } + } + return null; + } } diff --git a/sdk/resourcemanager/azure-resourcemanager-compute/src/main/java/com/azure/resourcemanager/compute/models/VirtualMachine.java b/sdk/resourcemanager/azure-resourcemanager-compute/src/main/java/com/azure/resourcemanager/compute/models/VirtualMachine.java index 0950a6fa7b0f8..bfb78ed631d17 100644 --- a/sdk/resourcemanager/azure-resourcemanager-compute/src/main/java/com/azure/resourcemanager/compute/models/VirtualMachine.java +++ b/sdk/resourcemanager/azure-resourcemanager-compute/src/main/java/com/azure/resourcemanager/compute/models/VirtualMachine.java @@ -1898,6 +1898,17 @@ interface WithNetworkInterfaceDeleteOptions { WithCreate withPrimaryNetworkInterfaceDeleteOptions(DeleteOptions deleteOptions); } + /** The stage of the definition allowing to specify delete options for the public ip address. */ + interface WithPublicIPAddressDeleteOptions { + /** + * Sets delete options for public ip address. + * + * @param deleteOptions the delete options for primary network interfaces + * @return the next stage of the definition + */ + WithCreate withPublicIPAddressDeleteOptions(DeleteOptions deleteOptions); + } + /** The stage of the VM definition allowing to specify additional capacities. */ interface WithAdditionalCapacities { /** @@ -1988,6 +1999,7 @@ interface WithCreate DefinitionStages.WithLicenseType, DefinitionStages.WithAdditionalCapacities, DefinitionStages.WithNetworkInterfaceDeleteOptions, + DefinitionStages.WithPublicIPAddressDeleteOptions, DefinitionStages.WithEphemeralOSDisk, DefinitionStages.WithScaleSet, DefinitionStages.WithSecurityTypes, @@ -2610,6 +2622,33 @@ interface WithDeleteOptions { */ Update withDataDisksDeleteOptions(DeleteOptions deleteOptions, Integer... luns); + /** + * Update delete option for the primary public ip address of the primary network interface. + * + * @param deleteOptions what happens to the public IP address when the VM using it is deleted + * @return the next stage of the update + */ + Update withPrimaryNicPrimaryPipDeleteOption(DeleteOptions deleteOptions); + + /** + * Update delete option for the primary public ip address of the specified network interface. + * + * @param deleteOptions what happens to the public IP address when the VM using it is deleted + * @param nicIds resource Ids of the specified network interface + * @return the next stage of the update + */ + Update withSpecifiedNicPrimaryPIpDeleteOption(DeleteOptions deleteOptions, String... nicIds); + + /** + * Update delete option for the specified public ip address of the specified network interface. + * + * @param deleteOptions what happens to the public IP address when the VM using it is deleted + * @param nicId resource id of the specified network interfac + * @param ipConfigIds resource Ids of specified network interface ip configs + * @return the next stage of the update + */ + Update withSpecifiedNicSpecifiedPIpDeleteOption(DeleteOptions deleteOptions, String nicId, String... ipConfigIds); + /** * Specifies delete options for all the existing data disk attached to the VM. *

This operation only affects existing attached data disks. Any newly-attached data disks diff --git a/sdk/resourcemanager/azure-resourcemanager-compute/src/test/java/com/azure/resourcemanager/compute/VirtualMachineOperationsTests.java b/sdk/resourcemanager/azure-resourcemanager-compute/src/test/java/com/azure/resourcemanager/compute/VirtualMachineOperationsTests.java index f6acacb5f6b45..90f9a2f27f9e4 100644 --- a/sdk/resourcemanager/azure-resourcemanager-compute/src/test/java/com/azure/resourcemanager/compute/VirtualMachineOperationsTests.java +++ b/sdk/resourcemanager/azure-resourcemanager-compute/src/test/java/com/azure/resourcemanager/compute/VirtualMachineOperationsTests.java @@ -30,6 +30,7 @@ import com.azure.resourcemanager.compute.models.InstanceViewTypes; import com.azure.resourcemanager.compute.models.KnownLinuxVirtualMachineImage; import com.azure.resourcemanager.compute.models.KnownWindowsVirtualMachineImage; +import com.azure.resourcemanager.compute.models.NetworkInterfaceReference; import com.azure.resourcemanager.compute.models.PowerState; import com.azure.resourcemanager.compute.models.ProximityPlacementGroupType; import com.azure.resourcemanager.compute.models.RunCommandInputParameter; @@ -54,6 +55,7 @@ import com.azure.resourcemanager.network.models.NetworkInterface; import com.azure.resourcemanager.network.models.NetworkSecurityGroup; import com.azure.resourcemanager.network.models.NicIpConfiguration; +import com.azure.resourcemanager.network.models.NicIpConfigurationBase; import com.azure.resourcemanager.network.models.PublicIPSkuType; import com.azure.resourcemanager.network.models.PublicIpAddress; import com.azure.resourcemanager.network.models.SecurityRuleProtocol; @@ -66,6 +68,7 @@ import com.azure.resourcemanager.resources.models.ResourceGroup; import com.azure.resourcemanager.storage.models.StorageAccount; import com.azure.resourcemanager.storage.models.StorageAccountSkuType; +import com.azure.resourcemanager.test.utils.TestUtilities; import com.azure.security.keyvault.keys.models.KeyType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; @@ -93,6 +96,7 @@ public class VirtualMachineOperationsTests extends ComputeManagementTest { private final String availabilitySetName = "availset1"; private final String availabilitySetName2 = "availset2"; private final ProximityPlacementGroupType proxGroupType = ProximityPlacementGroupType.STANDARD; + private static final Integer SLEEP_TIME_MILLI_SECONDS = 15 * 1000; @Override protected void initializeClients(HttpPipeline httpPipeline, AzureProfile profile) { @@ -1998,6 +2002,345 @@ private CreatablesInfo prepareCreatableVirtualMachines( return creatablesInfo; } + @Test + public void canDeleteSinglePublicIpAddressWithVM() { + PublicIpAddress publicIPAddress = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + + VirtualMachine vm = computeManager.virtualMachines() + .define(vmName) + .withRegion(region) + .withNewResourceGroup(rgName) + .withNewPrimaryNetwork("10.0.0.0/28") + .withPrimaryPrivateIPAddressDynamic() + .withExistingPrimaryPublicIPAddress(publicIPAddress) + .withPopularWindowsImage(KnownWindowsVirtualMachineImage.WINDOWS_SERVER_2019_DATACENTER_GEN2) + .withAdminUsername("Foo12") + .withAdminPassword(password()) + .withNewDataDisk(127) + .withSize(VirtualMachineSizeTypes.fromString("Standard_D2a_v4")) + .withPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .create(); + + vm.refresh(); + List deleteOptionsList = new ArrayList<>(); + vm.innerModel().networkProfile().networkInterfaces() + .stream().filter(NetworkInterfaceReference::primary) + .forEach(nicReference -> networkManager.networkInterfaces().getById(nicReference.id()) + .ipConfigurations().values() + .stream().filter(NicIpConfigurationBase::isPrimary) + .forEach(ipConfig -> deleteOptionsList.add(ipConfig.innerModel().publicIpAddress().deleteOption()))); + + Assertions.assertEquals(1, deleteOptionsList.size()); + deleteOptionsList.forEach(deleteOption -> Assertions.assertEquals(com.azure.resourcemanager.network.models.DeleteOptions.DELETE, deleteOption)); + + computeManager.virtualMachines().deleteById(vm.id(), true); + TestUtilities.sleep(SLEEP_TIME_MILLI_SECONDS, true); + Assertions.assertTrue(networkManager.publicIpAddresses().listByResourceGroup(rgName).stream().findAny().isPresent()); + } + + @Test + public void canDeleteMultiplePublicIpAddressWithVM() { + String subnetName = generateRandomResourceName("subnet-", 15); + PublicIpAddress publicIPAddress1 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + PublicIpAddress publicIPAddress2 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + PublicIpAddress publicIPAddress3 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + Network vnet = networkManager.networks() + .define(generateRandomResourceName("vnet-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withAddressSpace("10.0.0.0/28") + .withSubnet(subnetName, "10.0.0.0/28") + .create(); + + NetworkInterface secondaryNic = networkManager.networkInterfaces() + .define(generateRandomResourceName("nic-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withExistingPrimaryNetwork(vnet) + .withSubnet(subnetName) + .withPrimaryPrivateIPAddressDynamic() + .withExistingPrimaryPublicIPAddress(publicIPAddress1) + .defineSecondaryIPConfiguration("secondary") + .withExistingNetwork(vnet) + .withSubnet(subnetName) + .withPrivateIpAddressDynamic() + .withExistingPublicIpAddress(publicIPAddress2) + .attach() + .withPublicIPAddressDeleteOptions(com.azure.resourcemanager.network.models.DeleteOptions.DELETE) + .create(); + + VirtualMachine vm = computeManager.virtualMachines() + .define(vmName) + .withRegion(region) + .withNewResourceGroup(rgName) + .withExistingPrimaryNetwork(vnet) + .withSubnet(subnetName) + .withPrimaryPrivateIPAddressDynamic() + .withExistingPrimaryPublicIPAddress(publicIPAddress3) + .withPopularWindowsImage(KnownWindowsVirtualMachineImage.WINDOWS_SERVER_2019_DATACENTER_GEN2) + .withAdminUsername("Foo12") + .withAdminPassword(password()) + .withNewDataDisk(127) + .withSize(VirtualMachineSizeTypes.fromString("Standard_D2a_v4")) + .withExistingSecondaryNetworkInterface(secondaryNic) + .withPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .create(); + + vm.refresh(); + List deleteOptionsList = new ArrayList<>(); + vm.innerModel().networkProfile().networkInterfaces() + .forEach(nicReference -> networkManager.networkInterfaces().getById(nicReference.id()) + .ipConfigurations().values() + .forEach(ipConfig -> deleteOptionsList.add(ipConfig.innerModel().publicIpAddress().deleteOption()))); + + Assertions.assertEquals(3, deleteOptionsList.size()); + deleteOptionsList.forEach(deleteOption -> Assertions.assertEquals(com.azure.resourcemanager.network.models.DeleteOptions.DELETE, deleteOption)); + + computeManager.virtualMachines().deleteById(vm.id(), true); + TestUtilities.sleep(SLEEP_TIME_MILLI_SECONDS, true); + Assertions.assertTrue(networkManager.publicIpAddresses().listByResourceGroup(rgName).stream().findAny().isPresent()); + } + + @Test + public void updateDeleteOptionWithPrimaryNicPrimaryPip() { + PublicIpAddress publicIPAddress = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + + VirtualMachine vm = computeManager.virtualMachines() + .define(vmName) + .withRegion(region) + .withNewResourceGroup(rgName) + .withNewPrimaryNetwork("10.0.0.0/28") + .withPrimaryPrivateIPAddressDynamic() + .withExistingPrimaryPublicIPAddress(publicIPAddress) + .withPopularWindowsImage(KnownWindowsVirtualMachineImage.WINDOWS_SERVER_2019_DATACENTER_GEN2) + .withAdminUsername("Foo12") + .withAdminPassword(password()) + .withNewDataDisk(127) + .withSize(VirtualMachineSizeTypes.fromString("Standard_D2a_v4")) + .withPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .create(); + + vm.refresh(); + vm.update().withPrimaryNicPrimaryPipDeleteOption(DeleteOptions.DETACH).apply(); + vm.refresh(); + List deleteOptionsList = new ArrayList<>(); + vm.innerModel().networkProfile().networkInterfaces() + .stream().filter(NetworkInterfaceReference::primary) + .forEach(nicReference -> { + networkManager.networkInterfaces().getById(nicReference.id()) + .ipConfigurations().values() + .stream().filter(NicIpConfigurationBase::isPrimary) + .forEach(ipConfig -> deleteOptionsList.add(ipConfig.innerModel().publicIpAddress().deleteOption())); + }); + + Assertions.assertEquals(1, deleteOptionsList.size()); + deleteOptionsList.forEach(deleteOption -> Assertions.assertEquals(com.azure.resourcemanager.network.models.DeleteOptions.DETACH, deleteOption)); + } + + @Test + public void updateDeleteOptionWithSpecifiedNicPrimaryPip() { + String subnetName = generateRandomResourceName("subnet-", 15); + PublicIpAddress publicIPAddress1 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + PublicIpAddress publicIPAddress2 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + PublicIpAddress publicIPAddress3 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + Network vnet = networkManager.networks() + .define(generateRandomResourceName("vnet-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withAddressSpace("10.0.0.0/28") + .withSubnet(subnetName, "10.0.0.0/28") + .create(); + + NetworkInterface secondaryNic = networkManager.networkInterfaces() + .define(generateRandomResourceName("nic-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withExistingPrimaryNetwork(vnet) + .withSubnet(subnetName) + .withPrimaryPrivateIPAddressDynamic() + .withExistingPrimaryPublicIPAddress(publicIPAddress1) + .defineSecondaryIPConfiguration("secondary") + .withExistingNetwork(vnet) + .withSubnet(subnetName) + .withPrivateIpAddressDynamic() + .withExistingPublicIpAddress(publicIPAddress2) + .attach() + .withPublicIPAddressDeleteOptions(com.azure.resourcemanager.network.models.DeleteOptions.DELETE) + .create(); + + VirtualMachine vm = computeManager.virtualMachines() + .define(vmName) + .withRegion(region) + .withNewResourceGroup(rgName) + .withExistingPrimaryNetwork(vnet) + .withSubnet(subnetName) + .withPrimaryPrivateIPAddressDynamic() + .withExistingPrimaryPublicIPAddress(publicIPAddress3) + .withPopularWindowsImage(KnownWindowsVirtualMachineImage.WINDOWS_SERVER_2019_DATACENTER_GEN2) + .withAdminUsername("Foo12") + .withAdminPassword(password()) + .withNewDataDisk(127) + .withSize(VirtualMachineSizeTypes.fromString("Standard_D2a_v4")) + .withExistingSecondaryNetworkInterface(secondaryNic) + .withPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .create(); + vm.refresh(); + + vm.innerModel().networkProfile().networkInterfaces() + .stream().filter(nicReference -> Boolean.FALSE.equals(nicReference.primary())) + .forEach(nicReference -> vm.update().withSpecifiedNicPrimaryPIpDeleteOption(DeleteOptions.DETACH, nicReference.id()).apply()); + vm.refresh(); + + List deleteOptionsList = new ArrayList<>(); + vm.innerModel().networkProfile().networkInterfaces() + .stream().filter(nicReference -> Boolean.FALSE.equals(nicReference.primary())) + .forEach(nicReference -> deleteOptionsList.add(networkManager.networkInterfaces().getById(nicReference.id()).primaryIPConfiguration().innerModel().publicIpAddress().deleteOption())); + Assertions.assertEquals(1, deleteOptionsList.size()); + deleteOptionsList.forEach(deleteOption -> Assertions.assertEquals(com.azure.resourcemanager.network.models.DeleteOptions.DETACH, deleteOption)); + } + + @Test + public void updateDeleteOptionWithSpecifiedNicSpecifiedPip() { + String subnetName = generateRandomResourceName("subnet-", 15); + PublicIpAddress publicIPAddress1 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + PublicIpAddress publicIPAddress2 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + PublicIpAddress publicIPAddress3 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + Network vnet = networkManager.networks() + .define(generateRandomResourceName("vnet-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withAddressSpace("10.0.0.0/28") + .withSubnet(subnetName, "10.0.0.0/28") + .create(); + + NetworkInterface secondaryNic = networkManager.networkInterfaces() + .define(generateRandomResourceName("nic-", 15)) + .withRegion(region) + .withNewResourceGroup(rgName) + .withExistingPrimaryNetwork(vnet) + .withSubnet(subnetName) + .withPrimaryPrivateIPAddressDynamic() + .withExistingPrimaryPublicIPAddress(publicIPAddress1) + .defineSecondaryIPConfiguration("secondary") + .withExistingNetwork(vnet) + .withSubnet(subnetName) + .withPrivateIpAddressDynamic() + .withExistingPublicIpAddress(publicIPAddress2) + .attach() + .withPublicIPAddressDeleteOptions(com.azure.resourcemanager.network.models.DeleteOptions.DELETE) + .create(); + + VirtualMachine vm = computeManager.virtualMachines() + .define(vmName) + .withRegion(region) + .withNewResourceGroup(rgName) + .withExistingPrimaryNetwork(vnet) + .withSubnet(subnetName) + .withPrimaryPrivateIPAddressDynamic() + .withExistingPrimaryPublicIPAddress(publicIPAddress3) + .withPopularWindowsImage(KnownWindowsVirtualMachineImage.WINDOWS_SERVER_2019_DATACENTER_GEN2) + .withAdminUsername("Foo12") + .withAdminPassword(password()) + .withNewDataDisk(127) + .withSize(VirtualMachineSizeTypes.fromString("Standard_D2a_v4")) + .withExistingSecondaryNetworkInterface(secondaryNic) + .withPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .create(); + vm.refresh(); + + vm.innerModel().networkProfile().networkInterfaces() + .stream().filter(nicReference -> Boolean.FALSE.equals(nicReference.primary())) + .forEach(nicReference -> { + String specifiedIpConfigId = networkManager.networkInterfaces().getById(nicReference.id()).specifiedIPConfiguration("secondary").innerModel().id(); + vm.update().withSpecifiedNicSpecifiedPIpDeleteOption(DeleteOptions.DETACH, nicReference.id(), specifiedIpConfigId).apply(); + }); + + vm.refresh(); + List deleteOptionsList = new ArrayList<>(); + vm.innerModel().networkProfile().networkInterfaces() + .stream().filter(nicReference -> Boolean.FALSE.equals(nicReference.primary())) + .forEach(nicReference -> deleteOptionsList.add(networkManager.networkInterfaces().getById(nicReference.id()).specifiedIPConfiguration("secondary").innerModel().publicIpAddress().deleteOption())); + Assertions.assertEquals(1, deleteOptionsList.size()); + deleteOptionsList.forEach(deleteOption -> Assertions.assertEquals(com.azure.resourcemanager.network.models.DeleteOptions.DETACH, deleteOption)); + } + class CreatablesInfo { private List> virtualMachineCreatables; List networkCreatableKeys; diff --git a/sdk/resourcemanager/azure-resourcemanager-network/assets.json b/sdk/resourcemanager/azure-resourcemanager-network/assets.json index ccfb7e0098d77..2f47236c8c300 100644 --- a/sdk/resourcemanager/azure-resourcemanager-network/assets.json +++ b/sdk/resourcemanager/azure-resourcemanager-network/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/resourcemanager/azure-resourcemanager-network", - "Tag": "java/resourcemanager/azure-resourcemanager-network_271269e41a" + "Tag": "java/resourcemanager/azure-resourcemanager-network_579661caaf" } diff --git a/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/implementation/NetworkInterfaceImpl.java b/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/implementation/NetworkInterfaceImpl.java index 3b2d2c6e2f5ea..840b01c4c52ce 100644 --- a/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/implementation/NetworkInterfaceImpl.java +++ b/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/implementation/NetworkInterfaceImpl.java @@ -9,6 +9,7 @@ import com.azure.resourcemanager.network.NetworkManager; import com.azure.resourcemanager.network.fluent.models.ApplicationSecurityGroupInner; import com.azure.resourcemanager.network.models.ApplicationSecurityGroup; +import com.azure.resourcemanager.network.models.DeleteOptions; import com.azure.resourcemanager.network.models.IpAllocationMethod; import com.azure.resourcemanager.network.models.LoadBalancer; import com.azure.resourcemanager.network.models.Network; @@ -60,6 +61,7 @@ class NetworkInterfaceImpl private NetworkSecurityGroup existingNetworkSecurityGroupToAssociate; /** cached related resources. */ private NetworkSecurityGroup networkSecurityGroup; + private DeleteOptions publicIPAddressDeleteOption; NetworkInterfaceImpl(String name, NetworkInterfaceInner innerModel, final NetworkManager networkManager) { super(name, innerModel, networkManager); @@ -416,6 +418,22 @@ public NetworkSecurityGroup getNetworkSecurityGroup() { return this.networkSecurityGroup; } + @Override + public NicIpConfigurationImpl specifiedIPConfiguration(String ipConfigName) { + NicIpConfigurationImpl specifiedIPConfig = null; + for (NicIpConfiguration ipConfiguration : this.nicIPConfigurations.values()) { + if (ipConfigName.equals(ipConfiguration.name())) { + specifiedIPConfig = (NicIpConfigurationImpl) ipConfiguration; + break; + } + } + if (specifiedIPConfig == null) { + specifiedIPConfig = prepareNewNicIPConfiguration(ipConfigName); + withIPConfiguration(specifiedIPConfig); + } + return specifiedIPConfig; + } + /** @return the primary IP configuration of the network interface */ @Override public NicIpConfigurationImpl primaryIPConfiguration() { @@ -563,9 +581,24 @@ protected void beforeCreating() { .withNetworkSecurityGroup(new NetworkSecurityGroupInner().withId(networkSecurityGroup.id())); } - NicIpConfigurationImpl.ensureConfigurations(this.nicIPConfigurations.values()); + NicIpConfigurationImpl.ensureConfigurations(this.nicIPConfigurations.values(), this.publicIPAddressDeleteOption); // Reset and update IP configs this.innerModel().withIpConfigurations(innersFromWrappers(this.nicIPConfigurations.values())); } + + @Override + public NetworkInterfaceImpl withPublicIPAddressDeleteOptions(DeleteOptions deleteOptions) { + this.publicIPAddressDeleteOption = deleteOptions; + return this; + } + + @Override + public NetworkInterfaceImpl withSpecifiedNicSpecifiedPipDeleteOption( + DeleteOptions deleteOptions, PublicIpAddress publicIpAddress, String ipConfigName) { + this.specifiedIPConfiguration(ipConfigName).withExistingPublicIpAddress(publicIpAddress); + this.specifiedIPConfiguration(ipConfigName).withPrivateIpVersion(publicIpAddress.version()); + this.publicIPAddressDeleteOption = deleteOptions; + return this; + } } diff --git a/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/implementation/NicIpConfigurationImpl.java b/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/implementation/NicIpConfigurationImpl.java index aa05e3df0d123..ae19faadaaf1f 100644 --- a/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/implementation/NicIpConfigurationImpl.java +++ b/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/implementation/NicIpConfigurationImpl.java @@ -9,6 +9,7 @@ import com.azure.resourcemanager.network.models.ApplicationGateway; import com.azure.resourcemanager.network.models.ApplicationGatewayBackendAddressPool; import com.azure.resourcemanager.network.models.ApplicationSecurityGroup; +import com.azure.resourcemanager.network.models.DeleteOptions; import com.azure.resourcemanager.network.models.IpAllocationMethod; import com.azure.resourcemanager.network.models.IpVersion; import com.azure.resourcemanager.network.models.LoadBalancer; @@ -257,11 +258,11 @@ private List ensureInboundNatRules() { return natRefs; } - protected static void ensureConfigurations(Collection nicIPConfigurations) { + protected static void ensureConfigurations(Collection nicIPConfigurations, DeleteOptions deleteOptions) { for (NicIpConfiguration nicIPConfiguration : nicIPConfigurations) { NicIpConfigurationImpl config = (NicIpConfigurationImpl) nicIPConfiguration; config.innerModel().withSubnet(config.subnetToAssociate()); - config.innerModel().withPublicIpAddress(config.publicIPToAssociate()); + config.innerModel().withPublicIpAddress(config.publicIPToAssociate(deleteOptions)); } } @@ -331,9 +332,10 @@ private SubnetInner subnetToAssociate() { * public IP in create fluent chain. In case of update chain, if withoutPublicIP(..) is not specified then existing * associated (if any) public IP will be returned. * + * @param deleteOptions what happens to the public IP address when the VM using it is deleted. * @return public IP SubResource */ - private PublicIpAddressInner publicIPToAssociate() { + private PublicIpAddressInner publicIPToAssociate(DeleteOptions deleteOptions) { String pipId = null; if (this.removePrimaryPublicIPAssociation) { return null; @@ -344,9 +346,13 @@ private PublicIpAddressInner publicIPToAssociate() { } if (pipId != null) { - return new PublicIpAddressInner().withId(pipId); + return new PublicIpAddressInner().withId(pipId).withDeleteOption(deleteOptions); } else if (!this.isInCreateMode) { - return this.innerModel().publicIpAddress(); + if (Objects.isNull(this.innerModel().publicIpAddress())) { + return this.innerModel().publicIpAddress(); + } else { + return this.innerModel().publicIpAddress().withDeleteOption(deleteOptions); + } } else { return null; } diff --git a/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/models/NetworkInterface.java b/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/models/NetworkInterface.java index 84f1a5cb888d8..b74f273d7cdf1 100644 --- a/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/models/NetworkInterface.java +++ b/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/models/NetworkInterface.java @@ -29,6 +29,14 @@ public interface NetworkInterface /** @return the primary IP configuration of this network interface */ NicIpConfiguration primaryIPConfiguration(); + /** + * Gets the specified ip configuration + * + * @param ipConfigName the name of th specified ip configuration + * @return the specified IP configuration of this network interface + */ + NicIpConfiguration specifiedIPConfiguration(String ipConfigName); + /** The entirety of the network interface definition. */ interface Definition extends DefinitionStages.Blank, @@ -256,6 +264,17 @@ interface WithAcceleratedNetworking { WithCreate withAcceleratedNetworking(); } + /** The stage of the definition allowing to specify delete options for the public ip address. */ + interface WithPublicIPAddressDeleteOptions { + /** + * Sets delete options for public ip address. + * + * @param deleteOptions the delete options for primary network interfaces + * @return the next stage of the definition + */ + WithCreate withPublicIPAddressDeleteOptions(DeleteOptions deleteOptions); + } + /** * The stage of the network interface definition which contains all the minimum required inputs for the resource * to be created, but also allows for any other optional settings to be specified. @@ -268,7 +287,8 @@ interface WithCreate WithSecondaryIPConfiguration, WithAcceleratedNetworking, WithLoadBalancer, - WithApplicationSecurityGroup { + WithApplicationSecurityGroup, + WithPublicIPAddressDeleteOptions { /** * Enables IP forwarding in the network interface. * @@ -576,6 +596,19 @@ interface WithLoadBalancer { */ Update withoutLoadBalancerInboundNatRules(); } + + /** The stage of the network interface update allowing to update delete option of the public ip address. */ + interface WithSpecifiedNicSpecifiedPipDeleteOption { + /** + * Update delete option for specified public ip address of specified network interface ip config. + * + * @param deleteOptions what happens to the public IP address when the VM using it is deleted + * @param publicIpAddress an object of existing public ip address + * @param ipConfigName the name of specified network interface ip config + * @return the next stage of the update + */ + Update withSpecifiedNicSpecifiedPipDeleteOption(DeleteOptions deleteOptions, PublicIpAddress publicIpAddress, String ipConfigName); + } } /** The template for an update operation, containing all the settings that can be modified. */ @@ -591,6 +624,7 @@ interface Update UpdateStages.WithIPConfiguration, UpdateStages.WithLoadBalancer, UpdateStages.WithAcceleratedNetworking, - UpdateStages.WithApplicationSecurityGroup { + UpdateStages.WithApplicationSecurityGroup, + UpdateStages.WithSpecifiedNicSpecifiedPipDeleteOption { } } diff --git a/sdk/resourcemanager/azure-resourcemanager-network/src/test/java/com/azure/resourcemanager/network/NetworkInterfaceOperationsTests.java b/sdk/resourcemanager/azure-resourcemanager-network/src/test/java/com/azure/resourcemanager/network/NetworkInterfaceOperationsTests.java index 4f74986fe237c..eedfb3da14f4a 100644 --- a/sdk/resourcemanager/azure-resourcemanager-network/src/test/java/com/azure/resourcemanager/network/NetworkInterfaceOperationsTests.java +++ b/sdk/resourcemanager/azure-resourcemanager-network/src/test/java/com/azure/resourcemanager/network/NetworkInterfaceOperationsTests.java @@ -6,6 +6,7 @@ import com.azure.core.management.Region; import com.azure.resourcemanager.network.fluent.models.NatGatewayInner; import com.azure.resourcemanager.network.models.ApplicationSecurityGroup; +import com.azure.resourcemanager.network.models.DeleteOptions; import com.azure.resourcemanager.network.models.NatGatewaySku; import com.azure.resourcemanager.network.models.NatGatewaySkuName; import com.azure.resourcemanager.network.models.Network; @@ -13,6 +14,7 @@ import com.azure.resourcemanager.network.models.NetworkInterfaces; import com.azure.resourcemanager.network.models.Networks; import com.azure.resourcemanager.network.models.NicIpConfiguration; +import com.azure.resourcemanager.network.models.PublicIpAddress; import com.azure.resourcemanager.network.models.Subnet; import com.azure.resourcemanager.resources.fluentcore.arm.ResourceUtils; import com.azure.resourcemanager.resources.fluentcore.model.Creatable; @@ -26,6 +28,7 @@ import reactor.core.publisher.Mono; import java.util.Arrays; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -509,6 +512,116 @@ public void canAssociateNatGateway() { Assertions.assertEquals(gateway2.id(), subnet2.natGatewayId()); } + @Test + public void createNetWorkInterfaceWorkWithDeleteOption() { + String subnetName = generateRandomResourceName("subnet-", 15); + PublicIpAddress publicIPAddress1 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(Region.US_EAST) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + + PublicIpAddress publicIPAddress2 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(Region.US_EAST) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + + Network vnet = networkManager.networks() + .define(generateRandomResourceName("vnet-", 15)) + .withRegion(Region.US_EAST) + .withNewResourceGroup(rgName) + .withAddressSpace("10.0.0.0/28") + .withSubnet(subnetName, "10.0.0.0/28") + .create(); + + NetworkInterface nic = networkManager.networkInterfaces() + .define(generateRandomResourceName("nic-", 15)) + .withRegion(Region.US_EAST) + .withNewResourceGroup(rgName) + .withExistingPrimaryNetwork(vnet) + .withSubnet(subnetName) + .withPrimaryPrivateIPAddressDynamic() + .withExistingPrimaryPublicIPAddress(publicIPAddress1) + .defineSecondaryIPConfiguration("secondary") + .withExistingNetwork(vnet) + .withSubnet(subnetName) + .withPrivateIpAddressDynamic() + .withExistingPublicIpAddress(publicIPAddress2) + .attach() + .withPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .create(); + + nic.refresh(); + List deleteOptionsList = new ArrayList<>(); + nic.innerModel().ipConfigurations() + .forEach(ipConfig -> deleteOptionsList.add(ipConfig.publicIpAddress().deleteOption())); + + Assertions.assertEquals(2, deleteOptionsList.size()); + deleteOptionsList.forEach(deleteOptions -> Assertions.assertEquals(DeleteOptions.DELETE, deleteOptions)); + } + + @Test + public void updateNetWorkInterfaceWorkWithDeleteOption() { + String subnetName = generateRandomResourceName("subnet-", 15); + PublicIpAddress publicIPAddress1 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(Region.US_EAST) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + + PublicIpAddress publicIPAddress2 = + networkManager + .publicIpAddresses() + .define(generateRandomResourceName("pip-", 15)) + .withRegion(Region.US_EAST) + .withNewResourceGroup(rgName) + .withDynamicIP() + .create(); + + Network vnet = networkManager.networks() + .define(generateRandomResourceName("vnet-", 15)) + .withRegion(Region.US_EAST) + .withNewResourceGroup(rgName) + .withAddressSpace("10.0.0.0/28") + .withSubnet(subnetName, "10.0.0.0/28") + .create(); + + NetworkInterface nic = networkManager.networkInterfaces() + .define(generateRandomResourceName("nic-", 15)) + .withRegion(Region.US_EAST) + .withNewResourceGroup(rgName) + .withExistingPrimaryNetwork(vnet) + .withSubnet(subnetName) + .withPrimaryPrivateIPAddressDynamic() + .withExistingPrimaryPublicIPAddress(publicIPAddress1) + .defineSecondaryIPConfiguration("secondary") + .withExistingNetwork(vnet) + .withSubnet(subnetName) + .withPrivateIpAddressDynamic() + .withExistingPublicIpAddress(publicIPAddress2) + .attach() + .withPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .create(); + + nic.update().withSpecifiedNicSpecifiedPipDeleteOption(DeleteOptions.DETACH, publicIPAddress1, "primary").apply(); + nic.refresh(); + Assertions.assertEquals(DeleteOptions.DETACH, nic.primaryIPConfiguration().innerModel().publicIpAddress().deleteOption()); + + nic.update().withSpecifiedNicSpecifiedPipDeleteOption(DeleteOptions.DETACH, publicIPAddress2, "secondary").apply(); + nic.refresh(); + Assertions.assertEquals(DeleteOptions.DETACH, nic.specifiedIPConfiguration("secondary").innerModel().publicIpAddress().deleteOption()); + } + private NatGatewayInner createNatGateway() { String natGatewayName = generateRandomResourceName("natgw", 10); return networkManager.serviceClient()