diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/HealthBuilderDelegate.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/HealthBuilderDelegate.java new file mode 100644 index 00000000..394425ae --- /dev/null +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/HealthBuilderDelegate.java @@ -0,0 +1,62 @@ +/* + * Copyright 2018-2019 the original author or authors. + * + * Licensed 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 + * + * https://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.springframework.cloud.vault.config; + +import org.springframework.boot.actuate.health.Health; +import org.springframework.util.StringUtils; +import org.springframework.vault.support.VaultHealth; + +/** + * Common delegate to transport health properties into the Health actuator + * {@link Health.Builder}. + * + * @author Mark Paluch + * @since 2.2 + */ +final class HealthBuilderDelegate { + + private HealthBuilderDelegate() { + } + + static void contributeToHealth(VaultHealth healthResponse, Health.Builder builder) { + + if (!healthResponse.isInitialized()) { + builder.down().withDetail("state", "Vault uninitialized"); + } + else if (healthResponse.isSealed()) { + builder.down().withDetail("state", "Vault sealed"); + } + else if (healthResponse.isStandby()) { + builder.up().withDetail("state", "Vault in standby"); + } + else if (healthResponse.isPerformanceStandby()) { + builder.up().withDetail("state", "Vault in performance standby"); + } + else if (healthResponse.isRecoveryReplicationSecondary()) { + builder.up().withDetail("state", + "Vault in recovery replication secondary mode"); + } + else { + builder.up(); + } + + if (StringUtils.hasText(healthResponse.getVersion())) { + builder.withDetail("version", healthResponse.getVersion()); + } + } + +} diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultHealthIndicator.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultHealthIndicator.java index 35c1b315..fa3b39a8 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultHealthIndicator.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultHealthIndicator.java @@ -18,7 +18,6 @@ package org.springframework.cloud.vault.config; import org.springframework.boot.actuate.health.AbstractHealthIndicator; import org.springframework.boot.actuate.health.Health.Builder; -import org.springframework.util.StringUtils; import org.springframework.vault.core.VaultOperations; import org.springframework.vault.support.VaultHealth; @@ -40,23 +39,7 @@ public class VaultHealthIndicator extends AbstractHealthIndicator { protected void doHealthCheck(Builder builder) { VaultHealth vaultHealthResponse = this.vaultOperations.opsForSys().health(); - - if (!vaultHealthResponse.isInitialized()) { - builder.down().withDetail("state", "Vault uninitialized"); - } - else if (vaultHealthResponse.isSealed()) { - builder.down().withDetail("state", "Vault sealed"); - } - else if (vaultHealthResponse.isStandby()) { - builder.up().withDetail("state", "Vault in standby"); - } - else { - builder.up(); - } - - if (StringUtils.hasText(vaultHealthResponse.getVersion())) { - builder.withDetail("version", vaultHealthResponse.getVersion()); - } + HealthBuilderDelegate.contributeToHealth(vaultHealthResponse, builder); } } diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultReactiveHealthIndicator.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultReactiveHealthIndicator.java index bf820d3d..a54ea045 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultReactiveHealthIndicator.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultReactiveHealthIndicator.java @@ -28,7 +28,6 @@ import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.Health.Builder; import org.springframework.lang.Nullable; -import org.springframework.util.StringUtils; import org.springframework.vault.core.ReactiveVaultOperations; import org.springframework.vault.support.VaultHealth; import org.springframework.web.reactive.function.client.WebClientResponseException; @@ -65,22 +64,7 @@ public class VaultReactiveHealthIndicator extends AbstractReactiveHealthIndicato private static Health getHealth(Builder builder, VaultHealthImpl vaultHealthResponse) { - if (!vaultHealthResponse.isInitialized()) { - builder.withDetail("state", "Vault uninitialized"); - } - else if (vaultHealthResponse.isSealed()) { - builder.down().withDetail("state", "Vault sealed"); - } - else if (vaultHealthResponse.isStandby()) { - builder.up().withDetail("state", "Vault in standby"); - } - else { - builder.up(); - } - - if (StringUtils.hasText(vaultHealthResponse.getVersion())) { - builder.withDetail("version", vaultHealthResponse.getVersion()); - } + HealthBuilderDelegate.contributeToHealth(vaultHealthResponse, builder); return builder.build(); } @@ -96,7 +80,7 @@ public class VaultReactiveHealthIndicator extends AbstractReactiveHealthIndicato } @JsonIgnoreProperties(ignoreUnknown = true) - private static final class VaultHealthImpl implements VaultHealth { + static class VaultHealthImpl implements VaultHealth { private final boolean initialized; @@ -104,20 +88,29 @@ public class VaultReactiveHealthIndicator extends AbstractReactiveHealthIndicato private final boolean standby; + private final boolean performanceStandby; + + private final boolean replicationRecoverySecondary; + private final int serverTimeUtc; @Nullable private final String version; - private VaultHealthImpl(@JsonProperty("initialized") boolean initialized, + VaultHealthImpl(@JsonProperty("initialized") boolean initialized, @JsonProperty("sealed") boolean sealed, @JsonProperty("standby") boolean standby, + @JsonProperty("performance_standby") boolean performanceStandby, + @Nullable @JsonProperty("replication_dr_mode") String replicationRecoverySecondary, @JsonProperty("server_time_utc") int serverTimeUtc, @Nullable @JsonProperty("version") String version) { this.initialized = initialized; this.sealed = sealed; this.standby = standby; + this.performanceStandby = performanceStandby; + this.replicationRecoverySecondary = replicationRecoverySecondary != null + && !"disabled".equalsIgnoreCase(replicationRecoverySecondary); this.serverTimeUtc = serverTimeUtc; this.version = version; } @@ -134,6 +127,14 @@ public class VaultReactiveHealthIndicator extends AbstractReactiveHealthIndicato return this.standby; } + public boolean isPerformanceStandby() { + return this.performanceStandby; + } + + public boolean isRecoveryReplicationSecondary() { + return this.replicationRecoverySecondary; + } + public int getServerTimeUtc() { return this.serverTimeUtc; } @@ -154,6 +155,8 @@ public class VaultReactiveHealthIndicator extends AbstractReactiveHealthIndicato VaultHealthImpl that = (VaultHealthImpl) o; return this.initialized == that.initialized && this.sealed == that.sealed && this.standby == that.standby + && this.performanceStandby == that.performanceStandby + && this.replicationRecoverySecondary == that.replicationRecoverySecondary && this.serverTimeUtc == that.serverTimeUtc && Objects.equals(this.version, that.version); } @@ -161,22 +164,10 @@ public class VaultReactiveHealthIndicator extends AbstractReactiveHealthIndicato @Override public int hashCode() { return Objects.hash(this.initialized, this.sealed, this.standby, + this.performanceStandby, this.replicationRecoverySecondary, this.serverTimeUtc, this.version); } - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append(getClass().getSimpleName()); - sb.append(" [initialized=").append(this.initialized); - sb.append(", sealed=").append(this.sealed); - sb.append(", standby=").append(this.standby); - sb.append(", serverTimeUtc=").append(this.serverTimeUtc); - sb.append(", version='").append(this.version).append('\''); - sb.append(']'); - return sb.toString(); - } - } } diff --git a/spring-cloud-vault-config/src/test/java/org/springframework/cloud/vault/config/VaultHealthIndicatorUnitTests.java b/spring-cloud-vault-config/src/test/java/org/springframework/cloud/vault/config/VaultHealthIndicatorUnitTests.java index 1ab83256..c1a01b9f 100644 --- a/spring-cloud-vault-config/src/test/java/org/springframework/cloud/vault/config/VaultHealthIndicatorUnitTests.java +++ b/spring-cloud-vault-config/src/test/java/org/springframework/cloud/vault/config/VaultHealthIndicatorUnitTests.java @@ -115,4 +115,30 @@ public class VaultHealthIndicatorUnitTests { assertThat(health.getDetails()).containsKey("error"); } + @Test + public void shouldReportPerformanceStandby() { + + when(this.healthResponse.isInitialized()).thenReturn(true); + when(this.healthResponse.isPerformanceStandby()).thenReturn(true); + + Health health = this.healthIndicator.health(); + + assertThat(health.getStatus()).isEqualTo(Status.UP); + assertThat(health.getDetails()).containsEntry("state", + "Vault in performance standby"); + } + + @Test + public void shouldReportRecoveryReplication() { + + when(this.healthResponse.isInitialized()).thenReturn(true); + when(this.healthResponse.isRecoveryReplicationSecondary()).thenReturn(true); + + Health health = this.healthIndicator.health(); + + assertThat(health.getStatus()).isEqualTo(Status.UP); + assertThat(health.getDetails()).containsEntry("state", + "Vault in recovery replication secondary mode"); + } + }