fix: forEach and child tracking for NetworkPolicy, ResourceQuota, LimitRange, ClusterRole, ClusterRoleBinding#202
Merged
Merged
Conversation
…ource types NetworkPolicy, ResourceQuota, LimitRange, ClusterRole, and ClusterRoleBinding were missing ForEach field wiring, ExpandForEach* functions, name extractors, GVR entries, and read blocks — so forEach produced no expansion and none of the resources appeared as tracked children.
isFileMotif only matched ./ ../ and absolute paths. Bare relative paths like motifs/01-namespaced/motif.yaml were silently treated as OCI refs, causing ork validate to fail when run from outside the katalog directory.
…ypes Six motifs (namespaced, rbac, workloads, network, config, storage) imported into one katalog. Every resource uses forEach, giving a single runnable fixture for developing and verifying children changes.
ork e2e --report-file <path> writes test results as a GFM table in addition to stdout. Designed like Go's -coverprofile — the caller decides what to do with the file. ork-action passes $GITHUB_STEP_SUMMARY to populate the CI job summary automatically.
Passed and failed cases are rendered in separate tables so the error column only appears when there are failures. Newlines in error messages are collapsed to ". " to keep table rows valid GFM.
… detail Passed cases print first, failed cases follow with the full error message indented beneath each — multiline want/got errors render on separate lines. Also fixes a broken link to the e2e-universal guide in faqs/06-testing.md.
spec.onFailure runs once after all expectations when any failed. expect[].onFailure runs immediately when that specific checkpoint fails, capturing cluster state at the moment of failure. Both accept the same kubectl DSL (get, logs, describe, events, exec) and raw commands. Assertion fields are ignored — output is always printed. Also bumps Chart.yaml to v0.7.10 and updates schema docs and fixture.
… isolated vs composite runs 06-full-stack/katalog.yaml declares managed-database commented out so the root composite can import it from 03-cross-crd without a duplicate CRD error. Step 1 in 06-full-stack/README.md now tells users to uncomment it when running in isolation. Root README.md adds a Troubleshooting section explaining the duplicate CRD error and the fix.
…subject namespace Cluster-scoped CR fixes cross-namespace owner reference GC — Kubernetes was deleting namespaced children (NetworkPolicy, ResourceQuota, LimitRange) because their owner reference pointed to a Namespaced CR in a different namespace. ClusterRoleBinding subject namespace hardcoded to default — it was resolving to the role name (developer/reviewer) from the forEach loop, producing an invalid namespace value.
…ion use linkTitle sync-docs.sh splits CHANGELOG.md into one page per release under content/docs/changelog/; _index.md auto-generated as a release index. sidebar.yaml: Changelog added after Roadmap. sidebar.html + single.html: display text uses .LinkTitle so changelog entries show just the version number while full title remains the page heading. Also: tip admonition indent fixed in 00-kubernetes-basics.md; roadmap last-updated date bumped to July 2026; CHANGELOG.md [UNRELEASED] marker removed — v0.7.10 is ready to ship.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
forEach:support for NetworkPolicy, ResourceQuota, LimitRange, ClusterRole, and ClusterRoleBinding was deferred from v0.7.8 when these types were first introduced. A declaredforEach:block was silently dropped — no expansion, no error. None of these types appeared as tracked children in the CR detail view or Control Center Resources tab.Also fixes a bug in
pkg/mergerwhere motif paths supplied as bare relative paths (e.g.motifs/01-namespaced/motif.yaml) were not recognised as file paths, causingork validate -f <katalog>to fail when run from outside the katalog's directory.Adds
ork e2e --report-file <path>— a CI-agnostic flag that writes test results as a markdown table to a file in addition to stdout — andonFailure:diagnostics at both spec level and per-expectation level.What changed
pkg/types/types_networkpolicy.go—ForEach *ForEachSpecadded toNetworkPolicyTemplateSourcetypes_resourcequota.go—ForEach *ForEachSpecadded toResourceQuotaTemplateSourcetypes_limitrange.go—ForEach *ForEachSpecadded toLimitRangeTemplateSourcetypes_rbac.go—ForEach *ForEachSpecadded toClusterRoleTemplateSourceandClusterRoleBindingTemplateSourcepkg/children/gvr.go—ResourceQuotaGVRandLimitRangeGVRvars added; both added toChildGVRs()foreach.go—ExpandForEachNetworkPolicies,ExpandForEachResourceQuotas,ExpandForEachLimitRanges,ExpandForEachClusterRoles,ExpandForEachClusterRoleBindingsaddedread.go—NetworkPoliciesadded to bothonCreateandonReconcilemerge blocks inmergeTemplatesnames.go—networkPolicyNames,resourceQuotaNames,limitRangeNames,clusterRoleNames,clusterRoleBindingNamesaddedchildren.go— read blocks for all five types added; resources now appear in the CR detail children mappkg/children/fixtures/Restructured from a single flat katalog into a motif-based fixture covering every child resource type, all using
forEach:. Tenant CRD is cluster-scoped so owner references from namespaced children in different namespaces are valid and not GC'd.katalog.yaml— one katalog importing six focused motifs (one per resource group)crd.yaml— Tenant CRD (cluster-scoped) withspec.namespaces,spec.roles, andspec.appsarray fieldscr.yaml— sample Tenant CR with values for all three arraysmotifs/01-namespaced/motif.yaml— Namespace, NetworkPolicy, ResourceQuota, LimitRange; allforEachoverspec.namespacesmotifs/02-rbac/motif.yaml— ClusterRole, ClusterRoleBinding (spec.roles); ServiceAccount, Role, RoleBinding (spec.namespaces); ClusterRoleBinding subjects usenamespace: defaultmotifs/03-workloads/motif.yaml— Deployment, StatefulSet, ReplicaSet, Pod, Job, CronJob; allforEachoverspec.appsmotifs/04-network/motif.yaml— Service, Ingress, HPA, PDB; allforEachoverspec.appsmotifs/05-config/motif.yaml— ConfigMap, Secret;forEachoverspec.namespacesmotifs/06-storage/motif.yaml— PV (spec.apps), PVC (spec.namespaces)README.md— why the fixture exists, coverage table, running locally, adding a new child typepkg/merger/helper.goisFileMotifextended to recognise bare relative paths (e.g.motifs/foo/motif.yaml) as file paths. Previously only./,../, and absolute paths were matched; bare paths without a leading./were silently treated as OCI references and failed to resolve.pkg/reconciler/run_template_reconcile.go— runner calls for all five types now pass slices throughExpandForEach*wrapperspkg/e2e/result.go—Markdown()renders results as two GFM tables: passed (icon, test, time) and failed (icon, test, time, error); newlines in error messages replaced with.runner.go— terminal output split: passed cases first, then failed cases with full error indented line-by-line;ReportFile stringinOptionswrites the markdown report to a file and printsReport written to <path>;runOnFailurecalled at spec level when any expectation fails, and per-expectation immediately when that checkpoint failsonfailure.go(new) —runOnFailureprints diagnostic kubectl and shell command output; never fails;printOnFailureKubectlmirrors the five read subcommands (get, logs, describe, events, exec);printDiagformats each entry with label and indented outputpkg/types/e2e.go—E2EOnFailuretype added;OnFailure *E2EOnFailureadded to bothE2ESpec(spec-level, runs once after all expectations) andE2EExpectation(per-expectation, runs immediately on that checkpoint's failure)cmd/cli/e2e.go--report-file <path>flag added; wired through toe2e.Options.ReportFileexamples/use-cases/full-stack-app/06-full-stack/katalog.yaml—managed-databaseCRD block commented out by default; uncomment when running this example in isolation06-full-stack/README.md— Step 1 updated with uncomment instruction and expected two-CRD validate outputREADME.md— Troubleshooting section added explaining the duplicate CRD error and fixRoot cause
forEach:support for the five v0.7.8 types was deferred — runners inpkg/resources/and builtins inpkg/children/builtins.gowere completed, but thepkg/children/plumbing (ExpandForEach*,*Names, GVR vars, read blocks inmergeTemplates, child tracking inchildren.go) was not.isFileMotifassumed all relative paths start with./or../, which is not enforced when users write motif imports by hand.Test plan
ork validate -f pkg/children/fixtures/katalog.yaml— passes from repo rootork run -f pkg/children/fixtures/katalog.yaml— Tenant CR applied; all resource types createdkubectl get namespaces—acme-devandacme-stagingappearkubectl get networkpolicies -A— deny-all policies in each namespacekubectl get resourcequotas -A— quotas in each namespacekubectl get limitranges -A— limit ranges in each namespacekubectl get clusterroles—acme-developerandacme-reviewerappearkubectl get clusterrolebindings— bindings appearkubectl get deployments -A—apiandworkerdeployments appearork e2e --report-file /tmp/results.md—Report written to /tmp/results.mdprinted; file contains two GFM tables (passed + failed with Error column)spec.onFailure:— diagnostic output printed after all expectations completeonFailure:— diagnostic output printed immediately after that checkpoint fails