Skip to content

feat(kubernetes): add Namespace to the core group [FIX-555] - #88

Merged
liamcervante merged 1 commit into
mainfrom
fix-555-add-namespace-resources
Aug 7, 2026
Merged

feat(kubernetes): add Namespace to the core group [FIX-555]#88
liamcervante merged 1 commit into
mainfrom
fix-555-add-namespace-resources

Conversation

@liamcervante

Copy link
Copy Markdown
Contributor

Description

Adds core.Namespace to the Kubernetes core group so the parser can put namespaces in the tree, which is what lets tagging policies be enforced on them (FIX-555).

Namespaces are where teams commonly record ownership — team, cost-centre, environment — so an unlabelled namespace is exactly the kind of gap a tagging policy exists to catch. It can't be reported while namespaces never reach the tree.

Open question — address shape (opinions wanted)

A Namespace is cluster-scoped, so it has no metadata.namespace of its own, and it doesn't fit the [namespace, kind, name] address every other Kubernetes kind uses. Two options; I went with the first, but I'm not attached to it and would like a second opinion before this lands.

Chosen — self-scoped, 3 segments:

prod.namespace.prod        segments: [prod, namespace, prod]

Keeps every Kubernetes kind on one address shape, and groups a namespace with the resources inside it — which reads well when policies are reported per namespace. Downside: the name appears twice, which looks odd on first sight.

Rejected — cluster-scoped, 2 segments:

namespace.prod             segments: [namespace, prod]

Honest about the API model (a Namespace really has no namespace). Downside: it'd be the only Kubernetes kind with a 2-segment address, and it needs a carve-out that returns a differently-shaped address rather than one that just fills in a different value.

The tie-breaker for me was that nothing actually depends on the choice, so consistency won over literal accuracy. I checked providers, runner and cli: the address is treated as an opaque string everywhere (.String() for map keys, display, and comparison against PreviousResourceAddresses). The only length-sensitive code is providers/internal/infracost/usage.go:77, which indexes from the end (At(Len()-2)) behind a Len() >= 2 guard, so it resolves the type correctly under either shape. Happy to switch if people prefer the literal model — it's a one-line change in the companion parser PR.

Notes for reviewers

  • Namespace is the first kind in this group that costs nothing. The other two are here because they provision cloud spend (a disk, a load balancer); this one is here purely for label enforcement. The package doc now splits those two rationales rather than claiming everything in core is cost-relevant.
  • No cost-relevant fields of its own. The labels are the point, and they live in the embedded resource.Resource's Tags — the same promotion every other Kubernetes kind does, which is what makes the existing tag machinery apply. Annotations is carried too, matching Workload / PersistentVolumeClaim / Service.
  • The tree is entirely reflection-driven, so wiring the slice into Core with a tree:"namespace" tag is the whole change — no generated code to update.

Testing

Extended TestKubernetesRoundTrip to cover a Namespace through ToProtoFromProto, asserting the labels-as-tags and SupportsTags survive — those being what tag policies act on. Full suite and golangci-lint pass.

Checklist

  • Technical docs updated (or not needed) — not needed; internal type addition with no user-facing surface.

Namespaces are where teams record ownership (team, cost-centre,
environment), so an unlabelled namespace is exactly the kind of gap a
tagging policy exists to catch — but it cannot be reported if the
namespace never reaches the tree.

Adds core.Namespace and wires it into the core group. Unlike the other
kinds in the group it provisions nothing and has no cost-relevant fields
of its own: its labels, stored as the base resource's Tags, are the
point. Annotations are carried too, matching the other kinds.
@liamcervante
liamcervante requested a review from a team August 7, 2026 05:45
@liamcervante
liamcervante merged commit 517dde5 into main Aug 7, 2026
2 checks passed
@liamcervante
liamcervante deleted the fix-555-add-namespace-resources branch August 7, 2026 09:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants