This commit is contained in:
Jakob Beckmann 2025-09-08 15:06:46 +00:00 committed by GitHub
commit 27d6ed8a3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 1752 additions and 871 deletions

2553
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -31,14 +31,14 @@ config = { workspace = true }
futures = { workspace = true }
handlebars = { workspace = true }
json-patch = { workspace = true }
k8s-openapi = { workspace = true, features = ["v1_28", "schemars"] }
k8s-openapi = { workspace = true, features = ["v1_30", "schemars"] }
kube = { workspace = true, features = ["runtime", "derive", "default"] }
opentelemetry = { workspace = true }
opentelemetry_sdk = { workspace = true }
opentelemetry-otlp = { workspace = true }
rcgen = { workspace = true }
schemars = { workspace = true }
secrecy = { workspace = true }
secrecy = { workspace = true, features = ["serde"] }
serde = { workspace = true }
serde_json = { workspace = true }
serde_yaml = { workspace = true }
@ -57,7 +57,7 @@ wadm-types = { workspace = true }
wasmcloud-operator-types = { workspace = true }
[workspace.dependencies]
async-nats = "0.33"
async-nats = "0.39"
axum = { version = "0.6", features = ["headers"] }
axum-server = { version = "0.4", features = ["tls-rustls"] }
anyhow = "1"
@ -65,13 +65,13 @@ config = { version = "0.14", default-features = false, features = [
"convert-case",
"async",
] }
cloudevents-sdk = "0.7"
cloudevents-sdk = "0.8"
ctrlc = "3"
futures = "0.3"
handlebars = "5.1"
json-patch = "1.4.0"
k8s-openapi = { version = "0.20", default-features = false }
kube = { version = "0.87", default-features = false }
k8s-openapi = { version = "0.26", default-features = false }
kube = { version = "2.0", default-features = false }
opentelemetry = { version = "0.21", default-features = false }
opentelemetry_sdk = { version = "0.21", features = [
"metrics",
@ -80,7 +80,7 @@ opentelemetry_sdk = { version = "0.21", features = [
] }
opentelemetry-otlp = { version = "0.14", features = ["tokio"] }
rcgen = "0.11"
schemars = "0.8"
schemars = "1.0"
secrecy = "0.8"
serde = "1"
serde_json = "1"
@ -94,9 +94,9 @@ tracing-opentelemetry = "0.22"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
utoipa = { version = "4.2", features = ["axum_extras"] }
uuid = { version = "1", features = ["v5"] }
wadm = "0.13.1"
wadm-client = "0.2.0"
wadm-types = "0.2.0"
wadm = "0.21.0"
wadm-client = "0.10.0"
wadm-types = "0.8.3"
wasmcloud-operator-types = { version = "*", path = "./crates/types" }
[workspace]

View File

@ -1,8 +1,9 @@
use k8s_openapi::api::core::v1::{Container, PodSpec, ResourceRequirements, Volume};
use kube::CustomResource;
use schemars::{gen::SchemaGenerator, schema::Schema, JsonSchema};
use schemars::{generate::SchemaGenerator, Schema, JsonSchema};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet};
use serde_json::json;
use std::collections::BTreeMap;
#[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema)]
#[cfg_attr(test, derive(Default))]
@ -166,35 +167,35 @@ pub struct OtelSignalConfiguration {
/// an optional field. It generates the OpenAPI schema for the PodSpec type the same way that
/// kube.rs does while dropping any required fields.
fn pod_schema(_gen: &mut SchemaGenerator) -> Schema {
let gen = schemars::gen::SchemaSettings::openapi3()
let gen = schemars::generate::SchemaSettings::openapi3()
.with(|s| {
s.inline_subschemas = true;
s.meta_schema = None;
})
.with_visitor(kube::core::schema::StructuralSchemaRewriter)
.with_transform(kube::core::schema::StructuralSchemaRewriter)
.into_generator();
let mut val = gen.into_root_schema_for::<PodSpec>();
// Drop `containers` as a required field, along with any others.
val.schema.object.as_mut().unwrap().required = BTreeSet::new();
val.schema.into()
val.as_object_mut().unwrap()["required"] = json!(Vec::<String>::new());
val
}
/// This is a workaround for the fact that we can't override the Container schema to make name
/// an optional field. It generates the OpenAPI schema for the Container type the same way that
/// kube.rs does while dropping any required fields.
fn container_schema(_gen: &mut SchemaGenerator) -> Schema {
let gen = schemars::gen::SchemaSettings::openapi3()
let gen = schemars::generate::SchemaSettings::openapi3()
.with(|s| {
s.inline_subschemas = true;
s.meta_schema = None;
})
.with_visitor(kube::core::schema::StructuralSchemaRewriter)
.with_transform(kube::core::schema::StructuralSchemaRewriter)
.into_generator();
let mut val = gen.into_root_schema_for::<Container>();
// Drop `name` as a required field as it will be filled in from container
// definition coming the controller that this configuration gets merged into.
val.schema.object.as_mut().unwrap().required = BTreeSet::new();
val.schema.into()
val.as_object_mut().unwrap()["required"] = json!(Vec::<String>::new());
val
}
fn default_host_replicas() -> u32 {

View File

@ -417,7 +417,7 @@ async fn pod_template(config: &WasmCloudHostConfig, ctx: Arc<Context>) -> Result
let mut volumes = vec![Volume {
name: "nats-config".to_string(),
config_map: Some(ConfigMapVolumeSource {
name: Some(config.name_any()),
name: config.name_any(),
..Default::default()
}),
..Default::default()
@ -485,14 +485,7 @@ async fn pod_template(config: &WasmCloudHostConfig, ctx: Arc<Context>) -> Result
// configmaps
if let Some(configmap_ref) = &authority.config_map {
let configmap_name = match &configmap_ref.name {
Some(s) => s,
None => {
return Err(Error::CertificateError(format!(
"Missing configmap name for authority '{authority_name}'"
)))
}
};
let configmap_name = &configmap_ref.name;
items = discover_configmap_certificates(
&config.namespace().unwrap_or_default(),
configmap_name,
@ -507,7 +500,7 @@ async fn pod_template(config: &WasmCloudHostConfig, ctx: Arc<Context>) -> Result
volumes.push(Volume {
name: volume_name.clone(),
config_map: Some(ConfigMapVolumeSource {
name: Some(configmap_name.to_string()),
name: configmap_name.to_string(),
..Default::default()
}),
..Default::default()

View File

@ -224,11 +224,13 @@ impl From<Vec<ModelSummary>> for ApplicationTable {
i.name,
i.deployed_version.unwrap_or("N/A".to_string()),
i.version,
match i.status {
match i.detailed_status.info.status_type {
StatusType::Undeployed => "Undeployed".to_string(),
StatusType::Reconciling => "Reconciling".to_string(),
StatusType::Deployed => "Deployed".to_string(),
StatusType::Failed => "Failed".to_string(),
StatusType::Waiting => "Waiting".to_string(),
StatusType::Unhealthy => "Unhealthy".to_string(),
},
],
})
@ -290,6 +292,8 @@ impl CombinedManifest {
StatusType::Reconciling => "Reconciling",
StatusType::Deployed => "Deployed",
StatusType::Failed => "Failed",
StatusType::Waiting => "Waiting",
StatusType::Unhealthy => "Unhealthy",
}
.to_string()
}
@ -569,6 +573,8 @@ pub async fn get_application(
StatusType::Reconciling => "Reconciling",
StatusType::Deployed => "Deployed",
StatusType::Failed => "Failed",
StatusType::Waiting => "Waiting",
StatusType::Unhealthy => "Unhealthy",
};
manifest_value["status"] = json!({
"phase": phase,

View File

@ -510,8 +510,8 @@ pub async fn create_or_update_service(
endpoints: ips
.iter()
.filter_map(|ip| {
ip.ip.as_ref().map(|i| Endpoint {
addresses: vec![i.clone()],
Some(Endpoint {
addresses: vec![ip.ip.clone()],
conditions: Some(EndpointConditions {
ready: Some(true),
serving: Some(true),
@ -568,7 +568,9 @@ fn http_server_component(manifest: &Manifest) -> Option<HttpServerComponent> {
if let Properties::Capability { properties } = &c.properties {
if properties
.image
.starts_with("ghcr.io/wasmcloud/http-server")
.as_ref()
.map(|i| i.starts_with("ghcr.io/wasmcloud/http-server"))
.unwrap_or(false)
{
return true;
}