mirror of https://github.com/halo-dev/halo
refactor: the value structure of ConfigMap for Setting custom extension (#2243)
<!-- Thanks for sending a pull request! Here are some tips for you: 1. 如果这是你的第一次,请阅读我们的贡献指南:<https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>。 1. If this is your first time, please read our contributor guidelines: <https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>. 2. 请根据你解决问题的类型为 Pull Request 添加合适的标签。 2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. 3. 请确保你已经添加并运行了适当的测试。 3. Ensure you have added or ran the appropriate tests for your PR. --> #### What type of PR is this? /kind improvement /area core /milestone 2.0 <!-- 添加其中一个类别: Add one of the following kinds: /kind bug /kind cleanup /kind documentation /kind feature /kind improvement 适当添加其中一个或多个类别(可选): Optionally add one or more of the following kinds if applicable: /kind api-change /kind deprecation /kind failing-test /kind flake /kind regression --> #### What this PR does / why we need it: 由于 Setting 自定义模型关联表单值的存储结构改变,对应修改 SettingFetcher 的取值方式 https://github.com/halo-dev/rfcs/pull/18 #### Which issue(s) this PR fixes: <!-- PR 合并时自动关闭 issue。 Automatically closes linked issue when PR is merged. 用法:`Fixes #<issue 号>`,或者 `Fixes (粘贴 issue 完整链接)` Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. --> Fixes # #### Special notes for your reviewer: /cc @halo-dev/sig-halo #### Does this PR introduce a user-facing change? <!-- 如果当前 Pull Request 的修改不会造成用户侧的任何变更,在 `release-note` 代码块儿中填写 `NONE`。 否则请填写用户侧能够理解的 Release Note。如果当前 Pull Request 包含破坏性更新(Break Change), Release Note 需要以 `action required` 开头。 If no, just write "NONE" in the release-note block below. If yes, a release note is required: Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required". --> ```release-note None ```pull/2247/head
parent
55040d6918
commit
a8db2e5e4b
|
@ -135,7 +135,7 @@ public class UserEndpoint implements CustomEndpoint {
|
||||||
.parameter(parameterBuilder().in(ParameterIn.PATH).name("name")
|
.parameter(parameterBuilder().in(ParameterIn.PATH).name("name")
|
||||||
.description("User name")
|
.description("User name")
|
||||||
.required(true))
|
.required(true))
|
||||||
.response(responseBuilder().implementation(Set.class)))
|
.response(responseBuilder().implementation(UserPermission.class)))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,11 @@ package run.halo.app.plugin;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
@ -25,9 +28,7 @@ import run.halo.app.infra.utils.JsonUtils;
|
||||||
*/
|
*/
|
||||||
public class SettingFetcher {
|
public class SettingFetcher {
|
||||||
|
|
||||||
private static final String PLUGIN_SETTING_VALUE = "setting";
|
private final AtomicReference<Map<String, JsonNode>> valueRef = new AtomicReference<>(null);
|
||||||
|
|
||||||
private final AtomicReference<JsonNode> valueRef = new AtomicReference<>(null);
|
|
||||||
|
|
||||||
private final ExtensionClient extensionClient;
|
private final ExtensionClient extensionClient;
|
||||||
|
|
||||||
|
@ -49,9 +50,16 @@ public class SettingFetcher {
|
||||||
return getInternal(group);
|
return getInternal(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get values from {@link ConfigMap}.
|
||||||
|
*
|
||||||
|
* @return a unmodifiable map of values(non-null).
|
||||||
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public JsonNode getValues() {
|
public Map<String, JsonNode> getValues() {
|
||||||
return valueRef.updateAndGet(m -> m != null ? m : getValuesInternal());
|
Map<String, JsonNode> values =
|
||||||
|
valueRef.updateAndGet(m -> m != null ? m : getValuesInternal());
|
||||||
|
return Map.copyOf(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonNode getInternal(String group) {
|
private JsonNode getInternal(String group) {
|
||||||
|
@ -59,13 +67,14 @@ public class SettingFetcher {
|
||||||
.orElse(JsonNodeFactory.instance.missingNode());
|
.orElse(JsonNodeFactory.instance.missingNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonNode getValuesInternal() {
|
private Map<String, JsonNode> getValuesInternal() {
|
||||||
return configMap(pluginName)
|
return configMap(pluginName)
|
||||||
.filter(configMap -> configMap.getData() != null
|
.filter(configMap -> configMap.getData() != null)
|
||||||
&& configMap.getData().containsKey(PLUGIN_SETTING_VALUE))
|
.map(ConfigMap::getData)
|
||||||
.map(configMap -> configMap.getData().get(PLUGIN_SETTING_VALUE))
|
.map(Map::entrySet)
|
||||||
.map(this::readTree)
|
.stream()
|
||||||
.orElse(JsonNodeFactory.instance.missingNode());
|
.flatMap(Collection::stream)
|
||||||
|
.collect(Collectors.toMap(Map.Entry::getKey, entry -> readTree(entry.getValue())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<ConfigMap> configMap(String pluginName) {
|
private Optional<ConfigMap> configMap(String pluginName) {
|
||||||
|
@ -80,6 +89,9 @@ public class SettingFetcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonNode readTree(String json) {
|
private JsonNode readTree(String json) {
|
||||||
|
if (StringUtils.isBlank(json)) {
|
||||||
|
return JsonNodeFactory.instance.missingNode();
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return JsonUtils.DEFAULT_JSON_MAPPER.readTree(json);
|
return JsonUtils.DEFAULT_JSON_MAPPER.readTree(json);
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
|
|
|
@ -54,7 +54,7 @@ class SettingFetcherTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getValues() throws JSONException {
|
void getValues() throws JSONException {
|
||||||
JsonNode values = settingFetcher.getValues();
|
Map<String, JsonNode> values = settingFetcher.getValues();
|
||||||
|
|
||||||
verify(extensionClient, times(1)).fetch(eq(ConfigMap.class), any());
|
verify(extensionClient, times(1)).fetch(eq(ConfigMap.class), any());
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ class SettingFetcherTest {
|
||||||
JSONAssert.assertEquals(getSns(), JsonUtils.objectToJson(values.get("sns")), true);
|
JSONAssert.assertEquals(getSns(), JsonUtils.objectToJson(values.get("sns")), true);
|
||||||
|
|
||||||
// The extensionClient will only be called once
|
// The extensionClient will only be called once
|
||||||
JsonNode callAgain = settingFetcher.getValues();
|
Map<String, JsonNode> callAgain = settingFetcher.getValues();
|
||||||
assertThat(callAgain).isNotNull();
|
assertThat(callAgain).isNotNull();
|
||||||
verify(extensionClient, times(1)).fetch(eq(ConfigMap.class), any());
|
verify(extensionClient, times(1)).fetch(eq(ConfigMap.class), any());
|
||||||
}
|
}
|
||||||
|
@ -98,15 +98,14 @@ class SettingFetcherTest {
|
||||||
configMap.setMetadata(metadata);
|
configMap.setMetadata(metadata);
|
||||||
configMap.setKind("ConfigMap");
|
configMap.setKind("ConfigMap");
|
||||||
configMap.setApiVersion("v1alpha1");
|
configMap.setApiVersion("v1alpha1");
|
||||||
configMap.setData(Map.of("setting", String.format("""
|
configMap.setData(Map.of("sns", getSns(),
|
||||||
{
|
"basic", """
|
||||||
"sns": %s,
|
{
|
||||||
"basic": {
|
|
||||||
"color": "red",
|
"color": "red",
|
||||||
"width": "100"
|
"width": "100"
|
||||||
}
|
}
|
||||||
}
|
""")
|
||||||
""", getSns())));
|
);
|
||||||
return configMap;
|
return configMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue