Skip to content

Commit 476d216

Browse files
authored
feat: olm deployment helper (#546)
* wip: added olm-deployer * wip * wip: checkpoint * wip * wip: working version * reorg test manifests * impl owner ref * Added readme, update manifests, successful run * reorg modules * wip * test env * copy resources * add secret op lib crate * patch namespace * Revert "add secret op lib crate" This reverts commit acee691. * added test for namespace patch * cargo fmt * added owner name cli param * obtain clusterrole by label selector * olm creates multiple clusterroles per subscription * delete tests in favor of olm manifests * modify DynamicObjects in place and reduce cloning * added keep_alive cli option * sleep forever * fix lint * Update inline docs. * Drop the op_version arg in favor of the csv name. * Update changelog. * fix typos * update readme to mention oci.stackable.tech
1 parent 85f141a commit 476d216

File tree

14 files changed

+1111
-12
lines changed

14 files changed

+1111
-12
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file.
1313

1414
- Made RSA key length configurable for certificates issued by cert-manager ([#528]).
1515
- Kerberos principal backends now also provision principals for IP address, not just DNS hostnames ([#552]).
16+
- OLM deployment helper ([#546]).
1617

1718
### Changed
1819

@@ -22,6 +23,7 @@ All notable changes to this project will be documented in this file.
2223
[#548]: https://github.com/stackabletech/secret-operator/pull/548
2324
[#552]: https://github.com/stackabletech/secret-operator/pull/552
2425
[#544]: https://github.com/stackabletech/secret-operator/pull/544
26+
[#546]: https://github.com/stackabletech/secret-operator/pull/546
2527

2628
## [24.11.1] - 2025-01-10
2729

Cargo.lock

+54-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ clap = "4.5"
2020
futures = { version = "0.3", features = ["compat"] }
2121
h2 = "0.4"
2222
ldap3 = { version = "0.11", default-features = false, features = [
23-
"gssapi",
24-
"tls",
23+
"gssapi",
24+
"tls",
2525
] }
2626
libc = "0.2"
2727
native-tls = "0.2"
@@ -49,6 +49,7 @@ tonic-build = "0.12"
4949
tonic-reflection = "0.12"
5050
tracing = "0.1"
5151
tracing-subscriber = "0.3"
52+
walkdir = "2.5.0"
5253
uuid = { version = "1.10.0", features = ["v4"] }
5354
yasna = "0.5"
5455

nginx-deployment.yaml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
apiVersion: apps/v1
3+
kind: Deployment
4+
metadata:
5+
name: secret-operator-deployer
6+
labels:
7+
app: nginx
8+
spec:
9+
replicas: 3
10+
selector:
11+
matchLabels:
12+
app: nginx
13+
template:
14+
metadata:
15+
labels:
16+
app: nginx
17+
spec:
18+
containers:
19+
- name: nginx
20+
image: nginx:1.14.2
21+
ports:
22+
- containerPort: 80
23+
tolerations:
24+
- key: keep-out
25+
value: "yes"
26+
operator: Equal
27+
effect: NoSchedule

rust/olm-deployer/Cargo.toml

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[package]
2+
name = "olm-deployer"
3+
description = "OLM deployment helper."
4+
version.workspace = true
5+
authors.workspace = true
6+
license.workspace = true
7+
edition.workspace = true
8+
repository.workspace = true
9+
publish = false
10+
11+
[dependencies]
12+
anyhow.workspace = true
13+
clap.workspace = true
14+
tokio.workspace = true
15+
tracing.workspace = true
16+
stackable-operator.workspace = true
17+
serde.workspace = true
18+
serde_json.workspace = true
19+
serde_yaml.workspace = true
20+
walkdir.workspace = true
21+
22+
[build-dependencies]
23+
built.workspace = true

rust/olm-deployer/README.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# How to test
2+
3+
Requirements:
4+
5+
1. An OpenShift cluster.
6+
2. Checkout the branch `secret-olm-deployer` from the [operators](https://github.com/stackabletech/openshift-certified-operators/tree/secret-olm-deployer) repo.
7+
3. Clone the `stackable-utils` [repo](https://github.com/stackabletech/stackable-utils)
8+
9+
Install the secret operator using OLM and the `olm-deployer`. From the `stackable-utils` repo, run:
10+
11+
```bash
12+
$ ./olm/build-bundles.sh -c $HOME/repo/stackable/openshift-certified-operators -r 24.11.0 -o secret -d
13+
...
14+
```
15+
16+
[!NOTE]
17+
Bundle images are published to `oci.stackable.tech` so you need to log in there first.
18+
19+
The secret op and all it's dependencies should be installed and running in the `stackable-operators` namespace.
20+
21+
Run the integration tests:
22+
23+
```bash
24+
$ ./scripts/run-tests --skip-operator secret --test-suite openshift
25+
...
26+
```

rust/olm-deployer/build.rs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
built::write_built_file().unwrap();
3+
}

rust/olm-deployer/src/data.rs

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use anyhow::{bail, Result};
2+
use stackable_operator::kube::{api::DynamicObject, ResourceExt};
3+
4+
pub fn data_field_as_mut<'a>(
5+
value: &'a mut serde_json::Value,
6+
pointer: &str,
7+
) -> Result<&'a mut serde_json::Value> {
8+
match value.pointer_mut(pointer) {
9+
Some(field) => Ok(field),
10+
x => bail!("invalid pointer {pointer} for object {x:?}"),
11+
}
12+
}
13+
14+
pub fn container<'a>(
15+
target: &'a mut DynamicObject,
16+
container_name: &str,
17+
) -> anyhow::Result<&'a mut serde_json::Value> {
18+
let tname = target.name_any();
19+
let path = "template/spec/containers".split("/");
20+
match get_or_create(target.data.pointer_mut("/spec").unwrap(), path)? {
21+
serde_json::Value::Array(containers) => {
22+
for c in containers {
23+
if c.is_object() {
24+
if let Some(serde_json::Value::String(name)) = c.get("name") {
25+
if container_name == name {
26+
return Ok(c);
27+
}
28+
}
29+
} else {
30+
anyhow::bail!("container is not a object: {:?}", c);
31+
}
32+
}
33+
anyhow::bail!("container named {container_name} not found");
34+
}
35+
_ => anyhow::bail!("no containers found in object {tname}"),
36+
}
37+
}
38+
39+
/// Returns the object nested in `root` by traversing the `path` of nested keys.
40+
/// Creates any missing objects in path.
41+
/// In case of success, the returned value is either the existing object or
42+
/// serde_json::Value::Null.
43+
/// Returns an error if any of the nested objects has a type other than map.
44+
pub fn get_or_create<'a, 'b, I>(
45+
root: &'a mut serde_json::Value,
46+
path: I,
47+
) -> anyhow::Result<&'a mut serde_json::Value>
48+
where
49+
I: IntoIterator<Item = &'b str>,
50+
{
51+
let mut iter = path.into_iter();
52+
match iter.next() {
53+
None => Ok(root),
54+
Some(first) => {
55+
let new_root = get_or_insert_default_object(root, first)?;
56+
get_or_create(new_root, iter)
57+
}
58+
}
59+
}
60+
61+
/// Given a map object create or return the object corresponding to the given `key`.
62+
fn get_or_insert_default_object<'a>(
63+
value: &'a mut serde_json::Value,
64+
key: &str,
65+
) -> anyhow::Result<&'a mut serde_json::Value> {
66+
let map = match value {
67+
serde_json::Value::Object(map) => map,
68+
x @ serde_json::Value::Null => {
69+
*x = serde_json::json!({});
70+
x.as_object_mut().unwrap()
71+
}
72+
x => anyhow::bail!("invalid type {x:?}, expected map"),
73+
};
74+
Ok(map.entry(key).or_insert_with(|| serde_json::Value::Null))
75+
}

0 commit comments

Comments
 (0)