Skip to content

Commit e781f76

Browse files
adwk67sbernauer
andauthored
feat(stackable-operator): Support gitsync via SSH (#1121)
* add ssh key information * remove ssh_known_hosts flag and git_ssh_volume_mounts * pre-commit fix * added check for multiple credential types * changelog * add gitsync to dummy cluster * replace fields with enum * flatten enum and re-name fields * Update crates/stackable-operator/src/crd/git_sync/v1alpha1_impl.rs Co-authored-by: Sebastian Bernauer <sebastian.bernauer@stackable.de> * Update crates/stackable-operator/src/crd/git_sync/v1alpha1_impl.rs Co-authored-by: Sebastian Bernauer <sebastian.bernauer@stackable.de> * make enum untagged * make enum untagged: corrected * changelog: mark change as breaking * wip: versioning * added comment * fix/webhook): Don't crash on dropped initial_reconcile_tx channel * fix/webhook): Don't crash on dropped initial_reconcile_tx channel * changelog * changelog * corrected changelog * move default functions to non-versioned functions * corrected order in changelog --------- Co-authored-by: Sebastian Bernauer <sebastian.bernauer@stackable.de> Co-authored-by: Sebastian Bernauer <sebastian.bernauer@stackable.tech>
1 parent 4029117 commit e781f76

File tree

6 files changed

+1268
-34
lines changed

6 files changed

+1268
-34
lines changed

crates/stackable-operator/CHANGELOG.md

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

55
## [Unreleased]
66

7+
### Changed
8+
9+
- BREAKING: Add support for the SSH protocol for pulling git content ([#1121]).
10+
This is a user-facing breaking change and should also be highlighted by operators using this functionality.
11+
12+
[#1121]: https://github.com/stackabletech/operator-rs/pull/1121
13+
714
## [0.102.0] - 2026-01-14
815

916
### Added

crates/stackable-operator/crds/DummyCluster.yaml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,83 @@ 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+
description: An optional secret used for git access.
89+
nullable: true
90+
oneOf:
91+
- required:
92+
- basicAuthSecretName
93+
- required:
94+
- sshPrivateKeySecretName
95+
properties:
96+
basicAuthSecretName:
97+
description: |-
98+
The name of the Secret used to access the repository via Basic Authentication if it is not public.
99+
100+
The referenced Secret must include two fields: `user` and `password`.
101+
The `password` field can either be an actual password (not recommended) or a GitHub token,
102+
as described in the git-sync [documentation].
103+
104+
[documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
105+
type: string
106+
sshPrivateKeySecretName:
107+
description: |-
108+
The name of the Secret used for SSH access to the repository.
109+
110+
The referenced Secret must include two fields: `key` and `knownHosts`.
111+
112+
[documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
113+
type: string
114+
type: object
115+
depth:
116+
default: 1
117+
description: The depth of syncing, i.e. the number of commits to clone; defaults to 1.
118+
format: uint32
119+
minimum: 0.0
120+
type: integer
121+
gitFolder:
122+
default: /
123+
description: |-
124+
Location in the Git repository containing the resource; defaults to the root folder.
125+
126+
It can optionally start with `/`, however, no trailing slash is recommended.
127+
An empty string (``) or slash (`/`) corresponds to the root folder in Git.
128+
type: string
129+
gitSyncConf:
130+
additionalProperties:
131+
type: string
132+
default: {}
133+
description: |-
134+
A map of optional configuration settings that are listed in the git-sync [documentation].
135+
136+
Also read the git-sync [example] in our documentation. These settings are not verified.
137+
138+
[documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
139+
[example]: https://docs.stackable.tech/home/nightly/airflow/usage-guide/mounting-dags#_example
140+
type: object
141+
repo:
142+
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`.'
143+
format: uri
144+
type: string
145+
wait:
146+
default: 20s
147+
description: |-
148+
The synchronization interval, e.g. `20s` or `5m`; defaults to `20s`.
149+
150+
Since git-sync v4.x.x this field is mapped to the flag `--period`.
151+
type: string
152+
required:
153+
- repo
154+
type: object
78155
hostName:
79156
type: string
80157
kerberosRealmName:
@@ -1404,6 +1481,7 @@ spec:
14041481
- clientAuthenticationDetails
14051482
- clusterOperation
14061483
- domainName
1484+
- gitSync
14071485
- hostName
14081486
- kerberosRealmName
14091487
- opaConfig

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+
}

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

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use k8s_openapi::api::core::v1::{
44
Container, EmptyDirVolumeSource, EnvVar, EnvVarSource, SecretKeySelector, Volume, VolumeMount,
55
};
66
use snafu::{ResultExt, Snafu};
7-
use stackable_shared::time::Duration;
87
use strum::{EnumDiscriminants, IntoStaticStr};
98

109
use crate::{
@@ -42,24 +41,6 @@ pub enum Error {
4241
},
4342
}
4443

45-
impl GitSync {
46-
pub(crate) fn default_branch() -> String {
47-
"main".to_string()
48-
}
49-
50-
pub(crate) fn default_git_folder() -> PathBuf {
51-
PathBuf::from("/")
52-
}
53-
54-
pub(crate) fn default_depth() -> u32 {
55-
1
56-
}
57-
58-
pub(crate) fn default_wait() -> Duration {
59-
Duration::from_secs(20)
60-
}
61-
}
62-
6344
/// Kubernetes resources generated from `GitSync` specifications which should be added to the Pod.
6445
#[derive(Default)]
6546
pub struct GitSyncResources {

0 commit comments

Comments
 (0)