k8stools 2.3.0__tar.gz → 2.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {k8stools-2.3.0 → k8stools-2.4.0}/CHANGELOG.md +34 -0
  2. {k8stools-2.3.0 → k8stools-2.4.0}/CLAUDE.md +2 -1
  3. {k8stools-2.3.0 → k8stools-2.4.0}/PKG-INFO +7 -4
  4. {k8stools-2.3.0 → k8stools-2.4.0}/README.md +6 -3
  5. {k8stools-2.3.0 → k8stools-2.4.0}/designs/mock-state-capture.md +5 -1
  6. {k8stools-2.3.0 → k8stools-2.4.0}/pyproject.toml +1 -1
  7. {k8stools-2.3.0 → k8stools-2.4.0}/src/k8stools/__init__.py +3 -1
  8. {k8stools-2.3.0 → k8stools-2.4.0}/src/k8stools/capture.py +14 -3
  9. {k8stools-2.3.0 → k8stools-2.4.0}/src/k8stools/fixtures/otel-demo.json +194 -0
  10. {k8stools-2.3.0 → k8stools-2.4.0}/src/k8stools/k8s_tools.py +551 -1
  11. {k8stools-2.3.0 → k8stools-2.4.0}/src/k8stools/mock_state.py +47 -0
  12. {k8stools-2.3.0 → k8stools-2.4.0}/src/k8stools/mock_tools.py +8 -0
  13. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_builtin_fixture.py +36 -0
  14. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_duration_format.py +2 -0
  15. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_k8s_tools_realk8s.py +42 -0
  16. k8stools-2.4.0/tests/test_workload_history.py +376 -0
  17. {k8stools-2.3.0 → k8stools-2.4.0}/uv.lock +1 -1
  18. {k8stools-2.3.0 → k8stools-2.4.0}/.claude/settings.local.json +0 -0
  19. {k8stools-2.3.0 → k8stools-2.4.0}/.github/workflows/unit-tests.yml +0 -0
  20. {k8stools-2.3.0 → k8stools-2.4.0}/.gitignore +0 -0
  21. {k8stools-2.3.0 → k8stools-2.4.0}/.python-version +0 -0
  22. {k8stools-2.3.0 → k8stools-2.4.0}/.vscode/mcp.json +0 -0
  23. {k8stools-2.3.0 → k8stools-2.4.0}/.vscode/settings.json +0 -0
  24. {k8stools-2.3.0 → k8stools-2.4.0}/LICENSE +0 -0
  25. {k8stools-2.3.0 → k8stools-2.4.0}/chat-with-cluster.png +0 -0
  26. {k8stools-2.3.0 → k8stools-2.4.0}/docs/ROADMAP.md +0 -0
  27. {k8stools-2.3.0 → k8stools-2.4.0}/envrc.template +0 -0
  28. {k8stools-2.3.0 → k8stools-2.4.0}/src/k8stools/mcp_client.py +0 -0
  29. {k8stools-2.3.0 → k8stools-2.4.0}/src/k8stools/mcp_server.py +0 -0
  30. {k8stools-2.3.0 → k8stools-2.4.0}/src/k8stools/redaction.py +0 -0
  31. {k8stools-2.3.0 → k8stools-2.4.0}/tests/conftest.py +0 -0
  32. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_capture.py +0 -0
  33. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_cluster_binding.py +0 -0
  34. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_events.py +0 -0
  35. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_k8s_tools.py +0 -0
  36. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_log_decoding.py +0 -0
  37. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_mcp_client.py +0 -0
  38. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_mock_state.py +0 -0
  39. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_mock_tools.py +0 -0
  40. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_new_tools.py +0 -0
  41. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_node_conditions.py +0 -0
  42. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_redaction.py +0 -0
  43. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_replicaset_tool.py +0 -0
  44. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_version.py +0 -0
  45. {k8stools-2.3.0 → k8stools-2.4.0}/tests/test_workloads.py +0 -0
