rework portforward + benchmarks
parent
1ef375e781
commit
2822ac702e
|
|
@ -49,11 +49,11 @@ type (
|
|||
|
||||
// BenchConfig represents a service benchmark.
|
||||
BenchConfig struct {
|
||||
Name string
|
||||
C int `yaml:"concurrency"`
|
||||
N int `yaml:"requests"`
|
||||
Auth Auth `yaml:"auth"`
|
||||
HTTP HTTP `yaml:"http"`
|
||||
Name string
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -73,7 +73,8 @@ func newBenchmark() Benchmark {
|
|||
}
|
||||
}
|
||||
|
||||
func (b Benchmark) empty() bool {
|
||||
// Empty checks if the benchmark is set
|
||||
func (b Benchmark) Empty() bool {
|
||||
return b.C == 0 && b.N == 0
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ func TestBenchEmpty(t *testing.T) {
|
|||
for k := range uu {
|
||||
u := uu[k]
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.e, u.b.empty())
|
||||
assert.Equal(t, u.e, u.b.Empty())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@ import (
|
|||
|
||||
const localhost = "localhost"
|
||||
|
||||
// Tunnel represents a host tunnel port mapper.
|
||||
type Tunnel struct {
|
||||
Address, LocalPort, ContainerPort string
|
||||
}
|
||||
|
||||
// PortForwarder tracks a port forward stream.
|
||||
type PortForwarder struct {
|
||||
client.Connection
|
||||
|
|
@ -88,8 +93,9 @@ func (p *PortForwarder) FQN() string {
|
|||
}
|
||||
|
||||
// Start initiates a port forward session for a given pod and ports.
|
||||
func (p *PortForwarder) Start(path, co, address string, ports []string) (*portforward.PortForwarder, error) {
|
||||
p.path, p.container, p.ports, p.age = path, co, ports, time.Now()
|
||||
func (p *PortForwarder) Start(path, co string, t Tunnel) (*portforward.PortForwarder, error) {
|
||||
fwds := []string{t.LocalPort + ":" + t.ContainerPort}
|
||||
p.path, p.container, p.ports, p.age = path, co, fwds, time.Now()
|
||||
|
||||
ns, n := client.Namespaced(path)
|
||||
auth, err := p.CanI(ns, "v1/pods", []string{client.GetVerb})
|
||||
|
|
@ -99,6 +105,8 @@ func (p *PortForwarder) Start(path, co, address string, ports []string) (*portfo
|
|||
if !auth {
|
||||
return nil, fmt.Errorf("user is not authorized to get pods")
|
||||
}
|
||||
|
||||
// BOZO!! Use the factory!
|
||||
pod, err := p.DialOrDie().CoreV1().Pods(ns).Get(n, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -131,7 +139,7 @@ func (p *PortForwarder) Start(path, co, address string, ports []string) (*portfo
|
|||
Name(n).
|
||||
SubResource("portforward")
|
||||
|
||||
return p.forwardPorts("POST", req.URL(), address, ports)
|
||||
return p.forwardPorts("POST", req.URL(), t.Address, fwds)
|
||||
}
|
||||
|
||||
func (p *PortForwarder) forwardPorts(method string, url *url.URL, address string, ports []string) (*portforward.PortForwarder, error) {
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ func (b *Benchmark) init(base, version string) error {
|
|||
}
|
||||
req.Header.Set("User-Agent", ua)
|
||||
|
||||
log.Debug().Msgf("Benching %d:%d", b.config.N, b.config.C)
|
||||
|
||||
b.worker = &requester.Work{
|
||||
Request: req,
|
||||
RequestBody: []byte(b.config.HTTP.Body),
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
package dialog
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/derailed/k9s/internal/ui"
|
||||
"github.com/derailed/tview"
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
const portForwardKey = "portforward"
|
||||
|
||||
// ShowPortForward pops a port forwarding configuration dialog.
|
||||
func ShowPortForward(p *ui.Pages, port string, okFn func(address, lport, cport string)) {
|
||||
f := tview.NewForm()
|
||||
f.SetItemPadding(0)
|
||||
f.SetButtonsAlign(tview.AlignCenter).
|
||||
SetButtonBackgroundColor(tview.Styles.PrimitiveBackgroundColor).
|
||||
SetButtonTextColor(tview.Styles.PrimaryTextColor).
|
||||
SetLabelColor(tcell.ColorAqua).
|
||||
SetFieldTextColor(tcell.ColorOrange)
|
||||
|
||||
p1, p2, address := port, port, "localhost"
|
||||
f.AddInputField("Pod Port:", p1, 20, nil, func(p string) {
|
||||
p1 = p
|
||||
})
|
||||
f.AddInputField("Local Port:", p2, 20, nil, func(p string) {
|
||||
p2 = p
|
||||
})
|
||||
f.AddInputField("Address:", address, 20, nil, func(h string) {
|
||||
address = h
|
||||
})
|
||||
|
||||
f.AddButton("OK", func() {
|
||||
okFn(address, stripPort(p2), stripPort(p1))
|
||||
})
|
||||
f.AddButton("Cancel", func() {
|
||||
DismissPortForward(p)
|
||||
})
|
||||
|
||||
modal := tview.NewModalForm("<PortForward>", f)
|
||||
modal.SetDoneFunc(func(_ int, b string) {
|
||||
DismissPortForward(p)
|
||||
})
|
||||
p.AddPage(portForwardKey, modal, false, false)
|
||||
p.ShowPage(portForwardKey)
|
||||
}
|
||||
|
||||
// DismissPortForward dismiss the port forward dialog.
|
||||
func DismissPortForward(p *ui.Pages) {
|
||||
p.RemovePage(portForwardKey)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
// StripPort removes the named port id if present.
|
||||
func stripPort(p string) string {
|
||||
tokens := strings.Split(p, ":")
|
||||
if len(tokens) == 2 {
|
||||
return strings.Replace(tokens[1], "╱UDP", "", 1)
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
|
@ -2,14 +2,19 @@ package dialog
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/derailed/k9s/internal/client"
|
||||
"github.com/derailed/k9s/internal/config"
|
||||
"github.com/derailed/k9s/internal/dao"
|
||||
"github.com/derailed/k9s/internal/ui"
|
||||
"github.com/derailed/tview"
|
||||
)
|
||||
|
||||
const portForwardKey = "portforward"
|
||||
|
||||
// PortForwardFunc represents a port-forward callback function.
|
||||
type PortForwardFunc func(path, address, lport, cport string)
|
||||
type PortForwardFunc func(path, co string, mapper dao.Tunnel)
|
||||
|
||||
// ShowPortForwards pops a port forwarding configuration dialog.
|
||||
func ShowPortForwards(p *ui.Pages, s *config.Styles, path string, ports []string, okFn PortForwardFunc) {
|
||||
|
|
@ -23,7 +28,7 @@ func ShowPortForwards(p *ui.Pages, s *config.Styles, path string, ports []string
|
|||
|
||||
p1, p2, address := ports[0], ports[0], "localhost"
|
||||
f.AddDropDown("Container Ports", ports, 0, func(sel string, _ int) {
|
||||
p1, p2 = sel, stripPort(sel)
|
||||
p1, p2 = sel, extractPort(sel)
|
||||
})
|
||||
|
||||
dropD, ok := f.GetFormItem(0).(*tview.DropDown)
|
||||
|
|
@ -43,15 +48,20 @@ func ShowPortForwards(p *ui.Pages, s *config.Styles, path string, ports []string
|
|||
})
|
||||
|
||||
f.AddButton("OK", func() {
|
||||
okFn(path, address, stripPort(p2), stripPort(p1))
|
||||
tunnel := dao.Tunnel{
|
||||
Address: address,
|
||||
LocalPort: p2,
|
||||
ContainerPort: extractPort(p1),
|
||||
}
|
||||
okFn(path, extractContainer(p1), tunnel)
|
||||
})
|
||||
f.AddButton("Cancel", func() {
|
||||
DismissPortForward(p)
|
||||
DismissPortForwards(p)
|
||||
})
|
||||
|
||||
modal := tview.NewModalForm(fmt.Sprintf("<PortForward on %s>", path), f)
|
||||
modal.SetDoneFunc(func(_ int, b string) {
|
||||
DismissPortForward(p)
|
||||
DismissPortForwards(p)
|
||||
})
|
||||
p.AddPage(portForwardKey, modal, false, false)
|
||||
p.ShowPage(portForwardKey)
|
||||
|
|
@ -61,3 +71,28 @@ func ShowPortForwards(p *ui.Pages, s *config.Styles, path string, ports []string
|
|||
func DismissPortForwards(p *ui.Pages) {
|
||||
p.RemovePage(portForwardKey)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
func extractPort(p string) string {
|
||||
tokens := strings.Split(p, ":")
|
||||
switch {
|
||||
case len(tokens) < 2:
|
||||
return tokens[0]
|
||||
case len(tokens) == 2:
|
||||
return strings.Replace(tokens[1], "╱UDP", "", 1)
|
||||
default:
|
||||
return tokens[1]
|
||||
}
|
||||
}
|
||||
|
||||
func extractContainer(p string) string {
|
||||
tokens := strings.Split(p, ":")
|
||||
if len(tokens) != 2 {
|
||||
return "n/a"
|
||||
}
|
||||
|
||||
co, _ := client.Namespaced(tokens[0])
|
||||
return co
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,26 +3,27 @@ package dialog
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/derailed/k9s/internal/config"
|
||||
"github.com/derailed/k9s/internal/dao"
|
||||
"github.com/derailed/k9s/internal/ui"
|
||||
"github.com/derailed/tview"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPortForwardDialog(t *testing.T) {
|
||||
func TestPortForwards(t *testing.T) {
|
||||
p := ui.NewPages()
|
||||
|
||||
okFunc := func(address, lport, cport string) {
|
||||
}
|
||||
ShowPortForward(p, "8080", okFunc)
|
||||
cbFunc := func(path, co string, t dao.Tunnel) {}
|
||||
ShowPortForwards(p, config.NewStyles(), "fred", []string{"8080"}, cbFunc)
|
||||
|
||||
d := p.GetPrimitive(portForwardKey).(*tview.ModalForm)
|
||||
assert.NotNil(t, d)
|
||||
|
||||
DismissPortForward(p)
|
||||
DismissPortForwards(p)
|
||||
assert.Nil(t, p.GetPrimitive(portForwardKey))
|
||||
}
|
||||
|
||||
func TestStripPort(t *testing.T) {
|
||||
func TestExtractPort(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
port, e string
|
||||
}{
|
||||
|
|
@ -40,7 +41,7 @@ func TestStripPort(t *testing.T) {
|
|||
for k := range uu {
|
||||
u := uu[k]
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.e, stripPort(u.port))
|
||||
assert.Equal(t, u.e, extractPort(u.port))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ func (b *Benchmark) viewBench(app *App, model ui.Tabular, gvr, path string) {
|
|||
return
|
||||
}
|
||||
|
||||
details := NewDetails(b.App(), "Benchmark", fileToSubject(path), false).Update(data)
|
||||
details := NewDetails(b.App(), "Results", fileToSubject(path), false).Update(data)
|
||||
if err := app.inject(details); err != nil {
|
||||
app.Flash().Err(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ func (c *Container) portFwdCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
return evt
|
||||
}
|
||||
|
||||
log.Debug().Msgf("CONTAINER-SEL %q", path)
|
||||
if _, ok := c.App().factory.ForwarderFor(fwFQN(c.GetTable().Path, path)); ok {
|
||||
c.App().Flash().Err(fmt.Errorf("A PortForward already exist on container %s", c.GetTable().Path))
|
||||
return nil
|
||||
|
|
@ -112,12 +113,24 @@ func (c *Container) portFwdCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
dialog.ShowPortForward(c.App().Content.Pages, c.preparePort(ports), c.portForward)
|
||||
log.Debug().Msgf("CONTAINER-PORTS %#v", ports)
|
||||
dialog.ShowPortForwards(c.App().Content.Pages, c.App().Styles, c.GetTable().Path, ports, c.portForward)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Container) portForward(path, co string, t dao.Tunnel) {
|
||||
pf := dao.NewPortForwarder(c.App().Conn())
|
||||
fw, err := pf.Start(path, co, t)
|
||||
if err != nil {
|
||||
c.App().Flash().Err(err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug().Msgf(">>> Starting port forward %q %#v", path, t)
|
||||
go runForward(c.App(), pf, fw)
|
||||
}
|
||||
|
||||
func (c *Container) isForwardable(path string) ([]string, bool) {
|
||||
state := c.GetTable().GetSelectedCell(3)
|
||||
if state != "Running" {
|
||||
|
|
@ -132,43 +145,15 @@ func (c *Container) isForwardable(path string) ([]string, bool) {
|
|||
return nil, false
|
||||
}
|
||||
|
||||
return ports, true
|
||||
}
|
||||
|
||||
func (c *Container) preparePort(pp []string) string {
|
||||
var port string
|
||||
for _, p := range pp {
|
||||
pp := make([]string, 0, len(ports))
|
||||
for _, p := range ports {
|
||||
if !isTCPPort(p) {
|
||||
continue
|
||||
}
|
||||
port = strings.TrimSpace(p)
|
||||
tokens := strings.Split(port, ":")
|
||||
if len(tokens) == 2 {
|
||||
port = tokens[1]
|
||||
}
|
||||
break
|
||||
}
|
||||
if port == "" {
|
||||
c.App().Flash().Warn("No valid TCP port found on this container. User will specify...")
|
||||
return "MY_TCP_PORT!"
|
||||
pp = append(pp, path+"/"+p)
|
||||
}
|
||||
|
||||
return port
|
||||
}
|
||||
|
||||
func (c *Container) portForward(address, lport, cport string) {
|
||||
co := c.GetTable().GetSelectedCell(0)
|
||||
pf := dao.NewPortForwarder(c.App().Conn())
|
||||
path := c.GetTable().GetSelectedItem()
|
||||
ports := []string{lport + ":" + cport}
|
||||
fw, err := pf.Start(path, co, address, ports)
|
||||
if err != nil {
|
||||
c.App().Flash().Err(err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug().Msgf(">>> Starting port forward %q %v", path, ports)
|
||||
go runForward(c.App(), pf, fw)
|
||||
return pp, true
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -178,7 +163,7 @@ func runForward(a *App, pf *dao.PortForwarder, f *portforward.PortForwarder) {
|
|||
a.QueueUpdateDraw(func() {
|
||||
a.factory.AddForwarder(pf)
|
||||
a.Flash().Infof("PortForward activated %s:%s", pf.Path(), pf.Ports()[0])
|
||||
dialog.DismissPortForward(a.Content.Pages)
|
||||
dialog.DismissPortForwards(a.Content.Pages)
|
||||
})
|
||||
|
||||
pf.SetActive(true)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/derailed/k9s/internal"
|
||||
"github.com/derailed/k9s/internal/client"
|
||||
|
|
@ -135,48 +136,51 @@ func (p *Pod) portFwdCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
return evt
|
||||
}
|
||||
|
||||
pp, err := fetchPodPorts(p.App().factory, path)
|
||||
if err != nil {
|
||||
if err := showFwdDialog(p.App(), path, p.portForward); err != nil {
|
||||
p.App().Flash().Err(err)
|
||||
return nil
|
||||
}
|
||||
ports := make([]string, 0, len(pp))
|
||||
for _, p := range pp {
|
||||
if p.Protocol == v1.ProtocolTCP {
|
||||
port := fmt.Sprintf("%s:%d", p.Name, p.ContainerPort)
|
||||
if p.Name == "" {
|
||||
port = fmt.Sprintf("%d", p.ContainerPort)
|
||||
}
|
||||
ports = append(ports, port)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ports) == 0 {
|
||||
p.App().Flash().Err(fmt.Errorf("no tcp ports found on %s", path))
|
||||
return nil
|
||||
}
|
||||
|
||||
dialog.ShowPortForwards(p.App().Content.Pages, p.App().Styles, path, ports, p.portForward)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Pod) portForward(path, address, lport, cport string) {
|
||||
func (p *Pod) portForward(path, co string, t dao.Tunnel) {
|
||||
pf := dao.NewPortForwarder(p.App().Conn())
|
||||
ports := []string{lport + ":" + cport}
|
||||
fw, err := pf.Start(path, "", address, ports)
|
||||
fw, err := pf.Start(path, co, t)
|
||||
if err != nil {
|
||||
p.App().Flash().Err(err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug().Msgf(">>> Starting port forward %q %v", path, ports)
|
||||
log.Debug().Msgf(">>> Starting port forward %q:%s %v", path, co, t)
|
||||
go runForward(p.App(), pf, fw)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
func showFwdDialog(a *App, path string, cb dialog.PortForwardFunc) error {
|
||||
mm, err := fetchPodPorts(a.factory, path)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
ports := make([]string, 0, len(mm))
|
||||
for co, pp := range mm {
|
||||
for _, p := range pp {
|
||||
if p.Protocol != v1.ProtocolTCP {
|
||||
continue
|
||||
}
|
||||
ports = append(ports, client.FQN(co, p.Name)+":"+strconv.Itoa(int(p.ContainerPort)))
|
||||
}
|
||||
}
|
||||
|
||||
if len(ports) == 0 {
|
||||
return fmt.Errorf("no tcp ports found on %s", path)
|
||||
}
|
||||
dialog.ShowPortForwards(a.Content.Pages, a.Styles, path, ports, cb)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func containerShellin(a *App, comp model.Component, path, co string) error {
|
||||
if co != "" {
|
||||
resumeShellIn(a, comp, path, co)
|
||||
|
|
@ -262,7 +266,7 @@ func fetchContainers(f *watch.Factory, path string, includeInit bool) ([]string,
|
|||
return nn, nil
|
||||
}
|
||||
|
||||
func fetchPodPorts(f *watch.Factory, path string) ([]v1.ContainerPort, error) {
|
||||
func fetchPodPorts(f *watch.Factory, path string) (map[string][]v1.ContainerPort, error) {
|
||||
log.Debug().Msgf("Fetching ports on pod %q", path)
|
||||
o, err := f.Get("v1/pods", path, false, labels.Everything())
|
||||
if err != nil {
|
||||
|
|
@ -275,9 +279,9 @@ func fetchPodPorts(f *watch.Factory, path string) ([]v1.ContainerPort, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
pp := make([]v1.ContainerPort, 0, len(pod.Spec.Containers))
|
||||
for _, c := range pod.Spec.Containers {
|
||||
pp = append(pp, c.Ports...)
|
||||
pp := make(map[string][]v1.ContainerPort)
|
||||
for _, co := range pod.Spec.Containers {
|
||||
pp[co.Name] = co.Ports
|
||||
}
|
||||
|
||||
return pp, nil
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package view
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/derailed/k9s/internal"
|
||||
|
|
@ -63,6 +65,8 @@ func (p *PortForward) showBenchCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
return nil
|
||||
}
|
||||
|
||||
var podNameRX = regexp.MustCompile(`\A(.+)\-(\w{10})\-(\w{5})\z`)
|
||||
|
||||
func (p *PortForward) toggleBenchCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if p.bench != nil {
|
||||
p.App().Status(ui.FlashErr, "Benchmark Canceled!")
|
||||
|
|
@ -71,18 +75,34 @@ func (p *PortForward) toggleBenchCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
return nil
|
||||
}
|
||||
|
||||
sel := p.GetTable().GetSelectedItem()
|
||||
if sel == "" {
|
||||
path := p.GetTable().GetSelectedItem()
|
||||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
tokens := strings.Split(path, ":")
|
||||
ns, po := client.Namespaced(tokens[0])
|
||||
sections := podNameRX.FindStringSubmatch(po)
|
||||
log.Debug().Msgf("SECTIONS %q::%q--%#v", ns, po, sections)
|
||||
if len(sections) >= 1 {
|
||||
po = sections[1]
|
||||
}
|
||||
key := client.FQN(ns, po) + ":" + tokens[1]
|
||||
|
||||
r, _ := p.GetTable().GetSelection()
|
||||
cfg := defaultConfig()
|
||||
if b, ok := p.App().Bench.Benchmarks.Containers[sel]; ok {
|
||||
if defaults := p.App().Bench.Benchmarks.Defaults; !defaults.Empty() {
|
||||
cfg.C, cfg.N = defaults.C, defaults.N
|
||||
}
|
||||
|
||||
log.Debug().Msgf("CUST-CFG %q -- %#v", path, key)
|
||||
if b, ok := p.App().Bench.Benchmarks.Containers[key]; ok {
|
||||
log.Debug().Msgf("FOUND CUST BENCH_CFG!")
|
||||
cfg = b
|
||||
}
|
||||
cfg.Name = sel
|
||||
cfg.Name = path
|
||||
|
||||
log.Debug().Msgf("BenchCFG %q::%#v", path, cfg)
|
||||
|
||||
r, _ := p.GetTable().GetSelection()
|
||||
base := ui.TrimCell(p.GetTable().SelectTable, r, 4)
|
||||
var err error
|
||||
if p.bench, err = perf.NewBenchmark(base, p.App().version, cfg); err != nil {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/derailed/k9s/internal/dao"
|
||||
"github.com/derailed/k9s/internal/perf"
|
||||
"github.com/derailed/k9s/internal/ui"
|
||||
"github.com/derailed/k9s/internal/ui/dialog"
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/rs/zerolog/log"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
|
|
@ -87,42 +86,22 @@ func (s *Service) portFwdCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
return nil
|
||||
}
|
||||
|
||||
pp, err := fetchPodPorts(s.App().factory, pod)
|
||||
if err != nil {
|
||||
if err := showFwdDialog(s.App(), pod, s.portForward); err != nil {
|
||||
s.App().Flash().Err(err)
|
||||
return nil
|
||||
}
|
||||
ports := make([]string, 0, len(pp))
|
||||
for _, p := range pp {
|
||||
if p.Protocol == v1.ProtocolTCP {
|
||||
port := fmt.Sprintf("%s:%d", p.Name, p.ContainerPort)
|
||||
if p.Name == "" {
|
||||
port = fmt.Sprintf("%d", p.ContainerPort)
|
||||
}
|
||||
ports = append(ports, port)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ports) == 0 {
|
||||
s.App().Flash().Err(fmt.Errorf("no tcp ports found on %s", path))
|
||||
return nil
|
||||
}
|
||||
|
||||
dialog.ShowPortForwards(s.App().Content.Pages, s.App().Styles, pod, ports, s.portForward)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) portForward(path, address, lport, cport string) {
|
||||
func (s *Service) portForward(path, co string, t dao.Tunnel) {
|
||||
pf := dao.NewPortForwarder(s.App().Conn())
|
||||
ports := []string{lport + ":" + cport}
|
||||
fw, err := pf.Start(path, "", address, ports)
|
||||
fw, err := pf.Start(path, co, t)
|
||||
if err != nil {
|
||||
s.App().Flash().Err(err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug().Msgf(">>> Starting port forward %q %v", path, ports)
|
||||
log.Debug().Msgf(">>> Starting port forward %q %#v", path, t)
|
||||
go runForward(s.App(), pf, fw)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"k8s.io/client-go/tools/portforward"
|
||||
)
|
||||
|
||||
// Forwarder represents a port forwarder.
|
||||
type Forwarder interface {
|
||||
// Start initializes a port forward.
|
||||
Start(path, co, address string, ports []string) (*portforward.PortForwarder, error)
|
||||
// BOZO!!
|
||||
// // Start initializes a port forward.
|
||||
// Start(path, co, string, t dao.Tunnel) (*portforward.PortForwarder, error)
|
||||
|
||||
// Stop terminates a port forward.
|
||||
Stop()
|
||||
|
|
|
|||
Loading…
Reference in New Issue