Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions crates/stackable-operator/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ All notable changes to this project will be documented in this file.

- BREAKING: `ClusterResources` now requires the objects added to implement `DeepMerge`.
This is very likely a stackable-operator internal change, but technically breaking ([#1118]).
- BREAKING: Add support for the SSH protocol for pulling git content ([#1121]).
This is a user-facing breaking change and should also be highlighted by operators using this functionality.
- Depend on the patched version of kube-rs available at <https://github.com/stackabletech/kube-rs>,
ensuring the operators automatically benefit from the fixes ([#1124]).

Expand All @@ -21,6 +23,7 @@ All notable changes to this project will be documented in this file.
- BREAKING: `ClusterResources` no longer derives `Eq` ([#1118]).

[#1118]: https://github.com/stackabletech/operator-rs/pull/1118
[#1121]: https://github.com/stackabletech/operator-rs/pull/1121
[#1124]: https://github.com/stackabletech/operator-rs/pull/1124

## [0.100.3] - 2025-10-31
Expand Down
78 changes: 78 additions & 0 deletions crates/stackable-operator/crds/DummyCluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,83 @@ spec:
domainName:
description: A validated domain name type conforming to RFC 1123, so e.g. not an IP address
type: string
gitSync:
properties:
branch:
default: main
description: |-
The branch to clone; defaults to `main`.

Since git-sync v4.x.x this field is mapped to the flag `--ref`.
type: string
credentials:
description: An optional secret used for git access.
nullable: true
oneOf:
- required:
- basicAuthSecretName
- required:
- sshPrivateKeySecretName
properties:
basicAuthSecretName:
description: |-
The name of the Secret used to access the repository via Basic Authentication if it is not public.

The referenced Secret must include two fields: `user` and `password`.
The `password` field can either be an actual password (not recommended) or a GitHub token,
as described in the git-sync [documentation].

[documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
type: string
sshPrivateKeySecretName:
description: |-
The name of the Secret used for SSH access to the repository.

The referenced Secret must include two fields: `key` and `knownHosts`.

[documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
type: string
type: object
depth:
default: 1
description: The depth of syncing, i.e. the number of commits to clone; defaults to 1.
format: uint32
minimum: 0.0
type: integer
gitFolder:
default: /
description: |-
Location in the Git repository containing the resource; defaults to the root folder.

It can optionally start with `/`, however, no trailing slash is recommended.
An empty string (``) or slash (`/`) corresponds to the root folder in Git.
type: string
gitSyncConf:
additionalProperties:
type: string
default: {}
description: |-
A map of optional configuration settings that are listed in the git-sync [documentation].

Also read the git-sync [example] in our documentation. These settings are not verified.

[documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
[example]: https://docs.stackable.tech/home/nightly/airflow/usage-guide/mounting-dags#_example
type: object
repo:
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`.'
format: uri
type: string
wait:
default: 20s
description: |-
The synchronization interval, e.g. `20s` or `5m`; defaults to `20s`.

Since git-sync v4.x.x this field is mapped to the flag `--period`.
type: string
required:
- repo
type: object
hostName:
type: string
kerberosRealmName:
Expand Down Expand Up @@ -1402,6 +1479,7 @@ spec:
- clientAuthenticationDetails
- clusterOperation
- domainName
- gitSync
- hostName
- kerberosRealmName
- opaConfig
Expand Down
67 changes: 52 additions & 15 deletions crates/stackable-operator/src/crd/git_sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,61 +7,98 @@ use serde::{Deserialize, Serialize};
use stackable_shared::time::Duration;
use url::Url;

use crate::versioned::versioned;
use crate::{crd::git_sync::v1alpha2::Credentials, versioned::versioned};

mod v1alpha1_impl;
mod v1alpha2_impl;

#[versioned(version(name = "v1alpha1"))]
#[versioned(version(name = "v1alpha1"), version(name = "v1alpha2"))]
pub mod versioned {
pub mod v1alpha1 {
pub use v1alpha1_impl::{Error, GitSyncResources};
}
pub mod v1alpha2 {
pub use v1alpha2_impl::{Error, GitSyncResources};
}

#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GitSync {
/// The git repository URL that will be cloned, for example: `https://github.com/stackabletech/airflow-operator`.
/// 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`.
pub repo: Url,

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

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

/// The depth of syncing, i.e. the number of commits to clone; defaults to 1.
#[serde(default = "GitSync::default_depth")]
#[serde(default = "v1alpha2::GitSync::default_depth")]
pub depth: u32,

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

/// The name of the Secret used to access the repository if it is not public.
/// A map of optional configuration settings that are listed in the git-sync [documentation].
///
/// Also read the git-sync [example] in our documentation. These settings are not verified.
///
/// [documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
/// [example]: DOCS_BASE_URL_PLACEHOLDER/airflow/usage-guide/mounting-dags#_example
#[serde(default)]
pub git_sync_conf: BTreeMap<String, String>,

/// An optional secret used for git access.
#[versioned(changed(
since = "v1alpha2",
from_name = "credentials_secret",
from_type = "Option<String>",
upgrade_with = credentials_secret_to_basic_auth,
downgrade_with = credentials_to_secret
))]
pub credentials: Option<Credentials>,
}

#[derive(strum::Display, Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
#[schemars(rename_all = "camelCase")]
pub enum Credentials {
/// The name of the Secret used to access the repository via Basic Authentication if it is not public.
///
/// The referenced Secret must include two fields: `user` and `password`.
/// The `password` field can either be an actual password (not recommended) or a GitHub token,
/// as described in the git-sync [documentation].
///
/// [documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
pub credentials_secret: Option<String>,

/// A map of optional configuration settings that are listed in the git-sync [documentation].
BasicAuthSecretName(String),
/// The name of the Secret used for SSH access to the repository.
///
/// Also read the git-sync [example] in our documentation. These settings are not verified.
/// The referenced Secret must include two fields: `key` and `knownHosts`.
///
/// [documentation]: https://github.com/kubernetes/git-sync/tree/v4.2.4?tab=readme-ov-file#manual
/// [example]: DOCS_BASE_URL_PLACEHOLDER/airflow/usage-guide/mounting-dags#_example
#[serde(default)]
pub git_sync_conf: BTreeMap<String, String>,
SshPrivateKeySecretName(String),
}
}

pub fn credentials_to_secret(input: Option<Credentials>) -> Option<String> {
if let Some(Credentials::BasicAuthSecretName(credentials_secret)) = input {
Some(credentials_secret)
} else {
None
}
}

pub fn credentials_secret_to_basic_auth(input: Option<String>) -> Option<Credentials> {
input.map(Credentials::BasicAuthSecretName)
}
19 changes: 0 additions & 19 deletions crates/stackable-operator/src/crd/git_sync/v1alpha1_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use k8s_openapi::api::core::v1::{
Container, EmptyDirVolumeSource, EnvVar, EnvVarSource, SecretKeySelector, Volume, VolumeMount,
};
use snafu::{ResultExt, Snafu};
use stackable_shared::time::Duration;
use strum::{EnumDiscriminants, IntoStaticStr};

use crate::{
Expand Down Expand Up @@ -42,24 +41,6 @@ pub enum Error {
},
}

impl GitSync {
pub(crate) fn default_branch() -> String {
"main".to_string()
}

pub(crate) fn default_git_folder() -> PathBuf {
PathBuf::from("/")
}

pub(crate) fn default_depth() -> u32 {
1
}

pub(crate) fn default_wait() -> Duration {
Duration::from_secs(20)
}
}

/// Kubernetes resources generated from `GitSync` specifications which should be added to the Pod.
#[derive(Default)]
pub struct GitSyncResources {
Expand Down
Loading