Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/dev/preview/previewctl/pkg/k8s/pforward.go
2501 views
1
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package k8s
6
7
import (
8
"bytes"
9
"context"
10
"fmt"
11
"net/http"
12
"net/url"
13
14
"github.com/cockroachdb/errors"
15
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
16
"k8s.io/client-go/tools/portforward"
17
"k8s.io/client-go/transport/spdy"
18
)
19
20
type PortForwardOpts struct {
21
Name string
22
Namespace string
23
Ports []string
24
ReadyChan, StopChan chan struct{}
25
ErrChan chan error
26
}
27
28
func (c *Config) PortForward(ctx context.Context, opts PortForwardOpts) error {
29
roundTripper, upgrader, err := spdy.RoundTripperFor(c.config)
30
if err != nil {
31
panic(err)
32
}
33
34
path := fmt.Sprintf("/api/v1/namespaces/%s/pods/%s/portforward", opts.Namespace, opts.Name)
35
u, err := url.Parse(c.config.Host)
36
if err != nil {
37
return errors.Wrap(err, "couldn't parse k8s host url")
38
}
39
u.Path = path
40
u.Scheme = "https"
41
42
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: roundTripper}, http.MethodPost, u)
43
44
out, errOut := new(bytes.Buffer), new(bytes.Buffer)
45
forwarder, err := portforward.New(dialer, opts.Ports, opts.StopChan, opts.ReadyChan, out, errOut)
46
if err != nil {
47
return err
48
}
49
50
go func() {
51
for range opts.ReadyChan { // Kubernetes will close this channel when it has something to tell us.
52
}
53
if len(errOut.String()) != 0 {
54
opts.ErrChan <- errors.New(errOut.String())
55
} else if len(out.String()) != 0 {
56
c.logger.Debug(out.String())
57
}
58
}()
59
60
if err = forwarder.ForwardPorts(); err != nil { // Locks until stopChan is closed.
61
return err
62
}
63
64
return nil
65
}
66
67
func (c *Config) GetSVCTargets(ctx context.Context, name, namespace string) ([]string, error) {
68
svc, err := c.CoreClient.CoreV1().Services(namespace).Get(ctx, name, metav1.GetOptions{})
69
if err != nil {
70
return nil, err
71
}
72
73
pods, err := c.CoreClient.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{
74
LabelSelector: metav1.FormatLabelSelector(&metav1.LabelSelector{
75
MatchLabels: svc.Spec.Selector,
76
}),
77
})
78
79
podList := make([]string, 0, len(pods.Items))
80
for _, p := range pods.Items {
81
podList = append(podList, p.Name)
82
}
83
84
return podList, err
85
}
86
87