Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ jobs:
- name: helm unittest
run: make test-unit

- name: config-seed script against sample files
run: make test-config-seed

config-keys:
runs-on: ubuntu-24.04
steps:
Expand Down
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ HELM ?= helm
CHART_DIR := charts/arcadedb
HELM_UNITTEST_VERSION := 0.5.2

.PHONY: help lint test-unit test-config-keys test-integration test plugin-install
.PHONY: help lint test-unit test-config-seed test-config-keys test-integration test plugin-install

help:
@echo "Targets:"
@echo " make lint Run helm lint"
@echo " make test-unit Run helm-unittest suites"
@echo " make test-config-seed Run the config-seed init container script against sample files"
@echo " make test-config-keys Check rendered -Darcadedb.* keys against the server image (needs docker)"
@echo " make test-integration Run kind-based integration tests"
@echo " make test All of the above"
Expand All @@ -27,10 +28,13 @@ plugin-install:
test-unit: plugin-install
$(HELM) unittest $(CHART_DIR)

test-config-seed:
bash ci/test-config-seed.sh

test-config-keys:
bash ci/check-config-keys.sh

test-integration:
bash ci/integration-test.sh

test: lint test-unit test-config-keys test-integration
test: lint test-unit test-config-seed test-config-keys test-integration
40 changes: 31 additions & 9 deletions charts/arcadedb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ Enable plugins by adding a plugin entry under `arcadedb.plugins`.
| `arcadedb.plugins.bolt.enabled` | Enable Bolt protocol support | not set |
| `arcadedb.plugins.bolt.port` | Bolt protocol port | `7687` when enabled |
| `arcadedb.plugins.gremlin.enabled` | Enable Gremlin protocol support | not set |
| `arcadedb.plugins.gremlin.port` | Gremlin protocol port; only `8182` is accepted (see below) | `8182` when enabled |
| `arcadedb.plugins.gremlin.port` | Gremlin protocol port; only `8182` unless `writePortToConfig` or `portManagedExternally` is set (see below) | `8182` when enabled |
| `arcadedb.plugins.gremlin.writePortToConfig` | Have `config-seed` write `port` into `gremlin-server.yaml` on every start (see below) | `false` |
| `arcadedb.plugins.gremlin.portManagedExternally` | Accept a `port` other than `8182` because your own `gremlin-server.yaml` sets it (see below) | `false` |
| `arcadedb.plugins.postgres.enabled` | Enable PostgreSQL protocol support | not set |
| `arcadedb.plugins.postgres.port` | PostgreSQL protocol port | `5432` when enabled |
Expand All @@ -115,14 +116,34 @@ Enable plugins by adding a plugin entry under `arcadedb.plugins`.
| `arcadedb.plugins.<custom>.class` | Custom plugin implementation class | required |

The Gremlin plugin takes its port from `gremlin-server.yaml` (the image's sets none, so TinkerPop's default
`8182`), not from a `-D` setting, so the chart cannot move it. `arcadedb.plugins.gremlin.port` only sets the port
the Services and the NetworkPolicy expose, and any value other than `8182` fails the render instead of pointing
them at a port nothing listens on.
`8182`), not from a `-D` setting, so the chart cannot pass it on the command line. By default
`arcadedb.plugins.gremlin.port` only sets the port the Services and the NetworkPolicy expose, and any value other
than `8182` fails the render instead of pointing them at a port nothing listens on.

