package dao import ( "context" "fmt" "regexp" "strings" "github.com/derailed/k9s/internal" "github.com/derailed/k9s/internal/client" "github.com/derailed/k9s/internal/config" "github.com/derailed/k9s/internal/render" "github.com/rs/zerolog/log" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) var ( _ Accessor = (*PortForward)(nil) _ Nuker = (*PortForward)(nil) ) // PortForward represents a port forward dao. type PortForward struct { NonResource } // Delete deletes a portforward. func (p *PortForward) Delete(_ context.Context, path string, _ *metav1.DeletionPropagation, _ bool) error { p.GetFactory().DeleteForwarder(path) return nil } // List returns a collection of port forwards. func (p *PortForward) List(ctx context.Context, _ string) ([]runtime.Object, error) { benchFile, ok := ctx.Value(internal.KeyBenchCfg).(string) if !ok { return nil, fmt.Errorf("no bench file found in context") } path, _ := ctx.Value(internal.KeyPath).(string) config, err := config.NewBench(benchFile) if err != nil { log.Warn().Msgf("No custom benchmark config file found") } ff, cc := p.GetFactory().Forwarders(), config.Benchmarks.Containers oo := make([]runtime.Object, 0, len(ff)) for k, f := range ff { if !strings.HasPrefix(k, path) { continue } cfg := render.BenchCfg{ C: config.Benchmarks.Defaults.C, N: config.Benchmarks.Defaults.N, } if cust, ok := cc[PodToKey(k)]; ok { cfg.C, cfg.N = cust.C, cust.N cfg.Host, cfg.Path = cust.HTTP.Host, cust.HTTP.Path } oo = append(oo, render.ForwardRes{ Forwarder: f, Config: cfg, }) } return oo, nil } // ---------------------------------------------------------------------------- // Helpers... var podNameRX = regexp.MustCompile(`\A(.+)\-(\w{10})\-(\w{5})\z`) // PodToKey converts a pod path to a generic bench config key. func PodToKey(path string) string { tokens := strings.Split(path, ":") ns, po := client.Namespaced(tokens[0]) sections := podNameRX.FindStringSubmatch(po) if len(sections) >= 1 { po = sections[1] } return client.FQN(ns, po) + ":" + tokens[1] } // BenchConfigFor returns a custom bench spec if defined otherwise returns the default one. func BenchConfigFor(benchFile, path string) config.BenchConfig { def := config.DefaultBenchSpec() cust, err := config.NewBench(benchFile) if err != nil { log.Debug().Msgf("No custom benchmark config file found") return def } if b, ok := cust.Benchmarks.Containers[PodToKey(path)]; ok { return b } def.C, def.N = cust.Benchmarks.Defaults.C, cust.Benchmarks.Defaults.N return def }