@@ -3,6 +3,40 @@
3
3
  All notable changes to k8stools. Versions follow [semantic versioning](https://semver.org/);
4
4
  dates are release-tag dates.
5
5
 
6
+ ## 2.4.0 — 2026-10-05
7
+
8
+ ### Added
9
+ - **`get_workload_history` tool** (issue #11): what changed in a Deployment,
10
+ StatefulSet or DaemonSet, and when. It lists the retained pod-template revisions
11
+ newest first (a Deployment's ReplicaSets; a StatefulSet's or DaemonSet's
12
+ ControllerRevisions), each compared with the one before it:
13
+ - per container, matched by name: image, resource requests and limits,
14
+ command, args, probes, env vars, `envFrom` and volume mounts;
15
+ - for the pod: volumes, node selector and tolerations;
16
+ - any other changed field is named;
17
+ - template label and annotation changes are listed separately, so a Helm
18
+ version-label bump doesn't bury a memory-limit change;
19
+ - a `kubectl rollout restart` is flagged.
20
+
21
+ Env vars are compared by name and shown by name only, never by value. The
22
+ result also lists the ConfigMaps and Secrets the current template uses, and
23
+ how. ConfigMaps get their age and `last_written`. Secrets are named but never
24
+ read. Each result carries the limits of what history can show. `print_workload_history`
25
+ is its companion.
26
+ - Captures store each workload's history (the tool's result, so no env values are
27
+ written); captures from before 2.4.0 replay an images-only history rebuilt from
28
+ their ReplicaSet records, marked `complete: false`. The `--mock` fixture has a
29
+ history for each of its four workloads.
30
+
31
+ ### Changed
32
+ - **A capture needs `list` on `controllerrevisions`** (apps), for StatefulSet and
33
+ DaemonSet histories, and fails without it. The README's role includes it.
34
+
35
+ ### Documentation
36
+ - `get_replicaset_summaries` no longer says the newest replica set's age is always
37
+ when the deployment last changed: a rollback re-activates an older replica set
38
+ under a new revision number.
39
+
6
40
  ## 2.3.0 — 2026-10-03
7
41
 
8
42
  ### Added
@@ -28,7 +28,8 @@ tests/
28
28
  test_cluster_binding.py - Cluster selection: configure(), the shared binding, get_cluster_info, server flags
29
29
  test_node_conditions.py - NodeSummary.conditions_since (condition transition times), incl. capture replay
30
30
  test_workloads.py - get_daemonset_summaries and PodSummary.owner, incl. capture replay
31
- test_builtin_fixture.py - The built-in fixture describes a cluster that could exist (owners, images, ages, log windows)
31
+ test_builtin_fixture.py - The built-in fixture describes a cluster that could exist (owners, images, ages, log windows, histories)
32
+ test_workload_history.py - get_workload_history: template diffs, revisions, config refs, no env values or Secret reads, replay
32
33
  test_log_decoding.py - Log decoding at the API boundary (bytes vs str), `previous` plumbing, log redaction
33
34
  test_mcp_client.py - MCP client tests
34
35
  test_version.py - Asserts pyproject and package __version__ agree
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: k8stools
3
- Version: 2.3.0
3
+ Version: 2.4.0
4
4
  Summary: Tools and an MCP server for building Kubernetes agents
5
5
  Project-URL: Homepage, https://github.com/BenedatLLC/k8stools
6
6
  Project-URL: Changelog, https://github.com/BenedatLLC/k8stools/blob/main/CHANGELOG.md
@@ -293,7 +293,7 @@ rules:
293
293
  persistentvolumeclaims]
294
294
  verbs: [get, list]
295
295
  - apiGroups: [apps]
296
- resources: [deployments, replicasets, statefulsets, daemonsets]
296
+ resources: [deployments, replicasets, statefulsets, daemonsets, controllerrevisions]
297
297
  verbs: [get, list]
298
298
  - apiGroups: [batch]
299
299
  resources: [jobs, cronjobs]
