package console import "sort" // DeploymentVersion is one version reported by an app's owned routes. type DeploymentVersion struct { Version string Count int } // DeploymentStatus describes observed adoption independently of channel // pointers. A pointer says what a route should adopt; Route.Version says what // that address actually reports serving. type DeploymentStatus struct { RouteCount int ReportableCount int ReportedCount int UnknownCount int Versions []DeploymentVersion } func (d DeploymentStatus) HasRoutes() bool { return d.RouteCount > 0 } func (d DeploymentStatus) HasReportable() bool { return d.ReportableCount > 0 } func (d DeploymentStatus) HasReportedVersion() bool { return d.ReportedCount > 0 } func (d DeploymentStatus) Mixed() bool { return len(d.Versions) > 1 } // UniformVersion is non-empty only when every reported route agrees. Unknown // routes do not manufacture disagreement: callers use UnknownCount to expose // that the observation is partial. func (d DeploymentStatus) UniformVersion() string { if len(d.Versions) == 1 { return d.Versions[0].Version } return "" } // observedDeployment folds only routes owned by the viewed account. Assemble // groups routes by app name across accounts, so this is a tenant boundary. func observedDeployment(routes []RouteView, acct string) DeploymentStatus { counts := make(map[string]int) var d DeploymentStatus for _, rt := range routes { if rt.Account != acct || rt.Platform { continue } d.RouteCount++ if rt.Kind != "" && rt.Kind != "instance" { continue } d.ReportableCount++ if rt.Version == "" { d.UnknownCount++ continue } d.ReportedCount++ counts[rt.Version]++ } versions := make([]string, 0, len(counts)) for version := range counts { versions = append(versions, version) } sort.Strings(versions) for _, version := range versions { d.Versions = append(d.Versions, DeploymentVersion{Version: version, Count: counts[version]}) } return d }