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
2500 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
return err
45
}
46
47
if hasAccess(ctx, logger, name) {
48
opts.logger.Debugf("Access to [%s] already configured and connections can be established", name)
49
return nil
50
}
51
52
p, err := preview.New(branch, logger)
53
if err != nil {
54
return err
55
}
56
57
if lastSuccessfulPreviewEnvironment != nil && lastSuccessfulPreviewEnvironment.Same(p) {
58
logger.Infof("The preview envrionment hasn't changed")
59
return nil
60
}
61
62
err = p.InstallContext(ctx, &preview.InstallCtxOpts{
63
Retry: retry,
64
RetryTimeout: opts.timeout,
65
KubeSavePath: opts.kubeConfigSavePath,
66
SSHPrivateKeyPath: opts.sshPrivateKeyPath,
67
})
68
69
if err == nil {
70
lastSuccessfulPreviewEnvironment = p
71
}
72
73
return err
74
}
75
76
cmd := &cobra.Command{
77
Use: "install-context",
78
Short: "Installs the kubectl context of a preview environment.",
79
PreRunE: func(cmd *cobra.Command, args []string) error {
80
if _, err := os.Stat(opts.sshPrivateKeyPath); errors.Is(err, fs.ErrNotExist) {
81
err := preview.GenerateSSHPrivateKey(opts.sshPrivateKeyPath)
82
if err != nil {
83
return err
84
}
85
}
86
87
opts.kubeConfigSavePath = getKubeConfigPath()
88
return nil
89
},
90
RunE: func(cmd *cobra.Command, args []string) error {
91
if opts.watch {
92
for range time.Tick(15 * time.Second) {
93
// We're using a short timeout here to handle the scenario where someone switches
94
// to a branch that doesn't have a preview environment. In that case the default
95
// timeout would mean that we would block for 10 minutes, potentially missing
96
// if the user changes to a new branch that does that a preview.
97
err := install(true, 30*time.Second)
98
if err != nil {
99
logger.WithFields(logrus.Fields{"err": err}).Info("Failed to install context. Trying again soon.")
100
}
101
}
102
}
103
104
return install(true, opts.timeout)
105
},
106
}
107
108
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.")
109
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")
110
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")
111
112
return cmd
113
}
114
115