k9s/internal/model/pulse.go

93 lines
2.0 KiB
Go

package model
import (
"context"
"fmt"
"github.com/derailed/k9s/internal"
"github.com/derailed/k9s/internal/client"
"github.com/derailed/k9s/internal/dao"
"github.com/derailed/k9s/internal/health"
)
// PulseListener represents a health model listener.
type PulseListener interface {
// PulseChanged notifies the model data changed.
PulseChanged(*health.Check)
// PulseFailed notifies the health check failed.
PulseFailed(error)
// MetricsChanged update metrics time series.
MetricsChanged(dao.TimeSeries)
}
// Pulse tracks multiple resources health.
type Pulse struct {
gvr *client.GVR
namespace string
listeners []PulseListener
health *PulseHealth
}
// NewPulse returns a new pulse.
func NewPulse(gvr *client.GVR) *Pulse {
return &Pulse{
gvr: gvr,
}
}
type HealthChan chan HealthPoint
// Watch monitors pulses.
func (p *Pulse) Watch(ctx context.Context) (HealthChan, dao.MetricsChan, error) {
f, ok := ctx.Value(internal.KeyFactory).(dao.Factory)
if !ok {
return nil, nil, fmt.Errorf("expected Factory in context but got %T", ctx.Value(internal.KeyFactory))
}
if p.health == nil {
p.health = NewPulseHealth(f)
}
healthChan := p.health.Watch(ctx, p.namespace)
metricsChan := dao.DialRecorder(f.Client()).Watch(ctx, p.namespace)
return healthChan, metricsChan, nil
}
// Refresh update the model now.
func (*Pulse) Refresh(context.Context) {}
// GetNamespace returns the model namespace.
func (p *Pulse) GetNamespace() string {
return p.namespace
}
// SetNamespace sets up model namespace.
func (p *Pulse) SetNamespace(ns string) {
if client.IsAllNamespaces(ns) {
ns = client.BlankNamespace
}
p.namespace = ns
}
// AddListener adds a listener.
func (p *Pulse) AddListener(l PulseListener) {
p.listeners = append(p.listeners, l)
}
// RemoveListener delete a listener.
func (p *Pulse) RemoveListener(l PulseListener) {
victim := -1
for i, lis := range p.listeners {
if lis == l {
victim = i
break
}
}
if victim >= 0 {
p.listeners = append(p.listeners[:victim], p.listeners[victim+1:]...)
}
}