NAME

Kubernetes::Comb::SVG::Cell - One Comb custom resource, normalised for layout and drawing

VERSION

version 0.001

SYNOPSIS

use Kubernetes::Comb::SVG::Cell;

my $cell = Kubernetes::Comb::SVG::Cell->from_cr( $cr,
  group_label => 'app.kubernetes.io/part-of' );

my @cells = Kubernetes::Comb::SVG::Cell->cells_from($list_or_array_or_cr);

for my $cell (@cells) {
  printf "%s %s -> %s\n", $cell->id, $cell->phase,
    join ',', @{ $cell->dependencies };
}

DESCRIPTION

The only place a Comb custom resource is read. A cell carries the plain values layout and drawing need; nothing in it is escaped (the drawing does that). The input is duck-typed: a hash in CR shape, or an object answering TO_JSON, which is also tried on every section (metadata, spec, status, ...). The module never talks to a cluster and does not need Kubernetes::Comb or IO::K8s.

Odd data degrades quietly: a section that is not a hash counts as empty, a value that is not a plain non-empty string counts as absent, a missing status gives phase Unknown. Only a Comb without metadata.name is an error.

name

Required. metadata.name.

namespace

metadata.namespace, or undef when the custom resource has none.

id

namespace/name, or the "name" alone when there is no namespace. This is what makes a cell unique in a set (so kubectl get combs -A may carry one name in two namespaces), what "dependencies" hold, and what the drawing puts in data-id. Not a constructor argument.

class

spec.class, or undef.

phase

Default Unknown. The phase the cell is drawn in: Disabled when "enabled" is false, else status.phase when it is one of "known_phases", else Unknown (also for a missing status).

raw_phase

status.phase as the custom resource has it, or undef when it is absent or not a string. It is kept even when "phase" says something else, so the tooltip can show what an Unknown cell really reported.

enabled

Default true. spec.enabled is read as a tri-state: unset is true; only a false value switches the cell off (false, the string false in any case, 0, the empty string); any other value is true. A disabled cell has the phase Disabled even without a status.

depends_on

ArrayRef of the entries of spec.dependsOn as written, each name or namespace/name, in order, without duplicates. A single string instead of a list is accepted. Entries that are not plain non-empty strings are dropped. Not yet resolved; see "dependencies" and "missing".

dependencies

ArrayRef of the "id"s of the cells this one depends on, in the order of "depends_on", without duplicates. Filled by "cells_from"; empty on a cell built alone. A cell that lists itself has its own id here. Not a constructor argument.

missing

ArrayRef of the "depends_on" entries, as written, that match no cell of the set, or more than one. Filled by "cells_from"; empty on a cell built alone. The drawing lists them in the tooltip; they do not take part in the layout. Not a constructor argument.

endpoints

ArrayRef of { name => $name, port => $port } from status.endpoints, in order. port is a string, or undef when the entry has none; an entry without a name is skipped.

borrowed

Default false. True when the Comb really takes its service from an upstream layer instead of running it: an upstream is recorded ("upstream_recorded"), its reachable is not false, and "phase" is one of "borrowing_phases", Running or Pending -- the two phases Kubernetes::Comb ends its upstream path in, with the bridge in place. reachable is read like spec.enabled (see "enabled"): unset counts as reachable, only a false value says otherwise. In any other phase a recorded upstream is what an earlier step left behind, or one the Comb did not get to, and the cell is not borrowed. This is what the drawing marks.

upstream_recorded

Default false. True when status.upstream is present, that is a non-empty hash -- whether or not the cell is "borrowed". "upstream_class", "upstream_context" and "upstream_via" are kept for every such cell, so the tooltip can name the upstream of a cell that does not borrow from it.

upstream_class

status.upstream.class, or undef.

upstream_context

status.upstream.context, or undef.

upstream_via

ArrayRef of the names in status.upstream.via, in order, without duplicates; a single string is accepted.

group

The value of the label named by the group_label option in metadata.labels. undef without that option, without the label, or with an empty value.

message

The message of every entry of status.conditions, each once, joined by newlines; undef when there is none. Only read when "phase" is not Running. It is what the tooltip shows; "reason" is the one short line in the picture.

reason

Why the cell is not Running, in a few words and uncut: the line the drawing puts under the phase. undef when "phase" is Running.

It comes from one entry of status.conditions: the one of type Ready, else the first whose status is not True. Its reason is taken, unless that is absent, is NotChecked, or only repeats the phase (Disabled on a Disabled cell; compared without case and punctuation, against "phase" and "raw_phase"). Then the first line of the message of that same entry stands in, trimmed -- unless it too only repeats the phase. With neither, or without such an entry, it is undef.

known_phases

my @phases = Kubernetes::Comb::SVG::Cell->known_phases;

Returns the phases of Kubernetes::Comb that are drawn as themselves: Running, Pending, Blocked, NeedsConfig, Disabled, Error, Stopped, NotDeployed -- the order of its CombStatus. Any other phase is Unknown. Callable on the class.

borrowing_phases

my @phases = Kubernetes::Comb::SVG::Cell->borrowing_phases;

Returns the phases in which a Comb with a recorded upstream is "borrowed": Running and Pending. Callable on the class.

is_known_phase

$cell->is_known_phase('Running');   # true
$cell->is_known_phase('Starting');  # false

True when the phase is one of "known_phases"; false for an unknown phase and for undef.

from_cr

my $cell = Kubernetes::Comb::SVG::Cell->from_cr( $cr, group_label => $key );

Builds one cell from a custom resource: a hash in CR shape or an object answering TO_JSON. group_label is the label key for "group". Reads metadata.name, metadata.namespace, metadata.labels, spec.class, spec.enabled, spec.dependsOn, status.phase, status.conditions, status.endpoints and status.upstream; everything else is ignored.

"dependencies" and "missing" stay empty, since one cell alone cannot resolve them; use "cells_from" for a set. Croaks with Comb without metadata.name when there is no name (a missing, empty or non-string one) -- it is the only error; any other odd shape is read as absent.

cells_from

my @cells = Kubernetes::Comb::SVG::Cell->cells_from( $input, group_label => $key );

Returns the cells of a whole set, in input order. $input is an array reference of custom resources, a List hash with items, one custom resource (a hash without items), or an object answering TO_JSON that turns into one of these; undef gives the empty list. Options are those of "from_cr". Croaks like "from_cr" on an element without a name. Of several custom resources with one "id" the first is kept.

Then every spec.dependsOn entry is resolved over the set into "dependencies" and "missing":

  • namespace/name is the cell with exactly that "id".

  • A bare name is the cell of that name in the dependent's own namespace (without namespace: the cell of that name without one), else the only cell of that name in the whole set.

  • No match, or several equally good ones, makes the entry "missing".

SEE ALSO

SUPPORT

Issues

Please report bugs and feature requests on GitHub at https://github.com/Getty/p5-kubernetes-comb-svg/issues.

IRC

Join #kubernetes on irc.perl.org or message Getty directly.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <getty@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.