From a95949bbd9e263d416fc96ddf99eb82b50e103e8 Mon Sep 17 00:00:00 2001 From: yuanyi Date: Tue, 22 Jun 2021 18:17:32 +0800 Subject: [PATCH 01/14] add_environment_variable_DynamicConfigProvider --- .../druid/metadata/DynamicConfigProvider.java | 1 + ...ironmentVariableDynamicConfigProvider.java | 89 +++++++++++++++++++ ...mentVariableDynamicConfigProviderTest.java | 42 +++++++++ 3 files changed, 132 insertions(+) create mode 100644 core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java create mode 100644 core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java diff --git a/core/src/main/java/org/apache/druid/metadata/DynamicConfigProvider.java b/core/src/main/java/org/apache/druid/metadata/DynamicConfigProvider.java index 52f032a0a195..166437c5cc54 100644 --- a/core/src/main/java/org/apache/druid/metadata/DynamicConfigProvider.java +++ b/core/src/main/java/org/apache/druid/metadata/DynamicConfigProvider.java @@ -32,6 +32,7 @@ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = MapStringDynamicConfigProvider.class) @JsonSubTypes(value = { @JsonSubTypes.Type(name = "mapString", value = MapStringDynamicConfigProvider.class), + @JsonSubTypes.Type(name = "environment", value = EnvironmentVariableDynamicConfigProvider.class) }) public interface DynamicConfigProvider { diff --git a/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java b/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java new file mode 100644 index 000000000000..2828b85005bf --- /dev/null +++ b/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java @@ -0,0 +1,89 @@ +/* + * 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.druid.metadata; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.collect.ImmutableMap; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class EnvironmentVariableDynamicConfigProvider implements DynamicConfigProvider +{ + private final ImmutableMap variables; + + @JsonCreator + public EnvironmentVariableDynamicConfigProvider( + @JsonProperty("variables") Map config + ) + { + this.variables = ImmutableMap.copyOf(config); + } + + @JsonProperty("variables") + public Map getVariables() + { + return variables; + } + + @Override + public Map getConfig() + { + HashMap map = new HashMap<>(); + for (Map.Entry entry : variables.entrySet()) { + map.put(entry.getKey(), System.getenv(entry.getValue())); + } + return map; + } + + @Override + public String toString() + { + return "EnvironmentVariablePasswordProvider{" + + "variable='" + variables + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) + { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + EnvironmentVariableDynamicConfigProvider that = (EnvironmentVariableDynamicConfigProvider) o; + + return Objects.equals(variables, that.variables); + + } + + @Override + public int hashCode() + { + return variables != null ? variables.hashCode() : 0; + } + + +} diff --git a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java new file mode 100644 index 000000000000..6cca89026676 --- /dev/null +++ b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java @@ -0,0 +1,42 @@ +/* + * 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.druid.metadata; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; + +public class EnvironmentVariableDynamicConfigProviderTest +{ + private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); + + @Test + public void testSerde() throws IOException + { + String providerString = "{\"type\": \"environment\", \"variables\" : {\"testKey\":\"testValue\"}}"; + DynamicConfigProvider provider = JSON_MAPPER.readValue(providerString, DynamicConfigProvider.class); + Assert.assertTrue(provider instanceof EnvironmentVariableDynamicConfigProvider); + Assert.assertEquals("testValue", ((EnvironmentVariableDynamicConfigProvider) provider).getVariables().get("testKey")); + DynamicConfigProvider serde = JSON_MAPPER.readValue(JSON_MAPPER.writeValueAsString(provider), DynamicConfigProvider.class); + Assert.assertEquals(provider, serde); + } +} From 72a8a322017fd7c78387709138b85fa5d7125605 Mon Sep 17 00:00:00 2001 From: yuanyi Date: Fri, 25 Jun 2021 15:53:11 +0800 Subject: [PATCH 02/14] fix code --- ...ironmentVariableDynamicConfigProvider.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java b/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java index 2828b85005bf..466eb8eb6cd6 100644 --- a/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java +++ b/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java @@ -22,21 +22,31 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.collect.ImmutableMap; +import org.apache.druid.java.util.common.logger.Logger; import java.util.HashMap; import java.util.Map; import java.util.Objects; -public class EnvironmentVariableDynamicConfigProvider implements DynamicConfigProvider +public class EnvironmentVariableDynamicConfigProvider implements DynamicConfigProvider { - private final ImmutableMap variables; + + private static final Logger log = new Logger(EnvironmentVariableDynamicConfigProvider.class); + + private ImmutableMap variables; @JsonCreator public EnvironmentVariableDynamicConfigProvider( @JsonProperty("variables") Map config ) { - this.variables = ImmutableMap.copyOf(config); + try { + this.variables = ImmutableMap.copyOf(config); + } + catch (NullPointerException e) { + log.error(e, "Can not parse config by EnvironmentVariableDynamicConfigProvider! Please check your config file."); + throw e; + } } @JsonProperty("variables") @@ -46,7 +56,7 @@ public Map getVariables() } @Override - public Map getConfig() + public Map getConfig() { HashMap map = new HashMap<>(); for (Map.Entry entry : variables.entrySet()) { @@ -82,8 +92,7 @@ public boolean equals(Object o) @Override public int hashCode() { - return variables != null ? variables.hashCode() : 0; + return variables.hashCode(); } - } From a6f2042774db3289c623af9e689270fabb06afd3 Mon Sep 17 00:00:00 2001 From: yuanyi Date: Sat, 26 Jun 2021 12:35:50 +0800 Subject: [PATCH 03/14] code fixed --- .../EnvironmentVariableDynamicConfigProvider.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java b/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java index 466eb8eb6cd6..70e630201863 100644 --- a/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java +++ b/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import org.apache.druid.java.util.common.logger.Logger; @@ -33,20 +34,14 @@ public class EnvironmentVariableDynamicConfigProvider implements DynamicConfigPr private static final Logger log = new Logger(EnvironmentVariableDynamicConfigProvider.class); - private ImmutableMap variables; + private final ImmutableMap variables; @JsonCreator public EnvironmentVariableDynamicConfigProvider( @JsonProperty("variables") Map config ) { - try { - this.variables = ImmutableMap.copyOf(config); - } - catch (NullPointerException e) { - log.error(e, "Can not parse config by EnvironmentVariableDynamicConfigProvider! Please check your config file."); - throw e; - } + this.variables = ImmutableMap.copyOf(Preconditions.checkNotNull(config, "config")); } @JsonProperty("variables") From 02a439713ef37da21fbf733f6d630368fed7ac94 Mon Sep 17 00:00:00 2001 From: yuanyi Date: Sat, 26 Jun 2021 12:37:10 +0800 Subject: [PATCH 04/14] code fixed --- .../metadata/EnvironmentVariableDynamicConfigProvider.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java b/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java index 70e630201863..629c748cf88d 100644 --- a/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java +++ b/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java @@ -23,7 +23,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; -import org.apache.druid.java.util.common.logger.Logger; import java.util.HashMap; import java.util.Map; @@ -31,9 +30,6 @@ public class EnvironmentVariableDynamicConfigProvider implements DynamicConfigProvider { - - private static final Logger log = new Logger(EnvironmentVariableDynamicConfigProvider.class); - private final ImmutableMap variables; @JsonCreator From 7b0f9728472016c4b1644fc0f22e723a9e0f80db Mon Sep 17 00:00:00 2001 From: yuanyi Date: Wed, 30 Jun 2021 12:48:41 +0800 Subject: [PATCH 05/14] add document --- docs/operations/dynamic-config-provider.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/operations/dynamic-config-provider.md b/docs/operations/dynamic-config-provider.md index 33bf96639322..cf1140aa59c2 100644 --- a/docs/operations/dynamic-config-provider.md +++ b/docs/operations/dynamic-config-provider.md @@ -31,3 +31,16 @@ Users can create custom extension of the `DynamicConfigProvider` interface that For more information, see [Adding a new DynamicConfigProvider implementation](../development/modules.md#adding-a-new-dynamicconfigprovider-implementation). +## EnvironmentVariableDynamicConfigProvider + +`EnvironmentVariableDynamicConfigProvider` can be used to replace `EnvironmentVariablePasswordProvider`. This class allow users to avoid exposing passwords or other secret information in the runtime.properties file. You can set environment variables in the following example: +```json +druid.metadata.storage.connector.dynamicConfigProvider={"type": "environment","variables":{"user": "MY_USER_NAME_VAR","password": "MY_PASSWORD_VAR"} +``` +The values are described below. + +|Field|Type|Description|Required| +|-----|----|-----------|--------| +|`type`|String|dynamic config provider type|Yes: `environment`| +|`variables`|Map|environment variables to get information from|Yes| + From 5f297c7d63fc5d55ae7ef0534d2b191bc955f9bf Mon Sep 17 00:00:00 2001 From: yuanyi Date: Wed, 30 Jun 2021 12:50:37 +0800 Subject: [PATCH 06/14] fix doc --- docs/operations/dynamic-config-provider.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/operations/dynamic-config-provider.md b/docs/operations/dynamic-config-provider.md index cf1140aa59c2..3d82cae9bbfd 100644 --- a/docs/operations/dynamic-config-provider.md +++ b/docs/operations/dynamic-config-provider.md @@ -35,7 +35,7 @@ For more information, see [Adding a new DynamicConfigProvider implementation](.. `EnvironmentVariableDynamicConfigProvider` can be used to replace `EnvironmentVariablePasswordProvider`. This class allow users to avoid exposing passwords or other secret information in the runtime.properties file. You can set environment variables in the following example: ```json -druid.metadata.storage.connector.dynamicConfigProvider={"type": "environment","variables":{"user": "MY_USER_NAME_VAR","password": "MY_PASSWORD_VAR"} +druid.metadata.storage.connector.dynamicConfigProvider={"type": "environment","variables":{"user": "MY_USER_NAME_VAR","password": "MY_PASSWORD_VAR"}} ``` The values are described below. From 18c22f19a7e1c3aa4117eff83dc0eb6721ad6cf2 Mon Sep 17 00:00:00 2001 From: yuanyi Date: Thu, 1 Jul 2021 17:01:50 +0800 Subject: [PATCH 07/14] fix doc --- docs/operations/dynamic-config-provider.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/operations/dynamic-config-provider.md b/docs/operations/dynamic-config-provider.md index 3d82cae9bbfd..88ca6fb53b92 100644 --- a/docs/operations/dynamic-config-provider.md +++ b/docs/operations/dynamic-config-provider.md @@ -31,7 +31,7 @@ Users can create custom extension of the `DynamicConfigProvider` interface that For more information, see [Adding a new DynamicConfigProvider implementation](../development/modules.md#adding-a-new-dynamicconfigprovider-implementation). -## EnvironmentVariableDynamicConfigProvider +## Environment variable dynamic config provider `EnvironmentVariableDynamicConfigProvider` can be used to replace `EnvironmentVariablePasswordProvider`. This class allow users to avoid exposing passwords or other secret information in the runtime.properties file. You can set environment variables in the following example: ```json From 60fdd538657b605d48c14a7c8d304316ee26d838 Mon Sep 17 00:00:00 2001 From: yuanyi Date: Thu, 1 Jul 2021 18:35:50 +0800 Subject: [PATCH 08/14] add more unit test --- ...mentVariableDynamicConfigProviderTest.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java index 6cca89026676..91f3d2c1291b 100644 --- a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java +++ b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java @@ -20,15 +20,26 @@ package org.apache.druid.metadata; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableMap; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.Map; public class EnvironmentVariableDynamicConfigProviderTest { private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); + @Before + public void setupTest() throws Exception + { + setEnv(ImmutableMap.of("DRUID_USER", "druid", "DRUID_PASSWORD", "123")); + } + @Test public void testSerde() throws IOException { @@ -39,4 +50,42 @@ public void testSerde() throws IOException DynamicConfigProvider serde = JSON_MAPPER.readValue(JSON_MAPPER.writeValueAsString(provider), DynamicConfigProvider.class); Assert.assertEquals(provider, serde); } + + @Test + public void testGetConfig() throws Exception + { + String providerString = "{\"type\": \"environment\", \"variables\" : {\"user\":\"DRUID_USER\",\"password\":\"DRUID_PASSWORD\"}}"; + DynamicConfigProvider provider = JSON_MAPPER.readValue(providerString, DynamicConfigProvider.class); + Assert.assertTrue(provider instanceof EnvironmentVariableDynamicConfigProvider); + Assert.assertEquals("druid", ((EnvironmentVariableDynamicConfigProvider) provider).getConfig().get("user")); + Assert.assertEquals("123", ((EnvironmentVariableDynamicConfigProvider) provider).getConfig().get("password")); + } + + protected static void setEnv(Map newenv) throws Exception + { + try { + Class processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment"); + Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment"); + theEnvironmentField.setAccessible(true); + Map env = (Map) theEnvironmentField.get(null); + env.putAll(newenv); + Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment"); + theCaseInsensitiveEnvironmentField.setAccessible(true); + Map cienv = (Map) theCaseInsensitiveEnvironmentField.get(null); + cienv.putAll(newenv); + } catch (NoSuchFieldException e) { + Class[] classes = Collections.class.getDeclaredClasses(); + Map env = System.getenv(); + for (Class cl : classes) { + if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) { + Field field = cl.getDeclaredField("m"); + field.setAccessible(true); + Object obj = field.get(env); + Map map = (Map) obj; + map.clear(); + map.putAll(newenv); + } + } + } + } } From cc774cc5a67d78f6d17931ac850aa8b342d98cc2 Mon Sep 17 00:00:00 2001 From: yuanyi Date: Thu, 1 Jul 2021 18:39:26 +0800 Subject: [PATCH 09/14] fix style --- .../metadata/EnvironmentVariableDynamicConfigProviderTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java index 91f3d2c1291b..aab8780678d9 100644 --- a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java +++ b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java @@ -73,7 +73,8 @@ protected static void setEnv(Map newenv) throws Exception theCaseInsensitiveEnvironmentField.setAccessible(true); Map cienv = (Map) theCaseInsensitiveEnvironmentField.get(null); cienv.putAll(newenv); - } catch (NoSuchFieldException e) { + } + catch (NoSuchFieldException e) { Class[] classes = Collections.class.getDeclaredClasses(); Map env = System.getenv(); for (Class cl : classes) { From 6d352bc3819da994c4db76238f989c33870813dd Mon Sep 17 00:00:00 2001 From: yuanyi Date: Fri, 2 Jul 2021 12:20:30 +0800 Subject: [PATCH 10/14] fix document --- docs/operations/dynamic-config-provider.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/operations/dynamic-config-provider.md b/docs/operations/dynamic-config-provider.md index 88ca6fb53b92..141244483bdc 100644 --- a/docs/operations/dynamic-config-provider.md +++ b/docs/operations/dynamic-config-provider.md @@ -33,9 +33,9 @@ For more information, see [Adding a new DynamicConfigProvider implementation](.. ## Environment variable dynamic config provider -`EnvironmentVariableDynamicConfigProvider` can be used to replace `EnvironmentVariablePasswordProvider`. This class allow users to avoid exposing passwords or other secret information in the runtime.properties file. You can set environment variables in the following example: +`EnvironmentVariableDynamicConfigProvider` can be used to avoid exposing credentials or other secret information in the configuration files using environment variables. An example to use this configProvider is: ```json -druid.metadata.storage.connector.dynamicConfigProvider={"type": "environment","variables":{"user": "MY_USER_NAME_VAR","password": "MY_PASSWORD_VAR"}} +druid.some.config.dynamicConfigProvider={"type": "environment","variables":{"secret1": "SECRET1_VAR","secret2": "SECRET2_VAR"}} ``` The values are described below. From 13d62fe7b425c2c41b360235ab7308ed6d8a2efc Mon Sep 17 00:00:00 2001 From: yuanyi Date: Sat, 3 Jul 2021 12:52:01 +0800 Subject: [PATCH 11/14] bug fixed --- docs/operations/dynamic-config-provider.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/operations/dynamic-config-provider.md b/docs/operations/dynamic-config-provider.md index 141244483bdc..45b61d54b942 100644 --- a/docs/operations/dynamic-config-provider.md +++ b/docs/operations/dynamic-config-provider.md @@ -33,7 +33,7 @@ For more information, see [Adding a new DynamicConfigProvider implementation](.. ## Environment variable dynamic config provider -`EnvironmentVariableDynamicConfigProvider` can be used to avoid exposing credentials or other secret information in the configuration files using environment variables. An example to use this configProvider is: +`EnvironmentVariableDynamicConfigProvider` can be used to avoid exposing credentials or other secret information in the configuration files using environment variables. An example to use this `configProvider` is: ```json druid.some.config.dynamicConfigProvider={"type": "environment","variables":{"secret1": "SECRET1_VAR","secret2": "SECRET2_VAR"}} ``` From b32d3e00bb0efe045c472e9770b8ed06762a8183 Mon Sep 17 00:00:00 2001 From: yuanyi Date: Mon, 12 Jul 2021 19:44:53 +0800 Subject: [PATCH 12/14] fix unit test --- ...mentVariableDynamicConfigProviderTest.java | 65 ++++++++++++------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java index aab8780678d9..756786b7ba9e 100644 --- a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java +++ b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableMap; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -33,11 +34,18 @@ public class EnvironmentVariableDynamicConfigProviderTest { private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); + private static final Map NEW_ENV_MAP = ImmutableMap.of("DRUID_USER", "druid", "DRUID_PASSWORD", "123"); @Before public void setupTest() throws Exception { - setEnv(ImmutableMap.of("DRUID_USER", "druid", "DRUID_PASSWORD", "123")); + changeENV(); + } + + @After + public void tearDownTest() throws Exception + { + recoverENV(); } @Test @@ -61,32 +69,41 @@ public void testGetConfig() throws Exception Assert.assertEquals("123", ((EnvironmentVariableDynamicConfigProvider) provider).getConfig().get("password")); } - protected static void setEnv(Map newenv) throws Exception + private static void changeENV() throws Exception + { + getENVMap().putAll(NEW_ENV_MAP); + } + + private static void recoverENV() throws Exception { - try { - Class processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment"); - Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment"); - theEnvironmentField.setAccessible(true); - Map env = (Map) theEnvironmentField.get(null); - env.putAll(newenv); - Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment"); - theCaseInsensitiveEnvironmentField.setAccessible(true); - Map cienv = (Map) theCaseInsensitiveEnvironmentField.get(null); - cienv.putAll(newenv); + Map envMap = getENVMap(); + for (String envName : NEW_ENV_MAP.keySet()) { + envMap.remove(envName); } - catch (NoSuchFieldException e) { - Class[] classes = Collections.class.getDeclaredClasses(); - Map env = System.getenv(); - for (Class cl : classes) { - if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) { - Field field = cl.getDeclaredField("m"); - field.setAccessible(true); - Object obj = field.get(env); - Map map = (Map) obj; - map.clear(); - map.putAll(newenv); - } + } + + /** + * This method use reflection to get system evniorment variables map in runtime JVM + * which can be changed. + * + * @return system evniorment variables map. + */ + private static Map getENVMap() throws Exception + { + Map envMap = null; + Class[] classes = Collections.class.getDeclaredClasses(); + Map systemEnv = System.getenv(); + for (Class cl : classes) { + if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) { + Field field = cl.getDeclaredField("m"); + field.setAccessible(true); + Object object = field.get(systemEnv); + envMap = (Map) object; } } + if (envMap == null) { + throw new RuntimeException("Failed to get environment map."); + } + return envMap; } } From 47c7f44d2921539876b400d0849f126b0ed1f6a2 Mon Sep 17 00:00:00 2001 From: yuanyi Date: Mon, 12 Jul 2021 19:48:17 +0800 Subject: [PATCH 13/14] fix comment --- .../EnvironmentVariableDynamicConfigProviderTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java index 756786b7ba9e..268bc24ba713 100644 --- a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java +++ b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java @@ -83,10 +83,10 @@ private static void recoverENV() throws Exception } /** - * This method use reflection to get system evniorment variables map in runtime JVM + * This method use reflection to get system environment variables map in runtime JVM * which can be changed. * - * @return system evniorment variables map. + * @return system environment variables map. */ private static Map getENVMap() throws Exception { From 86be09909c870f0f74cda0a2935b516bbf052a53 Mon Sep 17 00:00:00 2001 From: yuanyi Date: Mon, 12 Jul 2021 20:22:32 +0800 Subject: [PATCH 14/14] fix test --- ...mentVariableDynamicConfigProviderTest.java | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java index 268bc24ba713..94f408d530e3 100644 --- a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java +++ b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java @@ -21,31 +21,44 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableMap; -import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import java.io.IOException; import java.lang.reflect.Field; import java.util.Collections; +import java.util.HashMap; import java.util.Map; public class EnvironmentVariableDynamicConfigProviderTest { private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); - private static final Map NEW_ENV_MAP = ImmutableMap.of("DRUID_USER", "druid", "DRUID_PASSWORD", "123"); + private static final Map CHANGED_ENV_MAP = new HashMap<>(); - @Before - public void setupTest() throws Exception + @BeforeClass + public static void setupTest() throws Exception { - changeENV(); + Map oldEnvMap = getENVMap(); + Map addEnvMap = ImmutableMap.of("DRUID_USER", "druid", "DRUID_PASSWORD", "123"); + for (Map.Entry entry : addEnvMap.entrySet()) { + CHANGED_ENV_MAP.put(entry.getKey(), oldEnvMap.get(entry.getKey())); + oldEnvMap.put(entry.getKey(), entry.getValue()); + } } - @After - public void tearDownTest() throws Exception + @AfterClass + public static void tearDownTest() throws Exception { - recoverENV(); + Map oldEnvMap = getENVMap(); + for (Map.Entry entry : CHANGED_ENV_MAP.entrySet()) { + if (entry.getValue() == null) { + oldEnvMap.remove(entry.getKey()); + } else { + oldEnvMap.put(entry.getKey(), entry.getValue()); + } + } } @Test @@ -69,19 +82,6 @@ public void testGetConfig() throws Exception Assert.assertEquals("123", ((EnvironmentVariableDynamicConfigProvider) provider).getConfig().get("password")); } - private static void changeENV() throws Exception - { - getENVMap().putAll(NEW_ENV_MAP); - } - - private static void recoverENV() throws Exception - { - Map envMap = getENVMap(); - for (String envName : NEW_ENV_MAP.keySet()) { - envMap.remove(envName); - } - } - /** * This method use reflection to get system environment variables map in runtime JVM * which can be changed.