Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/dev/gpctl/cmd/workspaces.go
2498 views
1
// Copyright (c) 2020 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 cmd
6
7
import (
8
"context"
9
"crypto/tls"
10
"crypto/x509"
11
"fmt"
12
"io/ioutil"
13
"path/filepath"
14
"strings"
15
16
"github.com/spf13/cobra"
17
"golang.org/x/xerrors"
18
"google.golang.org/grpc"
19
"google.golang.org/grpc/credentials"
20
"google.golang.org/grpc/credentials/insecure"
21
"k8s.io/client-go/kubernetes"
22
23
"github.com/gitpod-io/gitpod/gpctl/pkg/util"
24
"github.com/gitpod-io/gitpod/ws-manager/api"
25
)
26
27
// workspacesCmd represents the client command
28
var workspacesCmd = &cobra.Command{
29
Use: "workspaces",
30
Short: "Controls and inspects workspaces in the Gitpod installation",
31
Args: cobra.ExactArgs(1),
32
}
33
34
func init() {
35
workspacesCmd.PersistentFlags().StringP("tls-path", "t", "", "TLS certificate when connecting to a secured gRPC endpoint")
36
workspacesCmd.PersistentFlags().Bool("tls-from-secret", true, "get TLS certificate from Kubernetes secret")
37
workspacesCmd.PersistentFlags().StringP("pod", "s", "ws-manager", "Pod label for the port forwarding")
38
workspacesCmd.PersistentFlags().StringP("port", "p", "8080", "remote port")
39
workspacesCmd.PersistentFlags().String("host", "", "talk to a ws-manager host directly rather than to a pod - ignores tls-from-secret")
40
41
rootCmd.AddCommand(workspacesCmd)
42
}
43
44
func getWorkspacesClient(ctx context.Context) (*grpc.ClientConn, api.WorkspaceManagerClient, error) {
45
var addr string
46
secopt := grpc.WithTransportCredentials(insecure.NewCredentials())
47
if host, _ := workspacesCmd.PersistentFlags().GetString("host"); host == "" {
48
cfg, namespace, err := getKubeconfig()
49
if err != nil {
50
return nil, nil, err
51
}
52
clientSet, err := kubernetes.NewForConfig(cfg)
53
if err != nil {
54
return nil, nil, err
55
}
56
57
podLabel, err := workspacesCmd.Flags().GetString("pod")
58
if err != nil {
59
return nil, nil, err
60
}
61
62
remotePort, err := workspacesCmd.Flags().GetString("port")
63
if err != nil {
64
return nil, nil, err
65
}
66
67
port := fmt.Sprintf("20202:%s", remotePort)
68
podName, err := util.FindAnyPodForComponent(clientSet, namespace, podLabel)
69
if err != nil {
70
return nil, nil, err
71
}
72
readychan, errchan := util.ForwardPort(ctx, cfg, namespace, podName, port)
73
select {
74
case <-readychan:
75
case err := <-errchan:
76
return nil, nil, err
77
case <-ctx.Done():
78
return nil, nil, ctx.Err()
79
}
80
81
if certFromSecret, _ := workspacesCmd.Flags().GetBool("tls-from-secret"); certFromSecret {
82
certPool, err := util.CertPoolFromSecret(clientSet, namespace, "ws-manager-mk2-tls", []string{"ca.crt"})
83
if err != nil {
84
return nil, nil, xerrors.Errorf("could not load ca cert: %w", err)
85
}
86
cert, err := util.CertFromSecret(clientSet, namespace, "ws-manager-mk2-client-tls", "tls.crt", "tls.key")
87
if err != nil {
88
return nil, nil, xerrors.Errorf("could not load tls cert: %w", err)
89
}
90
creds := credentials.NewTLS(&tls.Config{
91
Certificates: []tls.Certificate{cert},
92
RootCAs: certPool,
93
ServerName: "ws-manager",
94
})
95
96
secopt = grpc.WithTransportCredentials(creds)
97
}
98
99
addr = "localhost:20202"
100
} else {
101
port, _ := workspacesCmd.PersistentFlags().GetString("port")
102
addr = fmt.Sprintf("%s:%s", host, port)
103
}
104
105
if fn, _ := workspacesCmd.Flags().GetString("tls-path"); fn != "" {
106
crt, err := ioutil.ReadFile(filepath.Join(fn, "tls.crt"))
107
if err != nil {
108
return nil, nil, err
109
}
110
key, err := ioutil.ReadFile(filepath.Join(fn, "tls.key"))
111
if err != nil {
112
return nil, nil, err
113
}
114
cert, err := tls.X509KeyPair(crt, key)
115
if err != nil {
116
return nil, nil, err
117
}
118
119
ca, err := ioutil.ReadFile(filepath.Join(fn, "ca.crt"))
120
if err != nil {
121
return nil, nil, err
122
}
123
certPool := x509.NewCertPool()
124
certPool.AppendCertsFromPEM(ca)
125
126
creds := credentials.NewTLS(&tls.Config{
127
Certificates: []tls.Certificate{cert},
128
RootCAs: certPool,
129
ServerName: "ws-manager",
130
})
131
if err != nil {
132
return nil, nil, xerrors.Errorf("could not load tls cert: %w", err)
133
}
134
135
secopt = grpc.WithTransportCredentials(creds)
136
}
137
conn, err := grpc.Dial(addr, secopt, util.WithClientUnaryInterceptor())
138
if err != nil {
139
return nil, nil, err
140
}
141
return conn, api.NewWorkspaceManagerClient(conn), nil
142
}
143
144
func getStatusByURL(ctx context.Context, client api.WorkspaceManagerClient, url string) (*api.WorkspaceStatus, error) {
145
wsresp, err := client.GetWorkspaces(ctx, &api.GetWorkspacesRequest{})
146
if err != nil {
147
return nil, err
148
}
149
150
for _, ws := range wsresp.GetStatus() {
151
if ws.Spec.Url == url || strings.TrimPrefix(ws.Spec.Url, "https://") == url || strings.TrimPrefix(ws.Spec.Url, "http://") == url {
152
return ws, nil
153
}
154
}
155
156
return nil, xerrors.Errorf("no workspace with URL \"%s\" found", url)
157
}
158
159