diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4812c9cae..9c7ccdda1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: '0' CARGO_PROFILE_DEV_DEBUG: '0' - RUST_TOOLCHAIN_VERSION: "1.80.0" + RUST_TOOLCHAIN_VERSION: "1.79.0" RUSTFLAGS: "-D warnings" RUSTDOCFLAGS: "-D warnings" RUST_LOG: "info" @@ -37,7 +37,7 @@ jobs: - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 with: key: udeps - - run: cargo install --locked cargo-udeps@0.1.50 + - run: cargo install --locked cargo-udeps@0.1.47 - run: cargo udeps --all-targets run_cargodeny: diff --git a/.github/workflows/pr_pre-commit.yaml b/.github/workflows/pr_pre-commit.yaml index 2582c7ea4..b5c1d1981 100644 --- a/.github/workflows/pr_pre-commit.yaml +++ b/.github/workflows/pr_pre-commit.yaml @@ -6,7 +6,7 @@ on: env: CARGO_TERM_COLOR: always - RUST_TOOLCHAIN_VERSION: "1.80.0" + RUST_TOOLCHAIN_VERSION: "1.79.0" jobs: pre-commit: diff --git a/Cargo.lock b/Cargo.lock index 885296b68..807c99955 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1541,6 +1541,7 @@ name = "k8s-version" version = "0.1.1" dependencies = [ "darling", + "lazy_static", "proc-macro2", "quote", "regex", @@ -2915,6 +2916,7 @@ dependencies = [ "json-patch", "k8s-openapi", "kube", + "lazy_static", "opentelemetry-jaeger", "opentelemetry_sdk", "product-config", diff --git a/Cargo.toml b/Cargo.toml index e2f7893f2..fed66ad0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ json-patch = "2.0.0" k8s-openapi = { version = "0.22.0", default-features = false, features = ["schemars", "v1_30"] } # We use rustls instead of openssl for easier portablitly, e.g. so that we can build stackablectl without the need to vendor (build from source) openssl kube = { version = "0.93.1", default-features = false, features = ["client", "jsonpatch", "runtime", "derive", "rustls-tls"] } +lazy_static = "1.5.0" opentelemetry = "0.23.0" opentelemetry_sdk = { version = "0.23.0", features = ["rt-tokio"] } opentelemetry-appender-tracing = "0.4.0" diff --git a/crates/k8s-version/CHANGELOG.md b/crates/k8s-version/CHANGELOG.md index aa8dd8880..339aef913 100644 --- a/crates/k8s-version/CHANGELOG.md +++ b/crates/k8s-version/CHANGELOG.md @@ -4,12 +4,6 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -### Changed - -- Replace `lazy_static` with `std::cell::LazyCell` ([#827]). - -[#827]: https://github.com/stackabletech/operator-rs/pull/827 - ## [0.1.1] - 2024-07-10 ### Changed diff --git a/crates/k8s-version/Cargo.toml b/crates/k8s-version/Cargo.toml index 09a2e381a..379304e07 100644 --- a/crates/k8s-version/Cargo.toml +++ b/crates/k8s-version/Cargo.toml @@ -11,6 +11,7 @@ darling = ["dep:darling"] [dependencies] darling = { workspace = true, optional = true } +lazy_static.workspace = true regex.workspace = true snafu.workspace = true diff --git a/crates/k8s-version/src/group.rs b/crates/k8s-version/src/group.rs index 9094b3b5e..c4d2658b8 100644 --- a/crates/k8s-version/src/group.rs +++ b/crates/k8s-version/src/group.rs @@ -1,14 +1,16 @@ -use std::{fmt, ops::Deref, str::FromStr, sync::LazyLock}; +use std::{fmt, ops::Deref, str::FromStr}; +use lazy_static::lazy_static; use regex::Regex; use snafu::{ensure, Snafu}; const MAX_GROUP_LENGTH: usize = 253; -static API_GROUP_REGEX: LazyLock = LazyLock::new(|| { - Regex::new(r"^(?:(?:[a-z0-9][a-z0-9-]{0,61}[a-z0-9])\.?)+$") - .expect("failed to compile API group regex") -}); +lazy_static! { + static ref API_GROUP_REGEX: Regex = + Regex::new(r"^(?:(?:[a-z0-9][a-z0-9-]{0,61}[a-z0-9])\.?)+$") + .expect("failed to compile API group regex"); +} /// Error variants which can be encountered when creating a new [`Group`] from /// unparsed input. diff --git a/crates/k8s-version/src/level.rs b/crates/k8s-version/src/level.rs index 823ca63f0..ae446ebe1 100644 --- a/crates/k8s-version/src/level.rs +++ b/crates/k8s-version/src/level.rs @@ -4,18 +4,19 @@ use std::{ num::ParseIntError, ops::{Add, AddAssign, Sub, SubAssign}, str::FromStr, - sync::LazyLock, }; +use lazy_static::lazy_static; use regex::Regex; use snafu::{OptionExt, ResultExt, Snafu}; #[cfg(feature = "darling")] use darling::FromMeta; -static LEVEL_REGEX: LazyLock = LazyLock::new(|| { - Regex::new(r"^(?P[a-z]+)(?P\d+)$").expect("failed to compile level regex") -}); +lazy_static! { + static ref LEVEL_REGEX: Regex = Regex::new(r"^(?P[a-z]+)(?P\d+)$") + .expect("failed to compile level regex"); +} /// Error variants which can be encountered when creating a new [`Level`] from /// unparsed input. diff --git a/crates/k8s-version/src/version.rs b/crates/k8s-version/src/version.rs index ec8d6aa6f..3a73583c7 100644 --- a/crates/k8s-version/src/version.rs +++ b/crates/k8s-version/src/version.rs @@ -1,5 +1,6 @@ -use std::{cmp::Ordering, fmt::Display, num::ParseIntError, str::FromStr, sync::LazyLock}; +use std::{cmp::Ordering, fmt::Display, num::ParseIntError, str::FromStr}; +use lazy_static::lazy_static; use regex::Regex; use snafu::{OptionExt, ResultExt, Snafu}; @@ -8,10 +9,11 @@ use darling::FromMeta; use crate::{Level, ParseLevelError}; -static VERSION_REGEX: LazyLock = LazyLock::new(|| { - Regex::new(r"^v(?P\d+)(?P[a-z0-9][a-z0-9-]{0,60}[a-z0-9])?$") - .expect("failed to compile version regex") -}); +lazy_static! { + static ref VERSION_REGEX: Regex = + Regex::new(r"^v(?P\d+)(?P[a-z0-9][a-z0-9-]{0,60}[a-z0-9])?$") + .expect("failed to compile version regex"); +} /// Error variants which can be encountered when creating a new [`Version`] from /// unparsed input. diff --git a/crates/stackable-operator/CHANGELOG.md b/crates/stackable-operator/CHANGELOG.md index 51a010ad9..bc1e9bc10 100644 --- a/crates/stackable-operator/CHANGELOG.md +++ b/crates/stackable-operator/CHANGELOG.md @@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file. - Rollout tracker for `StatefulSet` ([#833]). +### Changed + +- Reverted [#827]. + [#833]: https://github.com/stackabletech/operator-rs/pull/833 ## [0.72.0] - 2024-08-05 diff --git a/crates/stackable-operator/Cargo.toml b/crates/stackable-operator/Cargo.toml index a33a8a195..23003406a 100644 --- a/crates/stackable-operator/Cargo.toml +++ b/crates/stackable-operator/Cargo.toml @@ -24,6 +24,7 @@ futures.workspace = true json-patch.workspace = true k8s-openapi.workspace = true kube.workspace = true +lazy_static.workspace = true opentelemetry_sdk.workspace = true opentelemetry-jaeger.workspace = true product-config.workspace = true diff --git a/crates/stackable-operator/src/client.rs b/crates/stackable-operator/src/client.rs index 235c3e2eb..a49feac63 100644 --- a/crates/stackable-operator/src/client.rs +++ b/crates/stackable-operator/src/client.rs @@ -373,15 +373,15 @@ impl Client { /// There are four different patch strategies: /// 1) Apply () - /// Starting from Kubernetes v1.18, you can enable the Server Side Apply feature so that the control plane tracks managed fields for all newly created objects. + /// Starting from Kubernetes v1.18, you can enable the Server Side Apply feature so that the control plane tracks managed fields for all newly created objects. /// 2) Json (): - /// This is supported on crate feature jsonpatch only + /// This is supported on crate feature jsonpatch only /// 3) Merge (): - /// For example, if you want to update a list you have to specify the complete list and update everything + /// For example, if you want to update a list you have to specify the complete list and update everything /// 4) Strategic (not for CustomResource) - /// With a strategic merge patch, a list is either replaced or merged depending on its patch strategy. - /// The patch strategy is specified by the value of the patchStrategy key in a field tag in the Kubernetes source code. - /// For example, the Containers field of PodSpec struct has a patchStrategy of merge. + /// With a strategic merge patch, a list is either replaced or merged depending on its patch strategy. + /// The patch strategy is specified by the value of the patchStrategy key in a field tag in the Kubernetes source code. + /// For example, the Containers field of PodSpec struct has a patchStrategy of merge. async fn patch_status( &self, resource: &T, diff --git a/crates/stackable-operator/src/commons/listener.rs b/crates/stackable-operator/src/commons/listener.rs index 39b1704ae..4efbfc534 100644 --- a/crates/stackable-operator/src/commons/listener.rs +++ b/crates/stackable-operator/src/commons/listener.rs @@ -110,7 +110,7 @@ pub enum KubernetesTrafficPolicy { /// 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 -/// ["sticky" scheduling](DOCS_BASE_URL_PLACEHOLDER/listener-operator/listener#_sticky_scheduling). +/// ["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( diff --git a/crates/stackable-operator/src/commons/opa.rs b/crates/stackable-operator/src/commons/opa.rs index 5339e0148..c8d94381e 100644 --- a/crates/stackable-operator/src/commons/opa.rs +++ b/crates/stackable-operator/src/commons/opa.rs @@ -43,23 +43,15 @@ //! assert_eq!(opa_config.document_url(&cluster, Some("allow"), OpaApiVersion::V1), "v1/data/test/allow".to_string()); //! assert_eq!(opa_config.full_document_url(&cluster, "http://localhost:8081", None, OpaApiVersion::V1), "http://localhost:8081/v1/data/test".to_string()); //! ``` -use std::sync::LazyLock; - use crate::client::{Client, GetApi}; use k8s_openapi::{api::core::v1::ConfigMap, NamespaceResourceScope}; use kube::{Resource, ResourceExt}; +use lazy_static::lazy_static; use regex::Regex; use schemars::{self, JsonSchema}; use serde::{Deserialize, Serialize}; use snafu::{OptionExt, ResultExt, Snafu}; -static DOT_REGEX: LazyLock = - LazyLock::new(|| Regex::new("\\.").expect("failed to compile OPA dot regex")); - -/// To remove leading slashes from OPA package name (if present) -static LEADING_SLASH_REGEX: LazyLock = - LazyLock::new(|| Regex::new("(/*)(.*)").expect("failed to compile OPA leasing slash regex")); - type Result = std::result::Result; #[derive(Debug, Snafu)] @@ -80,6 +72,11 @@ pub enum Error { }, } +lazy_static! { + static ref DOT_REGEX: Regex = Regex::new("\\.").unwrap(); + /// To remove leading slashes from OPA package name (if present) + static ref LEADING_SLASH_REGEX: Regex = Regex::new("(/*)(.*)").unwrap(); +} /// Indicates the OPA API version. This is required to choose the correct /// path when constructing the OPA urls to query. pub enum OpaApiVersion { diff --git a/crates/stackable-operator/src/cpu.rs b/crates/stackable-operator/src/cpu.rs index 92a7a83d6..8fae864d2 100644 --- a/crates/stackable-operator/src/cpu.rs +++ b/crates/stackable-operator/src/cpu.rs @@ -101,14 +101,12 @@ impl Display for CpuQuantity { impl FromStr for CpuQuantity { type Err = Error; - /// Only two formats can be parsed: - /// + /// Only two formats can be parsed /// - {usize}m /// - {f32} - /// - /// For the float, only milli-precision is supported. Using more precise - /// values will trigger an error, and using any other unit than 'm' or None - /// will also trigger an error. + /// For the float, only milli-precision is supported. + /// Using more precise values will trigger an error, and using any other + /// unit than 'm' or None will also trigger an error. fn from_str(q: &str) -> Result { let start_of_unit = q.find(|c: char| c != '.' && !c.is_numeric()); if let Some(start_of_unit) = start_of_unit { diff --git a/crates/stackable-operator/src/kvp/key.rs b/crates/stackable-operator/src/kvp/key.rs index a7a6e0790..3defc0cfb 100644 --- a/crates/stackable-operator/src/kvp/key.rs +++ b/crates/stackable-operator/src/kvp/key.rs @@ -1,21 +1,18 @@ -use std::{fmt::Display, ops::Deref, str::FromStr, sync::LazyLock}; +use std::{fmt::Display, ops::Deref, str::FromStr}; +use lazy_static::lazy_static; use regex::Regex; use snafu::{ensure, ResultExt, Snafu}; const KEY_PREFIX_MAX_LEN: usize = 253; const KEY_NAME_MAX_LEN: usize = 63; -// Lazily initialized regular expressions -static KEY_PREFIX_REGEX: LazyLock = LazyLock::new(|| { - Regex::new(r"^[a-zA-Z](\.?[a-zA-Z0-9-])*\.[a-zA-Z]{2,}\.?$") - .expect("failed to compile key prefix regex") -}); - -static KEY_NAME_REGEX: LazyLock = LazyLock::new(|| { - Regex::new(r"^[a-z0-9A-Z]([a-z0-9A-Z-_.]*[a-z0-9A-Z]+)?$") - .expect("failed to compile key name regex") -}); +lazy_static! { + static ref KEY_PREFIX_REGEX: Regex = + Regex::new(r"^[a-zA-Z](\.?[a-zA-Z0-9-])*\.[a-zA-Z]{2,}\.?$").unwrap(); + static ref KEY_NAME_REGEX: Regex = + Regex::new(r"^[a-z0-9A-Z]([a-z0-9A-Z-_.]*[a-z0-9A-Z]+)?$").unwrap(); +} /// The error type for key parsing/validation operations. /// diff --git a/crates/stackable-operator/src/kvp/label/value.rs b/crates/stackable-operator/src/kvp/label/value.rs index 2f8610e04..4190b0545 100644 --- a/crates/stackable-operator/src/kvp/label/value.rs +++ b/crates/stackable-operator/src/kvp/label/value.rs @@ -1,5 +1,6 @@ -use std::{fmt::Display, ops::Deref, str::FromStr, sync::LazyLock}; +use std::{fmt::Display, ops::Deref, str::FromStr}; +use lazy_static::lazy_static; use regex::Regex; use snafu::{ensure, Snafu}; @@ -7,11 +8,10 @@ use crate::kvp::Value; const LABEL_VALUE_MAX_LEN: usize = 63; -// Lazily initialized regular expressions -static LABEL_VALUE_REGEX: LazyLock = LazyLock::new(|| { - Regex::new(r"^[a-z0-9A-Z]([a-z0-9A-Z-_.]*[a-z0-9A-Z]+)?$") - .expect("failed to compile value regex") -}); +lazy_static! { + static ref LABEL_VALUE_REGEX: Regex = + Regex::new(r"^[a-z0-9A-Z]([a-z0-9A-Z-_.]*[a-z0-9A-Z]+)?$").unwrap(); +} /// The error type for label value parse/validation operations. #[derive(Debug, PartialEq, Snafu)] diff --git a/crates/stackable-operator/src/memory.rs b/crates/stackable-operator/src/memory.rs index 4217a2a90..f62f5cc36 100644 --- a/crates/stackable-operator/src/memory.rs +++ b/crates/stackable-operator/src/memory.rs @@ -1,7 +1,7 @@ //! Utilities for converting Kubernetes quantities to Java heap settings. //! Since Java heap sizes are a subset of Kubernetes quantities, the conversion -//! might lose precision or fail completely. In addition: -//! +//! might lose precision or fail completely. +//! In addition: //! - decimal quantities are not supported ("2G" is invalid) //! - units are case sensitive ("2gi" is invalid) //! - exponential notation is not supported. @@ -121,15 +121,12 @@ impl Display for BinaryMultiple { } /// Convert a (memory) [`Quantity`] to Java heap settings. -/// /// Quantities are usually passed on to container resources while Java heap -/// sizes need to be scaled accordingly. This implements a very simple heuristic -/// to ensure that: -/// +/// sizes need to be scaled accordingly. +/// This implements a very simple heuristic to ensure that: /// - the quantity unit has been mapped to a java supported heap unit. Java only /// supports up to Gibibytes while K8S quantities can be expressed in Exbibytes. /// - the heap size has a non-zero value. -/// /// Fails if it can't enforce the above restrictions. #[deprecated( since = "0.33.0", @@ -151,17 +148,15 @@ pub fn to_java_heap(q: &Quantity, factor: f32) -> Result { } /// Convert a (memory) [`Quantity`] to a raw Java heap value of the desired `target_unit`. -/// /// Quantities are usually passed on to container resources while Java heap -/// sizes need to be scaled accordingly. The raw heap value is converted to the -/// specified `target_unit` (this conversion is done even if specified a unit -/// greater that Gibibytes. It is not recommended to scale to anything bigger -/// than Gibibytes. This implements a very simple heuristic to ensure that: -/// +/// sizes need to be scaled accordingly. +/// The raw heap value is converted to the specified `target_unit` (this conversion +/// is done even if specified a unit greater that Gibibytes. It is not recommended to scale +/// to anything bigger than Gibibytes. +/// This implements a very simple heuristic to ensure that: /// - the quantity unit has been mapped to a java supported heap unit. Java only /// supports up to Gibibytes while K8S quantities can be expressed in Exbibytes. /// - the heap size has a non-zero value. -/// /// Fails if it can't enforce the above restrictions. #[deprecated( since = "0.33.0", diff --git a/crates/stackable-operator/src/status/condition/mod.rs b/crates/stackable-operator/src/status/condition/mod.rs index a356c323e..026686312 100644 --- a/crates/stackable-operator/src/status/condition/mod.rs +++ b/crates/stackable-operator/src/status/condition/mod.rs @@ -290,20 +290,16 @@ impl ClusterConditionSet { self.conditions[index] = Some(condition); } - /// Merges two [`ClusterConditionSet`]s. - /// - /// The condition_combiner implements the strategy used to merge two - /// conditions of the same `type_`. + /// Merges two [`ClusterConditionSet`]s. The condition_combiner implements the strategy used to + /// merge two conditions of the same `type_`. /// /// # Arguments /// /// * `other` - The [`ClusterConditionSet`] to be merged - /// * `condition_combiner` - This is either be `update_message` or - /// `update_timestamps`. The `update_message` is used to concatenate - /// messages of the same [`ClusterConditionStatus`] and the same - /// [`ClusterConditionType`]. The `update_timestamps` is required to merge - /// the old cluster status with the new one and update transition - /// timestamps correctly. + /// * `condition_combiner` - This is either be `update_message` or `update_timestamps`. The + /// `update_message` is used to concatenate messages of the same [`ClusterConditionStatus`] and + /// the same [`ClusterConditionType`]. The `update_timestamps` is required to merge the old + /// cluster status with the new one and update transition timestamps correctly. fn merge( self, other: ClusterConditionSet, @@ -365,7 +361,7 @@ fn update_timestamps( /// A condition combiner strategy with the following properties: /// 1. It preserves the condition with the highest status. /// 2. It joins the previous messages to the current one if both conditions -/// have the same status. +/// have the same status. fn update_message( old_condition: ClusterCondition, new_condition: ClusterCondition, diff --git a/crates/stackable-operator/src/validation.rs b/crates/stackable-operator/src/validation.rs index 1c253b157..969b61cd0 100644 --- a/crates/stackable-operator/src/validation.rs +++ b/crates/stackable-operator/src/validation.rs @@ -9,9 +9,8 @@ // This is adapted from Kubernetes. // See apimachinery/pkg/util/validation/validation.go, apimachinery/pkg/api/validation/generic.go and pkg/apis/core/validation/validation.go in the Kubernetes source -use std::sync::LazyLock; - use const_format::concatcp; +use lazy_static::lazy_static; use regex::Regex; const RFC_1123_LABEL_FMT: &str = "[a-z0-9]([-a-z0-9]*[a-z0-9])?"; @@ -31,15 +30,14 @@ const RFC_1035_LABEL_ERR_MSG: &str = "a DNS-1035 label must consist of lower cas // This is a label's max length in DNS (RFC 1035) const RFC_1035_LABEL_MAX_LENGTH: usize = 63; -// Lazily initialized regular expressions -static RFC_1123_SUBDOMAIN_REGEX: LazyLock = LazyLock::new(|| { - Regex::new(&format!("^{RFC_1123_SUBDOMAIN_FMT}$")) - .expect("failed to compile RFC 1123 subdomain regex") -}); - -static RFC_1035_LABEL_REGEX: LazyLock = LazyLock::new(|| { - Regex::new(&format!("^{RFC_1035_LABEL_FMT}$")).expect("failed to compile RFC 1035 label regex") -}); +lazy_static! { + static ref RFC_1123_SUBDOMAIN_REGEX: Regex = + Regex::new(&format!("^{RFC_1123_SUBDOMAIN_FMT}$")).unwrap(); + static ref RFC_1123_LABEL_REGEX: Regex = + Regex::new(&format!("^{RFC_1123_SUBDOMAIN_FMT}$")).unwrap(); + static ref RFC_1035_LABEL_REGEX: Regex = + Regex::new(&format!("^{RFC_1035_LABEL_FMT}$")).unwrap(); +} /// Returns a formatted error message for maximum length violations. fn max_len_error(length: usize) -> String { diff --git a/crates/stackable-telemetry/src/instrumentation/axum/mod.rs b/crates/stackable-telemetry/src/instrumentation/axum/mod.rs index 5b88c437b..e621f16df 100644 --- a/crates/stackable-telemetry/src/instrumentation/axum/mod.rs +++ b/crates/stackable-telemetry/src/instrumentation/axum/mod.rs @@ -199,8 +199,8 @@ pub trait RequestExt { /// section of the HTTP span semantic conventions: /// /// > HTTP server instrumentations SHOULD do the best effort when populating - /// > server.address and server.port attributes and SHOULD determine them by - /// > using the first of the following that applies: + /// server.address and server.port attributes and SHOULD determine them by + /// using the first of the following that applies: /// > /// > - The original host which may be passed by the reverse proxy in the /// > Forwarded#host, X-Forwarded-Host, or a similar header. diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 4d2dee853..628740b12 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.80.0" +channel = "1.79.0"