Repository navigation
CLO-188 orchestratord: report Materialize lifecycle transitions as events #38537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
493ffb7
3918cf6
8698e04
fa572cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3563,9 +3563,59 @@ def workflow_manually_promote( | |
| wait_for_rollout_complete() | ||
| print("Test 2 PASSED: Promotion via v1 requestedRolloutHash succeeded") | ||
|
|
||
| # Two manual promotions have now driven the full lifecycle, so every phase | ||
| # of one should have been reported as an event. | ||
| check_lifecycle_events(definition) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider — Noted by claude: The sibling check just above uses retry(lambda: _check_lifecycle_events(name), 60)written by claude on behalf of @jubrad |
||
| print("workflow_manually_promote PASSED") | ||
|
|
||
|
|
||
| def check_lifecycle_events(definition: dict[str, Any]) -> None: | ||
| """Assert that the operator reported each rollout phase as an event. | ||
|
|
||
| The status conditions record only the phase the resource is in now, so the | ||
| events are the only account of the phases it passed through. Their reasons | ||
| are what a dashboard groups on, which is why this pins the exact vocabulary | ||
| rather than checking that any event at all was published. | ||
| """ | ||
| name = definition["materialize"]["metadata"]["name"] | ||
| events = json.loads( | ||
| spawn.capture( | ||
| [ | ||
| "kubectl", | ||
| "get", | ||
| # The events.k8s.io API explicitly, rather than the core v1 view | ||
| # `kubectl get events` serves, which renames these fields. | ||
| "events.events.k8s.io", | ||
| "-n", | ||
| "materialize-environment", | ||
| "-o", | ||
| "json", | ||
| ], | ||
| ) | ||
| )["items"] | ||
| by_reason = { | ||
| event["reason"]: event | ||
| for event in events | ||
| if event.get("regarding", {}).get("kind") == "Materialize" | ||
| and event.get("regarding", {}).get("name") == name | ||
| } | ||
| # ManuallyPromote holds at ReadyToPromote until forcePromote is set, so a | ||
| # promotion under this strategy passes through all three. | ||
| for reason in ("Applying", "ReadyToPromote", "Promoting", "Applied"): | ||
| assert reason in by_reason, ( | ||
| f"Expected a {reason} event on Materialize/{name}, " | ||
| f"found {sorted(by_reason)}" | ||
| ) | ||
| event = by_reason[reason] | ||
| assert event["type"] == "Normal", event | ||
| assert event["reportingController"] == "orchestratord.materialize.cloud", event | ||
| assert event.get("note"), event | ||
| # The promotion events should name the generation they promoted, which is | ||
| # what makes them readable against a rollout after the fact. | ||
| applied = by_reason["Applied"]["note"] | ||
| assert "generation" in applied, applied | ||
|
|
||
|
|
||
| def apply_materialize(definition: dict[str, Any]) -> None: | ||
| """Apply the materialize resource definition via kubectl.""" | ||
| defs = [ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit — This is ~30 lines of doc and inline prose for ~20 lines of code, and a good part of it re-argues things that already have an owner. The third paragraph ("These do not aggregate the way repeated failures do...") restates
Publisher's aggregation contract, which thePublisherdoc explains at length; the inline comment at thelet condition = ...line restates the guard three lines above it; and the second paragraph explains the relationship toObserved::publish_failurefrom the wrong end.Per CLAUDE.md the doc comment should be the caller's contract, with reasoning at the decision point and each fact owned once. Something like a one-line summary plus "published only once the status is durable" would carry everything a caller needs, with the severity policy staying on
transition_event_typewhere it already lives.written by claude on behalf of @jubrad