Hedronite · Ops Lesson · 01-Earth-DevOps / GCS · Sun 2026-09-13

Python GCS bucket lifecycle and retention census — classes, rules, locks

Lifecycle moves class. Retention locks delete. Versioning keeps generations.

Lesson Class: Ops (DevOps + Python + GCS lifecycle/retention)
Cloud Referent: GCP Cloud Storage lifecycle + retention + versioning
Paired Dev: Python google-cloud-storage bucket policy inventory
Paired Cert: GCP PCA Cloud Storage classes and retention
Paired Go: Go BucketAttrs lifecycle inventory
Grounding: Bootcamp Ch.3 lifecycle JSON · PCA-Notes retention · ACE/PCA cheatsheet
Class
Standard, Nearline, Coldline, Archive.
Lifecycle
SetStorageClass and Delete by age.
Lock
Retention period and locked flag.
Print all three shelves before you trust a bucket.

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

ShelfWhat it doesWhat it does not do
Storage class / lifecycleAges objects into Nearline, Coldline, Archive, or DeleteReplace a retention lock
Retention policyBlocks delete and overwrite for a locked periodKeep prior generations after overwrite
Object versioningKeeps noncurrent generationsStop 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

  1. Empty lifecycle on a log bucket. Default Standard forever. Chapter-3 expected Coldline at 30 days. Finding: missing SetStorageClass rule.
  2. 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.
  3. Versioning on, retention off, no lifecycle. Overwrites keep generations and bill for them. Versioning without a noncurrent delete rule is a cost leftover.
  4. 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

  1. Scope the project (and folder if you must walk many projects).
  2. List buckets; reload each.
  3. Print storage_class, lifecycle_rules, retention_*, versioning_enabled.
  4. Flag Standard+empty-lifecycle on cold data classes.
  5. Flag Delete rules that beat retention or legal hold needs.
  6. Flag versioning without noncurrent cleanup when cost matters.
  7. 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