Repository: cassandra
Updated Branches:
  refs/heads/trunk 8a5e1cbe2 -> fd44a69fc


Use standard Amazon naming for datacenter and rack in Ec2Snitch.

patch by Gregory Ramsperger and jasobrown; reviewed by Joey Lynch for 
CASSANDRA-7839


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/fd44a69f
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/fd44a69f
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/fd44a69f

Branch: refs/heads/trunk
Commit: fd44a69fce135c6ddf7ebcba25d032a36a1d9064
Parents: 8a5e1cb
Author: Gregory Ramsperger <ramsper...@users.noreply.github.com>
Authored: Sat Apr 16 00:42:03 2016 -0500
Committer: Jason Brown <jasedbr...@gmail.com>
Committed: Mon Apr 16 17:59:06 2018 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 NEWS.txt                                        |   4 +
 conf/cassandra-rackdc.properties                |  12 ++
 .../locator/DynamicEndpointSnitch.java          |   5 +
 .../org/apache/cassandra/locator/Ec2Snitch.java | 109 +++++++++++++++--
 .../cassandra/locator/IEndpointSnitch.java      |   9 ++
 .../cassandra/locator/SnitchProperties.java     |   2 +-
 .../cassandra/service/StorageService.java       |  26 ++++
 test/conf/cassandra-rackdc.properties           |  12 ++
 .../apache/cassandra/locator/EC2SnitchTest.java | 118 ++++++++++++++++++-
 10 files changed, 279 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/fd44a69f/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 0362d01..71d947a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.0
+ * Use standard Amazon naming for datacenter and rack in Ec2Snitch 
(CASSANDRA-7839)
  * Fix junit failure for SSTableReaderTest (CASSANDRA-14387)
  * Abstract write path for pluggable storage (CASSANDRA-14118)
  * nodetool describecluster should be more informative (CASSANDRA-13853)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fd44a69f/NEWS.txt
----------------------------------------------------------------------
diff --git a/NEWS.txt b/NEWS.txt
index df4c32a..3be52dc 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -141,6 +141,10 @@ Upgrading
       storage port or native port at nodes you must first upgrade the entire 
cluster
       and clients to 4.0 so they can handle the port not being consistent 
across
       the cluster.
+    - Names of AWS regions/availability zones have been cleaned up to more 
correctly
+      match the Amazon names. There is now a new option in 
conf/cassandra-rackdc.properties
+      that lets users enable the correct names for new clusters, or use the 
legacy
+      names for existing clusters. See conf/cassandra-rackdc.properties for 
details.
 
 Materialized Views
 -------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fd44a69f/conf/cassandra-rackdc.properties
----------------------------------------------------------------------
diff --git a/conf/cassandra-rackdc.properties b/conf/cassandra-rackdc.properties
index 2ea6043..cc472b4 100644
--- a/conf/cassandra-rackdc.properties
+++ b/conf/cassandra-rackdc.properties
@@ -25,3 +25,15 @@ rack=rack1
 
 # Uncomment the following line to make this snitch prefer the internal ip when 
possible, as the Ec2MultiRegionSnitch does.
 # prefer_local=true
+
+# Datacenter and rack naming convention used by the Ec2Snitch and 
Ec2MultiRegionSnitch.
+# Options are:
+#   legacy : datacenter name is the part of the availability zone name 
preceding the last "-"
+#       when the zone ends in -1 and includes the number if not -1. Rack is 
the portion of
+#       the availability zone name following  the last "-".
+#       Examples: us-west-1a => dc: us-west, rack: 1a; us-west-2b => dc: 
us-west-2, rack: 2b; 
+#       YOU MUST USE THIS VALUE IF YOU ARE UPGRADING A PRE-4.0 CLUSTER
+#   standard : Default value. datacenter name is the standard AWS region name, 
including the number.
+#       rack name is the region plus the availability zone letter.
+#       Examples: us-west-1a => dc: us-west-1, rack: us-west-1a; us-west-2b => 
dc: us-west-2, rack: us-west-2b;
+# ec2_naming_scheme=standard

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fd44a69f/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java 
b/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java
index 9ea7e05..010c892 100644
--- a/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java
+++ b/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java
@@ -448,4 +448,9 @@ public class DynamicEndpointSnitch extends 
AbstractEndpointSnitch implements ILa
         }
         return maxScore;
     }
