Skip to content

Commit

Permalink
Merge pull request #13 from projectsyn/multi-instance
Browse files Browse the repository at this point in the history
Add Multi instance support
  • Loading branch information
ccremer authored May 18, 2021
2 parents 24399e6 + 9ccf07d commit df58994
Show file tree
Hide file tree
Showing 28 changed files with 1,122 additions and 85 deletions.
21 changes: 18 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,30 @@ jobs:
- name: Run ${{ matrix.command }}
run: make ${{ matrix.command }}

# This tests just whether compilation works, not whether the output is correct.
compile:
test:
runs-on: ubuntu-latest
strategy:
matrix:
provider:
- builtin
- external
defaults:
run:
working-directory: ${{ env.COMPONENT_NAME }}
steps:
- uses: actions/checkout@v2
with:
path: ${{ env.COMPONENT_NAME }}
- name: Determine Go version from go.mod
run: echo "GO_VERSION=$(grep "go 1." tests/go.mod | cut -d " " -f 2)" >> $GITHUB_ENV
- uses: actions/setup-go@v2
with:
go-version: ${{ env.GO_VERSION }}
- uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Compile component
run: make compile
run: make test -e provider=${{ matrix.provider }}
29 changes: 23 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,44 @@ help: ## Show this help
all: lint

.PHONY: lint
lint: lint_jsonnet lint_yaml lint_adoc
lint: lint_jsonnet lint_yaml lint_adoc ## All-in-one linting

.PHONY: lint_jsonnet
lint_jsonnet: $(JSONNET_FILES)
lint_jsonnet: $(JSONNET_FILES) ## Lint jsonnet files
$(JSONNET_DOCKER) $(JSONNETFMT_ARGS) --test -- $?

.PHONY: lint_yaml
lint_yaml: $(YAML_FILES)
lint_yaml: $(YAML_FILES) ## Lint yaml files
$(YAMLLINT_DOCKER) -f parsable -c $(YAMLLINT_CONFIG) $(YAMLLINT_ARGS) -- $?

.PHONY: lint_adoc
lint_adoc:
$(VALE_CMD) $(VALE_ARGS)

.PHONY: format
format: format_jsonnet
format: format_jsonnet ## All-in-one formatting

.PHONY: format_jsonnet
format_jsonnet: $(JSONNET_FILES)
format_jsonnet: $(JSONNET_FILES) ## Format jsonnet files
$(JSONNET_DOCKER) $(JSONNETFMT_ARGS) -- $?

.PHONY: docs-serve
docs-serve: ## Preview the documentation
$(ANTORA_PREVIEW_CMD)

.PHONY: docs-vale
docs-vale: ## Lint the documentation
$(VALE_CMD) $(VALE_ARGS)

.PHONY: compile
compile:
.compile:
$(COMMODORE_CMD)

.PHONY: test
test: commodore_args = -f tests/$(provider).yml
test: .compile ## Test component with a provider set by "provider=..."
cd tests/ && go test ./$(provider)/... -count=1

.PHONY: clean
clean: ## Clean the project
rm -rf compiled dependencies vendor helmcharts jsonnetfile*.json || true
2 changes: 1 addition & 1 deletion Makefile.vars.mk
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ VALE_ARGS ?= --minAlertLevel=error --config=/pages/ROOT/pages/.vale.ini /pages

ANTORA_PREVIEW_CMD ?= $(DOCKER_CMD) run --rm --publish 2020:2020 --volume "${PWD}":/antora vshn/antora-preview:2.3.3 --style=syn --antora=docs

COMMODORE_CMD ?= $(DOCKER_CMD) $(DOCKER_ARGS) $(root_volume) projectsyn/commodore:latest component compile . -f tests/test.yml $(commodore_args)
COMMODORE_CMD ?= $(DOCKER_CMD) $(DOCKER_ARGS) $(root_volume) projectsyn/commodore:latest component compile . $(commodore_args)
JB_CMD ?= $(DOCKER_CMD) $(DOCKER_ARGS) --entrypoint /usr/local/bin/jb projectsyn/commodore:latest install
34 changes: 24 additions & 10 deletions class/defaults.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
parameters:
keycloak:
namespace: syn-keycloak
multi_instance: true
# make lookup table constant to prevent changes to it through the hierarchy
=_enable_pg_chart:
# This lookup table controls whether to enable the chart depending on the value of `keycloak.database.provider`
builtin: true
external: false

