Skip to content

Commit ce8a455

Browse files
authored
Feat: Add skaffold support (#509)
Provide possibility to deploy the keystone into the K8 using [skaffold](https://skaffold.dev)
1 parent 694469f commit ce8a455

File tree

17 files changed

+490
-6
lines changed

17 files changed

+490
-6
lines changed

.dockerignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ doc
33
.git/
44
.gitignore
55
.github/
6-
target
6+
tools/
7+
target/

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
################
22
##### Builder
3-
FROM rust:1.90.0-slim-bookworm AS builder
3+
FROM rust:1.92.0-slim-bookworm AS builder
44

55
#RUN rustup target add x86_64-unknown-linux-gnu &&\
66
RUN apt update &&\

doc/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,4 @@
4444

4545
[API](./swagger-ui.html)
4646
[Performance comparison](performance.md)
47+
[Developer's guide](developer.md)

doc/src/developer.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Developer's guide
2+
3+
Running and testing the Keystone locally requires additional components. Easiest
4+
way to achieve it is to use the docker-compose or the `skaffold` to deploy
5+
components into the small Kubernetes cluster.
6+
7+
## Skaffold
8+
9+
When a kubernetes is available for the local development and testing the
10+
[skaffold](https://skaffold.dev/) can be used to deploy Keystone, OPA, database
11+
and the python keystone together. This is very helpful for being able to test
12+
the compatibility between Keystone implementations and running the API tests
13+
that require the system to be up and running.
14+
15+
It is necessary to have any sort of the image registry running that can be
16+
accessed by the K8 to pull images from. It depends heavily on the concrete K8
17+
implementation since some may come with the built-in registry that the local
18+
docker can push directly to or that the K8 accesses the images directly from the
19+
local docker. When not available the registry can be easily [deployed
20+
locally](https://www.docker.com/blog/how-to-use-your-own-registry-2/).
21+
22+
Skaffold can be invoked with the following command to build and push images,
23+
deploy kubernetes manifests and watch for the changes for reload:
24+
25+
```console
26+
27+
skaffold dev --default-repo localhost:5000
28+
29+
```
30+
31+
It might be useful to add `--cleanup=false` flag to the above command to prevent
32+
skaffold from tearing down all resources when the process is stopped.
33+
34+
Currently the manifests are built to expose the Kestone within the K8 cluster
35+
under: `http://keystone.local` (with certain routes pointing to the python
36+
version and others to the rust), `http://keystone-rs.local` (rust version) and
37+
`http://keystone-py.local` (the python version correspondingly). Depending on
38+
the how the K8 is being deployed and access the Keystone may be directly
39+
accessible from the localhost when i.e. the routes are added in the `/etc/hosts`
40+
file. The manifests are not currently designed to be used for production
41+
deployment.

skaffold.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
apiVersion: skaffold/v4beta13
2+
kind: Config
3+
metadata:
4+
name: keystone
5+
build:
6+
insecureRegistries:
7+
- localhost:5000
8+
artifacts:
9+
- image: localhost:5000/keystone-rs
10+
context: .
11+
docker:
12+
dockerfile: Dockerfile
13+
- image: localhost:5000/keystone-opa-policies
14+
context: policy
15+
docker:
16+
dockerfile: ../tools/Dockerfile.opa # Just FROM opa, but allows syncing
17+
local:
18+
useDockerCLI: true
19+
#tryImportMissing: true
20+
manifests:
21+
kustomize:
22+
paths:
23+
- tools/k8s/keystone/overlays/dev
24+
deploy:
25+
kubectl: {}
26+
helm:
27+
releases:
28+
- name: cloudnative-pg
29+
repo: https://cloudnative-pg.github.io/charts
30+
remoteChart: cloudnative-pg
31+
createNamespace: true
32+
namespace: cnpg

src/config.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,13 @@ impl Config {
127127
let mut builder = config::Config::builder();
128128

129129
if std::path::Path::new(&path).is_file() {
130-
builder = builder.add_source(File::from(path).format(FileFormat::Ini));
130+
builder = builder
131+
.add_source(File::from(path).format(FileFormat::Ini))
132+
.add_source(
133+
config::Environment::with_prefix("OS")
134+
.prefix_separator("_")
135+
.separator("__"),
136+
);
131137
}
132138

133139
builder.try_into()
@@ -146,6 +152,3 @@ impl TryFrom<config::ConfigBuilder<config::builder::DefaultState>> for Config {
146152
.wrap_err("Failed to parse configuration file")
147153
}
148154
}
149-
150-
#[cfg(test)]
151-
mod tests {}

src/config/common.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,7 @@ where
6767
pub fn default_sql_driver() -> String {
6868
"sql".into()
6969
}
70+
71+
pub fn default_true() -> bool {
72+
true
73+
}

src/config/policy.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ use serde::Deserialize;
1515
use url::Url;
1616
use url_macro::url;
1717

18+
use super::common::default_true;
19+
1820
/// The configuration options for the API policy enforcement.
1921
#[derive(Clone, Debug, Deserialize)]
2022
pub struct PolicyProvider {
2123
/// Whether the policy enforcement should be enforced or not.
24+
#[serde(default = "default_true")]
2225
pub enable: bool,
2326

2427
/// OpenPolicyAgent instance url to use for evaluating the policy.

tools/Dockerfile.opa

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FROM docker.io/alpine
2+
# This preserves your entire hierarchy
3+
COPY . /policy
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
apiVersion: batch/v1
2+
kind: Job
3+
metadata:
4+
name: "keystone-bootstrap"
5+
spec:
6+
backoffLimit: 1
7+
template:
8+
spec:
9+
initContainers:
10+
- name: db-waiter
11+
image: busybox:1.36.1
12+
imagePullPolicy: IfNotPresent
13+
command: ['sh', '-c', 'echo "Waiting for PostgreSQL to be available..."; while ! nc -z -w 1 $HOST 5432; do echo "Still waiting for postgres-service..."; sleep 2; done; echo "PostgreSQL is available! Starting application."']
14+
env:
15+
- name: "HOST"
16+
valueFrom:
17+
secretKeyRef:
18+
key: "host"
19+
name: "keystone-db-app"
20+
- env:
21+
- name: OS_DATABASE__CONNECTION
22+
valueFrom:
23+
secretKeyRef:
24+
key: fqdn-uri
25+
name: keystone-db-app
26+
image: py-keystone
27+
name: keystone-db-py
28+
command: [keystone-manage, db_sync]
29+
volumeMounts:
30+
- mountPath: /etc/keystone/keystone.conf
31+
name: config
32+
subPath: keystone.conf
33+
34+
- env:
35+
- name: OS_DATABASE__CONNECTION
36+
valueFrom:
37+
secretKeyRef:
38+
key: fqdn-uri
39+
name: keystone-db-app
40+
image: keystone-rs
41+
name: keystone-db-rs
42+
command: [keystone-db, up]
43+
volumeMounts:
44+
- mountPath: /etc/keystone/keystone.conf
45+
name: config
46+
subPath: keystone.conf
47+
48+
containers:
49+
50+
- env:
51+
- name: OS_DATABASE__CONNECTION
52+
valueFrom:
53+
secretKeyRef:
54+
key: fqdn-uri
55+
name: keystone-db-app
56+
image: py-keystone
57+
name: keystone-bootstrap
58+
command: [keystone-manage, "bootstrap", "--bootstrap-username", "admin", "--bootstrap-password", "password", "--bootstrap-public-url", "http://keystone.local:80", "--bootstrap-internal-url", "http://keystone-rs.local:80"]
59+
volumeMounts:
60+
- mountPath: /etc/keystone/keystone.conf
61+
name: config
62+
subPath: keystone.conf
63+
- mountPath: /etc/keystone/fernet-keys
64+
name: fernet
65+
66+
volumes:
67+
68+
- name: "config"
69+
configMap:
70+
name: "keystone"
71+
72+
- name: "fernet"
73+
secret:
74+
defaultMode: 420
75+
optional: false
76+
secretName: "fernet-keys"
77+
items:
78+
- key: "k0"
79+
path: "0"
80+
- key: "k1"
81+
path: "1"
82+
83+
restartPolicy: "Never"

0 commit comments

Comments
 (0)