fix: theme status phase is always FAILED even if version of Halo is satisfied (#3390)

#### What type of PR is this?
/kind improvement
/area core
/milestone 2.3.x

#### What this PR does / why we need it:
修复主题 requires 版本匹配后依然显示 FAILED 状态的问题

how to test it?
1. 安装一个主题后更新主题的 requires 为不匹配系统版本号,此时主题 status 会提示版本号不匹配的错误
2. 再更新 requires 为正确的,phase 会从 FAILED 变为 READY

#### Which issue(s) this PR fixes:
Fixes #3326
#### Does this PR introduce a user-facing change?
```release-note
修复主题状态显示不正确的问题
```
pull/3425/head
guqing 2023-02-28 22:10:18 +08:00 committed by GitHub
parent 166a440df1
commit 3146589d25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 16 deletions

View File

@ -6,8 +6,10 @@ import java.time.Instant;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Component;
@ -82,38 +84,40 @@ public class ThemeReconciler implements Reconciler<Request> {
.build();
}
private void reconcileStatus(String name) {
void reconcileStatus(String name) {
client.fetch(Theme.class, name).ifPresent(theme -> {
final Theme oldTheme = JsonUtils.deepCopy(theme);
if (theme.getStatus() == null) {
theme.setStatus(new Theme.ThemeStatus());
}
Theme.ThemeStatus status = theme.getStatus();
final Theme.ThemeStatus status =
ObjectUtils.defaultIfNull(theme.getStatus(), new Theme.ThemeStatus());
final Theme.ThemeStatus oldStatus = JsonUtils.deepCopy(status);
theme.setStatus(status);
Path themePath = themePathPolicy.generate(theme);
status.setLocation(themePath.toAbsolutePath().toString());
if (status.getPhase() == null) {
status.setPhase(Theme.ThemePhase.READY);
}
status.setPhase(Theme.ThemePhase.READY);
Condition.ConditionBuilder conditionBuilder = Condition.builder()
.type(Theme.ThemePhase.READY.name())
.status(ConditionStatus.TRUE)
.reason(Theme.ThemePhase.READY.name())
.message(StringUtils.EMPTY)
.lastTransitionTime(Instant.now());
// Check if this theme version is match requires param.
String normalVersion = systemVersionSupplier.get().getNormalVersion();
String requires = theme.getSpec().getRequires();
if (!VersionUtils.satisfiesRequires(normalVersion, requires)) {
status.setPhase(Theme.ThemePhase.FAILED);
Condition condition = Condition.builder()
conditionBuilder
.type(Theme.ThemePhase.FAILED.name())
.status(ConditionStatus.FALSE)
.reason("UnsatisfiedRequiresVersion")
.message(String.format(
"Theme requires a minimum system version of [%s], and you have [%s].",
requires, normalVersion))
.lastTransitionTime(Instant.now())
.build();
Theme.nullSafeConditionList(theme).add(condition);
requires, normalVersion));
}
Theme.nullSafeConditionList(theme).addAndEvictFIFO(conditionBuilder.build());
if (!oldTheme.equals(theme)) {
if (!Objects.equals(oldStatus, status)) {
client.update(theme);
}
});

View File

@ -195,6 +195,38 @@ class ThemeReconcilerTest {
verify(extensionClient, times(2)).fetch(eq(Setting.class), eq(settingName));
}
@Test
void reconcileStatus() {
when(systemVersionSupplier.get()).thenReturn(Version.valueOf("2.3.0"));
Path testWorkDir = tempDirectory.resolve("reconcile-delete");
when(haloProperties.getWorkDir()).thenReturn(testWorkDir);
final ThemeReconciler themeReconciler =
new ThemeReconciler(extensionClient, haloProperties, systemVersionSupplier);
Theme theme = fakeTheme();
theme.setStatus(null);
theme.getSpec().setRequires(">2.3.0");
when(extensionClient.fetch(eq(Theme.class), eq("fake-theme")))
.thenReturn(Optional.of(theme));
themeReconciler.reconcileStatus("fake-theme");
ArgumentCaptor<Theme> themeUpdateCaptor = ArgumentCaptor.forClass(Theme.class);
verify(extensionClient).update(themeUpdateCaptor.capture());
Theme value = themeUpdateCaptor.getValue();
assertThat(value.getStatus()).isNotNull();
assertThat(value.getStatus().getConditions().peekFirst().getType())
.isEqualTo(Theme.ThemePhase.FAILED.name());
assertThat(value.getStatus().getPhase())
.isEqualTo(Theme.ThemePhase.FAILED);
theme.getSpec().setRequires(">=2.3.0");
when(extensionClient.fetch(eq(Theme.class), eq("fake-theme")))
.thenReturn(Optional.of(theme));
themeReconciler.reconcileStatus("fake-theme");
verify(extensionClient, times(2)).update(themeUpdateCaptor.capture());
assertThat(themeUpdateCaptor.getValue().getStatus().getPhase())
.isEqualTo(Theme.ThemePhase.READY);
}
private Theme fakeTheme() {
Theme theme = new Theme();
Metadata metadata = new Metadata();
@ -206,7 +238,7 @@ class ThemeReconcilerTest {
Theme.ThemeSpec themeSpec = new Theme.ThemeSpec();
themeSpec.setSettingName("theme-test-setting");
theme.setSpec(themeSpec);
when(extensionClient.fetch(eq(Theme.class), eq(metadata.getName())))
lenient().when(extensionClient.fetch(eq(Theme.class), eq(metadata.getName())))
.thenReturn(Optional.of(theme));
return theme;
}