You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by to...@apache.org on 2011/05/11 03:03:32 UTC

svn commit: r1101714 - in /hadoop/common/trunk: ./ src/java/org/apache/hadoop/tools/ src/test/core/org/apache/hadoop/tools/

Author: todd
Date: Wed May 11 01:03:31 2011
New Revision: 1101714

URL: http://svn.apache.org/viewvc?rev=1101714&view=rev
Log:
HADOOP-7214. Add Common functionality necessary to provide an equivalent of /usr/bin/groups for Hadoop. Contributed by Aaron T. Myers.

Added:
    hadoop/common/trunk/src/java/org/apache/hadoop/tools/
    hadoop/common/trunk/src/java/org/apache/hadoop/tools/GetGroupsBase.java
    hadoop/common/trunk/src/java/org/apache/hadoop/tools/GetUserMappingsProtocol.java
    hadoop/common/trunk/src/test/core/org/apache/hadoop/tools/
    hadoop/common/trunk/src/test/core/org/apache/hadoop/tools/GetGroupsTestBase.java
Modified:
    hadoop/common/trunk/CHANGES.txt

Modified: hadoop/common/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/CHANGES.txt?rev=1101714&r1=1101713&r2=1101714&view=diff
==============================================================================
--- hadoop/common/trunk/CHANGES.txt (original)
+++ hadoop/common/trunk/CHANGES.txt Wed May 11 01:03:31 2011
@@ -29,6 +29,8 @@ Trunk (unreleased changes)
     HADOOP-6920. Metrics instrumentation to move new metrics2 framework.
     (Luke Lu via suresh)
 
+    HADOOP-7214. Add Common functionality necessary to provide an equivalent
+    of /usr/bin/groups for Hadoop. (Aaron T. Myers via todd)
 
   IMPROVEMENTS
 

Added: hadoop/common/trunk/src/java/org/apache/hadoop/tools/GetGroupsBase.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/java/org/apache/hadoop/tools/GetGroupsBase.java?rev=1101714&view=auto
==============================================================================
--- hadoop/common/trunk/src/java/org/apache/hadoop/tools/GetGroupsBase.java (added)
+++ hadoop/common/trunk/src/java/org/apache/hadoop/tools/GetGroupsBase.java Wed May 11 01:03:31 2011
@@ -0,0 +1,107 @@
+/**
+ * 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.hadoop.tools;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.InetSocketAddress;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.conf.Configured;
+import org.apache.hadoop.ipc.RPC;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.util.Tool;
+
+/**
+ * Base class for the HDFS and MR implementations of tools which fetch and
+ * display the groups that users belong to.
+ */
+public abstract class GetGroupsBase extends Configured implements Tool {
+  
+  private PrintStream out;
+  
+  /**
+   * Create an instance of this tool using the given configuration.
+   * @param conf
+   */
+  protected GetGroupsBase(Configuration conf) {
+    this(conf, System.out);
+  }
+  
+  /**
+   * Used exclusively for testing.
+   * 
+   * @param conf The configuration to use.
+   * @param out The PrintStream to write to, instead of System.out
+   */
+  protected GetGroupsBase(Configuration conf, PrintStream out) {
+    super(conf);
+    this.out = out;
+  }
+
+  /**
+   * Get the groups for the users given and print formatted output to the
+   * {@link PrintStream} configured earlier.
+   */
+  @Override
+  public int run(String[] args) throws Exception {
+    if (args.length == 0) {
+      args = new String[] { UserGroupInformation.getCurrentUser().getUserName() }; 
+    }
+
+    for (String username : args) {
+      StringBuilder sb = new StringBuilder();
+      sb.append(username + " :");
+      for (String group : getUgmProtocol().getGroupsForUser(username)) {
+        sb.append(" ");
+        sb.append(group);
+      }
+      out.println(sb);
+    }
+
+    return 0;
+  }
+
+  /**
+   * Must be overridden by subclasses to get the address where the
+   * {@link GetUserMappingsProtocol} implementation is running.
+   * 
+   * @param conf The configuration to use.
+   * @return The address where the service is listening.
+   * @throws IOException
+   */
+  protected abstract InetSocketAddress getProtocolAddress(Configuration conf)
+      throws IOException;
+  
+  /**
+   * Get a client of the {@link GetUserMappingsProtocol}.
+   * @return A {@link GetUserMappingsProtocol} client proxy.
+   * @throws IOException
+   */
+  private GetUserMappingsProtocol getUgmProtocol() throws IOException {
+    GetUserMappingsProtocol userGroupMappingProtocol =
+      RPC.getProxy(GetUserMappingsProtocol.class, 
+          GetUserMappingsProtocol.versionID,
+          getProtocolAddress(getConf()), UserGroupInformation.getCurrentUser(),
+          getConf(), NetUtils.getSocketFactory(getConf(),
+              GetUserMappingsProtocol.class));
+    return userGroupMappingProtocol;
+  }
+
+}