@@ -301,7 +301,8 @@ rules:
301
301
  ```
302
302
 
303
303
  `get_cluster_info` also reads the server version (`/version`), which every
304
- authenticated user can read by default. No tool reads Secrets.
304
+ authenticated user can read by default. No tool reads Secrets: `get_workload_history`
305
+ names the Secrets a workload uses, from its pod template, without reading them.
305
306
 
306
307
  ## Current tools
307
308
 
@@ -317,6 +318,7 @@ These are the tools we define:
317
318
  * `get_logs_for_pod_and_container` - retrieves logs from a pod and container (supports `tail`, `since_seconds`, and `previous`). See [Previous-instance log semantics](#previous-instance-log-semantics) for when `previous=True` returns the same text as `previous=False` — it is Kubernetes behavior, not a bug.
318
319
  * `get_deployment_summaries` - get a list of deployments, like `kubectl get deployments`
319
320
  * `get_replicaset_summaries` - get a deployment's replica sets with their revision numbers and images. A deployment's replica sets are its change history: use this to see when a workload last changed and what the change was.
321
+ * `get_workload_history` - what changed in a Deployment, StatefulSet or DaemonSet, and when: each retained revision of its pod template compared with the one before (images, resources, probes, command/args, env var *names*, volumes, scheduling), plus the ConfigMaps and Secrets it references. It states what history cannot show.
320
322
  * `get_service_summaries` - get a list of services, like `kubectl get services` (includes `selector`/labels/annotations)
321
323
  * `get_configmap_summaries` - get a list of ConfigMaps, like `kubectl get configmaps`
322
324
  * `get_configmap` - retrieve the full contents of a single ConfigMap
@@ -338,6 +340,7 @@ We also define a set of associated "print_" functions that are helpful in debugg
338
340
  * `print_pod_events`
339
341
  * `print_pod_spec`
340
342
  * `print_deployment_summaries`
343
+ * `print_workload_history`
341
344
  * `print_service_summaries`
342
345
  * `print_configmap_summaries`
343
346
  * `print_configmap`
@@ -609,7 +612,7 @@ Everything the tools can read, so that every tool answers on replay:
609
612
  |---|---|
610
613
  | Cluster | context name, API server URL and version, so `get_cluster_info` answers on replay (not the kubeconfig path, which names a file on the capturing machine) |
611
614
  | Cluster-wide | namespaces, nodes |
612
- | Per namespace | deployments, replica sets, services, statefulsets, daemonsets, cronjobs, jobs, PVCs, events |
615
+ | Per namespace | deployments, replica sets, services, statefulsets, daemonsets, cronjobs, jobs, PVCs, events, and each workload's change history (`get_workload_history`'s result, so no env values are written) |
613
616
  | ConfigMaps | summary **and** full contents, so `get_configmap` works too |
614
617
  | Per pod | summary, labels, container statuses, spec, and per-container logs |
615
618
 
@@ -73,7 +73,7 @@ rules:
73
73
  persistentvolumeclaims]
74
74
  verbs: [get, list]
75
75
  - apiGroups: [apps]
76
- resources: [deployments, replicasets, statefulsets, daemonsets]
76
+ resources: [deployments, replicasets, statefulsets, daemonsets, controllerrevisions]
77
77
  verbs: [get, list]
78
78
  - apiGroups: [batch]
79
79
  resources: [jobs, cronjobs]
@@ -81,7 +81,8 @@ rules:
81
81
  ```
82
82
 
83
83
  `get_cluster_info` also reads the server version (`/version`), which every
84
- authenticated user can read by default. No tool reads Secrets.
84
+ authenticated user can read by default. No tool reads Secrets: `get_workload_history`
85
+ names the Secrets a workload uses, from its pod template, without reading them.
85
86
 
86
87
  ## Current tools
87
88
 
