github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/cmd/infrastructure/tasks/kubernetes.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package tasks 21 22 import ( 23 "fmt" 24 "path/filepath" 25 "strings" 26 27 "github.com/StudioSol/set" 28 kubekeyapiv1alpha2 "github.com/kubesphere/kubekey/v3/cmd/kk/apis/kubekey/v1alpha2" 29 "github.com/kubesphere/kubekey/v3/cmd/kk/pkg/bootstrap/os" 30 "github.com/kubesphere/kubekey/v3/cmd/kk/pkg/bootstrap/os/templates" 31 "github.com/kubesphere/kubekey/v3/cmd/kk/pkg/common" 32 "github.com/kubesphere/kubekey/v3/cmd/kk/pkg/core/connector" 33 "github.com/kubesphere/kubekey/v3/cmd/kk/pkg/core/task" 34 "github.com/kubesphere/kubekey/v3/cmd/kk/pkg/kubernetes" 35 "k8s.io/client-go/tools/clientcmd" 36 clientcmdapi "k8s.io/client-go/tools/clientcmd/api" 37 38 "github.com/1aal/kubeblocks/pkg/cli/cmd/infrastructure/builder" 39 "github.com/1aal/kubeblocks/pkg/cli/cmd/infrastructure/constant" 40 "github.com/1aal/kubeblocks/pkg/cli/cmd/infrastructure/types" 41 cfgcore "github.com/1aal/kubeblocks/pkg/configuration/core" 42 "github.com/1aal/kubeblocks/pkg/gotemplate" 43 ) 44 45 type PrepareK8sBinariesModule struct { 46 common.KubeModule 47 48 // kubernetes version 49 BinaryVersion types.InfraVersionInfo 50 } 51 52 type ConfigureNodeOSModule struct { 53 common.KubeModule 54 Nodes []types.ClusterNode 55 } 56 57 type SaveKubeConfigModule struct { 58 common.KubeModule 59 60 OutputKubeconfig string 61 } 62 63 func (p *PrepareK8sBinariesModule) Init() { 64 p.Name = "PrepareK8sBinariesModule" 65 p.Desc = "Download installation binaries for kubernetes" 66 67 p.Tasks = []task.Interface{ 68 &task.LocalTask{ 69 Name: "PrepareK8sBinaries", 70 Desc: "Download installation binaries", 71 Action: &DownloadKubernetesBinary{BinaryVersion: p.BinaryVersion}, 72 }} 73 } 74 75 func (c *ConfigureNodeOSModule) Init() { 76 c.Name = "ConfigureNodeOSModule" 77 c.Desc = "Init os dependencies" 78 c.Tasks = []task.Interface{ 79 &task.RemoteTask{ 80 Name: "GetOSData", 81 Desc: "Get OS release", 82 Hosts: c.Runtime.GetAllHosts(), 83 Action: new(os.GetOSData), 84 Parallel: true, 85 }, 86 &task.RemoteTask{ 87 Name: "SetHostName", 88 Desc: "Prepare to init OS", 89 Hosts: c.Runtime.GetAllHosts(), 90 Action: new(os.NodeConfigureOS), 91 Parallel: true, 92 }, 93 &task.RemoteTask{ 94 Name: "GenerateScript", 95 Desc: "Generate init os script", 96 Hosts: c.Runtime.GetAllHosts(), 97 Action: &NodeScriptGenerator{ 98 Hosts: templates.GenerateHosts(c.Runtime, c.KubeConf), 99 Nodes: c.Nodes, 100 }, 101 Parallel: true, 102 }, 103 &task.RemoteTask{ 104 Name: "ExecScript", 105 Desc: "Exec init os script", 106 Hosts: c.Runtime.GetAllHosts(), 107 Action: new(os.NodeExecScript), 108 Parallel: true, 109 }} 110 } 111 112 func (p *SaveKubeConfigModule) Init() { 113 p.Name = "SaveKubeConfigModule" 114 p.Desc = "Save kube config to local file" 115 116 p.Tasks = []task.Interface{ 117 &task.LocalTask{ 118 Name: "SaveKubeConfig", 119 Desc: "Save kube config to local file", 120 Action: &SaveKubeConfig{outputKubeconfig: p.OutputKubeconfig}, 121 }} 122 } 123 124 type DownloadKubernetesBinary struct { 125 common.KubeAction 126 BinaryVersion types.InfraVersionInfo 127 } 128 129 func (d *DownloadKubernetesBinary) Execute(runtime connector.Runtime) error { 130 archSet := set.NewLinkedHashSetString() 131 for _, host := range runtime.GetAllHosts() { 132 archSet.Add(host.GetArch()) 133 } 134 135 for _, arch := range archSet.AsSlice() { 136 binariesMap, err := downloadKubernetesBinaryWithArch(runtime.GetWorkDir(), arch, d.BinaryVersion) 137 if err != nil { 138 return err 139 } 140 d.PipelineCache.Set(common.KubeBinaries+"-"+arch, binariesMap) 141 } 142 return nil 143 } 144 145 type SaveKubeConfig struct { 146 common.KubeAction 147 148 outputKubeconfig string 149 } 150 151 func (c *SaveKubeConfig) Execute(runtime connector.Runtime) error { 152 master := runtime.GetHostsByRole(common.Master)[0] 153 154 status, ok := c.PipelineCache.Get(common.ClusterStatus) 155 if !ok { 156 return cfgcore.MakeError("failed to get kubernetes status.") 157 } 158 cluster := status.(*kubernetes.KubernetesStatus) 159 kubeConfigStr := cluster.KubeConfig 160 kc, err := clientcmd.Load([]byte(kubeConfigStr)) 161 if err != nil { 162 return err 163 } 164 updateClusterAPIServer(kc, master, c.KubeConf.Cluster.ControlPlaneEndpoint) 165 kcFile := GetDefaultConfig() 166 existingKC, err := kubeconfigLoad(kcFile) 167 if err != nil { 168 return err 169 } 170 if c.outputKubeconfig == "" { 171 c.outputKubeconfig = kcFile 172 } 173 if existingKC != nil { 174 return kubeconfigMerge(kc, existingKC, c.outputKubeconfig) 175 } 176 return kubeconfigWrite(kc, c.outputKubeconfig) 177 } 178 179 type NodeScriptGenerator struct { 180 common.KubeAction 181 182 Nodes []types.ClusterNode 183 Hosts []string 184 } 185 186 func (c *NodeScriptGenerator) Execute(runtime connector.Runtime) error { 187 foundHostOptions := func(nodes []types.ClusterNode, host connector.Host) types.NodeOptions { 188 for _, node := range nodes { 189 switch { 190 default: 191 return types.NodeOptions{} 192 case node.Name != host.GetName(): 193 case node.NodeOptions != nil: 194 return *node.NodeOptions 195 } 196 } 197 return types.NodeOptions{} 198 } 199 200 scriptsTemplate := builder.Template{ 201 Template: constant.ConfigureOSScripts, 202 Dst: filepath.Join(common.KubeScriptDir, "initOS.sh"), 203 Values: gotemplate.TplValues{ 204 "Hosts": c.Hosts, 205 "Options": foundHostOptions(c.Nodes, runtime.RemoteHost()), 206 }} 207 return scriptsTemplate.Execute(runtime) 208 } 209 210 func updateClusterAPIServer(kc *clientcmdapi.Config, master connector.Host, endpoint kubekeyapiv1alpha2.ControlPlaneEndpoint) { 211 cpePrefix := fmt.Sprintf("https://%s:", endpoint.Domain) 212 for _, cluster := range kc.Clusters { 213 if strings.HasPrefix(cluster.Server, cpePrefix) { 214 cluster.Server = fmt.Sprintf("https://%s:%d", master.GetAddress(), endpoint.Port) 215 } 216 } 217 }