Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/dev/preview/previewctl/cmd/install_context.go
3602 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 cmd
6
7
import (
8
"context"
9
"fmt"
10
"io/fs"
11
"os"
12
"time"
13
14
"github.com/cockroachdb/errors"
15
"github.com/sirupsen/logrus"
16
"github.com/spf13/cobra"
17
"k8s.io/client-go/util/homedir"
18
19
"github.com/gitpod-io/gitpod/previewctl/pkg/preview"
20
)
21
22
type installContextCmdOpts struct {
23
logger *logrus.Logger
24
25
watch bool
26
timeout time.Duration
27
kubeConfigSavePath string
28
sshPrivateKeyPath string
29
}
30
31
func newInstallContextCmd(logger *logrus.Logger) *cobra.Command {
32
ctx := context.Background()
33
34
opts := installContextCmdOpts{
35
logger: logger,
36
}
37
38
// Used to ensure that we only install contexts
39
var lastSuccessfulPreviewEnvironment *preview.Config = nil
40
41
install := func(retry bool, timeout time.Duration) error {
42
name, err := preview.GetName(branch)
43
if err != nil {
44
logger.WithError(err).Error("failed to get preview name")
45
return err
46
}
47
48
if hasAccess(ctx, logger, name) {
49
opts.logger.Debugf("Access to [%s] already configured and connections can be established", name)
50
return nil
51
}
52
53
p, err := preview.New(branch, logger)
54
if err != nil {
55
logger.WithError(err).Error("failed to create preview config")
56
return err
57
}
58
59
if lastSuccessfulPreviewEnvironment != nil && lastSuccessfulPreviewEnvironment.Same(p) {
60
logger.Infof("The preview envrionment hasn't changed")
61
return nil
62
}
63
64
err = p.InstallContext(ctx, &preview.InstallCtxOpts{
65
Retry: retry,
66
RetryTimeout: opts.timeout,
67
KubeSavePath: opts.kubeConfigSavePath,
68
SSHPrivateKeyPath: opts.sshPrivateKeyPath,
69
})
70
71
if err != nil {
72
logger.WithError(err).Error("failed to install context")
73
} else {
74
lastSuccessfulPreviewEnvironment = p
75
}
76
77
return err
78
}
79
80
cmd := &cobra.Command{
81
Use: "install-context",
82
Short: "Installs the kubectl context of a preview environment.",
83
PreRunE: func(cmd *cobra.Command, args []string) error {
84
if _, err := os.Stat(opts.sshPrivateKeyPath); errors.Is(err, fs.ErrNotExist) {
85
err := preview.GenerateSSHPrivateKey(opts.sshPrivateKeyPath)
86
if err != nil {
87
return err
88
}
89
}
90
91
opts.kubeConfigSavePath = getKubeConfigPath()
92
return nil
93
},
94
RunE: func(cmd *cobra.Command, args []string) error {
95
if opts.watch {
96
for range time.Tick(15 * time.Second) {
97
// We're using a short timeout here to handle the scenario where someone switches
98
// to a branch that doesn't have a preview environment. In that case the default
99
// timeout would mean that we would block for 10 minutes, potentially missing
100
// if the user changes to a new branch that does that a preview.
101
err := install(true, 30*time.Second)
102
if err != nil {
103
logger.WithFields(logrus.Fields{"err": err}).Info("Failed to install context. Trying again soon.")
104
}
105
}
106
}
107
108
return install(true, opts.timeout)
109
},
110
}
111
112
cmd.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.")
113
cmd.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")
114
cmd.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")
115
116
return cmd
117
}
118
119