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

chia7712 pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/kafka.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 3f1d830174d MINOR: Remove duplicate renewTimePeriodOpt in 
DelegationTokenCommand validation (#20177)
3f1d830174d is described below

commit 3f1d830174df26a2459a0317275ba5b1b6e4eac9
Author: Tsung-Han Ho (Miles Ho) <[email protected]>
AuthorDate: Sun Aug 3 16:40:18 2025 +0800

    MINOR: Remove duplicate renewTimePeriodOpt in DelegationTokenCommand 
validation (#20177)
    
    The bug was a duplicate parameter validation in the
    `DelegationTokenCommand` class.  The `checkInvalidArgs` method for the
    `describeOpt` was incorrectly including `renewTimePeriodOpt` twice in
    the set of invalid arguments.
    
    This bug caused unexpected command errors during E2E testing.
    
    ### Before the fix:
    The following command would fail due to the duplicate validation logic:
    ```
    
TC_PATHS="tests/kafkatest/tests/core/delegation_token_test.py::DelegationTokenTest"
    /bin/bash tests/docker/run_tests.sh
    ```
    
    ### Error output:
    ```
    ducktape.cluster.remoteaccount.RemoteCommandError: ducker@ducker03:
    Command
    'KAFKA_OPTS="-Djava.security.auth.login.config=/mnt/security/jaas.conf
    -Djava.security.krb5.conf=/mnt/security/krb5.conf"
    /opt/kafka-dev/bin/kafka-delegation-tokens.sh --bootstrap-server
    ducker03:9094  --create  --max-life-time-period -1  --command-config
    /mnt/kafka/client.properties > /mnt/kafka/delegation_token.out' returned
    non-zero exit status 1. Remote error message: b'duplicate element:
    [renew-time-period]\njava.lang.IllegalArgumentException: duplicate
    element: [renew-time-period]\n\tat
    
java.base/java.util.ImmutableCollections$SetN.<init>(ImmutableCollections.java:918)\n\tat
    java.base/java.util.Set.of(Set.java:544)\n\tat
    
org.apache.kafka.tools.DelegationTokenCommand$DelegationTokenCommandOptions.checkArgs(DelegationTokenCommand.java:304)\n\tat
    
org.apache.kafka.tools.DelegationTokenCommand.execute(DelegationTokenCommand.java:79)\n\tat
    
org.apache.kafka.tools.DelegationTokenCommand.mainNoExit(DelegationTokenCommand.java:57)\n\tat
    
org.apache.kafka.tools.DelegationTokenCommand.main(DelegationTokenCommand.java:52)\n\n'
    
    [INFO:2025-07-31 11:27:25,531]: RunnerClient:
    
kafkatest.tests.core.delegation_token_test.DelegationTokenTest.test_delegation_token_lifecycle.metadata_quorum=ISOLATED_KRAFT:
    Data: None
    
================================================================================
    SESSION REPORT (ALL TESTS)
    ducktape version: 0.12.0
    session_id:       2025-07-31--002
    run time:         33.213 seconds
    tests run:        1
    passed:           0
    flaky:            0
    failed:           1
    ignored:          0
    
================================================================================
    test_id:
    
kafkatest.tests.core.delegation_token_test.DelegationTokenTest.test_delegation_token_lifecycle.metadata_quorum=ISOLATED_KRAFT
    status:     FAIL
    run time:   33.090 seconds
    ```
    
    ### After the fix:
    The same command now executes successfully:
    ```
    
TC_PATHS="tests/kafkatest/tests/core/delegation_token_test.py::DelegationTokenTest"
    /bin/bash tests/docker/run_tests.sh
    ```
    
    ### Success output:
    ```
    
================================================================================
    SESSION REPORT (ALL TESTS)
    ducktape version: 0.12.0
    session_id:       2025-07-31--001
    run time:         35.488 seconds
    tests run:        1
    passed:           1
    flaky:            0
    failed:           0
    ignored:          0
    
================================================================================
    test_id:
    
kafkatest.tests.core.delegation_token_test.DelegationTokenTest.test_delegation_token_lifecycle.metadata_quorum=ISOLATED_KRAFT
    status:     PASS
    run time:   35.363 seconds
    
--------------------------------------------------------------------------------
    ```
    
    Reviewers: Jhen-Yung Hsu <[email protected]>, TengYao Chi
     <[email protected]>, Ken Huang <[email protected]>, PoAn Yang
     <[email protected]>, Chia-Ping Tsai <[email protected]>
---
 .../apache/kafka/tools/DelegationTokenCommand.java |   2 +-
 .../kafka/tools/DelegationTokenCommandTest.java    | 153 +++++++++++++++++++++
 2 files changed, 154 insertions(+), 1 deletion(-)

diff --git 
a/tools/src/main/java/org/apache/kafka/tools/DelegationTokenCommand.java 
b/tools/src/main/java/org/apache/kafka/tools/DelegationTokenCommand.java
index dad388fee6b..da1c1cfcb78 100644
--- a/tools/src/main/java/org/apache/kafka/tools/DelegationTokenCommand.java
+++ b/tools/src/main/java/org/apache/kafka/tools/DelegationTokenCommand.java
@@ -300,7 +300,7 @@ public class DelegationTokenCommand {
             CommandLineUtils.checkInvalidArgs(parser, options, createOpt, 
Set.of(hmacOpt, renewTimePeriodOpt, expiryTimePeriodOpt));
             CommandLineUtils.checkInvalidArgs(parser, options, renewOpt, 
Set.of(renewPrincipalsOpt, maxLifeTimeOpt, expiryTimePeriodOpt, 
ownerPrincipalsOpt));
             CommandLineUtils.checkInvalidArgs(parser, options, expiryOpt, 
Set.of(renewOpt, maxLifeTimeOpt, renewTimePeriodOpt, ownerPrincipalsOpt));
-            CommandLineUtils.checkInvalidArgs(parser, options, describeOpt, 
Set.of(renewTimePeriodOpt, maxLifeTimeOpt, hmacOpt, renewTimePeriodOpt, 
expiryTimePeriodOpt));
+            CommandLineUtils.checkInvalidArgs(parser, options, describeOpt, 
Set.of(renewTimePeriodOpt, maxLifeTimeOpt, hmacOpt, expiryTimePeriodOpt));
         }
     }
 }
