You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pr@cassandra.apache.org by "jacek-lewandowski (via GitHub)" <gi...@apache.org> on 2023/06/27 05:20:46 UTC

[GitHub] [cassandra] jacek-lewandowski commented on a diff in pull request #2403: CASSANDRA-16555 trunk

jacek-lewandowski commented on code in PR #2403:
URL: https://github.com/apache/cassandra/pull/2403#discussion_r1243134753


##########
src/java/org/apache/cassandra/locator/AbstractCloudMetadataServiceConnector.java:
##########
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.locator;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+abstract class AbstractCloudMetadataServiceConnector
+{
+    protected String metadataServiceUrl;

Review Comment:
   Can it be final?



##########
src/java/org/apache/cassandra/locator/Ec2MetadataServiceConnector.java:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.locator;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.utils.Clock;
+import org.apache.cassandra.utils.Pair;
+
+import static java.lang.String.format;
+import static java.util.Arrays.stream;
+import static java.util.stream.Collectors.joining;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.EC2MetadataType.v2;
+
+abstract class Ec2MetadataServiceConnector extends AbstractCloudMetadataServiceConnector
+{
+    static final String EC2_METADATA_TYPE_PROPERTY = "ec2_metadata_type";
+    static final String EC2_METADATA_URL_PROPERTY = "ec2_metadata_url";
+    static final String DEFAULT_EC2_METADATA_URL = "http://169.254.169.254";
+
+    Ec2MetadataServiceConnector(SnitchProperties properties)
+    {
+        metadataServiceUrl = properties.get(EC2_METADATA_URL_PROPERTY, DEFAULT_EC2_METADATA_URL);
+    }
+
+    enum EC2MetadataType
+    {
+        v1(props -> Ec2MetadataServiceConnector.V1Connector.create(props)),
+        v2(props -> Ec2MetadataServiceConnector.V2Connector.create(props));
+
+        private final Function<SnitchProperties, Ec2MetadataServiceConnector> creator;
+
+        EC2MetadataType(Function<SnitchProperties, Ec2MetadataServiceConnector> creator)
+        {
+            this.creator = creator;
+        }
+
+        Ec2MetadataServiceConnector create(SnitchProperties properties)
+        {
+            return creator.apply(properties);
+        }
+    }
+
+    static Ec2MetadataServiceConnector create(SnitchProperties props)
+    {
+        try
+        {
+            return EC2MetadataType.valueOf(props.get(EC2_METADATA_TYPE_PROPERTY, v2.name())).create(props);
+        }
+        catch (IllegalArgumentException ex)
+        {
+            throw new ConfigurationException(format("%s must be one of %s", EC2_METADATA_TYPE_PROPERTY,
+                                                    stream(EC2MetadataType.values()).map(Enum::name).collect(joining(", "))));
+        }
+    }
+
+    static class V1Connector extends Ec2MetadataServiceConnector
+    {
+        static V1Connector create(SnitchProperties props)
+        {
+            return new V1Connector(props);
+        }
+
+        V1Connector(SnitchProperties props)
+        {
+            super(props);
+        }
+
+        @Override
+        public String toString()
+        {
+            return V1Connector.class.getName() + '{' + EC2_METADATA_URL_PROPERTY + '=' + metadataServiceUrl + '}';

Review Comment:
   nit: maybe use `String.format`



##########
src/java/org/apache/cassandra/locator/Ec2MetadataServiceConnector.java:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.locator;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.utils.Clock;
+import org.apache.cassandra.utils.Pair;
+
+import static java.lang.String.format;
+import static java.util.Arrays.stream;
+import static java.util.stream.Collectors.joining;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.EC2MetadataType.v2;
+
+abstract class Ec2MetadataServiceConnector extends AbstractCloudMetadataServiceConnector
+{
+    static final String EC2_METADATA_TYPE_PROPERTY = "ec2_metadata_type";
+    static final String EC2_METADATA_URL_PROPERTY = "ec2_metadata_url";
+    static final String DEFAULT_EC2_METADATA_URL = "http://169.254.169.254";
+
+    Ec2MetadataServiceConnector(SnitchProperties properties)
+    {
+        metadataServiceUrl = properties.get(EC2_METADATA_URL_PROPERTY, DEFAULT_EC2_METADATA_URL);
+    }
+
+    enum EC2MetadataType
+    {
+        v1(props -> Ec2MetadataServiceConnector.V1Connector.create(props)),
+        v2(props -> Ec2MetadataServiceConnector.V2Connector.create(props));
+
+        private final Function<SnitchProperties, Ec2MetadataServiceConnector> creator;
+
+        EC2MetadataType(Function<SnitchProperties, Ec2MetadataServiceConnector> creator)
+        {
+            this.creator = creator;
+        }
+
+        Ec2MetadataServiceConnector create(SnitchProperties properties)
+        {
+            return creator.apply(properties);
+        }
+    }
+
+    static Ec2MetadataServiceConnector create(SnitchProperties props)
+    {
+        try
+        {
+            return EC2MetadataType.valueOf(props.get(EC2_METADATA_TYPE_PROPERTY, v2.name())).create(props);
+        }
+        catch (IllegalArgumentException ex)
+        {
+            throw new ConfigurationException(format("%s must be one of %s", EC2_METADATA_TYPE_PROPERTY,
+                                                    stream(EC2MetadataType.values()).map(Enum::name).collect(joining(", "))));
+        }
+    }
+
+    static class V1Connector extends Ec2MetadataServiceConnector
+    {
+        static V1Connector create(SnitchProperties props)
+        {
+            return new V1Connector(props);
+        }
+
+        V1Connector(SnitchProperties props)
+        {
+            super(props);
+        }
+
+        @Override
+        public String toString()
+        {
+            return V1Connector.class.getName() + '{' + EC2_METADATA_URL_PROPERTY + '=' + metadataServiceUrl + '}';
+        }
+    }
+
+    static class V2Connector extends Ec2MetadataServiceConnector
+    {
+        @VisibleForTesting

Review Comment:
   nit: perhaps we do not need to annotate static final fields with `@VisibleForTesting`



##########
test/unit/org/apache/cassandra/locator/Ec2ConnectorTest.java:
##########
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.locator;
+
+import java.time.Duration;
+import java.util.Properties;
+
+import org.junit.Test;
+
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.locator.Ec2MetadataServiceConnector.EC2MetadataType;
+import org.apache.cassandra.locator.Ec2MetadataServiceConnector.V1Connector;
+import org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector;
+
+import static java.lang.String.format;
+import static java.util.Arrays.stream;
+import static java.util.stream.Collectors.joining;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.DEFAULT_EC2_METADATA_URL;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.EC2_METADATA_TYPE_PROPERTY;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector.AWS_EC2_METADATA_TOKEN_TTL_SECONDS_HEADER_PROPERTY;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector.MAX_TOKEN_TIME_IN_SECONDS;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector.MIN_TOKEN_TIME_IN_SECONDS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class Ec2ConnectorTest
+{
+    @Test
+    public void testV1Configuration()
+    {
+        Properties p = new Properties();
+        p.setProperty(EC2_METADATA_TYPE_PROPERTY, EC2MetadataType.v1.name());
+        Ec2MetadataServiceConnector ec2Connector = Ec2MetadataServiceConnector.create(new SnitchProperties(p));
+
+        assertTrue(ec2Connector instanceof V1Connector);
+
+        assertEquals(DEFAULT_EC2_METADATA_URL, ec2Connector.metadataServiceUrl);
+    }
+
+    @Test
+    public void testV2Configuration()
+    {
+        Ec2MetadataServiceConnector ec2Connector = Ec2MetadataServiceConnector.create(new SnitchProperties(new Properties()));
+
+        // v2 connector by default
+        assertTrue(ec2Connector instanceof V2Connector);
+        assertEquals(DEFAULT_EC2_METADATA_URL, ec2Connector.metadataServiceUrl);
+        assertEquals(Duration.ofSeconds(MAX_TOKEN_TIME_IN_SECONDS), ((V2Connector) ec2Connector).tokenTTL);
+    }
+
+    @Test
+    public void testInvalidConfiguration()
+    {
+        try
+        {
+            Properties p = new Properties();
+            p.setProperty(EC2_METADATA_TYPE_PROPERTY, "non-existent");
+
+            Ec2MetadataServiceConnector.create(new SnitchProperties(p));
+            fail("it should not be possible create a connector of type non-existent");
+        }
+        catch (ConfigurationException ex)

Review Comment:
   Could you use AssertJ in tests? (see https://www.tabnine.com/code/java/methods/org.assertj.core.api.Assertions/assertThatExceptionOfType)



##########
test/unit/org/apache/cassandra/locator/Ec2V2ConnectorMockingTest.java:
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.locator;
+
+import java.util.Properties;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.github.tomakehurst.wiremock.client.MappingBuilder;
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.put;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.EC2MetadataType.v2;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.EC2_METADATA_TYPE_PROPERTY;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.V1Connector.EC2_METADATA_URL_PROPERTY;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector.AWS_EC2_METADATA_TOKEN_HEADER;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector.AWS_EC2_METADATA_TOKEN_TTL_SECONDS_HEADER_PROPERTY;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector.TOKEN_QUERY;
+import static org.apache.cassandra.locator.Ec2Snitch.ZONE_NAME_QUERY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class Ec2V2ConnectorMockingTest

Review Comment:
   maybe you merge these tests to Ec2ConnectorTest?



##########
src/java/org/apache/cassandra/locator/Ec2MetadataServiceConnector.java:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.locator;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.utils.Clock;
+import org.apache.cassandra.utils.Pair;
+
+import static java.lang.String.format;
+import static java.util.Arrays.stream;
+import static java.util.stream.Collectors.joining;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.EC2MetadataType.v2;
+
+abstract class Ec2MetadataServiceConnector extends AbstractCloudMetadataServiceConnector
+{
+    static final String EC2_METADATA_TYPE_PROPERTY = "ec2_metadata_type";
+    static final String EC2_METADATA_URL_PROPERTY = "ec2_metadata_url";
+    static final String DEFAULT_EC2_METADATA_URL = "http://169.254.169.254";
+
+    Ec2MetadataServiceConnector(SnitchProperties properties)
+    {
+        metadataServiceUrl = properties.get(EC2_METADATA_URL_PROPERTY, DEFAULT_EC2_METADATA_URL);
+    }
+
+    enum EC2MetadataType
+    {
+        v1(props -> Ec2MetadataServiceConnector.V1Connector.create(props)),

Review Comment:
   Uppercase for enum names?



##########
test/unit/org/apache/cassandra/locator/Ec2SnitchTest.java:
##########
@@ -71,30 +124,60 @@ public static void setup() throws Exception
         StorageService.instance.initServer(0);
     }
 
-    private class TestEC2Snitch extends Ec2Snitch
+    private static class TestEc2Snitch extends Ec2Snitch
     {
-        public TestEC2Snitch() throws IOException, ConfigurationException
+        public TestEc2Snitch() throws IOException, ConfigurationException
         {
-            super();
+            this(new SnitchProperties());
         }
 
-        public TestEC2Snitch(SnitchProperties props) throws IOException, ConfigurationException
+        public TestEc2Snitch(SnitchProperties props) throws IOException, ConfigurationException

Review Comment:
   What do you think about refactoring this test a bit? We have separated a snitch from a connector so it would be enough to simply mock the connector and do not bother distinguishing between v1 and v2 at all. The whole test would be much simpler and easier to follow



##########
test/unit/org/apache/cassandra/locator/Ec2V2ConnectorMockingTest.java:
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.locator;
+
+import java.util.Properties;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.github.tomakehurst.wiremock.client.MappingBuilder;
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.put;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.EC2MetadataType.v2;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.EC2_METADATA_TYPE_PROPERTY;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.V1Connector.EC2_METADATA_URL_PROPERTY;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector.AWS_EC2_METADATA_TOKEN_HEADER;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector.AWS_EC2_METADATA_TOKEN_TTL_SECONDS_HEADER_PROPERTY;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.V2Connector.TOKEN_QUERY;
+import static org.apache.cassandra.locator.Ec2Snitch.ZONE_NAME_QUERY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class Ec2V2ConnectorMockingTest
+{
+    private static final String token = "thisismytoken";
+    private static final String az = "us-east-1a";
+
+    @Rule
+    public WireMockRule v2Service = new WireMockRule(wireMockConfig().bindAddress("127.0.0.1").port(8080));
+
+    @Test
+    public void testV2Connector() throws Throwable
+    {
+        v2Service.stubFor(tokenRequest(100, 200, token));
+        v2Service.stubFor(azRequest(az, 200, token));
+
+        assertEquals(az, getConnector(100).apiCall(ZONE_NAME_QUERY));
+    }
+
+    @Test
+    public void testV2ConnectorWhenUnauthorized() throws Throwable
+    {
+        String unauthorizedBody = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" +
+                                  "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" +
+                                  "\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" +
+                                  "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" +
+                                  " <head>\n" +
+                                  "  <title>401 - Unauthorized</title>\n" +
+                                  " </head>\n" +
+                                  " <body>\n" +
+                                  "  <h1>401 - Unauthorized</h1>\n" +
+                                  " </body>\n" +
+                                  "</html>\n";
+
+        v2Service.stubFor(tokenRequest(100, 200, token));
+
+        v2Service.stubFor(get(urlEqualTo(ZONE_NAME_QUERY)).withHeader(AWS_EC2_METADATA_TOKEN_HEADER, equalTo(token))
+                                                          .willReturn(aResponse().withStatus(401)
+                                                                                 .withStatusMessage("Unauthorized")
+                                                                                 .withHeader("Content-Type", "text/html")
+                                                                                 .withHeader("Content-Length", String.valueOf(unauthorizedBody.getBytes(UTF_8).length))));
+
+        V2Connector.HTTP_REQUEST_RETRIES = 0;
+        Ec2MetadataServiceConnector v2Connector = getConnector(100);
+
+        try
+        {
+            v2Connector.apiCall(ZONE_NAME_QUERY);

Review Comment:
   nit: maybe AssertJ?



##########
src/java/org/apache/cassandra/locator/Ec2MetadataServiceConnector.java:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.locator;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.utils.Clock;
+import org.apache.cassandra.utils.Pair;
+
+import static java.lang.String.format;
+import static java.util.Arrays.stream;
+import static java.util.stream.Collectors.joining;
+import static org.apache.cassandra.locator.Ec2MetadataServiceConnector.EC2MetadataType.v2;
+
+abstract class Ec2MetadataServiceConnector extends AbstractCloudMetadataServiceConnector
+{
+    static final String EC2_METADATA_TYPE_PROPERTY = "ec2_metadata_type";
+    static final String EC2_METADATA_URL_PROPERTY = "ec2_metadata_url";
+    static final String DEFAULT_EC2_METADATA_URL = "http://169.254.169.254";
+
+    Ec2MetadataServiceConnector(SnitchProperties properties)
+    {
+        metadataServiceUrl = properties.get(EC2_METADATA_URL_PROPERTY, DEFAULT_EC2_METADATA_URL);
+    }
+
+    enum EC2MetadataType
+    {
+        v1(props -> Ec2MetadataServiceConnector.V1Connector.create(props)),
+        v2(props -> Ec2MetadataServiceConnector.V2Connector.create(props));
+
+        private final Function<SnitchProperties, Ec2MetadataServiceConnector> creator;

Review Comment:
   maybe name it "provider" ?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org
For additional commands, e-mail: pr-help@cassandra.apache.org