Skip to content

Feat: More CRD docs #697

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Dec 12, 2023
Merged
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Added

- More CRD documentation ([#697]).

[#697]: https://github.com/stackabletech/operator-rs/pull/697

## [0.58.0] - 2023-12-04

### Added
Expand Down
14 changes: 7 additions & 7 deletions src/commons/authentication/ldap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,28 @@ use crate::{
#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthenticationProvider {
/// Hostname of the LDAP server
/// Hostname of the LDAP server, for example: `my.ldap.server`.
pub hostname: String,

/// Port of the LDAP server. If TLS is used defaults to 636 otherwise to 389
/// Port of the LDAP server. If TLS is used defaults to 636 otherwise to 389.
port: Option<u16>,

/// LDAP search base
/// LDAP search base, for example: `ou=users,dc=example,dc=org`.
#[serde(default)]
pub search_base: String,

/// LDAP query to filter users
/// LDAP query to filter users, for example: `(memberOf=cn=myTeam,ou=teams,dc=example,dc=org)`.
#[serde(default)]
pub search_filter: String,

/// The name of the LDAP object fields
/// The name of the LDAP object fields.
#[serde(default)]
pub ldap_field_names: FieldNames,

/// In case you need a special account for searching the LDAP server you can specify it here
/// In case you need a special account for searching the LDAP server you can specify it here.
bind_credentials: Option<SecretClassVolume>,

/// Use a TLS connection. If not specified no TLS will be used
/// Use a TLS connection. If not specified no TLS will be used.
#[serde(flatten)]
pub tls: TlsClientDetails,
}
Expand Down
18 changes: 17 additions & 1 deletion src/commons/authentication/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ pub mod tls;

pub(crate) const SECRET_BASE_PATH: &str = "/stackable/secrets";

/// The Stackable Platform uses the AuthenticationClass as a central mechanism to handle user authentication across supported products.
/// The authentication mechanism needs to be configured only in the AuthenticationClass which is then referenced in the product.
/// Multiple different authentication providers are supported.
/// Learn more in the [authentication concept documentation](DOCS_BASE_URL_PLACEHOLDER/concepts/authentication) and the
/// [Authentication with OpenLDAP tutorial](DOCS_BASE_URL_PLACEHOLDER/tutorials/authentication_with_openldap).
#[derive(Clone, CustomResource, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[kube(
group = "authentication.stackable.tech",
Expand All @@ -29,17 +34,28 @@ pub(crate) const SECRET_BASE_PATH: &str = "/stackable/secrets";
)]
#[serde(rename_all = "camelCase")]
pub struct AuthenticationClassSpec {
/// Provider used for authentication like LDAP or Kerberos
/// Provider used for authentication like LDAP or Kerberos.
pub provider: AuthenticationClassProvider,
}

#[derive(Clone, Debug, Deserialize, Display, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
#[allow(clippy::large_enum_variant)]
pub enum AuthenticationClassProvider {
/// The [static provider](https://DOCS_BASE_URL_PLACEHOLDER/concepts/authentication#_static) is used to configure a
/// static set of users, identified by username and password.
Static(static_::AuthenticationProvider),

/// The [LDAP provider](DOCS_BASE_URL_PLACEHOLDER/concepts/authentication#_ldap).
/// There is also the ["Authentication with LDAP" tutorial](DOCS_BASE_URL_PLACEHOLDER/tutorials/authentication_with_openldap)
/// where you can learn to configure Superset and Trino with OpenLDAP.
Ldap(ldap::AuthenticationProvider),

/// The OIDC provider can be used to configure OpenID Connect.
Oidc(oidc::AuthenticationProvider),

/// The [TLS provider](DOCS_BASE_URL_PLACEHOLDER/concepts/authentication#_tls).
/// The TLS AuthenticationClass is used when users should authenticate themselves with a TLS certificate.
Tls(tls::AuthenticationProvider),
}

Expand Down
8 changes: 4 additions & 4 deletions src/commons/authentication/oidc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ pub struct AuthenticationProvider {
/// Hostname of the identity provider, e.g. `my.keycloak.corp`.
hostname: String,

/// Port of the identity provider. If TLS is used defaults to `443`,
/// otherwise to `80`.
/// Port of the identity provider. If TLS is used defaults to 443,
/// otherwise to 80.
port: Option<u16>,

/// Root HTTP path of the identity provider. Defaults to `/`.
Expand Down Expand Up @@ -74,9 +74,9 @@ pub struct AuthenticationProvider {
pub scopes: Vec<String>,

/// This is a hint about which identity provider is used by the
/// [`AuthenticationClass`]. Operators *can* opt to use this
/// AuthenticationClass. Operators *can* opt to use this
/// value to enable known quirks around OIDC / OAuth authentication.
/// [`None`] means there is no hint and OIDC should be used as it is
/// Not providing a hint means there is no hint and OIDC should be used as it is
/// intended to be used (via the `.well-known` discovery).
#[serde(default)]
pub provider_hint: Option<IdentityProviderHint>,
Expand Down
6 changes: 3 additions & 3 deletions src/commons/authentication/static_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthenticationProvider {
/// Secret providing the usernames and password.
/// The secret must contain an entry for every user, with the key being the username and the value the password in plain text.
/// Secret providing the usernames and passwords.
/// The Secret must contain an entry for every user, with the key being the username and the value the password in plain text.
/// It must be located in the same namespace as the product using it.
pub user_credentials_secret: UserCredentialsSecretRef,
}

#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UserCredentialsSecretRef {
/// Name of the secret
/// Name of the Secret.
pub name: String,
}
22 changes: 11 additions & 11 deletions src/commons/authentication/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ use crate::{
#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthenticationProvider {
/// See `<https://docs.stackable.tech/home/contributor/adr/ADR016-tls-authentication.html>`.
/// See [ADR017: TLS authentication](DOCS_BASE_URL_PLACEHOLDER/contributor/adr/adr017-tls_authentication).
/// If `client_cert_secret_class` is not set, the TLS settings may also be used for client authentication.
/// If `client_cert_secret_class` is set, the [SecretClass](https://docs.stackable.tech/secret-operator/secretclass.html)
/// If `client_cert_secret_class` is set, the [SecretClass](DOCS_BASE_URL_PLACEHOLDER/secret-operator/secretclass)
/// will be used to provision client certificates.
pub client_cert_secret_class: Option<String>,
}

#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TlsClientDetails {
/// Use a TLS connection. If not specified no TLS will be used
/// Use a TLS connection. If not specified no TLS will be used.
pub tls: Option<Tls>,
}

Expand Down Expand Up @@ -108,36 +108,36 @@ impl TlsClientDetails {
#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Tls {
/// The verification method used to verify the certificates of the server and/or the client
/// The verification method used to verify the certificates of the server and/or the client.
pub verification: TlsVerification,
}

#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum TlsVerification {
/// Use TLS but don't verify certificates
/// Use TLS but don't verify certificates.
None {},

/// Use TLS and ca certificate to verify the server
/// Use TLS and a CA certificate to verify the server.
Server(TlsServerVerification),
}

