show

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package show fans one read out across the configured controllers, joins what each answered into rows, and hands them to a renderer.

Index

Constants

View Source
const (
	DefaultSortAPName    = keyAPName
	DefaultSortMAC       = "mac"
	DefaultSortWLANID    = "wlan_id"
	DefaultSortPolicyTag = keyPolicyTag
	DefaultSortSiteTag   = keySiteTag
	DefaultSortRFTag     = keyRFTag
)

Default sort keys, one per command. The three tag views sort by their own key leaf, the one column of each the controller cannot omit.

Variables

View Source
var (
	// ErrPartial means at least one read failed while at least one succeeded, whether the failure
	// cost a controller its rows or only some cells. The rows that exist are still printed.
	ErrPartial = errors.New("partial failure")

	// ErrAllFailed means no controller answered.
	ErrAllFailed = errors.New("all controllers failed")
)

Outcomes the fan-out reports. Both are raised only after every failure has been logged per controller, so the caller adds no message of its own.

Functions

func APColumns

func APColumns() []render.Column[APRow]

APColumns describes the access point view. Uptime is the access point's own age from boot-time and Assoc is the age of the current CAPWAP association from join-time; a controller switchover renews only the second, so one column for both would report it as a fleet reboot.

func APJoinColumns

func APJoinColumns() []render.Column[APJoinRow]

APJoinColumns describes the join view. It is the only one that shows an access point absent from capwap-data, whose record here carries the phase that failed and the reason it disconnected.

func APJoinKeys

func APJoinKeys() []string

APJoinKeys are the columns of show ap-join, one row per access point the controller remembers, joined or not. No counter is a column: nothing on the list declares a clear time, so a total since boot has no window.

func APKeys

func APKeys() []string

APKeys are the columns of show ap, one row per access point.

func APTagColumns

func APTagColumns() []render.Column[APTagRow]

APTagColumns describes the tag view. Policy, Site and RF Tag are the resolved values in force; AP Profile and Flex Profile have no resolved counterpart in the schema, so they are the configured site tag's own and agree with Site Tag only while the two site tags do.

func APTagKeys

func APTagKeys() []string

APTagKeys are the columns of show ap-tag, one row per access point. The MAC is named as "show ap tag summary" names it, where show ap keeps "radio_mac" beside the Ethernet MAC.

func ClientColumns

func ClientColumns() []render.Column[ClientRow]

ClientColumns describes the client view. Device is the controller's own classification label and not a hostname: the leaf that does carry one sits on a list this SDK cannot reach.

func ClientKeys

func ClientKeys() []string

ClientKeys are the columns of show client, one row per associated client.

func OverviewColumns

func OverviewColumns() []render.Column[OverviewRow]

OverviewColumns describes the per-radio view. Channel is a channel number and not a frequency, its YANG declaring no units, so the cell says "ch".

Of the units here only dBm and the percentage are declared by the controller, on curr-tx-power-in-dbm and cca-util-percentage; MHz rests on chan-width's own enum descriptions, because the leaf is a bare uint8 and the module declares no Hz unit.

func OverviewKeys

func OverviewKeys() []string

OverviewKeys are the columns of show overview, one row per AP radio.

func PolicyTagColumns

func PolicyTagColumns() []render.Column[PolicyTagRow]

PolicyTagColumns describes the policy tag view. WLAN is the WLAN profile name the binding keys on rather than the SSID, and the two differ on any WLAN not named after its SSID.

func PolicyTagKeys

func PolicyTagKeys() []string

PolicyTagKeys are the columns of show policy-tag, one row per WLAN binding the tag carries and one row for a tag that carries none.

func RFTagColumns

func RFTagColumns() []render.Column[RFTagRow]

RFTagColumns describes the RF tag view.

The 2.4 GHz column is the 802.11b leaf and the 5 GHz one the 802.11a leaf, which is the pairing the write path's own setters name and the one place these two can be swapped.

func RFTagKeys

func RFTagKeys() []string

RFTagKeys are the columns of show rf-tag, one row per RF tag. The three profile keys are the --profile-24ghz, --profile-5ghz and --profile-6ghz flags of set rf-tag.

func Run

