IGNITE-3202: Hadoop: Implemented user name mappers.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a815067a Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a815067a Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a815067a Branch: refs/heads/ignite-3212 Commit: a815067a0e8e7cfc9f49c57efe2b2eba562e9071 Parents: 56c6056 Author: vozerov-gridgain <voze...@gridgain.com> Authored: Tue May 31 10:23:00 2016 +0300 Committer: vozerov-gridgain <voze...@gridgain.com> Committed: Tue May 31 11:36:08 2016 +0300 ---------------------------------------------------------------------- .../hadoop/fs/BasicHadoopFileSystemFactory.java | 56 +++++++- .../fs/CachingHadoopFileSystemFactory.java | 7 +- .../fs/KerberosHadoopFileSystemFactory.java | 4 +- .../ignite/hadoop/util/BasicUserNameMapper.java | 114 +++++++++++++++ .../hadoop/util/ChainedUserNameMapper.java | 94 +++++++++++++ .../hadoop/util/KerberosUserNameMapper.java | 137 +++++++++++++++++++ .../ignite/hadoop/util/UserNameMapper.java | 37 +++++ .../util/BasicUserNameMapperSelfTest.java | 116 ++++++++++++++++ .../util/ChainedUserNameMapperSelfTest.java | 90 ++++++++++++ .../util/KerberosUserNameMapperSelfTest.java | 99 ++++++++++++++ .../ignite/igfs/Hadoop1DualAbstractTest.java | 46 +++++++ .../testsuites/IgniteHadoopTestSuite.java | 8 ++ 12 files changed, 796 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/BasicHadoopFileSystemFactory.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/BasicHadoopFileSystemFactory.java b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/BasicHadoopFileSystemFactory.java index 01fe6c9..06f76c3 100644 --- a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/BasicHadoopFileSystemFactory.java +++ b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/BasicHadoopFileSystemFactory.java @@ -21,6 +21,8 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.ignite.IgniteException; import org.apache.ignite.hadoop.fs.v1.IgniteHadoopFileSystem; +import org.apache.ignite.hadoop.util.KerberosUserNameMapper; +import org.apache.ignite.hadoop.util.UserNameMapper; import org.apache.ignite.internal.processors.hadoop.HadoopUtils; import org.apache.ignite.internal.processors.igfs.IgfsUtils; import org.apache.ignite.internal.util.typedef.internal.U; @@ -46,10 +48,13 @@ public class BasicHadoopFileSystemFactory implements HadoopFileSystemFactory, Ex private static final long serialVersionUID = 0L; /** File system URI. */ - protected String uri; + private String uri; /** File system config paths. */ - protected String[] cfgPaths; + private String[] cfgPaths; + + /** User name mapper. */ + private UserNameMapper usrNameMapper; /** Configuration of the secondary filesystem, never null. */ protected transient Configuration cfg; @@ -65,8 +70,13 @@ public class BasicHadoopFileSystemFactory implements HadoopFileSystemFactory, Ex } /** {@inheritDoc} */ - @Override public FileSystem get(String usrName) throws IOException { - return get0(IgfsUtils.fixUserName(usrName)); + @Override public final FileSystem get(String name) throws IOException { + String name0 = IgfsUtils.fixUserName(name); + + if (usrNameMapper != null) + name0 = IgfsUtils.fixUserName(usrNameMapper.map(name0)); + + return getWithMappedName(name0); } /** @@ -76,7 +86,7 @@ public class BasicHadoopFileSystemFactory implements HadoopFileSystemFactory, Ex * @return File system. * @throws IOException If failed. */ - protected FileSystem get0(String usrName) throws IOException { + protected FileSystem getWithMappedName(String usrName) throws IOException { assert cfg != null; try { @@ -168,6 +178,32 @@ public class BasicHadoopFileSystemFactory implements HadoopFileSystemFactory, Ex this.cfgPaths = cfgPaths; } + /** + * Get optional user name mapper. + * <p> + * When IGFS is invoked from Hadoop, user name is passed along the way to ensure that request will be performed + * with proper user context. User name is passed in a simple form and doesn't contain any extended information, + * such as host, domain or Kerberos realm. You may use name mapper to translate plain user name to full user + * name required by security engine of the underlying file system. + * <p> + * For example you may want to use {@link KerberosUserNameMapper} to user name from {@code "johndoe"} to + * {@code "john...@your.realm.com"}. + * + * @return User name mapper. + */ + @Nullable public UserNameMapper getUserNameMapper() { + return usrNameMapper; + } + + /** + * Set optional user name mapper. See {@link #getUserNameMapper()} for more information. + * + * @param usrNameMapper User name mapper. + */ + public void setUserNameMapper(@Nullable UserNameMapper usrNameMapper) { + this.usrNameMapper = usrNameMapper; + } + /** {@inheritDoc} */ @Override public void start() throws IgniteException { cfg = HadoopUtils.safeCreateConfiguration(); @@ -201,11 +237,15 @@ public class BasicHadoopFileSystemFactory implements HadoopFileSystemFactory, Ex throw new IgniteException("Failed to resolve secondary file system URI: " + uri); } } + + if (usrNameMapper != null && usrNameMapper instanceof LifecycleAware) + ((LifecycleAware)usrNameMapper).start(); } /** {@inheritDoc} */ @Override public void stop() throws IgniteException { - // No-op. + if (usrNameMapper != null && usrNameMapper instanceof LifecycleAware) + ((LifecycleAware)usrNameMapper).stop(); } /** {@inheritDoc} */ @@ -220,6 +260,8 @@ public class BasicHadoopFileSystemFactory implements HadoopFileSystemFactory, Ex } else out.writeInt(-1); + + out.writeObject(usrNameMapper); } /** {@inheritDoc} */ @@ -234,5 +276,7 @@ public class BasicHadoopFileSystemFactory implements HadoopFileSystemFactory, Ex for (int i = 0; i < cfgPathsCnt; i++) cfgPaths[i] = U.readString(in); } + + usrNameMapper = (UserNameMapper)in.readObject(); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/CachingHadoopFileSystemFactory.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/CachingHadoopFileSystemFactory.java b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/CachingHadoopFileSystemFactory.java index e1b30c4..bcbb082 100644 --- a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/CachingHadoopFileSystemFactory.java +++ b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/CachingHadoopFileSystemFactory.java @@ -23,7 +23,6 @@ import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.internal.processors.hadoop.fs.HadoopFileSystemsUtils; import org.apache.ignite.internal.processors.hadoop.fs.HadoopLazyConcurrentMap; -import org.apache.ignite.internal.processors.igfs.IgfsUtils; import java.io.IOException; import java.net.URI; @@ -47,7 +46,7 @@ public class CachingHadoopFileSystemFactory extends BasicHadoopFileSystemFactory private final transient HadoopLazyConcurrentMap<String, FileSystem> cache = new HadoopLazyConcurrentMap<>( new HadoopLazyConcurrentMap.ValueFactory<String, FileSystem>() { @Override public FileSystem createValue(String key) throws IOException { - return get0(key); + return CachingHadoopFileSystemFactory.super.getWithMappedName(key); } } ); @@ -60,8 +59,8 @@ public class CachingHadoopFileSystemFactory extends BasicHadoopFileSystemFactory } /** {@inheritDoc} */ - @Override public FileSystem get(String usrName) throws IOException { - return cache.getOrCreate(IgfsUtils.fixUserName(usrName)); + @Override public FileSystem getWithMappedName(String name) throws IOException { + return cache.getOrCreate(name); } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/KerberosHadoopFileSystemFactory.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/KerberosHadoopFileSystemFactory.java b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/KerberosHadoopFileSystemFactory.java index a78cabc..bbfbc59 100644 --- a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/KerberosHadoopFileSystemFactory.java +++ b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/KerberosHadoopFileSystemFactory.java @@ -68,10 +68,10 @@ public class KerberosHadoopFileSystemFactory extends BasicHadoopFileSystemFactor } /** {@inheritDoc} */ - @Override public FileSystem get(String userName) throws IOException { + @Override public FileSystem getWithMappedName(String name) throws IOException { reloginIfNeeded(); - return super.get(userName); + return super.getWithMappedName(name); } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/BasicUserNameMapper.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/BasicUserNameMapper.java b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/BasicUserNameMapper.java new file mode 100644 index 0000000..aea7196 --- /dev/null +++ b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/BasicUserNameMapper.java @@ -0,0 +1,114 @@ +/* + * 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.ignite.hadoop.util; + +import org.apache.ignite.internal.util.typedef.internal.S; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +/** + * Name mapper which maps one user name to another based on predefined dictionary. If name is not found in the + * dictionary, or dictionary is not defined, either passed user name or some default value could be returned. + */ +public class BasicUserNameMapper implements UserNameMapper { + /** */ + private static final long serialVersionUID = 0L; + + /** Mappings. */ + private Map<String, String> mappings; + + /** Whether to use default user name. */ + private boolean useDfltUsrName;; + + /** Default user name. */ + private String dfltUsrName; + + /** {@inheritDoc} */ + @Nullable @Override public String map(String name) { + assert mappings != null; + + String res = mappings.get(name); + + return res != null ? res : useDfltUsrName ? dfltUsrName : name; + } + + /** + * Get mappings. + * + * @return Mappings. + */ + @Nullable public Map<String, String> getMappings() { + return mappings; + } + + /** + * Set mappings. + * + * @param mappings Mappings. + */ + public void setMappings(@Nullable Map<String, String> mappings) { + this.mappings = mappings; + } + + /** + * Get whether to use default user name when there is no mapping for current user name. + * + * @return Whether to use default user name. + */ + public boolean isUseDefaultUserName() { + return useDfltUsrName; + } + + /** + * Set whether to use default user name when there is no mapping for current user name. + * + * @param useDfltUsrName Whether to use default user name. + */ + public void setUseDefaultUserName(boolean useDfltUsrName) { + this.useDfltUsrName = useDfltUsrName; + } + + /** + * Get default user name (optional). + * <p> + * This user name will be used if provided mappings doesn't contain mapping for the given user name and + * {#isUseDefaultUserName} is set to {@code true}. + * <p> + * Defaults to {@code null}. + * + * @return Default user name. + */ + @Nullable public String getDefaultUserName() { + return dfltUsrName; + } + + /** + * Set default user name (optional). See {@link #getDefaultUserName()} for more information. + * + * @param dfltUsrName Default user name. + */ + public void setDefaultUserName(@Nullable String dfltUsrName) { + this.dfltUsrName = dfltUsrName; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(BasicUserNameMapper.class, this); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/ChainedUserNameMapper.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/ChainedUserNameMapper.java b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/ChainedUserNameMapper.java new file mode 100644 index 0000000..7635e25 --- /dev/null +++ b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/ChainedUserNameMapper.java @@ -0,0 +1,94 @@ +/* + * 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.ignite.hadoop.util; + +import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.util.typedef.internal.S; +import org.apache.ignite.lifecycle.LifecycleAware; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + +/** + * Chained user name mapper. Delegate name conversion to child mappers. + */ +public class ChainedUserNameMapper implements UserNameMapper, LifecycleAware { + /** */ + private static final long serialVersionUID = 0L; + + /** Child mappers. */ + private UserNameMapper[] mappers; + + /** {@inheritDoc} */ + @Nullable @Override public String map(String name) { + for (UserNameMapper mapper : mappers) + name = mapper.map(name); + + return name; + } + + /** {@inheritDoc} */ + @Override public void start() throws IgniteException { + if (mappers == null) + throw new IgniteException("Mappers cannot be null."); + + for (int i = 0; i < mappers.length; i++) { + if (mappers[i] == null) + throw new IgniteException("Mapper cannot be null [index=" + i + ']'); + } + + for (UserNameMapper mapper : mappers) { + if (mapper instanceof LifecycleAware) + ((LifecycleAware)mapper).start(); + } + } + + /** {@inheritDoc} */ + @Override public void stop() throws IgniteException { + assert mappers != null; + + for (UserNameMapper mapper : mappers) { + if (mapper instanceof LifecycleAware) + ((LifecycleAware)mapper).stop(); + } + } + + /** + * Get child mappers. + * + * @return Child mappers. + */ + public UserNameMapper[] getMappers() { + return mappers; + } + + /** + * Set child mappers. + * + * @param mappers Child mappers. + */ + public void setMappers(UserNameMapper... mappers) { + this.mappers = mappers; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(ChainedUserNameMapper.class, this, + "mappers", mappers != null ? Arrays.toString(mappers) : null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/KerberosUserNameMapper.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/KerberosUserNameMapper.java b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/KerberosUserNameMapper.java new file mode 100644 index 0000000..433fb82 --- /dev/null +++ b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/KerberosUserNameMapper.java @@ -0,0 +1,137 @@ +/* + * 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.ignite.hadoop.util; + +import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.processors.igfs.IgfsUtils; +import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.internal.util.typedef.internal.S; +import org.apache.ignite.lifecycle.LifecycleAware; +import org.jetbrains.annotations.Nullable; + +/** + * Kerberos user name mapper. Use it when you need to map simple user name to Kerberos principal. + * E.g. from {@code johndoe} to {@code john...@your.realm.com} or {@code johndoe/ad...@your.realm.com}. + */ +public class KerberosUserNameMapper implements UserNameMapper, LifecycleAware { + /** */ + private static final long serialVersionUID = 0L; + + /** Instance. */ + private String instance; + + /** Realm. */ + private String realm; + + /** State. */ + private volatile State state; + + /** {@inheritDoc} */ + @Nullable @Override public String map(String name) { + assert state != null; + + name = IgfsUtils.fixUserName(name); + + switch (state) { + case NAME: + return name; + + case NAME_REALM: + return name + '@' + realm; + + case NAME_INSTANCE: + return name + '/' + instance; + + default: + assert state == State.NAME_INSTANCE_REALM; + + return name + '/' + instance + '@' + realm; + } + } + + /** {@inheritDoc} */ + @Override public void start() throws IgniteException { + if (!F.isEmpty(instance)) + state = F.isEmpty(realm) ? State.NAME_INSTANCE : State.NAME_INSTANCE_REALM; + else + state = F.isEmpty(realm) ? State.NAME : State.NAME_REALM; + } + + /** {@inheritDoc} */ + @Override public void stop() throws IgniteException { + // No-op. + } + + /** + * Get Kerberos instance (optional). + * + * @return Instance. + */ + @Nullable public String getInstance() { + return instance; + } + + /** + * Set Kerberos instance (optional). + * + * @param instance Kerberos instance. + */ + public void setInstance(@Nullable String instance) { + this.instance = instance; + } + + /** + * Get Kerberos realm (optional). + * + * @return Kerberos realm. + */ + @Nullable public String getRealm() { + return realm; + } + + /** + * Set Kerberos realm (optional). + * + * @param realm Kerberos realm. + */ + public void setRealm(@Nullable String realm) { + this.realm = realm; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(KerberosUserNameMapper.class, this); + } + + /** + * State enumeration. + */ + private enum State { + /** Name only. */ + NAME, + + /** Name and realm. */ + NAME_REALM, + + /** Name and host. */ + NAME_INSTANCE, + + /** Name, host and realm. */ + NAME_INSTANCE_REALM, + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/UserNameMapper.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/UserNameMapper.java b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/UserNameMapper.java new file mode 100644 index 0000000..26dc4b2 --- /dev/null +++ b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/util/UserNameMapper.java @@ -0,0 +1,37 @@ +/* + * 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.ignite.hadoop.util; + +import org.apache.ignite.hadoop.fs.HadoopFileSystemFactory; +import org.jetbrains.annotations.Nullable; + +import java.io.Serializable; + +/** + * Hadoop file system name mapper. Used by {@link HadoopFileSystemFactory} implementation to pass proper user names + * to the underlying Hadoop file system. + */ +public interface UserNameMapper extends Serializable { + /** + * Map user name. + * + * @param name User name. + * @return Mapped user name. + */ + @Nullable public String map(String name); +} http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/BasicUserNameMapperSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/BasicUserNameMapperSelfTest.java b/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/BasicUserNameMapperSelfTest.java new file mode 100644 index 0000000..54b03f9 --- /dev/null +++ b/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/BasicUserNameMapperSelfTest.java @@ -0,0 +1,116 @@ +/* + * 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.ignite.hadoop.util; + +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +/** + * Test for basic user name mapper. + */ +public class BasicUserNameMapperSelfTest extends GridCommonAbstractTest { + /** + * Test empty mappings. + * + * @throws Exception If failed. + */ + public void testEmptyMappings() throws Exception { + Map<String, String> map = new HashMap<>(); + + BasicUserNameMapper mapper = create(map, false, null); + + assertNull(mapper.map(null)); + assertEquals("1", mapper.map("1")); + assertEquals("2", mapper.map("2")); + + mapper = create(map, true, null); + + assertNull(mapper.map(null)); + assertNull(mapper.map("1")); + assertNull(mapper.map("2")); + + mapper = create(map, false, "A"); + + assertNull(mapper.map(null)); + assertEquals("1", mapper.map("1")); + assertEquals("2", mapper.map("2")); + + mapper = create(map, true, "A"); + + assertEquals("A", mapper.map(null)); + assertEquals("A", mapper.map("1")); + assertEquals("A", mapper.map("2")); + } + + /** + * Test regular mappings. + * + * @throws Exception If failed. + */ + public void testMappings() throws Exception { + Map<String, String> map = new HashMap<>(); + + map.put("1", "101"); + + BasicUserNameMapper mapper = create(map, false, null); + + assertNull(mapper.map(null)); + assertEquals("101", mapper.map("1")); + assertEquals("2", mapper.map("2")); + + mapper = create(map, true, null); + + assertNull(mapper.map(null)); + assertEquals("101", mapper.map("1")); + assertNull(mapper.map("2")); + + mapper = create(map, false, "A"); + + assertNull(mapper.map(null)); + assertEquals("101", mapper.map("1")); + assertEquals("2", mapper.map("2")); + + mapper = create(map, true, "A"); + + assertEquals("A", mapper.map(null)); + assertEquals("101", mapper.map("1")); + assertEquals("A", mapper.map("2")); + } + + /** + * Create mapper. + * + * @param dictionary Dictionary. + * @param useDfltUsrName Whether to use default user name. + * @param dfltUsrName Default user name. + * @return Mapper. + */ + private BasicUserNameMapper create(@Nullable Map<String, String> dictionary, boolean useDfltUsrName, + @Nullable String dfltUsrName) { + BasicUserNameMapper mapper = new BasicUserNameMapper(); + + mapper.setMappings(dictionary); + mapper.setUseDefaultUserName(useDfltUsrName); + mapper.setDefaultUserName(dfltUsrName); + + return mapper; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/ChainedUserNameMapperSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/ChainedUserNameMapperSelfTest.java b/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/ChainedUserNameMapperSelfTest.java new file mode 100644 index 0000000..5bdac8f --- /dev/null +++ b/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/ChainedUserNameMapperSelfTest.java @@ -0,0 +1,90 @@ +package org.apache.ignite.hadoop.util; + +import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.processors.igfs.IgfsUtils; +import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +import java.util.Collections; +import java.util.concurrent.Callable; + +/** + * Tests for chained user name mapper. + */ +public class ChainedUserNameMapperSelfTest extends GridCommonAbstractTest { + /** Test instance. */ + private static final String INSTANCE = "test_instance"; + + /** Test realm. */ + private static final String REALM = "test_realm"; + + /** + * Test case when mappers are null. + * + * @throws Exception If failed. + */ + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + public void testNullMappers() throws Exception { + GridTestUtils.assertThrows(null, new Callable<Void>() { + @Override public Void call() throws Exception { + create((UserNameMapper[])null); + + return null; + } + }, IgniteException.class, null); + } + + /** + * Test case when one of mappers is null. + * + * @throws Exception If failed. + */ + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + public void testNullMapperElement() throws Exception { + GridTestUtils.assertThrows(null, new Callable<Void>() { + @Override public Void call() throws Exception { + create(new BasicUserNameMapper(), null); + + return null; + } + }, IgniteException.class, null); + } + + /** + * Test actual chaining logic. + * + * @throws Exception If failed. + */ + public void testChaining() throws Exception { + BasicUserNameMapper mapper1 = new BasicUserNameMapper(); + + mapper1.setMappings(Collections.singletonMap("1", "101")); + + KerberosUserNameMapper mapper2 = new KerberosUserNameMapper(); + + mapper2.setInstance(INSTANCE); + mapper2.setRealm(REALM); + + ChainedUserNameMapper mapper = create(mapper1, mapper2); + + assertEquals("101" + "/" + INSTANCE + "@" + REALM, mapper.map("1")); + assertEquals("2" + "/" + INSTANCE + "@" + REALM, mapper.map("2")); + assertEquals(IgfsUtils.fixUserName(null) + "/" + INSTANCE + "@" + REALM, mapper.map(null)); + } + + /** + * Create chained mapper. + * + * @param mappers Child mappers. + * @return Chained mapper. + */ + private ChainedUserNameMapper create(UserNameMapper... mappers) { + ChainedUserNameMapper mapper = new ChainedUserNameMapper(); + + mapper.setMappers(mappers); + + mapper.start(); + + return mapper; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/KerberosUserNameMapperSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/KerberosUserNameMapperSelfTest.java b/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/KerberosUserNameMapperSelfTest.java new file mode 100644 index 0000000..cc685bb --- /dev/null +++ b/modules/hadoop/src/test/java/org/apache/ignite/hadoop/util/KerberosUserNameMapperSelfTest.java @@ -0,0 +1,99 @@ +/* + * 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.ignite.hadoop.util; + +import org.apache.ignite.internal.processors.igfs.IgfsUtils; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.jetbrains.annotations.Nullable; + +/** + * Tests for Kerberos name mapper. + */ +public class KerberosUserNameMapperSelfTest extends GridCommonAbstractTest { + /** Test instance. */ + private static final String INSTANCE = "test_instance"; + + /** Test realm. */ + private static final String REALM = "test_realm"; + + /** + * Test mapper without instance and realm components. + * + * @throws Exception If failed. + */ + public void testMapper() throws Exception { + KerberosUserNameMapper mapper = create(null, null); + + assertEquals(IgfsUtils.fixUserName(null), mapper.map(null)); + assertEquals("test", mapper.map("test")); + } + + /** + * Test mapper with instance component. + * + * @throws Exception If failed. + */ + public void testMapperInstance() throws Exception { + KerberosUserNameMapper mapper = create(INSTANCE, null); + + assertEquals(IgfsUtils.fixUserName(null) + "/" + INSTANCE, mapper.map(null)); + assertEquals("test" + "/" + INSTANCE, mapper.map("test")); + } + + /** + * Test mapper with realm. + * + * @throws Exception If failed. + */ + public void testMapperRealm() throws Exception { + KerberosUserNameMapper mapper = create(null, REALM); + + assertEquals(IgfsUtils.fixUserName(null) + "@" + REALM, mapper.map(null)); + assertEquals("test" + "@" + REALM, mapper.map("test")); + } + + /** + * Test mapper with instance and realm components. + * + * @throws Exception If failed. + */ + public void testMapperInstanceAndRealm() throws Exception { + KerberosUserNameMapper mapper = create(INSTANCE, REALM); + + assertEquals(IgfsUtils.fixUserName(null) + "/" + INSTANCE + "@" + REALM, mapper.map(null)); + assertEquals("test" + "/" + INSTANCE + "@" + REALM, mapper.map("test")); + } + + /** + * Create mapper. + * + * @param instance Instance. + * @param realm Realm. + * @return Mapper. + */ + private KerberosUserNameMapper create(@Nullable String instance, @Nullable String realm) { + KerberosUserNameMapper mapper = new KerberosUserNameMapper(); + + mapper.setInstance(instance); + mapper.setRealm(realm); + + mapper.start(); + + return mapper; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/test/java/org/apache/ignite/igfs/Hadoop1DualAbstractTest.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/test/java/org/apache/ignite/igfs/Hadoop1DualAbstractTest.java b/modules/hadoop/src/test/java/org/apache/ignite/igfs/Hadoop1DualAbstractTest.java index d1d7c10..4ee0b75 100644 --- a/modules/hadoop/src/test/java/org/apache/ignite/igfs/Hadoop1DualAbstractTest.java +++ b/modules/hadoop/src/test/java/org/apache/ignite/igfs/Hadoop1DualAbstractTest.java @@ -19,11 +19,17 @@ package org.apache.ignite.igfs; import java.io.IOException; import org.apache.hadoop.conf.Configuration; +import org.apache.ignite.IgniteException; import org.apache.ignite.hadoop.fs.CachingHadoopFileSystemFactory; import org.apache.ignite.hadoop.fs.IgniteHadoopIgfsSecondaryFileSystem; +import org.apache.ignite.hadoop.util.ChainedUserNameMapper; +import org.apache.ignite.hadoop.util.KerberosUserNameMapper; +import org.apache.ignite.hadoop.util.UserNameMapper; import org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystem; import org.apache.ignite.internal.processors.igfs.IgfsDualAbstractSelfTest; import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; +import org.apache.ignite.lifecycle.LifecycleAware; +import org.jetbrains.annotations.Nullable; import static org.apache.ignite.IgniteFileSystem.IGFS_SCHEME; import static org.apache.ignite.igfs.HadoopSecondaryFileSystemConfigurationTest.SECONDARY_CFG_PATH; @@ -75,10 +81,21 @@ public abstract class Hadoop1DualAbstractTest extends IgfsDualAbstractSelfTest { prepareConfiguration(); + KerberosUserNameMapper mapper1 = new KerberosUserNameMapper(); + + mapper1.setRealm("TEST.COM"); + + TestUserNameMapper mapper2 = new TestUserNameMapper(); + + ChainedUserNameMapper mapper = new ChainedUserNameMapper(); + + mapper.setMappers(mapper1, mapper2); + CachingHadoopFileSystemFactory factory = new CachingHadoopFileSystemFactory(); factory.setUri(secondaryUri); factory.setConfigPaths(secondaryConfFullPath); + factory.setUserNameMapper(mapper); IgniteHadoopIgfsSecondaryFileSystem second = new IgniteHadoopIgfsSecondaryFileSystem(); @@ -110,4 +127,33 @@ public abstract class Hadoop1DualAbstractTest extends IgfsDualAbstractSelfTest { secondaryUri = mkUri(IGFS_SCHEME, SECONDARY_AUTHORITY); } + + /** + * Test user name mapper. + */ + private static class TestUserNameMapper implements UserNameMapper, LifecycleAware { + /** */ + private static final long serialVersionUID = 0L; + + /** Started flag. */ + private boolean started; + + /** {@inheritDoc} */ + @Nullable @Override public String map(String name) { + assert started; + assert name != null && name.contains("@"); + + return name.substring(0, name.indexOf("@")); + } + + /** {@inheritDoc} */ + @Override public void start() throws IgniteException { + started = true; + } + + /** {@inheritDoc} */ + @Override public void stop() throws IgniteException { + // No-op. + } + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/a815067a/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java b/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java index 554cbc7..7d877ab 100644 --- a/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java +++ b/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java @@ -26,6 +26,10 @@ import org.apache.ignite.client.hadoop.HadoopClientProtocolEmbeddedSelfTest; import org.apache.ignite.client.hadoop.HadoopClientProtocolSelfTest; import org.apache.ignite.hadoop.cache.HadoopTxConfigCacheTest; import org.apache.ignite.hadoop.fs.KerberosHadoopFileSystemFactorySelfTest; +import org.apache.ignite.hadoop.util.BasicUserNameMapperSelfTest; +import org.apache.ignite.hadoop.util.ChainedUserNameMapperSelfTest; +import org.apache.ignite.hadoop.util.KerberosUserNameMapper; +import org.apache.ignite.hadoop.util.KerberosUserNameMapperSelfTest; import org.apache.ignite.igfs.Hadoop1OverIgfsDualAsyncTest; import org.apache.ignite.igfs.Hadoop1OverIgfsDualSyncTest; import org.apache.ignite.igfs.HadoopFIleSystemFactorySelfTest; @@ -106,6 +110,10 @@ public class IgniteHadoopTestSuite extends TestSuite { TestSuite suite = new TestSuite("Ignite Hadoop MR Test Suite"); + suite.addTest(new TestSuite(ldr.loadClass(BasicUserNameMapperSelfTest.class.getName()))); + suite.addTest(new TestSuite(ldr.loadClass(KerberosUserNameMapperSelfTest.class.getName()))); + suite.addTest(new TestSuite(ldr.loadClass(ChainedUserNameMapperSelfTest.class.getName()))); + suite.addTest(new TestSuite(ldr.loadClass(KerberosHadoopFileSystemFactorySelfTest.class.getName()))); suite.addTest(new TestSuite(ldr.loadClass(HadoopSnappyTest.class.getName())));