#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TlsServerVerification {
/// Ca cert to verify the server
/// CA cert to verify the server.
pub ca_cert: CaCert,
}

#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum CaCert {
/// Use TLS and the ca certificates trusted by the common web browsers to verify the server.
/// Use TLS and the CA certificates trusted by the common web browsers to verify the server.
/// This can be useful when you e.g. use public AWS S3 or other public available services.
WebPki {},

/// Name of the SecretClass which will provide the ca cert.
/// Note that a SecretClass does not need to have a key but can also work with just a ca cert.
/// So if you got provided with a ca cert but don't have access to the key you can still use this method.
/// Name of the [SecretClass](DOCS_BASE_URL_PLACEHOLDER/secret-operator/secretclass) which will provide the CA certificate.
/// Note that a SecretClass does not need to have a key but can also work with just a CA certificate,
/// so if you got provided with a CA cert but don't have access to the key you can still use this method.
SecretClass(String),
}
57 changes: 33 additions & 24 deletions src/commons/listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ use k8s_openapi::api::core::v1::{
#[cfg(doc)]
use crate::builder::ListenerOperatorVolumeSourceBuilder;

/// Defines a policy for how [`Listener`]s should be exposed.
/// Defines a policy for how [Listeners](DOCS_BASE_URL_PLACEHOLDER/listener-operator/listener) should be exposed.
/// Read the [ListenerClass documentation](DOCS_BASE_URL_PLACEHOLDER/listener-operator/listenerclass)
/// for more information.
#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq, Eq)]
#[kube(
group = "listeners.stackable.tech",
Expand All @@ -49,7 +51,8 @@ use crate::builder::ListenerOperatorVolumeSourceBuilder;
#[serde(rename_all = "camelCase")]
pub struct ListenerClassSpec {
pub service_type: ServiceType,
/// Annotations that should be added to the [`Service`] object.

/// Annotations that should be added to the Service object.
#[serde(default)]
pub service_annotations: BTreeMap<String, String>,
}
Expand All @@ -67,10 +70,13 @@ pub enum ServiceType {

/// Exposes a set of pods to the outside world.
///
/// Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes three things:
/// 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works
/// Essentially a Stackable extension of a Kubernetes Service. Compared to a Service, a Listener changes three things:
/// 1. It uses a cluster-level policy object (ListenerClass) to define how exactly the exposure works
/// 2. It has a consistent API for reading back the exposed address(es) of the service
/// 3. The [`Pod`] must mount a [`Volume`] referring to the `Listener`, which also allows us to control stickiness
/// 3. The Pod must mount a Volume referring to the Listener, which also allows
/// ["sticky" scheduling](DOCS_BASE_URL_PLACEHOLDER/listener-operator/listener#_sticky_scheduling).
///
/// Learn more in the [Listener documentation](DOCS_BASE_URL_PLACEHOLDER/listener-operator/listener).
#[derive(
CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq, Eq,
)]
Expand All @@ -83,14 +89,17 @@ pub enum ServiceType {
)]
#[serde(rename_all = "camelCase")]
pub struct ListenerSpec {
/// The name of the [`ListenerClass`].
/// The name of the [ListenerClass](DOCS_BASE_URL_PLACEHOLDER/listener-operator/listenerclass).
pub class_name: Option<String>,
/// Extra labels that the [`Pod`]s must match in order to be exposed. They must _also_ still have a `Volume` referring to the listener.

/// Extra labels that the Pods must match in order to be exposed. They must _also_ still have a Volume referring to the Listener.
#[serde(default)]
pub extra_pod_selector_labels: BTreeMap<String, String>,

/// Ports that should be exposed.
pub ports: Option<Vec<ListenerPort>>,
/// Whether incoming traffic should also be directed to `Pod`s that are not `Ready`.

/// Whether incoming traffic should also be directed to Pods that are not `Ready`.
#[schemars(default = "Self::default_publish_not_ready_addresses")]
pub publish_not_ready_addresses: Option<bool>,
}
Expand All @@ -106,34 +115,34 @@ impl ListenerSpec {
pub struct ListenerPort {
/// The name of the port.
///
/// The name of each port *must* be unique within a single [`Listener`].
/// The name of each port *must* be unique within a single Listener.
pub name: String,
/// The port number.
pub port: i32,
/// The layer-4 protocol (`TCP` or `UDP`).
pub protocol: Option<String>,
}

/// Informs users about how to reach the [`Listener`].
/// Informs users about how to reach the Listener.
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct ListenerStatus {
/// The backing Kubernetes [`Service`].
/// The backing Kubernetes Service.
pub service_name: Option<String>,
/// All addresses that the [`Listener`] is currently reachable from.
/// All addresses that the Listener is currently reachable from.
pub ingress_addresses: Option<Vec<ListenerIngress>>,
/// Port mappings for accessing the [`Listener`] on each [`Node`] that the [`Pod`]s are currently running on.
/// Port mappings for accessing the Listener on each Node that the Pods are currently running on.
///
/// This is only intended for internal use by listener-operator itself. This will be left unset if using a [`ListenerClass`] that does
/// not require [`Node`]-local access.
/// This is only intended for internal use by listener-operator itself. This will be left unset if using a ListenerClass that does
/// not require Node-local access.
pub node_ports: Option<BTreeMap<String, i32>>,
}

/// One address that a [`Listener`] is accessible from.
/// One address that a Listener is accessible from.
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct ListenerIngress {
/// The hostname or IP address to the [`Listener`].
/// The hostname or IP address to the Listener.
pub address: String,
/// The type of address (`Hostname` or `IP`).
pub address_type: AddressType,
Expand All @@ -149,7 +158,7 @@ pub enum AddressType {
Ip,
}

/// Informs users about [`Listener`]s that are bound by a given [`Pod`].
/// Informs users about Listeners that are bound by a given Pod.
///
/// This is not expected to be created or modified by users. It will be created by
/// the Stackable Listener Operator when mounting the listener volume, and is always
Expand All @@ -166,22 +175,22 @@ pub enum AddressType {
)]
#[serde(rename_all = "camelCase")]
pub struct PodListenersSpec {
/// All listeners currently bound by the [`Pod`].
/// All Listeners currently bound by the Pod.
///
/// Indexed by [`Volume`] name (not [`PersistentVolume`] or [`PersistentVolumeClaim`]).
/// Indexed by Volume name (not PersistentVolume or PersistentVolumeClaim).
pub listeners: BTreeMap<String, PodListener>,
}

#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct PodListener {
/// `Node` if this address only allows access to [`Pod`]s hosted on a specific Kubernetes [`Node`], otherwise `Cluster`.
/// `Node` if this address only allows access to Pods hosted on a specific Kubernetes Node, otherwise `Cluster`.
pub scope: PodListenerScope,
/// Addresses allowing access to this [`Pod`].
/// Addresses allowing access to this Pod.
///
/// Compared to [`ListenerStatus::ingress_addresses`], this list is restricted to addresses that can access this [`Pod`].
/// Compared to `ingress_addresses` on the Listener status, this list is restricted to addresses that can access this Pod.
///
/// This field is intended to be equivalent to the files mounted into the listener volume.
/// This field is intended to be equivalent to the files mounted into the Listener volume.
pub ingress_addresses: Option<Vec<ListenerIngress>>,
}

