New to Kestra?
Use blueprints to kickstart your first workflows.
Scan a Huawei OBS prefix for objects past retention, alert Slack with reclaimable bytes, and optionally delete and verify the stale ones.
Temporary exports, staging landing zones and old job output tend to accumulate in object
storage because nothing ever looks back at them. Huawei OBS has lifecycle rules, but they are
bucket-wide or prefix-wide console configuration with no review step and no record of what they
actually deleted on a given day. This blueprint does the same job as a flow: list what's under a
prefix, decide what's stale from lastModified, alert on what it found, and, only when you ask
it to, delete exactly those objects and prove they are gone.
This blueprint was created by Mohit Jeswani.
list_stale_candidates (io.kestra.plugin.huawei.obs.List) lists every object under
prefix in bucket, optionally narrowed further by regexp. Read-only.evaluate (io.kestra.plugin.core.output.OutputValues) compares each object's
lastModified date against now() - retention_days and produces the stale object list,
their count, their total size in bytes, and a severity.route (io.kestra.plugin.core.flow.If):remediate_gate runs only when auto_cleanup is true and dry_run is false.cleanup (io.kestra.plugin.core.flow.Loop, concurrencyLimit: 1) calls
io.kestra.plugin.huawei.obs.Delete once per stale key, never the whole prefix, so an
object that is not actually stale is never touched.reread lists the prefix again, and verify_result fails the flow if any object past
retention_days is still there.summary logs the stale count, reclaimable bytes and severity, closing the governance cycle.errors alerts Slack if the flow itself fails, for example on an expired AK/SK.obs.List and
obs.Delete used together safely.An OBS lifecycle rule is silent: it runs in the background with no alert, no count of what it
removed, and no easy way to preview the impact before enabling it. Kestra keeps retention_days
and the prefix as flow inputs, reports what it found before anything is deleted, requires two
separate flags to actually delete, and leaves a full execution history of every run, compliant
or not, remediated or not.
auto_cleanup is ever enabled.This flow calls the Huawei Cloud OBS API directly over HTTPS; there is no official local Huawei
Cloud emulator. OBS is S3-API compatible, so List and Delete can be pointed at a local MinIO
container via endpointOverride and pathStyleAccess: true for a dry run of the logic, but the
actual lastModified ages used to prove retention_days need real aged objects, which is easiest
against a real trial-tier OBS bucket.
HUAWEI_AK: the IAM access key used by every OBS task in this flow. In Kestra OSS, provide it
as the base64-encoded environment variable SECRET_HUAWEI_AK.HUAWEI_SK: the IAM secret key paired with HUAWEI_AK. In Kestra OSS, provide it as the
base64-encoded environment variable SECRET_HUAWEI_SK.SLACK_WEBHOOK_URL: used by alert and the errors block. In Kestra OSS, provide it as the
base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.| Input | Type | Default | Purpose |
|---|---|---|---|
region |
STRING | eu-west-101 |
Huawei Cloud region used to sign OBS requests |
bucket |
STRING | <your-obs-bucket> |
Bucket to scan |
prefix |
STRING | tmp/ |
Only objects under this prefix are scanned |
regexp |
STRING | empty | Optional extra key filter, applied after the prefix |
retention_days |
INT | 30 |
Age past which an object is reported stale |
auto_cleanup |
BOOL | false |
Allow deleting the stale objects found this run |
dry_run |
BOOL | true |
Must be false for Delete to run |
{{ outputs.list_stale_candidates.objects }}: every object under the prefix, each with
key, size, lastModified, etag, owner.{{ outputs.evaluate.values.stale_count }} / {{ outputs.evaluate.values.stale_size_bytes }}:
how many objects are past retention and their combined size.{{ outputs.evaluate.values.severity }}: OK or STALE_OBJECTS_FOUND.{{ outputs.reread.objects }}: only present after a cleanup run, the post-delete listing used
to verify.prefix is the entire blast radius for auto_cleanup. A prefix of "" scans and can delete
the whole bucket; scope it narrowly.lastModified, the last write time, not by when an object was created
or first accessed. An object rewritten in place resets its own clock.List iterates every page under the prefix into memory before evaluate runs; a prefix with
millions of keys should be narrowed further or should set maxResults on list_stale_candidates
directly.auto_cleanup is ever turned on; keep it
read-only otherwise.versionId: Delete places a
delete marker instead of removing the object. Pass a lifecycle rule or a separate purge for
versioned buckets.HUAWEI_AK, HUAWEI_SK and SLACK_WEBHOOK_URL secrets.bucket and prefix to a real location you expect to accumulate temporary objects.summary.auto_cleanup: true and dry_run: false on a non-production prefix first, confirm
verify_result logs remediated, then apply the same change to production.schedule_daily_at_0230 trigger, which always runs in safe mode until you change its mapped inputs.owner or by a key pattern in regexp to scope cleanup to one team's exports.Delete in the cleanup loop with a copy-then-delete into a cheaper storage class if
Huawei OBS exposes one for your bucket, instead of removing the object outright.stale_size_bytes over time by logging it to a table with
io.kestra.plugin.core.output.OutputValues on every scheduled run, compliant or not.io.kestra.plugin.core.flow.Loop around the whole flow to
cover a fleet of staging locations in one schedule.