@@ -97,6 +98,7 @@ These are the tools we define:
97
98
  * `get_logs_for_pod_and_container` - retrieves logs from a pod and container (supports `tail`, `since_seconds`, and `previous`). See [Previous-instance log semantics](#previous-instance-log-semantics) for when `previous=True` returns the same text as `previous=False` — it is Kubernetes behavior, not a bug.
98
99
  * `get_deployment_summaries` - get a list of deployments, like `kubectl get deployments`
99
100
  * `get_replicaset_summaries` - get a deployment's replica sets with their revision numbers and images. A deployment's replica sets are its change history: use this to see when a workload last changed and what the change was.
101
+ * `get_workload_history` - what changed in a Deployment, StatefulSet or DaemonSet, and when: each retained revision of its pod template compared with the one before (images, resources, probes, command/args, env var *names*, volumes, scheduling), plus the ConfigMaps and Secrets it references. It states what history cannot show.
100
102
  * `get_service_summaries` - get a list of services, like `kubectl get services` (includes `selector`/labels/annotations)
101
103
  * `get_configmap_summaries` - get a list of ConfigMaps, like `kubectl get configmaps`
102
104
  * `get_configmap` - retrieve the full contents of a single ConfigMap
@@ -118,6 +120,7 @@ We also define a set of associated "print_" functions that are helpful in debugg
118
120
  * `print_pod_events`
119
121
  * `print_pod_spec`
120
122
  * `print_deployment_summaries`
123
+ * `print_workload_history`
121
124
  * `print_service_summaries`
122
125
  * `print_configmap_summaries`
123
126
  * `print_configmap`
@@ -389,7 +392,7 @@ Everything the tools can read, so that every tool answers on replay:
389
392
  |---|---|
390
393
  | Cluster | context name, API server URL and version, so `get_cluster_info` answers on replay (not the kubeconfig path, which names a file on the capturing machine) |
391
394
  | Cluster-wide | namespaces, nodes |
392
- | Per namespace | deployments, replica sets, services, statefulsets, daemonsets, cronjobs, jobs, PVCs, events |
395
+ | Per namespace | deployments, replica sets, services, statefulsets, daemonsets, cronjobs, jobs, PVCs, events, and each workload's change history (`get_workload_history`'s result, so no env values are written) |
393
396
  | ConfigMaps | summary **and** full contents, so `get_configmap` works too |
394
397
  | Per pod | summary, labels, container statuses, spec, and per-container logs |
395
398
 
@@ -152,6 +152,7 @@ A single JSON file per capture. Top-level keys:
152
152
  "configmaps": [ ... ],
153
153
  "statefulsets": [ ... ],
154
154
  "daemonsets": [ ... ],
155
+ "workload_histories": [ ... ],
155
156
  "cronjobs": [ ... ],
156
157
  "jobs": [ ... ],
157
158
  "pvcs": [ ... ],
@@ -165,7 +166,10 @@ The `configmaps`..`events` keys were added alongside the 1.1.0 tool batch
165
166
  shapes. `replicasets` was added alongside the 1.2.0 tool batch — see