namespace: syn-${_instance}
release_name: keycloak
charts:
keycloak: '10.3.1'
Expand All @@ -10,7 +17,7 @@ parameters:
admin:
secretname: keycloak-admin-user
username: admin
password: '?{vaultkv:${customer:name}/${cluster:name}/keycloak/admin-password}'
password: '?{vaultkv:${customer:name}/${cluster:name}/${_instance}/admin-password}'
# Replica count
replicas: 2
# Ingress or Route should be enabled on the distribution level
Expand All @@ -24,7 +31,7 @@ parameters:
# entries in key `labels`.
labels:
app.kubernetes.io/name: keycloak
app.kubernetes.io/instance: syn-keycloak
app.kubernetes.io/instance: ${_instance}
app.kubernetes.io/version: v11.0.0
app.kubernetes.io/component: keycloak
app.kubernetes.io/managed-by: commodore
Expand All @@ -47,16 +54,22 @@ parameters:
rules: []
# Use Bitnami Postgres installed by the Keycloak chart by default
database:
builtin: true
provider: builtin

secretname: keycloak-postgresql
password: '?{vaultkv:${customer:name}/${cluster:name}/${_instance}/db-password}'
database: keycloak
username: keycloak

# Used when `provider=external`
external:
secretname: keycloak-db-credentials
vendor: postgres
host: postgres.example.com
port: 5432
database: keycloak
username: keycloak
password: '?{vaultkv:${customer:name}/${cluster:name}/keycloak/db-password}'

helm_values:
image:
repository: quay.io/keycloak/keycloak
replicas: ${keycloak:replicas}
statefulsetLabels: ${keycloak:labels}
resources: ${keycloak:resources}
Expand Down Expand Up @@ -87,7 +100,7 @@ parameters:
- secretRef:
name: ${keycloak:admin:secretname}
- secretRef:
name: ${keycloak:database:external:secretname}
name: ${keycloak:database:secretname}
serviceAccount:
labels: ${keycloak:labels}
ingress:
Expand Down Expand Up @@ -115,7 +128,8 @@ parameters:
labels: ${keycloak:labels}
rules: ${keycloak:monitoring:rules}
postgresql:
enabled: ${keycloak:database:builtin}
enabled: ${keycloak:_enable_pg_chart:${keycloak:database:provider}}
existingSecret: ${keycloak:database:secretname}
image:
registry: quay.io
master:
Expand Down
6 changes: 3 additions & 3 deletions class/keycloak.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ parameters:
- input_paths:
- keycloak/component/main.jsonnet
input_type: jsonnet
output_path: keycloak/
- output_path: keycloak/01_keycloak_helmchart
output_path: ${_instance}
- output_path: ${_instance}/01_keycloak_helmchart
input_type: helm
output_type: yaml
input_paths:
- keycloak/helmcharts/keycloak/${keycloak:charts:keycloak}/
helm_params:
release_name: '${keycloak:release_name}'
release_name: ${keycloak:release_name}
namespace: '${keycloak:namespace}'
helm_values: ${keycloak:helm_values}
5 changes: 3 additions & 2 deletions component/app.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ local kap = import 'lib/kapitan.libjsonnet';
local inv = kap.inventory();
local params = inv.parameters.keycloak;
local argocd = import 'lib/argocd.libjsonnet';
local instance = inv.parameters._instance;

local app = argocd.App('keycloak', params.namespace);
local app = argocd.App(instance, params.namespace);

{
keycloak: app,
[instance]: app,
}
46 changes: 21 additions & 25 deletions component/main.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,30 @@ local admin_secret = kube.Secret(params.admin.secretname) {
},
};

