mirror of
https://github.com/gitpod-io/gitpod.git
synced 2025-12-08 17:36:30 +00:00
The function grpc.WithInsecure() is deprecated, use grpc.WithTransportCredentials(insecure.NewCredentials()) instead. Signed-off-by: JenTing Hsiao <hsiaoairplane@gmail.com>
158 lines
4.7 KiB
Go
158 lines
4.7 KiB
Go
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.
|
|
// Licensed under the GNU Affero General Public License (AGPL).
|
|
// See License-AGPL.txt in the project root for license information.
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
"golang.org/x/xerrors"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
"k8s.io/client-go/kubernetes"
|
|
|
|
"github.com/gitpod-io/gitpod/gpctl/pkg/util"
|
|
"github.com/gitpod-io/gitpod/ws-manager/api"
|
|
)
|
|
|
|
// workspacesCmd represents the client command
|
|
var workspacesCmd = &cobra.Command{
|
|
Use: "workspaces",
|
|
Short: "Controls and inspects workspaces in the Gitpod installation",
|
|
Args: cobra.ExactArgs(1),
|
|
}
|
|
|
|
func init() {
|
|
workspacesCmd.PersistentFlags().StringP("tls-path", "t", "", "TLS certificate when connecting to a secured gRPC endpoint")
|
|
workspacesCmd.PersistentFlags().Bool("tls-from-secret", true, "get TLS certificate from Kubernetes secret")
|
|
workspacesCmd.PersistentFlags().StringP("pod", "s", "ws-manager", "Pod label for the port forwarding")
|
|
workspacesCmd.PersistentFlags().StringP("port", "p", "8080", "remote port")
|
|
workspacesCmd.PersistentFlags().String("host", "", "talk to a ws-manager host directly rather than to a pod - ignores tls-from-secret")
|
|
|
|
rootCmd.AddCommand(workspacesCmd)
|
|
}
|
|
|
|
func getWorkspacesClient(ctx context.Context) (*grpc.ClientConn, api.WorkspaceManagerClient, error) {
|
|
var addr string
|
|
secopt := grpc.WithTransportCredentials(insecure.NewCredentials())
|
|
if host, _ := workspacesCmd.PersistentFlags().GetString("host"); host == "" {
|
|
cfg, namespace, err := getKubeconfig()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
clientSet, err := kubernetes.NewForConfig(cfg)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
podLabel, err := workspacesCmd.Flags().GetString("pod")
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
remotePort, err := workspacesCmd.Flags().GetString("port")
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
port := fmt.Sprintf("20202:%s", remotePort)
|
|
podName, err := util.FindAnyPodForComponent(clientSet, namespace, podLabel)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
readychan, errchan := util.ForwardPort(ctx, cfg, namespace, podName, port)
|
|
select {
|
|
case <-readychan:
|
|
case err := <-errchan:
|
|
return nil, nil, err
|
|
case <-ctx.Done():
|
|
return nil, nil, ctx.Err()
|
|
}
|
|
|
|
if certFromSecret, _ := workspacesCmd.Flags().GetBool("tls-from-secret"); certFromSecret {
|
|
certPool, err := util.CertPoolFromSecret(clientSet, namespace, "ws-manager-tls", []string{"ca.crt"})
|
|
if err != nil {
|
|
return nil, nil, xerrors.Errorf("could not load ca cert: %w", err)
|
|
}
|
|
cert, err := util.CertFromSecret(clientSet, namespace, "ws-manager-client-tls", "tls.crt", "tls.key")
|
|
if err != nil {
|
|
return nil, nil, xerrors.Errorf("could not load tls cert: %w", err)
|
|
}
|
|
creds := credentials.NewTLS(&tls.Config{
|
|
Certificates: []tls.Certificate{cert},
|
|
RootCAs: certPool,
|
|
ServerName: "ws-manager",
|
|
})
|
|
|
|
secopt = grpc.WithTransportCredentials(creds)
|
|
}
|
|
|
|
addr = "localhost:20202"
|
|
} else {
|
|
port, _ := workspacesCmd.PersistentFlags().GetString("port")
|
|
addr = fmt.Sprintf("%s:%s", host, port)
|
|
}
|
|
|
|
if fn, _ := workspacesCmd.Flags().GetString("tls-path"); fn != "" {
|
|
crt, err := ioutil.ReadFile(filepath.Join(fn, "tls.crt"))
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
key, err := ioutil.ReadFile(filepath.Join(fn, "tls.key"))
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
cert, err := tls.X509KeyPair(crt, key)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
ca, err := ioutil.ReadFile(filepath.Join(fn, "ca.crt"))
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
certPool := x509.NewCertPool()
|
|
certPool.AppendCertsFromPEM(ca)
|
|
|
|
creds := credentials.NewTLS(&tls.Config{
|
|
Certificates: []tls.Certificate{cert},
|
|
RootCAs: certPool,
|
|
ServerName: "ws-manager",
|
|
})
|
|
if err != nil {
|
|
return nil, nil, xerrors.Errorf("could not load tls cert: %w", err)
|
|
}
|
|
|
|
secopt = grpc.WithTransportCredentials(creds)
|
|
}
|
|
conn, err := grpc.Dial(addr, secopt, util.WithClientUnaryInterceptor())
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return conn, api.NewWorkspaceManagerClient(conn), nil
|
|
}
|
|
|
|
func getStatusByURL(ctx context.Context, client api.WorkspaceManagerClient, url string) (*api.WorkspaceStatus, error) {
|
|
wsresp, err := client.GetWorkspaces(ctx, &api.GetWorkspacesRequest{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, ws := range wsresp.GetStatus() {
|
|
if ws.Spec.Url == url || strings.TrimPrefix(ws.Spec.Url, "https://") == url || strings.TrimPrefix(ws.Spec.Url, "http://") == url {
|
|
return ws, nil
|
|
}
|
|
}
|
|
|
|
return nil, xerrors.Errorf("no workspace with URL \"%s\" found", url)
|
|
}
|