func Run[R any](ctx context.Context, env Env, cols []render.Column[R], fetch Fetcher[R]) error

Run executes one show command end to end. Every controller is read concurrently while the reads inside one are sequential, and reporting waits for all of them and then walks them in the order they were given, so two runs of the same command produce the same lines.

func SiteTagColumns

func SiteTagColumns() []render.Column[SiteTagRow]

SiteTagColumns describes the site tag view. Local Site takes no glyph: neither reading is a fault or a feature switched off.

func SiteTagKeys

func SiteTagKeys() []string

SiteTagKeys are the columns of show site-tag, one row per site tag. ap_join_profile is spelt as the leaf and the --ap-join-profile flag spell it, where show ap-tag calls it ap_profile.

func WLANColumns

func WLANColumns() []render.Column[WLANRow]

WLANColumns describes the WLAN view. Policy Status is separate from Status because a WLAN can be enabled while the profile bound to it is shut, in which case no radio carries it.

func WLANKeys

func WLANKeys() []string

WLANKeys are the columns of show wlan, one row per WLAN and bound policy profile. interface is the policy profile's interface name, which is not a VLAN id.

Types

type APJoinRow

type APJoinRow struct {
	APName            *string `json:"ap_name,omitzero"`
	RadioMAC          *string `json:"radio_mac,omitzero"`
	EthernetMAC       *string `json:"ethernet_mac,omitzero"`
	IPAddress         *string `json:"ip_address,omitzero"`
	Status            *string `json:"status,omitzero"`
	LastFailurePhase  *string `json:"last_failure_phase,omitzero"`
	LastJoinFailure   *string `json:"last_join_failure,omitzero"`
	LastConfigFailure *string `json:"last_config_failure,omitzero"`
	LastDiscFailure   *string `json:"last_disc_failure,omitzero"`
	DisconnectReason  *string `json:"disconnect_reason,omitzero"`
	RebootReason      *string `json:"reboot_reason,omitzero"`
	LastJoin          *int64  `json:"last_join_seconds,omitzero"`
	LastConfig        *int64  `json:"last_config_seconds,omitzero"`
	LastDiscovery     *int64  `json:"last_discovery_seconds,omitzero"`
	LastError         *int64  `json:"last_error_seconds,omitzero"`
	Controller        string  `json:"controller"`
}

APJoinRow is one row of show ap-join: one access point the controller remembers, joined or not. Status is a *string rather than the *bool the controller sends, because the device's own words are Joined and Not Joined where render.Bool would print Yes and No.

func FetchAPJoins

func FetchAPJoins(ctx context.Context, c *wnc.Client, t config.Target, _ *Reporter) ([]APJoinRow, error)

FetchAPJoins reads one controller's join view. One collection carries every column, so there is no secondary read to degrade and no join to get wrong.

type APRow

type APRow struct {
	APName       *string `json:"ap_name,omitzero"`
	Model        *string `json:"model,omitzero"`
	Serial       *string `json:"serial,omitzero"`
	EthernetMAC  *string `json:"ethernet_mac,omitzero"`
	RadioMAC     *string `json:"radio_mac,omitzero"`
	IPAddress    *string `json:"ip_address,omitzero"`
	SWVersion    *string `json:"sw_version,omitzero"`
	Slots        *uint8  `json:"slots,omitzero"`
	Country      *string `json:"country,omitzero"`
	Mode         *string `json:"mode,omitzero"`
	Admin        *string `json:"admin,omitzero"`
	State        *string `json:"state,omitzero"`
	LLDPNeighbor *string `json:"lldp_neighbor,omitzero"`
	PowerType    *string `json:"power_type,omitzero"`
	PowerMode    *string `json:"power_mode,omitzero"`
	Uptime       *int64  `json:"uptime_seconds,omitzero"`
	AssocUptime  *int64  `json:"assoc_uptime_seconds,omitzero"`
	Controller   string  `json:"controller"`
}

APRow is one row of show ap.

func FetchAPs

func FetchAPs(ctx context.Context, c *wnc.Client, t config.Target, rep *Reporter) ([]APRow, error)

type APTagRow