166
167
  [Resource records added in 1.2.0](#resource-records-added-in-120). `daemonsets` was added
167
168
  in 2.3.0: `DaemonSetSummary` fields with `age` → `age_seconds`; captures without it
168
- replay no DaemonSets.
169
+ replay no DaemonSets. `workload_histories` was added in 2.4.0: one encoded
170
+ `WorkloadHistory` (the tool's result, not raw pod templates, so env values never
171
+ reach the file) per Deployment, StatefulSet and DaemonSet. Captures without it
172
+ replay an images-only history rebuilt from `replicasets`, with `complete: false`.
169
173
 
170
174
  `redacted` records which mode the capture was taken in — see
171
175
  [Redaction](#redaction). It exists so a consumer can tell without guessing;
@@ -1,7 +1,7 @@
1
1
 
2
2
  [project]
3
3
  name = "k8stools"
4
- version = "2.3.0"
4
+ version = "2.4.0"
5
5
  description = "Tools and an MCP server for building Kubernetes agents"
6
6
  readme = "README.md"
7
7
  requires-python = ">=3.12"
@@ -34,6 +34,7 @@ These are the tools we define:
34
34
  * get_logs_for_pod_and_container - retrieves logs from a pod and container (supports tail/since/previous)
35
35
  * get_deployment_summaries - get a list of deployments, like `kubectl get deployments`
36
36
  * get_replicaset_summaries - get a deployment's revision history, like `kubectl get replicasets`
37
+ * get_workload_history - a workload's pod-template revisions, compared, and the config it references
37
38
  * get_service_summaries - get a list of services, like `kubectl get services`
38
39
  * get_configmap_summaries - get a list of ConfigMaps, like `kubectl get configmaps`
39
40
  * get_configmap - retrieve the full contents of a single ConfigMap
@@ -56,6 +57,7 @@ We also define a set of associated "print_" functions that are helpful in debugg
56
57
  * print_pod_spec
57
58
  * print_deployment_summaries
58
59
  * print_replicaset_summaries
60
+ * print_workload_history
59
61
  * print_service_summaries
60
62
  * print_configmap_summaries
61
63
  * print_configmap
@@ -80,4 +82,4 @@ the built-in OTel Demo snapshot by default, or your own via load_mock_state() or
80
82
  the server's --state-file option.
81
83
  """
82
84
 
83
- __version__ = "2.3.0"
85
+ __version__ = "2.4.0"
@@ -186,6 +186,7 @@ def capture_state(namespaces: Optional[list[str]] = None,
186
186
  "configmaps": [],
187
187
  "statefulsets": [],
188
188
  "daemonsets": [],
189
+ "workload_histories": [],
189
190
  "cronjobs": [],
190
191
  "jobs": [],
191
192
  "pvcs": [],
@@ -193,11 +194,21 @@ def capture_state(namespaces: Optional[list[str]] = None,
193
194
  }
194
195
 
195
196
  for ns in target_namespaces:
196
- state["deployments"] += _encode_all(redactor(k8s_tools.get_deployment_summaries(ns)), captured_at)
197
+ deployments = k8s_tools.get_deployment_summaries(ns)
198
+ state["deployments"] += _encode_all(redactor(deployments), captured_at)
197
199
  state["replicasets"] += _encode_all(redactor(k8s_tools.get_replicaset_summaries(ns)), captured_at)
198
200
  state["services"] += _encode_all(redactor(k8s_tools.get_service_summaries(ns)), captured_at)
199
- state["statefulsets"] += _encode_all(redactor(k8s_tools.get_statefulset_summaries(ns)), captured_at)
200
- state["daemonsets"] += _encode_all(redactor(k8s_tools.get_daemonset_summaries(ns)), captured_at)
201
+ statefulsets = k8s_tools.get_statefulset_summaries(ns)
202
+ state["statefulsets"] += _encode_all(redactor(statefulsets), captured_at)
203
+ daemonsets = k8s_tools.get_daemonset_summaries(ns)
204
+ state["daemonsets"] += _encode_all(redactor(daemonsets), captured_at)
205
+ # The tool's own result, not raw templates: replay serves it as is, and
206
+ # env values never reach the file.
207
+ for kind, workloads in (("Deployment", deployments), ("StatefulSet", statefulsets),
208
+ ("DaemonSet", daemonsets)):
209
+ for w in workloads:
210
+ state["workload_histories"].append(encode_model(
211
+ redactor(k8s_tools.get_workload_history(w.name, ns, kind)), captured_at))
201
212
  state["cronjobs"] += _encode_all(redactor(k8s_tools.get_cronjob_summaries(ns)), captured_at)
202
213
  state["jobs"] += _encode_all(redactor(k8s_tools.get_job_summaries(ns)), captured_at)
203
214
  state["pvcs"] += _encode_all(redactor(k8s_tools.get_pvc_summaries(ns)), captured_at)
@@ -476,6 +476,26 @@
476
476
  "key": "node.kubernetes.io/unreachable",
477
477
  "operator": "Exists"
478
478
  }
479
+ ],
480
+ "volumes": [
481
+ {
482
+ "name": "opentelemetry-collector-configmap",
483
+ "config_map": {
484
+ "name": "otel-collector-agent",
485
+ "items": [
486
+ {
487
+ "key": "relay",
488
+ "path": "relay.yaml"
489
+ }
490
+ ]
491
+ }
492
+ },
493
+ {
494
+ "name": "hostfs",
495
+ "host_path": {
496
+ "path": "/"
497
+ }
498
+ }
479
499
  ]
480
500
  },
481
501
  "logs": {
@@ -939,6 +959,13 @@
939
959
  "age_seconds": 777605.0,
940
960
  "data": {},
941
961
  "binary_data_keys": []
962
+ },
963
+ {
964
+ "name": "otel-collector-agent",
965
+ "namespace": "default",
966
+ "key_count": 1,
967
+ "data_size": 234,
968
+ "age_seconds": 691200.0
942
969
  }
943
970
  ],
944
971
  "statefulsets": [
@@ -971,6 +998,173 @@
971
998
  "age_seconds": 691200.0
972
999
  }
973
1000
  ],
1001
+ "workload_histories": [
1002
+ {
1003
+ "kind": "Deployment",
1004
+ "name": "ad",
1005
+ "namespace": "default",
1006
+ "revisions": [
1007
+ {
1008
+ "revision": 2,
1009
+ "source": "ReplicaSet/ad-647b4947cc",
1010
+ "age_seconds": 27240.0,
1011
+ "current": true,
1012
+ "reused": false,
1013
+ "images": [
1014
+ "ghcr.io/open-telemetry/demo:2.2.0-ad"
1015
+ ],
1016
+ "compared_with": 1,
1017
+ "changes": [
1018
+ {
1019
+ "field": "containers[ad].image",
1020
+ "change": "changed",
1021
+ "before": "ghcr.io/open-telemetry/demo:2.0.2-ad",
1022
+ "after": "ghcr.io/open-telemetry/demo:2.2.0-ad"
1023
+ },
1024
+ {
1025
+ "field": "containers[ad].env[OTEL_RESOURCE_ATTRIBUTES]",
1026
+ "change": "removed",
1027
+ "before": null,
1028
+ "after": null
1029
+ }
1030
+ ],
1031
+ "metadata_changes": [
1032
+ {
1033
+ "field": "metadata.labels[app.kubernetes.io/version]",
1034
+ "change": "changed",
1035
+ "before": "2.0.2",
1036
+ "after": "2.2.0"
1037
+ }
1038
+ ],
1039
+ "rollout_restart": false
1040
+ },
1041
+ {
1042
+ "revision": 1,
1043
+ "source": "ReplicaSet/ad-d5c94c49b",
1044
+ "age_seconds": 691199.0,
1045
+ "current": false,
1046
+ "reused": false,
1047
+ "images": [
1048
+ "ghcr.io/open-telemetry/demo:2.0.2-ad"
1049
+ ],
1050
+ "compared_with": null,
1051
+ "changes": [],
1052
+ "metadata_changes": [],
1053
+ "rollout_restart": false
1054
+ }
1055
+ ],
1056
+ "config": [],
1057
+ "complete": true,
1058
+ "limits": [
1059
+ "Only pod-template changes are recorded. Replica counts, autoscaling and the update strategy are not, and neither are changes outside the cluster (feature flags, traffic, dependencies).",
1060
+ "Kubernetes keeps 10 old revisions (revisionHistoryLimit); older ones are deleted, so the oldest listed revision is not necessarily the first.",
1061
+ "A revision's age is when its ReplicaSet was created. A rollback reuses an older one (reused=true), which then went live later than its age says.",
1062
+ "Env var values are never shown, only names. Secret contents and change times are not read.",
1063
+ "A ConfigMap's last_written is its latest write of any kind, including label-only changes such as a Helm upgrade: it does not show that the data changed."
1064
+ ]
1065
+ },
1066
+ {
1067
+ "kind": "Deployment",
1068
+ "name": "test-deployment",
1069
+ "namespace": "default",
1070
+ "revisions": [
1071
+ {
1072
+ "revision": 1,
1073
+ "source": "ReplicaSet/test-deployment-7d4b9c85f",
1074
+ "age_seconds": 7199.0,
1075
+ "current": true,
1076
+ "reused": false,
1077
+ "images": [
1078
+ "ghcr.io/open-telemetry/demo:2.2.0-cart"
1079
+ ],
1080
+ "compared_with": null,
1081
+ "changes": [],
1082
+ "metadata_changes": [],
1083
+ "rollout_restart": false
1084
+ }
1085
+ ],
1086
+ "config": [],
1087
+ "complete": true,
1088
+ "limits": [
1089
+ "Only pod-template changes are recorded. Replica counts, autoscaling and the update strategy are not, and neither are changes outside the cluster (feature flags, traffic, dependencies).",
1090
+ "Kubernetes keeps 10 old revisions (revisionHistoryLimit); older ones are deleted, so the oldest listed revision is not necessarily the first.",
1091
+ "A revision's age is when its ReplicaSet was created. A rollback reuses an older one (reused=true), which then went live later than its age says.",
1092
+ "Env var values are never shown, only names. Secret contents and change times are not read.",
1093
+ "A ConfigMap's last_written is its latest write of any kind, including label-only changes such as a Helm upgrade: it does not show that the data changed."
1094
+ ]
1095
+ },
1096
+ {
1097
+ "kind": "StatefulSet",
1098
+ "name": "postgres",
1099
+ "namespace": "default",
1100
+ "revisions": [
1101
+ {
1102
+ "revision": 1,
1103
+ "source": "ControllerRevision/postgres-5d8f6c7b9",
1104
+ "age_seconds": 259200.0,
1105
+ "current": true,
1106
+ "reused": false,
1107
+ "images": [
1108
+ "postgres:16.4"
1109
+ ],
1110
+ "compared_with": null,
1111
+ "changes": [],
1112
+ "metadata_changes": [],
1113
+ "rollout_restart": false
1114
+ }
1115
+ ],
1116
+ "config": [],
1117
+ "complete": true,
1118
+ "limits": [
1119
+ "Only pod-template changes are recorded. Replica counts, autoscaling and the update strategy are not, and neither are changes outside the cluster (feature flags, traffic, dependencies).",
1120
+ "Kubernetes keeps 10 old revisions (revisionHistoryLimit); older ones are deleted, so the oldest listed revision is not necessarily the first.",
1121
+ "A revision's age is when its ControllerRevision was created. A rollback reuses an older one (reused=true), which then went live later than its age says.",
1122
+ "Env var values are never shown, only names. Secret contents and change times are not read.",
1123
+ "A ConfigMap's last_written is its latest write of any kind, including label-only changes such as a Helm upgrade: it does not show that the data changed."
1124
+ ]
1125
+ },
1126
+ {
1127
+ "kind": "DaemonSet",
1128
+ "name": "otel-collector-agent",
1129
+ "namespace": "default",
1130
+ "revisions": [
1131
+ {
1132
+ "revision": 1,
1133
+ "source": "ControllerRevision/otel-collector-agent-7bfc667c67",
1134
+ "age_seconds": 691200.0,
1135
+ "current": true,
1136
+ "reused": false,
1137
+ "images": [
1138
+ "otel/opentelemetry-collector-contrib:0.142.0"
1139
+ ],
1140
+ "compared_with": null,
1141
+ "changes": [],
1142
+ "metadata_changes": [],
1143
+ "rollout_restart": false
1144
+ }
1145
+ ],
1146
+ "config": [
1147
+ {
1148
+ "kind": "ConfigMap",
1149
+ "name": "otel-collector-agent",
1150
+ "used_as": [
1151
+ "volume"
1152
+ ],
1153
+ "exists": true,
1154
+ "age_seconds": 691200.0,
1155
+ "last_written_seconds": 691200.0
1156
+ }
1157
+ ],
1158
+ "complete": true,
1159
+ "limits": [
1160
+ "Only pod-template changes are recorded. Replica counts, autoscaling and the update strategy are not, and neither are changes outside the cluster (feature flags, traffic, dependencies).",
1161
+ "Kubernetes keeps 10 old revisions (revisionHistoryLimit); older ones are deleted, so the oldest listed revision is not necessarily the first.",
1162
+ "A revision's age is when its ControllerRevision was created. A rollback reuses an older one (reused=true), which then went live later than its age says.",
1163
+ "Env var values are never shown, only names. Secret contents and change times are not read.",
1164
+ "A ConfigMap's last_written is its latest write of any kind, including label-only changes such as a Helm upgrade: it does not show that the data changed."
1165
+ ]
1166
+ }
1167
+ ],
974
1168
  "cronjobs": [
975
1169
  {
976
1170
  "name": "cleanup",