diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d6dc958..6ea7a24 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -35,6 +35,7 @@ jobs: integration-tests: runs-on: ubuntu-latest + needs: unit-tests steps: - name: checkout repository diff --git a/Cargo.lock b/Cargo.lock index 0fdd22d..feee2b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,9 +88,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.16" +version = "1.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" dependencies = [ "shlex", ] @@ -167,9 +167,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -177,9 +177,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", @@ -331,6 +331,7 @@ name = "gateway-api" version = "0.15.0" dependencies = [ "anyhow", + "cfg-if", "delegate", "hyper-util", "k8s-openapi", @@ -602,9 +603,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -731,9 +732,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "lock_api" @@ -747,9 +748,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" @@ -765,9 +766,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] @@ -879,9 +880,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" +checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" dependencies = [ "memchr", "thiserror", @@ -890,9 +891,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" +checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5" dependencies = [ "pest", "pest_generator", @@ -900,9 +901,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" +checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841" dependencies = [ "pest", "pest_meta", @@ -913,9 +914,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" +checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0" dependencies = [ "once_cell", "pest", @@ -945,9 +946,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -969,13 +970,12 @@ checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha", "rand_core", - "zerocopy", ] [[package]] @@ -999,9 +999,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags", ] @@ -1063,9 +1063,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustls" -version = "0.23.25" +version = "0.23.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" +checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" dependencies = [ "log", "once_cell", @@ -1118,9 +1118,9 @@ checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" [[package]] name = "rustls-webpki" -version = "0.103.0" +version = "0.103.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" +checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" dependencies = [ "ring", "rustls-pki-types", @@ -1276,7 +1276,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.8.0", + "indexmap 2.9.0", "itoa", "ryu", "serde", @@ -1322,9 +1322,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "a1ee1aca2bc74ef9589efa7ccaa0f3752751399940356209b3fd80c078149b5e" dependencies = [ "libc", ] @@ -1340,9 +1340,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "socket2" @@ -1767,18 +1767,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index cb23be1..63f3d35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,5 @@ tower = { version = "0.5.2", features = ["limit"] } tracing = "0.1.41" tracing-subscriber = "0.3.19" uuid = { version = "1.16.0", features = ["v4", "fast-rng"] } +cfg-if = "1.0" + diff --git a/gateway-api/Cargo.toml b/gateway-api/Cargo.toml index b65c236..106f313 100644 --- a/gateway-api/Cargo.toml +++ b/gateway-api/Cargo.toml @@ -16,13 +16,14 @@ version.workspace = true [dependencies] delegate.workspace = true k8s-openapi = { workspace = true, features = ["schemars"] } -kube = { workspace = true, default-features = false, features = ["derive"] } +kube = { workspace = true, features = ["derive"] } once_cell.workspace = true regex.workspace = true schemars.workspace = true serde_json.workspace = true serde.workspace = true serde_yaml.workspace = true +cfg-if.workspace = true [dev-dependencies] k8s-openapi = { workspace = true, features = [ "v1_32", "schemars" ] } @@ -36,3 +37,7 @@ uuid.workspace = true [package.metadata.docs.rs] features = [ "k8s-openapi/v1_32" ] + +[features] +default = [] +experimental = [] diff --git a/gateway-api/src/apis/mod.rs b/gateway-api/src/apis/mod.rs deleted file mode 100644 index 7651e9f..0000000 --- a/gateway-api/src/apis/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod experimental; -pub mod standard; diff --git a/gateway-api/src/apis/experimental/constants.rs b/gateway-api/src/experimental/constants.rs similarity index 100% rename from gateway-api/src/apis/experimental/constants.rs rename to gateway-api/src/experimental/constants.rs diff --git a/gateway-api/src/apis/experimental/enum_defaults.rs b/gateway-api/src/experimental/enum_defaults.rs similarity index 100% rename from gateway-api/src/apis/experimental/enum_defaults.rs rename to gateway-api/src/experimental/enum_defaults.rs diff --git a/gateway-api/src/apis/experimental/gatewayclasses.rs b/gateway-api/src/experimental/gatewayclasses.rs similarity index 100% rename from gateway-api/src/apis/experimental/gatewayclasses.rs rename to gateway-api/src/experimental/gatewayclasses.rs diff --git a/gateway-api/src/apis/experimental/gateways.rs b/gateway-api/src/experimental/gateways.rs similarity index 100% rename from gateway-api/src/apis/experimental/gateways.rs rename to gateway-api/src/experimental/gateways.rs diff --git a/gateway-api/src/apis/experimental/grpcroutes.rs b/gateway-api/src/experimental/grpcroutes.rs similarity index 100% rename from gateway-api/src/apis/experimental/grpcroutes.rs rename to gateway-api/src/experimental/grpcroutes.rs diff --git a/gateway-api/src/apis/experimental/httproutes.rs b/gateway-api/src/experimental/httproutes.rs similarity index 100% rename from gateway-api/src/apis/experimental/httproutes.rs rename to gateway-api/src/experimental/httproutes.rs diff --git a/gateway-api/src/apis/experimental/mod.rs b/gateway-api/src/experimental/mod.rs similarity index 100% rename from gateway-api/src/apis/experimental/mod.rs rename to gateway-api/src/experimental/mod.rs diff --git a/gateway-api/src/apis/experimental/referencegrants.rs b/gateway-api/src/experimental/referencegrants.rs similarity index 100% rename from gateway-api/src/apis/experimental/referencegrants.rs rename to gateway-api/src/experimental/referencegrants.rs diff --git a/gateway-api/src/apis/experimental/tcproutes.rs b/gateway-api/src/experimental/tcproutes.rs similarity index 100% rename from gateway-api/src/apis/experimental/tcproutes.rs rename to gateway-api/src/experimental/tcproutes.rs diff --git a/gateway-api/src/apis/experimental/tlsroutes.rs b/gateway-api/src/experimental/tlsroutes.rs similarity index 100% rename from gateway-api/src/apis/experimental/tlsroutes.rs rename to gateway-api/src/experimental/tlsroutes.rs diff --git a/gateway-api/src/apis/experimental/udproutes.rs b/gateway-api/src/experimental/udproutes.rs similarity index 100% rename from gateway-api/src/apis/experimental/udproutes.rs rename to gateway-api/src/experimental/udproutes.rs diff --git a/gateway-api/src/lib.rs b/gateway-api/src/lib.rs index dc3fbc1..2c62f92 100644 --- a/gateway-api/src/lib.rs +++ b/gateway-api/src/lib.rs @@ -1,7 +1,15 @@ -pub mod apis; - pub mod duration; pub use duration::Duration; +pub mod standard; +pub use standard::*; + +cfg_if::cfg_if! { + if #[cfg(feature = "experimental")] { + pub mod experimental; + } else { + + } +} #[cfg(test)] mod tests { @@ -22,7 +30,7 @@ mod tests { use tower::ServiceBuilder; use uuid::Uuid; - use crate::apis::standard::{ + use crate::{ constants::{ GatewayConditionReason, GatewayConditionType, ListenerConditionReason, ListenerConditionType, diff --git a/gateway-api/src/apis/standard/constants.rs b/gateway-api/src/standard/constants.rs similarity index 100% rename from gateway-api/src/apis/standard/constants.rs rename to gateway-api/src/standard/constants.rs diff --git a/gateway-api/src/apis/standard/enum_defaults.rs b/gateway-api/src/standard/enum_defaults.rs similarity index 77% rename from gateway-api/src/apis/standard/enum_defaults.rs rename to gateway-api/src/standard/enum_defaults.rs index 95996d5..3fee275 100644 --- a/gateway-api/src/apis/standard/enum_defaults.rs +++ b/gateway-api/src/standard/enum_defaults.rs @@ -7,6 +7,20 @@ use super::httproutes::{ HTTPRouteRulesFiltersUrlRewritePathType, }; +use super::grpcroutes::{GRPCRouteRulesBackendRefsFiltersType, GRPCRouteRulesFiltersType}; + +impl Default for GRPCRouteRulesBackendRefsFiltersType { + fn default() -> Self { + GRPCRouteRulesBackendRefsFiltersType::RequestHeaderModifier + } +} + +impl Default for GRPCRouteRulesFiltersType { + fn default() -> Self { + GRPCRouteRulesFiltersType::RequestHeaderModifier + } +} + impl Default for HTTPRouteRulesBackendRefsFiltersRequestRedirectPathType { fn default() -> Self { HTTPRouteRulesBackendRefsFiltersRequestRedirectPathType::ReplaceFullPath diff --git a/gateway-api/src/apis/standard/gatewayclasses.rs b/gateway-api/src/standard/gatewayclasses.rs similarity index 100% rename from gateway-api/src/apis/standard/gatewayclasses.rs rename to gateway-api/src/standard/gatewayclasses.rs diff --git a/gateway-api/src/apis/standard/gateways.rs b/gateway-api/src/standard/gateways.rs similarity index 100% rename from gateway-api/src/apis/standard/gateways.rs rename to gateway-api/src/standard/gateways.rs diff --git a/gateway-api/src/standard/grpcroutes.rs b/gateway-api/src/standard/grpcroutes.rs new file mode 100644 index 0000000..0353700 --- /dev/null +++ b/gateway-api/src/standard/grpcroutes.rs @@ -0,0 +1,1556 @@ +// WARNING: generated by kopium - manual changes will be overwritten +// kopium command: kopium --schema=derived --derive=JsonSchema --derive=Default --derive=PartialEq --docs -f - +// kopium version: 0.21.1 + +#[allow(unused_imports)] +mod prelude { + pub use k8s_openapi::apimachinery::pkg::apis::meta::v1::Condition; + pub use kube::CustomResource; + pub use schemars::JsonSchema; + pub use serde::{Deserialize, Serialize}; +} +use self::prelude::*; + +/// Spec defines the desired state of GRPCRoute. +#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +#[kube( + group = "gateway.networking.k8s.io", + version = "v1", + kind = "GRPCRoute", + plural = "grpcroutes" +)] +#[kube(namespaced)] +#[kube(status = "GRPCRouteStatus")] +#[kube(derive = "Default")] +#[kube(derive = "PartialEq")] +pub struct GRPCRouteSpec { + /// Hostnames defines a set of hostnames to match against the GRPC + /// Host header to select a GRPCRoute to process the request. This matches + /// the RFC 1123 definition of a hostname with 2 notable exceptions: + /// + /// 1. IPs are not allowed. + /// 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + /// label MUST appear by itself as the first label. + /// + /// If a hostname is specified by both the Listener and GRPCRoute, there + /// MUST be at least one intersecting hostname for the GRPCRoute to be + /// attached to the Listener. For example: + /// + /// * A Listener with `test.example.com` as the hostname matches GRPCRoutes + /// that have either not specified any hostnames, or have specified at + /// least one of `test.example.com` or `*.example.com`. + /// * A Listener with `*.example.com` as the hostname matches GRPCRoutes + /// that have either not specified any hostnames or have specified at least + /// one hostname that matches the Listener hostname. For example, + /// `test.example.com` and `*.example.com` would both match. On the other + /// hand, `example.com` and `test.example.net` would not match. + /// + /// Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + /// as a suffix match. That means that a match for `*.example.com` would match + /// both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + /// + /// If both the Listener and GRPCRoute have specified hostnames, any + /// GRPCRoute hostnames that do not match the Listener hostname MUST be + /// ignored. For example, if a Listener specified `*.example.com`, and the + /// GRPCRoute specified `test.example.com` and `test.example.net`, + /// `test.example.net` MUST NOT be considered for a match. + /// + /// If both the Listener and GRPCRoute have specified hostnames, and none + /// match with the criteria above, then the GRPCRoute MUST NOT be accepted by + /// the implementation. The implementation MUST raise an 'Accepted' Condition + /// with a status of `False` in the corresponding RouteParentStatus. + /// + /// If a Route (A) of type HTTPRoute or GRPCRoute is attached to a + /// Listener and that listener already has another Route (B) of the other + /// type attached and the intersection of the hostnames of A and B is + /// non-empty, then the implementation MUST accept exactly one of these two + /// routes, determined by the following criteria, in order: + /// + /// * The oldest Route based on creation timestamp. + /// * The Route appearing first in alphabetical order by + /// "{namespace}/{name}". + /// + /// The rejected Route MUST raise an 'Accepted' condition with a status of + /// 'False' in the corresponding RouteParentStatus. + /// + /// Support: Core + #[serde(default, skip_serializing_if = "Option::is_none")] + pub hostnames: Option>, + /// ParentRefs references the resources (usually Gateways) that a Route wants + /// to be attached to. Note that the referenced parent resource needs to + /// allow this for the attachment to be complete. For Gateways, that means + /// the Gateway needs to allow attachment from Routes of this kind and + /// namespace. For Services, that means the Service must either be in the same + /// namespace for a "producer" route, or the mesh implementation must support + /// and allow "consumer" routes for the referenced Service. ReferenceGrant is + /// not applicable for governing ParentRefs to Services - it is not possible to + /// create a "producer" route for a Service in a different namespace from the + /// Route. + /// + /// There are two kinds of parent resources with "Core" support: + /// + /// * Gateway (Gateway conformance profile) + /// * Service (Mesh conformance profile, ClusterIP Services only) + /// + /// This API may be extended in the future to support additional kinds of parent + /// resources. + /// + /// ParentRefs must be _distinct_. This means either that: + /// + /// * They select different objects. If this is the case, then parentRef + /// entries are distinct. In terms of fields, this means that the + /// multi-part key defined by `group`, `kind`, `namespace`, and `name` must + /// be unique across all parentRef entries in the Route. + /// * They do not select different objects, but for each optional field used, + /// each ParentRef that selects the same object must set the same set of + /// optional fields to different values. If one ParentRef sets a + /// combination of optional fields, all must set the same combination. + /// + /// Some examples: + /// + /// * If one ParentRef sets `sectionName`, all ParentRefs referencing the + /// same object must also set `sectionName`. + /// * If one ParentRef sets `port`, all ParentRefs referencing the same + /// object must also set `port`. + /// * If one ParentRef sets `sectionName` and `port`, all ParentRefs + /// referencing the same object must also set `sectionName` and `port`. + /// + /// It is possible to separately reference multiple distinct objects that may + /// be collapsed by an implementation. For example, some implementations may + /// choose to merge compatible Gateway Listeners together. If that is the + /// case, the list of routes attached to those resources should also be + /// merged. + /// + /// Note that for ParentRefs that cross namespace boundaries, there are specific + /// rules. Cross-namespace references are only valid if they are explicitly + /// allowed by something in the namespace they are referring to. For example, + /// Gateway has the AllowedRoutes field, and ReferenceGrant provides a + /// generic way to enable other kinds of cross-namespace reference. + /// + /// + /// + /// + /// + /// + /// + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "parentRefs" + )] + pub parent_refs: Option>, + /// Rules are a list of GRPC matchers, filters and actions. + /// + /// + #[serde(default, skip_serializing_if = "Option::is_none")] + pub rules: Option>, +} + +/// ParentReference identifies an API object (usually a Gateway) that can be considered +/// a parent of this resource (usually a route). There are two kinds of parent resources +/// with "Core" support: +/// +/// * Gateway (Gateway conformance profile) +/// * Service (Mesh conformance profile, ClusterIP Services only) +/// +/// This API may be extended in the future to support additional kinds of parent +/// resources. +/// +/// The API object must be valid in the cluster; the Group and Kind must +/// be registered in the cluster for this reference to be valid. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteParentRefs { + /// Group is the group of the referent. + /// When unspecified, "gateway.networking.k8s.io" is inferred. + /// To set the core API group (such as for a "Service" kind referent), + /// Group must be explicitly set to "" (empty string). + /// + /// Support: Core + #[serde(default, skip_serializing_if = "Option::is_none")] + pub group: Option, + /// Kind is kind of the referent. + /// + /// There are two kinds of parent resources with "Core" support: + /// + /// * Gateway (Gateway conformance profile) + /// * Service (Mesh conformance profile, ClusterIP Services only) + /// + /// Support for other resources is Implementation-Specific. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub kind: Option, + /// Name is the name of the referent. + /// + /// Support: Core + pub name: String, + /// Namespace is the namespace of the referent. When unspecified, this refers + /// to the local namespace of the Route. + /// + /// Note that there are specific rules for ParentRefs which cross namespace + /// boundaries. Cross-namespace references are only valid if they are explicitly + /// allowed by something in the namespace they are referring to. For example: + /// Gateway has the AllowedRoutes field, and ReferenceGrant provides a + /// generic way to enable any other kind of cross-namespace reference. + /// + /// + /// + /// Support: Core + #[serde(default, skip_serializing_if = "Option::is_none")] + pub namespace: Option, + /// Port is the network port this Route targets. It can be interpreted + /// differently based on the type of parent resource. + /// + /// When the parent resource is a Gateway, this targets all listeners + /// listening on the specified port that also support this kind of Route(and + /// select this Route). It's not recommended to set `Port` unless the + /// networking behaviors specified in a Route must apply to a specific port + /// as opposed to a listener(s) whose port(s) may be changed. When both Port + /// and SectionName are specified, the name and port of the selected listener + /// must match both specified values. + /// + /// + /// + /// Implementations MAY choose to support other parent resources. + /// Implementations supporting other types of parent resources MUST clearly + /// document how/if Port is interpreted. + /// + /// For the purpose of status, an attachment is considered successful as + /// long as the parent resource accepts it partially. For example, Gateway + /// listeners can restrict which Routes can attach to them by Route kind, + /// namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + /// from the referencing Route, the Route MUST be considered successfully + /// attached. If no Gateway listeners accept attachment from this Route, + /// the Route MUST be considered detached from the Gateway. + /// + /// Support: Extended + #[serde(default, skip_serializing_if = "Option::is_none")] + pub port: Option, + /// SectionName is the name of a section within the target resource. In the + /// following resources, SectionName is interpreted as the following: + /// + /// * Gateway: Listener name. When both Port (experimental) and SectionName + /// are specified, the name and port of the selected listener must match + /// both specified values. + /// * Service: Port name. When both Port (experimental) and SectionName + /// are specified, the name and port of the selected listener must match + /// both specified values. + /// + /// Implementations MAY choose to support attaching Routes to other resources. + /// If that is the case, they MUST clearly document how SectionName is + /// interpreted. + /// + /// When unspecified (empty string), this will reference the entire resource. + /// For the purpose of status, an attachment is considered successful if at + /// least one section in the parent resource accepts it. For example, Gateway + /// listeners can restrict which Routes can attach to them by Route kind, + /// namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + /// the referencing Route, the Route MUST be considered successfully + /// attached. If no Gateway listeners accept attachment from this Route, the + /// Route MUST be considered detached from the Gateway. + /// + /// Support: Core + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "sectionName" + )] + pub section_name: Option, +} + +/// GRPCRouteRule defines the semantics for matching a gRPC request based on +/// conditions (matches), processing it (filters), and forwarding the request to +/// an API object (backendRefs). +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRules { + /// BackendRefs defines the backend(s) where matching requests should be + /// sent. + /// + /// Failure behavior here depends on how many BackendRefs are specified and + /// how many are invalid. + /// + /// If *all* entries in BackendRefs are invalid, and there are also no filters + /// specified in this route rule, *all* traffic which matches this rule MUST + /// receive an `UNAVAILABLE` status. + /// + /// See the GRPCBackendRef definition for the rules about what makes a single + /// GRPCBackendRef invalid. + /// + /// When a GRPCBackendRef is invalid, `UNAVAILABLE` statuses MUST be returned for + /// requests that would have otherwise been routed to an invalid backend. If + /// multiple backends are specified, and some are invalid, the proportion of + /// requests that would otherwise have been routed to an invalid backend + /// MUST receive an `UNAVAILABLE` status. + /// + /// For example, if two backends are specified with equal weights, and one is + /// invalid, 50 percent of traffic MUST receive an `UNAVAILABLE` status. + /// Implementations may choose how that 50 percent is determined. + /// + /// Support: Core for Kubernetes Service + /// + /// Support: Implementation-specific for any other resource + /// + /// Support for weight: Core + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "backendRefs" + )] + pub backend_refs: Option>, + /// Filters define the filters that are applied to requests that match + /// this rule. + /// + /// The effects of ordering of multiple behaviors are currently unspecified. + /// This can change in the future based on feedback during the alpha stage. + /// + /// Conformance-levels at this level are defined based on the type of filter: + /// + /// - ALL core filters MUST be supported by all implementations that support + /// GRPCRoute. + /// - Implementers are encouraged to support extended filters. + /// - Implementation-specific custom filters have no API guarantees across + /// implementations. + /// + /// Specifying the same filter multiple times is not supported unless explicitly + /// indicated in the filter. + /// + /// If an implementation can not support a combination of filters, it must clearly + /// document that limitation. In cases where incompatible or unsupported + /// filters are specified and cause the `Accepted` condition to be set to status + /// `False`, implementations may use the `IncompatibleFilters` reason to specify + /// this configuration error. + /// + /// Support: Core + #[serde(default, skip_serializing_if = "Option::is_none")] + pub filters: Option>, + /// Matches define conditions used for matching the rule against incoming + /// gRPC requests. Each match is independent, i.e. this rule will be matched + /// if **any** one of the matches is satisfied. + /// + /// For example, take the following matches configuration: + /// + /// ```text + /// matches: + /// - method: + /// service: foo.bar + /// headers: + /// values: + /// version: 2 + /// - method: + /// service: foo.bar.v2 + /// ``` + /// + /// For a request to match against this rule, it MUST satisfy + /// EITHER of the two conditions: + /// + /// - service of foo.bar AND contains the header `version: 2` + /// - service of foo.bar.v2 + /// + /// See the documentation for GRPCRouteMatch on how to specify multiple + /// match conditions to be ANDed together. + /// + /// If no matches are specified, the implementation MUST match every gRPC request. + /// + /// Proxy or Load Balancer routing configuration generated from GRPCRoutes + /// MUST prioritize rules based on the following criteria, continuing on + /// ties. Merging MUST not be done between GRPCRoutes and HTTPRoutes. + /// Precedence MUST be given to the rule with the largest number of: + /// + /// * Characters in a matching non-wildcard hostname. + /// * Characters in a matching hostname. + /// * Characters in a matching service. + /// * Characters in a matching method. + /// * Header matches. + /// + /// If ties still exist across multiple Routes, matching precedence MUST be + /// determined in order of the following criteria, continuing on ties: + /// + /// * The oldest Route based on creation timestamp. + /// * The Route appearing first in alphabetical order by + /// "{namespace}/{name}". + /// + /// If ties still exist within the Route that has been given precedence, + /// matching precedence MUST be granted to the first matching rule meeting + /// the above criteria. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub matches: Option>, +} + +/// GRPCBackendRef defines how a GRPCRoute forwards a gRPC request. +/// +/// Note that when a namespace different than the local namespace is specified, a +/// ReferenceGrant object is required in the referent namespace to allow that +/// namespace's owner to accept the reference. See the ReferenceGrant +/// documentation for details. +/// +/// +/// +/// When the BackendRef points to a Kubernetes Service, implementations SHOULD +/// honor the appProtocol field if it is set for the target Service Port. +/// +/// Implementations supporting appProtocol SHOULD recognize the Kubernetes +/// Standard Application Protocols defined in KEP-3726. +/// +/// If a Service appProtocol isn't specified, an implementation MAY infer the +/// backend protocol through its own means. Implementations MAY infer the +/// protocol from the Route type referring to the backend Service. +/// +/// If a Route is not able to send traffic to the backend using the specified +/// protocol then the backend is considered invalid. Implementations MUST set the +/// "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. +/// +/// +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesBackendRefs { + /// Filters defined at this level MUST be executed if and only if the + /// request is being forwarded to the backend defined here. + /// + /// Support: Implementation-specific (For broader support of filters, use the + /// Filters field in GRPCRouteRule.) + #[serde(default, skip_serializing_if = "Option::is_none")] + pub filters: Option>, + /// Group is the group of the referent. For example, "gateway.networking.k8s.io". + /// When unspecified or empty string, core API group is inferred. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub group: Option, + /// Kind is the Kubernetes resource kind of the referent. For example + /// "Service". + /// + /// Defaults to "Service" when not specified. + /// + /// ExternalName services can refer to CNAME DNS records that may live + /// outside of the cluster and as such are difficult to reason about in + /// terms of conformance. They also may not be safe to forward to (see + /// CVE-2021-25740 for more information). Implementations SHOULD NOT + /// support ExternalName Services. + /// + /// Support: Core (Services with a type other than ExternalName) + /// + /// Support: Implementation-specific (Services with type ExternalName) + #[serde(default, skip_serializing_if = "Option::is_none")] + pub kind: Option, + /// Name is the name of the referent. + pub name: String, + /// Namespace is the namespace of the backend. When unspecified, the local + /// namespace is inferred. + /// + /// Note that when a namespace different than the local namespace is specified, + /// a ReferenceGrant object is required in the referent namespace to allow that + /// namespace's owner to accept the reference. See the ReferenceGrant + /// documentation for details. + /// + /// Support: Core + #[serde(default, skip_serializing_if = "Option::is_none")] + pub namespace: Option, + /// Port specifies the destination port number to use for this resource. + /// Port is required when the referent is a Kubernetes Service. In this + /// case, the port number is the service port number, not the target port. + /// For other resources, destination port might be derived from the referent + /// resource or this field. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub port: Option, + /// Weight specifies the proportion of requests forwarded to the referenced + /// backend. This is computed as weight/(sum of all weights in this + /// BackendRefs list). For non-zero values, there may be some epsilon from + /// the exact proportion defined here depending on the precision an + /// implementation supports. Weight is not a percentage and the sum of + /// weights does not need to equal 100. + /// + /// If only one backend is specified and it has a weight greater than 0, 100% + /// of the traffic is forwarded to that backend. If weight is set to 0, no + /// traffic should be forwarded for this entry. If unspecified, weight + /// defaults to 1. + /// + /// Support for this field varies based on the context where used. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub weight: Option, +} + +/// GRPCRouteFilter defines processing steps that must be completed during the +/// request or response lifecycle. GRPCRouteFilters are meant as an extension +/// point to express processing that may be done in Gateway implementations. Some +/// examples include request or response modification, implementing +/// authentication strategies, rate-limiting, and traffic shaping. API +/// guarantee/conformance is defined based on the type of the filter. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesBackendRefsFilters { + /// ExtensionRef is an optional, implementation-specific extension to the + /// "filter" behavior. For example, resource "myroutefilter" in group + /// "networking.example.net"). ExtensionRef MUST NOT be used for core and + /// extended filters. + /// + /// Support: Implementation-specific + /// + /// This filter can be used multiple times within the same rule. + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "extensionRef" + )] + pub extension_ref: Option, + /// RequestHeaderModifier defines a schema for a filter that modifies request + /// headers. + /// + /// Support: Core + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "requestHeaderModifier" + )] + pub request_header_modifier: Option, + /// RequestMirror defines a schema for a filter that mirrors requests. + /// Requests are sent to the specified destination, but responses from + /// that destination are ignored. + /// + /// This filter can be used multiple times within the same rule. Note that + /// not all implementations will be able to support mirroring to multiple + /// backends. + /// + /// Support: Extended + /// + /// + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "requestMirror" + )] + pub request_mirror: Option, + /// ResponseHeaderModifier defines a schema for a filter that modifies response + /// headers. + /// + /// Support: Extended + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "responseHeaderModifier" + )] + pub response_header_modifier: Option, + /// Type identifies the type of filter to apply. As with other API fields, + /// types are classified into three conformance levels: + /// + /// - Core: Filter types and their corresponding configuration defined by + /// "Support: Core" in this package, e.g. "RequestHeaderModifier". All + /// implementations supporting GRPCRoute MUST support core filters. + /// + /// - Extended: Filter types and their corresponding configuration defined by + /// "Support: Extended" in this package, e.g. "RequestMirror". Implementers + /// are encouraged to support extended filters. + /// + /// - Implementation-specific: Filters that are defined and supported by specific vendors. + /// In the future, filters showing convergence in behavior across multiple + /// implementations will be considered for inclusion in extended or core + /// conformance levels. Filter-specific configuration for such filters + /// is specified using the ExtensionRef field. `Type` MUST be set to + /// "ExtensionRef" for custom filters. + /// + /// Implementers are encouraged to define custom implementation types to + /// extend the core API with implementation-specific behavior. + /// + /// If a reference to a custom filter type cannot be resolved, the filter + /// MUST NOT be skipped. Instead, requests that would have been processed by + /// that filter MUST receive a HTTP error response. + /// + /// + #[serde(rename = "type")] + pub r#type: GRPCRouteRulesBackendRefsFiltersType, +} + +/// ExtensionRef is an optional, implementation-specific extension to the +/// "filter" behavior. For example, resource "myroutefilter" in group +/// "networking.example.net"). ExtensionRef MUST NOT be used for core and +/// extended filters. +/// +/// Support: Implementation-specific +/// +/// This filter can be used multiple times within the same rule. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesBackendRefsFiltersExtensionRef { + /// Group is the group of the referent. For example, "gateway.networking.k8s.io". + /// When unspecified or empty string, core API group is inferred. + pub group: String, + /// Kind is kind of the referent. For example "HTTPRoute" or "Service". + pub kind: String, + /// Name is the name of the referent. + pub name: String, +} + +/// RequestHeaderModifier defines a schema for a filter that modifies request +/// headers. +/// +/// Support: Core +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesBackendRefsFiltersRequestHeaderModifier { + /// Add adds the given header(s) (name, value) to the request + /// before the action. It appends to any existing values associated + /// with the header name. + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header: foo + /// + /// Config: + /// add: + /// - name: "my-header" + /// value: "bar,baz" + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header: foo,bar,baz + #[serde(default, skip_serializing_if = "Option::is_none")] + pub add: Option>, + /// Remove the given header(s) from the HTTP request before the action. The + /// value of Remove is a list of HTTP header names. Note that the header + /// names are case-insensitive (see + /// https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header1: foo + /// my-header2: bar + /// my-header3: baz + /// + /// Config: + /// remove: ["my-header1", "my-header3"] + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header2: bar + #[serde(default, skip_serializing_if = "Option::is_none")] + pub remove: Option>, + /// Set overwrites the request with the given header (name, value) + /// before the action. + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header: foo + /// + /// Config: + /// set: + /// - name: "my-header" + /// value: "bar" + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header: bar + #[serde(default, skip_serializing_if = "Option::is_none")] + pub set: Option>, +} + +/// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesBackendRefsFiltersRequestHeaderModifierAdd { + /// Name is the name of the HTTP Header to be matched. Name matching MUST be + /// case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + /// + /// If multiple entries specify equivalent header names, the first entry with + /// an equivalent name MUST be considered for a match. Subsequent entries + /// with an equivalent header name MUST be ignored. Due to the + /// case-insensitivity of header names, "foo" and "Foo" are considered + /// equivalent. + pub name: String, + /// Value is the value of HTTP Header to be matched. + pub value: String, +} + +/// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesBackendRefsFiltersRequestHeaderModifierSet { + /// Name is the name of the HTTP Header to be matched. Name matching MUST be + /// case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + /// + /// If multiple entries specify equivalent header names, the first entry with + /// an equivalent name MUST be considered for a match. Subsequent entries + /// with an equivalent header name MUST be ignored. Due to the + /// case-insensitivity of header names, "foo" and "Foo" are considered + /// equivalent. + pub name: String, + /// Value is the value of HTTP Header to be matched. + pub value: String, +} + +/// RequestMirror defines a schema for a filter that mirrors requests. +/// Requests are sent to the specified destination, but responses from +/// that destination are ignored. +/// +/// This filter can be used multiple times within the same rule. Note that +/// not all implementations will be able to support mirroring to multiple +/// backends. +/// +/// Support: Extended +/// +/// +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesBackendRefsFiltersRequestMirror { + /// BackendRef references a resource where mirrored requests are sent. + /// + /// Mirrored requests must be sent only to a single destination endpoint + /// within this BackendRef, irrespective of how many endpoints are present + /// within this BackendRef. + /// + /// If the referent cannot be found, this BackendRef is invalid and must be + /// dropped from the Gateway. The controller must ensure the "ResolvedRefs" + /// condition on the Route status is set to `status: False` and not configure + /// this backend in the underlying implementation. + /// + /// If there is a cross-namespace reference to an *existing* object + /// that is not allowed by a ReferenceGrant, the controller must ensure the + /// "ResolvedRefs" condition on the Route is set to `status: False`, + /// with the "RefNotPermitted" reason and not configure this backend in the + /// underlying implementation. + /// + /// In either error case, the Message of the `ResolvedRefs` Condition + /// should be used to provide more detail about the problem. + /// + /// Support: Extended for Kubernetes Service + /// + /// Support: Implementation-specific for any other resource + #[serde(rename = "backendRef")] + pub backend_ref: GRPCRouteRulesBackendRefsFiltersRequestMirrorBackendRef, +} + +/// BackendRef references a resource where mirrored requests are sent. +/// +/// Mirrored requests must be sent only to a single destination endpoint +/// within this BackendRef, irrespective of how many endpoints are present +/// within this BackendRef. +/// +/// If the referent cannot be found, this BackendRef is invalid and must be +/// dropped from the Gateway. The controller must ensure the "ResolvedRefs" +/// condition on the Route status is set to `status: False` and not configure +/// this backend in the underlying implementation. +/// +/// If there is a cross-namespace reference to an *existing* object +/// that is not allowed by a ReferenceGrant, the controller must ensure the +/// "ResolvedRefs" condition on the Route is set to `status: False`, +/// with the "RefNotPermitted" reason and not configure this backend in the +/// underlying implementation. +/// +/// In either error case, the Message of the `ResolvedRefs` Condition +/// should be used to provide more detail about the problem. +/// +/// Support: Extended for Kubernetes Service +/// +/// Support: Implementation-specific for any other resource +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesBackendRefsFiltersRequestMirrorBackendRef { + /// Group is the group of the referent. For example, "gateway.networking.k8s.io". + /// When unspecified or empty string, core API group is inferred. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub group: Option, + /// Kind is the Kubernetes resource kind of the referent. For example + /// "Service". + /// + /// Defaults to "Service" when not specified. + /// + /// ExternalName services can refer to CNAME DNS records that may live + /// outside of the cluster and as such are difficult to reason about in + /// terms of conformance. They also may not be safe to forward to (see + /// CVE-2021-25740 for more information). Implementations SHOULD NOT + /// support ExternalName Services. + /// + /// Support: Core (Services with a type other than ExternalName) + /// + /// Support: Implementation-specific (Services with type ExternalName) + #[serde(default, skip_serializing_if = "Option::is_none")] + pub kind: Option, + /// Name is the name of the referent. + pub name: String, + /// Namespace is the namespace of the backend. When unspecified, the local + /// namespace is inferred. + /// + /// Note that when a namespace different than the local namespace is specified, + /// a ReferenceGrant object is required in the referent namespace to allow that + /// namespace's owner to accept the reference. See the ReferenceGrant + /// documentation for details. + /// + /// Support: Core + #[serde(default, skip_serializing_if = "Option::is_none")] + pub namespace: Option, + /// Port specifies the destination port number to use for this resource. + /// Port is required when the referent is a Kubernetes Service. In this + /// case, the port number is the service port number, not the target port. + /// For other resources, destination port might be derived from the referent + /// resource or this field. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub port: Option, +} + +/// ResponseHeaderModifier defines a schema for a filter that modifies response +/// headers. +/// +/// Support: Extended +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesBackendRefsFiltersResponseHeaderModifier { + /// Add adds the given header(s) (name, value) to the request + /// before the action. It appends to any existing values associated + /// with the header name. + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header: foo + /// + /// Config: + /// add: + /// - name: "my-header" + /// value: "bar,baz" + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header: foo,bar,baz + #[serde(default, skip_serializing_if = "Option::is_none")] + pub add: Option>, + /// Remove the given header(s) from the HTTP request before the action. The + /// value of Remove is a list of HTTP header names. Note that the header + /// names are case-insensitive (see + /// https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header1: foo + /// my-header2: bar + /// my-header3: baz + /// + /// Config: + /// remove: ["my-header1", "my-header3"] + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header2: bar + #[serde(default, skip_serializing_if = "Option::is_none")] + pub remove: Option>, + /// Set overwrites the request with the given header (name, value) + /// before the action. + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header: foo + /// + /// Config: + /// set: + /// - name: "my-header" + /// value: "bar" + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header: bar + #[serde(default, skip_serializing_if = "Option::is_none")] + pub set: Option>, +} + +/// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesBackendRefsFiltersResponseHeaderModifierAdd { + /// Name is the name of the HTTP Header to be matched. Name matching MUST be + /// case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + /// + /// If multiple entries specify equivalent header names, the first entry with + /// an equivalent name MUST be considered for a match. Subsequent entries + /// with an equivalent header name MUST be ignored. Due to the + /// case-insensitivity of header names, "foo" and "Foo" are considered + /// equivalent. + pub name: String, + /// Value is the value of HTTP Header to be matched. + pub value: String, +} + +/// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesBackendRefsFiltersResponseHeaderModifierSet { + /// Name is the name of the HTTP Header to be matched. Name matching MUST be + /// case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + /// + /// If multiple entries specify equivalent header names, the first entry with + /// an equivalent name MUST be considered for a match. Subsequent entries + /// with an equivalent header name MUST be ignored. Due to the + /// case-insensitivity of header names, "foo" and "Foo" are considered + /// equivalent. + pub name: String, + /// Value is the value of HTTP Header to be matched. + pub value: String, +} + +/// GRPCRouteFilter defines processing steps that must be completed during the +/// request or response lifecycle. GRPCRouteFilters are meant as an extension +/// point to express processing that may be done in Gateway implementations. Some +/// examples include request or response modification, implementing +/// authentication strategies, rate-limiting, and traffic shaping. API +/// guarantee/conformance is defined based on the type of the filter. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq)] +pub enum GRPCRouteRulesBackendRefsFiltersType { + ResponseHeaderModifier, + RequestHeaderModifier, + RequestMirror, + ExtensionRef, +} + +/// GRPCRouteFilter defines processing steps that must be completed during the +/// request or response lifecycle. GRPCRouteFilters are meant as an extension +/// point to express processing that may be done in Gateway implementations. Some +/// examples include request or response modification, implementing +/// authentication strategies, rate-limiting, and traffic shaping. API +/// guarantee/conformance is defined based on the type of the filter. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesFilters { + /// ExtensionRef is an optional, implementation-specific extension to the + /// "filter" behavior. For example, resource "myroutefilter" in group + /// "networking.example.net"). ExtensionRef MUST NOT be used for core and + /// extended filters. + /// + /// Support: Implementation-specific + /// + /// This filter can be used multiple times within the same rule. + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "extensionRef" + )] + pub extension_ref: Option, + /// RequestHeaderModifier defines a schema for a filter that modifies request + /// headers. + /// + /// Support: Core + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "requestHeaderModifier" + )] + pub request_header_modifier: Option, + /// RequestMirror defines a schema for a filter that mirrors requests. + /// Requests are sent to the specified destination, but responses from + /// that destination are ignored. + /// + /// This filter can be used multiple times within the same rule. Note that + /// not all implementations will be able to support mirroring to multiple + /// backends. + /// + /// Support: Extended + /// + /// + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "requestMirror" + )] + pub request_mirror: Option, + /// ResponseHeaderModifier defines a schema for a filter that modifies response + /// headers. + /// + /// Support: Extended + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "responseHeaderModifier" + )] + pub response_header_modifier: Option, + /// Type identifies the type of filter to apply. As with other API fields, + /// types are classified into three conformance levels: + /// + /// - Core: Filter types and their corresponding configuration defined by + /// "Support: Core" in this package, e.g. "RequestHeaderModifier". All + /// implementations supporting GRPCRoute MUST support core filters. + /// + /// - Extended: Filter types and their corresponding configuration defined by + /// "Support: Extended" in this package, e.g. "RequestMirror". Implementers + /// are encouraged to support extended filters. + /// + /// - Implementation-specific: Filters that are defined and supported by specific vendors. + /// In the future, filters showing convergence in behavior across multiple + /// implementations will be considered for inclusion in extended or core + /// conformance levels. Filter-specific configuration for such filters + /// is specified using the ExtensionRef field. `Type` MUST be set to + /// "ExtensionRef" for custom filters. + /// + /// Implementers are encouraged to define custom implementation types to + /// extend the core API with implementation-specific behavior. + /// + /// If a reference to a custom filter type cannot be resolved, the filter + /// MUST NOT be skipped. Instead, requests that would have been processed by + /// that filter MUST receive a HTTP error response. + /// + /// + #[serde(rename = "type")] + pub r#type: GRPCRouteRulesFiltersType, +} + +/// ExtensionRef is an optional, implementation-specific extension to the +/// "filter" behavior. For example, resource "myroutefilter" in group +/// "networking.example.net"). ExtensionRef MUST NOT be used for core and +/// extended filters. +/// +/// Support: Implementation-specific +/// +/// This filter can be used multiple times within the same rule. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesFiltersExtensionRef { + /// Group is the group of the referent. For example, "gateway.networking.k8s.io". + /// When unspecified or empty string, core API group is inferred. + pub group: String, + /// Kind is kind of the referent. For example "HTTPRoute" or "Service". + pub kind: String, + /// Name is the name of the referent. + pub name: String, +} + +/// RequestHeaderModifier defines a schema for a filter that modifies request +/// headers. +/// +/// Support: Core +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesFiltersRequestHeaderModifier { + /// Add adds the given header(s) (name, value) to the request + /// before the action. It appends to any existing values associated + /// with the header name. + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header: foo + /// + /// Config: + /// add: + /// - name: "my-header" + /// value: "bar,baz" + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header: foo,bar,baz + #[serde(default, skip_serializing_if = "Option::is_none")] + pub add: Option>, + /// Remove the given header(s) from the HTTP request before the action. The + /// value of Remove is a list of HTTP header names. Note that the header + /// names are case-insensitive (see + /// https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header1: foo + /// my-header2: bar + /// my-header3: baz + /// + /// Config: + /// remove: ["my-header1", "my-header3"] + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header2: bar + #[serde(default, skip_serializing_if = "Option::is_none")] + pub remove: Option>, + /// Set overwrites the request with the given header (name, value) + /// before the action. + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header: foo + /// + /// Config: + /// set: + /// - name: "my-header" + /// value: "bar" + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header: bar + #[serde(default, skip_serializing_if = "Option::is_none")] + pub set: Option>, +} + +/// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesFiltersRequestHeaderModifierAdd { + /// Name is the name of the HTTP Header to be matched. Name matching MUST be + /// case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + /// + /// If multiple entries specify equivalent header names, the first entry with + /// an equivalent name MUST be considered for a match. Subsequent entries + /// with an equivalent header name MUST be ignored. Due to the + /// case-insensitivity of header names, "foo" and "Foo" are considered + /// equivalent. + pub name: String, + /// Value is the value of HTTP Header to be matched. + pub value: String, +} + +/// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesFiltersRequestHeaderModifierSet { + /// Name is the name of the HTTP Header to be matched. Name matching MUST be + /// case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + /// + /// If multiple entries specify equivalent header names, the first entry with + /// an equivalent name MUST be considered for a match. Subsequent entries + /// with an equivalent header name MUST be ignored. Due to the + /// case-insensitivity of header names, "foo" and "Foo" are considered + /// equivalent. + pub name: String, + /// Value is the value of HTTP Header to be matched. + pub value: String, +} + +/// RequestMirror defines a schema for a filter that mirrors requests. +/// Requests are sent to the specified destination, but responses from +/// that destination are ignored. +/// +/// This filter can be used multiple times within the same rule. Note that +/// not all implementations will be able to support mirroring to multiple +/// backends. +/// +/// Support: Extended +/// +/// +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesFiltersRequestMirror { + /// BackendRef references a resource where mirrored requests are sent. + /// + /// Mirrored requests must be sent only to a single destination endpoint + /// within this BackendRef, irrespective of how many endpoints are present + /// within this BackendRef. + /// + /// If the referent cannot be found, this BackendRef is invalid and must be + /// dropped from the Gateway. The controller must ensure the "ResolvedRefs" + /// condition on the Route status is set to `status: False` and not configure + /// this backend in the underlying implementation. + /// + /// If there is a cross-namespace reference to an *existing* object + /// that is not allowed by a ReferenceGrant, the controller must ensure the + /// "ResolvedRefs" condition on the Route is set to `status: False`, + /// with the "RefNotPermitted" reason and not configure this backend in the + /// underlying implementation. + /// + /// In either error case, the Message of the `ResolvedRefs` Condition + /// should be used to provide more detail about the problem. + /// + /// Support: Extended for Kubernetes Service + /// + /// Support: Implementation-specific for any other resource + #[serde(rename = "backendRef")] + pub backend_ref: GRPCRouteRulesFiltersRequestMirrorBackendRef, +} + +/// BackendRef references a resource where mirrored requests are sent. +/// +/// Mirrored requests must be sent only to a single destination endpoint +/// within this BackendRef, irrespective of how many endpoints are present +/// within this BackendRef. +/// +/// If the referent cannot be found, this BackendRef is invalid and must be +/// dropped from the Gateway. The controller must ensure the "ResolvedRefs" +/// condition on the Route status is set to `status: False` and not configure +/// this backend in the underlying implementation. +/// +/// If there is a cross-namespace reference to an *existing* object +/// that is not allowed by a ReferenceGrant, the controller must ensure the +/// "ResolvedRefs" condition on the Route is set to `status: False`, +/// with the "RefNotPermitted" reason and not configure this backend in the +/// underlying implementation. +/// +/// In either error case, the Message of the `ResolvedRefs` Condition +/// should be used to provide more detail about the problem. +/// +/// Support: Extended for Kubernetes Service +/// +/// Support: Implementation-specific for any other resource +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesFiltersRequestMirrorBackendRef { + /// Group is the group of the referent. For example, "gateway.networking.k8s.io". + /// When unspecified or empty string, core API group is inferred. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub group: Option, + /// Kind is the Kubernetes resource kind of the referent. For example + /// "Service". + /// + /// Defaults to "Service" when not specified. + /// + /// ExternalName services can refer to CNAME DNS records that may live + /// outside of the cluster and as such are difficult to reason about in + /// terms of conformance. They also may not be safe to forward to (see + /// CVE-2021-25740 for more information). Implementations SHOULD NOT + /// support ExternalName Services. + /// + /// Support: Core (Services with a type other than ExternalName) + /// + /// Support: Implementation-specific (Services with type ExternalName) + #[serde(default, skip_serializing_if = "Option::is_none")] + pub kind: Option, + /// Name is the name of the referent. + pub name: String, + /// Namespace is the namespace of the backend. When unspecified, the local + /// namespace is inferred. + /// + /// Note that when a namespace different than the local namespace is specified, + /// a ReferenceGrant object is required in the referent namespace to allow that + /// namespace's owner to accept the reference. See the ReferenceGrant + /// documentation for details. + /// + /// Support: Core + #[serde(default, skip_serializing_if = "Option::is_none")] + pub namespace: Option, + /// Port specifies the destination port number to use for this resource. + /// Port is required when the referent is a Kubernetes Service. In this + /// case, the port number is the service port number, not the target port. + /// For other resources, destination port might be derived from the referent + /// resource or this field. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub port: Option, +} + +/// ResponseHeaderModifier defines a schema for a filter that modifies response +/// headers. +/// +/// Support: Extended +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesFiltersResponseHeaderModifier { + /// Add adds the given header(s) (name, value) to the request + /// before the action. It appends to any existing values associated + /// with the header name. + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header: foo + /// + /// Config: + /// add: + /// - name: "my-header" + /// value: "bar,baz" + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header: foo,bar,baz + #[serde(default, skip_serializing_if = "Option::is_none")] + pub add: Option>, + /// Remove the given header(s) from the HTTP request before the action. The + /// value of Remove is a list of HTTP header names. Note that the header + /// names are case-insensitive (see + /// https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header1: foo + /// my-header2: bar + /// my-header3: baz + /// + /// Config: + /// remove: ["my-header1", "my-header3"] + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header2: bar + #[serde(default, skip_serializing_if = "Option::is_none")] + pub remove: Option>, + /// Set overwrites the request with the given header (name, value) + /// before the action. + /// + /// Input: + /// GET /foo HTTP/1.1 + /// my-header: foo + /// + /// Config: + /// set: + /// - name: "my-header" + /// value: "bar" + /// + /// Output: + /// GET /foo HTTP/1.1 + /// my-header: bar + #[serde(default, skip_serializing_if = "Option::is_none")] + pub set: Option>, +} + +/// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesFiltersResponseHeaderModifierAdd { + /// Name is the name of the HTTP Header to be matched. Name matching MUST be + /// case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + /// + /// If multiple entries specify equivalent header names, the first entry with + /// an equivalent name MUST be considered for a match. Subsequent entries + /// with an equivalent header name MUST be ignored. Due to the + /// case-insensitivity of header names, "foo" and "Foo" are considered + /// equivalent. + pub name: String, + /// Value is the value of HTTP Header to be matched. + pub value: String, +} + +/// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesFiltersResponseHeaderModifierSet { + /// Name is the name of the HTTP Header to be matched. Name matching MUST be + /// case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + /// + /// If multiple entries specify equivalent header names, the first entry with + /// an equivalent name MUST be considered for a match. Subsequent entries + /// with an equivalent header name MUST be ignored. Due to the + /// case-insensitivity of header names, "foo" and "Foo" are considered + /// equivalent. + pub name: String, + /// Value is the value of HTTP Header to be matched. + pub value: String, +} + +/// GRPCRouteFilter defines processing steps that must be completed during the +/// request or response lifecycle. GRPCRouteFilters are meant as an extension +/// point to express processing that may be done in Gateway implementations. Some +/// examples include request or response modification, implementing +/// authentication strategies, rate-limiting, and traffic shaping. API +/// guarantee/conformance is defined based on the type of the filter. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq)] +pub enum GRPCRouteRulesFiltersType { + ResponseHeaderModifier, + RequestHeaderModifier, + RequestMirror, + ExtensionRef, +} + +/// GRPCRouteMatch defines the predicate used to match requests to a given +/// action. Multiple match types are ANDed together, i.e. the match will +/// evaluate to true only if all conditions are satisfied. +/// +/// For example, the match below will match a gRPC request only if its service +/// is `foo` AND it contains the `version: v1` header: +/// +/// ```text +/// matches: +/// - method: +/// type: Exact +/// service: "foo" +/// headers: +/// - name: "version" +/// value "v1" +/// +/// ``` +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesMatches { + /// Headers specifies gRPC request header matchers. Multiple match values are + /// ANDed together, meaning, a request MUST match all the specified headers + /// to select the route. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub headers: Option>, + /// Method specifies a gRPC request service/method matcher. If this field is + /// not specified, all services and methods will match. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub method: Option, +} + +/// GRPCHeaderMatch describes how to select a gRPC route by matching gRPC request +/// headers. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesMatchesHeaders { + /// Name is the name of the gRPC Header to be matched. + /// + /// If multiple entries specify equivalent header names, only the first + /// entry with an equivalent name MUST be considered for a match. Subsequent + /// entries with an equivalent header name MUST be ignored. Due to the + /// case-insensitivity of header names, "foo" and "Foo" are considered + /// equivalent. + pub name: String, + /// Type specifies how to match against the value of the header. + #[serde(default, skip_serializing_if = "Option::is_none", rename = "type")] + pub r#type: Option, + /// Value is the value of the gRPC Header to be matched. + pub value: String, +} + +/// GRPCHeaderMatch describes how to select a gRPC route by matching gRPC request +/// headers. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq)] +pub enum GRPCRouteRulesMatchesHeadersType { + Exact, + RegularExpression, +} + +/// Method specifies a gRPC request service/method matcher. If this field is +/// not specified, all services and methods will match. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteRulesMatchesMethod { + /// Value of the method to match against. If left empty or omitted, will + /// match all services. + /// + /// At least one of Service and Method MUST be a non-empty string. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub method: Option, + /// Value of the service to match against. If left empty or omitted, will + /// match any service. + /// + /// At least one of Service and Method MUST be a non-empty string. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub service: Option, + /// Type specifies how to match against the service and/or method. + /// Support: Core (Exact with service and method specified) + /// + /// Support: Implementation-specific (Exact with method specified but no service specified) + /// + /// Support: Implementation-specific (RegularExpression) + #[serde(default, skip_serializing_if = "Option::is_none", rename = "type")] + pub r#type: Option, +} + +/// Method specifies a gRPC request service/method matcher. If this field is +/// not specified, all services and methods will match. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq)] +pub enum GRPCRouteRulesMatchesMethodType { + Exact, + RegularExpression, +} + +/// Status defines the current state of GRPCRoute. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteStatus { + /// Parents is a list of parent resources (usually Gateways) that are + /// associated with the route, and the status of the route with respect to + /// each parent. When this route attaches to a parent, the controller that + /// manages the parent must add an entry to this list when the controller + /// first sees the route and should update the entry as appropriate when the + /// route or gateway is modified. + /// + /// Note that parent references that cannot be resolved by an implementation + /// of this API will not be added to this list. Implementations of this API + /// can only populate Route status for the Gateways/parent resources they are + /// responsible for. + /// + /// A maximum of 32 Gateways will be represented in this list. An empty list + /// means the route has not been attached to any Gateway. + pub parents: Vec, +} + +/// RouteParentStatus describes the status of a route with respect to an +/// associated Parent. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteStatusParents { + /// Conditions describes the status of the route with respect to the Gateway. + /// Note that the route's availability is also subject to the Gateway's own + /// status conditions and listener status. + /// + /// If the Route's ParentRef specifies an existing Gateway that supports + /// Routes of this kind AND that Gateway's controller has sufficient access, + /// then that Gateway's controller MUST set the "Accepted" condition on the + /// Route, to indicate whether the route has been accepted or rejected by the + /// Gateway, and why. + /// + /// A Route MUST be considered "Accepted" if at least one of the Route's + /// rules is implemented by the Gateway. + /// + /// There are a number of cases where the "Accepted" condition may not be set + /// due to lack of controller visibility, that includes when: + /// + /// * The Route refers to a non-existent parent. + /// * The Route is of a type that the controller does not support. + /// * The Route is in a namespace the controller does not have access to. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub conditions: Option>, + /// ControllerName is a domain/path string that indicates the name of the + /// controller that wrote this status. This corresponds with the + /// controllerName field on GatewayClass. + /// + /// Example: "example.net/gateway-controller". + /// + /// The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + /// valid Kubernetes names + /// (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + /// + /// Controllers MUST populate this field when writing status. Controllers should ensure that + /// entries to status populated with their ControllerName are cleaned up when they are no + /// longer necessary. + #[serde(rename = "controllerName")] + pub controller_name: String, + /// ParentRef corresponds with a ParentRef in the spec that this + /// RouteParentStatus struct describes the status of. + #[serde(rename = "parentRef")] + pub parent_ref: GRPCRouteStatusParentsParentRef, +} + +/// ParentRef corresponds with a ParentRef in the spec that this +/// RouteParentStatus struct describes the status of. +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq)] +pub struct GRPCRouteStatusParentsParentRef { + /// Group is the group of the referent. + /// When unspecified, "gateway.networking.k8s.io" is inferred. + /// To set the core API group (such as for a "Service" kind referent), + /// Group must be explicitly set to "" (empty string). + /// + /// Support: Core + #[serde(default, skip_serializing_if = "Option::is_none")] + pub group: Option, + /// Kind is kind of the referent. + /// + /// There are two kinds of parent resources with "Core" support: + /// + /// * Gateway (Gateway conformance profile) + /// * Service (Mesh conformance profile, ClusterIP Services only) + /// + /// Support for other resources is Implementation-Specific. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub kind: Option, + /// Name is the name of the referent. + /// + /// Support: Core + pub name: String, + /// Namespace is the namespace of the referent. When unspecified, this refers + /// to the local namespace of the Route. + /// + /// Note that there are specific rules for ParentRefs which cross namespace + /// boundaries. Cross-namespace references are only valid if they are explicitly + /// allowed by something in the namespace they are referring to. For example: + /// Gateway has the AllowedRoutes field, and ReferenceGrant provides a + /// generic way to enable any other kind of cross-namespace reference. + /// + /// + /// + /// Support: Core + #[serde(default, skip_serializing_if = "Option::is_none")] + pub namespace: Option, + /// Port is the network port this Route targets. It can be interpreted + /// differently based on the type of parent resource. + /// + /// When the parent resource is a Gateway, this targets all listeners + /// listening on the specified port that also support this kind of Route(and + /// select this Route). It's not recommended to set `Port` unless the + /// networking behaviors specified in a Route must apply to a specific port + /// as opposed to a listener(s) whose port(s) may be changed. When both Port + /// and SectionName are specified, the name and port of the selected listener + /// must match both specified values. + /// + /// + /// + /// Implementations MAY choose to support other parent resources. + /// Implementations supporting other types of parent resources MUST clearly + /// document how/if Port is interpreted. + /// + /// For the purpose of status, an attachment is considered successful as + /// long as the parent resource accepts it partially. For example, Gateway + /// listeners can restrict which Routes can attach to them by Route kind, + /// namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + /// from the referencing Route, the Route MUST be considered successfully + /// attached. If no Gateway listeners accept attachment from this Route, + /// the Route MUST be considered detached from the Gateway. + /// + /// Support: Extended + #[serde(default, skip_serializing_if = "Option::is_none")] + pub port: Option, + /// SectionName is the name of a section within the target resource. In the + /// following resources, SectionName is interpreted as the following: + /// + /// * Gateway: Listener name. When both Port (experimental) and SectionName + /// are specified, the name and port of the selected listener must match + /// both specified values. + /// * Service: Port name. When both Port (experimental) and SectionName + /// are specified, the name and port of the selected listener must match + /// both specified values. + /// + /// Implementations MAY choose to support attaching Routes to other resources. + /// If that is the case, they MUST clearly document how SectionName is + /// interpreted. + /// + /// When unspecified (empty string), this will reference the entire resource. + /// For the purpose of status, an attachment is considered successful if at + /// least one section in the parent resource accepts it. For example, Gateway + /// listeners can restrict which Routes can attach to them by Route kind, + /// namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + /// the referencing Route, the Route MUST be considered successfully + /// attached. If no Gateway listeners accept attachment from this Route, the + /// Route MUST be considered detached from the Gateway. + /// + /// Support: Core + #[serde( + default, + skip_serializing_if = "Option::is_none", + rename = "sectionName" + )] + pub section_name: Option, +} diff --git a/gateway-api/src/apis/standard/httproutes.rs b/gateway-api/src/standard/httproutes.rs similarity index 100% rename from gateway-api/src/apis/standard/httproutes.rs rename to gateway-api/src/standard/httproutes.rs diff --git a/gateway-api/src/apis/standard/mod.rs b/gateway-api/src/standard/mod.rs similarity index 89% rename from gateway-api/src/apis/standard/mod.rs rename to gateway-api/src/standard/mod.rs index be25b39..5111225 100644 --- a/gateway-api/src/apis/standard/mod.rs +++ b/gateway-api/src/standard/mod.rs @@ -3,5 +3,6 @@ pub mod constants; mod enum_defaults; pub mod gatewayclasses; pub mod gateways; +pub mod grpcroutes; pub mod httproutes; pub mod referencegrants; diff --git a/gateway-api/src/apis/standard/referencegrants.rs b/gateway-api/src/standard/referencegrants.rs similarity index 100% rename from gateway-api/src/apis/standard/referencegrants.rs rename to gateway-api/src/standard/referencegrants.rs diff --git a/update.sh b/update.sh index 8e066f8..6616f9e 100755 --- a/update.sh +++ b/update.sh @@ -20,6 +20,7 @@ STANDARD_APIS=( gateways httproutes referencegrants + grpcroutes ) EXPERIMENTAL_APIS=( @@ -33,24 +34,25 @@ EXPERIMENTAL_APIS=( udproutes ) -rm -rf gateway-api/src/apis/ +rm -rf gateway-api/src/standard/ +rm -rf gateway-api/src/experimental/ -mkdir -p gateway-api/src/apis/ -cat << EOF > gateway-api/src/apis/mod.rs -pub mod experimental; -pub mod standard; -EOF +# mkdir -p gateway-api/src/standard/ +# cat << EOF > gateway-api/src/standard/mod.rs +# pub mod experimental; +# pub mod standard; +# EOF -mkdir -p gateway-api/src/apis/standard/ -mkdir -p gateway-api/src/apis/experimental/ +mkdir -p gateway-api/src/standard/ +mkdir -p gateway-api/src/experimental/ -echo "// WARNING! generated file do not edit" > gateway-api/src/apis/standard/mod.rs +echo "// WARNING! generated file do not edit" > gateway-api/src/standard/mod.rs for API in "${STANDARD_APIS[@]}" do echo "generating standard api ${API}" - curl -sSL "https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/${VERSION}/config/crd/standard/gateway.networking.k8s.io_${API}.yaml" | kopium --schema=derived --derive=JsonSchema --derive=Default --derive=PartialEq --docs -f - > gateway-api/src/apis/standard/${API}.rs - echo "pub mod ${API};" >> gateway-api/src/apis/standard/mod.rs + curl -sSL "https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/${VERSION}/config/crd/standard/gateway.networking.k8s.io_${API}.yaml" | kopium --schema=derived --derive=JsonSchema --derive=Default --derive=PartialEq --docs -f - > gateway-api/src/standard/${API}.rs + echo "pub mod ${API};" >> gateway-api/src/standard/mod.rs done # Standard API enums that need a Default trait impl along with their respective default variant. @@ -61,6 +63,8 @@ ENUMS=( HTTPRouteRulesBackendRefsFiltersRequestRedirectPathType=ReplaceFullPath HTTPRouteRulesBackendRefsFiltersUrlRewritePathType=ReplaceFullPath HTTPRouteRulesBackendRefsFiltersType=RequestHeaderModifier + GRPCRouteRulesFiltersType=RequestHeaderModifier + GRPCRouteRulesBackendRefsFiltersType=RequestHeaderModifier ) # Create a comma separated string out of $ENUMS. @@ -68,8 +72,8 @@ ENUMS_WITH_DEFAULTS=$(printf ",%s" "${ENUMS[@]}") ENUMS_WITH_DEFAULTS=${ENUMS_WITH_DEFAULTS:1} # The task searches for $GATEWAY_API_ENUMS in the enviornment to get the enum names and their default variants. -GATEWAY_API_ENUMS=${ENUMS_WITH_DEFAULTS} cargo xtask gen_enum_defaults >> gateway-api/src/apis/standard/enum_defaults.rs -echo "mod enum_defaults;" >> gateway-api/src/apis/standard/mod.rs +GATEWAY_API_ENUMS=${ENUMS_WITH_DEFAULTS} cargo xtask gen_enum_defaults >> gateway-api/src/standard/enum_defaults.rs +echo "mod enum_defaults;" >> gateway-api/src/standard/mod.rs GATEWAY_CLASS_CONDITION_CONSTANTS="GatewayClassConditionType=Accepted" GATEWAY_CLASS_REASON_CONSTANTS="GatewayClassConditionReason=Accepted,InvalidParameters,Pending,Unsupported,Waiting" @@ -81,16 +85,16 @@ LISTENER_REASON_CONSTANTS="ListenerConditionReason=HostnameConflict,ProtocolConf GATEWAY_CLASS_CONDITION_CONSTANTS=${GATEWAY_CLASS_CONDITION_CONSTANTS} GATEWAY_CLASS_REASON_CONSTANTS=${GATEWAY_CLASS_REASON_CONSTANTS} \ GATEWAY_CONDITION_CONSTANTS=${GATEWAY_CONDITION_CONSTANTS} GATEWAY_REASON_CONSTANTS=${GATEWAY_REASON_CONSTANTS} \ LISTENER_CONDITION_CONSTANTS=${LISTENER_CONDITION_CONSTANTS} LISTENER_REASON_CONSTANTS=${LISTENER_REASON_CONSTANTS} \ - cargo xtask gen_condition_constants >> gateway-api/src/apis/standard/constants.rs -echo "pub mod constants;" >> gateway-api/src/apis/standard/mod.rs + cargo xtask gen_condition_constants >> gateway-api/src/standard/constants.rs +echo "pub mod constants;" >> gateway-api/src/standard/mod.rs -echo "// WARNING! generated file do not edit" > gateway-api/src/apis/experimental/mod.rs +echo "// WARNING! generated file do not edit" > gateway-api/src/experimental/mod.rs for API in "${EXPERIMENTAL_APIS[@]}" do echo "generating experimental api $API" - curl -sSL "https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/${VERSION}/config/crd/experimental/gateway.networking.k8s.io_${API}.yaml" | kopium --schema=derived --derive=JsonSchema --derive=Default --derive=PartialEq --docs -f - > gateway-api/src/apis/experimental/${API}.rs - echo "pub mod ${API};" >> gateway-api/src/apis/experimental/mod.rs + curl -sSL "https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/${VERSION}/config/crd/experimental/gateway.networking.k8s.io_${API}.yaml" | kopium --schema=derived --derive=JsonSchema --derive=Default --derive=PartialEq --docs -f - > gateway-api/src/experimental/${API}.rs + echo "pub mod ${API};" >> gateway-api/src/experimental/mod.rs done # Experimental API enums that need a Default trait impl along with their respective default variant. @@ -107,8 +111,8 @@ ENUMS=( ENUMS_WITH_DEFAULTS=$(printf ",%s" "${ENUMS[@]}") ENUMS_WITH_DEFAULTS=${ENUMS_WITH_DEFAULTS:1} -GATEWAY_API_ENUMS=${ENUMS_WITH_DEFAULTS} cargo xtask gen_enum_defaults >> gateway-api/src/apis/experimental/enum_defaults.rs -echo "mod enum_defaults;" >> gateway-api/src/apis/experimental/mod.rs +GATEWAY_API_ENUMS=${ENUMS_WITH_DEFAULTS} cargo xtask gen_enum_defaults >> gateway-api/src/experimental/enum_defaults.rs +echo "mod enum_defaults;" >> gateway-api/src/experimental/mod.rs # GatewayClass conditions vary between standard and experimental GATEWAY_CLASS_CONDITION_CONSTANTS="${GATEWAY_CLASS_CONDITION_CONSTANTS},SupportedVersion" @@ -117,8 +121,8 @@ GATEWAY_CLASS_REASON_CONSTANTS="${GATEWAY_CLASS_REASON_CONSTANTS},SupportedVersi GATEWAY_CLASS_CONDITION_CONSTANTS=${GATEWAY_CLASS_CONDITION_CONSTANTS} GATEWAY_CLASS_REASON_CONSTANTS=${GATEWAY_CLASS_REASON_CONSTANTS} \ GATEWAY_CONDITION_CONSTANTS=${GATEWAY_CONDITION_CONSTANTS} GATEWAY_REASON_CONSTANTS=${GATEWAY_REASON_CONSTANTS} \ LISTENER_CONDITION_CONSTANTS=${LISTENER_CONDITION_CONSTANTS} LISTENER_REASON_CONSTANTS=${LISTENER_REASON_CONSTANTS} \ - cargo xtask gen_condition_constants >> gateway-api/src/apis/experimental/constants.rs -echo "pub mod constants;" >> gateway-api/src/apis/experimental/mod.rs + cargo xtask gen_condition_constants >> gateway-api/src/experimental/constants.rs +echo "pub mod constants;" >> gateway-api/src/experimental/mod.rs # Format the code. cargo fmt