Refine error handling in MountInfo lookup.
We now do not cache failures caused by VaultException but rather return an unavailable MountInfo. Also, VaultKeyValueAdapter now throws an exception if the mount info isn't available. Closes gh-889
This commit is contained in:
@@ -23,6 +23,7 @@ import java.util.function.Supplier;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.core.VaultKeyValueOperationsSupport.KeyValueBackend;
|
||||
import org.springframework.vault.core.VaultOperations;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
@@ -127,6 +128,9 @@ public class KeyValueDelegate {
|
||||
|
||||
mountInfo = doGetMountInfo(path);
|
||||
}
|
||||
catch (VaultException e) {
|
||||
return MountInfo.unavailable();
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
mountInfo = MountInfo.unavailable();
|
||||
}
|
||||
|
||||
@@ -255,6 +255,10 @@ public class VaultKeyValueAdapter extends AbstractKeyValueAdapter {
|
||||
|
||||
KeyValueDelegate.MountInfo mountInfo = keyValueDelegate.getMountInfo(keyspace);
|
||||
|
||||
if (!mountInfo.isAvailable()) {
|
||||
throw new VaultException("Cannot determine MountInfo");
|
||||
}
|
||||
|
||||
return accessors.computeIfAbsent(keyspace, it -> {
|
||||
|
||||
if (keyValueDelegate.isVersioned(it)) {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2025 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.vault.repository.core;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.core.VaultIntegrationTestConfiguration;
|
||||
import org.springframework.vault.core.VaultTemplate;
|
||||
import org.springframework.vault.core.util.KeyValueDelegate;
|
||||
import org.springframework.vault.domain.Person;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultKeyValueAdapter}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
class VaultKeyValueAdapterIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Autowired
|
||||
VaultTemplate template;
|
||||
|
||||
@Test
|
||||
void shouldFailOnAbsentKeyspace() {
|
||||
|
||||
VaultKeyValueAdapter adapter = new VaultKeyValueAdapter(template);
|
||||
|
||||
assertThatExceptionOfType(VaultException.class).isThrownBy(() -> adapter.get("some-id", "absent", Person.class))
|
||||
.withMessageContaining("Cannot determine MountInfo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnVersionedMountInfo() {
|
||||
|
||||
KeyValueDelegate delegate = new KeyValueDelegate(template);
|
||||
|
||||
KeyValueDelegate.MountInfo mountInfo = delegate.getMountInfo("versioned/nothing/here");
|
||||
|
||||
assertThat(mountInfo.isAvailable()).isTrue();
|
||||
assertThat(mountInfo.getOptions()).containsEntry("version", "2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnUnversionedMountInfo() {
|
||||
|
||||
KeyValueDelegate delegate = new KeyValueDelegate(template);
|
||||
|
||||
KeyValueDelegate.MountInfo mountInfo = delegate.getMountInfo("secret/nothing/here");
|
||||
|
||||
assertThat(mountInfo.isAvailable()).isTrue();
|
||||
assertThat(mountInfo.getOptions()).doesNotContainEntry("version", "2");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,8 @@ As of version 2.4, Spring Vault can use additionally key/value version 2 secrets
|
||||
|
||||
NOTE: Deletes within versioned key/value secrets engine use the `DELETE` operation. Secrets are not destroyed through `CrudRepository.delete(…)`.
|
||||
|
||||
NOTE: Vault Repositories determine the mount path through Vault's `sys/internal/ui/mounts/…` endpoint. Make sure that your policy allows accessing that path, otherwise you won't be able to use the repository abstraction.
|
||||
|
||||
NOTE: Read more about Spring Data Repositories in the https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories[Spring Data Commons reference documentation].
|
||||
The reference documentation will give you an introduction to Spring Data repositories.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user