diff --git a/sources/Cargo.lock b/sources/Cargo.lock index 3efb59fda..5a69bde22 100644 --- a/sources/Cargo.lock +++ b/sources/Cargo.lock @@ -1062,13 +1062,12 @@ version = "0.1.0" dependencies = [ "rand", "serde_json", - "settings-extension-updates", ] [[package]] name = "bottlerocket-model-derive" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "darling 0.20.10", "quote", @@ -1077,10 +1076,11 @@ dependencies = [ [[package]] name = "bottlerocket-modeled-types" -version = "0.2.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +version = "0.3.0" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", + "bottlerocket-model-derive", "bottlerocket-scalar", "bottlerocket-scalar-derive", "bottlerocket-string-impls-for", @@ -1111,7 +1111,7 @@ dependencies = [ [[package]] name = "bottlerocket-scalar" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "serde", "serde_plain", @@ -1120,7 +1120,7 @@ dependencies = [ [[package]] name = "bottlerocket-scalar-derive" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-scalar", "darling 0.20.10", @@ -1144,8 +1144,8 @@ dependencies = [ [[package]] name = "bottlerocket-settings-models" -version = "0.2.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +version = "0.3.0" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", @@ -1165,10 +1165,12 @@ dependencies = [ "settings-extension-ecs", "settings-extension-host-containers", "settings-extension-kernel", + "settings-extension-kubernetes", "settings-extension-metrics", "settings-extension-motd", "settings-extension-network", "settings-extension-ntp", + "settings-extension-nvidia-container-runtime", "settings-extension-oci-defaults", "settings-extension-oci-hooks", "settings-extension-pki", @@ -1191,7 +1193,7 @@ dependencies = [ [[package]] name = "bottlerocket-settings-sdk" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "argh", "bottlerocket-template-helper", @@ -1204,7 +1206,7 @@ dependencies = [ [[package]] name = "bottlerocket-string-impls-for" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "serde", ] @@ -1212,7 +1214,7 @@ dependencies = [ [[package]] name = "bottlerocket-template-helper" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "darling 0.20.10", "proc-macro2", @@ -1771,7 +1773,7 @@ dependencies = [ "base64 0.22.1", "constants", "early-boot-config-provider", - "env_logger 0.11.3", + "env_logger", "generate-readme", "http 0.2.12", "log", @@ -1790,7 +1792,7 @@ name = "early-boot-config-provider" version = "0.1.0" dependencies = [ "async-trait", - "env_logger 0.11.3", + "env_logger", "flate2", "generate-readme", "hex-literal", @@ -1855,19 +1857,6 @@ dependencies = [ "regex", ] -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.11.3" @@ -2502,17 +2491,6 @@ dependencies = [ "serde", ] -[[package]] -name = "is-terminal" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.0" @@ -3142,6 +3120,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bottlerocket-modeled-types", + "bottlerocket-settings-models", "bytes", "constants", "futures-util", @@ -3679,12 +3658,12 @@ dependencies = [ [[package]] name = "settings-extension-autoscaling" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3692,12 +3671,12 @@ dependencies = [ [[package]] name = "settings-extension-aws" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3705,12 +3684,12 @@ dependencies = [ [[package]] name = "settings-extension-bootstrap-containers" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3718,12 +3697,12 @@ dependencies = [ [[package]] name = "settings-extension-cloudformation" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3731,12 +3710,12 @@ dependencies = [ [[package]] name = "settings-extension-container-registry" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3744,12 +3723,12 @@ dependencies = [ [[package]] name = "settings-extension-container-runtime" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3757,12 +3736,12 @@ dependencies = [ [[package]] name = "settings-extension-dns" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3770,12 +3749,12 @@ dependencies = [ [[package]] name = "settings-extension-ecs" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3783,12 +3762,12 @@ dependencies = [ [[package]] name = "settings-extension-host-containers" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3796,25 +3775,39 @@ dependencies = [ [[package]] name = "settings-extension-kernel" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] +[[package]] +name = "settings-extension-kubernetes" +version = "0.1.0" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" +dependencies = [ + "bottlerocket-model-derive", + "bottlerocket-modeled-types", + "bottlerocket-settings-sdk", + "env_logger", + "serde", + "serde_json", + "toml", +] + [[package]] name = "settings-extension-metrics" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3822,11 +3815,11 @@ dependencies = [ [[package]] name = "settings-extension-motd" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-settings-sdk", "bottlerocket-string-impls-for", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3834,12 +3827,12 @@ dependencies = [ [[package]] name = "settings-extension-network" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3847,12 +3840,25 @@ dependencies = [ [[package]] name = "settings-extension-ntp" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" +dependencies = [ + "bottlerocket-model-derive", + "bottlerocket-modeled-types", + "bottlerocket-settings-sdk", + "env_logger", + "serde", + "serde_json", +] + +[[package]] +name = "settings-extension-nvidia-container-runtime" +version = "0.1.0" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3860,12 +3866,12 @@ dependencies = [ [[package]] name = "settings-extension-oci-defaults" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", "toml", @@ -3874,12 +3880,12 @@ dependencies = [ [[package]] name = "settings-extension-oci-hooks" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3887,12 +3893,12 @@ dependencies = [ [[package]] name = "settings-extension-pki" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "serde", "serde_json", ] @@ -3900,12 +3906,12 @@ dependencies = [ [[package]] name = "settings-extension-updates" version = "0.1.0" -source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.2.0#848b3153922c5202e4f38c428b7572a9ee313f3f" +source = "git+https://github.com/bottlerocket-os/bottlerocket-settings-sdk?tag=bottlerocket-settings-models-v0.3.0#cebbd4cdd4cf86b24b52554b9db7bdc21aa4e67e" dependencies = [ "bottlerocket-model-derive", "bottlerocket-modeled-types", "bottlerocket-settings-sdk", - "env_logger 0.10.2", + "env_logger", "rand", "serde", "serde_json", diff --git a/sources/Cargo.toml b/sources/Cargo.toml index ed45ecd10..b0793b3da 100644 --- a/sources/Cargo.toml +++ b/sources/Cargo.toml @@ -190,13 +190,13 @@ base64 = "0.22" [workspace.dependencies.bottlerocket-modeled-types] git = "https://github.com/bottlerocket-os/bottlerocket-settings-sdk" -tag = "bottlerocket-settings-models-v0.2.0" -version = "0.2.0" +tag = "bottlerocket-settings-models-v0.3.0" +version = "0.3.0" [workspace.dependencies.bottlerocket-settings-models] git = "https://github.com/bottlerocket-os/bottlerocket-settings-sdk" -tag = "bottlerocket-settings-models-v0.2.0" -version = "0.2.0" +tag = "bottlerocket-settings-models-v0.3.0" +version = "0.3.0" [workspace.dependencies.bottlerocket-settings-plugin] git = "https://github.com/bottlerocket-os/bottlerocket-settings-sdk" @@ -205,12 +205,7 @@ version = "0.1.0" [workspace.dependencies.settings-extension-oci-defaults] git = "https://github.com/bottlerocket-os/bottlerocket-settings-sdk" -tag = "bottlerocket-settings-models-v0.2.0" -version = "0.1.0" - -[workspace.dependencies.settings-extension-updates] -git = "https://github.com/bottlerocket-os/bottlerocket-settings-sdk" -tag = "bottlerocket-settings-models-v0.2.0" +tag = "bottlerocket-settings-models-v0.3.0" version = "0.1.0" [profile.release] diff --git a/sources/api/bork/Cargo.toml b/sources/api/bork/Cargo.toml index 22288bf90..97ceaba8a 100644 --- a/sources/api/bork/Cargo.toml +++ b/sources/api/bork/Cargo.toml @@ -11,4 +11,3 @@ exclude = ["README.md"] [dependencies] rand = { workspace = true, features = ["default"] } serde_json.workspace = true -settings-extension-updates.workspace = true diff --git a/sources/api/pluto/Cargo.toml b/sources/api/pluto/Cargo.toml index af3595a99..07a834c81 100644 --- a/sources/api/pluto/Cargo.toml +++ b/sources/api/pluto/Cargo.toml @@ -10,6 +10,8 @@ build = "build.rs" exclude = ["README.md"] [dependencies] +bottlerocket-modeled-types.workspace = true +bottlerocket-settings-models.workspace = true bytes.workspace = true constants.workspace = true futures-util.workspace = true @@ -32,7 +34,6 @@ tokio-retry.workspace = true tokio-rustls.workspace = true url.workspace = true log.workspace = true -bottlerocket-modeled-types.workspace = true [build-dependencies] generate-readme.workspace = true diff --git a/sources/api/pluto/src/api.rs b/sources/api/pluto/src/api.rs index 7174feec5..d35f760e8 100644 --- a/sources/api/pluto/src/api.rs +++ b/sources/api/pluto/src/api.rs @@ -1,4 +1,5 @@ -use serde::{Deserialize, Serialize}; +use bottlerocket_settings_models::{AwsSettingsV1, KubernetesSettingsV1, NetworkSettingsV1}; +use serde::Deserialize; use snafu::{ensure, ResultExt, Snafu}; use std::ffi::OsStr; use tokio::process::Command; @@ -6,82 +7,123 @@ use tokio::process::Command; /// The result type for the [`api`] module. pub(super) type Result = std::result::Result; -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] -pub(crate) struct AwsK8sInfo { - #[serde(skip)] - pub(crate) region: Option, - #[serde(skip)] - pub(crate) https_proxy: Option, - #[serde(skip)] - pub(crate) no_proxy: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) cluster_name: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) cluster_dns_ip: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) node_ip: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) max_pods: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) provider_id: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) hostname_override: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) hostname_override_source: - Option, +/// A mutable view of API settings +/// +/// `SettingsViewDelta` keeps track of all changes in a separate structure so that only the changed +/// set can be sent back as writes to the API server. +/// +/// For convenience, `settings_view_get!` and `settings_view_set!` macros can be used to handle +/// the nested optional values present in the structure succinctly. +/// +/// `settings_view_get!` also automatically attempts to read from the settings delta before falling +/// back to the readonly settings. +#[derive(Debug, Clone, PartialEq)] +pub struct SettingsViewDelta { + readonly: SettingsView, + delta: SettingsView, } -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] -pub(crate) struct AwsInfo { - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) region: Option, -} +impl SettingsViewDelta { + /// Constructs a `SettingsViewDelta` based on an initial read-only view of settings. + pub fn from_api_response(readonly: SettingsView) -> Self { + Self { + readonly, + delta: SettingsView::default(), + } + } + + /// Returns the initial read-only settings model view + /// + /// Users should prefer to interact with this struct via the [`settings_view_get!`] and + /// [`settings_view_set!`] macros. + pub fn initial(&self) -> &SettingsView { + &self.readonly + } + + /// Returns a mutable reference to the "delta" settings model view + /// + /// Users should prefer to interact with this struct via the [`settings_view_get!`] and + /// [`settings_view_set!`] macros. + pub fn write(&mut self) -> &mut SettingsView { + &mut self.delta + } -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] -pub(crate) struct Kubernetes { - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) cluster_name: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) cluster_dns_ip: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) node_ip: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) max_pods: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) provider_id: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) hostname_override: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub(crate) hostname_override_source: - Option, + /// Returns an immutable reference to the "delta" settings model view + /// + /// Users should prefer to interact with this struct via the [`settings_view_get!`] and + /// [`settings_view_set!`] macros. + pub fn delta(&self) -> &SettingsView { + &self.delta + } } -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -struct Os { - variant_id: String, +/// Returns the optional value of a settings nested within `SettingsViewDelta`. +/// +/// Will refer to the delta before falling back to the readonly settings. +/// +/// ``` +/// let settings = SettingsViewDelta::from_api_response(SettingsView { +/// aws: Some(AwsSettingsV1 { +/// region: Some("us-west-2"), +/// ..Default::default() +/// }) +/// ..Default::default() +/// }); +/// assert_eq!(settings_view_get!(settings.aws.region), Some("us-west-2")); +/// ``` +macro_rules! settings_view_get { + (impl $parent:ident.$field:ident) => { + $parent.$field.as_ref() + }; + (impl $parent:ident.$field:ident$(.$fields:ident)+) => {{ + settings_view_get!(impl $parent.$field).and_then(|p| settings_view_get!(impl p.$($fields)+)) + }}; + ($settings:ident.$field:ident$(.$fields:ident)*) => {{ + let reader = $settings.initial(); + let delta = $settings.delta(); + settings_view_get!(impl delta.$field$(.$fields)*) + .or_else(|| settings_view_get!(impl reader.$field$(.$fields)*)) + }}; } -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] -struct Network { - https_proxy: Option, - no_proxy: Option, +/// Writes an optional value to the delta in a `SettingsViewDelta`. +/// +/// ``` +/// let settings = SettingsViewDelta::from_api_response(SettingsView { +/// aws: Some(AwsSettingsV1 { +/// region: Some("us-west-2"), +/// ..Default::default() +/// }) +/// ..Default::default() +/// }); +/// settings_view_set!(settings.aws.region = "us-east-1"); +/// assert_eq!(settings_view_get!(settings.aws.region), Some("us-east-1")); +/// ``` +macro_rules! settings_view_set { + (impl $parent:ident.$field:ident = $value:expr) => { + $parent.$field = Some($value) + }; + (impl $parent:ident.$field:ident$(.$fields:ident)+ = $value:expr) => {{ + let curr_val = $parent.$field.get_or_insert_with(Default::default); + settings_view_set!(impl curr_val.$($fields)+ = $value); + }}; + ($settings:ident.$field:ident$(.$fields:ident)* = $value:expr) => {{ + let writer = $settings.write(); + settings_view_set!(impl writer.$field$(.$fields)* = $value); + }} } +pub(crate) use {settings_view_get, settings_view_set}; -#[derive(Deserialize)] -struct View { - pub aws: Option, - pub network: Option, - pub kubernetes: Option, +#[derive(Debug, Deserialize, Default, PartialEq, Clone)] +pub struct SettingsView { + pub aws: Option, + pub network: Option, + pub kubernetes: Option, } #[derive(Deserialize)] -struct SettingsView { - pub settings: View, +struct APISettingsResponse { + pub settings: SettingsView, } #[derive(Debug, Snafu)] @@ -119,66 +161,93 @@ where } /// Gets the info that we need to know about the EKS cluster from the Bottlerocket API. -pub(crate) async fn get_aws_k8s_info() -> Result { +pub(crate) async fn get_aws_k8s_info() -> Result { let view_str = client_command(&[ "get", - "settings.aws.region", - "settings.network.http-proxy", - "settings.network.no-proxy", - "settings.kubernetes.cluster-name", - "settings.kubernetes.cluster-dns-ip", - "settings.kubernetes.node-ip", - "settings.kubernetes.max-pods", - "settings.kubernetes.provider-id", - "settings.kubernetes.hostname-override", - "settings.kubernetes.hostname-override-source", + "settings.aws", + "settings.network", + "settings.kubernetes", ]) .await?; - let view: SettingsView = + + let api_response: APISettingsResponse = serde_json::from_slice(view_str.as_slice()).context(DeserializeSnafu)?; + Ok(api_response.settings) +} + +#[cfg(test)] +mod test { + use super::*; + use bottlerocket_settings_models::{AwsSettingsV1, KubernetesSettingsV1}; + + #[test] + fn test_default_kubernetes_settings_empty() { + // `SettingsViewDelta` relies on its components default implementations being empty. + // If this test fails, `pluto` could submit incorrect settings changes. + let kubernetes_defaults = serde_json::to_value(KubernetesSettingsV1::default()).unwrap(); + assert_eq!(kubernetes_defaults, serde_json::json!({})); + } + + #[test] + fn test_default_network_settings_empty() { + // `SettingsViewDelta` relies on its components default implementations being empty. + // If this test fails, `pluto` could submit incorrect settings changes. + let network_defaults = serde_json::to_value(NetworkSettingsV1::default()).unwrap(); + assert_eq!(network_defaults, serde_json::json!({})); + } + + #[test] + fn test_default_aws_settings_empty() { + // `SettingsViewDelta` relies on its components default implementations being empty. + // If this test fails, `pluto` could submit incorrect settings changes. + let aws_defaults = serde_json::to_value(AwsSettingsV1::default()).unwrap(); + assert_eq!(aws_defaults, serde_json::json!({})); + } + + #[test] + fn test_settings_view_set() { + // When settings are written, the originals are preserved + let readonly_settings = SettingsView { + aws: Some(AwsSettingsV1 { + region: Some("us-west-2".try_into().unwrap()), + ..Default::default() + }), + ..Default::default() + }; + let mut settings = SettingsViewDelta::from_api_response(readonly_settings.clone()); + + settings_view_set!(settings.aws.region = "us-east-1".try_into().unwrap()); + + let expected = SettingsViewDelta { + readonly: settings.readonly.clone(), + delta: SettingsView { + aws: Some(AwsSettingsV1 { + region: Some("us-east-1".try_into().unwrap()), + ..Default::default() + }), + ..Default::default() + }, + }; + + assert_eq!(settings, expected); + } + + #[test] + fn test_settings_view_read_overwritten() { + // When settings are written, the delta is fetched first + let readonly_settings = SettingsView { + aws: Some(AwsSettingsV1 { + region: Some("us-west-2".try_into().unwrap()), + ..Default::default() + }), + ..Default::default() + }; + let mut settings = SettingsViewDelta::from_api_response(readonly_settings.clone()); - Ok(AwsK8sInfo { - region: view.settings.aws.and_then(|a| a.region), - https_proxy: view - .settings - .network - .as_ref() - .and_then(|n| n.https_proxy.clone()), - no_proxy: view - .settings - .network - .as_ref() - .and_then(|n| n.no_proxy.clone()), - cluster_name: view - .settings - .kubernetes - .as_ref() - .and_then(|k| k.cluster_name.clone()), - cluster_dns_ip: view - .settings - .kubernetes - .as_ref() - .and_then(|k| k.cluster_dns_ip.clone()), - node_ip: view - .settings - .kubernetes - .as_ref() - .and_then(|k| k.node_ip.clone()), - max_pods: view.settings.kubernetes.as_ref().and_then(|k| k.max_pods), - provider_id: view - .settings - .kubernetes - .as_ref() - .and_then(|k| k.provider_id.clone()), - hostname_override: view - .settings - .kubernetes - .as_ref() - .and_then(|k| k.hostname_override.clone()), - hostname_override_source: view - .settings - .kubernetes - .as_ref() - .and_then(|k| k.hostname_override_source.clone()), - }) + settings_view_set!(settings.aws.region = "us-east-1".try_into().unwrap()); + assert_eq!( + settings_view_get!(settings.aws.region).map(ToString::to_string), + Some("us-east-1".to_string()) + ); + } } diff --git a/sources/api/pluto/src/ec2.rs b/sources/api/pluto/src/ec2.rs index f2d3431a1..e8f5bf2fd 100644 --- a/sources/api/pluto/src/ec2.rs +++ b/sources/api/pluto/src/ec2.rs @@ -40,12 +40,16 @@ pub(super) enum Error { type Result = std::result::Result; -pub(super) async fn get_private_dns_name( +pub(super) async fn get_private_dns_name( region: &str, instance_id: &str, - https_proxy: Option, - no_proxy: Option, -) -> Result { + https_proxy: Option, + no_proxy: Option<&[N]>, +) -> Result +where + H: AsRef, + N: AsRef, +{ let config = sdk_config(region).await; let client = if let Some(https_proxy) = https_proxy { diff --git a/sources/api/pluto/src/eks.rs b/sources/api/pluto/src/eks.rs index fb5d8f8e5..31d2f8b8e 100644 --- a/sources/api/pluto/src/eks.rs +++ b/sources/api/pluto/src/eks.rs @@ -33,12 +33,16 @@ type Result = std::result::Result; /// Returns the cluster's [kubernetesNetworkConfig] by calling the EKS API. /// (https://docs.aws.amazon.com/eks/latest/APIReference/API_KubernetesNetworkConfigResponse.html) -pub(super) async fn get_cluster_network_config( +pub(super) async fn get_cluster_network_config( region: &str, cluster: &str, - https_proxy: Option, - no_proxy: Option, -) -> Result { + https_proxy: Option, + no_proxy: Option<&[N]>, +) -> Result +where + H: AsRef, + N: AsRef, +{ let config = sdk_config(region).await; let client = if let Some(https_proxy) = https_proxy { diff --git a/sources/api/pluto/src/main.rs b/sources/api/pluto/src/main.rs index 735403b5a..faff74be0 100644 --- a/sources/api/pluto/src/main.rs +++ b/sources/api/pluto/src/main.rs @@ -38,7 +38,7 @@ mod eks; mod hyper_proxy; mod proxy; -use api::AwsK8sInfo; +use api::{settings_view_get, settings_view_set, SettingsViewDelta}; use bottlerocket_modeled_types::{KubernetesClusterDnsIp, KubernetesHostnameOverrideSource}; use imdsclient::ImdsClient; use snafu::{ensure, OptionExt, ResultExt}; @@ -94,6 +94,16 @@ mod error { #[snafu(display("IMDS request failed: No '{}' found", what))] ImdsNone { what: String }, + #[snafu(display("Invalid hostname: {}", source))] + InvalidHostname { + source: bottlerocket_modeled_types::error::Error, + }, + + #[snafu(display("Invalid URL: {}", source))] + InvalidUrl { + source: bottlerocket_modeled_types::error::Error, + }, + #[snafu(display("{}", source))] EksError { source: eks::Error }, @@ -127,11 +137,16 @@ use error::PlutoError; type Result = std::result::Result; -async fn generate_max_pods(client: &mut ImdsClient, aws_k8s_info: &mut AwsK8sInfo) -> Result<()> { - if aws_k8s_info.max_pods.is_some() { +async fn generate_max_pods( + client: &mut ImdsClient, + aws_k8s_info: &mut SettingsViewDelta, +) -> Result<()> { + if settings_view_get!(aws_k8s_info.kubernetes.max_pods).is_some() { return Ok(()); } - aws_k8s_info.max_pods = get_max_pods(client).await.ok(); + if let Ok(max_pods) = get_max_pods(client).await { + settings_view_set!(aws_k8s_info.kubernetes.max_pods = max_pods); + } Ok(()) } @@ -173,9 +188,9 @@ async fn get_max_pods(client: &mut ImdsClient) -> Result { /// blocks to return one of two default addresses. async fn generate_cluster_dns_ip( client: &mut ImdsClient, - aws_k8s_info: &mut AwsK8sInfo, + aws_k8s_info: &mut SettingsViewDelta, ) -> Result<()> { - if aws_k8s_info.cluster_dns_ip.is_some() { + if settings_view_get!(aws_k8s_info.kubernetes.cluster_dns_ip).is_some() { return Ok(()); } @@ -188,26 +203,28 @@ async fn generate_cluster_dns_ip( get_ipv4_cluster_dns_ip_from_imds_mac(client).await? }; - aws_k8s_info.cluster_dns_ip = Some(KubernetesClusterDnsIp::Scalar( - IpAddr::from_str(ip_addr.as_str()).context(error::BadIpSnafu { - ip: ip_addr.clone(), - })?, - )); + settings_view_set!( + aws_k8s_info.kubernetes.cluster_dns_ip = KubernetesClusterDnsIp::Scalar( + IpAddr::from_str(ip_addr.as_str()).context(error::BadIpSnafu { + ip: ip_addr.clone(), + })?, + ) + ); Ok(()) } /// Retrieves the ip address from the kubernetes network configuration for the /// EKS Cluster -async fn get_eks_network_config(aws_k8s_info: &AwsK8sInfo) -> Result> { +async fn get_eks_network_config(aws_k8s_info: &SettingsViewDelta) -> Result> { if let (Some(region), Some(cluster_name)) = ( - aws_k8s_info.region.as_ref(), - aws_k8s_info.cluster_name.as_ref(), + settings_view_get!(aws_k8s_info.aws.region), + settings_view_get!(aws_k8s_info.kubernetes.cluster_name), ) { if let Ok(config) = eks::get_cluster_network_config( region, cluster_name, - aws_k8s_info.https_proxy.clone(), - aws_k8s_info.no_proxy.clone(), + settings_view_get!(aws_k8s_info.network.https_proxy), + settings_view_get!(aws_k8s_info.network.no_proxy).map(Vec::as_slice), ) .await .context(error::EksSnafu) @@ -284,15 +301,16 @@ async fn get_ipv4_cluster_dns_ip_from_imds_mac(client: &mut ImdsClient) -> Resul } /// Gets the IP address that should be associated with the node. -async fn generate_node_ip(client: &mut ImdsClient, aws_k8s_info: &mut AwsK8sInfo) -> Result<()> { - if aws_k8s_info.node_ip.is_some() { +async fn generate_node_ip( + client: &mut ImdsClient, + aws_k8s_info: &mut SettingsViewDelta, +) -> Result<()> { + if settings_view_get!(aws_k8s_info.kubernetes.node_ip).is_some() { return Ok(()); } // Ensure that this was set in case changes to main occur generate_cluster_dns_ip(client, aws_k8s_info).await?; - let cluster_dns_ip = aws_k8s_info - .cluster_dns_ip - .as_ref() + let cluster_dns_ip = settings_view_get!(aws_k8s_info.kubernetes.cluster_dns_ip) .and_then(|x| x.iter().next()) .context(error::NoIpSnafu)?; // If the cluster DNS IP is an IPv4 address, retrieve the IPv4 address for the instance. @@ -313,16 +331,21 @@ async fn generate_node_ip(client: &mut ImdsClient, aws_k8s_info: &mut AwsK8sInfo what: "ipv6s associated with primary network interface", }), }?; - aws_k8s_info.node_ip = Some(node_ip); + settings_view_set!( + aws_k8s_info.kubernetes.node_ip = + IpAddr::from_str(node_ip.as_str()).context(error::BadIpSnafu { + ip: node_ip.clone(), + })? + ); Ok(()) } /// Gets the provider ID that should be associated with the node async fn generate_provider_id( client: &mut ImdsClient, - aws_k8s_info: &mut AwsK8sInfo, + aws_k8s_info: &mut SettingsViewDelta, ) -> Result<()> { - if aws_k8s_info.provider_id.is_some() { + if settings_view_get!(aws_k8s_info.kubernetes.provider_id).is_some() { return Ok(()); } @@ -340,29 +363,32 @@ async fn generate_provider_id( .context(error::ImdsRequestSnafu)? .context(error::ImdsNoneSnafu { what: "zone" })?; - aws_k8s_info.provider_id = Some(format!("aws:///{}/{}", zone, instance_id)); + settings_view_set!( + aws_k8s_info.kubernetes.provider_id = format!("aws:///{}/{}", zone, instance_id) + .try_into() + .context(error::InvalidUrlSnafu)? + ); Ok(()) } /// generate_node_name sets the hostname_override, if it is not already specified -async fn generate_node_name(client: &mut ImdsClient, aws_k8s_info: &mut AwsK8sInfo) -> Result<()> { +async fn generate_node_name( + client: &mut ImdsClient, + aws_k8s_info: &mut SettingsViewDelta, +) -> Result<()> { // hostname override provided, so we do nothing regardless of the override source - if aws_k8s_info.hostname_override.is_some() { + if settings_view_get!(aws_k8s_info.kubernetes.hostname_override).is_some() { return Ok(()); } // no hostname override or override source provided, so we don't provide this value - if aws_k8s_info.hostname_override_source.is_none() { - return Ok(()); - } - - // use the hostname source provided, None case handled prior so unwrap is safe - let hostname_source = aws_k8s_info.hostname_override_source.clone().unwrap(); + let hostname_source = match settings_view_get!(aws_k8s_info.kubernetes.hostname_override_source) + { + None => return Ok(()), + Some(hostname_source) => hostname_source, + }; - let region = aws_k8s_info - .region - .as_ref() - .context(error::AwsRegionSnafu)?; + let region = settings_view_get!(aws_k8s_info.aws.region).context(error::AwsRegionSnafu)?; let instance_id = client .fetch_instance_id() .await @@ -373,19 +399,25 @@ async fn generate_node_name(client: &mut ImdsClient, aws_k8s_info: &mut AwsK8sIn match hostname_source { KubernetesHostnameOverrideSource::PrivateDNSName => { - aws_k8s_info.hostname_override = Some( - ec2::get_private_dns_name( - region, - &instance_id, - aws_k8s_info.https_proxy.clone(), - aws_k8s_info.no_proxy.clone(), - ) - .await - .context(error::Ec2Snafu)?, - ); + let hostname_override = ec2::get_private_dns_name( + region, + &instance_id, + settings_view_get!(aws_k8s_info.network.https_proxy), + settings_view_get!(aws_k8s_info.network.no_proxy).map(Vec::as_slice), + ) + .await + .context(error::Ec2Snafu)? + .try_into() + .context(error::InvalidHostnameSnafu)?; + + settings_view_set!(aws_k8s_info.kubernetes.hostname_override = hostname_override); } KubernetesHostnameOverrideSource::InstanceID => { - aws_k8s_info.hostname_override = Some(instance_id); + settings_view_set!( + aws_k8s_info.kubernetes.hostname_override = instance_id + .try_into() + .context(error::InvalidHostnameSnafu)? + ); } } @@ -394,7 +426,8 @@ async fn generate_node_name(client: &mut ImdsClient, aws_k8s_info: &mut AwsK8sIn async fn run() -> Result<()> { let mut client = ImdsClient::new(); - let mut aws_k8s_info = api::get_aws_k8s_info().await.context(error::AwsInfoSnafu)?; + let current_settings = api::get_aws_k8s_info().await.context(error::AwsInfoSnafu)?; + let mut aws_k8s_info = SettingsViewDelta::from_api_response(current_settings); generate_cluster_dns_ip(&mut client, &mut aws_k8s_info).await?; generate_node_ip(&mut client, &mut aws_k8s_info).await?; @@ -402,19 +435,20 @@ async fn run() -> Result<()> { generate_provider_id(&mut client, &mut aws_k8s_info).await?; generate_node_name(&mut client, &mut aws_k8s_info).await?; - let settings = serde_json::to_value(&aws_k8s_info).context(error::SerializeSnafu)?; - let generated_settings: serde_json::Value = serde_json::json!({ - "kubernetes": settings - }); - let json_str = generated_settings.to_string(); - let uri = &format!( - "{}?tx={}", - constants::API_SETTINGS_URI, - constants::LAUNCH_TRANSACTION - ); - api::client_command(&["raw", "-m", "PATCH", "-u", uri, "-d", json_str.as_str()]) - .await - .context(error::SetFailureSnafu)?; + if let Some(k8s_settings) = &aws_k8s_info.delta().kubernetes { + let generated_settings = serde_json::json!({ + "kubernetes": serde_json::to_value(&k8s_settings).context(error::SerializeSnafu)? + }); + let json_str = generated_settings.to_string(); + let uri = &format!( + "{}?tx={}", + constants::API_SETTINGS_URI, + constants::LAUNCH_TRANSACTION + ); + api::client_command(&["raw", "-m", "PATCH", "-u", uri, "-d", json_str.as_str()]) + .await + .context(error::SetFailureSnafu)?; + } Ok(()) } @@ -433,6 +467,9 @@ async fn main() { #[cfg(test)] mod test { use super::*; + use crate::api::SettingsViewDelta; + use api::SettingsView; + use bottlerocket_settings_models::AwsSettingsV1; use httptest::{matchers::*, responders::*, Expectation, Server}; #[test] @@ -484,68 +521,98 @@ mod test { let mut imds_client = ImdsClient::new_impl(base_uri); - let mut info = AwsK8sInfo { - region: Some(String::from("us-west-2")), - https_proxy: None, - no_proxy: None, - cluster_name: None, - cluster_dns_ip: None, - node_ip: None, - max_pods: None, - provider_id: None, - hostname_override: None, - hostname_override_source: None, - }; + let mut info = SettingsViewDelta::from_api_response(SettingsView { + aws: Some(AwsSettingsV1 { + region: Some("us-west-2".try_into().unwrap()), + ..Default::default() + }), + ..Default::default() + }); // specifying a hostname will cause it to be used - info.hostname_override = Some(String::from("hostname-specified")); + settings_view_set!( + info.kubernetes.hostname_override = + String::from("hostname-specified").try_into().unwrap() + ); generate_node_name(&mut imds_client, &mut info) .await .unwrap(); assert_eq!( - info.hostname_override, + settings_view_get!(info.kubernetes.hostname_override).map(ToString::to_string), Some(String::from("hostname-specified")) ); // regardless of the hostname override source - info.hostname_override = Some(String::from("hostname-specified")); - info.hostname_override_source = Some(KubernetesHostnameOverrideSource::InstanceID); + settings_view_set!( + info.kubernetes.hostname_override = + String::from("hostname-specified").try_into().unwrap() + ); + settings_view_set!( + info.kubernetes.hostname_override_source = KubernetesHostnameOverrideSource::InstanceID + ); generate_node_name(&mut imds_client, &mut info) .await .unwrap(); assert_eq!( - info.hostname_override, + settings_view_get!(info.kubernetes.hostname_override).map(ToString::to_string), Some(String::from("hostname-specified")) ); - info.hostname_override = Some(String::from("hostname-specified")); - info.hostname_override_source = Some(KubernetesHostnameOverrideSource::PrivateDNSName); + settings_view_set!( + info.kubernetes.hostname_override = + String::from("hostname-specified").try_into().unwrap() + ); + settings_view_set!( + info.kubernetes.hostname_override_source = + KubernetesHostnameOverrideSource::PrivateDNSName + ); generate_node_name(&mut imds_client, &mut info) .await .unwrap(); assert_eq!( - info.hostname_override, + settings_view_get!(info.kubernetes.hostname_override).map(ToString::to_string), Some(String::from("hostname-specified")) ); // no override provided if neither value is set - info.hostname_override = None; - info.hostname_override_source = None; + let mut info = SettingsViewDelta::from_api_response(SettingsView { + aws: Some(AwsSettingsV1 { + region: Some("us-west-2".try_into().unwrap()), + ..Default::default() + }), + ..Default::default() + }); + + assert!(settings_view_get!(info.kubernetes.hostname_override).is_none()); + assert!(settings_view_get!(info.kubernetes.hostname_override_source).is_none()); generate_node_name(&mut imds_client, &mut info) .await .unwrap(); - assert_eq!(info.hostname_override, None); + assert_eq!(settings_view_get!(info.kubernetes.hostname_override), None); // skipping tests that call use the private dns name since we would need to make the EC2 // API mockable to implement them // specifying no hostname, with override of instance-id causes the instance-id to be used // and pulled from IMDS - info.hostname_override = None; - info.hostname_override_source = Some(KubernetesHostnameOverrideSource::InstanceID); + let mut info = SettingsViewDelta::from_api_response(SettingsView { + aws: Some(AwsSettingsV1 { + region: Some("us-west-2".try_into().unwrap()), + ..Default::default() + }), + ..Default::default() + }); + + assert!(settings_view_get!(info.kubernetes.hostname_override).is_none()); + settings_view_set!( + info.kubernetes.hostname_override_source = KubernetesHostnameOverrideSource::InstanceID + ); generate_node_name(&mut imds_client, &mut info) .await .unwrap(); - assert_eq!(info.hostname_override, Some(String::from("i-123456789"))); + assert_eq!( + settings_view_get!(info.kubernetes.hostname_override).map(ToString::to_string), + Some(String::from("i-123456789")) + ); } } diff --git a/sources/api/pluto/src/proxy.rs b/sources/api/pluto/src/proxy.rs index a4b10ca25..2c4ad369a 100644 --- a/sources/api/pluto/src/proxy.rs +++ b/sources/api/pluto/src/proxy.rs @@ -27,27 +27,34 @@ pub(super) enum Error { type Result = std::result::Result; /// Setups a hyper-based HTTP client configured with a proxy connector. -pub(crate) fn setup_http_client( - https_proxy: String, - no_proxy: Option, -) -> Result>> { +pub(crate) fn setup_http_client( + https_proxy: H, + no_proxy: Option<&[N]>, +) -> Result>> +where + H: AsRef, + N: AsRef, +{ // Determines whether a request of a given scheme, host and port should be proxied // according to `https_proxy` and `no_proxy`. + + // The no-proxy intercept requires ownership of its input data. + let no_proxy: Option> = + no_proxy.map(|n| n.iter().map(|s| s.as_ref().to_owned()).collect()); let intercept = move |scheme: Option<&str>, host: Option<&str>, _port| { if let Some(host) = host { if let Some(no_proxy) = &no_proxy { if scheme != Some("https") { return false; } - let no_proxy_hosts: Vec<&str> = no_proxy.split(',').map(|s| s.trim()).collect(); - if no_proxy_hosts.iter().any(|s| *s == "*") { + if no_proxy.iter().any(|s| s == "*") { // Don't proxy anything return false; } // If the host matches one of the no proxy list entries, return false (don't proxy) // Note that we're not doing anything fancy here for checking `no_proxy` since // we only expect requests here to be going out to some AWS API endpoint. - return !no_proxy_hosts.iter().any(|no_proxy_host| { + return !no_proxy.iter().any(|no_proxy_host| { !no_proxy_host.is_empty() && host.ends_with(no_proxy_host) }); } @@ -56,8 +63,10 @@ pub(crate) fn setup_http_client( false } }; + + let https_proxy = https_proxy.as_ref(); let mut proxy_uri = https_proxy.parse::().context(UriParseSnafu { - input: &https_proxy, + input: https_proxy.to_owned(), })?; // If the proxy's URI doesn't have a scheme, assume HTTP for the scheme and let the proxy // server forward HTTPS connections and start a tunnel. @@ -65,13 +74,13 @@ pub(crate) fn setup_http_client( proxy_uri = format!("http://{}", https_proxy) .parse::() .context(UriParseSnafu { - input: &https_proxy, + input: https_proxy.to_owned(), })?; } let mut proxy = Proxy::new(intercept, proxy_uri); // Parse https_proxy as URL to extract out auth information if any let proxy_url = Url::parse(&https_proxy).context(UrlParseSnafu { - input: &https_proxy, + input: https_proxy.to_owned(), })?; if !proxy_url.username().is_empty() || proxy_url.password().is_some() { diff --git a/sources/deny.toml b/sources/deny.toml index 1d7175deb..6133441aa 100644 --- a/sources/deny.toml +++ b/sources/deny.toml @@ -55,8 +55,6 @@ deny = [{ name = "structopt" }, { name = "clap", wrappers = ["cargo-readme"] }] skip = [ # this can be removed once settings sdk is updated to base64 0.22.1 { name = "base64", version = "=0.21.7" }, - # this can be removed once settings sdk is updated to env_logger 0.11 - { name = "env_logger", version = "=0.10.2" }, ] skip-tree = [