diff --git a/Cargo.lock b/Cargo.lock index bab77ee4db3b..44d4980e1d22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -550,6 +550,18 @@ dependencies = [ "term", ] +[[package]] +name = "async-broadcast" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" +dependencies = [ + "event-listener 5.3.1", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -763,7 +775,7 @@ dependencies = [ "bitflags 1.3.2", "bytes", "futures-util", - "headers", + "headers 0.3.9", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.29", @@ -815,6 +827,17 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "backoff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +dependencies = [ + "getrandom", + "instant", + "rand", +] + [[package]] name = "backon" version = "0.4.4" @@ -3313,6 +3336,17 @@ dependencies = [ "serde", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive-new" version = "0.5.9" @@ -3889,6 +3923,15 @@ dependencies = [ "tonic 0.11.0", ] +[[package]] +name = "fluent-uri" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "fnv" version = "1.0.7" @@ -4345,13 +4388,28 @@ checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ "base64 0.21.7", "bytes", - "headers-core", + "headers-core 0.2.0", "http 0.2.12", "httpdate", "mime", "sha1", ] +[[package]] +name = "headers" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" +dependencies = [ + "base64 0.21.7", + "bytes", + "headers-core 0.3.0", + "http 1.1.0", + "httpdate", + "mime", + "sha1", +] + [[package]] name = "headers-core" version = "0.2.0" @@ -4361,6 +4419,15 @@ dependencies = [ "http 0.2.12", ] +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http 1.1.0", +] + [[package]] name = "heck" version = "0.4.1" @@ -4691,6 +4758,26 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-http-proxy" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d06dbdfbacf34d996c6fb540a71a684a7aae9056c71951163af8a8a4c07b9a4" +dependencies = [ + "bytes", + "futures-util", + "headers 0.4.0", + "http 1.1.0", + "hyper 1.3.1", + "hyper-rustls 0.27.2", + "hyper-util", + "pin-project-lite", + "rustls-native-certs", + "tokio", + "tokio-rustls 0.26.0", + "tower-service", +] + [[package]] name = "hyper-rustls" version = "0.26.0" @@ -4708,6 +4795,25 @@ dependencies = [ "tower-service", ] +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.3.1", + "hyper-util", + "log", + "rustls 0.23.10", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", + "tower-service", +] + [[package]] name = "hyper-timeout" version = "0.4.1" @@ -4720,6 +4826,19 @@ dependencies = [ "tokio-io-timeout", ] +[[package]] +name = "hyper-timeout" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +dependencies = [ + "hyper 1.3.1", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.5" @@ -5187,6 +5306,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json-patch" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b1fb8864823fad91877e6caea0baca82e49e8db50f8e5c9f9a453e27d3330fc" +dependencies = [ + "jsonptr", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "json5" version = "0.4.1" @@ -5198,6 +5329,32 @@ dependencies = [ "serde", ] +[[package]] +name = "jsonpath-rust" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d8fe85bd70ff715f31ce8c739194b423d79811a19602115d611a3ec85d6200" +dependencies = [ + "lazy_static", + "once_cell", + "pest", + "pest_derive", + "regex", + "serde_json", + "thiserror", +] + +[[package]] +name = "jsonptr" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c6e529149475ca0b2820835d3dce8fcc41c6b943ca608d32f35b449255e4627" +dependencies = [ + "fluent-uri", + "serde", + "serde_json", +] + [[package]] name = "jsonwebtoken" version = "9.3.0" @@ -5213,6 +5370,19 @@ dependencies = [ "simple_asn1", ] +[[package]] +name = "k8s-openapi" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19501afb943ae5806548bc3ebd7f3374153ca057a38f480ef30adfde5ef09755" +dependencies = [ + "base64 0.22.1", + "chrono", + "serde", + "serde-value", + "serde_json", +] + [[package]] name = "keccak" version = "0.1.5" @@ -5251,6 +5421,115 @@ dependencies = [ "libc", ] +[[package]] +name = "kube" +version = "0.92.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12dc4487eda98835dcaa7ac92a14165446db29dbd67a743c79fe9f41bf38ee72" +dependencies = [ + "k8s-openapi", + "kube-client", + "kube-core", + "kube-derive", + "kube-runtime", +] + +[[package]] +name = "kube-client" +version = "0.92.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "408f35eab36927d3b883e4ad54c3080ea8c49f899ac84a7856e7182e4ee3b392" +dependencies = [ + "base64 0.22.1", + "bytes", + "chrono", + "either", + "futures", + "home", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", + "hyper-http-proxy", + "hyper-rustls 0.27.2", + "hyper-timeout 0.5.1", + "hyper-util", + "jsonpath-rust", + "k8s-openapi", + "kube-core", + "pem", + "rustls 0.23.10", + "rustls-pemfile 2.1.2", + "secrecy", + "serde", + "serde_json", + "serde_yaml", + "thiserror", + "tokio", + "tokio-util", + "tower", + "tower-http 0.5.2", + "tracing", +] + +[[package]] +name = "kube-core" +version = "0.92.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f776624097c1e09e72eb1e9e0c2bb5d17d97c27a6a87734390a9fba246a8f67f" +dependencies = [ + "chrono", + "form_urlencoded", + "http 1.1.0", + "json-patch", + "k8s-openapi", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "kube-derive" +version = "0.92.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae07adfd7d21b7fa582789206391243f98e155b46c806eb494839569853bcfd" +dependencies = [ + "darling 0.20.9", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.66", +] + +[[package]] +name = "kube-runtime" +version = "0.92.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12e5933f2d429f3a05d4cb67f935b25c94a133b0baeb558ab3917c270a11f6ef" +dependencies = [ + "ahash 0.8.11", + "async-broadcast", + "async-stream", + "async-trait", + "backoff", + "derivative", + "futures", + "hashbrown 0.14.5", + "json-patch", + "jsonptr", + "k8s-openapi", + "kube-client", + "parking_lot 0.12.3", + "pin-project", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "lalrpop" version = "0.19.12" @@ -8594,7 +8873,7 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-rustls", + "hyper-rustls 0.26.0", "hyper-util", "ipnet", "js-sys", @@ -9037,6 +9316,21 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "log", + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki 0.102.4", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.7.0" @@ -9658,6 +9952,16 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "serde", + "zeroize", +] + [[package]] name = "security-framework" version = "2.11.0" @@ -9705,6 +10009,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float 2.10.1", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.203" @@ -9879,7 +10193,7 @@ dependencies = [ "derive_builder 0.12.0", "futures", "hashbrown 0.14.5", - "headers", + "headers 0.3.9", "hostname", "http 0.2.12", "http-body 0.4.6", @@ -9936,7 +10250,7 @@ dependencies = [ "tonic 0.11.0", "tonic-reflection", "tower", - "tower-http", + "tower-http 0.4.4", "urlencoding", "uuid", "zstd 0.13.1", @@ -10998,6 +11312,8 @@ dependencies = [ "datatypes", "derive_builder 0.12.0", "dotenv", + "k8s-openapi", + "kube", "lazy_static", "libfuzzer-sys", "nix 0.28.0", @@ -11005,8 +11321,10 @@ dependencies = [ "rand", "rand_chacha", "reqwest", + "schemars", "serde", "serde_json", + "serde_yaml", "snafu 0.8.3", "sql", "sqlparser 0.45.0 (git+https://github.com/GreptimeTeam/sqlparser-rs.git?rev=54a267ac89c09b11c0c88934690530807185d3e7)", @@ -11426,6 +11744,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.10", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.15" @@ -11462,6 +11791,7 @@ dependencies = [ "futures-io", "futures-sink", "pin-project-lite", + "slab", "tokio", ] @@ -11546,7 +11876,7 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.29", - "hyper-timeout", + "hyper-timeout 0.4.1", "percent-encoding", "pin-project", "prost 0.11.9", @@ -11574,7 +11904,7 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.29", - "hyper-timeout", + "hyper-timeout 0.4.1", "percent-encoding", "pin-project", "prost 0.12.6", @@ -11693,6 +12023,25 @@ dependencies = [ "uuid", ] +[[package]] +name = "tower-http" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +dependencies = [ + "base64 0.21.7", + "bitflags 2.5.0", + "bytes", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "mime", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower-layer" version = "0.3.2" diff --git a/tests-fuzz/Cargo.toml b/tests-fuzz/Cargo.toml index cc70f83ee4a4..3bf4f677f980 100644 --- a/tests-fuzz/Cargo.toml +++ b/tests-fuzz/Cargo.toml @@ -27,6 +27,13 @@ common-time = { workspace = true } datatypes = { workspace = true } derive_builder = { workspace = true } dotenv = "0.15" +k8s-openapi = { version = "0.22", features = ["v1_30"] } +kube = { version = "0.92", features = [ + "runtime", + "derive", + "client", + "admission", +] } lazy_static = { workspace = true } libfuzzer-sys = "0.4" nix = { version = "0.28", features = ["process", "signal"], optional = true } @@ -34,8 +41,10 @@ partition = { workspace = true } rand = { workspace = true } rand_chacha = "0.3.1" reqwest = { workspace = true } +schemars = "0.8" serde = { workspace = true } serde_json = { workspace = true } +serde_yaml = "0.9" snafu = { workspace = true } sql = { workspace = true } sqlparser.workspace = true diff --git a/tests-fuzz/src/utils.rs b/tests-fuzz/src/utils.rs index 7dff25b5285d..fd984e83a549 100644 --- a/tests-fuzz/src/utils.rs +++ b/tests-fuzz/src/utils.rs @@ -13,6 +13,7 @@ // limitations under the License. pub mod config; +pub mod crd; pub mod health; #[cfg(feature = "unstable")] pub mod process; diff --git a/tests-fuzz/src/utils/crd.rs b/tests-fuzz/src/utils/crd.rs new file mode 100644 index 000000000000..89d947a34c92 --- /dev/null +++ b/tests-fuzz/src/utils/crd.rs @@ -0,0 +1,16 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod common; +mod pod; diff --git a/tests-fuzz/src/utils/crd/common.rs b/tests-fuzz/src/utils/crd/common.rs new file mode 100644 index 000000000000..e27de866544a --- /dev/null +++ b/tests-fuzz/src/utils/crd/common.rs @@ -0,0 +1,78 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::collections::BTreeMap; + +use derive_builder::Builder; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "kebab-case")] +pub enum Mode { + One, + All, + Fixed, + FixedPercent, + RandomMaxPercent, +} + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Default, Builder, JsonSchema)] +#[serde(default, rename_all = "camelCase")] +#[builder(setter(into, strip_option), default)] +pub struct Selector { + #[serde(skip_serializing_if = "Vec::is_empty")] + namespaces: Vec, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + label_selectors: BTreeMap, + #[serde(skip_serializing_if = "Vec::is_empty")] + expression_selectors: Vec, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + annotation_selectors: BTreeMap, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + field_selectors: BTreeMap, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + pod_phase_selectors: BTreeMap, +} + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)] +pub struct ExpressionSelector { + key: String, + operator: String, + values: Vec, +} + +#[cfg(test)] +mod tests { + use std::collections::BTreeMap; + + use super::SelectorBuilder; + + #[test] + fn test_serde() { + let mut fs = BTreeMap::new(); + fs.insert("app.kubernetes.io/component".into(), "tikv".into()); + let selector = SelectorBuilder::default() + .field_selectors(fs) + .build() + .unwrap(); + let ser = serde_yaml::to_string(&selector).unwrap(); + assert_eq!( + r#"fieldSelectors: + app.kubernetes.io/component: tikv +"#, + ser + ); + } +} diff --git a/tests-fuzz/src/utils/crd/pod.rs b/tests-fuzz/src/utils/crd/pod.rs new file mode 100644 index 000000000000..14bd50c429fa --- /dev/null +++ b/tests-fuzz/src/utils/crd/pod.rs @@ -0,0 +1,114 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use derive_builder::Builder; +use kube::CustomResource; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::utils::crd::common::{Mode, Selector}; + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "kebab-case")] +pub enum Action { + PodFailure, + PodKill, + ContainerKill, +} + +#[derive( + CustomResource, Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Builder, JsonSchema, +)] +#[kube( + group = "chaos-mesh.org", + version = "v1alpha1", + namespaced, + kind = "PodChaos", + plural = "podchaos", + singular = "podchaos", + derive = "PartialEq" +)] +#[serde(rename_all = "camelCase")] +pub struct PodChaosSpec { + // Specifies the fault type to inject. The supported types include pod-failure, pod-kill, and container-kill. + action: Action, + // Specifies the mode of the experiment. + // The mode options include one (selecting a random Pod), + // all (selecting all eligible Pods), + // fixed (selecting a specified number of eligible Pods), + // fixed-percent (selecting a specified percentage of Pods from the eligible Pods), + // and random-max-percent (selecting the maximum percentage of Pods from the eligible Pods). + mode: Mode, + // Provides parameters for the mode configuration, depending on mode. + // For example, when mode is set to `fixed-percent`, value specifies the percentage of Pods. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into), default = "None")] + value: Option, + // Specifies the target Pod. + selector: Selector, + // When you configure action to `container-kill`, + // this configuration is mandatory to specify the target container name for injecting faults. + #[serde(skip_serializing_if = "Vec::is_empty", default)] + #[builder(setter(into), default = "Vec::new()")] + container_names: Vec, + // When you configure action to `pod-kill`, + // this configuration is mandatory to specify the duration before deleting Pod. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into), default = "None")] + grace_period: Option, + // Specifies the duration of the experiment. + #[builder(setter(into), default)] + duration: String, +} + +#[cfg(test)] +mod tests { + use std::collections::BTreeMap; + + use super::*; + use crate::utils::crd::common::SelectorBuilder; + + #[test] + fn test_crd_serialization() { + let mut fs = BTreeMap::new(); + fs.insert("app.kubernetes.io/component".into(), "tikv".into()); + let selector = SelectorBuilder::default() + .field_selectors(fs) + .build() + .unwrap(); + + let spec = PodChaosSpecBuilder::default() + .duration("10s") + .selector(selector) + .action(Action::PodKill) + .mode(Mode::One) + .build() + .unwrap(); + let crd = PodChaos::new("my-pod-chaos", spec); + let serialized = serde_yaml::to_string(&crd).unwrap(); + let expected = r#"apiVersion: chaos-mesh.org/v1alpha1 +kind: PodChaos +metadata: + name: my-pod-chaos +spec: + action: pod-kill + mode: one + selector: + fieldSelectors: + app.kubernetes.io/component: tikv + duration: 10s +"#; + assert_eq!(expected, serialized); + } +}