TT Lab
Get started
Learn Learning paths Courses

CBA — Backstage Associate

Writing Software Catalog Entities

Continue in TT Lab

Goal

Write the eight entity kinds of the Backstage software catalog yourself, and get used to the relation declarations and reference format between them. At the end, you express the same ownership information on a real cluster workload and connect the two worlds.

Why it matters

A catalog is not a list but a relationship graph. If you declare spec.owner, spec.system, and spec.providesApis on only one side, the catalog computes the bidirectional relations — so which field you write where decides the shape of the graph. The owner in particular matters so much that, if only one thing in the catalog had to be accurate, it would be that. Outage calls, vulnerability tickets, cost attribution, and retirement decisions all branch from the owner. And the owner must always be a team, not a person — because people leave and teams are taken over. In real operations, the files you create in this lab are committed together at the root of the service's code repository and registered automatically by discovery. Backstage itself is not in this environment, so grading reads the files and cluster objects.

Steps

  1. In /root/cba-catalog/catalog-info.yaml, write a Component — apiVersion: backstage.io/v1alpha1, kind: Component, metadata.name: checkout-service, metadata.description any sentence, metadata.annotations with backstage.io/techdocs-ref: dir:. and backstage.io/kubernetes-id: checkout-service, spec.type: service, spec.lifecycle: production, spec.owner: group:team-checkout, spec.system: commerce, and spec.providesApis with the first item checkout-api.
  2. In /root/cba-catalog/api-checkout.yaml, write an API — kind: API, metadata.name: checkout-api, spec.type: openapi, spec.lifecycle: production, spec.owner: group:team-checkout, spec.system: commerce, and spec.definition as a multi-line string (block scalar) that starts with openapi: 3.0.0.
  3. In /root/cba-catalog/resource-db.yaml, write a Resource — kind: Resource, metadata.name: checkout-db, spec.type: database, spec.owner: group:team-checkout, spec.system: commerce.
  4. In /root/cba-catalog/system-commerce.yaml, write a System — kind: System, metadata.name: commerce, spec.owner: group:team-checkout, spec.domain: retail. In /root/cba-catalog/domain-retail.yaml, write a Domain — kind: Domain, metadata.name: retail, spec.owner: group:team-checkout.
  5. In /root/cba-catalog/group-team-checkout.yaml, write a Group — kind: Group, metadata.name: team-checkout, spec.type: team, spec.profile.displayName any value, spec.children: []. In /root/cba-catalog/user-youngju.yaml, write a User — kind: User, metadata.name: youngju, spec.memberOf with the first item team-checkout.
  6. In /root/cba-catalog/all.yaml, write a Location — kind: Location, metadata.name: cba-catalog-all, spec.type: url, and in spec.targets list the seven entity files you created earlier as relative paths like ./catalog-info.yaml (7 in total).
  7. Express the same ownership information on the cluster. Create the namespace cba-commerce (with the label app.kubernetes.io/part-of: commerce), and inside it create the Deployment checkout-service — in the metadata labels put backstage.io/kubernetes-id: checkout-service, app.kubernetes.io/name: checkout-service, and app.kubernetes.io/part-of: commerce, and also put backstage.io/kubernetes-id: checkout-service in the Pod template labels. The image is nginx:1.27-alpine and replicas is 1.
  8. In /root/cba-catalog/refs.txt, write the normalized references of all the entities you created earlier (Component, API, Resource, System, Domain, Group, User — 7 in total), one per line. The format is <소문자 kind>:default/<이름> (the placeholders are the lowercase kind and the name). Example: component:default/checkout-service. Exclude the Location.

Notes

Component entity

In /root/cba-catalog/catalog-info.yaml, write a Component — apiVersion: backstage.io/v1alpha1, kind: Component, metadata.name: checkout-service, metadata.description any sentence, metadata.annotations with backstage.io/techdocs-ref: dir:. and backstage.io/kubernetes-id: checkout-service, spec.type: service, spec.lifecycle: production, spec.owner: group:team-checkout, spec.system: commerce, and spec.providesApis with the first item checkout-api.

The required spec fields of a Component are type, lifecycle, and owner. Write the owner so that it points to a team, not a person, and spell out the first part of the reference format.

API entity

In /root/cba-catalog/api-checkout.yaml, write an API — kind: API, metadata.name: checkout-api, spec.type: openapi, spec.lifecycle: production, spec.owner: group:team-checkout, spec.system: commerce, and spec.definition as a multi-line string (block scalar) that starts with openapi: 3.0.0.

An API entity holds its definition as a string. If you use a YAML block scalar, you can hold several lines as they are.

Resource entity

In /root/cba-catalog/resource-db.yaml, write a Resource — kind: Resource, metadata.name: checkout-db, spec.type: database, spec.owner: group:team-checkout, spec.system: commerce.

A Resource is infrastructure a component needs. The field name that indicates the type is the same as in Component.

System and Domain

In /root/cba-catalog/system-commerce.yaml, write a System — kind: System, metadata.name: commerce, spec.owner: group:team-checkout, spec.domain: retail. In /root/cba-catalog/domain-retail.yaml, write a Domain — kind: Domain, metadata.name: retail, spec.owner: group:team-checkout.

A System is a group of things that work together, and a Domain is the higher-level area of systems. The field that links the two is on the System side.

Group and User

In /root/cba-catalog/group-team-checkout.yaml, write a Group — kind: Group, metadata.name: team-checkout, spec.type: team, spec.profile.displayName any value, spec.children: []. In /root/cba-catalog/user-youngju.yaml, write a User — kind: User, metadata.name: youngju, spec.memberOf with the first item team-checkout.

A Group is a team and a User is a person. The field that says which team a person belongs to is on the User side.

Group them with a Location

In /root/cba-catalog/all.yaml, write a Location — kind: Location, metadata.name: cba-catalog-all, spec.type: url, and in spec.targets list the seven entity files you created earlier as relative paths like ./catalog-info.yaml (7 in total).

A Location is a signpost that points to other entity files. It only makes sense if the targets it points to actually exist.

The same ownership as cluster labels

Express the same ownership information on the cluster. Create the namespace cba-commerce (with the label app.kubernetes.io/part-of: commerce), and inside it create the Deployment checkout-service — in the metadata labels put backstage.io/kubernetes-id: checkout-service, app.kubernetes.io/name: checkout-service, and app.kubernetes.io/part-of: commerce, and also put backstage.io/kubernetes-id: checkout-service in the Pod template labels. The image is nginx:1.27-alpine and replicas is 1.

The Kubernetes plugin looks for workload labels that have the same value as the entity's annotation. Tell apart which of annotation and label belongs to the entity and which to the workload.

Normalize entity references

In /root/cba-catalog/refs.txt, write the normalized references of all the entities you created earlier (Component, API, Resource, System, Domain, Group, User — 7 in total), one per line. The format is <소문자 kind>:default/<이름> (the placeholders are the lowercase kind and the name). Example: component:default/checkout-service. Exclude the Location.

The normalized format writes kind in lowercase and does not omit the namespace. All the entities you created earlier are targets.