You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by st...@apache.org on 2023/02/26 01:39:56 UTC
[impala] 02/02: IMPALA-11945: Fix Flaky Test in JwtHttpTest
This is an automated email from the ASF dual-hosted git repository.
stigahuang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git
commit d0592c0dbf4d634cc26b2e9872a9f62af5249cdd
Author: jasonmfehr <jf...@cloudera.com>
AuthorDate: Fri Feb 24 12:54:03 2023 -0800
IMPALA-11945: Fix Flaky Test in JwtHttpTest
The JwtHttpTest.testJwtAuthWithUntrustedJwksHttpsUrl test has been
flaky in the impala-asf-master-core Jenkins build. This build was
executed twice with this test passing in one run and failing in the
other.
This test and another test named
testJwtAuthWithTrustedJwksHttpsUrlInvalidCN both follow the same
pattern. They attempt to start up a cluster with incorrectly
configured Impala daemons. Then, the Impala coordinator's log file
is searched to ensure the coordinator failed to start up for the
expected reason. Both these tests were introduced by IMPALA-11922.
The theory for the test flakiness is that the Impala coordinator logs
did not finish writing to disk before they were checked for the
expected startup failure message. The evidence backing this theory
is that all expected log messages were present in the log file except
for the final log line containing the error message.
Three changes were made to fix the flakiness
1. The tests where log files are search for startup failure messages
now use a single coordinator. Only a single coordinator is needed
thus this change eliminates potential issues caused by multiple
coordinators.
2. The tests sleep 5 seconds before searching the log files to give
time for the logs to be fully written to disk.
3. Log buffering in the Impala daemons was turned off by setting the
logbuflevel startup flag to -1 which turns off in-memory log
buffering and writes the logs directly to disk.
Change-Id: I26d8c2cffa7bc095b81eb572709f55b04ac1fa67
Reviewed-on: http://gerrit.cloudera.org:8080/19536
Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
.../apache/impala/customcluster/JwtHttpTest.java | 83 +++++++++++++++++-----
1 file changed, 65 insertions(+), 18 deletions(-)
diff --git a/fe/src/test/java/org/apache/impala/customcluster/JwtHttpTest.java b/fe/src/test/java/org/apache/impala/customcluster/JwtHttpTest.java
index 4a72c3e39..82fba0618 100644
--- a/fe/src/test/java/org/apache/impala/customcluster/JwtHttpTest.java
+++ b/fe/src/test/java/org/apache/impala/customcluster/JwtHttpTest.java
@@ -36,6 +36,7 @@ import org.apache.hive.service.rpc.thrift.*;
import org.apache.impala.testutil.WebClient;
import org.apache.impala.testutil.X509CertChain;
import org.apache.thrift.transport.THttpClient;
+import org.hamcrest.Matcher;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.junit.After;
import org.junit.Test;
@@ -51,6 +52,7 @@ public class JwtHttpTest {
private static final String CA_CERT = "cacert.pem";
private static final String SERVER_CERT = "server-cert.pem";
private static final String SERVER_KEY = "server-key.pem";
+ private static final String JWKS_FILE_NAME = "jwks_rs256.json";
WebClient client_ = new WebClient();
@@ -89,13 +91,34 @@ public class JwtHttpTest {
private void setUp(String impaladArgs, String catalogdArgs,
String statestoredArgs, int expectedRetCode)
throws Exception {
- if (createJWKSForWebServer_) createTempJWKSInWebServerRootDir("jwks_rs256.json");
+ if (createJWKSForWebServer_) createTempJWKSInWebServerRootDir(JWKS_FILE_NAME);
int ret = CustomClusterRunner.StartImpalaCluster(
impaladArgs, catalogdArgs, statestoredArgs);
assertEquals(expectedRetCode, ret);
}
+ /**
+ * Helper method to start a JWT auth enabled Impala cluster that has only a single
+ * coordinator daemon process.
+ *
+ * @param impaladArgs startup flags to send to the impala coordinator/executors
+ * @param catalogdArgs startup flags to send to the impala catalog
+ * @param statestoredArgs startup flags to send to the statestore
+ * @param expectedRetCode expected exit code for the start impala cluster command,
+ * if the cluster is expected to start successfully, set to 0
+ */
+ private void setUpWithSingleCoordinator(String impaladArgs, String catalogdArgs,
+ String statestoredArgs, int expectedRetCode)
+ throws Exception {
+ if (createJWKSForWebServer_) createTempJWKSInWebServerRootDir(JWKS_FILE_NAME);
+
+ int ret = CustomClusterRunner.StartImpalaCluster(
+ impaladArgs, catalogdArgs, statestoredArgs, new HashMap<String, String>(),
+ "--num_coordinators=1");
+ assertEquals(expectedRetCode, ret);
+ }
+
@After
public void cleanUp() throws Exception {
// Leave a cluster running with the default configuration, then delete temporary
@@ -178,7 +201,8 @@ public class JwtHttpTest {
public void testJwtAuth() throws Exception {
createJWKSForWebServer_ = false;
String jwksFilename =
- new File(System.getenv("IMPALA_HOME"), "testdata/jwt/jwks_rs256.json").getPath();
+ new File(System.getenv("IMPALA_HOME"),
+ String.format("testdata/jwt/%s", JWKS_FILE_NAME)).getPath();
setUp(String.format(
"--jwt_token_auth=true --jwt_validate_signature=true --jwks_file_path=%s "
+ "--jwt_allow_without_tls=true",
@@ -404,7 +428,7 @@ public class JwtHttpTest {
String jwksHttpUrl = "https://localhost:25010/www/temp_jwks.json";
String impaladJwtArgs = String.format("--jwt_token_auth=true "
+ "--jwt_validate_signature=true --jwks_url=%s "
- + "--jwt_allow_without_tls=true --log_dir=%s ",
+ + "--jwt_allow_without_tls=true --log_dir=%s --logbuflevel=-1 ",
jwksHttpUrl, logDir.toAbsolutePath());
String expectedErrString = String.format("Impalad services did not start correctly, "
+ "exiting. Error: Error downloading JWKS from '%s': Network error: curl "
@@ -413,14 +437,9 @@ public class JwtHttpTest {
// cluster start will fail because the TLS cert returned by the
// JWKS server is not trusted
- setUp(impaladJwtArgs, "", statestoreWebserverArgs, 1);
-
- // check in the impalad logs that the server startup failed for the expected reason
- List<String> logLines = Files.readAllLines(logDir.resolve("impalad.ERROR"));
+ setUpWithSingleCoordinator(impaladJwtArgs, "", statestoreWebserverArgs, 1);
- assertThat(String.format("Impalad startup failed but not for the expected reason. "
- + "See logs in the '%s' folder for details.", logDir), logLines,
- hasItem(containsString(expectedErrString)));
+ checkCoordinatorLogs(expectedErrString, logDir);
}
/**
@@ -448,8 +467,9 @@ public class JwtHttpTest {
String jwksHttpUrl = "https://localhost:25010/www/temp_jwks.json";
String impaladJwtArgs = String.format("--jwt_token_auth=true "
+ "--jwt_validate_signature=true --jwks_url=%s "
- + "--jwt_allow_without_tls=true --log_dir=%s --jwks_ca_certificate=%s ",
- jwksHttpUrl, logDir.toAbsolutePath(), Paths.get(certDir, CA_CERT));
+ + "--jwt_allow_without_tls=true --log_dir=%s --jwks_ca_certificate=%s "
+ + "--logbuflevel=-1 ", jwksHttpUrl, logDir.toAbsolutePath(),
+ Paths.get(certDir, CA_CERT));
String expectedErrString = String.format("Impalad services did not start correctly, "
+ "exiting. Error: Error downloading JWKS from '%s': Network error: curl "
+ "error: SSL peer certificate or SSH remote key was not OK: SSL: "
@@ -458,13 +478,9 @@ public class JwtHttpTest {
// cluster start will fail because the TLS cert returned by the
// JWKS server is not trusted
- setUp(impaladJwtArgs, "", statestoreWebserverArgs, 1);
+ setUpWithSingleCoordinator(impaladJwtArgs, "", statestoreWebserverArgs, 1);
- // check in the impalad logs that the server startup failed for the expected reason
- List<String> logLines = Files.readAllLines(logDir.resolve("impalad.ERROR"));
- assertThat(String.format("Impalad startup failed but not for the expected reason. "
- + "See logs in the '%s' folder for details.", logDir), logLines,
- hasItem(containsString(expectedErrString)));
+ checkCoordinatorLogs(expectedErrString, logDir);
}
/**
@@ -524,4 +540,35 @@ public class JwtHttpTest {
return certDir.toString();
}
+
+ /**
+ * Asserts that the specified string is present in the impalad.ERROR file within the
+ * specified log directory.
+ *
+ * @param expectedString The impalad.ERROR file is searched for this string. If it is
+ * not found, the test fails.
+ * @param logDir Location of the directory where log files are stored.
+ */
+ private void checkCoordinatorLogs(String expectedString, Path logDir)
+ throws IOException, InterruptedException {
+ // check in the impalad logs that the server startup failed for the expected reason
+ List<String> logLines = null;
+ Matcher<Iterable<? super String>> m = hasItem(containsString(expectedString));
+
+ // writing logs to disk may take some time, try a few times to search for the
+ // expected error in the log
+ for (int i=0; i<10; i++) {
+ logLines = Files.readAllLines(logDir.resolve("impalad.ERROR"));
+ if (m.matches(logLines)) {
+ break;
+ }
+ Thread.sleep(250);
+ }
+
+ // runs the matcher one more time to ensure a descriptive failure message is
+ // generated if the assert fails
+ assertThat(String.format("Impalad startup failed but not for the expected reason. "
+ + "See logs in the '%s' folder for details.", logDir), logLines,
+ hasItem(containsString(expectedString)));
+ }
}