local external_db_secret =
local isdummysecret =
if params.database.builtin then
{
'commodore.syn.tools/dummy-secret': 'true',
}
else
{};
kube.Secret(params.database.external.secretname) {
metadata+: {
labels+: params.labels + isdummysecret,
},
stringData:
if !params.database.builtin then
{
DB_VENDOR: params.database.external.vendor,
DB_ADDR: params.database.external.host,
DB_PORT: params.database.external.port,
DB_DATABASE: params.database.external.database,
DB_USER: params.database.external.username,
DB_PASSWORD: params.database.external.password,
}
else {},
};
local secrets = {
builtin: {
'postgresql-password': params.database.password,
},
external: {
DB_DATABASE: params.database.database,
DB_USER: params.database.username,
DB_PASSWORD: params.database.password,
DB_VENDOR: params.database.external.vendor,
DB_ADDR: params.database.external.host,
DB_PORT: std.toString(params.database.external.port),
},
};

local db_secret = kube.Secret(params.database.secretname) {
metadata+: {
labels+: params.labels,
},
stringData: secrets[params.database.provider],
};

// Define outputs below
{
'00_namespace': namespace,
'10_admin_secret': admin_secret,
'20_external_db_secret': external_db_secret,
'11_db_secret': db_secret,
}
Empty file.
55 changes: 55 additions & 0 deletions docs/modules/ROOT/pages/how-tos/multi-instance.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
= Deploy multiple instances

This guide provides an example how to deploy multiple instances of this component.

====
Requirements
* `commodore`
* `pwgen`
* `vault`
====

. Prepare catalog
+
[source,yaml]
----
# Add the instances and give them a name.
applications:
- keycloak as keycloak-test
- keycloak as keycloak-prod

parameters:
# Configure the test instance with defaults and built-in database
keycloak_test:
namespace: tenant-keycloak-test

# Configure the production instance using an external database
keycloak_prod:
namespace: tenant-keycloak-prod
database:
provider: external
external:
host: my-postgres-db-server.tld
----
+
[NOTE]
====
By default, the component configures the namespace with `syn-<instance-name>`.
Using the `syn-` prefix might not be what you want when using multiple instances or when deploying Keycloak for another tenant.
Use the `namespace` parameter to customize the namespace, but be sure that each instance gets their own namespace.
====
. Set secrets
+
[source,bash]
----
parent="clusters/kv/${TENANT_ID}/${CLUSTER_ID}"

vault kv put -cas=0 "${parent}/keycloak-test" admin-password=$(pwgen -s 32 1) db-password=$(pwgen -s 32 1)
vault kv put -cas=0 "${parent}/keycloak-prod" admin-password=$(pwgen -s 32 1) db-password=<your-external-db-password>
----
. Compile and push the cluster catalog
. Wait until changes are applied
. Verify that the instances are up and configured correctly
36 changes: 36 additions & 0 deletions docs/modules/ROOT/pages/how-tos/pin-versions.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
= Pin versions

This tutorial explains how to pin Keycloak to specific version.

== Pin Helm chart version

The Keycloak deployment is mainly generated through https://github.com/codecentric/helm-charts/tree/master/charts/keycloak[codecentric's Keycloak Helm chart].
New versions are released in the https://github.com/codecentric/helm-charts/releases[Releases page].

Normally the component tries to stay up-to-date with the latest Helm chart version.
If you need to override the chart version, you can pin it in the parameters:

[source,yaml]
----
parameters:
keycloak:
charts:
keycloak: '<version>'
----

== Pin container image tag

The version of Keycloak itself is defined in the Helm chart release.
New versions are released in the https://quay.io/repository/keycloak/keycloak?tab=tags[Quay.io container registry].

Since we're using an upstream Helm chart, it can sometimes take a while until new Keycloak releases actually make it into a new Helm chart release.
If you need to override the Keycloak version, you can pin it in the parameters:

[source,yaml]
----
parameters:
keycloak:
helm_values:
image:
tag: '<tag>'
----
Loading

0 comments on commit df58994

Please sign in to comment.