Python GCS bucket lifecycle and retention census — classes, rules, locks
Lifecycle moves class. Retention locks delete. Versioning keeps generations.
Lifecycle moves class. Retention locks delete. Versioning keeps generations. Print all three before you trust a bucket.
§I — Frame
Thursday named CloudWatch alarms on AWS. Monday named BigQuery partitions on GCP. Those leftovers stay on their shelves.
Today the cert seat is GCP PCA again. Counter 10 mod 4 is seat 2. Prior PCA visits opened hierarchy (08-08), Compute MIG and HTTP load balancing (08-20), and BigQuery prune (09-01). Bootcamp Chapter-3 left a JSON file on disk: age 30 moves Standard or Nearline to Coldline; age 365 deletes. That file waited. Open it.
The ops tool talks to google.cloud.storage.Client. It lists buckets in a project. For each bucket it reloads metadata and prints default storage class, lifecycle rules, retention fields, and versioning. It does not patch. It does not rewrite lifecycle. It does not delete objects. A census that mutates the bucket is no longer a census.
§II — Three shelves on one bucket
| Shelf | What it does | What it does not do |
|---|---|---|
| Storage class / lifecycle | Ages objects into Nearline, Coldline, Archive, or Delete | Replace a retention lock |
| Retention policy | Blocks delete and overwrite for a locked period | Keep prior generations after overwrite |
| Object versioning | Keeps noncurrent generations | Stop a retention-locked delete by itself |
PCA-Notes splits retention and versioning in one breath: retention protects from deletion and changes; versioning allows modification history; GCS objects are immutable at the generation. Confusing any two shelves is the exam trap and the ops trap.
Chapter-3's JSON is the lifecycle shelf only:
{
"lifecycle": {
"rule": [
{
"action": { "type": "SetStorageClass", "storageClass": "COLDLINE" },
"condition": { "age": 30, "matchesStorageClass": ["STANDARD", "NEARLINE"] }
},
{
"action": { "type": "Delete" },
"condition": { "age": 365 }
}
]
}
}
Print the rules. Do not invent a retention period from them. Do not invent versioning from them.
§III — Mechanism: list, reload, print
from google.cloud import storage
def census(project):
client = storage.Client(project=project)
rows = []
for bucket in client.list_buckets():
bucket.reload()
retention = bucket.retention_policy_effective_time
rows.append({
"name": bucket.name,
"location": bucket.location,
"storage_class": bucket.storage_class,
"versioning": bool(bucket.versioning_enabled),
"lifecycle_rules": list(bucket.lifecycle_rules or []),
"retention_period": bucket.retention_period,
"retention_locked": bool(bucket.retention_policy_locked),
"retention_effective": None if retention is None else retention.isoformat(),
"soft_delete_retention": getattr(bucket, "soft_delete_policy", None),
})
return rows
list_buckets returns thin stubs. reload() fills lifecycle and retention. Print rule action type, storage class target, age, and matchesStorageClass. Treat a Standard-default bucket with zero rules and unlocked retention as a finding when the data class is cold archive or compliance.
Never call bucket.patch(). Never blob.delete(). Never upload a new lifecycle JSON from the census tool.
§IV — Worked findings
- Empty lifecycle on a log bucket. Default Standard forever. Chapter-3 expected Coldline at 30 days. Finding: missing SetStorageClass rule.
- Lifecycle Delete at 90 without retention. Compliance says keep seven years. Lifecycle will delete. Retention must block that path, or the delete rule is wrong.
- Versioning on, retention off, no lifecycle. Overwrites keep generations and bill for them. Versioning without a noncurrent delete rule is a cost leftover.
- Retention locked, wrong period. Locked retention cannot shorten. Print locked=true before anyone plans a "quick fix."
§V — Boundaries versus recent days
09-10 measured CloudWatch actions with boto3. 09-01 dry-ran BigQuery bytes. 09-04 measured Azure redundancy. Today measures GCS policy shelves on GCP. Same census posture. Different API. Different coin.
§VI — Operator checklist
- Scope the project (and folder if you must walk many projects).
- List buckets; reload each.
- Print storage_class, lifecycle_rules, retention_*, versioning_enabled.
- Flag Standard+empty-lifecycle on cold data classes.
- Flag Delete rules that beat retention or legal hold needs.
- Flag versioning without noncurrent cleanup when cost matters.
- Hand findings to humans. Do not patch from the census.
§VII — Closing
Read the three shelves. Trust none by name alone. Maghrib will quiz the Cert framing later; keep this tool read-only.
Related
- Dev — Python GCS bucket policy inventory
- Cert — GCP PCA Cloud Storage classes and retention
- Go — BucketAttrs lifecycle inventory