Skip to content

Commit 7f84c09

Browse files
committed
fix: SGShardedCluster REST API endpoint was overlapping managed sql sections
1 parent 14f5c81 commit 7f84c09

2 files changed

Lines changed: 144 additions & 54 deletions

File tree

stackgres-k8s/src/api-web/src/main/java/io/stackgres/apiweb/rest/sgscripts/ScriptResource.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ public static String scriptEntryResourceName(String scriptName, int index) {
299299
return scriptName + "-" + index;
300300
}
301301

302+
public static String scriptEntryResourceName(String scriptName, String suffix, int index) {
303+
return scriptName + "-" + suffix + "-" + index;
304+
}
305+
302306
@Override
303307
protected void updateSpec(StackGresScript resourceToUpdate, StackGresScript resource) {
304308
resourceToUpdate.setSpec(resource.getSpec());

stackgres-k8s/src/api-web/src/main/java/io/stackgres/apiweb/rest/sgshardedcluster/ShardedClusterResource.java

Lines changed: 140 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,11 @@ ShardedClusterDto setInfo(ShardedClusterDto resource) {
233233

234234
ShardedClusterDto setScripts(ShardedClusterDto resource) {
235235
final String namespace = resource.getMetadata().getNamespace();
236-
getScriptEntries(resource)
236+
Seq
237+
.concat(
238+
getScriptEntriesForCoordinator(resource).stream(),
239+
getScriptEntriesForShards(resource).stream(),
240+
getScriptEntriesForShardsOverride(resource).stream().map(Tuple2::v2).flatMap(List::stream))
237241
.forEach(managedScriptEntry -> {
238242
var script = scriptFinder
239243
.findByNameAndNamespace(managedScriptEntry.getSgScript(), namespace);
@@ -246,18 +250,28 @@ ShardedClusterDto setScripts(ShardedClusterDto resource) {
246250
}
247251

248252
ShardedClusterDto setConfigMaps(ShardedClusterDto resource) {
249-
final String namespace = resource.getMetadata().getNamespace();
250-
Seq.of(Optional.ofNullable(resource.getSpec())
251-
.map(ShardedClusterSpec::getCoordinator)
252-
.map(ShardedClusterCoordinator::getManagedSql)
253-
.map(ClusterManagedSql::getScripts),
254-
Optional.ofNullable(resource.getSpec())
255-
.map(ShardedClusterSpec::getShards)
256-
.map(ShardedClusterShards::getManagedSql)
257-
.map(ClusterManagedSql::getScripts))
258-
.filter(Optional::isPresent)
259-
.map(Optional::get)
260-
.flatMap(List::stream)
253+
setConfigMaps(
254+
resource,
255+
"coord",
256+
getScriptEntriesForCoordinator(resource));
257+
setConfigMaps(
258+
resource,
259+
"shards",
260+
getScriptEntriesForShards(resource));
261+
getScriptEntriesForShardsOverride(resource)
262+
.forEach(override -> setConfigMaps(
263+
resource,
264+
"shard" + override.v1.intValue(),
265+
override.v2));
266+
return resource;
267+
}
268+
269+
void setConfigMaps(
270+
ShardedClusterDto resource,
271+
String suffix,
272+
List<ClusterManagedScriptEntry> scripts) {
273+
String namespace = resource.getMetadata().getNamespace();
274+
Seq.seq(scripts)
261275
.flatMap(managedScriptEntry -> Seq.seq(
262276
Optional.ofNullable(managedScriptEntry.getScriptSpec())
263277
.map(ScriptSpec::getScripts)
@@ -267,7 +281,7 @@ ShardedClusterDto setConfigMaps(ShardedClusterDto resource) {
267281
.map(Tuple.tuple(managedScriptEntry)::concat))
268282
.filter(t -> t.v2.getScriptFrom() != null
269283
&& t.v2.getScriptFrom().getConfigMapKeyRef() != null)
270-
.map(t -> extractConfigMapInfo(t.v1, t.v2, t.v3.intValue()))
284+
.map(t -> extractConfigMapInfo(t.v1, t.v2, suffix, t.v3.intValue()))
271285
.filter(t -> t.v2.v3 != null)
272286
.grouped(t -> t.v2.v3.getName())
273287
.flatMap(t -> {
@@ -280,11 +294,49 @@ ShardedClusterDto setConfigMaps(ShardedClusterDto resource) {
280294
.orElse(Seq.empty());
281295
})
282296
.forEach(t -> t.v2.accept(t.v1));
283-
return resource;
284297
}
285298

286-
private void createOrUpdateScripts(ShardedClusterDto resource) {
287-
var scriptsToCreate = getScriptsToCreate(resource)
299+
void createOrUpdateScripts(ShardedClusterDto resource) {
300+
createOrUpdateScripts(
301+
resource,
302+
"coordinator",
303+
"coord",
304+
"spec.coordinator",
305+
Optional.ofNullable(resource.getSpec())
306+
.map(ShardedClusterSpec::getCoordinator)
307+
.map(ShardedClusterCoordinator::getManagedSql)
308+
.map(ClusterManagedSql::getScripts)
309+
.stream()
310+
.flatMap(List::stream)
311+
.toList());
312+
createOrUpdateScripts(
313+
resource,
314+
"shards",
315+
"shards",
316+
"spec.shards",
317+
Optional.ofNullable(resource.getSpec())
318+
.map(ShardedClusterSpec::getShards)
319+
.map(ShardedClusterShards::getManagedSql)
320+
.map(ClusterManagedSql::getScripts)
321+
.stream()
322+
.flatMap(List::stream)
323+
.toList());
324+
getScriptEntriesForShardsOverride(resource)
325+
.forEach(override -> createOrUpdateScripts(
326+
resource,
327+
"shards override " + (override.v1.intValue() + 1),
328+
"shard" + override.v1.intValue(),
329+
"spec.shards.overrides[" + override.v1.intValue() + "]",
330+
override.v2));
331+
}
332+
333+
void createOrUpdateScripts(
334+
ShardedClusterDto resource,
335+
String section,
336+
String prefix,
337+
String path,
338+
List<ClusterManagedScriptEntry> scripts) {
339+
var scriptsToCreate = getScriptsToCreate(resource, prefix, scripts)
288340
.stream()
289341
.filter(t -> isNotDefaultScript(t.v2))
290342
.map(t -> t.concat(
@@ -296,15 +348,16 @@ private void createOrUpdateScripts(ShardedClusterDto resource) {
296348
.grouped(t -> t.v2.getMetadata().getName())
297349
.anyMatch(t -> t.v2.count() > 1)) {
298350
throw new IllegalArgumentException(
299-
"script entries can not reference the same script more than once. Repeated SGScripts are: "
351+
"script entries can not reference the same script more than once for " + section + "."
352+
+ " Repeated SGScripts are: "
300353
+ Seq.seq(scriptsToCreate)
301354
.grouped(t -> t.v2.getMetadata().getName())
302355
.map(t -> t.map2(Stream::toList))
303356
.filter(t -> t.v2.size() > 1)
304357
.map(Tuple2::v1)
305358
.toString(", "));
306359
}
307-
var secretsToCreate = Seq.seq(getSecretsToCreate(resource))
360+
var secretsToCreate = Seq.seq(getSecretsToCreate(resource, prefix, scripts))
308361
.grouped(secret -> secret.getMetadata().getName())
309362
.flatMap(t -> t.v2.reduce(
310363
Optional.<Secret>empty(),
@@ -321,7 +374,7 @@ private void createOrUpdateScripts(ShardedClusterDto resource) {
321374
secret.getMetadata().getName(),
322375
secret.getMetadata().getNamespace())))
323376
.toList();
324-
var configMapsToCreate = Seq.seq(getConfigMapsToCreate(resource))
377+
var configMapsToCreate = Seq.seq(getConfigMapsToCreate(resource, prefix, scripts))
325378
.grouped(configMap -> configMap.getMetadata().getName())
326379
.flatMap(t -> t.v2.reduce(
327380
Optional.<ConfigMap>empty(),
@@ -357,17 +410,20 @@ private void createOrUpdateScripts(ShardedClusterDto resource) {
357410
.forEach(secretWriter::update);
358411
scriptsToCreate.stream()
359412
.filter(t -> t.v3.isEmpty())
360-
.forEach(t -> addFieldPrefixOnScriptValidationError(t.v1, t.v2, scriptScheduler::create));
413+
.forEach(t -> addFieldPrefixOnScriptValidationError(path, t.v1, t.v2, scriptScheduler::create));
361414
scriptsToCreate.stream()
362415
.filter(t -> t.v3.isPresent())
363-
.forEach(t -> addFieldPrefixOnScriptValidationError(t.v1, t.v2, scriptScheduler::update));
416+
.forEach(t -> addFieldPrefixOnScriptValidationError(path, t.v1, t.v2, scriptScheduler::update));
364417
}
365418

366-
private boolean isNotDefaultScript(StackGresScript script) {
419+
boolean isNotDefaultScript(StackGresScript script) {
367420
return !script.getMetadata().getName().endsWith(ManagedSqlUtil.DEFAULT_SCRIPT_NAME_SUFFIX);
368421
}
369422

370-
private void addFieldPrefixOnScriptValidationError(Integer sgScriptIndex, StackGresScript script,
423+
void addFieldPrefixOnScriptValidationError(
424+
String path,
425+
Integer sgScriptIndex,
426+
StackGresScript script,
371427
Consumer<StackGresScript> consumer) {
372428
try {
373429
consumer.accept(script);
@@ -377,7 +433,7 @@ private void addFieldPrefixOnScriptValidationError(Integer sgScriptIndex, StackG
377433
&& ex.getStatus().getDetails() != null
378434
&& ex.getStatus().getDetails().getName() != null
379435
&& ex.getStatus().getDetails().getName().startsWith("spec.")) {
380-
final String fieldPrefix = "spec.managedSql.scripts[" + sgScriptIndex + "].scriptSpec.";
436+
final String fieldPrefix = path + ".managedSql.scripts[" + sgScriptIndex + "].scriptSpec.";
381437
ex.getStatus().getDetails().setName(
382438
fieldPrefix + ex.getStatus().getDetails().getName().substring("spec.".length()));
383439
Optional.ofNullable(ex.getStatus().getDetails().getCauses())
@@ -391,16 +447,19 @@ private void addFieldPrefixOnScriptValidationError(Integer sgScriptIndex, StackG
391447
}
392448
}
393449

394-
private List<Tuple2<Integer, StackGresScript>> getScriptsToCreate(ShardedClusterDto resource) {
395-
return getScriptEntries(resource)
450+
List<Tuple2<Integer, StackGresScript>> getScriptsToCreate(
451+
ShardedClusterDto resource,
452+
String prefix,
453+
List<ClusterManagedScriptEntry> scripts) {
454+
return Seq.seq(scripts)
396455
.zipWithIndex()
397456
.filter(t -> t.v1.getScriptSpec() != null)
398457
.map(t -> {
399458
StackGresScript script = new StackGresScript();
400459
script.setMetadata(new ObjectMeta());
401460
if (t.v1.getSgScript() == null) {
402461
t.v1.setSgScript(scriptResourceName(
403-
resource, t.v2.intValue()));
462+
resource, prefix, t.v2.intValue()));
404463
}
405464
script.getMetadata().setName(t.v1.getSgScript());
406465
script.getMetadata().setNamespace(resource.getMetadata().getNamespace());
@@ -417,8 +476,11 @@ private List<Tuple2<Integer, StackGresScript>> getScriptsToCreate(ShardedCluster
417476
.toList();
418477
}
419478

420-
private List<ConfigMap> getConfigMapsToCreate(ShardedClusterDto resource) {
421-
return getScriptEntries(resource)
479+
List<ConfigMap> getConfigMapsToCreate(
480+
ShardedClusterDto resource,
481+
String prefix,
482+
List<ClusterManagedScriptEntry> scripts) {
483+
return Seq.seq(scripts)
422484
.flatMap(managedScriptEntry -> Seq.seq(
423485
Optional.ofNullable(managedScriptEntry.getScriptSpec())
424486
.map(ScriptSpec::getScripts)
@@ -432,7 +494,7 @@ private List<ConfigMap> getConfigMapsToCreate(ShardedClusterDto resource) {
432494
ScriptFrom clusterScriptFrom = t.v2.getScriptFrom();
433495
final String configMapScript = clusterScriptFrom.getConfigMapScript();
434496
if (clusterScriptFrom.getConfigMapKeyRef() == null) {
435-
String configMapName = scriptEntryResourceName(t.v1, t.v3.intValue());
497+
String configMapName = scriptEntryResourceName(t.v1, prefix, t.v3.intValue());
436498
ConfigMapKeySelector configMapKeyRef = new ConfigMapKeySelector();
437499
configMapKeyRef.setName(configMapName);
438500
configMapKeyRef.setKey(DEFAULT_SCRIPT_KEY);
@@ -450,8 +512,11 @@ private List<ConfigMap> getConfigMapsToCreate(ShardedClusterDto resource) {
450512
.toList();
451513
}
452514

453-
private List<Secret> getSecretsToCreate(ShardedClusterDto resource) {
454-
return getScriptEntries(resource)
515+
List<Secret> getSecretsToCreate(
516+
ShardedClusterDto resource,
517+
String prefix,
518+
List<ClusterManagedScriptEntry> scripts) {
519+
return Seq.seq(scripts)
455520
.flatMap(managedScriptEntry -> Seq.seq(
456521
Optional.ofNullable(managedScriptEntry.getScriptSpec())
457522
.map(ScriptSpec::getScripts)
@@ -466,7 +531,7 @@ private List<Secret> getSecretsToCreate(ShardedClusterDto resource) {
466531
final String secretScript = ResourceUtil
467532
.encodeSecret(clusterScriptFrom.getSecretScript());
468533
if (clusterScriptFrom.getSecretKeyRef() == null) {
469-
String secretName = scriptEntryResourceName(t.v1, t.v3.intValue());
534+
String secretName = scriptEntryResourceName(t.v1, prefix, t.v3.intValue());
470535
SecretKeySelector secretKeyRef = new SecretKeySelector();
471536
secretKeyRef.setName(secretName);
472537
secretKeyRef.setKey(DEFAULT_SCRIPT_KEY);
@@ -489,10 +554,11 @@ private List<Secret> getSecretsToCreate(ShardedClusterDto resource) {
489554
extractConfigMapInfo(
490555
ClusterManagedScriptEntry managedScriptEntry,
491556
ScriptEntry scriptEntry,
557+
String suffix,
492558
int index) {
493559
return Tuple
494560
.<String, Tuple4<String, Consumer<String>, ConfigMapKeySelector, Consumer<ConfigMapKeySelector>>>tuple(
495-
scriptEntryResourceName(managedScriptEntry, index),
561+
scriptEntryResourceName(managedScriptEntry, suffix, index),
496562
Tuple
497563
.<String, Consumer<String>, ConfigMapKeySelector, Consumer<ConfigMapKeySelector>>tuple(
498564
scriptEntry.getScriptFrom().getConfigMapScript(),
@@ -501,35 +567,55 @@ private List<Secret> getSecretsToCreate(ShardedClusterDto resource) {
501567
scriptEntry.getScriptFrom()::setConfigMapKeyRef));
502568
}
503569

504-
private String scriptResourceName(ShardedClusterDto cluster,
570+
String scriptResourceName(
571+
ShardedClusterDto cluster,
572+
String suffix,
505573
int index) {
506-
return cluster.getMetadata().getName() + "-managed-sql-" + index;
574+
return cluster.getMetadata().getName() + "-managed-sql-" + suffix + "-" + index;
507575
}
508576

509-
private String scriptEntryResourceName(ClusterManagedScriptEntry managedScriptEntry, int index) {
510-
return ScriptResource.scriptEntryResourceName(managedScriptEntry.getSgScript(), index);
577+
String scriptEntryResourceName(ClusterManagedScriptEntry managedScriptEntry, String suffix, int index) {
578+
return ScriptResource.scriptEntryResourceName(managedScriptEntry.getSgScript(), suffix, index);
511579
}
512580

513-
private Seq<ClusterManagedScriptEntry> getScriptEntries(ShardedClusterDto resource) {
514-
return Seq.of(Optional.ofNullable(resource.getSpec())
515-
.map(ShardedClusterSpec::getCoordinator)
516-
.map(ShardedClusterCoordinator::getManagedSql)
517-
.map(ClusterManagedSql::getScripts),
518-
Optional.ofNullable(resource.getSpec())
581+
List<ClusterManagedScriptEntry> getScriptEntriesForCoordinator(ShardedClusterDto resource) {
582+
return Seq
583+
.of(Optional.ofNullable(resource.getSpec())
584+
.map(ShardedClusterSpec::getCoordinator)
585+
.map(ShardedClusterCoordinator::getManagedSql)
586+
.map(ClusterManagedSql::getScripts))
587+
.filter(Optional::isPresent)
588+
.map(Optional::get)
589+
.flatMap(List::stream)
590+
.toList();
591+
}
592+
593+
List<ClusterManagedScriptEntry> getScriptEntriesForShards(ShardedClusterDto resource) {
594+
return Seq
595+
.of(Optional.ofNullable(resource.getSpec())
519596
.map(ShardedClusterSpec::getShards)
520597
.map(ShardedClusterShards::getManagedSql)
521598
.map(ClusterManagedSql::getScripts))
522-
.append(Optional.ofNullable(resource.getSpec())
523-
.map(ShardedClusterSpec::getShards)
524-
.map(ShardedClusterShards::getOverrides)
525-
.stream()
526-
.flatMap(List::stream)
527-
.map(override -> Optional.of(override)
528-
.map(ShardedClusterShard::getManagedSql)
529-
.map(ClusterManagedSql::getScripts)))
530599
.filter(Optional::isPresent)
531600
.map(Optional::get)
532-
.flatMap(List::stream);
601+
.flatMap(List::stream)
602+
.toList();
603+
}
604+
605+
List<Tuple2<Integer, List<ClusterManagedScriptEntry>>> getScriptEntriesForShardsOverride(ShardedClusterDto resource) {
606+
return Seq
607+
.seq(Optional.ofNullable(resource.getSpec())
608+
.map(ShardedClusterSpec::getShards)
609+
.map(ShardedClusterShards::getOverrides))
610+
.flatMap(List::stream)
611+
.zipWithIndex()
612+
.map(override -> Tuple.tuple(
613+
override.v2.intValue(),
614+
Optional.of(override.v1)
615+
.map(ShardedClusterShard::getManagedSql)
616+
.map(ClusterManagedSql::getScripts)
617+
.orElse(List.of())))
618+
.toList();
533619
}
534620

535621
@Override

0 commit comments

Comments
 (0)