Path: blob/main/dev/preview/previewctl/pkg/k8s/pforward.go
2501 views
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package k8s56import (7"bytes"8"context"9"fmt"10"net/http"11"net/url"1213"github.com/cockroachdb/errors"14metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"15"k8s.io/client-go/tools/portforward"16"k8s.io/client-go/transport/spdy"17)1819type PortForwardOpts struct {20Name string21Namespace string22Ports []string23ReadyChan, StopChan chan struct{}24ErrChan chan error25}2627func (c *Config) PortForward(ctx context.Context, opts PortForwardOpts) error {28roundTripper, upgrader, err := spdy.RoundTripperFor(c.config)29if err != nil {30panic(err)31}3233path := fmt.Sprintf("/api/v1/namespaces/%s/pods/%s/portforward", opts.Namespace, opts.Name)34u, err := url.Parse(c.config.Host)35if err != nil {36return errors.Wrap(err, "couldn't parse k8s host url")37}38u.Path = path39u.Scheme = "https"4041dialer := spdy.NewDialer(upgrader, &http.Client{Transport: roundTripper}, http.MethodPost, u)4243out, errOut := new(bytes.Buffer), new(bytes.Buffer)44forwarder, err := portforward.New(dialer, opts.Ports, opts.StopChan, opts.ReadyChan, out, errOut)45if err != nil {46return err47}4849go func() {50for range opts.ReadyChan { // Kubernetes will close this channel when it has something to tell us.51}52if len(errOut.String()) != 0 {53opts.ErrChan <- errors.New(errOut.String())54} else if len(out.String()) != 0 {55c.logger.Debug(out.String())56}57}()5859if err = forwarder.ForwardPorts(); err != nil { // Locks until stopChan is closed.60return err61}6263return nil64}6566func (c *Config) GetSVCTargets(ctx context.Context, name, namespace string) ([]string, error) {67svc, err := c.CoreClient.CoreV1().Services(namespace).Get(ctx, name, metav1.GetOptions{})68if err != nil {69return nil, err70}7172pods, err := c.CoreClient.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{73LabelSelector: metav1.FormatLabelSelector(&metav1.LabelSelector{74MatchLabels: svc.Spec.Selector,75}),76})7778podList := make([]string, 0, len(pods.Items))79for _, p := range pods.Items {80podList = append(podList, p.Name)81}8283return podList, err84}858687