[Feature][Engine]Metalake support for data source information storage and management#9688
Conversation
…nel-env.cmd files; modify EnvCommonOptions class to include metalake configuration option
…metalake_enable=true
…ntroduce factory for type-based MetalakeClient creation; Fetch Metalake data by sourceId and replace Config placeholders
|
cc @liugddx |
|
Please add test cases and add documentation. |
| <groupId>org.apache.httpcomponents</groupId> | ||
| <artifactId>httpclient</artifactId> | ||
| <version>4.5.13</version> |
There was a problem hiding this comment.
we need to send http request to get metainfo from gravitino, so a http tool is necessary
| } | ||
|
|
||
| sink { | ||
| Console { |
There was a problem hiding this comment.
Please use the Assert connector.
There was a problem hiding this comment.
I used the Assert connector instead of console
| boolean metalakeEnabled = | ||
| Boolean.parseBoolean(System.getenv().getOrDefault("METALAKE_ENABLED", "false")); | ||
| if (metalakeEnabled) { | ||
| this.seaTunnelJobConfig = | ||
| getMetalakeConfig(ConfigBuilder.of(Paths.get(jobDefineFilePath), variables)); | ||
| } else { | ||
| this.seaTunnelJobConfig = ConfigBuilder.of(Paths.get(jobDefineFilePath), variables); | ||
| } |
There was a problem hiding this comment.
We need to ensure that Flink/Spark/Zeta all support this feature simultaneously.
Therefore, it needs to be adapted in both the FlinkTaskExecuteCommandand SparkTaskExecuteCommand classes.
There was a problem hiding this comment.
I added this feature in spark and flink engine and the test has passed
| </dependency> | ||
| <dependency> | ||
| <groupId>org.testcontainers</groupId> | ||
| <artifactId>mysql</artifactId> |
There was a problem hiding this comment.
E2e test case need to support flink/spark/zeta, so they should be placed in the seatunnel-connector-v2-e2e.
There was a problem hiding this comment.
I moved the metalakeIT to seatunnel-connector-v2-e2e
…or instead of console in the conf file for test
| if (entity == null) { | ||
| throw new RuntimeException("No response entity"); | ||
| } | ||
| ObjectMapper mapper = new ObjectMapper(); |
There was a problem hiding this comment.
I added a readTree method in JsonUtils and reuse it here
| String metalakeType = System.getenv("METALAKE_TYPE"); | ||
| String metalakeUrl = System.getenv("METALAKE_URL"); |
There was a problem hiding this comment.
Maybe user can overwrite it on job config env part is better. cc @liugddx
There was a problem hiding this comment.
Maybe user can overwrite it on job config
envpart is better. cc @liugddx
Yes, user can retrieve variables from the environment (env), and if they are not present in the environment, they can obtain them from the System. Config envConfig = config.getConfig("env");
| if (value.valueType() == ConfigValueType.STRING) { | ||
| String strValue = (String) value.unwrapped(); | ||
| Matcher matcher = pattern.matcher(strValue); | ||
| if (matcher.find()) { | ||
| String placeholder = matcher.group(1); |
There was a problem hiding this comment.
how about move this part into PlaceholderUtils with new method?
There was a problem hiding this comment.
I have moved this into PlaceholderUtils
| if (sinkObj.containsKey("sourceId")) { | ||
| ConfigObject tmp = sinkObj; | ||
| String sourceId = sinkObj.toConfig().getString("sourceId"); | ||
| JsonNode metalakeJson = metalakeClient.getMetaInfo(sourceId); | ||
| for (Map.Entry<String, ConfigValue> entry : sinkObj.entrySet()) { | ||
| String subKey = entry.getKey(); | ||
| ConfigValue value = entry.getValue(); | ||
|
|
||
| if (value.valueType() == ConfigValueType.STRING) { | ||
| String strValue = (String) value.unwrapped(); | ||
| Matcher matcher = pattern.matcher(strValue); | ||
| if (matcher.find()) { | ||
| String placeholder = matcher.group(1); | ||
|
|
||
| if (metalakeJson.has(placeholder)) { | ||
| String replaced = metalakeJson.get(placeholder).asText(); |
There was a problem hiding this comment.
parse source and sink has same code. Let's refactor it again!
There was a problem hiding this comment.
I have refactored these same code
| httpcore-4.4.13.jar | ||
| httpcore-4.4.16.jar | ||
| httpcore-4.4.4.jar |
There was a problem hiding this comment.
It's weired we introduce new two version of httpcore. Can you analyze the dependencies and use only httpcore-4.4.16.jar?
There was a problem hiding this comment.
It is actually wired. I just introduce httpclient-4.5.13 which is already in the other part of the project, but the Dependency License test remind me to add other two version of httpcore
There was a problem hiding this comment.
We should find the core reason before merge it. cc @liugddx
There was a problem hiding this comment.
Can we unify the version?
Sure.
There was a problem hiding this comment.
I have unified the version of httpcore to 4.4.16 and removed the extra version in known-dependency.txt
| @Slf4j | ||
| public class MetalakeConfigUtils { | ||
|
|
||
| public static Config getMetalakeConfig(Config jobConfigTmp) { |
There was a problem hiding this comment.
We should support transform too. For example, OpenAI key in LLM/Embedding etc.
There was a problem hiding this comment.
I have supported transform here.
| Config envConfig = | ||
| ConfigBuilder.of(Paths.get(jobDefineFilePath), variables).getConfig("env"); | ||
| boolean metalakeEnabled = | ||
| envConfig.hasPath("metalake_enabled") | ||
| ? envConfig.getBoolean("metalake_enabled") | ||
| : Boolean.parseBoolean( | ||
| System.getenv().getOrDefault("METALAKE_ENABLED", "false")); | ||
| if (metalakeEnabled) { | ||
| this.seaTunnelJobConfig = | ||
| MetalakeConfigUtils.getMetalakeConfig( | ||
| ConfigBuilder.of(Paths.get(jobDefineFilePath), variables)); | ||
| } else { | ||
| this.seaTunnelJobConfig = ConfigBuilder.of(Paths.get(jobDefineFilePath), variables); | ||
| } |
There was a problem hiding this comment.
I have refactored this part
| return result.toString(); | ||
| } | ||
|
|
||
| public static String replacePlaceholders(String input, JsonNode json) { |
There was a problem hiding this comment.
| public static String replacePlaceholders(String input, JsonNode json) { | |
| public static String replacePlaceholders(String input, JsonNode supportedValues) { |
| Config update = jobConfigTmp; | ||
| try { | ||
| ConfigList sourceList = jobConfigTmp.getList("source"); | ||
| update = | ||
| update.withValue( | ||
| "source", | ||
| ConfigValueFactory.fromIterable( | ||
| replaceConfigList(sourceList, envConfig))); | ||
| } catch (IOException e) { | ||
| log.error("Fail to get MetaInfo", e); | ||
| } | ||
|
|
||
| try { | ||
| ConfigList sinkList = jobConfigTmp.getList("sink"); | ||
| update = | ||
| update.withValue( | ||
| "sink", | ||
| ConfigValueFactory.fromIterable( | ||
| replaceConfigList(sinkList, envConfig))); | ||
| } catch (IOException e) { | ||
| log.error("Fail to get MetaInfo", e); | ||
| } | ||
|
|
||
| try { | ||
| ConfigList sinkList = jobConfigTmp.getList("transform"); | ||
| update = | ||
| update.withValue( | ||
| "transform", | ||
| ConfigValueFactory.fromIterable( | ||
| replaceConfigList(sinkList, envConfig))); | ||
| } catch (IOException e) { | ||
| log.error("Fail to get MetaInfo", e); | ||
| } |
There was a problem hiding this comment.
I found this part can be refactor too.
…etMetalakeConfig method
| Config envConfig = updateConfig.getConfig("env"); | ||
| String metalakeType = | ||
| envConfig.hasPath("metalake_type") | ||
| ? envConfig.getString("metalake_type") | ||
| : System.getenv("METALAKE_TYPE"); | ||
| String metalakeUrl = | ||
| envConfig.hasPath("metalake_url") | ||
| ? envConfig.getString("metalake_url") | ||
| : System.getenv("METALAKE_URL"); | ||
| MetalakeClient metalakeClient = MetalakeClientFactory.create(metalakeType, metalakeUrl); |
There was a problem hiding this comment.
we should move this part outer replaceConfigList. The metalakeClient should only created once.
Hisoka-X
left a comment
There was a problem hiding this comment.
Thanks @wtybxqm ! Finally, let's update https://github.com/apache/seatunnel/blob/dev/docs/sidebars.js#L88
|
waiting test case passes. |

Purpose of this pull request
To address the problem: sensitive information such as data source usernames and passwords is directly written into task scripts
close #9687
Does this PR introduce any user-facing change?
yes
To enable Metalake, users need to configure three critical settings in seatunnel.sh: first set 'metalake_enable=true', then specify their 'metalake_url' and 'metalake_type'. Once activated, users can simply add a 'sourceId' field in their task script's source/sink configurations and replace sensitive credentials with secure placeholders like '${password}'.
How was this patch tested?
Integration testing has passed.
Check list
New License Guide