|
6 | 6 | <!-- DO NOT touch the headers, UNRELEAS'D line, or compare url manually - they are sed'd --> |
7 | 7 | <!-- next-header --> |
8 | 8 | ## Unreleased |
9 | | - * see https://github.com/kube-rs/kube/compare/2.0.1...main |
| 9 | + * see https://github.com/kube-rs/kube/compare/3.0.0...main |
| 10 | + |
| 11 | +## [3.0.0](https://github.com/kube-rs/kube/releases/tag/3.0.0) / 2026-01-12 |
| 12 | +<!-- Release notes generated using configuration in .github/release.yml at 3.0.0 --> |
| 13 | +## New Major |
| 14 | +As per the new release schedule to match up with the new Kubernetes release. |
| 15 | +Lots of additions, fixes and improvements. Thanks to everyone who contributed so heavily over the holidays! Happy new year. |
| 16 | + |
| 17 | +## Breaking Changes |
| 18 | +### Kubernetes `v1_35` support via k8s-openapi [0.27](https://github.com/Arnavion/k8s-openapi/releases/tag/v0.27.0) |
| 19 | + |
| 20 | +Please [upgrade k8s-openapi along with kube](https://kube.rs/upgrading/) to avoid conflicts. |
| 21 | + |
| 22 | +### `jiff` replaces `chrono` |
| 23 | +Matching k8s-openapi's [change](https://github.com/Arnavion/k8s-openapi/commit/8c1b6fccb7258eb487ed8c829791d427a4b16216), kube has also swapped out `chrono`. The biggest impact of this is for interacting with timestamps in `metadata`, but it also updates 2 smaller public interfaces in [`LogParams`](https://docs.rs/kube/latest/kube/api/struct.LogParams.html#structfield.since_time), [`Client::with_valid_until`](https://docs.rs/kube/latest/kube/struct.Client.html#method.with_valid_until). See [controller-rs#217](https://github.com/kube-rs/controller-rs/pull/217/changes) for an example change. |
| 24 | + |
| 25 | +Changes: https://github.com/kube-rs/kube/pull/1868 + https://github.com/kube-rs/kube/pull/1870 |
| 26 | + |
| 27 | +## `ErrorResponse` has been replaced with [`Status`](https://docs.rs/kube/latest/kube/core/struct.Status.html) |
| 28 | +`ErrorResponse` served as a partial metav1/Status replacement which ended up hiding error information to users. These structs have merged, more information is available on errors, and a type alias with a deprecation warning is in place for [`ErrorResponse`](https://docs.rs/kube/latest/kube/core/type.ErrorResponse.html) which will be removed in a later version. |
| 29 | + |
| 30 | +This creates a small breaking change for users matching on specific [`Error::Api`](https://docs.rs/kube/latest/kube/enum.Error.html#variant.Api) codes; |
| 31 | + |
| 32 | +```diff |
| 33 | + .map_err(|error| match error { |
| 34 | +- kube::Error::Api(kube::error::ErrorResponse { code: 403, .. }) => { |
| 35 | +- Error::UnauthorizedToPatch(obj) |
| 36 | +- } |
| 37 | ++ kube::Error::Api(s) if s.is_forbidden() => Error::UnauthorizedToPatch(obj), |
| 38 | + other => Error::Other(other), |
| 39 | + })?; |
| 40 | +``` |
| 41 | + |
| 42 | +https://github.com/kube-rs/kube/pull/1875 + https://github.com/kube-rs/kube/pull/1883 + https://github.com/kube-rs/kube/pull/1891. |
| 43 | + |
| 44 | +## Predicates now has a TTL Cache |
| 45 | +This prevents unbounded memory for controllers, particularly affecting ones watching quickly rotating objects with generated names (e.g. pods). By default the TTL is `1h`. It can be configured via new [`PredicateConfig`](https://docs.rs/kube/latest/kube/runtime/struct.PredicateConfig.html) parameter. To use the default; |
| 46 | + |
| 47 | +```diff |
| 48 | +- .predicate_filter(predicates::resource_version); |
| 49 | ++ .predicate_filter(predicates::resource_version, Default::default()); |
| 50 | +``` |
| 51 | + |
| 52 | +Change in https://github.com/kube-rs/kube/pull/1836. This helped expose and fix a bug in watches with streaming_lists now fixed in https://github.com/kube-rs/kube/pull/1882. |
| 53 | + |
| 54 | +## Subresource Api |
| 55 | +Some subresource write methods were public with inconsistent signatures that required less ergonomic use than any other write methods. They took a `Vec<u8>` for the post body, now they take a `&K: Serialize` or the actual subresource. |
| 56 | +There affect `Api::create_subresource`, `Api::replace_subresource`, [`Api::replace_status`](https://docs.rs/kube/latest/kube/struct.Api.html#method.replace_status), `Api::replace_scale`. In essence this generally means you do not have to wrap raw objects in `json!` and `serde_json::to_vec` for these calls and lean more on rust's typed objects rather than `json!` blobs which has some [footguns](https://github.com/kube-rs/kube/pull/1884#discussion_r2680782556) for subresources. |
| 57 | + |
| 58 | +```diff |
| 59 | +- let o = foos.replace_status("qux", &pp, serde_json::to_vec(&object)?).await?; |
| 60 | ++ let o = foos.replace_status("qux", &pp, &object).await?; |
| 61 | +``` |
| 62 | + |
| 63 | +See some more shifts in examples in the implementaion; https://github.com/kube-rs/kube/pull/1884 |
| 64 | + |
| 65 | + |
| 66 | +## Improvements |
| 67 | + |
| 68 | +### Support Kubernetes 1.30 [Aggregated Discovery](https://kubernetes.io/docs/concepts/overview/kubernetes-api/#aggregated-discovery) |
| 69 | +Speeds up api discovery __significantly__ by using the newer api with much less round-tripping. |
| 70 | +To opt-in change `Discovery::run()` to [`Discovery::run_aggregated()`](https://docs.rs/kube/latest/kube/struct.Discovery.html#method.run_aggregated) |
| 71 | + |
| 72 | +Changes; https://github.com/kube-rs/kube/pull/1876 + https://github.com/kube-rs/kube/pull/1873 + https://github.com/kube-rs/kube/pull/1889 |
| 73 | + |
| 74 | +### Rust 2024 |
| 75 | +While this is mostly for internal ergonomics, we would like to highlight this also simplifies the [`Condition`](https://docs.rs/kube/latest/kube/runtime/wait/conditions/trait.Condition.html) implementors which had to deal with a lot of options; |
| 76 | +```diff |
| 77 | + pub fn is_job_completed() -> impl Condition<Job> { |
| 78 | + |obj: Option<&Job>| { |
| 79 | +- if let Some(job) = &obj { |
| 80 | +- if let Some(s) = &job.status { |
| 81 | +- if let Some(conds) = &s.conditions { |
| 82 | +- if let Some(pcond) = conds.iter().find(|c| c.type_ == "Complete") { |
| 83 | +- return pcond.status == "True"; |
| 84 | +- } |
| 85 | +- } |
| 86 | +- } |
| 87 | ++ if let Some(job) = &obj |
| 88 | ++ && let Some(s) = &job.status |
| 89 | ++ && let Some(conds) = &s.conditions |
| 90 | ++ && let Some(pcond) = conds.iter().find(|c| c.type_ == "Complete") |
| 91 | ++ { |
| 92 | ++ return pcond.status == "True"; |
| 93 | +``` |
| 94 | + |
| 95 | +Change https://github.com/kube-rs/kube/pull/1856 + https://github.com/kube-rs/kube/pull/1792 |
| 96 | + |
| 97 | +### New Client [`RetryPolicy`](https://docs.rs/kube/latest/kube/client/retry/struct.RetryPolicy.html) opt-in |
| 98 | +Allows custom clients (for now) to enable exponential backoff'd retries for retryable errors by exposing a [`tower::retry::Policy`](https://tower-rs.github.io/tower/tower/retry/trait.Policy.html) for a [`tower::retry::Layer`](https://tower-rs.github.io/tower/tower/retry/struct.RetryLayer.html). See the new [custom_client_retry](https://github.com/kube-rs/kube/blob/main/examples/custom_client_retry.rs#L24-L37) example for details. |
| 99 | + |
| 100 | +Enabled by a [clonable body](https://github.com/kube-rs/kube/pull/1867) + the new [RetryPolicy](https://github.com/kube-rs/kube/pull/1894) based on mirrord's solution[*](https://github.com/metalbear-co/mirrord/blob/a9e4c52a720fd5a833e30aee1ac650360031b7a7/mirrord/kube/src/retry.rs#L41-L135). |
| 101 | + |
| 102 | +## Fixes |
| 103 | +- streaming list bug fix - https://github.com/kube-rs/kube/pull/1882 |
| 104 | +- watcher jitter bug fix - https://github.com/kube-rs/kube/pull/1897 |
| 105 | +- schema fix for IntOrString - https://github.com/kube-rs/kube/pull/1867 |
| 106 | +- schema fix for optional enums - https://github.com/kube-rs/kube/pull/1853 |
| 107 | +- websocket keepalives for long running attaches - https://github.com/kube-rs/kube/pull/1889 |
| 108 | +### More |
| 109 | +- `Resize` subresource impl for `Pod` - https://github.com/kube-rs/kube/pull/1851 |
| 110 | +- add `#[kube(attr="...")` to allow custom attrs on derives - https://github.com/kube-rs/kube/pull/1850 |
| 111 | +- example updates for admission w/axum - https://github.com/kube-rs/kube/pull/1859 |
| 112 | + |
| 113 | + |
| 114 | +## What's Changed |
| 115 | +### Added |
| 116 | +* Add `Resize` subresource for `Pod` by @hugoponthieu in https://github.com/kube-rs/kube/pull/1851 |
| 117 | +* feat: add #[kube(attr="...")] attribute helper to set attribute helper on the CR root type by @ngergs in https://github.com/kube-rs/kube/pull/1850 |
| 118 | +* Rust 2024 let-chains to simplify wait Conditions by @clux in https://github.com/kube-rs/kube/pull/1792 |
| 119 | +* Adds a `try_clone` method for `kube_client::client::Body` when it's `Kind::Once` by @meowjesty in https://github.com/kube-rs/kube/pull/1867 |
| 120 | +* Implement client aggregated discovery API methods by @doxxx93 in https://github.com/kube-rs/kube/pull/1873 |
| 121 | +* Implement aggregated discovery API methods by @doxxx93 in https://github.com/kube-rs/kube/pull/1876 |
| 122 | +* Permit older version of API for v2 discovery for k8s < 1.30 (down to 1.27) by @Danil-Grigorev in https://github.com/kube-rs/kube/pull/1889 |
| 123 | +* Add RetryPolicy for client-level request retries by @doxxx93 in https://github.com/kube-rs/kube/pull/1894 |
| 124 | +### Changed |
| 125 | +* Update tokio-tungstenite requirement from 0.27.0 to 0.28.0 by @dependabot[bot] in https://github.com/kube-rs/kube/pull/1829 |
| 126 | +* Predicates: add configurable cache TTL for `predicate_filter` by @doxxx93 in https://github.com/kube-rs/kube/pull/1838 |
| 127 | +* Update darling requirement from 0.21.0 to 0.23.0 by @dependabot[bot] in https://github.com/kube-rs/kube/pull/1861 |
| 128 | +* update to jsonpath-rust 1 by @tottoto in https://github.com/kube-rs/kube/pull/1863 |
| 129 | +* Replace `chrono` with `jiff` by @ngergs in https://github.com/kube-rs/kube/pull/1868 |
| 130 | +* Merge ErrorResponse and Status by @imp in https://github.com/kube-rs/kube/pull/1875 |
| 131 | +* Make subresource methods more ergonomic by @doxxx93 in https://github.com/kube-rs/kube/pull/1884 |
| 132 | +* Drop k8s v1.30, crono->jiff replacement for runtime & examples by @ngergs in https://github.com/kube-rs/kube/pull/1870 |
| 133 | +* Add a metadata field to Status by @ryanpbrewster in https://github.com/kube-rs/kube/pull/1891 |
| 134 | +* Bump `k8s-openapi` for Kubernetes 1.35 by @clux in https://github.com/kube-rs/kube/pull/1898 |
| 135 | +### Fixed |
| 136 | +* fix: add use<> to kubelet_node_logs for rust edition 2024 by @co42 in https://github.com/kube-rs/kube/pull/1849 |
| 137 | +* Transform optional enums to match pre kube 2.0.0 format by @Danil-Grigorev in https://github.com/kube-rs/kube/pull/1853 |
| 138 | +* Distinguish between initial and resumed watch phases for streaming lists by @doxxx93 in https://github.com/kube-rs/kube/pull/1882 |
| 139 | +* Re-export deprecated type alias and improve deprecation guidance by @clux in https://github.com/kube-rs/kube/pull/1883 |
| 140 | +* Add nullable to optional fields with x-kubernetes-int-or-string by @doxxx93 in https://github.com/kube-rs/kube/pull/1885 |
| 141 | +* send websocket ping to keep idle connections alive by @inqode-lars in https://github.com/kube-rs/kube/pull/1887 |
| 142 | +* Fix watcher ExponentialBackoff jitter ignored by @doxxx93 in https://github.com/kube-rs/kube/pull/1897 |
| 143 | + |
| 144 | + |
| 145 | +## 3.0.0 / 2026-01-12 |
10 | 146 |
|
11 | 147 | ## [2.0.1](https://github.com/kube-rs/kube/releases/tag/2.0.1) / 2025-09-12 |
12 | 148 | <!-- Release notes generated using configuration in .github/release.yml at 2.0.1 --> |
|
0 commit comments