type APTagRow struct {
	APName          *string `json:"ap_name,omitzero"`
	APMAC           *string `json:"ap_mac,omitzero"`
	Misconfigured   *bool   `json:"misconfigured,omitzero"`
	MisconfigReason *string `json:"misconfig_reason,omitzero"`
	TagSource       *string `json:"tag_source,omitzero"`
	FilterName      *string `json:"filter_name,omitzero"`
	PolicyTag       *string `json:"policy_tag,omitzero"`
	SiteTag         *string `json:"site_tag,omitzero"`
	RFTag           *string `json:"rf_tag,omitzero"`
	APProfile       *string `json:"ap_profile,omitzero"`
	FlexProfile     *string `json:"flex_profile,omitzero"`
	Controller      string  `json:"controller"`
}

APTagRow is one row of show ap-tag.

func FetchAPTags

func FetchAPTags(ctx context.Context, c *wnc.Client, t config.Target, _ *Reporter) ([]APTagRow, error)

FetchAPTags reads one controller's tag view. One collection carries every column, so there is no secondary read to degrade and no join to get wrong.

type ClientFilter

type ClientFilter struct {
	Band   string
	SSID   string
	APName string
}

ClientFilter narrows the rows. An empty field selects everything.

type ClientRow

type ClientRow struct {
	MAC        *string `json:"mac,omitzero"`
	IPv4       *string `json:"ipv4,omitzero"`
	IPv6       *string `json:"ipv6,omitzero"`
	Device     *string `json:"device,omitzero"`
	Username   *string `json:"username,omitzero"`
	SSID       *string `json:"ssid,omitzero"`
	APName     *string `json:"ap_name,omitzero"`
	Slot       *int    `json:"slot,omitzero"`
	Band       *string `json:"band,omitzero"`
	Protocol   *string `json:"protocol,omitzero"`
	Channel    *int    `json:"channel,omitzero"`
	State      *string `json:"state,omitzero"`
	RSSI       *int    `json:"rssi_dbm,omitzero"`
	SNR        *int    `json:"snr_db,omitzero"`
	Speed      *int    `json:"speed_mbps,omitzero"`
	Streams    *int    `json:"spatial_streams,omitzero"`
	Assoc      *int64  `json:"assoc_seconds,omitzero"`
	RxBytes    *uint64 `json:"rx_bytes,omitzero"`
	TxBytes    *uint64 `json:"tx_bytes,omitzero"`
	Controller string  `json:"controller"`
}

ClientRow is one row of show client.

type Env

type Env struct {
	Settings  config.Settings
	Logger    *logrus.Logger
	Out       io.Writer
	UserAgent string
}

Env is what a show command needs from the CLI layer.

type Fetcher

type Fetcher[R any] func(ctx context.Context, c *wnc.Client, t config.Target, rep *Reporter) ([]R, error)

Fetcher reads one controller and builds its rows. The error it returns is fatal for that controller, so its rows are dropped; a read costing only some cells goes to the Reporter and the fetch continues.

func FetchClients

func FetchClients(filter ClientFilter) Fetcher[ClientRow]

FetchClients builds the fetcher for one filter.

func FetchOverview

func FetchOverview(band string) Fetcher[OverviewRow]

FetchOverview builds the fetcher for one band filter.

type OverviewRow

type OverviewRow struct {
	APName     *string `json:"ap_name,omitzero"`
	APMAC      *string `json:"ap_mac,omitzero"`
	Slot       *int    `json:"slot,omitzero"`
	Mode       *string `json:"mode,omitzero"`
	Band       *string `json:"band,omitzero"`
	Admin      *string `json:"admin,omitzero"`
	Oper       *string `json:"oper,omitzero"`
	Channel    *int    `json:"channel,omitzero"`
	Width      *int    `json:"channel_width_mhz,omitzero"`
	TxPower    *int8   `json:"tx_power_dbm,omitzero"`
	Clients    *int    `json:"clients,omitzero"`
	ChUtil     *int    `json:"ch_util_percent,omitzero"`
	RFProfile  *string `json:"rf_profile,omitzero"`
	Controller string  `json:"controller"`
}

OverviewRow is one row of show overview: one access point radio. ap_mac is the access point's base radio address and is the same on every radio of one access point, so the row identity is the (controller, ap_mac, slot) triple and the column is not called "radio mac".

