Skip to content

Commit bf26667

Browse files
authored
hashivault: add configurable retry interval (#201)
1 parent 2141d9a commit bf26667

File tree

15 files changed

+586
-981
lines changed

15 files changed

+586
-981
lines changed

tasks/hashivault/pom.xml

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@
1414
<packaging>jar</packaging>
1515

1616
<properties>
17-
<okhttp.version>3.11.0</okhttp.version>
18-
<nginx.image.version>nginx:1.21.5-alpine</nginx.image.version>
19-
<vault.image.version>vault:1.1.3</vault.image.version>
17+
<nginx.image.version>nginx:1.27-alpine</nginx.image.version>
18+
<vault.image.version>hashicorp/vault:1.19</vault.image.version>
2019
</properties>
2120

2221
<dependencies>
@@ -71,6 +70,17 @@
7170
<artifactId>junit-jupiter</artifactId>
7271
<scope>test</scope>
7372
</dependency>
73+
<dependency>
74+
<groupId>org.mockito</groupId>
75+
<artifactId>mockito-core</artifactId>
76+
<scope>test</scope>
77+
</dependency>
78+
<dependency>
79+
<groupId>org.mockito</groupId>
80+
<artifactId>mockito-junit-jupiter</artifactId>
81+
<version>4.9.0</version>
82+
<scope>test</scope>
83+
</dependency>
7484
<dependency>
7585
<groupId>org.testcontainers</groupId>
7686
<artifactId>vault</artifactId>

tasks/hashivault/src/main/java/com/walmartlabs/concord/plugins/hashivault/HashiVaultTaskCommon.java

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import org.slf4j.LoggerFactory;
3030

3131
import java.nio.charset.Charset;
32-
import java.util.Map;
3332

3433
public class HashiVaultTaskCommon {
3534
Logger log = LoggerFactory.getLogger(HashiVaultTaskCommon.class);
@@ -75,27 +74,16 @@ private static VaultConfig buildConfig(TaskParams params) {
7574
public HashiVaultTaskResult execute(TaskParams params) {
7675
final VaultConfig config = buildConfig(params);
7776
final Vault vault = new Vault(config);
78-
HashiVaultTaskResult result;
79-
80-
switch (params.action()) {
81-
case READKV:
82-
Map<String, String> data = readValue(vault, params);
83-
result = HashiVaultTaskResult.of(true, data, null, params);
84-
break;
85-
case WRITEKV:
86-
writeValue(vault, params);
87-
result = HashiVaultTaskResult.of(true, null, null, params);
88-
break;
89-
default:
90-
throw new HashiVaultTaskException("Unsupported action: " + params.action());
91-
}
9277

93-
return result;
78+
return switch (params.action()) {
79+
case READKV -> readValue(vault, params);
80+
case WRITEKV -> writeValue(vault, params);
81+
};
9482
}
9583

96-
private Map<String, String> readValue(Vault vault, TaskParams params) {
84+
private HashiVaultTaskResult readValue(Vault vault, TaskParams params) {
9785
try {
98-
final LogicalResponse r = vault.withRetries(3, 5000).logical()
86+
final LogicalResponse r = vault.withRetries(params.retryCount(), params.retryIntervalMs()).logical()
9987
.withNameSpace(params.ns())
10088
.read(params.path());
10189
final int status = r.getRestResponse().getStatus();
@@ -106,8 +94,7 @@ private Map<String, String> readValue(Vault vault, TaskParams params) {
10694
throw new VaultException(body, status);
10795
}
10896

109-
return r.getData();
110-
97+
return HashiVaultTaskResult.of(true, r.getData(), null, params);
11198
} catch (VaultException e) {
11299
String msg = String.format("Error reading from vault (%s): %s",
113100
e.getHttpStatusCode(), e.getMessage());
@@ -118,14 +105,14 @@ private Map<String, String> readValue(Vault vault, TaskParams params) {
118105
}
119106
}
120107

121-
private void writeValue(Vault vault, TaskParams params) {
108+
private HashiVaultTaskResult writeValue(Vault vault, TaskParams params) {
122109
if (dryRunMode) {
123110
log.info("Dry-run mode enabled: Skipping write to vault");
124-
return;
111+
return HashiVaultTaskResult.of(true, null, null, params);
125112
}
126113

127114
try {
128-
final LogicalResponse r = vault.withRetries(3, 5000).logical()
115+
final LogicalResponse r = vault.withRetries(params.retryCount(), params.retryIntervalMs()).logical()
129116
.withNameSpace(params.ns())
130117
.write(params.path(), params.kvPairs());
131118
final int status = r.getRestResponse().getStatus();
@@ -144,5 +131,7 @@ private void writeValue(Vault vault, TaskParams params) {
144131
log.error(msg);
145132
throw new HashiVaultTaskException(msg);
146133
}
134+
135+
return HashiVaultTaskResult.of(true, null, null, params);
147136
}
148137
}

tasks/hashivault/src/main/java/com/walmartlabs/concord/plugins/hashivault/TaskParams.java

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public class TaskParams {
3333
private static final String DEFAULT_NAMESPACE = null;
3434
private static final int DEFAULT_ENGINE_VERSION = 2;
3535
private static final boolean DEFAULT_VERIFY_SSL = true;
36+
private static final long DEFAULT_RETRY_COUNT = 3;
37+
private static final long DEFAULT_RETRY_INTERVAL_MS = 5_000;
3638

3739
public static final String DEFAULT_PARAMS_KEY = "hashivaultParams";
3840
public static final String TX_ID_KEY = "txId";
@@ -50,6 +52,8 @@ public class TaskParams {
5052
public static final String PATH_KEY = "path";
5153
public static final String KEY_KEY = "key";
5254
public static final String KV_PAIRS_KEY = "kvPairs";
55+
public static final String RETRY_COUNT_KEY = "retryCount";
56+
public static final String RETRY_INTERVAL_MS_KEY = "retryIntervalMs";
5357

5458
protected final Variables variables;
5559

@@ -69,28 +73,21 @@ public static TaskParams of(Variables input, Map<String, Object> defaults, Secre
6973
Variables variables = new MapBackedVariables(variablesMap);
7074
TaskParams p = new TaskParams(variables);
7175

72-
switch (p.action()) {
73-
case READKV:
74-
case WRITEKV:
75-
return new TaskParams(variables);
76-
default:
77-
throw new IllegalArgumentException("Unsupported action type: " + p.action());
78-
}
76+
return switch (p.action()) {
77+
case READKV, WRITEKV -> new TaskParams(variables);
78+
};
7979
}
8080

8181
private static String exportToken(SecretExporter secretExporter, Map<String, Object> secret) {
8282
String o = MapUtils.assertString(secret, ORG_KEY);
8383
String n = MapUtils.assertString(secret, NAME_KEY);
8484
String p = MapUtils.getString(secret, PASSWORD_KEY);
8585

86-
String token;
87-
8886
try {
89-
token = secretExporter.exportAsString(o, n, p);
87+
return secretExporter.exportAsString(o, n, p);
9088
} catch (Exception e) {
9189
throw new HashiVaultTaskException("Error retrieving API token from Concord secret: " + e.getMessage());
9290
}
93-
return token;
9491
}
9592

9693
public Action action() {
@@ -122,6 +119,14 @@ public boolean verifySsl() {
122119
return variables.getBoolean(VERIFY_SSL_KEY, DEFAULT_VERIFY_SSL);
123120
}
124121

122+
public int retryCount() {
123+
return variables.getNumber(RETRY_COUNT_KEY, DEFAULT_RETRY_COUNT).intValue();
124+
}
125+
126+
public int retryIntervalMs() {
127+
return variables.getNumber(RETRY_INTERVAL_MS_KEY, DEFAULT_RETRY_INTERVAL_MS).intValue();
128+
}
129+
125130
public int engineVersion() {
126131
if (path().matches("^/?cubbyhole.*")) {
127132
return 1;

tasks/hashivault/src/main/java/com/walmartlabs/concord/plugins/hashivault/v1/HashiVaultTask.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,8 @@ public String exportAsString(String o, String n, String p) throws Exception {
111111
return secretService.exportAsString(ctx, txId, o, n, p);
112112
}
113113
}
114+
115+
protected void setDefaults(Map<String, Object> d) {
116+
defaults = d;
117+
}
114118
}

tasks/hashivault/src/main/java/com/walmartlabs/concord/plugins/hashivault/v2/HashiVaultTask.java

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,8 @@
2828
import javax.inject.Inject;
2929
import javax.inject.Named;
3030
import java.util.Collections;
31-
import java.util.HashMap;
3231
import java.util.Map;
3332

34-
3533
@Named("hashivault")
3634
@DryRunReady
3735
public class HashiVaultTask implements Task {
@@ -52,47 +50,45 @@ public TaskResult.SimpleResult execute(Variables input) {
5250
final TaskParams params = createParams(input);
5351
final HashiVaultTaskCommon delegate = new HashiVaultTaskCommon(dryRunMode);
5452
final HashiVaultTaskResult result = delegate.execute(params);
55-
final Map<String, Object> data = new HashMap<>(1);
56-
data.put("data", result.data());
53+
final Object data = result.data() == null ? Map.of() : result.data();
5754

58-
return TaskResult.of(result.ok(), result.error(), data);
55+
return result.ok()
56+
? TaskResult.success().values(Map.of("data", data))
57+
: TaskResult.fail(result.error());
5958
}
6059

6160
private TaskParams createParams(Variables input) {
62-
final SecretExporterV2 exporterV2 = new SecretExporterV2(secretService);
61+
final var exporterV2 = new SecretExporterV2(secretService);
6362
return TaskParams.of(input, defaults, exporterV2);
6463
}
6564

6665
public Map<String, Object> readKV(String path) {
67-
Map<String, Object> vars = new HashMap<>();
68-
vars.put(TaskParams.ACTION_KEY, TaskParams.Action.READKV.toString());
69-
vars.put(TaskParams.PATH_KEY, path);
70-
71-
final Variables input = new MapBackedVariables(vars);
66+
final Variables input = new MapBackedVariables(Map.of(
67+
TaskParams.ACTION_KEY, TaskParams.Action.READKV.toString(),
68+
TaskParams.PATH_KEY, path
69+
));
7270
final TaskParams params = createParams(input);
7371
final HashiVaultTaskResult result = new HashiVaultTaskCommon().execute(params);
7472
return result.data();
7573
}
7674

7775
public String readKV(String path, String field) {
78-
Map<String, Object> vars = new HashMap<>();
79-
vars.put(TaskParams.ACTION_KEY, TaskParams.Action.READKV.toString());
80-
vars.put(TaskParams.PATH_KEY, path);
81-
vars.put(TaskParams.KEY_KEY, field);
82-
83-
final Variables input = new MapBackedVariables(vars);
76+
final Variables input = new MapBackedVariables(Map.of(
77+
TaskParams.ACTION_KEY, TaskParams.Action.READKV.toString(),
78+
TaskParams.PATH_KEY, path,
79+
TaskParams.KEY_KEY, field
80+
));
8481
final TaskParams params = createParams(input);
8582
final HashiVaultTaskResult result = new HashiVaultTaskCommon().execute(params);
8683
return result.data();
8784
}
8885

8986
public void writeKV(String path, Map<String, Object> kvPairs) {
90-
Map<String, Object> vars = new HashMap<>();
91-
vars.put(TaskParams.ACTION_KEY, TaskParams.Action.WRITEKV.toString());
92-
vars.put(TaskParams.PATH_KEY, path);
93-
vars.put(TaskParams.KV_PAIRS_KEY, kvPairs);
94-
95-
final Variables input = new MapBackedVariables(vars);
87+
final Variables input = new MapBackedVariables(Map.of(
88+
TaskParams.ACTION_KEY, TaskParams.Action.WRITEKV.toString(),
89+
TaskParams.PATH_KEY, path,
90+
TaskParams.KV_PAIRS_KEY, kvPairs
91+
));
9692
final TaskParams params = createParams(input);
9793
final HashiVaultTaskCommon delegate = new HashiVaultTaskCommon();
9894
delegate.execute(params);

tasks/hashivault/src/test/java/com/walmartlabs/concord/plugins/hashivault/AbstractVaultTest.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public abstract class AbstractVaultTest {
4848
.withNetworkAliases("vault")
4949
.withSecretInVault("secret/testing", "top_secret=password1","db_password=dbpassword1")
5050
.withSecretInVault("cubbyhole/hello", "cubbyKey=cubbyVal")
51+
// we could explicitly wait for the http endpoint to be available here,
52+
// but the nginx check will implicitly handle that
5153
.waitingFor(Wait.forLogMessage(".*Vault server started.*", 1));
5254
@Container
5355
public static NginxContainer<?> nginxContainer =
@@ -61,7 +63,10 @@ public abstract class AbstractVaultTest {
6163
.withCopyFileToContainer(mountRes("nginx.conf"), "/etc/nginx/templates/default.conf.template")
6264
.withCopyFileToContainer(mountRes("server.crt"), "/etc/nginx/certs/server.crt")
6365
.withCopyFileToContainer(mountRes("server.key"), "/etc/nginx/certs/server.key")
64-
.waitingFor(Wait.forLogMessage(".*ready for start up.*", 1));
66+
.waitingFor(Wait.forHttps("/v1/sys/health")
67+
.forPort(NGINX_SSL_PORT)
68+
.forStatusCode(200)
69+
.allowInsecure());
6570

6671
protected static String getVaultBaseUrl() {
6772
return String.format("http://%s:%s",

0 commit comments

Comments
 (0)