{"id":16769523,"url":"https://github.com/cmur2/kube-stale-resources","last_synced_at":"2026-04-26T12:32:07.338Z","repository":{"id":37825525,"uuid":"227851500","full_name":"cmur2/kube-stale-resources","owner":"cmur2","description":"Utility to detect stale resources in Kubernetes clusters based on local manifests","archived":false,"fork":false,"pushed_at":"2026-04-02T09:45:25.000Z","size":83,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-03T00:34:44.318Z","etag":null,"topics":["configuration","diff","diffing","drift","drift-detection","kubectl","kubernetes"],"latest_commit_sha":null,"homepage":"https://mycroba.se/mirror-redirect/kube-stale-resources","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cmur2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-12-13T13:56:35.000Z","updated_at":"2026-04-02T09:45:28.000Z","dependencies_parsed_at":"2024-02-29T12:15:10.726Z","dependency_job_id":"3374bb1d-92a9-445b-b3b4-8f2c16b0f7c9","html_url":"https://github.com/cmur2/kube-stale-resources","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cmur2/kube-stale-resources","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmur2%2Fkube-stale-resources","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmur2%2Fkube-stale-resources/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmur2%2Fkube-stale-resources/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmur2%2Fkube-stale-resources/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cmur2","download_url":"https://codeload.github.com/cmur2/kube-stale-resources/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmur2%2Fkube-stale-resources/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32297893,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration","diff","diffing","drift","drift-detection","kubectl","kubernetes"],"created_at":"2024-10-13T06:14:19.222Z","updated_at":"2026-04-26T12:32:07.324Z","avatar_url":"https://github.com/cmur2.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kube-stale-resources\n\n![Build Status](https://github.com/cmur2/kube-stale-resources/workflows/ci/badge.svg)\n\nThis is a utility to detect stale resources in [Kubernetes](https://kubernetes.io/) clusters between resources from YAML manifests supplied via local file or stdin (target state) and a Kubernetes cluster (live state).\nAll resources that exist in the live state but not in the target state are considered *stale* as they deviate from the intended state of the Kubernetes cluster (closed world assumption). It is intended as a complement to [kubectl diff](https://kubernetes.io/blog/2019/01/14/apiserver-dry-run-and-kubectl-diff/).\n\nUsing a blacklist you can ignore resources from the live state from the comparison so they are not considered *stale* even though they do not exist in the given target state. This is useful when those resources are created by Kubernetes itself (e.g. the `kubernetes` service in the default namespace), managed by the Kubernetes cluster provider or another tool outside the scope.\n\nA use case for `kube-stale-resources` is using it alongside `kubectl diff` on locally present YAML manifests so `kubectl diff` can detect newly created Kubernetes resources and changes to those resources and `kube-stale-resources` can alert the user on stale resources that should be deleted from the cluster.\n\nLimitations:\n\n- currently only works on namespaced resources\n- currently requires explicit `metadata.namespace` field even for resources in default namespace\n- requires unauthenticated HTTP(S) access to Kubernetes apiserver, e.g. via `kubectl proxy`\n- only accounts for `apiVersion` deprecations up until Kubernetes 1.16\n\n\n## Usage\n\nYou need Python 3.8 or higher.\n\nAssuming you have a properly setup `.kube/config` (e.g. using [minikube](https://github.com/kubernetes/minikube) after a successful `minikube start`) running:\n\n```bash\nkubectl proxy \u0026\n\n# ignore minikube resources\ncat \u003c\u003cEOF \u003e blacklist.txt\n^kubernetes-dashboard:.*$\n^default:events.k8s.io/v1beta1:Event:minikube..*$\nEOF\n\n# orderly created resource using YAML manifest in e.g. git\ncat \u003c\u003cEOF \u003e version-controlled-resources.yml\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: foo\n  namespace: default\nspec:\n  type: ClusterIP\n  ports:\n    - port: 80\n      name: http\n      targetPort: 80\n  selector:\n    app: foo\nEOF\nkubectl apply -f version-controlled-resources.yml\n\n# on-the-fly created resource using imperative command\nkubectl create service clusterip bar --tcp='8080:8080'\n\ncat version-controlled-resources.yml | python kube-stale-resources.py -f - --blacklist blacklist.txt\n```\n\nThis should yield a similar output to as we ignored what minikube sets up by default (e.g. the whole `kubernetes-dashboard` namespace):\n\n```\nReading blacklist file blacklist.txt...\nRetrieving target state...\nRetrieving live state from http://localhost:8001...\nLive dynamic configmaps that are not in target (stale):\n.. 0 entries\n\nLive resources w/o dynamic configmaps that are not in target (stale):\n  default:v1:Service:bar\n.. 1 entries\n```\n\nRun `python kube-stale-resources.py -h` for full list of options.\n\n\n## Blacklisting\n\nExample blacklist file for a cluster on [GKE](https://cloud.google.com/kubernetes-engine/) that also uses [cert-manager](https://github.com/jetstack/cert-manager):\n\n```\n^.*:v1:ResourceQuota:gke-resource-quotas$\n^default:v1:LimitRange:limits$\n\n^.*:certmanager.k8s.io/v1alpha1:Order:.*$\n```\n\nIn general a blacklist file contains one regular expression per line that are matched against a string of format `\u003cnamespace-name\u003e:\u003capiVersion\u003e:\u003ckind\u003e:\u003cresource-name\u003e` for each resource.\n\n\n## License\n\nkube-stale-resources is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for more information\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmur2%2Fkube-stale-resources","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcmur2%2Fkube-stale-resources","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmur2%2Fkube-stale-resources/lists"}