diff --git 
a/tools/src/test/java/org/apache/kafka/tools/DelegationTokenCommandTest.java 
b/tools/src/test/java/org/apache/kafka/tools/DelegationTokenCommandTest.java
index f0ac5a7a8ed..be0b744a7a4 100644
--- a/tools/src/test/java/org/apache/kafka/tools/DelegationTokenCommandTest.java
+++ b/tools/src/test/java/org/apache/kafka/tools/DelegationTokenCommandTest.java
@@ -19,6 +19,7 @@ package org.apache.kafka.tools;
 import org.apache.kafka.clients.admin.Admin;
 import org.apache.kafka.clients.admin.MockAdminClient;
 import org.apache.kafka.common.security.token.delegation.DelegationToken;
+import org.apache.kafka.common.utils.Exit;
 
 import org.junit.jupiter.api.Test;
 
@@ -109,4 +110,156 @@ public class DelegationTokenCommandTest {
         String[] args = {"--bootstrap-server", "localhost:9092", 
"--command-config", "testfile", "--expire", "--expiry-time-period", "-1", 
"--hmac", hmac};
         return new DelegationTokenCommand.DelegationTokenCommandOptions(args);
     }
+
+
+    @Test
+    public void testCheckArgsMissingRequiredArgs() {
+        Exit.setExitProcedure((exitCode, message) -> {
+            throw new RuntimeException("Exit with code " + exitCode + ": " + 
message);
+        });
+        try {
+            String[] argsCreateMissingBootstrap = {"--command-config", 
"testfile", "--create", "--max-life-time-period", "604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsCreateMissingBootstrap = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsCreateMissingBootstrap);
+            assertThrows(RuntimeException.class, 
optsCreateMissingBootstrap::checkArgs);
+
+            String[] argsCreateMissingConfig = {"--bootstrap-server", 
"localhost:9092", "--create", "--max-life-time-period", "604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsCreateMissingConfig = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsCreateMissingConfig);
+            assertThrows(RuntimeException.class, 
optsCreateMissingConfig::checkArgs);
+
+            String[] argsCreateMissingMaxLife = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--create"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsCreateMissingMaxLife = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsCreateMissingMaxLife);
+            assertThrows(RuntimeException.class, 
optsCreateMissingMaxLife::checkArgs);
+
+            String[] argsRenewMissingBootstrap = {"--command-config", 
"testfile", "--renew", "--hmac", "test-hmac", "--renew-time-period", 
"604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsRenewMissingBootstrap = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsRenewMissingBootstrap);
+            assertThrows(RuntimeException.class, 
optsRenewMissingBootstrap::checkArgs);
+
+            String[] argsRenewMissingConfig = {"--bootstrap-server", 
"localhost:9092", "--renew", "--hmac", "test-hmac", "--renew-time-period", 
"604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsRenewMissingConfig = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsRenewMissingConfig);
+            assertThrows(RuntimeException.class, 
optsRenewMissingConfig::checkArgs);
+
+            String[] argsRenewMissingHmac = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--renew", 
"--renew-time-period", "604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsRenewMissingHmac = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsRenewMissingHmac);
+            assertThrows(RuntimeException.class, 
optsRenewMissingHmac::checkArgs);
+
+            String[] argsRenewMissingRenewTime = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--renew", "--hmac", 
"test-hmac"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsRenewMissingRenewTime = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsRenewMissingRenewTime);
+            assertThrows(RuntimeException.class, 
optsRenewMissingRenewTime::checkArgs);
+
+            String[] argsExpireMissingBootstrap = {"--command-config", 
"testfile", "--expire", "--hmac", "test-hmac", "--expiry-time-period", 
"604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsExpireMissingBootstrap = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsExpireMissingBootstrap);
+            assertThrows(RuntimeException.class, 
optsExpireMissingBootstrap::checkArgs);
+
+            String[] argsExpireMissingConfig = {"--bootstrap-server", 
"localhost:9092", "--expire", "--hmac", "test-hmac", "--expiry-time-period", 
"604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsExpireMissingConfig = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsExpireMissingConfig);
+            assertThrows(RuntimeException.class, 
optsExpireMissingConfig::checkArgs);
+
+            String[] argsExpireMissingHmac = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--expire", 
"--expiry-time-period", "604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsExpireMissingHmac = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsExpireMissingHmac);
+            assertThrows(RuntimeException.class, 
optsExpireMissingHmac::checkArgs);
+
+            String[] argsExpireMissingExpiryTime = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--expire", "--hmac", 
"test-hmac"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsExpireMissingExpiryTime = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsExpireMissingExpiryTime);
+            assertThrows(RuntimeException.class, 
optsExpireMissingExpiryTime::checkArgs);
+
+            String[] argsDescribeMissingBootstrap = {"--command-config", 
"testfile", "--describe"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsDescribeMissingBootstrap = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsDescribeMissingBootstrap);
+            assertThrows(RuntimeException.class, 
optsDescribeMissingBootstrap::checkArgs);
+
+            String[] argsDescribeMissingConfig = {"--bootstrap-server", 
"localhost:9092", "--describe"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsDescribeMissingConfig = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsDescribeMissingConfig);
+            assertThrows(RuntimeException.class, 
optsDescribeMissingConfig::checkArgs);
+        } finally {
+            Exit.resetExitProcedure();
+        }
+    }
+
+    @Test
+    public void testCheckArgsInvalidArgs() {
+        Exit.setExitProcedure((exitCode, message) -> {
+            throw new RuntimeException("Exit with code " + exitCode + ": " + 
message);
+        });
+        try {
+            String[] argsCreateWithHmac = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--create", 
"--max-life-time-period", "604800000", "--hmac", "test-hmac"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsCreateWithHmac = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsCreateWithHmac);
+            assertThrows(RuntimeException.class, 
optsCreateWithHmac::checkArgs);
+
+            String[] argsCreateWithRenewTime = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--create", 
"--max-life-time-period", "604800000", "--renew-time-period", "604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsCreateWithRenewTime = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsCreateWithRenewTime);
+            assertThrows(RuntimeException.class, 
optsCreateWithRenewTime::checkArgs);
+
+            String[] argsCreateWithExpiryTime = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--create", 
"--max-life-time-period", "604800000", "--expiry-time-period", "604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsCreateWithExpiryTime = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsCreateWithExpiryTime);
+            assertThrows(RuntimeException.class, 
optsCreateWithExpiryTime::checkArgs);
+
+            String[] argsRenewWithRenewPrincipals = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--renew", "--hmac", 
"test-hmac", "--renew-time-period", "604800000", "--renewer-principal", 
"User:renewer"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsRenewWithRenewPrincipals = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsRenewWithRenewPrincipals);
+            assertThrows(RuntimeException.class, 
optsRenewWithRenewPrincipals::checkArgs);
+
+            String[] argsRenewWithMaxLife = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--renew", "--hmac", 
"test-hmac", "--renew-time-period", "604800000", "--max-life-time-period", 
"604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsRenewWithMaxLife = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsRenewWithMaxLife);
+            assertThrows(RuntimeException.class, 
optsRenewWithMaxLife::checkArgs);
+
+            String[] argsRenewWithExpiryTime = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--renew", "--hmac", 
"test-hmac", "--renew-time-period", "604800000", "--expiry-time-period", 
"604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsRenewWithExpiryTime = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsRenewWithExpiryTime);
+            assertThrows(RuntimeException.class, 
optsRenewWithExpiryTime::checkArgs);
+
+            String[] argsRenewWithOwner = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--renew", "--hmac", 
"test-hmac", "--renew-time-period", "604800000", "--owner-principal", 
"User:owner"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsRenewWithOwner = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsRenewWithOwner);
+            assertThrows(RuntimeException.class, 
optsRenewWithOwner::checkArgs);
+
+            String[] argsExpireWithRenew = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--expire", "--renew", 
"--hmac", "test-hmac", "--expiry-time-period", "604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsExpireWithRenew = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsExpireWithRenew);
+            assertThrows(RuntimeException.class, 
optsExpireWithRenew::checkArgs);
+
+            String[] argsExpireWithMaxLife = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--expire", "--hmac", 
"test-hmac", "--expiry-time-period", "604800000", "--max-life-time-period", 
"604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsExpireWithMaxLife = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsExpireWithMaxLife);
+            assertThrows(RuntimeException.class, 
optsExpireWithMaxLife::checkArgs);
+
+            String[] argsExpireWithRenewTime = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--expire", "--hmac", 
"test-hmac", "--expiry-time-period", "604800000", "--renew-time-period", 
"604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsExpireWithRenewTime = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsExpireWithRenewTime);
+            assertThrows(RuntimeException.class, 
optsExpireWithRenewTime::checkArgs);
+
+            String[] argsExpireWithOwner = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--expire", "--hmac", 
"test-hmac", "--expiry-time-period", "604800000", "--owner-principal", 
"User:owner"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsExpireWithOwner = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsExpireWithOwner);
+            assertThrows(RuntimeException.class, 
optsExpireWithOwner::checkArgs);
+
+            String[] argsDescribeWithRenewTime = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--describe", 
"--renew-time-period", "604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsDescribeWithRenewTime = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsDescribeWithRenewTime);
+            assertThrows(RuntimeException.class, 
optsDescribeWithRenewTime::checkArgs);
+
+            String[] argsDescribeWithExpiryTime = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--describe", 
"--expiry-time-period", "604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsDescribeWithExpiryTime = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsDescribeWithExpiryTime);
+            assertThrows(RuntimeException.class, 
optsDescribeWithExpiryTime::checkArgs);
+
+            String[] argsDescribeWithMaxLife = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--describe", 
"--max-life-time-period", "604800000"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsDescribeWithMaxLife = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsDescribeWithMaxLife);
+            assertThrows(RuntimeException.class, 
optsDescribeWithMaxLife::checkArgs);
+
+            String[] argsDescribeWithHmac = {"--bootstrap-server", 
"localhost:9092", "--command-config", "testfile", "--describe", "--hmac", 
"test-hmac"};
+            DelegationTokenCommand.DelegationTokenCommandOptions 
optsDescribeWithHmac = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsDescribeWithHmac);
+            assertThrows(RuntimeException.class, 
optsDescribeWithHmac::checkArgs);
+        } finally {
+            Exit.resetExitProcedure();
+        }
+    }
+
+    @Test
+    public void testCheckArgsValidOperations() {
+        String[] argsCreate = {"--bootstrap-server", "localhost:9092", 
"--command-config", "testfile", "--create", "--max-life-time-period", 
"604800000"};
+        DelegationTokenCommand.DelegationTokenCommandOptions optsCreate = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsCreate);
+        optsCreate.checkArgs();
+
+        String[] argsRenew = {"--bootstrap-server", "localhost:9092", 
"--command-config", "testfile", "--renew", "--hmac", "test-hmac", 
"--renew-time-period", "604800000"};
+        DelegationTokenCommand.DelegationTokenCommandOptions optsRenew = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsRenew);
+        optsRenew.checkArgs();
+
+        String[] argsExpire = {"--bootstrap-server", "localhost:9092", 
"--command-config", "testfile", "--expire", "--hmac", "test-hmac", 
"--expiry-time-period", "604800000"};
+        DelegationTokenCommand.DelegationTokenCommandOptions optsExpire = new 
DelegationTokenCommand.DelegationTokenCommandOptions(argsExpire);
+        optsExpire.checkArgs();
+
+        String[] argsDescribe = {"--bootstrap-server", "localhost:9092", 
"--command-config", "testfile", "--describe"};
+        DelegationTokenCommand.DelegationTokenCommandOptions optsDescribe = 
new DelegationTokenCommand.DelegationTokenCommandOptions(argsDescribe);
+        optsDescribe.checkArgs();
+    }
 }

Reply via email to