Catalog Consistency Checks and Gates
Goal
You statically diagnose a catalog you have taken over to find four kinds of defects, create a fixed copy, and harden the same checks into a lint gate that runs in a PR. Backstage is not in this environment, so all diagnoses are done by reading files.
Why it matters
A catalog rots not at the moment of registration but as time passes. And most of the rot is not reported as an error by Backstage. An entity that violates the schema is displayed, but a reference to a nonexistent target simply ends up as a relation that was not computed and appears as a blank cell on screen. An empty screen does not look like an outage, so nobody reports it, and so nobody fixes it. The four things this lab covers are the shapes that appear repeatedly in the field. The habit of normalizing references before comparing them is especially important. team-orders, group:team-orders, and group:default/team-orders point to the same thing, but if you compare them as strings, a perfectly good reference is reported as a defect. The lint gate in the last step is only half done if you just check that it gives 0 on clean input. Only when it gives a non-zero value when you deliberately insert a defect is that gate protecting something.
Steps
- Create the eight files below in
/root/cba-audit/incoming/exactly as written. All haveapiVersion: backstage.io/v1alpha1. Do not fill in fields that are described as missing.component-orders.yaml— Componentorders-service,spec.type: service,spec.lifecycle: production,spec.owner: group:team-orders,spec.system: commerce-core,spec.providesApiswith the first itemorders-api, andspec.dependsOnwith two itemsresource:orders-dbandcomponent:ledger-service.component-ledger.yaml— Componentledger-service,spec.type: service,spec.lifecycle: production,spec.owner: group:team-ledger,spec.system: finance-core, andspec.dependsOnwith the first itemcomponent:orders-service.component-report.yaml— Componentreport-worker,spec.type: service,spec.owner: group:team-analytics,spec.system: commerce-core, andspec.dependsOnwith the first itemresource:analytics-warehouse. There is nospec.lifecycle.api-orders.yaml— APIorders-api,spec.type: openapi,spec.lifecycle: production, andspec.system: commerce-core. There is nospec.owner.resource-orders-db.yaml— Resourceorders-db,spec.type: database,spec.owner: group:team-storage, andspec.system: commerce-core.system-commerce-core.yaml— Systemcommerce-core,spec.owner: group:team-orders, andspec.domain: retail-ops.group-team-orders.yaml— Groupteam-orders,spec.type: team.group-team-ledger.yaml— Groupteam-ledger,spec.type: team.
- In
/root/cba-audit/missing-required.txt, write the places where required fields are missing, one per line. The format is<정규화된 엔티티 참조> <필드 경로>(the placeholders are the normalized entity reference and the field path). The required fields common to all kinds areapiVersion,kind, andmetadata.name, and to these are addedspec.type,spec.lifecycle, andspec.ownerfor Component and API,spec.typeandspec.ownerfor Resource,spec.ownerfor System and Domain, andspec.typefor Group. - In
/root/cba-audit/dangling-owners.txt, write the cases wherespec.ownerpoints to a group that does not exist in this directory. The format is<엔티티 참조> <정규화한 소유자 참조>(the placeholders are the entity reference and the normalized owner reference). The default kind of the owner isgroup, and the namespace default isdefault. - In
/root/cba-audit/dangling-refs.txt, write the cases where references other than the owner point to targets that do not exist. The target fields arespec.system(default kind system),spec.domain(domain),spec.dependsOn(component), andspec.providesApis(api). The format is<가리킨 쪽 참조> <없는 대상의 참조>(the placeholders are the referencing side's reference and the reference of the nonexistent target). - In
/root/cba-audit/dependency-cycle.txt, write, one per line, the references of entities that are caught in a cycle when you follow thespec.dependsOnedges. Count only edges that point to entities that actually exist. - Create the fixed catalog in
/root/cba-audit/fixed/. When you run the four diagnoses of steps 2–5 again againstfixed/, all must be 0 findings, and the eight entities that were inincoming/must all remain with their kind and name as they were. You may create missing entities anew if needed. - Write
/root/cba-audit/lint.sh. It checks the directory given as the first argument, and must end with a non-zero value if there is even one missing required field or reference to a nonexistent target, and with 0 if there is nothing. The grader runs this script againstincoming/,fixed/, and two directories in which one defect each was planted. - Record the audit result on the cluster. Create the namespace
cba-audit(with the labelapp.kubernetes.io/part-of: developer-portal), and inside it create the ConfigMapcatalog-audit. There are three keys —incoming-findingsis the total number of defects found in steps 2–5,fixed-findingsis0, andentitiesis the number of entity files infixed/.
Notes
- A reference is
[<kind>:][<namespace>/]<name>and you must always normalize it before comparing. - The default kind differs per field.
spec.owneris group,spec.systemis system, andspec.dependsOnis component. - Common mistake 1: deleting entities with defects to make the list clean. A service you made invisible also breaks at 3 a.m.
- Common mistake 2: fixing individual entities first. If you do not create the missing Groups and Domains first, you end up fixing the same spot twice.
- Common mistake 3: testing lint only on clean input. A gate that always gives 0 is worse than none.
Reproduce the catalog you took over
Create the eight files below in /root/cba-audit/incoming/ exactly as written. All have apiVersion: backstage.io/v1alpha1. Do not fill in fields that are described as missing.
component-orders.yaml— Componentorders-service,spec.type: service,spec.lifecycle: production,spec.owner: group:team-orders,spec.system: commerce-core,spec.providesApiswith the first itemorders-api, andspec.dependsOnwith two itemsresource:orders-dbandcomponent:ledger-service.component-ledger.yaml— Componentledger-service,spec.type: service,spec.lifecycle: production,spec.owner: group:team-ledger,spec.system: finance-core, andspec.dependsOnwith the first itemcomponent:orders-service.component-report.yaml— Componentreport-worker,spec.type: service,spec.owner: group:team-analytics,spec.system: commerce-core, andspec.dependsOnwith the first itemresource:analytics-warehouse. There is nospec.lifecycle.api-orders.yaml— APIorders-api,spec.type: openapi,spec.lifecycle: production, andspec.system: commerce-core. There is nospec.owner.resource-orders-db.yaml— Resourceorders-db,spec.type: database,spec.owner: group:team-storage, andspec.system: commerce-core.system-commerce-core.yaml— Systemcommerce-core,spec.owner: group:team-orders, andspec.domain: retail-ops.group-team-orders.yaml— Groupteam-orders,spec.type: team.group-team-ledger.yaml— Groupteam-ledger,spec.type: team.
Copy exactly what the instructions say. Do not fill in fields that are described as missing. Those defects are what you diagnose in later steps.
Diagnose missing required fields
In /root/cba-audit/missing-required.txt, write the places where required fields are missing, one per line. The format is <정규화된 엔티티 참조> <필드 경로> (the placeholders are the normalized entity reference and the field path). The required fields common to all kinds are apiVersion, kind, and metadata.name, and to these are added spec.type, spec.lifecycle, and spec.owner for Component and API, spec.type and spec.owner for Resource, spec.owner for System and Domain, and spec.type for Group.
Required fields differ by kind. Component and API need all three of type, lifecycle, and owner, Resource needs two, and System and Domain need only owner.
Diagnose broken owners
In /root/cba-audit/dangling-owners.txt, write the cases where spec.owner points to a group that does not exist in this directory. The format is <엔티티 참조> <정규화한 소유자 참조> (the placeholders are the entity reference and the normalized owner reference). The default kind of the owner is group, and the namespace default is default.
The owner value can omit the kind, so you must normalize before comparing. The default for the namespace is default.
Diagnose broken references
In /root/cba-audit/dangling-refs.txt, write the cases where references other than the owner point to targets that do not exist. The target fields are spec.system (default kind system), spec.domain (domain), spec.dependsOn (component), and spec.providesApis (api). The format is <가리킨 쪽 참조> <없는 대상의 참조> (the placeholders are the referencing side's reference and the reference of the nonexistent target).
Besides the owner, there are four more fields that point to targets. Each field has a different default kind, so you must match that when you normalize.
Diagnose the dependency cycle
In /root/cba-audit/dependency-cycle.txt, write, one per line, the references of entities that are caught in a cycle when you follow the spec.dependsOn edges. Count only edges that point to entities that actually exist.
You only need to follow dependsOn. Count only edges that point to entities that actually exist, and on that graph find the entities that have a path back to themselves.
The fixed catalog
Create the fixed catalog in /root/cba-audit/fixed/. When you run the four diagnoses of steps 2–5 again against fixed/, all must be 0 findings, and the eight entities that were in incoming/ must all remain with their kind and name as they were. You may create missing entities anew if needed.
Fill in the organization data first, then the groupings, and fix the individual entities last. Deleting entities with defects to make the list clean is not fixing.
A lint gate that runs in a PR
Write /root/cba-audit/lint.sh. It checks the directory given as the first argument, and must end with a non-zero value if there is even one missing required field or reference to a nonexistent target, and with 0 if there is nothing. The grader runs this script against incoming/, fixed/, and two directories in which one defect each was planted.
It is not enough for a gate to give 0 on clean input. Deliberately insert a defect and be sure to check that a non-zero value comes out. The grader tests it that way too.
The audit result on the cluster
Record the audit result on the cluster. Create the namespace cba-audit (with the label app.kubernetes.io/part-of: developer-portal), and inside it create the ConfigMap catalog-audit. There are three keys — incoming-findings is the total number of defects found in steps 2–5, fixed-findings is 0, and entities is the number of entity files in fixed/.
Do not count the numbers by hand; calculate them from the outputs of the earlier steps and put them in. The grader recomputes the same values from the original directory and compares them.