Expand Down
10 changes: 6 additions & 4 deletions src/commons/s3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use crate::{
error::{self, OperatorResult},
};

/// S3 bucket specification containing only the bucket name and an inlined or
/// referenced connection specification.
/// S3 bucket specification containing the bucket name and an inlined or referenced connection specification.
/// Learn more on the [S3 concept documentation](DOCS_BASE_URL_PLACEHOLDER/concepts/s3).
#[derive(
Clone, CustomResource, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize,
)]
Expand Down Expand Up @@ -153,7 +153,8 @@ impl S3ConnectionDef {
}
}

/// S3 connection definition as CRD.
/// S3 connection definition as a resource.
/// Learn more on the [S3 concept documentation](DOCS_BASE_URL_PLACEHOLDER/concepts/s3).
#[derive(
CustomResource, Clone, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize,
)]
Expand Down Expand Up @@ -189,7 +190,8 @@ pub struct S3ConnectionSpec {
pub access_style: Option<S3AccessStyle>,

/// If the S3 uses authentication you have to specify you S3 credentials.
/// In the most cases a SecretClass providing `accessKey` and `secretKey` is sufficient.
/// In the most cases a [SecretClass](DOCS_BASE_URL_PLACEHOLDER/secret-operator/secretclass)
/// providing `accessKey` and `secretKey` is sufficient.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub credentials: Option<SecretClassVolume>,

Expand Down
Loading