Path: blob/main/dev/preview/previewctl/cmd/install_context.go
3602 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 cmd56import (7"context"8"fmt"9"io/fs"10"os"11"time"1213"github.com/cockroachdb/errors"14"github.com/sirupsen/logrus"15"github.com/spf13/cobra"16"k8s.io/client-go/util/homedir"1718"github.com/gitpod-io/gitpod/previewctl/pkg/preview"19)2021type installContextCmdOpts struct {22logger *logrus.Logger2324watch bool25timeout time.Duration26kubeConfigSavePath string27sshPrivateKeyPath string28}2930func newInstallContextCmd(logger *logrus.Logger) *cobra.Command {31ctx := context.Background()3233opts := installContextCmdOpts{34logger: logger,35}3637// Used to ensure that we only install contexts38var lastSuccessfulPreviewEnvironment *preview.Config = nil3940install := func(retry bool, timeout time.Duration) error {41name, err := preview.GetName(branch)42if err != nil {43logger.WithError(err).Error("failed to get preview name")44return err45}4647if hasAccess(ctx, logger, name) {48opts.logger.Debugf("Access to [%s] already configured and connections can be established", name)49return nil50}5152p, err := preview.New(branch, logger)53if err != nil {54logger.WithError(err).Error("failed to create preview config")55return err56}5758if lastSuccessfulPreviewEnvironment != nil && lastSuccessfulPreviewEnvironment.Same(p) {59logger.Infof("The preview envrionment hasn't changed")60return nil61}6263err = p.InstallContext(ctx, &preview.InstallCtxOpts{64Retry: retry,65RetryTimeout: opts.timeout,66KubeSavePath: opts.kubeConfigSavePath,67SSHPrivateKeyPath: opts.sshPrivateKeyPath,68})6970if err != nil {71logger.WithError(err).Error("failed to install context")72} else {73lastSuccessfulPreviewEnvironment = p74}7576return err77}7879cmd := &cobra.Command{80Use: "install-context",81Short: "Installs the kubectl context of a preview environment.",82PreRunE: func(cmd *cobra.Command, args []string) error {83if _, err := os.Stat(opts.sshPrivateKeyPath); errors.Is(err, fs.ErrNotExist) {84err := preview.GenerateSSHPrivateKey(opts.sshPrivateKeyPath)85if err != nil {86return err87}88}8990opts.kubeConfigSavePath = getKubeConfigPath()91return nil92},93RunE: func(cmd *cobra.Command, args []string) error {94if opts.watch {95for range time.Tick(15 * time.Second) {96// We're using a short timeout here to handle the scenario where someone switches97// to a branch that doesn't have a preview environment. In that case the default98// timeout would mean that we would block for 10 minutes, potentially missing99// if the user changes to a new branch that does that a preview.100err := install(true, 30*time.Second)101if err != nil {102logger.WithFields(logrus.Fields{"err": err}).Info("Failed to install context. Trying again soon.")103}104}105}106107return install(true, opts.timeout)108},109}110111cmd.Flags().BoolVar(&opts.watch, "watch", false, "If watch is enabled, previewctl will keep trying to install the kube-context every 15 seconds, even when successful.")112cmd.Flags().DurationVarP(&opts.timeout, "timeout", "t", 10*time.Minute, "Timeout before considering the installation failed. It will retry installing the context until successful or the timeout is reached")113cmd.PersistentFlags().StringVar(&opts.sshPrivateKeyPath, "private-key-path", fmt.Sprintf("%s/.ssh/vm_ed25519", homedir.HomeDir()), "path to the private key used to authenticate with the VM")114115return cmd116}117118119