+
+    public boolean validate(Set<String> datacenters, Set<String> racks)
+    {
+        return subsnitch.validate(datacenters, racks);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fd44a69f/src/java/org/apache/cassandra/locator/Ec2Snitch.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/locator/Ec2Snitch.java 
b/src/java/org/apache/cassandra/locator/Ec2Snitch.java
index c7324c8..b6aafd3 100644
--- a/src/java/org/apache/cassandra/locator/Ec2Snitch.java
+++ b/src/java/org/apache/cassandra/locator/Ec2Snitch.java
@@ -24,7 +24,9 @@ import java.net.HttpURLConnection;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.Map;
+import java.util.Set;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.cassandra.db.SystemKeyspace;
@@ -42,30 +44,63 @@ import org.apache.cassandra.utils.FBUtilities;
 public class Ec2Snitch extends AbstractNetworkTopologySnitch
 {
     protected static final Logger logger = 
LoggerFactory.getLogger(Ec2Snitch.class);
-    protected static final String ZONE_NAME_QUERY_URL = 
"http://169.254.169.254/latest/meta-data/placement/availability-zone";;
+
+    private static final String SNITCH_PROP_NAMING_SCHEME = 
"ec2_naming_scheme";
+    static final String EC2_NAMING_LEGACY = "legacy";
+    private static final String EC2_NAMING_STANDARD = "standard";
+
+    private static final String ZONE_NAME_QUERY_URL = 
"http://169.254.169.254/latest/meta-data/placement/availability-zone";;
     private static final String DEFAULT_DC = "UNKNOWN-DC";
     private static final String DEFAULT_RACK = "UNKNOWN-RACK";
+
+    final String ec2region;
+    private final String ec2zone;
+    private final boolean usingLegacyNaming;
+
     private Map<InetAddressAndPort, Map<String, String>> savedEndpoints;
-    protected String ec2zone;
-    protected String ec2region;
 
     public Ec2Snitch() throws IOException, ConfigurationException
     {
+        this(new SnitchProperties());
+    }
+
+    public Ec2Snitch(SnitchProperties props) throws IOException, 
ConfigurationException
+    {
         String az = awsApiCall(ZONE_NAME_QUERY_URL);
-        // Split "us-east-1a" or "asia-1a" into "us-east"/"1a" and "asia"/"1a".
-        String[] splits = az.split("-");
-        ec2zone = splits[splits.length - 1];
 
-        // hack for CASSANDRA-4026
-        ec2region = az.substring(0, az.length() - 1);
-        if (ec2region.endsWith("1"))
-            ec2region = az.substring(0, az.length() - 3);
+        // if using the full naming scheme, region name is created by removing 
letters from the 
+        // end of the availability zone and zone is the full zone name
+        usingLegacyNaming = isUsingLegacyNaming(props);
+        String region;
+        if (usingLegacyNaming)
+        {
+            // Split "us-east-1a" or "asia-1a" into "us-east"/"1a" and 
"asia"/"1a".
+            String[] splits = az.split("-");
+            ec2zone = splits[splits.length - 1];
+
+            // hack for CASSANDRA-4026
+            region = az.substring(0, az.length() - 1);
+            if (region.endsWith("1"))
+                region = az.substring(0, az.length() - 3);
+        }
+        else
+        {
+            // grab the region name, which is embedded in the availability 
zone name.
+            // thus an AZ of "us-east-1a" yields the region name "us-east-1"
+            region = az.replaceFirst("[a-z]+$","");
+            ec2zone = az;
+        }
 
-        String datacenterSuffix = (new SnitchProperties()).get("dc_suffix", 
"");
-        ec2region = ec2region.concat(datacenterSuffix);
+        String datacenterSuffix = props.get("dc_suffix", "");
+        ec2region = region.concat(datacenterSuffix);
         logger.info("EC2Snitch using region: {}, zone: {}.", ec2region, 
ec2zone);
     }
 
+    private static boolean isUsingLegacyNaming(SnitchProperties props)
+    {
+        return props.get(SNITCH_PROP_NAMING_SCHEME, 
EC2_NAMING_STANDARD).equalsIgnoreCase(EC2_NAMING_LEGACY);
+    }
+
     String awsApiCall(String url) throws IOException, ConfigurationException
     {
         // Populate the region and zone by introspection, fail if 404 on 
metadata
@@ -122,4 +157,54 @@ public class Ec2Snitch extends 
AbstractNetworkTopologySnitch
         }
         return state.getApplicationState(ApplicationState.DC).value;
     }
+
+    @Override
+    public boolean validate(Set<String> datacenters, Set<String> racks)
+    {
+        return validate(datacenters, racks, usingLegacyNaming);
+    }
+
+    @VisibleForTesting
+    static boolean validate(Set<String> datacenters, Set<String> racks, 
boolean usingLegacyNaming)
+    {
+        boolean valid = true;
+
+        for (String dc : datacenters)
+        {
+            // predicated on the late-2017 AWS naming 'convention' that all 
region names end with a digit.
+            // Unfortunately, life isn't that simple. Since we allow custom 
datacenter suffixes (CASSANDRA-5155),
+            // an operator could conceiveably make the suffix "a", and thus 
create a region name that looks just like
+            // one of the region's availability zones. (for example, 
"us-east-1a").
+            // Further, we can't make any assumptions of what that suffix 
might be by looking at this node's
+            // datacenterSuffix as conceivably their could be many different 
suffixes in play for a given region.
+            //
+            // Thus, the best we can do is make sure the region name follows
+            // the basic region naming pattern: "us-east-1<custom-suffix>"
+            boolean dcUsesLegacyFormat = !dc.matches("[a-z]+-[a-z].+-[\\d].*");
+            if (dcUsesLegacyFormat != usingLegacyNaming)
+                valid = false;
+        }
+
+        for (String rack : racks)
+        {
+            // predicated on late-2017 AWS naming 'convention' that AZs do not 
have a digit as the first char -
+            // we had that in our legacy AZ (rack) names. Thus we test to see 
if the rack is in the legacy format.
+            //
+            // NOTE: the allowed custom suffix only applies to datacenter 
(region) names, not availability zones.
+            boolean rackUsesLegacyFormat = rack.matches("[\\d][a-z]");
+            if (rackUsesLegacyFormat != usingLegacyNaming)
+                valid = false;
+        }
+
+        if (!valid)
+        {
+            logger.error("This ec2-enabled snitch appears to be using the {} 
naming scheme for regions, " +
+                         "but existing nodes in cluster are using the 
opposite: region(s) = {}, availability zone(s) = {}. " +
+                         "Please check the {} property in the {} configuration 
file for more details.",
+                         usingLegacyNaming ? "legacy" : "standard", 
datacenters, racks,
+                         SNITCH_PROP_NAMING_SCHEME, 
SnitchProperties.RACKDC_PROPERTY_FILENAME);
+        }
+
+        return valid;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fd44a69f/src/java/org/apache/cassandra/locator/IEndpointSnitch.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/locator/IEndpointSnitch.java 
b/src/java/org/apache/cassandra/locator/IEndpointSnitch.java
index 00a1543..63d333b 100644
--- a/src/java/org/apache/cassandra/locator/IEndpointSnitch.java
+++ b/src/java/org/apache/cassandra/locator/IEndpointSnitch.java
@@ -19,6 +19,7 @@ package org.apache.cassandra.locator;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 /**
  * This interface helps determine location of node in the datacenter relative 
to another node.
@@ -63,4 +64,12 @@ public interface IEndpointSnitch
      * to be faster than 2 sequential queries, one against l1 followed by one 
against l2.
      */
     public boolean isWorthMergingForRangeQuery(List<InetAddressAndPort> 
merged, List<InetAddressAndPort> l1, List<InetAddressAndPort> l2);
+
+    /**
+     * Determine if the datacenter or rack values in the current node's snitch 
conflict with those passed in parameters.
+     */
+    default boolean validate(Set<String> datacenters, Set<String> racks)
+    {
+        return true;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fd44a69f/src/java/org/apache/cassandra/locator/SnitchProperties.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/locator/SnitchProperties.java 
b/src/java/org/apache/cassandra/locator/SnitchProperties.java
index 158feef..afb6804 100644
--- a/src/java/org/apache/cassandra/locator/SnitchProperties.java
+++ b/src/java/org/apache/cassandra/locator/SnitchProperties.java
@@ -30,7 +30,7 @@ public class SnitchProperties
     private static final Logger logger = 
LoggerFactory.getLogger(SnitchProperties.class);
     public static final String RACKDC_PROPERTY_FILENAME = 
"cassandra-rackdc.properties";
 
-    private Properties properties;
+    private final Properties properties;
 
     public SnitchProperties()
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fd44a69f/src/java/org/apache/cassandra/service/StorageService.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/StorageService.java 
b/src/java/org/apache/cassandra/service/StorageService.java
index e5911f3..400ab75 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -482,6 +482,8 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
         if (epStates.get(replaceAddress) == null)
             throw new RuntimeException(String.format("Cannot replace_address 
%s because it doesn't exist in gossip", replaceAddress));
 
+        validateEndpointSnitch(epStates.values().iterator());
+
         try
         {
             VersionedValue tokensVersionedValue = 
epStates.get(replaceAddress).getApplicationState(ApplicationState.TOKENS);
@@ -527,6 +529,8 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
                                                      
FBUtilities.getBroadcastAddressAndPort()));
         }
 
+        validateEndpointSnitch(epStates.values().iterator());
+
         if (shouldBootstrap() && useStrictConsistency && 
!allowSimultaneousMoves())
         {
             for (Map.Entry<InetAddressAndPort, EndpointState> entry : 
epStates.entrySet())
@@ -550,6 +554,28 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
         }
     }
 
+    private static void validateEndpointSnitch(Iterator<EndpointState> 
endpointStates)
+    {
+        Set<String> datacenters = new HashSet<>();
+        Set<String> racks = new HashSet<>();
+        while (endpointStates.hasNext())
+        {
+            EndpointState state = endpointStates.next();
+            VersionedValue val = 
state.getApplicationState(ApplicationState.DC);
+            if (val != null)
+                datacenters.add(val.value);
+            val = state.getApplicationState(ApplicationState.RACK);
+            if (val != null)
+                racks.add(val.value);
+        }
+
+        IEndpointSnitch snitch = DatabaseDescriptor.getEndpointSnitch();
+        if (!snitch.validate(datacenters, racks))
+        {
+            throw new IllegalStateException();
+        }
+    }
+
     private boolean allowSimultaneousMoves()
     {
         return allowSimultaneousMoves && DatabaseDescriptor.getNumTokens() == 
1;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fd44a69f/test/conf/cassandra-rackdc.properties
----------------------------------------------------------------------
diff --git a/test/conf/cassandra-rackdc.properties 
b/test/conf/cassandra-rackdc.properties
index be2e7d2..742def3 100644
--- a/test/conf/cassandra-rackdc.properties
+++ b/test/conf/cassandra-rackdc.properties
@@ -22,3 +22,15 @@ rack=RAC1
 # Add a suffix to a datacenter name. Used by the Ec2Snitch and 
Ec2MultiRegionSnitch
 # to append a string to the EC2 region name.
 #dc_suffix=
+
+# Datacenter and rack naming convention used by the Ec2Snitch and 
Ec2MultiRegionSnitch.
+# Options are:
+#   legacy : datacenter name is the part of the availability zone name 
preceding the last "-"
+#       when the zone ends in -1 and includes the number if not -1. Rack is 
the portion of
+#       the availability zone name following  the last "-".
+#       Examples: us-west-1a => dc: us-west, rack: 1a; us-west-2b => dc: 
us-west-2, rack: 2b; 
+#   standard : datacenter name is the standard AWS region name, including the 
number. rack name is the
+#       region plus the availability zone letter.
+#       Examples: us-west-1a => dc: us-west-1, rack: us-west-1a; us-west-2b => 
dc: us-west-2, rack: us-west-2b;
+# default: standard
+ec2_naming_scheme=standard

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fd44a69f/test/unit/org/apache/cassandra/locator/EC2SnitchTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/locator/EC2SnitchTest.java 
b/test/unit/org/apache/cassandra/locator/EC2SnitchTest.java
index 182ff1a..062bf69 100644
--- a/test/unit/org/apache/cassandra/locator/EC2SnitchTest.java
+++ b/test/unit/org/apache/cassandra/locator/EC2SnitchTest.java
@@ -20,11 +20,14 @@ package org.apache.cassandra.locator;
 
 
 import java.io.IOException;
-import java.net.UnknownHostException;
+import java.util.Collections;
 import java.util.EnumMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 import org.junit.AfterClass;
+import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -37,12 +40,21 @@ import org.apache.cassandra.gms.Gossiper;
 import org.apache.cassandra.gms.VersionedValue;
 import org.apache.cassandra.service.StorageService;
 
+import static org.apache.cassandra.locator.Ec2Snitch.EC2_NAMING_LEGACY;
 import static org.junit.Assert.assertEquals;
 
 public class EC2SnitchTest
 {
     private static String az;
 
+    private final SnitchProperties legacySnitchProps = new SnitchProperties()
+    {
+        public String get(String propertyName, String defaultValue)
+        {
+            return propertyName.equals("ec2_naming_scheme") ? 
EC2_NAMING_LEGACY : super.get(propertyName, defaultValue);
+        }
+    };
+
     @BeforeClass
     public static void setup() throws Exception
     {
@@ -60,6 +72,11 @@ public class EC2SnitchTest
             super();
         }
 
+        public TestEC2Snitch(SnitchProperties props) throws IOException, 
ConfigurationException
+        {
+            super(props);
+        }
+
         @Override
         String awsApiCall(String url) throws IOException, 
ConfigurationException
         {
@@ -68,10 +85,10 @@ public class EC2SnitchTest
     }
 
     @Test
-    public void testRac() throws IOException, ConfigurationException
+    public void testLegacyRac() throws IOException, ConfigurationException
     {
         az = "us-east-1d";
-        Ec2Snitch snitch = new TestEC2Snitch();
+        Ec2Snitch snitch = new TestEC2Snitch(legacySnitchProps);
         InetAddressAndPort local = InetAddressAndPort.getByName("127.0.0.1");
         InetAddressAndPort nonlocal = 
InetAddressAndPort.getByName("127.0.0.7");
 
@@ -87,17 +104,106 @@ public class EC2SnitchTest
         assertEquals("us-east", snitch.getDatacenter(local));
         assertEquals("1d", snitch.getRack(local));
     }
-    
+
     @Test
-    public void testNewRegions() throws IOException, ConfigurationException
+    public void testLegacyNewRegions() throws IOException, 
ConfigurationException
     {
         az = "us-east-2d";
-        Ec2Snitch snitch = new TestEC2Snitch();
+        Ec2Snitch snitch = new TestEC2Snitch(legacySnitchProps);
         InetAddressAndPort local = InetAddressAndPort.getByName("127.0.0.1");
         assertEquals("us-east-2", snitch.getDatacenter(local));
         assertEquals("2d", snitch.getRack(local));
     }
 
+    @Test
+    public void testFullNamingScheme() throws IOException, 
ConfigurationException
+    {
+        InetAddressAndPort local = InetAddressAndPort.getByName("127.0.0.1");
+        az = "us-east-2d";
+        Ec2Snitch snitch = new TestEC2Snitch();
+
+        assertEquals("us-east-2", snitch.getDatacenter(local));
+        assertEquals("us-east-2d", snitch.getRack(local));
+
+        az = "us-west-1a";
+        snitch = new TestEC2Snitch();
+
+        assertEquals("us-west-1", snitch.getDatacenter(local));
+        assertEquals("us-west-1a", snitch.getRack(local));
+    }
+
+    @Test
+    public void validateDatacenter_RequiresLegacy_CorrectAmazonName()
+    {
+        Set<String> datacenters = new HashSet<>();
+        datacenters.add("us-east-1");
+        Assert.assertFalse(Ec2Snitch.validate(datacenters, 
Collections.emptySet(), true));
+    }
+
+    @Test
+    public void validateDatacenter_RequiresLegacy_LegacyName()
+    {
+        Set<String> datacenters = new HashSet<>();
+        datacenters.add("us-east");
+        Assert.assertTrue(Ec2Snitch.validate(datacenters, 
Collections.emptySet(), true));
+    }
+
+    @Test
+    public void validate_RequiresLegacy_HappyPath()
+    {
+        Set<String> datacenters = new HashSet<>();
+        datacenters.add("us-east");
+        Set<String> racks = new HashSet<>();
+        racks.add("1a");
+        Assert.assertTrue(Ec2Snitch.validate(datacenters, racks, true));
+    }
+
+    @Test
+    public void validate_RequiresLegacy_HappyPathWithDCSuffix()
+    {
+        Set<String> datacenters = new HashSet<>();
+        datacenters.add("us-east_CUSTOM_SUFFIX");
+        Set<String> racks = new HashSet<>();
+        racks.add("1a");
+        Assert.assertTrue(Ec2Snitch.validate(datacenters, racks, true));
+    }
+
+    @Test
+    public void validateRack_RequiresAmazonName_CorrectAmazonName()
+    {
+        Set<String> racks = new HashSet<>();
+        racks.add("us-east-1a");
+        Assert.assertTrue(Ec2Snitch.validate(Collections.emptySet(), racks, 
false));
+    }
+
+    @Test
+    public void validateRack_RequiresAmazonName_LegacyName()
+    {
+        Set<String> racks = new HashSet<>();
+        racks.add("1a");
+        Assert.assertFalse(Ec2Snitch.validate(Collections.emptySet(), racks, 
false));
+    }
+
+    @Test
+    public void validate_RequiresAmazonName_HappyPath()
+    {
+        Set<String> datacenters = new HashSet<>();
+        datacenters.add("us-east-1");
+        Set<String> racks = new HashSet<>();
+        racks.add("us-east-1a");
+        Assert.assertTrue(Ec2Snitch.validate(datacenters, racks, false));
+    }
+
+    @Test
+    public void validate_RequiresAmazonName_HappyPathWithDCSuffix()
+    {
+        Set<String> datacenters = new HashSet<>();
+        datacenters.add("us-east-1_CUSTOM_SUFFIX");
+        Set<String> racks = new HashSet<>();
+        racks.add("us-east-1a");
+        Assert.assertTrue(Ec2Snitch.validate(datacenters, racks, false));
+    }
+
     @AfterClass
     public static void tearDown()
     {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to