diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 0fb6e9288c1..68913bc3d74 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -25,7 +25,8 @@ Trunk (Unreleased) NEW FEATURES - HADOOP-6590. Add a username check for hadoop sub-commands (John Smith via aw) + HADOOP-6590. Add a username check for hadoop sub-commands (John Smith via + aw) HADOOP-11353. Add support for .hadooprc (aw) @@ -41,6 +42,9 @@ Trunk (Unreleased) HADOOP-11565. Add --slaves shell option (aw) + HADOOP-9642. Configuration to resolve environment variables via + ${env.VARIABLE} references (Kengo Seki via aw) + IMPROVEMENTS HADOOP-8017. Configure hadoop-main pom to get rid of M2E plugin execution diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java index 8a312ffda81..7c25e6caaab 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java @@ -146,6 +146,8 @@ import com.google.common.base.Preconditions; * available properties are:
When conf.get("tempdir") is called, then ${basedir} * will be resolved to another property in this Configuration, while * ${user.name} would then ordinarily be resolved to the value * of the System property with that name. - * By default, warnings will be given to any deprecated configuration + *
When conf.get("otherdir") is called, then ${env.BASE_DIR} + * will be resolved to the value of the ${BASE_DIR} environment variable. + * It supports ${env.NAME:-default} and ${env.NAME-default} notations. + * The former is resolved to “default” if ${NAME} environment variable is undefined + * or its value is empty. + * The latter behaves the same way only if ${NAME} is undefined. + *
By default, warnings will be given to any deprecated configuration
* parameters and these are suppressible by configuring
* log4j.logger.org.apache.hadoop.conf.Configuration.deprecation in
* log4j.properties file.
@@ -915,6 +929,7 @@ public class Configuration implements Iterable
+ *
@@ -947,7 +962,31 @@ public class Configuration implements Iterablename
property, null
if
* no such property exists. If the key is deprecated, it returns the value of
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestConfiguration.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestConfiguration.java
index a3675537bf0..ec6c964bb9e 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestConfiguration.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestConfiguration.java
@@ -50,6 +50,7 @@ import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.net.NetUtils;
import static org.apache.hadoop.util.PlatformName.IBM_JAVA;
import org.codehaus.jackson.map.ObjectMapper;
+import org.mockito.Mockito;
public class TestConfiguration extends TestCase {
@@ -148,46 +149,77 @@ public class TestConfiguration extends TestCase {
}
public void testVariableSubstitution() throws IOException {
+ // stubbing only environment dependent functions
+ Configuration mock = Mockito.spy(conf);
+ Mockito.when(mock.getProperty("user.name")).thenReturn("hadoop_user");
+ Mockito.when(mock.getenv("FILE_NAME")).thenReturn("hello");
+
out=new BufferedWriter(new FileWriter(CONFIG));
startConfig();
declareProperty("my.int", "${intvar}", "42");
declareProperty("intvar", "42", "42");
- declareProperty("my.base", "/tmp/${user.name}", UNSPEC);
- declareProperty("my.file", "hello", "hello");
+ declareProperty("my.base", "/tmp/${user.name}", "/tmp/hadoop_user");
+ declareProperty("my.file", "${env.FILE_NAME}", "hello");
declareProperty("my.suffix", ".txt", ".txt");
declareProperty("my.relfile", "${my.file}${my.suffix}", "hello.txt");
- declareProperty("my.fullfile", "${my.base}/${my.file}${my.suffix}", UNSPEC);
+ declareProperty("my.fullfile", "${my.base}/${my.file}${my.suffix}", "/tmp/hadoop_user/hello.txt");
// check that undefined variables are returned as-is
declareProperty("my.failsexpand", "a${my.undefvar}b", "a${my.undefvar}b");
endConfig();
Path fileResource = new Path(CONFIG);
- conf.addResource(fileResource);
+ mock.addResource(fileResource);
for (Prop p : props) {
System.out.println("p=" + p.name);
- String gotVal = conf.get(p.name);
- String gotRawVal = conf.getRaw(p.name);
+ String gotVal = mock.get(p.name);
+ String gotRawVal = mock.getRaw(p.name);
assertEq(p.val, gotRawVal);
- if (p.expectEval == UNSPEC) {
- // expansion is system-dependent (uses System properties)
- // can't do exact match so just check that all variables got expanded
- assertTrue(gotVal != null && -1 == gotVal.indexOf("${"));
- } else {
- assertEq(p.expectEval, gotVal);
- }
+ assertEq(p.expectEval, gotVal);
}
// check that expansion also occurs for getInt()
- assertTrue(conf.getInt("intvar", -1) == 42);
- assertTrue(conf.getInt("my.int", -1) == 42);
+ assertTrue(mock.getInt("intvar", -1) == 42);
+ assertTrue(mock.getInt("my.int", -1) == 42);
+ }
- Map