This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 407eb2a592 HDDS-9548. Intermittent failures in 
TestRootCaRotationPoller (#5525)
407eb2a592 is described below

commit 407eb2a5926b6d539a7587fa1e72d861e4644d02
Author: Galsza <[email protected]>
AuthorDate: Thu Nov 16 16:01:17 2023 +0100

    HDDS-9548. Intermittent failures in TestRootCaRotationPoller (#5525)
---
 .../certificate/client/RootCaRotationPoller.java   | 12 +++-
 .../TestRootCaRotationPoller.java                  | 81 +++++++++++++---------
 2 files changed, 59 insertions(+), 34 deletions(-)

diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java
index 24f47ed499..ba939524d7 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/x509/certificate/client/RootCaRotationPoller.java
@@ -73,7 +73,14 @@ public class RootCaRotationPoller implements Runnable, 
Closeable {
     certificateRenewalError = new AtomicBoolean(false);
   }
 
-  private void pollRootCas() {
+  /**
+   * Polls the SCM for root ca certificates and compares them to the known
+   * set of root ca certificates. If there are new root ca certificates it
+   * invokes the necessary handlers provided in rootCaRotationProcessors.
+   *
+   * @return returns true if the SCM provided a new root ca certificate.
+   */
+  void pollRootCas() {
     try {
       List<String> pemEncodedRootCaList =
           scmSecureClient.getAllRootCaCertificates();
@@ -99,8 +106,9 @@ public class RootCaRotationPoller implements Runnable, 
Closeable {
       allRootCAProcessorFutures.whenComplete((unused, throwable) -> {
         if (throwable == null && !certificateRenewalError.get()) {
           knownRootCerts = new HashSet<>(rootCAsFromSCM);
+          LOG.info("Certificate processing was successful.");
         } else {
-          LOG.info("Certificate consumption was unsuccesfull. " +
+          LOG.info("Certificate consumption was unsuccessful. " +
               (certificateRenewalError.get() ?
                   "There was a caught exception when trying to sign the " +
                       "certificate" :
diff --git 
a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java
 
b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/client/TestRootCaRotationPoller.java
similarity index 73%
rename from 
hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java
rename to 
hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/client/TestRootCaRotationPoller.java
index f0b81c7d6e..e66f1e1a50 100644
--- 
a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/utils/TestRootCaRotationPoller.java
+++ 
b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/security/x509/certificate/client/TestRootCaRotationPoller.java
@@ -16,12 +16,13 @@
  * limitations under the License.
  *
  */
-package org.apache.hadoop.hdds.security.x509.certificate.utils;
+package org.apache.hadoop.hdds.security.x509.certificate.client;
 
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import 
org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolClientSideTranslatorPB;
 import org.apache.hadoop.hdds.security.SecurityConfig;
-import 
org.apache.hadoop.hdds.security.x509.certificate.client.RootCaRotationPoller;
+import org.apache.hadoop.hdds.security.x509.certificate.utils.CertificateCodec;
+import 
org.apache.hadoop.hdds.security.x509.certificate.utils.SelfSignedCertificate;
 import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
 import org.apache.ozone.test.GenericTestUtils;
 import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
@@ -69,6 +70,7 @@ public class TestRootCaRotationPoller {
 
   @Test
   public void testPollerDoesNotInvokeRootCaProcessor() throws Exception {
+    //Given the root ca poller that knows a set of root ca certificates
     X509Certificate knownCert = generateX509Cert(
         LocalDateTime.now(), Duration.ofSeconds(50));
     HashSet<X509Certificate> knownCerts = new HashSet<>();
@@ -77,24 +79,30 @@ public class TestRootCaRotationPoller {
     certsFromScm.add(CertificateCodec.getPEMEncodedString(knownCert));
     RootCaRotationPoller poller = new RootCaRotationPoller(secConf,
         knownCerts, scmSecurityClient, "");
-
+    //When the scm returns the same set of root ca certificates, and they poll
+    //for them
     Mockito.when(scmSecurityClient.getAllRootCaCertificates())
         .thenReturn(certsFromScm);
-    AtomicBoolean atomicBoolean = new AtomicBoolean();
-    atomicBoolean.set(false);
+    CompletableFuture<Void> processingResult = new CompletableFuture<>();
+    AtomicBoolean isProcessed = new AtomicBoolean(false);
     poller.addRootCARotationProcessor(
-        certificates -> CompletableFuture.supplyAsync(() -> {
-          atomicBoolean.set(true);
-          Assertions.assertEquals(certificates.size(), 2);
-          return null;
-        }));
-    poller.run();
+        certificates -> {
+          isProcessed.set(true);
+          processingResult.complete(null);
+          return processingResult;
+        }
+    );
+    poller.pollRootCas();
+    //Then the certificates are not processed. Note that we can't invoke
+    // processingResult.join before as it never gets completed
     Assertions.assertThrows(TimeoutException.class, () ->
-        GenericTestUtils.waitFor(atomicBoolean::get, 50, 5000));
+        GenericTestUtils.waitFor(isProcessed::get, 50, 5000));
   }
 
   @Test
   public void testPollerInvokesRootCaProcessors() throws Exception {
+    //Given the root ca poller knowing a root ca certificate, and an unknown
+    //root ca certificate
     X509Certificate knownCert = generateX509Cert(
         LocalDateTime.now(), Duration.ofSeconds(50));
     X509Certificate newRootCa = generateX509Cert(
@@ -106,22 +114,28 @@ public class TestRootCaRotationPoller {
     certsFromScm.add(CertificateCodec.getPEMEncodedString(newRootCa));
     RootCaRotationPoller poller = new RootCaRotationPoller(secConf,
         knownCerts, scmSecurityClient, "");
-    poller.run();
+    //when the scm returns the unknown certificate to the poller
     Mockito.when(scmSecurityClient.getAllRootCaCertificates())
         .thenReturn(certsFromScm);
-    AtomicBoolean atomicBoolean = new AtomicBoolean();
-    atomicBoolean.set(false);
+    CompletableFuture<Void> processingResult = new CompletableFuture<>();
+    AtomicBoolean isProcessed = new AtomicBoolean(false);
     poller.addRootCARotationProcessor(
-        certificates -> CompletableFuture.supplyAsync(() -> {
-          atomicBoolean.set(true);
-          Assertions.assertEquals(certificates.size(), 2);
-          return null;
-        }));
-    GenericTestUtils.waitFor(atomicBoolean::get, 50, 5000);
+        certificates -> {
+          isProcessed.set(true);
+          processingResult.complete(null);
+          return processingResult;
+        }
+    );
+    poller.pollRootCas();
+    processingResult.join();
+    //The root ca processors are invoked
+    Assertions.assertTrue(isProcessed.get());
   }
 
   @Test
   public void testPollerRetriesAfterFailure() throws Exception {
+    //Given a the root ca poller knowing about a root ca certificate and the
+    // SCM providing a new one
     X509Certificate knownCert = generateX509Cert(
         LocalDateTime.now(), Duration.ofSeconds(50));
     X509Certificate newRootCa = generateX509Cert(
@@ -133,27 +147,30 @@ public class TestRootCaRotationPoller {
     certsFromScm.add(CertificateCodec.getPEMEncodedString(newRootCa));
     RootCaRotationPoller poller = new RootCaRotationPoller(secConf,
         knownCerts, scmSecurityClient, "");
-    poller.run();
     Mockito.when(scmSecurityClient.getAllRootCaCertificates())
         .thenReturn(certsFromScm);
-    AtomicBoolean atomicBoolean = new AtomicBoolean();
-    atomicBoolean.set(false);
-    //Set that the first certificate renewal encountered an error
+    CompletableFuture<Void> processingResult = new CompletableFuture<>();
+    //When encountering an error for the first run:
     AtomicInteger runNumber = new AtomicInteger(1);
     poller.addRootCARotationProcessor(
-        certificates -> CompletableFuture.supplyAsync(() -> {
+        certificates -> {
           if (runNumber.getAndIncrement() < 2) {
             poller.setCertificateRenewalError();
           }
-          atomicBoolean.set(true);
           Assertions.assertEquals(certificates.size(), 2);
-          return null;
-        }));
-    //Assert for the poller success even if there was an error at first
-    GenericTestUtils.waitFor(atomicBoolean::get, 50, 5000);
-    //And that we see the error in the logs
+          processingResult.complete(null);
+          return processingResult;
+        }
+    );
+    //Then the first run encounters an error
+    poller.pollRootCas();
+    processingResult.join();
     Assertions.assertTrue(logCapturer.getOutput().contains(
         "There was a caught exception when trying to sign the certificate"));
+    //And then the second clean run is successful.
+    poller.pollRootCas();
+    Assertions.assertTrue(logCapturer.getOutput().contains(
+        "Certificate processing was successful."));
   }
 
   private X509Certificate generateX509Cert(


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to