diff --git a/cmd/localizer/localizer.go b/cmd/localizer/localizer.go index c792ea9..710f9d5 100644 --- a/cmd/localizer/localizer.go +++ b/cmd/localizer/localizer.go @@ -24,7 +24,6 @@ import ( "strings" "syscall" - "github.com/davecgh/go-spew/spew" "github.com/jaredallard/localizer/internal/expose" "github.com/jaredallard/localizer/internal/kube" "github.com/jaredallard/localizer/internal/proxier" @@ -102,9 +101,7 @@ func main() { //nolint:funlen,gocyclo // note: port 50 is chosen as least likely to collide with anything // we may want to look into randomizing it in the future - port := 50 - tls := false - return errors.Wrap(server.RunServer(ctx, &port, &tls, nil, nil), "server failed") + return errors.Wrap(server.RunServer(ctx, server.WithPort(50), server.WithLogger(log)), "server failed") }, }, { @@ -113,11 +110,8 @@ func main() { //nolint:funlen,gocyclo Usage: "expose ", Flags: []cli.Flag{ &cli.StringSliceFlag{ - // Note: We should make this true override support - // right now this will only work for a targetPort -> another targetPort - // and not the noted localPort Name: "map", - Usage: "Map a service's target port to another port, --map targetPortName:remotePort", + Usage: "Map a local port to a remote port, i.e --map 80:8080 will bind what is normally :8080 to :80 locally", }, }, Action: func(c *cli.Context) error { @@ -146,59 +140,40 @@ func main() { //nolint:funlen,gocyclo return errors.Wrap(err, "failed to resolve service ports") } - portOverrides := make(map[string]uint) + log.Debugf("map %v", c.StringSlice("map")) for _, portOverride := range c.StringSlice("map") { spl := strings.Split(portOverride, ":") if len(spl) != 2 { return fmt.Errorf("invalid port map '%s', expected 'local:remote'", portOverride) } - local := spl[0] - rem := spl[1] - - remote, err := strconv.ParseUint(rem, 10, 0) + local, err := strconv.ParseUint(spl[0], 10, 0) if err != nil { return errors.Wrapf(err, "failed to parse port map '%s'", portOverride) } - portOverrides[local] = uint(remote) - } - - // if we couldn't find endpoints, check if we mapped the port, if not - // then prompt the user - if !exists { - log.Info("Failed to resolve ports due to endpoints not exists, please use --map or awnser the below prompt(s)") - for _, sp := range servicePorts { - if sp.TargetPort.Type != intstr.String { - continue - } - - v, err := getUserInput(fmt.Sprintf("Please enter a port to map '%s' to: ", sp.TargetPort.StrVal)) - if err != nil { - return errors.Wrap(err, "failed to get user input") - } + rem, err := strconv.ParseUint(spl[1], 10, 0) + if err != nil { + return errors.Wrapf(err, "failed to parse port map '%s'", portOverride) + } - remote, err := strconv.ParseUint(v, 10, 0) - if err != nil { - return errors.Wrapf(err, "failed to parse port map '%s'", v) + // TODO: this is slow... + for i, sp := range servicePorts { + log.Debugf("checking if we need to map %v, using %d:%d", sp.TargetPort, rem, local) + if uint(servicePorts[i].TargetPort.IntVal) == uint(rem) { + servicePorts[i].MappedPort = uint(local) } - - portOverrides[strconv.Itoa(int(sp.Port))] = uint(remote) } } - mappedServicePorts := make([]kube.ResolvedServicePort, len(servicePorts)) - for i, sp := range servicePorts { - mappedPort, ok := portOverrides[strconv.Itoa(int(sp.Port))] - if ok { - sp.Port = int32(mappedPort) - sp.TargetPort = intstr.FromInt(int(mappedPort)) + // if we couldn't find endpoints, then we fall back to binding whatever the + // public port of the service is + if !exists { + for i, sp := range servicePorts { + servicePorts[i].TargetPort = intstr.FromInt(int(sp.Port)) } - mappedServicePorts[i] = sp } - log.WithField("portoverride", "").Debug(spew.Sdump(portOverrides)) - // if there's no endpoints if !exists { log.Debug("service has no endpoints") @@ -209,7 +184,7 @@ func main() { //nolint:funlen,gocyclo return err } - p, err := e.Expose(ctx, mappedServicePorts, serviceSplit[0], serviceSplit[1]) + p, err := e.Expose(ctx, servicePorts, serviceSplit[0], serviceSplit[1]) if err != nil { return errors.Wrap(err, "failed to create reverse tunnel") } diff --git a/go.mod b/go.mod index 38fe7f2..e1ea6d1 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,6 @@ require ( ) replace ( - github.com/omrikiei/ktunnel => github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926055947-16b943a26404 + github.com/omrikiei/ktunnel => github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926161618-3698a12ca694 k8s.io/client-go => github.com/jaredallard/client-go v0.0.0-20200919203213-e55c7f2b41ab ) diff --git a/go.sum b/go.sum index 7679942..a39bca4 100644 --- a/go.sum +++ b/go.sum @@ -265,6 +265,14 @@ github.com/jaredallard/client-go v0.0.0-20200919203213-e55c7f2b41ab h1:POcVSGYlT github.com/jaredallard/client-go v0.0.0-20200919203213-e55c7f2b41ab/go.mod h1:SnLtmp6F+NMdYHYqnSKVWW81iA2wv5QfXXncW8aWuKc= github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926055947-16b943a26404 h1:COTI4mawAmM5OLPssFnVCIvwaN92mRubN7MJLMu/XDk= github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926055947-16b943a26404/go.mod h1:8tqZSClJ9vDe6gIx/XSrLPZ4PwZiW9X16Y2ujbm3NgA= +github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926160510-2fbf336cf727 h1:/LSsu67oZN8a+D57pMalTi7mdfa4f1izzTZUSpt3fNw= +github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926160510-2fbf336cf727/go.mod h1:8tqZSClJ9vDe6gIx/XSrLPZ4PwZiW9X16Y2ujbm3NgA= +github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926161115-31da13c84f9f h1:P22nFDZslbjnSgE60eICyN7cfTO/QXlyeALTMmXOuuc= +github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926161115-31da13c84f9f/go.mod h1:8tqZSClJ9vDe6gIx/XSrLPZ4PwZiW9X16Y2ujbm3NgA= +github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926161423-12ee824c0786 h1:3MKb2EvPoviSW9jtyGH1UdpLAvb+g/M2KCrsH3qRYJc= +github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926161423-12ee824c0786/go.mod h1:8tqZSClJ9vDe6gIx/XSrLPZ4PwZiW9X16Y2ujbm3NgA= +github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926161618-3698a12ca694 h1:F48BX7xXpcF30lOaVRxpRE5bNvi8dT9NpLjOqj+ECto= +github.com/jaredallard/ktunnel v1.2.8-beta.0.20200926161618-3698a12ca694/go.mod h1:8tqZSClJ9vDe6gIx/XSrLPZ4PwZiW9X16Y2ujbm3NgA= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= diff --git a/internal/expose/port.go b/internal/expose/port.go index 2ad11bc..632c102 100644 --- a/internal/expose/port.go +++ b/internal/expose/port.go @@ -128,6 +128,13 @@ func (p *ServiceForward) createServerPodAndTransport(ctx context.Context) (clean return func() {}, 0, errors.Wrap(err, "failed to create pod") } + cleanupFn = func() { + p.c.log.Debug("cleaning up pod") + // cleanup the pod + //nolint:errcheck + p.c.k.CoreV1().Pods(p.Namespace).Delete(context.Background(), po.Name, metav1.DeleteOptions{}) + } + p.c.log.Infof("created pod %s", po.ObjectMeta.Name) p.c.log.Info("waiting for remote pod to be ready ...") @@ -154,6 +161,7 @@ loop: } } case <-ctx.Done(): + cleanupFn() return func() {}, 0, ctx.Err() } } @@ -177,6 +185,7 @@ loop: select { case <-fw.Ready: case <-ctx.Done(): + cleanupFn() return func() {}, 0, ctx.Err() } @@ -195,12 +204,7 @@ loop: return func() {}, 0, fmt.Errorf("failed to determine the generated underlying transport port") } - return func() { - p.c.log.Debug("cleaning up pod") - // cleanup the pod - //nolint:errcheck - p.c.k.CoreV1().Pods(p.Namespace).Delete(context.Background(), po.Name, metav1.DeleteOptions{}) - }, port, nil + return cleanupFn, port, nil } // Start starts forwarding a service @@ -208,7 +212,7 @@ func (p *ServiceForward) Start(ctx context.Context) error { ports := make([]string, len(p.Ports)) for i, port := range p.Ports { prt := int(port.TargetPort.IntVal) - ports[i] = fmt.Sprintf("%d:%d", prt, prt) + ports[i] = fmt.Sprintf("%d:%d", port.MappedPort, prt) } cleanupFn, localPort, err := p.createServerPodAndTransport(ctx) @@ -217,10 +221,6 @@ func (p *ServiceForward) Start(ctx context.Context) error { } defer cleanupFn() - // TODO(jaredallard): We likely need reconnect logic here - host := "127.0.0.1" - tls := false - // scale down the other resources that powered this service for _, o := range p.objects { p.c.log.Infof("scaling %s from %d -> 0", o.GetKey(), o.Replicas) @@ -239,7 +239,12 @@ func (p *ServiceForward) Start(ctx context.Context) error { }() p.c.log.Debug("creating ktunnel client") - err = client.RunClient(ctx, &host, &localPort, "tcp", &tls, nil, nil, ports) + err = client.RunClient( + ctx, + client.WithServer("127.0.0.1", localPort), + client.WithTunnels("tcp", ports...), + client.WithLogger(p.c.log), + ) if err != nil { return errors.Wrap(err, "failed to create grpc transport") } diff --git a/internal/kube/client.go b/internal/kube/client.go index 5e5b204..7fea58b 100644 --- a/internal/kube/client.go +++ b/internal/kube/client.go @@ -91,6 +91,10 @@ type ResolvedServicePort struct { // OriginalTargetPort is set if the ServicePort // was modified OriginalTargetPort string + + // MappedPort is the locally mapped port that this should have + // defaults to the targetPort + MappedPort uint } // ResolveServicePorts converts named ports into their true @@ -105,6 +109,7 @@ func ResolveServicePorts(ctx context.Context, k kubernetes.Interface, servicePorts[i] = ResolvedServicePort{ sp, "", + uint(sp.Port), } } return servicePorts, false, nil @@ -136,6 +141,7 @@ func ResolveServicePorts(ctx context.Context, k kubernetes.Interface, servicePorts[i] = ResolvedServicePort{ p, original, + uint(p.TargetPort.IntVal), } }