From aed181156986629ebe6cfd71282b244f746df979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20K=C5=91v=C3=A1ri?= Date: Thu, 19 Dec 2024 20:10:45 +0100 Subject: [PATCH] feat(validation): warn for link props source_configs and target_configs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Márk Kővári --- crates/wadm-types/src/validation.rs | 63 ++++++++++++++++++- .../deprecated-source-and-target-config.yaml | 53 ++++++++++++++++ tests/validation.rs | 16 +++++ 3 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 tests/fixtures/manifests/deprecated-source-and-target-config.yaml diff --git a/crates/wadm-types/src/validation.rs b/crates/wadm-types/src/validation.rs index e69ba4a1..ed3ffc94 100644 --- a/crates/wadm-types/src/validation.rs +++ b/crates/wadm-types/src/validation.rs @@ -298,9 +298,12 @@ pub async fn validate_manifest_file( pub async fn validate_manifest_bytes( content: impl AsRef<[u8]>, ) -> Result<(Manifest, Vec)> { + let raw_yaml_content = content.as_ref(); let manifest = serde_yaml::from_slice(content.as_ref()).context("failed to parse manifest content")?; - let failures = validate_manifest(&manifest).await?; + let mut failures = validate_manifest(&manifest).await?; + let mut yaml_issues = validate_raw_yaml(raw_yaml_content)?; + failures.append(&mut yaml_issues); Ok((manifest, failures)) } @@ -349,6 +352,14 @@ pub async fn validate_manifest(manifest: &Manifest) -> Result Result> { + let mut failures = Vec::new(); + let raw_content: serde_yaml::Value = + serde_yaml::from_slice(content).context("failed read raw yaml content")?; + failures.extend(validate_components_configs(&raw_content)); + Ok(failures) +} + fn core_validation(manifest: &Manifest) -> Vec { let mut failures = Vec::new(); let mut name_registry: HashSet = HashSet::new(); @@ -728,7 +739,55 @@ pub fn validate_link_configs(manifest: &Manifest) -> Vec { } } } - }; + } + failures +} + +/// Funtion to validate the component configs +/// from 0.13.0 source_config is deprecated and replaced with source:config: +/// this function validates the raw yaml to check for deprecated source_config and target_config +pub fn validate_components_configs(application: &serde_yaml::Value) -> Vec { + let mut failures = Vec::new(); + + if let Some(specs) = application.get("spec") { + if let Some(components) = specs.get("components") { + if let Some(components_sequence) = components.as_sequence() { + for component in components_sequence.iter() { + failures.extend(get_deprecated_configs(component)); + } + } + } + } + failures +} + +fn get_deprecated_configs(component: &serde_yaml::Value) -> Vec { + let mut failures = vec![]; + if let Some(traits) = component.get("traits") { + if let Some(traits_sequence) = traits.as_sequence() { + for trait_ in traits_sequence.iter() { + if let Some(trait_type) = trait_.get("type") { + if trait_type.ne("link") { + continue; + } + } + if let Some(trait_properties) = trait_.get("properties") { + if let Some(_) = trait_properties.get("source_config") { + failures.push(ValidationFailure { + level: ValidationFailureLevel::Warning, + msg: "one of the components' link trait contains a source_config key, please use source:config: rather".to_string(), + }); + } + if let Some(_) = trait_properties.get("target_config") { + failures.push(ValidationFailure { + level: ValidationFailureLevel::Warning, + msg: "one of the components' link trait contains a target_config key, please use target:config: rather".to_string(), + }); + } + } + } + } + } failures } diff --git a/tests/fixtures/manifests/deprecated-source-and-target-config.yaml b/tests/fixtures/manifests/deprecated-source-and-target-config.yaml new file mode 100644 index 00000000..e5ad2369 --- /dev/null +++ b/tests/fixtures/manifests/deprecated-source-and-target-config.yaml @@ -0,0 +1,53 @@ +--- +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: rust-http-blobstore + annotations: + version: v0.0.1 + description: 'HTTP Blobstore demo in Rust, using the WebAssembly Component Model and WebAssembly Interfaces Types (WIT)' + wasmcloud.dev/authors: wasmCloud team + wasmcloud.dev/source-url: https://github.com/wasmCloud/wasmCloud/blob/main/examples/rust/components/http-blobstore/wadm.yaml + wasmcloud.dev/readme-md-url: https://github.com/wasmCloud/wasmCloud/blob/main/examples/rust/components/http-blobstore/README.md + wasmcloud.dev/homepage: https://github.com/wasmCloud/wasmCloud/tree/main/examples/rust/components/http-blobstore + wasmcloud.dev/categories: | + http,http-server,rust,blobstore,object-storage,example +spec: + components: + - name: http-blobstore + type: component + properties: + image: ghcr.io/wasmcloud/components/http-blobstore-rust:0.2.0 + traits: + - type: spreadscaler + properties: + instances: 1 + - type: link + properties: + target: blobstore-fs + namespace: wasi + package: blobstore + interfaces: [blobstore] + target_config: + - name: root-directory + properties: + root: '/tmp' + - name: httpserver + type: capability + properties: + image: ghcr.io/wasmcloud/http-server:0.23.2 + traits: + - type: link + properties: + target: http-blobstore + namespace: wasi + package: http + interfaces: [incoming-handler] + source_config: + - name: default-http + properties: + address: 0.0.0.0:8000 + - name: blobstore-fs + type: capability + properties: + image: ghcr.io/wasmcloud/blobstore-fs:0.10.1 \ No newline at end of file diff --git a/tests/validation.rs b/tests/validation.rs index a7335d5c..7b26ea83 100644 --- a/tests/validation.rs +++ b/tests/validation.rs @@ -141,3 +141,19 @@ async fn validate_link_config_names() -> Result<()> { ); Ok(()) } + +#[tokio::test] +async fn validate_deprecated_configs_raw_yaml() -> Result<()> { + let (_manifest, failures) = validate_manifest_file( + "./tests/fixtures/manifests/deprecated-source-and-target-config.yaml", + ) + .await + .context("failed to validate manifest")?; + assert!(failures.valid(), "expected valid manifest"); + assert_eq!( + failures.warnings().len(), + 2, + "expected 2 warnings during validating manifest" + ); + Ok(()) +}