diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneTenantShell.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneTenantShell.java index da311909f78..8adb2292348 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneTenantShell.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneTenantShell.java @@ -102,8 +102,8 @@ public class TestOzoneTenantShell { private static OzoneShell ozoneSh = null; private static TenantShell tenantShell = null; - private static final StringWriter OUT = new StringWriter(); - private static final StringWriter ERR = new StringWriter(); + private final StringWriter out = new StringWriter(); + private final StringWriter err = new StringWriter(); private static String omServiceId; private static int numOfOMs; @@ -171,10 +171,10 @@ public static void shutdown() { @BeforeEach public void setup() throws UnsupportedEncodingException { - tenantShell.getCmd().setOut(new PrintWriter(OUT)); - tenantShell.getCmd().setErr(new PrintWriter(ERR)); - ozoneSh.getCmd().setOut(new PrintWriter(OUT)); - ozoneSh.getCmd().setErr(new PrintWriter(ERR)); + tenantShell.getCmd().setOut(new PrintWriter(out)); + tenantShell.getCmd().setErr(new PrintWriter(err)); + ozoneSh.getCmd().setOut(new PrintWriter(out)); + ozoneSh.getCmd().setErr(new PrintWriter(err)); // Suppress OMNotLeaderException in the log GenericTestUtils.setLogLevel(RetryInvocationHandler.LOG, Level.WARN); // Enable debug logging for interested classes @@ -186,13 +186,6 @@ public void setup() throws UnsupportedEncodingException { GenericTestUtils.setLogLevel(OMRangerBGSyncService.LOG, Level.DEBUG); } - @AfterEach - public void reset() { - // reset stream after each unit test - OUT.getBuffer().setLength(0); - ERR.getBuffer().setLength(0); - } - /** * Returns exit code. */ @@ -201,9 +194,7 @@ private int execute(GenericCli shell, String[] args) { CommandLine cmd = shell.getCmd(); CommandLine.IExecutionExceptionHandler exceptionHandler = (ex, commandLine, parseResult) -> { - try (PrintWriter writer = new PrintWriter(ERR)) { - writer.println(ex.getMessage()); - } + commandLine.getErr().println(ex.getMessage()); return commandLine.getCommandSpec().exitCodeOnExecutionException(); }; @@ -338,8 +329,8 @@ private void checkOutput(String str, String stringToMatch, private void deleteVolume(String volumeName) throws IOException { int exitC = execute(ozoneSh, new String[] {"volume", "delete", volumeName}); - checkOutput(OUT, "Volume " + volumeName + " is deleted\n", true); - checkOutput(ERR, "", true); + checkOutput(out, "Volume " + volumeName + " is deleted\n", true); + checkOutput(err, "", true); // Exit code should be 0 assertEquals(0, exitC); } @@ -351,48 +342,48 @@ public void testAssignAdmin() throws IOException { final String userName = "alice"; executeHA(tenantShell, new String[] {"create", tenantName}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Loop assign-revoke 4 times for (int i = 0; i < 4; i++) { executeHA(tenantShell, new String[] { "user", "assign", userName, "--tenant=" + tenantName}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID=", false); - checkOutput(ERR, "", true); + checkOutput(out, "export AWS_ACCESS_KEY_ID=", false); + checkOutput(err, "", true); executeHA(tenantShell, new String[] {"--verbose", "user", "assign-admin", tenantName + "$" + userName, "--tenant=" + tenantName, "--delegated=true"}); - checkOutput(OUT, "{\n" + " \"accessId\" : \"devaa$alice\",\n" + checkOutput(out, "{\n" + " \"accessId\" : \"devaa$alice\",\n" + " \"tenantId\" : \"devaa\",\n" + " \"isAdmin\" : true,\n" + " \"isDelegatedAdmin\" : true\n" + "}\n", true, true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Clean up executeHA(tenantShell, new String[] {"--verbose", "user", "revoke-admin", tenantName + "$" + userName, "--tenant=" + tenantName}); - checkOutput(OUT, "{\n" + " \"accessId\" : \"devaa$alice\",\n" + checkOutput(out, "{\n" + " \"accessId\" : \"devaa$alice\",\n" + " \"tenantId\" : \"devaa\",\n" + " \"isAdmin\" : false,\n" + " \"isDelegatedAdmin\" : false\n" + "}\n", true, true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "revoke", tenantName + "$" + userName}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); } // Clean up executeHA(tenantShell, new String[] {"delete", tenantName}); - checkOutput(OUT, "", true); - checkOutput(ERR, "Deleted tenant '" + tenantName + "'.\n", false); + checkOutput(out, "", true); + checkOutput(err, "Deleted tenant '" + tenantName + "'.\n", false); deleteVolume(tenantName); // Sanity check: tenant list should be empty executeHA(tenantShell, new String[] {"list"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); } /** @@ -407,18 +398,18 @@ public void testOzoneTenantBasicOperations() throws IOException { assertEquals(0, lines.size()); executeHA(tenantShell, new String[] {"list"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Create tenants // Equivalent to `ozone tenant create finance` executeHA(tenantShell, new String[] {"create", "finance"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] {"list"}); - checkOutput(OUT, "finance\n", true); - checkOutput(ERR, "", true); + checkOutput(out, "finance\n", true); + checkOutput(err, "", true); lines = FileUtils.readLines(AUDIT_LOG_FILE, (String)null); assertThat(lines.size()).isGreaterThan(0); @@ -430,93 +421,93 @@ public void testOzoneTenantBasicOperations() throws IOException { // Creating the tenant with the same name again should fail executeHA(tenantShell, new String[] {"create", "finance"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "Tenant 'finance' already exists\n", true); + checkOutput(out, "", true); + checkOutput(err, "Tenant 'finance' already exists\n", true); executeHA(tenantShell, new String[] {"create", "research"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] {"create", "dev"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] {"ls"}); - checkOutput(OUT, "dev\nfinance\nresearch\n", true); - checkOutput(ERR, "", true); + checkOutput(out, "dev\nfinance\nresearch\n", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] {"list", "--json"}); // Not checking the full output here - checkOutput(OUT, "\"tenantId\" : \"dev\",", false); - checkOutput(ERR, "", true); + checkOutput(out, "\"tenantId\" : \"dev\",", false); + checkOutput(err, "", true); // Attempt user getsecret before assignment, should fail executeHA(tenantShell, new String[] { "user", "getsecret", "finance$bob"}); - checkOutput(OUT, "", false); - checkOutput(ERR, "accessId 'finance$bob' doesn't exist\n", + checkOutput(out, "", false); + checkOutput(err, "accessId 'finance$bob' doesn't exist\n", true); // Assign user accessId // Equivalent to `ozone tenant user assign bob --tenant=finance` executeHA(tenantShell, new String[] { "--verbose", "user", "assign", "bob", "--tenant=finance"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='finance$bob'\n" + checkOutput(out, "export AWS_ACCESS_KEY_ID='finance$bob'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "Assigned 'bob' to 'finance' with accessId" + checkOutput(err, "Assigned 'bob' to 'finance' with accessId" + " 'finance$bob'.\n", true); // Try user getsecret again after assignment, should succeed executeHA(tenantShell, new String[] { "user", "getsecret", "finance$bob"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='finance$bob'\n", + checkOutput(out, "export AWS_ACCESS_KEY_ID='finance$bob'\n", false); - checkOutput(ERR, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "--verbose", "user", "assign", "bob", "--tenant=research"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='research$bob'\n" + checkOutput(out, "export AWS_ACCESS_KEY_ID='research$bob'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "Assigned 'bob' to 'research' with accessId" + checkOutput(err, "Assigned 'bob' to 'research' with accessId" + " 'research$bob'.\n", true); executeHA(tenantShell, new String[] { "user", "assign", "bob", "--tenant=dev"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='dev$bob'\n" + checkOutput(out, "export AWS_ACCESS_KEY_ID='dev$bob'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // accessId length exceeding limit, should fail executeHA(tenantShell, new String[] { "user", "assign", StringUtils.repeat('a', 100), "--tenant=dev"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "accessId length (104) exceeds the maximum length " + checkOutput(out, "", true); + checkOutput(err, "accessId length (104) exceeds the maximum length " + "allowed (100)\n", true); // Get user info // Equivalent to `ozone tenant user info bob` executeHA(tenantShell, new String[] { "user", "info", "bob"}); - checkOutput(OUT, "User 'bob' is assigned to:\n" + checkOutput(out, "User 'bob' is assigned to:\n" + "- Tenant 'research' with accessId 'research$bob'\n" + "- Tenant 'finance' with accessId 'finance$bob'\n" + "- Tenant 'dev' with accessId 'dev$bob'\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Assign admin executeHA(tenantShell, new String[] { "user", "assign-admin", "dev$bob", "--tenant=dev", "--delegated"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "info", "bob"}); - checkOutput(OUT, "Tenant 'dev' delegated admin with accessId", false); - checkOutput(ERR, "", true); + checkOutput(out, "Tenant 'dev' delegated admin with accessId", false); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "info", "--json", "bob"}); - checkOutput(OUT, + checkOutput(out, "{\n" + " \"user\" : \"bob\",\n" + " \"tenants\" : [ {\n" + @@ -537,97 +528,97 @@ public void testOzoneTenantBasicOperations() throws IOException { " } ]\n" + "}\n", true, true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Revoke admin executeHA(tenantShell, new String[] { "user", "revoke-admin", "dev$bob", "--tenant=dev"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "info", "bob"}); - checkOutput(OUT, "User 'bob' is assigned to:\n" + checkOutput(out, "User 'bob' is assigned to:\n" + "- Tenant 'research' with accessId 'research$bob'\n" + "- Tenant 'finance' with accessId 'finance$bob'\n" + "- Tenant 'dev' with accessId 'dev$bob'\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Revoke user accessId executeHA(tenantShell, new String[] { "user", "revoke", "research$bob"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "info", "bob"}); - checkOutput(OUT, "User 'bob' is assigned to:\n" + checkOutput(out, "User 'bob' is assigned to:\n" + "- Tenant 'finance' with accessId 'finance$bob'\n" + "- Tenant 'dev' with accessId 'dev$bob'\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Assign user again executeHA(tenantShell, new String[] { "user", "assign", "bob", "--tenant=research"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='research$bob'\n" + checkOutput(out, "export AWS_ACCESS_KEY_ID='research$bob'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Attempt to assign the user to the tenant again executeHA(tenantShell, new String[] { "user", "assign", "bob", "--tenant=research", "--accessId=research$bob"}); - checkOutput(OUT, "", false); - checkOutput(ERR, "accessId 'research$bob' already exists!\n", true); + checkOutput(out, "", false); + checkOutput(err, "accessId 'research$bob' already exists!\n", true); // Attempt to assign the user to the tenant with a custom accessId executeHA(tenantShell, new String[] { "user", "assign", "bob", "--tenant=research", "--accessId=research$bob42"}); - checkOutput(OUT, "", false); + checkOutput(out, "", false); // HDDS-6366: Disallow specifying custom accessId. - checkOutput(ERR, "Invalid accessId 'research$bob42'. " + checkOutput(err, "Invalid accessId 'research$bob42'. " + "Specifying a custom access ID disallowed. " + "Expected accessId to be assigned is 'research$bob'\n", true); executeHA(tenantShell, new String[] {"list"}); - checkOutput(OUT, "dev\nfinance\nresearch\n", true); - checkOutput(ERR, "", true); + checkOutput(out, "dev\nfinance\nresearch\n", true); + checkOutput(err, "", true); // Clean up executeHA(tenantShell, new String[] { "user", "revoke", "research$bob"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] {"delete", "research"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "Deleted tenant 'research'.\n", false); + checkOutput(out, "", true); + checkOutput(err, "Deleted tenant 'research'.\n", false); deleteVolume("research"); executeHA(tenantShell, new String[] { "user", "revoke", "finance$bob"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] {"list"}); - checkOutput(OUT, "dev\nfinance\n", true); - checkOutput(ERR, "", true); + checkOutput(out, "dev\nfinance\n", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] {"delete", "finance"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "Deleted tenant 'finance'.\n", false); + checkOutput(out, "", true); + checkOutput(err, "Deleted tenant 'finance'.\n", false); deleteVolume("finance"); executeHA(tenantShell, new String[] {"list"}); - checkOutput(OUT, "dev\n", true); - checkOutput(ERR, "", true); + checkOutput(out, "dev\n", true); + checkOutput(err, "", true); // Attempt to delete tenant with accessIds still assigned to it, should fail int exitCode = executeHA(tenantShell, new String[] {"delete", "dev"}); assertNotEquals(0, exitCode, "Tenant delete should fail!"); - checkOutput(OUT, "", true); - checkOutput(ERR, "Tenant 'dev' is not empty. All accessIds associated " + checkOutput(out, "", true); + checkOutput(err, "Tenant 'dev' is not empty. All accessIds associated " + "to this tenant must be revoked before the tenant can be deleted. " + "See `ozone tenant user revoke`\n", true); @@ -644,64 +635,64 @@ public void testOzoneTenantBasicOperations() throws IOException { // Delete dev volume should fail because the volume reference count > 0L exitCode = execute(ozoneSh, new String[] {"volume", "delete", "dev"}); assertNotEquals(0, exitCode, "Volume delete should fail!"); - checkOutput(OUT, "", true); - checkOutput(ERR, "Volume reference count is not zero (1). " + checkOutput(out, "", true); + checkOutput(err, "Volume reference count is not zero (1). " + "Ozone features are enabled on this volume. " + "Try `ozone tenant delete ` first.\n", true); executeHA(tenantShell, new String[] {"list"}); - checkOutput(OUT, "dev\n", true); - checkOutput(ERR, "", true); + checkOutput(out, "dev\n", true); + checkOutput(err, "", true); // Revoke accessId first executeHA(tenantShell, new String[] { "user", "revoke", "dev$bob"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Then delete tenant, should succeed executeHA(tenantShell, new String[] {"--verbose", "delete", "dev"}); - checkOutput(OUT, "{\n" + " \"tenantId\" : \"dev\",\n" + checkOutput(out, "{\n" + " \"tenantId\" : \"dev\",\n" + " \"volumeName\" : \"dev\",\n" + " \"volumeRefCount\" : 0\n" + "}\n", true, true); - checkOutput(ERR, "Deleted tenant 'dev'.\n", false); + checkOutput(err, "Deleted tenant 'dev'.\n", false); deleteVolume("dev"); // Sanity check: tenant list should be empty executeHA(tenantShell, new String[] {"list"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); } @Test public void testListTenantUsers() throws IOException { executeHA(tenantShell, new String[] {"--verbose", "create", "tenant1"}); - checkOutput(OUT, "{\n" + + checkOutput(out, "{\n" + " \"tenantId\" : \"tenant1\"\n" + "}\n", true, true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "--verbose", "user", "assign", "alice", "--tenant=tenant1"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='tenant1$alice'\n" + checkOutput(out, "export AWS_ACCESS_KEY_ID='tenant1$alice'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "Assigned 'alice' to 'tenant1'" + + checkOutput(err, "Assigned 'alice' to 'tenant1'" + " with accessId 'tenant1$alice'.\n", true); executeHA(tenantShell, new String[] { "user", "assign", "bob", "--tenant=tenant1"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='tenant1$bob'\n" + checkOutput(out, "export AWS_ACCESS_KEY_ID='tenant1$bob'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "list", "tenant1"}); - checkOutput(OUT, "- User 'bob' with accessId 'tenant1$bob'\n" + + checkOutput(out, "- User 'bob' with accessId 'tenant1$bob'\n" + "- User 'alice' with accessId 'tenant1$alice'\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "list", "tenant1", "--json"}); - checkOutput(OUT, + checkOutput(out, "[ {\n" + " \"user\" : \"bob\",\n" + " \"accessId\" : \"tenant1$bob\"\n" + @@ -709,48 +700,48 @@ public void testListTenantUsers() throws IOException { " \"user\" : \"alice\",\n" + " \"accessId\" : \"tenant1$alice\"\n" + "} ]\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "list", "tenant1", "--prefix=b"}); - checkOutput(OUT, "- User 'bob' with accessId " + + checkOutput(out, "- User 'bob' with accessId " + "'tenant1$bob'\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "list", "tenant1", "--prefix=b", "--json"}); - checkOutput(OUT, "[ {\n" + + checkOutput(out, "[ {\n" + " \"user\" : \"bob\",\n" + " \"accessId\" : \"tenant1$bob\"\n" + "} ]\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); int exitCode = executeHA(tenantShell, new String[] { "user", "list", "unknown"}); assertNotEquals(0, exitCode, "Expected non-zero exit code"); - checkOutput(OUT, "", true); - checkOutput(ERR, "Tenant 'unknown' doesn't exist.\n", true); + checkOutput(out, "", true); + checkOutput(err, "Tenant 'unknown' doesn't exist.\n", true); // Clean up executeHA(tenantShell, new String[] { "user", "revoke", "tenant1$alice"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "--verbose", "user", "revoke", "tenant1$bob"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "Revoked accessId", false); + checkOutput(out, "", true); + checkOutput(err, "Revoked accessId", false); executeHA(tenantShell, new String[] {"delete", "tenant1"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "Deleted tenant 'tenant1'.\n", false); + checkOutput(out, "", true); + checkOutput(err, "Deleted tenant 'tenant1'.\n", false); deleteVolume("tenant1"); // Sanity check: tenant list should be empty executeHA(tenantShell, new String[] {"list"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); } @Test @@ -760,44 +751,44 @@ public void testTenantSetSecret() throws IOException, InterruptedException { // Create test tenant executeHA(tenantShell, new String[] {"create", tenantName}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Set secret for non-existent accessId. Expect failure executeHA(tenantShell, new String[] { "user", "set-secret", tenantName + "$alice", "--secret=somesecret0"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "accessId '" + tenantName + "$alice' not found.\n", true); + checkOutput(out, "", true); + checkOutput(err, "accessId '" + tenantName + "$alice' not found.\n", true); // Assign a user to the tenant so that we have an accessId entry executeHA(tenantShell, new String[] { "user", "assign", "alice", "--tenant=" + tenantName}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + + checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Set secret as OM admin should succeed executeHA(tenantShell, new String[] { "user", "setsecret", tenantName + "$alice", "--secret=somesecret1"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + + checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + "export AWS_SECRET_ACCESS_KEY='somesecret1'\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Set empty secret key should fail int exitCode = executeHA(tenantShell, new String[] { "user", "setsecret", tenantName + "$alice", "--secret=short"}); assertNotEquals(0, exitCode, "Expected non-zero exit code"); - checkOutput(OUT, "", true); - checkOutput(ERR, "Secret key length should be at least 8 characters\n", + checkOutput(out, "", true); + checkOutput(err, "Secret key length should be at least 8 characters\n", true); // Get secret should still give the previous secret key executeHA(tenantShell, new String[] { "user", "getsecret", tenantName + "$alice"}); - checkOutput(OUT, "somesecret1", false); - checkOutput(ERR, "", true); + checkOutput(out, "somesecret1", false); + checkOutput(err, "", true); // Set secret as alice should succeed final UserGroupInformation ugiAlice = UserGroupInformation @@ -807,18 +798,18 @@ public void testTenantSetSecret() throws IOException, InterruptedException { executeHA(tenantShell, new String[] { "user", "setsecret", tenantName + "$alice", "--secret=somesecret2"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + + checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + "export AWS_SECRET_ACCESS_KEY='somesecret2'\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); return null; }); // Set secret as bob should fail executeHA(tenantShell, new String[] { "user", "assign", "bob", "--tenant=" + tenantName}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='" + tenantName + "$bob'\n" + + checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$bob'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "", true); + checkOutput(err, "", true); final UserGroupInformation ugiBob = UserGroupInformation .createUserForTesting("bob", new String[] {"usergroup"}); @@ -828,8 +819,8 @@ public void testTenantSetSecret() throws IOException, InterruptedException { "user", "setsecret", tenantName + "$alice", "--secret=somesecret2"}); assertNotEquals(0, exitC, "Should return non-zero exit code!"); - checkOutput(OUT, "", true); - checkOutput(ERR, "Requested accessId 'tenant-test-set-secret$alice'" + checkOutput(out, "", true); + checkOutput(err, "Requested accessId 'tenant-test-set-secret$alice'" + " doesn't belong to current user 'bob', nor does current user" + " have Ozone or tenant administrator privilege\n", true); return null; @@ -840,45 +831,45 @@ public void testTenantSetSecret() throws IOException, InterruptedException { executeHA(tenantShell, new String[] {"user", "assign-admin", tenantName + "$" + ugiBob.getShortUserName(), "--tenant=" + tenantName, "--delegated=false"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Set secret should succeed now ugiBob.doAs((PrivilegedExceptionAction) () -> { executeHA(tenantShell, new String[] { "user", "setsecret", tenantName + "$alice", "--secret=somesecret2"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + + checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + "export AWS_SECRET_ACCESS_KEY='somesecret2'\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); return null; }); // Clean up executeHA(tenantShell, new String[] {"user", "revoke-admin", tenantName + "$" + ugiBob.getShortUserName()}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "revoke", tenantName + "$bob"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "revoke", tenantName + "$alice"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] {"delete", tenantName}); - checkOutput(OUT, "", true); - checkOutput(ERR, "Deleted tenant '" + tenantName + "'.\n", false); + checkOutput(out, "", true); + checkOutput(err, "Deleted tenant '" + tenantName + "'.\n", false); deleteVolume(tenantName); // Sanity check: tenant list should be empty executeHA(tenantShell, new String[] {"list"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); } @Test @@ -896,35 +887,35 @@ public void testTenantAdminOperations() // Create test tenant executeHA(tenantShell, new String[] {"create", tenantName}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Assign alice and bob as tenant users executeHA(tenantShell, new String[] { "user", "assign", "alice", "--tenant=" + tenantName}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + + checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "assign", "bob", "--tenant=" + tenantName}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='" + tenantName + "$bob'\n" + + checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$bob'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Make alice a delegated tenant admin executeHA(tenantShell, new String[] {"user", "assign-admin", tenantName + "$" + ugiAlice.getShortUserName(), "--tenant=" + tenantName, "--delegated=true"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Make bob a non-delegated tenant admin executeHA(tenantShell, new String[] {"user", "assign-admin", tenantName + "$" + ugiBob.getShortUserName(), "--tenant=" + tenantName, "--delegated=false"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Start test matrix @@ -936,49 +927,49 @@ public void testTenantAdminOperations() // Assign carol as a new tenant user executeHA(tenantShell, new String[] { "user", "assign", "carol", "--tenant=" + tenantName}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='" + tenantName + "$carol'\n" + checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$carol'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Set secret should work executeHA(tenantShell, new String[] { "user", "setsecret", tenantName + "$alice", "--secret=somesecret2"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + + checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + "export AWS_SECRET_ACCESS_KEY='somesecret2'\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Make carol a tenant delegated tenant admin executeHA(tenantShell, new String[] {"user", "assign-admin", tenantName + "$carol", "--tenant=" + tenantName, "--delegated=true"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Revoke carol's tenant admin privilege executeHA(tenantShell, new String[] {"user", "revoke-admin", tenantName + "$carol"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Make carol a tenant non-delegated tenant admin executeHA(tenantShell, new String[] {"user", "assign-admin", tenantName + "$carol", "--tenant=" + tenantName, "--delegated=false"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Revoke carol's tenant admin privilege executeHA(tenantShell, new String[] {"user", "revoke-admin", tenantName + "$carol"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Revoke carol's accessId from this tenant executeHA(tenantShell, new String[] { "user", "revoke", tenantName + "$carol"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); return null; }); @@ -992,73 +983,73 @@ public void testTenantAdminOperations() // Assign carol as a new tenant user executeHA(tenantShell, new String[] { "user", "assign", "carol", "--tenant=" + tenantName}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='" + tenantName + "$carol'\n" + checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$carol'\n" + "export AWS_SECRET_ACCESS_KEY='", false); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Set secret should work, even for a non-delegated admin executeHA(tenantShell, new String[] { "user", "setsecret", tenantName + "$alice", "--secret=somesecret2"}); - checkOutput(OUT, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + + checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" + "export AWS_SECRET_ACCESS_KEY='somesecret2'\n", true); - checkOutput(ERR, "", true); + checkOutput(err, "", true); // Attempt to make carol a tenant delegated tenant admin, should fail executeHA(tenantShell, new String[] {"user", "assign-admin", tenantName + "$carol", "--tenant=" + tenantName, "--delegated=true"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "User 'bob' is neither an Ozone admin " + checkOutput(out, "", true); + checkOutput(err, "User 'bob' is neither an Ozone admin " + "nor a delegated admin of tenant", false); // Attempt to make carol a tenant non-delegated tenant admin, should fail executeHA(tenantShell, new String[] {"user", "assign-admin", tenantName + "$carol", "--tenant=" + tenantName, "--delegated=false"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "User 'bob' is neither an Ozone admin " + checkOutput(out, "", true); + checkOutput(err, "User 'bob' is neither an Ozone admin " + "nor a delegated admin of tenant", false); // Attempt to revoke tenant admin, should fail at the permission check executeHA(tenantShell, new String[] {"user", "revoke-admin", tenantName + "$carol"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "User 'bob' is neither an Ozone admin " + checkOutput(out, "", true); + checkOutput(err, "User 'bob' is neither an Ozone admin " + "nor a delegated admin of tenant", false); // Revoke carol's accessId from this tenant executeHA(tenantShell, new String[] { "user", "revoke", tenantName + "$carol"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); return null; }); // Clean up executeHA(tenantShell, new String[] {"user", "revoke-admin", tenantName + "$" + ugiAlice.getShortUserName()}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "revoke", tenantName + "$" + ugiAlice.getShortUserName()}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] {"user", "revoke-admin", tenantName + "$" + ugiBob.getShortUserName()}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] { "user", "revoke", tenantName + "$" + ugiBob.getShortUserName()}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); executeHA(tenantShell, new String[] {"delete", tenantName}); - checkOutput(OUT, "", true); - checkOutput(ERR, "Deleted tenant '" + tenantName + "'.\n", false); + checkOutput(out, "", true); + checkOutput(err, "Deleted tenant '" + tenantName + "'.\n", false); deleteVolume(tenantName); } @@ -1068,29 +1059,29 @@ public void testCreateTenantOnExistingVolume() throws IOException { int exitC = execute(ozoneSh, new String[] {"volume", "create", testVolume}); // Volume create should succeed assertEquals(0, exitC); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Try to create tenant on the same volume, should fail by default executeHA(tenantShell, new String[] {"create", testVolume}); - checkOutput(OUT, "", true); - checkOutput(ERR, "Volume already exists\n", true); + checkOutput(out, "", true); + checkOutput(err, "Volume already exists\n", true); // Try to create tenant on the same volume with --force, should work executeHA(tenantShell, new String[] {"create", testVolume, "--force"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "", true); + checkOutput(out, "", true); + checkOutput(err, "", true); // Try to create the same tenant one more time, should fail even // with --force because the tenant already exists. executeHA(tenantShell, new String[] {"create", testVolume, "--force"}); - checkOutput(OUT, "", true); - checkOutput(ERR, "Tenant '" + testVolume + "' already exists\n", true); + checkOutput(out, "", true); + checkOutput(err, "Tenant '" + testVolume + "' already exists\n", true); // Clean up executeHA(tenantShell, new String[] {"delete", testVolume}); - checkOutput(OUT, "", true); - checkOutput(ERR, "Deleted tenant '" + testVolume + "'.\n", false); + checkOutput(out, "", true); + checkOutput(err, "Deleted tenant '" + testVolume + "'.\n", false); deleteVolume(testVolume); } } diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ValueSchema.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ValueSchema.java index aba7c931369..0c2fb302be9 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ValueSchema.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ValueSchema.java @@ -83,7 +83,7 @@ public Void call() throws Exception { String dbPath = parent.getDbPath(); Map fields = new HashMap<>(); - success = getValueFields(dbPath, fields, depth, tableName, dnDBSchemaVersion); + success = getValueFields(dbPath, fields); out().println(JsonUtils.toJsonStringWithDefaultPrettyPrinter(fields)); @@ -96,25 +96,24 @@ public Void call() throws Exception { return null; } - public boolean getValueFields(String dbPath, Map valueSchema, int d, String table, - String dndbschemaversion) { + public boolean getValueFields(String dbPath, Map valueSchema) { dbPath = removeTrailingSlashIfNeeded(dbPath); - DBDefinitionFactory.setDnDBSchemaVersion(dndbschemaversion); + DBDefinitionFactory.setDnDBSchemaVersion(dnDBSchemaVersion); DBDefinition dbDefinition = DBDefinitionFactory.getDefinition(Paths.get(dbPath), new OzoneConfiguration()); if (dbDefinition == null) { err().println("Error: Incorrect DB Path"); return false; } final DBColumnFamilyDefinition columnFamilyDefinition = - dbDefinition.getColumnFamily(table); + dbDefinition.getColumnFamily(tableName); if (columnFamilyDefinition == null) { - err().print("Error: Table with name '" + table + "' not found"); + err().print("Error: Table with name '" + tableName + "' not found"); return false; } Class c = columnFamilyDefinition.getValueType(); - valueSchema.put(c.getSimpleName(), getFieldsStructure(c, d)); + valueSchema.put(c.getSimpleName(), getFieldsStructure(c, depth)); return true; }