type PolicyTagRow

type PolicyTagRow struct {
	PolicyTag     *string `json:"policy_tag,omitzero"`
	Description   *string `json:"description,omitzero"`
	WLAN          *string `json:"wlan,omitzero"`
	PolicyProfile *string `json:"policy_profile,omitzero"`
	Controller    string  `json:"controller"`
}

PolicyTagRow is one row of show policy-tag: one policy tag paired with one WLAN binding it carries, so a tag binding three WLANs is three rows.

func FetchPolicyTags

func FetchPolicyTags(ctx context.Context, c *wnc.Client, t config.Target, _ *Reporter) ([]PolicyTagRow, error)

FetchPolicyTags reads one controller's policy tags. One collection carries every column, so there is no secondary read to degrade and no join to get wrong.

type RFTagRow

type RFTagRow struct {
	RFTag        *string `json:"rf_tag,omitzero"`
	Description  *string `json:"description,omitzero"`
	Profile24GHz *string `json:"profile_24ghz,omitzero"`
	Profile5GHz  *string `json:"profile_5ghz,omitzero"`
	Profile6GHz  *string `json:"profile_6ghz,omitzero"`
	Controller   string  `json:"controller"`
}

RFTagRow is one row of show rf-tag.

func FetchRFTags

func FetchRFTags(ctx context.Context, c *wnc.Client, t config.Target, _ *Reporter) ([]RFTagRow, error)

type Reporter

type Reporter struct {
	// contains filtered or unexported fields
}

Reporter collects what went wrong while reading one controller, so the reads finish before anything is written: a line per failure interleaved across concurrent controllers would come out in a different order every run.

func (*Reporter) Degradations

func (r *Reporter) Degradations() int

func (*Reporter) Degraded

func (r *Reporter) Degraded(endpoint string, err error)

Degraded records a read that failed while leaving the rows intact. The cells it would have filled stay unreported, because a zero in their place would be a reading nothing gave.

func (*Reporter) Excluded

func (r *Reporter) Excluded(n int, reason string)

Excluded records rows a filter dropped because the leaf it filters on was not reported, which is the difference between "no client on that band" and "the band was never reported".

func (*Reporter) Note

func (r *Reporter) Note(text string)

Note records something an operator should see that is not a failure.

type SiteTagRow

type SiteTagRow struct {
	SiteTag       *string `json:"site_tag,omitzero"`
	Description   *string `json:"description,omitzero"`
	APJoinProfile *string `json:"ap_join_profile,omitzero"`
	FlexProfile   *string `json:"flex_profile,omitzero"`
	LocalSite     *bool   `json:"local_site,omitzero"`
	Controller    string  `json:"controller"`
}

SiteTagRow is one row of show site-tag.

func FetchSiteTags

func FetchSiteTags(ctx context.Context, c *wnc.Client, t config.Target, _ *Reporter) ([]SiteTagRow, error)

type WLANRow

type WLANRow struct {
	WLANID         *int    `json:"wlan_id,omitzero"`
	Profile        *string `json:"profile,omitzero"`
	SSID           *string `json:"ssid,omitzero"`
	Status         *string `json:"status,omitzero"`
	Security       *string `json:"security,omitzero"`
	Bands          *string `json:"bands,omitzero"`
	Broadcast      *string `json:"broadcast,omitzero"`
	P2PBlock       *string `json:"p2p_block,omitzero"`
	PolicyStatus   *string `json:"policy_status,omitzero"`
	Switching      *string `json:"switching,omitzero"`
	Interface      *string `json:"interface,omitzero"`
	SessionTimeout *int    `json:"session_timeout_seconds,omitzero"`
	DHCPRequired   *bool   `json:"dhcp_required,omitzero"`
	PolicyProfile  *string `json:"policy_profile,omitzero"`
	Tags           *string `json:"tags,omitzero"`
	Controller     string  `json:"controller"`
}

WLANRow is one row of show wlan: one WLAN paired with one policy profile it is bound to, so the same WLAN bound under two tags to two profiles is two rows.

func FetchWLANs

func FetchWLANs(ctx context.Context, c *wnc.Client, t config.Target, rep *Reporter) ([]WLANRow, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL