diff --git a/sdk/core/azure-core-management/CHANGELOG.md b/sdk/core/azure-core-management/CHANGELOG.md index 83027fef550a..75d53c8a0f0f 100644 --- a/sdk/core/azure-core-management/CHANGELOG.md +++ b/sdk/core/azure-core-management/CHANGELOG.md @@ -2,6 +2,7 @@ ## 1.0.0-beta.4 (Unreleased) +- Added `Region` class. ## 1.0.0-beta.3 (2020-08-07) diff --git a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/Region.java b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/Region.java new file mode 100644 index 000000000000..5331652a0c01 --- /dev/null +++ b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/Region.java @@ -0,0 +1,349 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.core.management; + +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collection; +import java.util.Locale; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * Enumeration of the Azure datacenter regions. See https://azure.microsoft.com/regions/ + */ +public final class Region { + // This needs to be at the beginning for the initialization to happen correctly + private static final ConcurrentMap VALUES_BY_NAME = new ConcurrentHashMap<>(); + + /* + * Azure Cloud - Americas + */ + /** + * East US (US) (recommended) + */ + public static final Region US_EAST = new Region("eastus", "East US"); + /** + * East US 2 (US) (recommended) + */ + public static final Region US_EAST2 = new Region("eastus2", "East US 2"); + /** + * South Central US (US) (recommended) + */ + public static final Region US_SOUTH_CENTRAL = new Region("southcentralus", "South Central US"); + /** + * West US 2 (US) (recommended) + */ + public static final Region US_WEST2 = new Region("westus2", "West US 2"); + /** + * Central US (US) (recommended) + */ + public static final Region US_CENTRAL = new Region("centralus", "Central US"); + /** + * North Central US (US) (recommended) + */ + public static final Region US_NORTH_CENTRAL = new Region("northcentralus", "North Central US"); + /** + * West US (US) (recommended) + */ + public static final Region US_WEST = new Region("westus", "West US"); + /** + * West Central US (US) + */ + public static final Region US_WEST_CENTRAL = new Region("westcentralus", "West Central US"); + /** + * Canada Central (Canada) (recommended) + */ + public static final Region CANADA_CENTRAL = new Region("canadacentral", "Canada Central"); + /** + * Canada East (Canada) + */ + public static final Region CANADA_EAST = new Region("canadaeast", "Canada East"); + /** + * Brazil South (South America) (recommended) + */ + public static final Region BRAZIL_SOUTH = new Region("brazilsouth", "Brazil South"); + /** + * Brazil Southeast (South America) + */ + public static final Region BRAZIL_SOUTHEAST = new Region("brazilsoutheast", "Brazil Southeast"); + /* + * Azure Cloud - Europe + */ + /** + * North Europe (Europe) (recommended) + */ + public static final Region EUROPE_NORTH = new Region("northeurope", "North Europe"); + /** + * UK South (Europe) (recommended) + */ + public static final Region UK_SOUTH = new Region("uksouth", "UK South"); + /** + * West Europe (Europe) (recommended) + */ + public static final Region EUROPE_WEST = new Region("westeurope", "West Europe"); + /** + * France Central (Europe) (recommended) + */ + public static final Region FRANCE_CENTRAL = new Region("francecentral", "France Central"); + /** + * Germany West Central (Europe) (recommended) + */ + public static final Region GERMANY_WEST_CENTRAL = new Region("germanywestcentral", "Germany West Central"); + /** + * Norway East (Europe) (recommended) + */ + public static final Region NORWAY_EAST = new Region("norwayeast", "Norway East"); + /** + * Switzerland North (Europe) (recommended) + */ + public static final Region SWITZERLAND_NORTH = new Region("switzerlandnorth", "Switzerland North"); + /** + * France South (Europe) + */ + public static final Region FRANCE_SOUTH = new Region("francesouth", "France South"); + /** + * Germany North (Europe) + */ + public static final Region GERMANY_NORTH = new Region("germanynorth", "Germany North"); + /** + * Norway West (Europe) + */ + public static final Region NORWAY_WEST = new Region("norwaywest", "Norway West"); + /** + * Switzerland West (Europe) + */ + public static final Region SWITZERLAND_WEST = new Region("switzerlandwest", "Switzerland West"); + /** + * UK West (Europe) + */ + public static final Region UK_WEST = new Region("ukwest", "UK West"); + /* + * Azure Cloud - Asia + */ + /** + * Australia East (Asia Pacific) (recommended) + */ + public static final Region AUSTRALIA_EAST = new Region("australiaeast", "Australia East"); + /** + * Southeast Asia (Asia Pacific) (recommended) + */ + public static final Region ASIA_SOUTHEAST = new Region("southeastasia", "Southeast Asia"); + /** + * Central India (Asia Pacific) (recommended) + */ + public static final Region INDIA_CENTRAL = new Region("centralindia", "Central India"); + /** + * East Asia (Asia Pacific) (recommended) + */ + public static final Region ASIA_EAST = new Region("eastasia", "East Asia"); + /** + * Japan East (Asia Pacific) (recommended) + */ + public static final Region JAPAN_EAST = new Region("japaneast", "Japan East"); + /** + * Korea Central (Asia Pacific) (recommended) + */ + public static final Region KOREA_CENTRAL = new Region("koreacentral", "Korea Central"); + /** + * Australia Central (Asia Pacific) + */ + public static final Region AUSTRALIA_CENTRAL = new Region("australiacentral", "Australia Central"); + /** + * Australia Central 2 (Asia Pacific) + */ + public static final Region AUSTRALIA_CENTRAL2 = new Region("australiacentral2", "Australia Central 2"); + /** + * Australia Southeast (Asia Pacific) + */ + public static final Region AUSTRALIA_SOUTHEAST = new Region("australiasoutheast", "Australia Southeast"); + /** + * Japan West (Asia Pacific) + */ + public static final Region JAPAN_WEST = new Region("japanwest", "Japan West"); + /** + * Korea South (Asia Pacific) + */ + public static final Region KOREA_SOUTH = new Region("koreasouth", "Korea South"); + /** + * South India (Asia Pacific) + */ + public static final Region INDIA_SOUTH = new Region("southindia", "South India"); + /** + * West India (Asia Pacific) + */ + public static final Region INDIA_WEST = new Region("westindia", "West India"); + /* + * Azure Cloud - Middle East and Africa + */ + /** + * UAE North (Middle East) (recommended) + */ + public static final Region UAE_NORTH = new Region("uaenorth", "UAE North"); + /** + * UAE Central (Middle East) + */ + public static final Region UAE_CENTRAL = new Region("uaecentral", "UAE Central"); + /** + * South Africa North (Africa) (recommended) + */ + public static final Region SOUTHAFRICA_NORTH = new Region("southafricanorth", "South Africa North"); + /** + * South Africa West (Africa) + */ + public static final Region SOUTHAFRICA_WEST = new Region("southafricawest", "South Africa West"); + /* + * Azure China Cloud + */ + /** + * China North + */ + public static final Region CHINA_NORTH = new Region("chinanorth", "China North"); + /** + * China East + */ + public static final Region CHINA_EAST = new Region("chinaeast", "China East"); + /** + * China North 2 + */ + public static final Region CHINA_NORTH2 = new Region("chinanorth2", "China North 2"); + /** + * China East 2 + */ + public static final Region CHINA_EAST2 = new Region("chinaeast2", "China East 2"); + /* + * Azure German Cloud + */ + /** + * Germany Central + */ + public static final Region GERMANY_CENTRAL = new Region("germanycentral", "Germany Central"); + /** + * Germany Northeast + */ + public static final Region GERMANY_NORTHEAST = new Region("germanynortheast", "Germany Northeast"); + /* + * Azure Government Cloud + */ + /** + * U.S. government cloud in Virginia. + */ + public static final Region GOV_US_VIRGINIA = new Region("usgovvirginia", "US Gov Virginia"); + + /** + * U.S. government cloud in Iowa. + */ + public static final Region GOV_US_IOWA = new Region("usgoviowa", "US Gov Iowa"); + + /** + * U.S. government cloud in Arizona. + */ + public static final Region GOV_US_ARIZONA = new Region("usgovarizona", "US Gov Arizona"); + + /** + * U.S. government cloud in Texas. + */ + public static final Region GOV_US_TEXAS = new Region("usgovtexas", "US Gov Texas"); + + /** + * U.S. Department of Defense cloud - East. + */ + public static final Region GOV_US_DOD_EAST = new Region("usdodeast", "US DoD East"); + + /** + * U.S. Department of Defense cloud - Central. + */ + public static final Region GOV_US_DOD_CENTRAL = new Region("usdodcentral", "US DoD Central"); + + private final String name; + private final String label; + + /** + * @return predefined Azure regions. + */ + public static Collection values() { + return VALUES_BY_NAME.values(); + } + + private Region(String name, String label) { + this.name = name; + this.label = label; + VALUES_BY_NAME.put(name.toLowerCase(Locale.ROOT), this); + } + + /** + * Creates a region from a name and a label. + * + * @param name the uniquely identifiable name of the region. + * @param label the label of the region. + * @return the newly created region. + */ + public static Region create(String name, String label) { + Objects.requireNonNull(name, "'name' cannot be null."); + + Region region = VALUES_BY_NAME.get(name.toLowerCase(Locale.ROOT)); + if (region != null) { + return region; + } else { + return new Region(name, label); + } + } + + @JsonValue + @Override + public String toString() { + return name(); + } + + /** + * @return the name of the region. + */ + public String name() { + return this.name; + } + + /** + * @return the label of the region. + */ + public String label() { + return this.label; + } + + /** + * Parses a name into a Region object and creates a new Region instance if not found among the existing ones. + * + * @param name the name of the region. + * @return the parsed or created region. + */ + public static Region fromName(String name) { + if (name == null) { + return null; + } + + Region region = VALUES_BY_NAME.get(name.toLowerCase(Locale.ROOT).replace(" ", "")); + if (region != null) { + return region; + } else { + return Region.create(name.toLowerCase(Locale.ROOT).replace(" ", ""), name); + } + } + + @Override + public int hashCode() { + return this.name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Region)) { + return false; + } else if (obj == this) { + return true; + } else { + Region rhs = (Region) obj; + return this.name.equalsIgnoreCase(rhs.name); + } + } +} diff --git a/sdk/core/azure-core-management/src/test/java/com/azure/core/management/RegionTests.java b/sdk/core/azure-core-management/src/test/java/com/azure/core/management/RegionTests.java new file mode 100644 index 000000000000..d61a61ad2996 --- /dev/null +++ b/sdk/core/azure-core-management/src/test/java/com/azure/core/management/RegionTests.java @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.core.management; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class RegionTests { + + @Test + public void testPredefined() { + Region region = Region.US_WEST; + + Region sameRegion = Region.US_WEST; + Assertions.assertTrue(region.equals(sameRegion)); + Assertions.assertTrue(region == sameRegion); + + Region differentRegion = Region.US_WEST2; + Assertions.assertTrue(!region.equals(differentRegion)); + Assertions.assertTrue(region != differentRegion); + } + + @Test + public void testCreate() { + // reuse region if exist + Region sameRegion = Region.create("WESTUS", "WEST US"); + Assertions.assertEquals(Region.US_WEST, sameRegion); + Assertions.assertTrue(Region.US_WEST == sameRegion); + + int size = Region.values().size(); + + // create region with new name + Region newRegion = Region.create("centraluseuap2", "Central US 2 EUAP"); + Assertions.assertTrue(Region.values().size() >= size + 1); // 'testFromLabel' might create region in parallel, hence use >= instead of == + Region newRegionSame = Region.fromName("centraluseuap2"); + Assertions.assertTrue(newRegion.equals(newRegionSame)); + Assertions.assertEquals("Central US 2 EUAP", newRegionSame.label()); + } + + @Test + public void testFromLabel() { + // reuse region if exist + Region region = Region.fromName("westus"); + Assertions.assertEquals(Region.US_WEST, region); + + // space is ignored + Region sameRegion = Region.fromName("west us"); + Assertions.assertEquals(Region.US_WEST, sameRegion); + + // case is ignored + sameRegion = Region.fromName("WEST US"); + Assertions.assertEquals(Region.US_WEST, sameRegion); + + // create region if not exist + Region newRegion = Region.fromName("newregion"); + Assertions.assertEquals("newregion", newRegion.label()); + Assertions.assertTrue(Region.values().stream().anyMatch(r -> r.name().equals("newregion"))); + + // null + Assertions.assertNull(Region.fromName(null)); + } + + @Test + public void testNegative() { + Assertions.assertThrows(NullPointerException.class, () -> Region.create(null, "desc")); + } +} diff --git a/sdk/resourcemanager/azure-resourcemanager-resources/src/main/java/com/azure/resourcemanager/resources/fluentcore/arm/Region.java b/sdk/resourcemanager/azure-resourcemanager-resources/src/main/java/com/azure/resourcemanager/resources/fluentcore/arm/Region.java index 43af0b5741d4..9fed929d1c59 100644 --- a/sdk/resourcemanager/azure-resourcemanager-resources/src/main/java/com/azure/resourcemanager/resources/fluentcore/arm/Region.java +++ b/sdk/resourcemanager/azure-resourcemanager-resources/src/main/java/com/azure/resourcemanager/resources/fluentcore/arm/Region.java @@ -32,6 +32,7 @@ public final class Region { public static final Region CANADA_CENTRAL = new Region("canadacentral", "Canada Central"); public static final Region CANADA_EAST = new Region("canadaeast", "Canada East"); public static final Region BRAZIL_SOUTH = new Region("brazilsouth", "Brazil South"); + public static final Region BRAZIL_SOUTHEAST = new Region("brazilsoutheast", "Brazil Southeast"); /************************************************** * Azure Cloud - Europe **************************************************/ diff --git a/sdk/resourcemanager/azure-resourcemanager/src/test/java/com/azure/resourcemanager/AzureTests.java b/sdk/resourcemanager/azure-resourcemanager/src/test/java/com/azure/resourcemanager/AzureTests.java index 74f069285c48..21603714094f 100644 --- a/sdk/resourcemanager/azure-resourcemanager/src/test/java/com/azure/resourcemanager/AzureTests.java +++ b/sdk/resourcemanager/azure-resourcemanager/src/test/java/com/azure/resourcemanager/AzureTests.java @@ -55,6 +55,7 @@ import com.azure.resourcemanager.resources.models.DeploymentMode; import com.azure.resourcemanager.resources.models.GenericResource; import com.azure.resourcemanager.resources.models.Location; +import com.azure.resourcemanager.resources.models.RegionCategory; import com.azure.resourcemanager.resources.models.RegionType; import com.azure.resourcemanager.resources.models.Subscription; import com.azure.resourcemanager.storage.models.SkuName; @@ -1323,23 +1324,85 @@ public void generateMissingRegion() { azure .getCurrentSubscription() .listLocations(); // note the region is not complete since it depends on current subscription + + List locationGroupByGeography = new ArrayList<>(); + List geographies = Arrays.asList( + "US", "Canada", "South America", "Europe", "Asia Pacific", "Middle East", "Africa"); + for (String geography : geographies) { + for (Location location : locations) { + if (location.regionType() == RegionType.PHYSICAL) { + if (geography.equals(location.inner().metadata().geographyGroup())) { + locationGroupByGeography.add(location); + } + } + } + } for (Location location : locations) { + if (location.regionType() == RegionType.PHYSICAL) { + if (!geographies.contains(location.inner().metadata().geographyGroup())) { + locationGroupByGeography.add(location); + } + } + } + + for (Location location : locationGroupByGeography) { if (location.regionType() == RegionType.PHYSICAL) { Region region = Region.findByLabelOrName(location.name()); if (region == null) { sb - .append("\n") - .append( - MessageFormat - .format( - "public static final Region {0} = new Region(\"{1}\", \"{2}\");", - location.displayName().toUpperCase().replace(" ", "_"), - location.name(), - location.displayName())); + .append("\n").append("/**") + .append("\n").append(MessageFormat.format( + " * {0} ({1})", + location.displayName(), + location.inner().metadata().geographyGroup())) + .append(location.inner().metadata().regionCategory() == RegionCategory.RECOMMENDED + ? " (recommended)" : "") + .append("\n").append(" */") + .append("\n").append(MessageFormat.format( + "public static final Region {0} = new Region(\"{1}\", \"{2}\");", + getLocationVariableName(location), + location.name(), + location.displayName())); } } } Assertions.assertTrue(sb.length() == 0, sb.toString()); } + + private static String getLocationVariableName(Location location) { + final String geographyGroup = location.inner().metadata().geographyGroup(); + String displayName = location.displayName(); + if ("US".equals(geographyGroup)) { + if (displayName.contains(" US")) { + displayName = displayName.replace(" US", ""); + displayName = "US " + displayName; + } + } else if ("Europe".equals(geographyGroup)) { + if (displayName.contains(" Europe")) { + displayName = displayName.replace(" Europe", ""); + displayName = "Europe " + displayName; + } + } else if ("Asia Pacific".equals(geographyGroup)) { + if (displayName.contains(" Asia")) { + displayName = displayName.replace(" Asia", ""); + displayName = "Asia " + displayName; + } else if (displayName.contains(" India")) { + displayName = displayName.replace(" India", ""); + displayName = "India " + displayName; + } + + } else if ("Africa".equals(geographyGroup)) { + if (displayName.startsWith("South Africa")) { + displayName = displayName.replace("South Africa", "SouthAfrica"); + } + } + if (displayName.length() > 2 && displayName.charAt(displayName.length() - 1) >= '0' + && displayName.charAt(displayName.length() - 1) <= '9' + && displayName.charAt(displayName.length() - 2) == ' ') { + displayName = displayName.replace(displayName.substring(displayName.length() - 2), + displayName.substring(displayName.length() - 1)); + } + return displayName.toUpperCase().replace(" ", "_"); + } }