coverage

package
v0.29.0 Latest Latest
Warning

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

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package coverage builds the disco-vs-upstream type coverage matrix for every registered cloud provider. Each provider implements Provider and registers itself via init() — see internal/providers/<p>/coverage.go.

Coverage truth source = the emits []TypeDecl declared on each scanner's serviceEntry, aggregated through the provider's Emits() method. Upstream truth source = a live registry call (CFN ListTypes / ARM Providers/List / GCP Discovery API) executed at command time. The matching engine reconciles the two sets via per-provider alias maps to produce the final matrix.

Index

Constants

View Source
const (
	RegionCovered = "covered"
	RegionStale   = "stale"
	RegionMissing = "missing"
)

Region status string constants.

Variables

This section is empty.

Functions

func AlgorithmicUpstreamKey

func AlgorithmicUpstreamKey(discoType string) string

AlgorithmicUpstreamKey is the fallback used when no alias is registered for a disco-type. Today it's just the lowercased disco-type itself — alias maps are the source of truth for accurate matching; the fallback only lets providers whose upstream-key shape equals the disco-type skip alias entries.

Per-provider algorithmic conversions (CFN PascalCase, ARM camelCase, GCP resource-collection forms) live in the provider's coverage.go alias-map builder, alongside the provider's other quirks.

func Names

func Names() []string

Names returns the sorted names of every registered provider.

func Register

func Register(p Provider)

Register adds a Provider to the global registry. Called from each provider package's init().

func RenderJSON

func RenderJSON(w io.Writer, matrices []Matrix) error

RenderJSON emits a structured matrix slice for tooling. Shape mirrors the in-memory Matrix/Row types directly so consumers can decode into the same structs.

func RenderMarkdown

func RenderMarkdown(w io.Writer, matrices []Matrix) error

RenderMarkdown writes a per-provider markdown matrix (covered / uncovered / uncatalogued / upstream-missing). Suitable for `disco coverage -o markdown` piped into docs/coverage.md or pasted into the README.

func RenderRegionsMarkdown

func RenderRegionsMarkdown(w io.Writer, rows []RegionRow) error

RenderRegionsMarkdown writes a markdown table of region rows.

func RenderRegionsTable

func RenderRegionsTable(w io.Writer, rows []RegionRow) error

RenderRegionsTable writes a tabwriter-aligned table of region rows.

func RenderTable

func RenderTable(w io.Writer, matrices []Matrix) error

RenderTable writes a tabwriter-aligned plain-text matrix. Bucket column supports shell filtering, e.g. `awk '$4 == "covered"'`.

Types

type Bucket

type Bucket string

Bucket classifies a single matrix row.

const (
	BucketCovered         Bucket = "covered"
	BucketUncovered       Bucket = "uncovered"
	BucketNotScannable    Bucket = "not-scannable"
	BucketUncatalogued    Bucket = "uncatalogued"
	BucketUpstreamMissing Bucket = "upstream-missing"
)

Bucket values; semantics documented in internal/coverage/CLAUDE.md.

type CanonicalKeyer

type CanonicalKeyer interface {
	CanonicalKey(upstreamKey string) string
}

