Skip to content

chore: cherry-pick upstream tagging fixes onto July release branch - #25

Merged
jtroup merged 12 commits into
release/2026-07-27from
elmo/low-dove
Sep 23, 2026
Merged

jtroup merged 12 commits into
release/2026-07-27from
elmo/low-dove

Conversation

@jtroup

@jtroup jtroup commented Sep 23, 2026 •

Copy link
Copy Markdown

ENG-8877

what

Cherry-picks eleven upstream commits onto release/2026-07-27.

Dynamic tag values (#10942, #10961, #10968): a tag value can be
resolved from the resource being tagged, on AWS, GCP and Azure.
#10968 extracts the resolve-and-group logic into a
TagValueResolver mixin so the ASG tag action can share it without
being a Tag subclass, and extends the "default value with no key"
form from AWS to GCP and Azure, which writes the tag only when the
resource doesn't already carry it.

Resources that disappear or can't be tagged (#11089, #11050,
#10967, #11016, #19): #11089 centralizes mid-run deletion
handling in c7n/tags.py, where retry_skip_bad_ids drops the ids
EC2 names in a rejected batch and retries the rest, and
is_resource_gone recognizes the per-service "already gone" error
codes. That replaces the bespoke EBS snapshot and volume tag actions,
which are deleted. The others exclude AWS-managed KMS keys, Route53
resources and the default Athena data catalog from tag operations,
and keep S3 going when a single bucket errors during augment() or
tagging.

GCP (#11052, #10969): Cloud Run label mutations send only schema
fields in a knative replace body, and a None source result is
normalized to [] before augment() iterates it.

CloudWatch dashboards (#11090): tagged through the native
CloudWatch APIs, which the resource groups tagging API doesn't
support.

why

The July release branch was cut before this run of upstream tagging
work landed. Most of it already sits on the June release branch -
#10942, #10961, #10967, #10969, #11052 and the S3 tolerance
changes were backported there - so this brings July to parity and
adds the newer upstream fixes (#10968, #11050, #11089,
#11090) on top.

testing

Each cherry-pick carries its upstream tests. Between them they cover
tag value resolution by lookup, fallback and conditional default
across the three providers, the ASG tag action driving the shared
resolver, batch tagging where EC2 rejects named ids and where a
service reports a resource already gone, the AWS-managed exclusions
for KMS, Route53 and Athena, per-bucket tolerance in the S3 augment
and tag paths, knative body field filtering for Cloud Run, and
dashboard tag and untag through the CloudWatch APIs. New flight data
and terraform fixtures accompany the EC2 and dashboard tagging paths.

Verification beyond that lands downstream: unit tests here, then
platform's unit and functional suites once this prerelease publishes.

docs

No docs needed. The tag and label actions carry their own :example:
docstrings, which came across with the cherry-picks and feed the
generated resource documentation.


🤖 Generated with Claude Code

jtroup and others added 11 commits September 17, 2026 14:34
### what

`modify_bucket_tags()` tolerates the same transport failures
`BucketAssembly.assemble()` already does, on both the tag re-fetch and
the write. A bucket whose endpoint doesn't answer is logged and
skipped; the rest of the batch is tagged as normal.

`ConnectionClosedError` joins that set in both places. A degraded
endpoint can accept a connection and then drop it rather than refusing
or hanging, and that class was in neither handler - so it would still
abort the tag action, and still abort collection for the whole
account, which is what cd79871 set out to stop.

`ProxyConnectionError`, `SSLError` and `ResponseStreamingError` are
deliberately left to raise: the first two say something is wrong with
the path to s3 rather than with one bucket, and the third can't
plausibly happen on a response this small.

### why

One bucket whose endpoint hangs silently costs healthy buckets their
tags, on every run.

`modify_bucket_tags()` caught only `ClientError`, so a connect timeout
raised out of it and abandoned the rest of its batch.
`_common_tag_processer` chunks at `Tag.batch_size` - 25 for `tag`, 100
for `remove-tag` - and walks each chunk serially, so the loss is every
bucket after the hung one in its own chunk. How many that is depends
on where the hung bucket sorts in `list_buckets` order, so it is
silent, it varies, and it repeats every run. Measured against an
account matching the reported one, 76 buckets with one timing out on
every call:

| hung bucket's position | before | after |
| ---------------------- | ------ | ----- |
| last | run errors, 75 of 75 tagged | succeeds, 75 of 75 |
| eleventh | run errors, 61 of 75 tagged | succeeds, 75 of 75 |

The run also reported error either way, so an account that was in fact
being tagged still looked like a failure to anything gating on run
status.

This is what remains after cd79871, which stopped the same bucket
from aborting resource collection outright. `list_buckets` is global,
so every run in every region enumerates the whole account - one bucket
whose endpoint hangs is on the path of every s3 policy, not only ones
targeting its region.

The bucket that couldn't be read is skipped rather than written to:
tags are set atomically for the whole set, so writing one we couldn't
re-read would drop whatever tags it has.

### testing

New tests cover a hung bucket on the re-fetch and on the write leaving
the rest of the batch tagged; a connection closed mid response
surviving both collection and the tag action; and an end to end case -
collection then tag action, with one bucket timing out on every call -
asserting that a hung bucket at the head of a chunk costs none of the
29 buckets behind it. That last one fails against the previous
behaviour with the timeout propagating out of the action, which is the
reported symptom.

### docs

No docs needed.

---------------------------

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…operations (cloud-custodian#10967)

---------

Co-authored-by: Matthew Heidelbaugh <42586165+mattheidelbaugh@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…oud-custodian#10969)

Policies targeting gcp.cloud-run-service or gcp.cloud-run-job crashed with
`TypeError: 'NoneType' object is not iterable` on any account that has zero
Cloud Run resources. The non-paginated GCP source path returns None (rather
than []) for an empty result set, and the augment() methods added in cloud-custodian#10658
iterate `resources` directly, so the crash fires before the existing `or []`
guard in _fetch_resources can coerce it.

Move the guard up one level so the source result is normalized to [] before
augment() runs, per @ajkerrigan's suggestion in cloud-custodian#10955. This single choke
point protects every resource type's augment() instead of adding a brittle
per-augment guard.

Includes a regression test: an empty Cloud Run service list now returns []
instead of raising.

Reported and root-caused by Thatcher Smith (@tjs-rubrik).

Closes cloud-custodian#10955

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d-custodian#11050)

- kms-key: AWS managed keys (KeyManager == 'AWS', e.g. the keys behind
  alias/aws/s3, alias/aws/ebs) reject tag mutations, key policy changes,
  rotation changes, and ScheduleKeyDeletion - AWS owns their full
  lifecycle.
- resolver-rule: Route 53's global auto-defined rules (e.g.
  rslvr-autodefined-rr-internet-resolver) have no owning account and
  reject tag mutations the same way.

Fixes cloud-custodian#11027

Co-authored-by: Usman Qureshi <usman.nja.14@gmail.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* Centralize dynamic tag lookup logic where possible
* Extend the "default-value with no key" pattern from AWS to GCP & Azure
* Fix aws.asg-specific tag logic, and extract shared behavior between ASG & generic tag logic into a mixin
…1089)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…loud-custodian#11090)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jtroup
jtroup requested a review from a team as a code owner September 23, 2026 16:12

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 59 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread c7n/resources/s3.py Resolved
Comment thread c7n/resources/route53.py Resolved
Comment thread c7n/resources/cw.py Resolved
Comment thread c7n/tags.py Resolved
@greptile-apps

greptile-apps Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The latest version-stamping and release-guard changes appear safe to merge, with no new blocking findings.

Summary

Backports upstream tagging fixes onto the July release branch, including resource-derived tag values, shared AWS deletion handling, managed-resource exclusions, native CloudWatch dashboard tagging, and GCP request corrections.

  • The latest changes stamp all 13 workspace packages with .post1 and synchronize the lockfile and embedded core version.
  • The release guard now accepts stamped alpha post-releases while preserving the existing prerelease and hash requirements.
  • No new actionable issues were identified in the changes since the previous review.

Reviews (2) · Last reviewed commit: "chore: stamp 0.9.52a4.post1 and allow .p..."

Comment thread c7n/resources/s3.py Resolved
Comment thread c7n/tags.py Resolved
Comment thread c7n/resources/cw.py Resolved
Comment thread c7n/tags.py Resolved
Comment thread c7n/tags.py Resolved
Comment thread tools/c7n_gcp/c7n_gcp/actions/labels.py Resolved

@kevin-birkett kevin-birkett left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @jtroup

@jtroup
jtroup merged commit 52df489 into release/2026-07-27 Sep 23, 2026
4 checks passed
@jtroup
jtroup deleted the elmo/low-dove branch September 23, 2026 22:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants