Skip to content

Commit a4734e8

Browse files
committed
Merge remote-tracking branch 'origin/main' into feat/kube-3
2 parents 77a529b + eace189 commit a4734e8

26 files changed

Lines changed: 1613 additions & 154 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/stackable-certs/src/ca/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ where
247247
//
248248
// The root profile doesn't add the AuthorityKeyIdentifier extension.
249249
// We manually add it below by using the 160-bit SHA-1 hash of the
250-
// subject pulic key. This conforms to one of the outlined methods for
250+
// subject public key. This conforms to one of the outlined methods for
251251
// generating key identifiers outlined in RFC 5280, section 4.2.1.2.
252252
//
253253
// Prepare extensions so we can avoid clones.

crates/stackable-operator/CHANGELOG.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,60 @@ All notable changes to this project will be documented in this file.
44

55
## [Unreleased]
66

7+
### Fixed
8+
9+
- Store the Vector state in the log directory to ensure it persists across container restarts ([#1149]).
10+
11+
[#1149]: https://github.com/stackabletech/operator-rs/pull/1149
12+
13+
## [0.105.0] - 2026-02-03
14+
15+
### Added
16+
17+
- BREAKING: Add support to gracefully shutdown `EosChecker`.
18+
`EosChecker::run` now requires passing a shutdown signal, which is any `Future<Output = ()>` ([#1146]).
19+
- Add `SignalWatcher` which can be used to watch signals and multiply them to gracefully shutdown
20+
multiple concurrent tasks/futures ([#1147]).
21+
22+
[#1146]: https://github.com/stackabletech/operator-rs/pull/1146
23+
[#1147]: https://github.com/stackabletech/operator-rs/pull/1147
24+
25+
## [0.104.0] - 2026-01-26
26+
27+
### Added
28+
29+
- Add `serviceOverrides` field of type `Service` to `ListenerClass.spec.serviceOverrides` ([#1142]).
30+
31+
### Changed
32+
33+
- BREAKING: `ListenerClassSpec` no longer implements `Eq` ([#1142]).
34+
35+
[#1142]: https://github.com/stackabletech/operator-rs/pull/1142
36+
37+
## [0.103.0] - 2026-01-16
38+
39+
### Changed
40+
41+
- BREAKING: Add support for the SSH protocol for pulling git content ([#1121]).
42+
This is a user-facing breaking change and should also be highlighted by operators using this functionality.
43+
44+
[#1121]: https://github.com/stackabletech/operator-rs/pull/1121
45+
46+
## [0.102.0] - 2026-01-14
47+
48+
### Added
49+
50+
- BREAKING: Add `objectOverrides` field to `ListenerSpec` ([#1136]).
51+
- Added `stackable_operator::constants::RESTART_CONTROLLER_ENABLED_LABEL` constant, which represents the `restarter.stackable.tech/enabled=true` label ([#1139]).
52+
753
### Changed
854

955
- Revert and pin k8s-openapi to 0.26.0 ([#1135]).
56+
- BREAKING: `ListenerSpec` no longer derives `Eq` ([#1136]).
1057

1158
[#1135]: https://github.com/stackabletech/operator-rs/pull/1135
59+
[#1136]: https://github.com/stackabletech/operator-rs/pull/1136
60+
[#1139]: https://github.com/stackabletech/operator-rs/pull/1139
1261

1362
## [0.101.2] - 2026-01-07
1463

crates/stackable-operator/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "stackable-operator"
33
description = "Stackable Operator Framework"
4-
version = "0.101.2"
4+
version = "0.105.0"
55
authors.workspace = true
66
license.workspace = true
77
edition.workspace = true

crates/stackable-operator/crds/DummyCluster.yaml

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,86 @@ spec:
7575
domainName:
7676
description: A validated domain name type conforming to RFC 1123, so e.g. not an IP address
7777
type: string
78+
gitSync:
79+
properties:
80+
branch:
81+
default: main
82+
description: |-
83+
The branch to clone; defaults to `main`.
84+
85+
Since git-sync v4.x.x this field is mapped to the flag `--ref`.
86+
type: string
87+
credentials:
88+
anyOf:
89+
- oneOf:
90+
- required:
91+
- basicAuthSecretName
92+
- required:
93+
- sshPrivateKeySecretName
94+
- enum:
95+
- null
96+
nullable: true
97+
description: An optional secret used for git access.
98+
properties:
99+
basicAuthSecretName:
100+
description: |-
101+
The name of the Secret used to access the repository via Basic Authentication if it is not public.
102+
103+
The referenced Secret must include two fields: `user` and `password`.
104+
The `password` field can either be an actual password (not recommended) or a GitHub token,
105+
as described in the git-sync [documentation].
106+
107+
[documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
108+
type: string
109+
sshPrivateKeySecretName:
110+
description: |-
111+
The name of the Secret used for SSH access to the repository.
112+
113+
The referenced Secret must include two fields: `key` and `knownHosts`.
114+
115+
[documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
116+
type: string
117+
type: object
118+
depth:
119+
default: 1
120+
description: The depth of syncing, i.e. the number of commits to clone; defaults to 1.
121+
format: uint32
122+
minimum: 0.0
123+
type: integer
124+
gitFolder:
125+
default: /
126+
description: |-
127+
Location in the Git repository containing the resource; defaults to the root folder.
128+
129+
It can optionally start with `/`, however, no trailing slash is recommended.
130+
An empty string (``) or slash (`/`) corresponds to the root folder in Git.
131+
type: string
132+
gitSyncConf:
133+
additionalProperties:
134+
type: string
135+
default: {}
136+
description: |-
137+
A map of optional configuration settings that are listed in the git-sync [documentation].
138+
139+
Also read the git-sync [example] in our documentation. These settings are not verified.
140+
141+
[documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
142+
[example]: https://docs.stackable.tech/home/nightly/airflow/usage-guide/mounting-dags#_example
143+
type: object
144+
repo:
145+
description: 'The git repository URL that will be cloned, for example: `https://github.com/stackabletech/airflow-operator` or `ssh://git@github.com:stackable-airflow/dags.git`.'
146+
format: uri
147+
type: string
148+
wait:
149+
default: 20s
150+
description: |-
151+
The synchronization interval, e.g. `20s` or `5m`; defaults to `20s`.
152+
153+
Since git-sync v4.x.x this field is mapped to the flag `--period`.
154+
type: string
155+
required:
156+
- repo
157+
type: object
78158
hostName:
79159
type: string
80160
kerberosRealmName:
@@ -655,7 +735,7 @@ spec:
655735
default: {}
656736
description: |-
657737
In the `podOverrides` property you can define a
658-
[PodTemplateSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#podtemplatespec-v1-core)
738+
[PodTemplateSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#podtemplatespec-v1-core)
659739
to override any property that can be set on a Kubernetes Pod.
660740
Read the
661741
[Pod overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#pod-overrides)
@@ -1268,7 +1348,7 @@ spec:
12681348
default: {}
12691349
description: |-
12701350
In the `podOverrides` property you can define a
1271-
[PodTemplateSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#podtemplatespec-v1-core)
1351+
[PodTemplateSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#podtemplatespec-v1-core)
12721352
to override any property that can be set on a Kubernetes Pod.
12731353
Read the
12741354
[Pod overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#pod-overrides)
@@ -2054,6 +2134,7 @@ spec:
20542134
- clientAuthenticationDetails
20552135
- clusterOperation
20562136
- domainName
2137+
- gitSync
20572138
- hostName
20582139
- kerberosRealmName
20592140
- opaConfig

crates/stackable-operator/crds/Listener.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,20 @@ spec:
4141
default: {}
4242
description: Extra labels that the Pods must match in order to be exposed. They must _also_ still have a Volume referring to the Listener.
4343
type: object
44+
objectOverrides:
45+
default: []
46+
description: |-
47+
A list of generic Kubernetes objects, which are merged into the objects that the operator
48+
creates.
49+
50+
List entries are arbitrary YAML objects, which need to be valid Kubernetes objects.
51+
52+
Read the [Object overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#object-overrides)
53+
for more information.
54+
items:
55+
type: object
56+
x-kubernetes-preserve-unknown-fields: true
57+
type: array
4458
ports:
4559
description: Ports that should be exposed.
4660
items:

crates/stackable-operator/crds/ListenerClass.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,20 @@ spec:
106106
sophisticated LoadBalancer, that respects what Pods run on which nodes and routes traffic only
107107
to these nodes accordingly. Some cloud providers or bare metal installations do not implement
108108
some of the required features.
109+
serviceOverrides:
110+
default:
111+
apiVersion: v1
112+
kind: Service
113+
metadata: {}
114+
description: |-
115+
In the `serviceOverrides` property you can define a
116+
[Service](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#service-v1-core)
117+
to override any property that can be set on a Kubernetes Service.
118+
119+
This mechanism is similar to the `podOverrides`, which are documented in the
120+
[Pod overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#pod-overrides).
121+
type: object
122+
x-kubernetes-preserve-unknown-fields: true
109123
serviceType:
110124
description: The method used to access the services.
111125
enum:
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,10 @@
1+
use std::sync::LazyLock;
2+
3+
use crate::kvp::Label;
4+
15
pub mod secret;
6+
7+
pub static RESTART_CONTROLLER_ENABLED_LABEL: LazyLock<Label> = LazyLock::new(|| {
8+
Label::try_from(("restarter.stackable.tech/enabled", "true"))
9+
.expect("static label is always valid")
10+
});

crates/stackable-operator/src/crd/git_sync/mod.rs

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,61 +7,116 @@ use serde::{Deserialize, Serialize};
77
use stackable_shared::time::Duration;
88
use url::Url;
99

10-
use crate::versioned::versioned;
10+
use crate::{crd::git_sync::v1alpha2::Credentials, versioned::versioned};
1111

1212
mod v1alpha1_impl;
13+
mod v1alpha2_impl;
1314

14-
#[versioned(version(name = "v1alpha1"))]
15+
#[versioned(version(name = "v1alpha1"), version(name = "v1alpha2"))]
1516
pub mod versioned {
1617
pub mod v1alpha1 {
1718
pub use v1alpha1_impl::{Error, GitSyncResources};
1819
}
20+
pub mod v1alpha2 {
21+
pub use v1alpha2_impl::{Error, GitSyncResources};
22+
}
1923

2024
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Eq, Serialize)]
2125
#[serde(rename_all = "camelCase")]
2226
pub struct GitSync {
23-
/// The git repository URL that will be cloned, for example: `https://github.com/stackabletech/airflow-operator`.
27+
/// The git repository URL that will be cloned, for example: `https://github.com/stackabletech/airflow-operator` or `ssh://git@github.com:stackable-airflow/dags.git`.
2428
pub repo: Url,
2529

2630
/// The branch to clone; defaults to `main`.
2731
///
2832
/// Since git-sync v4.x.x this field is mapped to the flag `--ref`.
29-
#[serde(default = "GitSync::default_branch")]
33+
#[serde(default = "default_branch")]
3034
pub branch: String,
3135

3236
/// Location in the Git repository containing the resource; defaults to the root folder.
3337
///
3438
/// It can optionally start with `/`, however, no trailing slash is recommended.
3539
/// An empty string (``) or slash (`/`) corresponds to the root folder in Git.
36-
#[serde(default = "GitSync::default_git_folder")]
40+
#[serde(default = "default_git_folder")]
3741
pub git_folder: PathBuf,
3842

3943
/// The depth of syncing, i.e. the number of commits to clone; defaults to 1.
40-
#[serde(default = "GitSync::default_depth")]
44+
#[serde(default = "default_depth")]
4145
pub depth: u32,
4246

4347
/// The synchronization interval, e.g. `20s` or `5m`; defaults to `20s`.
4448
///
4549
/// Since git-sync v4.x.x this field is mapped to the flag `--period`.
46-
#[serde(default = "GitSync::default_wait")]
50+
#[serde(default = "default_wait")]
4751
pub wait: Duration,
4852

49-
/// The name of the Secret used to access the repository if it is not public.
53+
/// A map of optional configuration settings that are listed in the git-sync [documentation].
54+
///
55+
/// Also read the git-sync [example] in our documentation. These settings are not verified.
56+
///
57+
/// [documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
58+
/// [example]: DOCS_BASE_URL_PLACEHOLDER/airflow/usage-guide/mounting-dags#_example
59+
#[serde(default)]
60+
pub git_sync_conf: BTreeMap<String, String>,
61+
62+
/// An optional secret used for git access.
63+
#[versioned(changed(
64+
since = "v1alpha2",
65+
from_name = "credentials_secret",
66+
from_type = "Option<String>",
67+
upgrade_with = credentials_secret_to_basic_auth,
68+
downgrade_with = credentials_to_secret
69+
))]
70+
pub credentials: Option<Credentials>,
71+
}
72+
73+
#[derive(strum::Display, Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
74+
#[serde(rename_all = "camelCase")]
75+
#[schemars(rename_all = "camelCase")]
76+
pub enum Credentials {
77+
/// The name of the Secret used to access the repository via Basic Authentication if it is not public.
5078
///
5179
/// The referenced Secret must include two fields: `user` and `password`.
5280
/// The `password` field can either be an actual password (not recommended) or a GitHub token,
5381
/// as described in the git-sync [documentation].
5482
///
5583
/// [documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
56-
pub credentials_secret: Option<String>,
57-
58-
/// A map of optional configuration settings that are listed in the git-sync [documentation].
84+
BasicAuthSecretName(String),
85+
/// The name of the Secret used for SSH access to the repository.
5986
///
60-
/// Also read the git-sync [example] in our documentation. These settings are not verified.
87+
/// The referenced Secret must include two fields: `key` and `knownHosts`.
6188
///
6289
/// [documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
63-
/// [example]: DOCS_BASE_URL_PLACEHOLDER/airflow/usage-guide/mounting-dags#_example
64-
#[serde(default)]
65-
pub git_sync_conf: BTreeMap<String, String>,
90+
SshPrivateKeySecretName(String),
91+
}
92+
}
93+
94+
pub(crate) fn default_branch() -> String {
95+
"main".to_string()
96+
}
97+
98+
pub(crate) fn default_git_folder() -> PathBuf {
99+
PathBuf::from("/")
100+
}
101+
102+
pub(crate) fn default_depth() -> u32 {
103+
1
104+
}
105+
106+
pub(crate) fn default_wait() -> Duration {
107+
Duration::from_secs(20)
108+
}
109+
110+
pub fn credentials_to_secret(input: Option<Credentials>) -> Option<String> {
111+
if let Some(Credentials::BasicAuthSecretName(credentials_secret)) = input {
112+
Some(credentials_secret)
113+
} else {
114+
// We cannot downgrade SshPrivateKeySecretName as it does not map onto
115+
// anything in v1alpha1
116+
None
66117
}
67118
}
119+
120+
pub fn credentials_secret_to_basic_auth(input: Option<String>) -> Option<Credentials> {
121+
input.map(Credentials::BasicAuthSecretName)
122+
}

0 commit comments

Comments
 (0)