CanonicalKeyer is an optional interface a Provider may implement to collapse the same physical resource spelled differently across two upstream catalogs (AWS's CloudFormation ∪ Service Reference union). It maps an upstream key to a catalog-agnostic identity; Build treats an unmatched upstream key as covered when its identity equals an already-covered key's identity (the cross-catalog duplicate case). No impl → no canonical dedup (Azure/GCP single-catalog).

type FetchOptions

type FetchOptions struct {
	Regions      []string
	Profile      string
	Subscription string
}

FetchOptions carry per-invocation knobs from the cmd. Each provider reads only the fields it cares about — AWS uses Regions/Profile, Azure uses Subscription, GCP ignores all three.

Regions is a slice so multi-region sweeps can union upstream type lists across regions in one call. Empty slice = provider-default (AWS falls back to "us-east-1" for CloudFormation ListTypes; Azure ARM types are subscription-scoped so a no-op; GCP Discovery is region-agnostic).

type Matrix

type Matrix struct {
	Provider string `json:"provider"`
	Rows     []Row  `json:"rows"`
}

Matrix groups rows by provider for rendering.

func Build

func Build(providerName string, emits []TypeDecl, aliases map[string]string, algorithmic func(string) string, upstream []UpstreamType, skips map[string]string, canonical func(string) string) Matrix

Build assembles the coverage matrix for one provider. emits and upstream are deduped by canonical keys (DiscoType / UpstreamKey) first. A disco-type whose alias resolves to a live upstream key is covered; a miss falls to BucketUncatalogued if flagged Uncatalogued (expected registry gap for a scanned resource), else BucketUpstreamMissing — the drift signal in ROADMAP G5. Uncatalogued is checked only after a failed match, so such a type auto-upgrades to covered once the registry lists it. skips maps a (case-insensitive) upstream key to why disco doesn't scan it; matching leftover-upstream entries become BucketNotScannable instead of BucketUncovered. Pass nil if the provider declares no skips.

type Provider

type Provider interface {
	Name() string
	Fetch(ctx context.Context, opts FetchOptions) ([]UpstreamType, error)
	Emits() []TypeDecl
	Aliases() map[string]string             // disco-type -> upstream key (overrides)
	AlgorithmicKey(discoType string) string // fallback when no alias entry exists
}

Provider is implemented by each cloud provider package. Aggregates emits from registeredServices, exposes the live Fetch, and supplies the alias map + an algorithmic fallback used when a disco-type has no explicit alias.

func All

func All() []Provider

All returns every registered Provider, sorted by Name.

func Get

func Get(name string) (Provider, bool)

Get returns the registered Provider by name.

type RegionLister

type RegionLister interface {
	FetchRegions(ctx context.Context, opts FetchOptions) ([]string, error)
}

RegionLister is implemented by Provider impls that can fetch the cloud's authoritative region/location list via SDK. Optional — providers without an SDK list endpoint don't implement it. Drives `disco coverage --regions`.

type RegionRow

type RegionRow struct {
	Provider string `json:"provider"`
	Region   string `json:"region"`
	Status   string `json:"status"`
}

RegionRow categorises a single region across the static-vs-live diff. Status values:

  • "covered" — region appears in both disco's static RegionNames list and the cloud's live API response.
  • "stale" — disco lists it but the live API doesn't return it (region retired or typo in the static list).
  • "missing" — live API returns it but disco's static list lacks it (refresh internal/providers/<p>/regions.go).

func DiffRegions

func DiffRegions(static, live []string) []RegionRow

DiffRegions categorises every region across the union of static and live lists. Output is sorted by region name for diff-stable rendering. Provider field on each row is left empty; the caller fills it in.

type ResolverAuditor

type ResolverAuditor interface {
	ListResolvers() []ResolverInfo // one entry per registered resolver, registration order
	ResolverEdgeSources() []string // distinct EdgeDecl.Source disco-types across all resolvers
}

ResolverAuditor is an optional interface a Provider may implement to expose its relationship-resolver registry to `disco coverage resolvers`. Keeping it behind the registry (rather than a direct provider-package import in cmd) lets cmd stay provider-agnostic, so a slim build that excludes the provider simply reports the auditor as unavailable. AWS, Azure, and GCP implement it.

type ResolverInfo

type ResolverInfo struct {
	Name      string   `json:"name"`
	EdgeCount int      `json:"edgeCount"`
	Services  []string `json:"services,omitempty"`
}

ResolverInfo summarises one registered relationship resolver for the `disco coverage resolvers` tooling: the resolver function name, the count of declared EdgeDecls, and the distinct disco service segments its edges touch. EdgeCount==0 marks an unannotated (intentional no-op or pending) resolver.

type Row

type Row struct {
	Provider    string `json:"provider"`
	Service     string `json:"service"`
	DiscoType   string `json:"discoType,omitempty"`   // empty when row is upstream-only (uncovered/not-scannable)
	UpstreamKey string `json:"upstreamKey,omitempty"` // empty when row is uncatalogued
	Bucket      Bucket `json:"bucket"`
	Reason      string `json:"reason,omitempty"` // not-scannable rationale, or "duplicate of <key>" on a cross-catalog twin
}

Row is one entry in the coverage matrix.

type Skipper

type Skipper interface {
	Skips() map[string]string // upstream-key -> rationale
}

Skipper is an optional interface a Provider may implement to declare upstream resource keys it deliberately does not scan — CFN sub-resource/association types with no standalone List API, ephemeral task/quote/report records, preview services with no public SDK, or duplicates of an already-scanned type. Each entry maps the upstream key to a one-line rationale. Build reclassifies matching leftover-upstream rows from BucketUncovered to BucketNotScannable so the uncovered bucket reflects genuine, actionable gaps only.

type TypeDecl

type TypeDecl struct {
	Service   string // disco's service segment (e.g. "ec2", "compute", "microsoft.compute")
	DiscoType string // canonical disco type, e.g. "aws:ec2:instance"
	// Uncatalogued marks a real resource disco scans via the SDK that no
	// upstream registry (CFN/SR, ARM, Discovery) lists — e.g. aws:kms:grant,
	// the Azure Entra identities. Suppresses the upstream-missing drift signal
	// on the no-match path; auto-upgrades to covered if the registry later
	// lists it.
	Uncatalogued bool
	// Leaf marks a type as intentionally edge-less: its scanner upserts rows
	// but the resource has no outbound refs to other scanned types
	// (account-level configs, registry policies, leaf catalogue items).
	// `disco coverage --missing-resolvers` filters these out so the orphan
	// list only contains genuinely wire-able candidates.
	Leaf bool
}

TypeDecl is one disco resource type declared by a scanner's emits field.

type UpstreamType

type UpstreamType struct {
	Key     string // canonical upstream identifier, provider-specific shape
	Service string // grouping bucket for matrix rendering
}

UpstreamType is one entry returned by a provider's live registry Fetch.

Jump to

Keyboard shortcuts

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