This is an automated email from the ASF dual-hosted git repository.
wenjin272 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/flink-agents.git
The following commit(s) were added to refs/heads/main by this push:
new 10ba7294e [runtime][java] Fall back to legacy flink-conf.yaml when
loading agent configuration (#1337)
10ba7294e is described below
commit 10ba7294e07b307c5e75db8354ff64db2b1bb593
Author: Samuele Langhi <[email protected]>
AuthorDate: Wed Nov 4 03:17:50 2026 +0100
[runtime][java] Fall back to legacy flink-conf.yaml when loading agent
configuration (#1337)
Generated-by: Claude Code 2.1.312 (Claude Opus 5.5)
---
docs/content/docs/operations/configuration.md | 21 ++-
.../agents/runtime/env/LegacyFlinkConfParser.java | 85 ++++++++++++
.../runtime/env/RemoteExecutionEnvironment.java | 84 ++++++++++-
.../runtime/env/LegacyFlinkConfParserTest.java | 90 ++++++++++++
.../env/RemoteExecutionEnvironmentTest.java | 153 +++++++++++++++++++++
5 files changed, 427 insertions(+), 6 deletions(-)
diff --git a/docs/content/docs/operations/configuration.md
b/docs/content/docs/operations/configuration.md
index a5efff5b9..5118a95b3 100644
--- a/docs/content/docs/operations/configuration.md
+++ b/docs/content/docs/operations/configuration.md
@@ -94,6 +94,19 @@ agent:
async: true
```
+In Java, settings can also be written as flattened keys prefixed with `agent.`:
+
+```yaml
+agent.max-retries: 3
+agent.chat.async: true
+```
+
+This is the only form the legacy `flink-conf.yaml` supports. Java reads that
file with Flink's
+legacy rules rather than as YAML, as Flink 1.20 does: one `key: value` pair
per line, split on
+the first `": "`, with `#` starting a comment, invalid lines skipped and a
repeated key overriding
+earlier ones. Values are read as strings and converted when an option is read,
so list-typed
+options such as `event-listeners` cannot be set in `flink-conf.yaml`.
+
#### Loading Behavior
When creating an `AgentsExecutionEnvironment` for a Flink job, Flink Agents
loads
@@ -104,7 +117,13 @@ Set this environment variable before creating the
environment:
export FLINK_CONF_DIR="/path/to/flink/conf"
```
-`FLINK_CONF_DIR` points to a directory. Java reads `config.yaml` from that
directory.
+`FLINK_CONF_DIR` points to a directory. Java selects the file the way Flink
itself does:
+
+| Flink version | Files read |
+| --- | --- |
+| 1.20 | `flink-conf.yaml` if it exists (legacy rules), otherwise
`config.yaml` (standard YAML) |
+| 2.0 and later | `config.yaml` only (standard YAML) |
+
Python reads `flink-conf.yaml` if it exists, otherwise `config.yaml`.
If `FLINK_CONF_DIR` is unset, no YAML configuration file is loaded.
Configuration
diff --git
a/runtime/src/main/java/org/apache/flink/agents/runtime/env/LegacyFlinkConfParser.java
b/runtime/src/main/java/org/apache/flink/agents/runtime/env/LegacyFlinkConfParser.java
new file mode 100644
index 000000000..29db22741
--- /dev/null
+++
b/runtime/src/main/java/org/apache/flink/agents/runtime/env/LegacyFlinkConfParser.java
@@ -0,0 +1,85 @@
+/*
+ * 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.flink.agents.runtime.env;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Parser for the legacy Flink configuration file {@code flink-conf.yaml}.
+ *
+ * <p>Mirrors {@code GlobalConfiguration#loadLegacyYAMLResource} of Flink
1.20, which reads the file
+ * line by line rather than as YAML: everything after the first {@code #} is a
comment, key and
+ * value are split on the first {@code ": "}, lines without a valid pair are
skipped with a warning,
+ * values are kept as strings, and a duplicate key overrides the earlier one.
+ */
+final class LegacyFlinkConfParser {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(LegacyFlinkConfParser.class);
+
+ private LegacyFlinkConfParser() {}
+
+ static Map<String, String> parse(File file) throws IOException {
+ final Map<String, String> config = new LinkedHashMap<>();
+
+ try (BufferedReader reader = Files.newBufferedReader(file.toPath())) {
+ String line;
+ int lineNo = 0;
+ while ((line = reader.readLine()) != null) {
+ lineNo++;
+ String conf = line.split("#", 2)[0].trim();
+ if (conf.isEmpty()) {
+ continue;
+ }
+
+ String[] kv = conf.split(": ", 2);
+ if (kv.length == 1) {
+ LOG.warn(
+ "Error while trying to split key and value in
configuration file {}:{}: "
+ + "Line is not a key-value pair (missing
space after ':'?)",
+ file,
+ lineNo);
+ continue;
+ }
+
+ String key = kv[0].trim();
+ String value = kv[1].trim();
+ if (key.isEmpty() || value.isEmpty()) {
+ LOG.warn(
+ "Error after splitting key and value in
configuration file {}:{}: "
+ + "Key or value was empty",
+ file,
+ lineNo);
+ continue;
+ }
+
+ config.put(key, value);
+ }
+ }
+
+ return config;
+ }
+}
diff --git
a/runtime/src/main/java/org/apache/flink/agents/runtime/env/RemoteExecutionEnvironment.java
b/runtime/src/main/java/org/apache/flink/agents/runtime/env/RemoteExecutionEnvironment.java
index e2218f665..ecea46faf 100644
---
a/runtime/src/main/java/org/apache/flink/agents/runtime/env/RemoteExecutionEnvironment.java
+++
b/runtime/src/main/java/org/apache/flink/agents/runtime/env/RemoteExecutionEnvironment.java
@@ -26,12 +26,14 @@ import org.apache.flink.agents.plan.AgentConfiguration;
import org.apache.flink.agents.plan.AgentPlan;
import org.apache.flink.agents.runtime.CompileUtils;
import org.apache.flink.agents.runtime.OutputTypeUtils;
+import org.apache.flink.annotation.VisibleForTesting;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.typeutils.RowTypeInfo;
import org.apache.flink.configuration.ConfigConstants;
import org.apache.flink.configuration.YamlParserUtils;
+import org.apache.flink.runtime.util.EnvironmentInformation;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
@@ -39,6 +41,8 @@ import org.apache.flink.table.api.Schema;
import org.apache.flink.table.api.Table;
import org.apache.flink.table.api.bridge.java.StreamTableEnvironment;
import org.apache.flink.types.Row;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
@@ -60,8 +64,14 @@ public class RemoteExecutionEnvironment extends
AgentsExecutionEnvironment {
private final AgentConfiguration config;
+ private static final Logger LOG =
LoggerFactory.getLogger(RemoteExecutionEnvironment.class);
+
public static final String FLINK_CONF_FILENAME = "config.yaml";
+ public static final String LEGACY_FLINK_CONF_FILENAME = "flink-conf.yaml";
+
+ private static final String AGENT_CONFIG_PREFIX = "agent";
+
public RemoteExecutionEnvironment(
StreamExecutionEnvironment env, @Nullable StreamTableEnvironment
tEnv) {
this.env = env;
@@ -113,16 +123,50 @@ public class RemoteExecutionEnvironment extends
AgentsExecutionEnvironment {
env.execute(jobName);
}
- @SuppressWarnings("unchecked")
public static AgentConfiguration loadAgentConfiguration(String configDir) {
+ return loadAgentConfiguration(configDir,
EnvironmentInformation.getVersion());
+ }
+
+ /**
+ * Selects and parses the configuration file the way Flink's {@code
GlobalConfiguration} does:
+ * on Flink 1.x the legacy {@code flink-conf.yaml} wins and is parsed with
the legacy line-based
+ * rules, otherwise {@code config.yaml} is parsed as standard YAML; Flink
2.x reads only {@code
+ * config.yaml}.
+ */
+ @VisibleForTesting
+ @SuppressWarnings("unchecked")
+ static AgentConfiguration loadAgentConfiguration(
+ String configDir, @Nullable String flinkVersion) {
try {
if (configDir == null) {
return new AgentConfiguration();
}
- final Map<String, Object> configData =
- (Map<String, Object>)
- YamlParserUtils.loadYamlFile(new File(configDir,
FLINK_CONF_FILENAME))
- .getOrDefault("agent", new HashMap<>());
+
+ File legacyConfigFile = new File(configDir,
LEGACY_FLINK_CONF_FILENAME);
+ if (isFlink2OrLater(flinkVersion)) {
+ if (legacyConfigFile.exists()) {
+ LOG.warn(
+ "Ignoring {}: Flink {} reads only {}",
+ legacyConfigFile,
+ flinkVersion,
+ FLINK_CONF_FILENAME);
+ }
+ } else if (legacyConfigFile.exists()) {
+ LOG.info(
+ "Using legacy YAML parser to load Flink Agents
configuration from {}",
+ legacyConfigFile);
+ return new AgentConfiguration(
+
flatAgentOptions(LegacyFlinkConfParser.parse(legacyConfigFile)));
+ }
+
+ final Map<String, Object> yaml =
+ YamlParserUtils.loadYamlFile(new File(configDir,
FLINK_CONF_FILENAME));
+ final Map<String, Object> configData = new HashMap<>();
+ Object nested = yaml.get(AGENT_CONFIG_PREFIX);
+ if (nested instanceof Map) {
+ configData.putAll((Map<String, Object>) nested);
+ }
+ configData.putAll(flatAgentOptions(yaml));
return new AgentConfiguration(configData);
} catch (Exception e) {
@@ -131,6 +175,36 @@ public class RemoteExecutionEnvironment extends
AgentsExecutionEnvironment {
}
}
+ /** Collects top-level {@code agent.<key>} entries under {@code <key>}. */
+ private static Map<String, Object> flatAgentOptions(Map<String, ?> config)
{
+ String flatPrefix = AGENT_CONFIG_PREFIX + ".";
+ Map<String, Object> options = new HashMap<>();
+ config.forEach(
+ (key, value) -> {
+ if (key.startsWith(flatPrefix)) {
+ options.put(key.substring(flatPrefix.length()), value);
+ }
+ });
+ return options;
+ }
+
+ /**
+ * Whether {@code version} names Flink 2.0 or later. Vendor suffixes after
the first {@code -}
+ * are ignored; an unknown or unparseable version counts as 1.x, which
tries both files.
+ */
+ @VisibleForTesting
+ static boolean isFlink2OrLater(@Nullable String version) {
+ if (version == null) {
+ return false;
+ }
+ String major = version.split("-", 2)[0].split("\\.", 2)[0];
+ try {
+ return Integer.parseInt(major.trim()) >= 2;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+
/** Implementation of AgentBuilder for remote execution environment. */
private static class RemoteAgentBuilder<T, K> implements AgentBuilder {
diff --git
a/runtime/src/test/java/org/apache/flink/agents/runtime/env/LegacyFlinkConfParserTest.java
b/runtime/src/test/java/org/apache/flink/agents/runtime/env/LegacyFlinkConfParserTest.java
new file mode 100644
index 000000000..19791f3c7
--- /dev/null
+++
b/runtime/src/test/java/org/apache/flink/agents/runtime/env/LegacyFlinkConfParserTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.flink.agents.runtime.env;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.entry;
+
+class LegacyFlinkConfParserTest {
+ @TempDir private File tmpDir;
+
+ @Test
+ void testDuplicateKeyOverridesEarlierValue() throws IOException {
+ assertThat(parse("key: first", "key:
second")).containsOnly(entry("key", "second"));
+ }
+
+ @Test
+ void testValueContainingColonSpaceIsKeptWhole() throws IOException {
+ assertThat(parse("key: a: b: c")).containsOnly(entry("key", "a: b:
c"));
+ }
+
+ @Test
+ void testCommentsAreDropped() throws IOException {
+ assertThat(parse("# full-line comment", "key: value # trailing
comment", "other: a#b"))
+ .containsOnly(entry("key", "value"), entry("other", "a"));
+ }
+
+ @Test
+ void testLinesWithoutKeyValuePairAreSkipped() throws IOException {
+ assertThat(parse("key:value", "nested:", "key-only", "valid: yes"))
+ .containsOnly(entry("valid", "yes"));
+ }
+
+ @Test
+ void testEmptyKeyOrValueIsSkipped() throws IOException {
+ assertThat(parse(": value", "key: ", "key2: # only a comment",
"valid: yes"))
+ .containsOnly(entry("valid", "yes"));
+ }
+
+ @Test
+ void testKeysAndValuesAreTrimmedAndKeptAsStrings() throws IOException {
+ assertThat(parse(" key : 1 ", "flag: true", "quoted: 'v'",
"list: [a, b]"))
+ .containsOnly(
+ entry("key", "1"),
+ entry("flag", "true"),
+ entry("quoted", "'v'"),
+ entry("list", "[a, b]"));
+ }
+
+ @Test
+ void testIndentedLinesAreReadAsTopLevelKeys() throws IOException {
+ assertThat(parse("agent:", " key1: v1")).containsOnly(entry("key1",
"v1"));
+ }
+
+ @Test
+ void testMissingFileFails() {
+ assertThatThrownBy(() -> LegacyFlinkConfParser.parse(new File(tmpDir,
"missing.yaml")))
+ .isInstanceOf(IOException.class);
+ }
+
+ private Map<String, String> parse(String... lines) throws IOException {
+ File file = new File(tmpDir, "flink-conf.yaml");
+ Files.write(file.toPath(), Arrays.asList(lines));
+ return LegacyFlinkConfParser.parse(file);
+ }
+}
diff --git
a/runtime/src/test/java/org/apache/flink/agents/runtime/env/RemoteExecutionEnvironmentTest.java
b/runtime/src/test/java/org/apache/flink/agents/runtime/env/RemoteExecutionEnvironmentTest.java
index d49e291f8..ec44221f9 100644
---
a/runtime/src/test/java/org/apache/flink/agents/runtime/env/RemoteExecutionEnvironmentTest.java
+++
b/runtime/src/test/java/org/apache/flink/agents/runtime/env/RemoteExecutionEnvironmentTest.java
@@ -24,6 +24,7 @@ import org.apache.flink.agents.api.InputEvent;
import org.apache.flink.agents.api.OutputEvent;
import org.apache.flink.agents.api.agents.Agent;
import org.apache.flink.agents.api.annotation.Action;
+import org.apache.flink.agents.api.configuration.AgentConfigOptions;
import org.apache.flink.agents.api.context.MemoryObject;
import org.apache.flink.agents.api.context.RunnerContext;
import org.apache.flink.agents.plan.AgentConfiguration;
@@ -41,20 +42,28 @@ import org.junit.jupiter.api.io.TempDir;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.PrintWriter;
+import java.nio.file.Files;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import static
org.apache.flink.agents.runtime.env.RemoteExecutionEnvironment.FLINK_CONF_FILENAME;
+import static
org.apache.flink.agents.runtime.env.RemoteExecutionEnvironment.LEGACY_FLINK_CONF_FILENAME;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.entry;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class RemoteExecutionEnvironmentTest {
+ private static final String FLINK_1_20 = "1.20.3";
+ private static final String FLINK_2_3 = "2.3.0";
+
@TempDir private File tmpDir;
@Test
@@ -84,6 +93,150 @@ public class RemoteExecutionEnvironmentTest {
assert conf.getConfData().get("key7").equals(true);
}
+ @Test
+ void testIsFlink2OrLater() {
+
assertThat(RemoteExecutionEnvironment.isFlink2OrLater("1.20.3")).isFalse();
+
assertThat(RemoteExecutionEnvironment.isFlink2OrLater("1.20-vvr-11.5.0")).isFalse();
+
assertThat(RemoteExecutionEnvironment.isFlink2OrLater("2.3.0")).isTrue();
+
assertThat(RemoteExecutionEnvironment.isFlink2OrLater("2.0-SNAPSHOT")).isTrue();
+
assertThat(RemoteExecutionEnvironment.isFlink2OrLater("<unknown>")).isFalse();
+ assertThat(RemoteExecutionEnvironment.isFlink2OrLater("")).isFalse();
+ assertThat(RemoteExecutionEnvironment.isFlink2OrLater(null)).isFalse();
+ }
+
+ @Test
+ void testFlink1LoadsLegacyFileWhenOnlyLegacyFileExists() throws
IOException {
+ writeLegacyConf("agent.key1: fromLegacy");
+
+ assertThat(load(FLINK_1_20).getConfData()).containsOnly(entry("key1",
"fromLegacy"));
+ }
+
+ @Test
+ void testFlink1LoadsConfigYamlWhenOnlyConfigYamlExists() throws
IOException {
+ writeConfigYaml("agent:", " key1: fromConfigYaml");
+
+ assertThat(load(FLINK_1_20).getConfData()).containsOnly(entry("key1",
"fromConfigYaml"));
+ }
+
+ @Test
+ void testFlink1PrefersLegacyFileOverConfigYaml() throws IOException {
+ writeConfigYaml("agent:", " key1: fromConfigYaml");
+ writeLegacyConf("agent.key1: fromLegacy");
+
+ assertThat(load(FLINK_1_20).getConfData()).containsOnly(entry("key1",
"fromLegacy"));
+ }
+
+ @Test
+ void testFlink1FailsWhenNoConfigFileExists() {
+ assertThatThrownBy(() ->
load(FLINK_1_20)).isInstanceOf(RuntimeException.class);
+ }
+
+ @Test
+ void testFlink2IgnoresLegacyFile() throws IOException {
+ writeLegacyConf("agent.key1: fromLegacy");
+
+ assertThatThrownBy(() -> load(FLINK_2_3))
+ .isInstanceOf(RuntimeException.class)
+ .hasMessageContaining(tmpDir.getAbsolutePath());
+ }
+
+ @Test
+ void testFlink2LoadsConfigYamlWhenOnlyConfigYamlExists() throws
IOException {
+ writeConfigYaml("agent:", " key1: fromConfigYaml");
+
+ assertThat(load(FLINK_2_3).getConfData()).containsOnly(entry("key1",
"fromConfigYaml"));
+ }
+
+ @Test
+ void testFlink2LoadsConfigYamlWhenBothFilesExist() throws IOException {
+ writeConfigYaml("agent:", " key1: fromConfigYaml");
+ writeLegacyConf("agent.key1: fromLegacy");
+
+ assertThat(load(FLINK_2_3).getConfData()).containsOnly(entry("key1",
"fromConfigYaml"));
+ }
+
+ @Test
+ void testFlink2FailsWhenNoConfigFileExists() {
+ assertThatThrownBy(() ->
load(FLINK_2_3)).isInstanceOf(RuntimeException.class);
+ }
+
+ @Test
+ void testLegacyFileAcceptsDuplicateKeysAndValuesContainingColonSpace()
throws IOException {
+ // Both lines are rejected by a standard YAML parser but accepted by
Flink 1.20.
+ writeLegacyConf(
+ "env.java.opts.all: -Dfoo=bar",
+ "env.java.opts.all: -Dfoo=baz",
+ "kubernetes.jobmanager.annotations: owner: team-a",
+ "agent.key1: first",
+ "agent.key1: second",
+ "agent.key2: a: b");
+
+ assertThat(load(FLINK_1_20).getConfData())
+ .containsOnly(entry("key1", "second"), entry("key2", "a: b"));
+ }
+
+ @Test
+ void testLegacyFileWithoutAgentOptions() throws IOException {
+ writeLegacyConf(
+ "# Flink configuration as shipped by a distribution",
+ "jobmanager.rpc.address: localhost",
+ "taskmanager.memory.process.size: 1728m",
+ "env.java.opts.all: -XX:+UseG1GC -Dfoo=bar");
+
+ assertThat(load(FLINK_1_20).getConfData()).isEmpty();
+ }
+
+ @Test
+ void testLegacyFileIgnoresNestedAgentBlock() throws IOException {
+ writeLegacyConf("agent:", " key1: nested", "agent.key2: flat");
+
+ assertThat(load(FLINK_1_20).getConfData()).containsOnly(entry("key2",
"flat"));
+ }
+
+ @Test
+ void testLegacyFileValuesAreStringsAndConvertOnRead() throws IOException {
+ writeLegacyConf(
+ "agent.trace-log.base-dir: /tmp/agent-traces",
+ "agent.trace-log.pretty-print: true");
+
+ AgentConfiguration conf = load(FLINK_1_20);
+
+ assertThat(conf.getConfData()).containsEntry("trace-log.pretty-print",
"true");
+ assertThat(conf.get(AgentConfigOptions.TRACE_LOG_OUTPUT_BASE_DIR))
+ .isEqualTo("/tmp/agent-traces");
+
assertThat(conf.get(AgentConfigOptions.TRACE_LOG_OUTPUT_PRETTY_PRINT)).isTrue();
+ }
+
+ @Test
+ void testConfigYamlAcceptsNestedAndFlattenedKeys() throws IOException {
+ writeConfigYaml("agent:", " key1: v1", "agent.key2: v2");
+
+ assertThat(load(FLINK_2_3).getConfData())
+ .containsOnly(entry("key1", "v1"), entry("key2", "v2"));
+ }
+
+ @Test
+ void testFailIfConfigYamlUnparseable() throws IOException {
+ writeConfigYaml("agent.key1: [unclosed");
+
+ assertThatThrownBy(() -> load(FLINK_2_3))
+ .isInstanceOf(RuntimeException.class)
+ .hasMessageContaining(tmpDir.getAbsolutePath());
+ }
+
+ private AgentConfiguration load(String flinkVersion) {
+ return RemoteExecutionEnvironment.loadAgentConfiguration(
+ tmpDir.getAbsolutePath(), flinkVersion);
+ }
+
+ private void writeLegacyConf(String... lines) throws IOException {
+ Files.write(new File(tmpDir, LEGACY_FLINK_CONF_FILENAME).toPath(),
Arrays.asList(lines));
+ }
+
+ private void writeConfigYaml(String... lines) throws IOException {
+ Files.write(new File(tmpDir, FLINK_CONF_FILENAME).toPath(),
Arrays.asList(lines));
+ }
+
@Test
void testLoadAgentConfigurationFailIfNotLoaded() {
assertThatThrownBy(