From 38cf774a7accb8115c91ad2ce314db452f42daa2 Mon Sep 17 00:00:00 2001 From: "Hong Li(MSFT)" <74638143+v-hongli1@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:16:01 +0800 Subject: [PATCH] Fix DeleteOptions on Public Ip Address (issue#38806) (#39096) Fix DeleteOptions on Public Ip Address (issue#38806) --- .../CHANGELOG.md | 2 + .../azure-resourcemanager-network/assets.json | 2 +- .../implementation/NetworkInterfaceImpl.java | 23 +++++- .../NicIpConfigurationImpl.java | 21 +++++- .../network/models/NetworkInterface.java | 29 ++++++- .../network/models/NicIpConfiguration.java | 52 ++++++++++++- .../NetworkInterfaceOperationsTests.java | 75 +++++++++++++++++++ 7 files changed, 194 insertions(+), 10 deletions(-) diff --git a/sdk/resourcemanager/azure-resourcemanager-network/CHANGELOG.md b/sdk/resourcemanager/azure-resourcemanager-network/CHANGELOG.md index 350f7c5721d1e..519b878fdc796 100644 --- a/sdk/resourcemanager/azure-resourcemanager-network/CHANGELOG.md +++ b/sdk/resourcemanager/azure-resourcemanager-network/CHANGELOG.md @@ -4,6 +4,8 @@ ### Features Added +- Supported setting `DeleteOptions` for public IP addresses associated with `NetworkInterface`. + ### Breaking Changes ### Bugs Fixed diff --git a/sdk/resourcemanager/azure-resourcemanager-network/assets.json b/sdk/resourcemanager/azure-resourcemanager-network/assets.json index ccfb7e0098d77..daf9a4133b214 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_03b4909e5e" } 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..1a8793482863c 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; @@ -32,6 +33,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -60,11 +62,14 @@ class NetworkInterfaceImpl private NetworkSecurityGroup existingNetworkSecurityGroupToAssociate; /** cached related resources. */ private NetworkSecurityGroup networkSecurityGroup; + /** the name of specified ip config name */ + private Map specifiedIpConfigNames; NetworkInterfaceImpl(String name, NetworkInterfaceInner innerModel, final NetworkManager networkManager) { super(name, innerModel, networkManager); this.nicName = name; this.namer = this.manager().resourceManager().internalContext().createIdentifierProvider(this.nicName); + this.specifiedIpConfigNames = new HashMap(); initializeChildrenFromInner(); } @@ -563,9 +568,25 @@ protected void beforeCreating() { .withNetworkSecurityGroup(new NetworkSecurityGroupInner().withId(networkSecurityGroup.id())); } - NicIpConfigurationImpl.ensureConfigurations(this.nicIPConfigurations.values()); + NicIpConfigurationImpl.ensureConfigurations(this.nicIPConfigurations.values(), this.specifiedIpConfigNames); // Reset and update IP configs this.innerModel().withIpConfigurations(innersFromWrappers(this.nicIPConfigurations.values())); } + + @Override + public NetworkInterfaceImpl withPrimaryPublicIPAddressDeleteOptions(DeleteOptions deleteOptions) { + this.ensureDeleteOptions(deleteOptions, "primary"); + return this; + } + + @Override + public NetworkInterfaceImpl update() { + this.specifiedIpConfigNames = new HashMap(); + return super.update(); + } + + public void ensureDeleteOptions(DeleteOptions deleteOptions, String ipConfigName) { + this.specifiedIpConfigNames.put(ipConfigName, deleteOptions); + } } 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..ecca0e730cf00 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; @@ -28,6 +29,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Objects; /** Implementation for NicIPConfiguration and its create and update interfaces. */ @@ -257,11 +259,11 @@ private List ensureInboundNatRules() { return natRefs; } - protected static void ensureConfigurations(Collection nicIPConfigurations) { + protected static void ensureConfigurations(Collection nicIPConfigurations, Map specifiedIpConfigNames) { for (NicIpConfiguration nicIPConfiguration : nicIPConfigurations) { NicIpConfigurationImpl config = (NicIpConfigurationImpl) nicIPConfiguration; config.innerModel().withSubnet(config.subnetToAssociate()); - config.innerModel().withPublicIpAddress(config.publicIPToAssociate()); + config.innerModel().withPublicIpAddress(config.publicIPToAssociate(specifiedIpConfigNames.getOrDefault(config.name(), null))); } } @@ -331,9 +333,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,8 +347,14 @@ private PublicIpAddressInner publicIPToAssociate() { } if (pipId != null) { + if (Objects.nonNull(deleteOptions)) { + return new PublicIpAddressInner().withId(pipId).withDeleteOption(deleteOptions); + } return new PublicIpAddressInner().withId(pipId); } else if (!this.isInCreateMode) { + if (Objects.nonNull(this.innerModel().publicIpAddress()) && Objects.nonNull(deleteOptions)) { + return this.innerModel().publicIpAddress().withDeleteOption(deleteOptions); + } return this.innerModel().publicIpAddress(); } else { return null; @@ -400,4 +409,10 @@ NicIpConfigurationImpl withoutApplicationSecurityGroup(String name) { } return this; } + + @Override + public NicIpConfigurationImpl withPublicIPAddressDeleteOptions(DeleteOptions deleteOptions) { + this.parent().ensureDeleteOptions(deleteOptions, this.innerModel().name()); + return this; + } } 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..e080c4b56b1b7 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 @@ -256,6 +256,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 update + */ + WithCreate withPrimaryPublicIPAddressDeleteOptions(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 +279,8 @@ interface WithCreate WithSecondaryIPConfiguration, WithAcceleratedNetworking, WithLoadBalancer, - WithApplicationSecurityGroup { + WithApplicationSecurityGroup, + WithPublicIPAddressDeleteOptions { /** * Enables IP forwarding in the network interface. * @@ -576,6 +588,18 @@ interface WithLoadBalancer { */ Update withoutLoadBalancerInboundNatRules(); } + + /** The stage of the network interface update 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 update + */ + Update withPrimaryPublicIPAddressDeleteOptions(DeleteOptions deleteOptions); + } } /** The template for an update operation, containing all the settings that can be modified. */ @@ -591,6 +615,7 @@ interface Update UpdateStages.WithIPConfiguration, UpdateStages.WithLoadBalancer, UpdateStages.WithAcceleratedNetworking, - UpdateStages.WithApplicationSecurityGroup { + UpdateStages.WithApplicationSecurityGroup, + UpdateStages.WithPublicIPAddressDeleteOptions { } } diff --git a/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/models/NicIpConfiguration.java b/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/models/NicIpConfiguration.java index 2441c4d31d57d..fb6dcb288b463 100644 --- a/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/models/NicIpConfiguration.java +++ b/sdk/resourcemanager/azure-resourcemanager-network/src/main/java/com/azure/resourcemanager/network/models/NicIpConfiguration.java @@ -188,6 +188,22 @@ WithAttach withExistingApplicationGatewayBackend( ApplicationGateway appGateway, String backendName); } + + /** The stage of the definition allowing to specify delete options for the public ip address. + * + * @param the stage of the parent network interface definition to return to after attaching this + * definition + * */ + 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 + */ + WithAttach withPublicIPAddressDeleteOptions(DeleteOptions deleteOptions); + } + /** * The final stage of network interface IP configuration. * @@ -201,7 +217,8 @@ interface WithAttach extends Attachable.InDefinition, WithPublicIPAddress, WithLoadBalancer, - WithApplicationGateway { + WithApplicationGateway, + WithPublicIPAddressDeleteOptions { } } @@ -372,6 +389,22 @@ WithAttach withExistingApplicationGatewayBackend( ApplicationGateway appGateway, String backendName); } + /** + * The stage of the definition allowing to specify delete options for the public ip address. + * + * @param the stage of the parent network interface update to return to after attaching this + * definition + * */ + interface WithPublicIPAddressDeleteOptions { + /** + * Sets delete options for public ip address. + * + * @param deleteOptions the delete options for primary network interfaces + * @return the next stage of the update + */ + WithAttach withPublicIPAddressDeleteOptions(DeleteOptions deleteOptions); + } + /** * The final stage of network interface IP configuration. * @@ -385,7 +418,8 @@ interface WithAttach extends Attachable.InUpdate, WithPublicIPAddress, WithLoadBalancer, - WithApplicationGateway { + WithApplicationGateway, + WithPublicIPAddressDeleteOptions { } } @@ -396,7 +430,8 @@ interface Update UpdateStages.WithPrivateIP, UpdateStages.WithPublicIPAddress, UpdateStages.WithLoadBalancer, - UpdateStages.WithApplicationGateway { + UpdateStages.WithApplicationGateway, + UpdateStages.WithPublicIPAddressDeleteOptions { } /** Grouping of network interface IP configuration update stages. */ @@ -486,5 +521,16 @@ interface WithApplicationGateway { */ Update withoutApplicationGatewayBackends(); } + + /** The stage of the network interface update 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 update + */ + Update withPublicIPAddressDeleteOptions(DeleteOptions deleteOptions); + } } } 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..41523fe1a7d4d 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; @@ -509,6 +510,80 @@ public void canAssociateNatGateway() { Assertions.assertEquals(gateway2.id(), subnet2.natGatewayId()); } + @Test + public void canCreateAndUpdateNicWithMultipleDeleteOptions() { + String subnetName = generateRandomResourceName("subnet-", 15); + resourceManager.resourceGroups().define(rgName).withRegion(Region.US_EAST).create(); + Network vnet = networkManager.networks() + .define(generateRandomResourceName("vnet-", 15)) + .withRegion(Region.US_EAST) + .withExistingResourceGroup(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) + .withExistingResourceGroup(rgName) + .withExistingPrimaryNetwork(vnet) + .withSubnet(subnetName) + .withPrimaryPrivateIPAddressDynamic() + .withNewPrimaryPublicIPAddress() + .withPrimaryPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .defineSecondaryIPConfiguration("secondary1") + .withExistingNetwork(vnet) + .withSubnet(subnetName) + .withPrivateIpAddressDynamic() + .withNewPublicIpAddress() + .withPublicIPAddressDeleteOptions(DeleteOptions.DETACH) + .attach() + .defineSecondaryIPConfiguration("secondary2") + .withExistingNetwork(vnet) + .withSubnet(subnetName) + .withPrivateIpAddressDynamic() + .withNewPublicIpAddress() + .withPublicIPAddressDeleteOptions(DeleteOptions.DETACH) + .attach() + .create(); + + nic.refresh(); + Assertions.assertEquals(DeleteOptions.DELETE, nic.primaryIPConfiguration().innerModel().publicIpAddress().deleteOption()); + Assertions.assertEquals(DeleteOptions.DETACH, nic.ipConfigurations().get("secondary1").innerModel().publicIpAddress().deleteOption()); + Assertions.assertEquals(DeleteOptions.DETACH, nic.ipConfigurations().get("secondary2").innerModel().publicIpAddress().deleteOption()); + + String existingPrimaryIpAddressId = nic.primaryIPConfiguration().publicIpAddressId(); + nic.update().withNewPrimaryPublicIPAddress().withPrimaryPublicIPAddressDeleteOptions(DeleteOptions.DETACH).apply(); + nic.refresh(); + Assertions.assertFalse(existingPrimaryIpAddressId.equalsIgnoreCase(nic.primaryIPConfiguration().publicIpAddressId())); + Assertions.assertEquals(DeleteOptions.DETACH, nic.primaryIPConfiguration().innerModel().publicIpAddress().deleteOption()); + + String existingSecondary1IpAddressId = nic.ipConfigurations().get("secondary1").publicIpAddressId(); + nic.update() + .withPrimaryPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .updateIPConfiguration("secondary1") + .withNewPublicIpAddress() + .withPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .parent() + .updateIPConfiguration("secondary2") + .withPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .parent() + .defineSecondaryIPConfiguration("secondary3") + .withExistingNetwork(vnet) + .withSubnet(subnetName) + .withPrivateIpAddressDynamic() + .withNewPublicIpAddress() + .withPublicIPAddressDeleteOptions(DeleteOptions.DELETE) + .attach() + .apply(); + nic.refresh(); + Assertions.assertFalse(existingSecondary1IpAddressId.equalsIgnoreCase(nic.ipConfigurations().get("secondary1").publicIpAddressId())); + Assertions.assertEquals(DeleteOptions.DELETE, nic.primaryIPConfiguration().innerModel().publicIpAddress().deleteOption()); + Assertions.assertEquals(DeleteOptions.DELETE, nic.ipConfigurations().get("secondary1").innerModel().publicIpAddress().deleteOption()); + Assertions.assertEquals(DeleteOptions.DELETE, nic.ipConfigurations().get("secondary2").innerModel().publicIpAddress().deleteOption()); + Assertions.assertEquals(DeleteOptions.DELETE, nic.ipConfigurations().get("secondary3").innerModel().publicIpAddress().deleteOption()); + } + private NatGatewayInner createNatGateway() { String natGatewayName = generateRandomResourceName("natgw", 10); return networkManager.serviceClient()