-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathregister_member.go
More file actions
161 lines (141 loc) · 5.89 KB
/
Copy pathregister_member.go
File metadata and controls
161 lines (141 loc) · 5.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package adm
import (
"context"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1"
"github.com/kubesaw/ksctl/pkg/client"
"github.com/kubesaw/ksctl/pkg/cmd/flags"
"github.com/kubesaw/ksctl/pkg/configuration"
clicontext "github.com/kubesaw/ksctl/pkg/context"
"github.com/kubesaw/ksctl/pkg/ioutils"
"k8s.io/client-go/util/homedir"
errs "github.com/pkg/errors"
"github.com/spf13/cobra"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
)
const (
AddClusterScriptDomain = "https://raw.githubusercontent.com/"
AddClusterScriptPath = "codeready-toolchain/toolchain-cicd/master/scripts/add-cluster.sh"
AddClusterScriptURL = AddClusterScriptDomain + AddClusterScriptPath
)
func NewRegisterMemberCmd() *cobra.Command {
var hostKubeconfig, memberKubeconfig string
cmd := &cobra.Command{
Use: "register-member",
Short: "Executes add-cluster.sh script",
Long: `Downloads the 'add-cluster.sh' script from the 'toolchain-cicd' repo and calls it twice: once to register the Host cluster in the Member cluster and once to register the Member cluster in the host cluster.`,
RunE: func(cmd *cobra.Command, args []string) error {
term := ioutils.NewTerminal(cmd.InOrStdin, cmd.OutOrStdout)
newCommand := func(name string, args ...string) *exec.Cmd {
return exec.Command(name, args...)
}
return registerMemberCluster(context.Background(), term, client.DefaultNewClient, newCommand, hostKubeconfig, memberKubeconfig)
},
}
defaultKubeconfigPath := ""
if home := homedir.HomeDir(); home != "" {
defaultKubeconfigPath = filepath.Join(home, ".kube", "config")
}
cmd.Flags().StringVar(&hostKubeconfig, "host-kubeconfig", defaultKubeconfigPath, "Path to the kubeconfig file of the host cluster (default: "+defaultKubeconfigPath+")")
flags.MustMarkRequired(cmd, "host-kubeconfig")
cmd.Flags().StringVar(&memberKubeconfig, "member-kubeconfig", defaultKubeconfigPath, "Path to the kubeconfig file of the member cluster (default: "+defaultKubeconfigPath+")")
flags.MustMarkRequired(cmd, "member-kubeconfig")
return cmd
}
func registerMemberCluster(ctx context.Context, term ioutils.Terminal, newClient clicontext.NewClientFunc, newCommand client.CommandCreator, hostKubeconfig, memberKubeconfig string) error {
term.AskForConfirmation(ioutils.WithMessagef("register member cluster from kubeconfig %s. Be aware that the ksctl disables automatic approval to prevent new users being provisioned to the new member cluster. "+
"You will need to enable it again manually.", memberKubeconfig))
hostClusterConfig, err := configuration.LoadClusterConfig(term, configuration.HostName)
if err != nil {
return err
}
hostClusterClient, err := newClient(hostClusterConfig.Token, hostClusterConfig.ServerAPI)
if err != nil {
return err
}
if err := disableAutomaticApproval(hostClusterConfig, hostClusterClient); err != nil {
return err
}
if err := runAddClusterScript(term, newCommand, configuration.Host, hostKubeconfig, memberKubeconfig); err != nil {
return err
}
if err := runAddClusterScript(term, newCommand, configuration.Member, hostKubeconfig, memberKubeconfig); err != nil {
return err
}
warningMessage := "The automatic approval was disabled!\n Configure the new member cluster in ToolchainConfig and apply the changes to the cluster."
if err := restartHostOperator(ctx, term, hostClusterClient, hostClusterConfig); err != nil {
return fmt.Errorf("%w\nIn Additon, there is another warning you should be aware of:\n%s", err, warningMessage)
}
term.Printlnf("!!!!!!!!!!!!!!!")
term.Printlnf("!!! WARNING !!!")
term.Printlnf("!!!!!!!!!!!!!!!")
term.Printlnf(warningMessage)
return nil
}
func disableAutomaticApproval(hostClusterConfig configuration.ClusterConfig, cl runtimeclient.Client) error {
configs := &toolchainv1alpha1.ToolchainConfigList{}
if err := cl.List(context.TODO(), configs, runtimeclient.InNamespace(hostClusterConfig.SandboxNamespace)); err != nil {
return err
}
if len(configs.Items) == 0 {
return nil
}
if len(configs.Items) > 1 {
return fmt.Errorf("there are more than one instance of ToolchainConfig")
}
toolchainConfig := configs.Items[0]
if toolchainConfig.Spec.Host.AutomaticApproval.Enabled != nil && *toolchainConfig.Spec.Host.AutomaticApproval.Enabled {
enabled := false
toolchainConfig.Spec.Host.AutomaticApproval.Enabled = &enabled
return cl.Update(context.TODO(), &toolchainConfig)
}
return nil
}
func runAddClusterScript(term ioutils.Terminal, newCommand client.CommandCreator, joiningClusterType configuration.ClusterType, hostKubeconfig, memberKubeconfig string) error {
if !term.AskForConfirmation(ioutils.WithMessagef("register the %s cluster by creating a ToolchainCluster CR, a Secret and a new ServiceAccount resource?", joiningClusterType)) {
return nil
}
script, err := downloadScript(term)
if err != nil {
return err
}
args := []string{script.Name(), "--type", joiningClusterType.String(), "--host-kubeconfig", hostKubeconfig, "--member-kubeconfig", memberKubeconfig, "--lets-encrypt"}
term.Printlnf("Command to be called: bash %s\n", strings.Join(args, " "))
bash := newCommand("bash", args...)
bash.Stdout = os.Stdout
bash.Stderr = os.Stderr
return bash.Run()
}
func downloadScript(term ioutils.Terminal) (*os.File, error) {
resp, err := http.Get(AddClusterScriptURL)
if err != nil {
return nil, errs.Wrapf(err, "unable to get add-script.sh")
}
if resp.StatusCode < 200 || resp.StatusCode > 299 {
return nil, fmt.Errorf("unable to get add-script.sh - response status %s", resp.Status)
}
defer func() {
if err := resp.Body.Close(); err != nil {
term.Printlnf(err.Error())
}
}()
// Create the file
file, err := os.CreateTemp("", "add-cluster-*.sh")
if err != nil {
return nil, err
}
defer func() {
if err := file.Close(); err != nil {
term.Printlnf(err.Error())
}
}()
// Write the body to file
_, err = io.Copy(file, resp.Body)
return file, err
}