Added: hadoop/common/trunk/src/java/org/apache/hadoop/tools/GetUserMappingsProtocol.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/java/org/apache/hadoop/tools/GetUserMappingsProtocol.java?rev=1101714&view=auto
==============================================================================
--- hadoop/common/trunk/src/java/org/apache/hadoop/tools/GetUserMappingsProtocol.java (added)
+++ hadoop/common/trunk/src/java/org/apache/hadoop/tools/GetUserMappingsProtocol.java Wed May 11 01:03:31 2011
@@ -0,0 +1,46 @@
+/**
+ * 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.hadoop.tools;
+
+import java.io.IOException;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.ipc.VersionedProtocol;
+
+/**
+ * Protocol implemented by the Name Node and Job Tracker which maps users to
+ * groups.
+ */
+@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
+@InterfaceStability.Evolving
+public interface GetUserMappingsProtocol extends VersionedProtocol {
+  
+  /**
+   * Version 1: Initial version.
+   */
+  public static final long versionID = 1L;
+  
+  /**
+   * Get the groups which are mapped to the given user.
+   * @param user The user to get the groups for.
+   * @return The set of groups the user belongs to.
+   * @throws IOException
+   */
+  public String[] getGroupsForUser(String user) throws IOException;
+}

Added: hadoop/common/trunk/src/test/core/org/apache/hadoop/tools/GetGroupsTestBase.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/test/core/org/apache/hadoop/tools/GetGroupsTestBase.java?rev=1101714&view=auto
==============================================================================
--- hadoop/common/trunk/src/test/core/org/apache/hadoop/tools/GetGroupsTestBase.java (added)
+++ hadoop/common/trunk/src/test/core/org/apache/hadoop/tools/GetGroupsTestBase.java Wed May 11 01:03:31 2011
@@ -0,0 +1,127 @@
+/**
+ * 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.hadoop.tools;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.util.Tool;
+import org.apache.hadoop.util.ToolRunner;
+import org.junit.Before;
+import org.junit.Test;
+
+public abstract class GetGroupsTestBase {
+  
+  protected Configuration conf;
+  private UserGroupInformation testUser1;
+  private UserGroupInformation testUser2;
+  
+  protected abstract Tool getTool(PrintStream o);
+  
+  @Before
+  public void setUpUsers() throws IOException {
+    // Make sure the current user's info is in the list of test users.
+    UserGroupInformation currentUser = UserGroupInformation.getCurrentUser();
+    UserGroupInformation.createUserForTesting(currentUser.getUserName(), currentUser.getGroupNames());
+    
+    testUser1 = UserGroupInformation.createUserForTesting("foo", new String[]{"bar", "baz"});
+    testUser2 = UserGroupInformation.createUserForTesting("fiz", new String[]{"buz", "boz"});
+  }
+  
+  @Test
+  public void testNoUserGiven() throws Exception {
+    String actualOutput = runTool(conf, new String[0], true);
+    UserGroupInformation currentUser = UserGroupInformation.getCurrentUser();
+    assertEquals("No user provided should default to current user",
+        getExpectedOutput(currentUser), actualOutput);
+  }
+  
+  @Test
+  public void testExistingUser() throws Exception {
+    String actualOutput = runTool(conf, new String[]{testUser1.getUserName()}, true);
+    assertEquals("Show only the output of the user given",
+        getExpectedOutput(testUser1), actualOutput);
+  }
+  
+  @Test
+  public void testMultipleExistingUsers() throws Exception {
+    String actualOutput = runTool(conf,
+        new String[]{testUser1.getUserName(), testUser2.getUserName()}, true);
+    assertEquals("Show the output for both users given",
+        getExpectedOutput(testUser1) + getExpectedOutput(testUser2), actualOutput);
+  }
+  
+  @Test
+  public void testNonExistentUser() throws Exception {
+    String actualOutput = runTool(conf,
+        new String[]{"does-not-exist"}, true);
+    assertEquals("Show the output for only the user given, with no groups",
+        getExpectedOutput(UserGroupInformation.createRemoteUser("does-not-exist")),
+        actualOutput);
+  }
+  
+  @Test
+  public void testMultipleNonExistingUsers() throws Exception {
+    String actualOutput = runTool(conf,
+        new String[]{"does-not-exist1", "does-not-exist2"}, true);
+    assertEquals("Show the output for only the user given, with no groups",
+        getExpectedOutput(UserGroupInformation.createRemoteUser("does-not-exist1")) +
+        getExpectedOutput(UserGroupInformation.createRemoteUser("does-not-exist2")),
+        actualOutput);
+  }
+  
+  @Test
+  public void testExistingInterleavedWithNonExistentUsers() throws Exception {
+    String actualOutput = runTool(conf,
+        new String[]{"does-not-exist1", testUser1.getUserName(),
+                     "does-not-exist2", testUser2.getUserName()}, true);
+    assertEquals("Show the output for only the user given, with no groups",
+        getExpectedOutput(UserGroupInformation.createRemoteUser("does-not-exist1")) +
+        getExpectedOutput(testUser1) +
+        getExpectedOutput(UserGroupInformation.createRemoteUser("does-not-exist2")) +
+        getExpectedOutput(testUser2),
+        actualOutput);
+  }
+  
+  private static String getExpectedOutput(UserGroupInformation user) {
+    String expectedOutput = user.getUserName() + " :";
+    for (String group : user.getGroupNames()) {
+      expectedOutput += " " + group;
+    }
+    return expectedOutput + "\n";
+  }
+  
+  private String runTool(Configuration conf, String[] args, boolean success)
+      throws Exception {
+    ByteArrayOutputStream o = new ByteArrayOutputStream();
+    PrintStream out = new PrintStream(o, true);
+    try {
+      int ret = ToolRunner.run(getTool(out), args);
+      assertEquals(success, ret == 0);
+      return o.toString();
+    } finally {
+      o.close();
+      out.close();
+    }
+  }
+}