To run Gremlin on another port, set `port:` in the `gremlin-server.yaml` on the config volume (the `config-seed`
init container copies the image's file there only when it is absent, so an edited file is kept), then set
`arcadedb.plugins.gremlin.port` to the same value and `arcadedb.plugins.gremlin.portManagedExternally: true`.
The chart then exposes that port without checking it; keeping the two in step is up to you:
To run Gremlin on another port, set `arcadedb.plugins.gremlin.writePortToConfig: true` with the port you want:

```yaml
arcadedb:
plugins:
gremlin:
enabled: true
port: 8183
writePortToConfig: true
```

The `config-seed` init container then sets the top-level `port:` key of `gremlin-server.yaml` on the config volume
to that value on every pod start (adding the key when the file has none), and leaves every other line as it is. The
server, the Services and the NetworkPolicy all follow the one value, and a later `helm upgrade` that changes it
restarts the pods with the new port. It is opt-in because it edits a file `config-seed` otherwise never touches once it
exists. It needs `initContainers.configSeed.enabled` and a volume holding `arcadedb.configDirectory` (both the
default), and it fails the render when `gremlin-server.yaml` is mounted on its own from another volume (for example
a ConfigMap `subPath`), since the server would read that file instead. Turning it off later leaves the last `port:`
written in the file: set `port` back to `8182` there, or keep the value with `portManagedExternally` below.

If you manage `gremlin-server.yaml` yourself instead, set `port:` in it (the `config-seed` init container copies the
image's file there only when it is absent, so an edited file is kept), then set `arcadedb.plugins.gremlin.port` to
the same value and `arcadedb.plugins.gremlin.portManagedExternally: true`. The chart then exposes that port without
checking it; keeping the two in step is up to you:

```yaml
arcadedb:
Expand Down Expand Up @@ -569,7 +590,8 @@ The chart adds a `config-seed` init container that runs the server image itself
tag, so the defaults match the server version), mounts the volume holding the config directory at
`/config-seed` so the image's own `config/` stays visible, and copies each of those files that the config
directory does not hold yet. A file that already exists is never overwritten, so changes made at runtime or by
hand survive restarts. The logging files are not seeded: the chart ships
hand survive restarts. The one exception is opt-in: with `arcadedb.plugins.gremlin.writePortToConfig` it sets the
top-level `port:` of `gremlin-server.yaml` on every start (see [arcadedb.plugins](#arcadedbplugins)). The logging files are not seeded: the chart ships
`arcadedb-log.properties` from a ConfigMap (see `arcadedb.logging`). The container uses `securityContext`, so
it runs as the ArcadeDB user, and it runs after `config-chown` when that one is enabled.

Expand Down
39 changes: 39 additions & 0 deletions charts/arcadedb/files/config-seed.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
set -e
src="$1"; dst="$2"; shift 2
mkdir -p "$dst"
for f in "$@"; do
if [ -e "$dst/$f" ]; then
echo "config-seed: keeping existing $f"
elif [ -f "$src/$f" ]; then
cat "$src/$f" > "$dst/.$f.seed"
mv "$dst/.$f.seed" "$dst/$f"
echo "config-seed: seeded $f"
else
echo "config-seed: $f is not in the image, skipped"
fi
done
# GREMLIN_PORT (arcadedb.plugins.gremlin.writePortToConfig, #58): the Gremlin
# plugin reads its port only from gremlin-server.yaml, so set the top-level
# port: key there on every start. Every other line is kept as it is.
if [ -n "${GREMLIN_PORT:-}" ]; then
yaml="$dst/gremlin-server.yaml"
tmp="$dst/.gremlin-server.yaml.port"
found=""
: > "$tmp"
if [ -f "$yaml" ]; then
while IFS= read -r line || [ -n "$line" ]; do
case "$line" in
port:*|"port :"*|\"port\":*|\'port\':*)
[ -n "$found" ] || printf 'port: %s\n' "$GREMLIN_PORT" >> "$tmp"
found=1
;;
*)
printf '%s\n' "$line" >> "$tmp"
;;
esac
done < "$yaml"
fi
[ -n "$found" ] || printf 'port: %s\n' "$GREMLIN_PORT" >> "$tmp"
mv "$tmp" "$yaml"
echo "config-seed: set port: $GREMLIN_PORT in gremlin-server.yaml"
fi
67 changes: 50 additions & 17 deletions charts/arcadedb/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,22 @@ parameters, service and networkPolicy helpers build on this output.
gremlin-server.yaml on the config volume sets that port (#52): the value is
then only what the Services and the NetworkPolicy expose, and the chart
still passes no port to the server.
writePortToConfig: true has config-seed set port: in gremlin-server.yaml
on every start (#58), so the chart moves the port itself; the two
settings are alternatives and may not be combined.
*/}}
{{- if eq (toString $config.portManagedExternally) "true" }}
{{- $external := eq (toString $config.portManagedExternally) "true" }}
{{- $writePort := eq (toString $config.writePortToConfig) "true" }}
{{- if and $external $writePort }}
{{- fail "arcadedb.plugins.gremlin.portManagedExternally and arcadedb.plugins.gremlin.writePortToConfig are both true: either your own gremlin-server.yaml sets the port, or the chart writes it there. Set only one." -}}
{{- end }}
{{- if or $external $writePort }}
{{- if or (lt (int $port) 1) (gt (int $port) 65535) }}
{{- fail (printf "arcadedb.plugins.gremlin.port is %v, which is not a TCP port (1-65535)." $port) -}}
{{- end }}
{{- if $writePort }}{{- $_ := include "arcadedb.gremlin.configPort" $ }}{{- end }}
{{- else if ne (int $port) 8182 }}
{{- fail (printf "arcadedb.plugins.gremlin.port is %v, but the Gremlin plugin listens on 8182: it reads its port from gremlin-server.yaml and the server has no setting the chart can pass to change it (#47). Leave arcadedb.plugins.gremlin.port unset or set it to 8182." $port) -}}
{{- fail (printf "arcadedb.plugins.gremlin.port is %v, but the Gremlin plugin listens on 8182: it reads its port from gremlin-server.yaml and the server has no setting the chart can pass to change it (#47). Leave arcadedb.plugins.gremlin.port unset or set it to 8182, or set arcadedb.plugins.gremlin.writePortToConfig: true to have the chart write it into gremlin-server.yaml (#58)." $port) -}}
{{- end }}
{{- else if eq $plugin "postgres" }}
{{- $port = default 5432 $config.port }}
Expand Down Expand Up @@ -717,6 +726,35 @@ the chart ships arcadedb-log.properties from a ConfigMap (#38).
{{- list "server-groups.json" "gremlin-server.yaml" "gremlin-server.properties" "gremlin-server.groovy" | toJson -}}
{{- end -}}

{{/*
The Gremlin port config-seed writes into gremlin-server.yaml (#58), or nothing.
Set when arcadedb.plugins.gremlin is enabled with writePortToConfig: true: the
plugin reads its port only from that file, so config-seed sets its top-level
port: key on every start. Fails when config-seed cannot reach the file the
server reads: config-seed disabled, no volumeMounts entry holding
configDirectory, or a volumeMounts entry mounted on gremlin-server.yaml itself
(config-seed would edit the copy under it, which the server never sees).
*/}}
{{- define "arcadedb.gremlin.configPort" -}}
{{- $config := (.Values.arcadedb.plugins | default dict).gremlin | default dict -}}
{{- if and $config.enabled (eq (toString $config.writePortToConfig) "true") -}}
{{- $seed := (.Values.initContainers | default dict).configSeed | default dict -}}
{{- if not (or (not (hasKey $seed "enabled")) $seed.enabled) -}}
{{- fail "arcadedb.plugins.gremlin.writePortToConfig needs the config-seed init container, which writes the port into gremlin-server.yaml: set initContainers.configSeed.enabled=true, or set the port in your own gremlin-server.yaml with arcadedb.plugins.gremlin.portManagedExternally: true." -}}
{{- end -}}
{{- if not (include "arcadedb.configSeed.mount" . | fromJson) -}}
{{- fail (printf "arcadedb.plugins.gremlin.writePortToConfig needs a volumeMounts entry that holds arcadedb.configDirectory (%s): without one, the gremlin-server.yaml config-seed writes would not outlive the init container." .Values.arcadedb.configDirectory) -}}
{{- end -}}
{{- $file := printf "%s/gremlin-server.yaml" (trimSuffix "/" .Values.arcadedb.configDirectory) -}}
{{- range .Values.volumeMounts -}}
{{- if eq (trimSuffix "/" (toString .mountPath)) $file -}}
{{- fail (printf "arcadedb.plugins.gremlin.writePortToConfig cannot write the port: volumeMounts entry '%s' is mounted on %s, so the server reads that file, not the one config-seed edits. Set port: in it and use arcadedb.plugins.gremlin.portManagedExternally: true instead." .name $file) -}}
{{- end -}}
{{- end -}}
{{- int (default 8182 $config.port) -}}
{{- end -}}
{{- end -}}

{{/*
The volumeMounts entry that holds arcadedb.configDirectory: the deepest mountPath
that is the directory or one of its parents. Returns JSON {} when none does.
Expand Down Expand Up @@ -762,7 +800,10 @@ The config-seed init container. It runs the image named by
arcadedb.configSeed.image with the volume that holds configDirectory mounted at
/config-seed instead of over the image's config/, and copies each file the
directory does not hold yet. Existing files, including ones the server or an
operator changed, are never overwritten.
operator changed, are never overwritten; the one exception is the top-level
port: of gremlin-server.yaml, set on every start when arcadedb.gremlin.configPort
returns a port (#58). The script is files/config-seed.sh (ci/test-config-seed.sh
runs it against sample files).
Skipped when disabled, and when no volumeMounts entry holds configDirectory
(nothing would outlive the init container).
A values file without the key (helm upgrade --reuse-values) keeps it on.
Expand All @@ -786,20 +827,12 @@ A values file without the key (helm upgrade --reuse-values) keeps it on.
- sh
- -c
- |
set -e
src="$1"; dst="$2"; shift 2
mkdir -p "$dst"
for f in "$@"; do
if [ -e "$dst/$f" ]; then
echo "config-seed: keeping existing $f"
elif [ -f "$src/$f" ]; then
cat "$src/$f" > "$dst/.$f.seed"
mv "$dst/.$f.seed" "$dst/$f"
echo "config-seed: seeded $f"
else
echo "config-seed: $f is not in the image, skipped"
fi
done
{{ .Files.Get "files/config-seed.sh" | trim | indent 6 }}
{{- with include "arcadedb.gremlin.configPort" . }}
env:
- name: GREMLIN_PORT
value: {{ . | quote }}
{{- end }}
args:
- config-seed
- {{ $source | quote }}
Expand Down
2 changes: 1 addition & 1 deletion charts/arcadedb/tests/gremlin_port_external_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ tests:
arcadedb.plugins.gremlin.portManagedExternally: false
asserts:
- failedTemplate:
errorMessage: "arcadedb.plugins.gremlin.port is 9999, but the Gremlin plugin listens on 8182: it reads its port from gremlin-server.yaml and the server has no setting the chart can pass to change it (#47). Leave arcadedb.plugins.gremlin.port unset or set it to 8182."
errorMessage: "arcadedb.plugins.gremlin.port is 9999, but the Gremlin plugin listens on 8182: it reads its port from gremlin-server.yaml and the server has no setting the chart can pass to change it (#47). Leave arcadedb.plugins.gremlin.port unset or set it to 8182, or set arcadedb.plugins.gremlin.writePortToConfig: true to have the chart write it into gremlin-server.yaml (#58)."

- it: refuses a port that is not a valid TCP port even when managed externally
template: statefulset.yaml
Expand Down
6 changes: 3 additions & 3 deletions charts/arcadedb/tests/gremlin_port_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ tests:
arcadedb.plugins.gremlin.port: 9999
asserts:
- failedTemplate:
errorMessage: "arcadedb.plugins.gremlin.port is 9999, but the Gremlin plugin listens on 8182: it reads its port from gremlin-server.yaml and the server has no setting the chart can pass to change it (#47). Leave arcadedb.plugins.gremlin.port unset or set it to 8182."
errorMessage: "arcadedb.plugins.gremlin.port is 9999, but the Gremlin plugin listens on 8182: it reads its port from gremlin-server.yaml and the server has no setting the chart can pass to change it (#47). Leave arcadedb.plugins.gremlin.port unset or set it to 8182, or set arcadedb.plugins.gremlin.writePortToConfig: true to have the chart write it into gremlin-server.yaml (#58)."

- it: refuses a port other than 8182 with the NetworkPolicy and external Service enabled
template: statefulset.yaml
Expand All @@ -79,7 +79,7 @@ tests:
arcadedb.plugins.gremlin.port: 9999
asserts:
- failedTemplate:
errorMessage: "arcadedb.plugins.gremlin.port is 9999, but the Gremlin plugin listens on 8182: it reads its port from gremlin-server.yaml and the server has no setting the chart can pass to change it (#47). Leave arcadedb.plugins.gremlin.port unset or set it to 8182."
errorMessage: "arcadedb.plugins.gremlin.port is 9999, but the Gremlin plugin listens on 8182: it reads its port from gremlin-server.yaml and the server has no setting the chart can pass to change it (#47). Leave arcadedb.plugins.gremlin.port unset or set it to 8182, or set arcadedb.plugins.gremlin.writePortToConfig: true to have the chart write it into gremlin-server.yaml (#58)."

- it: a port given as a string is compared by value
template: statefulset.yaml
Expand All @@ -88,7 +88,7 @@ tests:
arcadedb.plugins.gremlin.port: "7777"
asserts:
- failedTemplate:
errorMessage: "arcadedb.plugins.gremlin.port is 7777, but the Gremlin plugin listens on 8182: it reads its port from gremlin-server.yaml and the server has no setting the chart can pass to change it (#47). Leave arcadedb.plugins.gremlin.port unset or set it to 8182."
errorMessage: "arcadedb.plugins.gremlin.port is 7777, but the Gremlin plugin listens on 8182: it reads its port from gremlin-server.yaml and the server has no setting the chart can pass to change it (#47). Leave arcadedb.plugins.gremlin.port unset or set it to 8182, or set arcadedb.plugins.gremlin.writePortToConfig: true to have the chart write it into gremlin-server.yaml (#58)."

- it: a disabled gremlin entry with another port renders
template: statefulset.yaml
Expand Down
Loading