github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/pkg/runtime/registry.go (about) 1 // Copyright © 2021 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package runtime 16 17 import ( 18 "fmt" 19 "path/filepath" 20 21 "github.com/alibaba/sealer/pkg/cert" 22 23 "github.com/alibaba/sealer/common" 24 25 "github.com/alibaba/sealer/logger" 26 "github.com/alibaba/sealer/utils" 27 "golang.org/x/crypto/bcrypt" 28 ) 29 30 const ( 31 RegistryName = "sealer-registry" 32 RegistryBindDest = "/var/lib/registry" 33 RegistryBindConfig = "registry_config.yml" 34 RegistryCustomConfig = "registry.yml" 35 SeaHub = "sea.hub" 36 DefaultRegistryHtPasswdFile = "registry_htpasswd" 37 DockerLoginCommand = "nerdctl login -u %s -p %s %s && " + KubeletAuthCommand 38 KubeletAuthCommand = "cp /root/.docker/config.json /var/lib/kubelet" 39 ) 40 41 type RegistryConfig struct { 42 IP string `yaml:"ip,omitempty"` 43 Domain string `yaml:"domain,omitempty"` 44 Port string `yaml:"port,omitempty"` 45 Username string `json:"username,omitempty"` 46 Password string `json:"password,omitempty"` 47 } 48 49 func (k *KubeadmRuntime) getRegistryHost() (host string) { 50 ip, _ := utils.GetSSHHostIPAndPort(k.RegConfig.IP) 51 return fmt.Sprintf("%s %s", ip, k.RegConfig.Domain) 52 } 53 54 // ApplyRegistry Only use this for join and init, due to the initiation operations. 55 func (k *KubeadmRuntime) ApplyRegistry() error { 56 ssh, err := k.getHostSSHClient(k.RegConfig.IP) 57 if err != nil { 58 return fmt.Errorf("failed to get registry ssh client: %v", err) 59 } 60 61 if k.RegConfig.Username != "" && k.RegConfig.Password != "" { 62 htpasswd, err := k.RegConfig.GenerateHtPasswd() 63 if err != nil { 64 return err 65 } 66 err = ssh.CmdAsync(k.RegConfig.IP, fmt.Sprintf("echo '%s' > %s", htpasswd, filepath.Join(k.getRootfs(), "etc", DefaultRegistryHtPasswdFile))) 67 if err != nil { 68 return err 69 } 70 } 71 initRegistry := fmt.Sprintf("cd %s/scripts && sh init-registry.sh %s %s %s", k.getRootfs(), k.RegConfig.Port, fmt.Sprintf("%s/registry", k.getRootfs()), k.RegConfig.Domain) 72 registryHost := k.getRegistryHost() 73 addRegistryHosts := fmt.Sprintf(RemoteAddEtcHosts, registryHost, registryHost) 74 if k.RegConfig.Domain != SeaHub { 75 addSeaHubHosts := fmt.Sprintf(RemoteAddEtcHosts, k.RegConfig.IP+" "+SeaHub, k.RegConfig.IP+" "+SeaHub) 76 addRegistryHosts = fmt.Sprintf("%s && %s", addRegistryHosts, addSeaHubHosts) 77 } 78 if err = ssh.CmdAsync(k.RegConfig.IP, initRegistry); err != nil { 79 return err 80 } 81 if err = ssh.CmdAsync(k.GetMaster0IP(), addRegistryHosts); err != nil { 82 return err 83 } 84 if k.RegConfig.Username == "" || k.RegConfig.Password == "" { 85 return nil 86 } 87 return ssh.CmdAsync(k.GetMaster0IP(), k.GerLoginCommand()) 88 } 89 90 func (k *KubeadmRuntime) GerLoginCommand() string { 91 return fmt.Sprintf("%s && %s", 92 fmt.Sprintf(DockerLoginCommand, k.RegConfig.Username, k.RegConfig.Password, k.RegConfig.Domain+":"+k.RegConfig.Port), 93 fmt.Sprintf(DockerLoginCommand, k.RegConfig.Username, k.RegConfig.Password, SeaHub+":"+k.RegConfig.Port)) 94 } 95 96 func (r *RegistryConfig) GenerateHtPasswd() (string, error) { 97 if r.Username == "" || r.Password == "" { 98 return "", fmt.Errorf("generate htpasswd failed: registry username or passwodr is empty") 99 } 100 pwdHash, err := bcrypt.GenerateFromPassword([]byte(r.Password), bcrypt.DefaultCost) 101 if err != nil { 102 return "", fmt.Errorf("failed to generate registry password: %v", err) 103 } 104 return r.Username + ":" + string(pwdHash), nil 105 } 106 107 func (r *RegistryConfig) Repo() string { 108 return fmt.Sprintf("%s:%s", r.Domain, r.Port) 109 } 110 111 func GetRegistryConfig(rootfs, defaultRegistry string) *RegistryConfig { 112 var config RegistryConfig 113 var DefaultConfig = &RegistryConfig{ 114 IP: defaultRegistry, 115 Domain: SeaHub, 116 Port: "5000", 117 } 118 registryConfigPath := filepath.Join(rootfs, common.EtcDir, RegistryCustomConfig) 119 if !utils.IsFileExist(registryConfigPath) { 120 logger.Debug("use default registry config") 121 return DefaultConfig 122 } 123 err := utils.UnmarshalYamlFile(registryConfigPath, &config) 124 if err != nil { 125 logger.Error("Failed to read registry config! ") 126 return DefaultConfig 127 } 128 if config.IP == "" { 129 config.IP = DefaultConfig.IP 130 } 131 if config.Port == "" { 132 config.Port = DefaultConfig.Port 133 } 134 if config.Domain == "" { 135 config.Domain = DefaultConfig.Domain 136 } 137 logger.Debug("show registry info, IP: %s, Domain: %s", config.IP, config.Domain) 138 return &config 139 } 140 141 func (k *KubeadmRuntime) DeleteRegistry() error { 142 ssh, err := k.getHostSSHClient(k.RegConfig.IP) 143 if err != nil { 144 return fmt.Errorf("failed to delete registry: %v", err) 145 } 146 147 cmd := fmt.Sprintf("if docker inspect %s;then docker rm -f %s;fi", RegistryName, RegistryName) 148 return ssh.CmdAsync(k.RegConfig.IP, cmd) 149 } 150 151 func GenerateRegistryCert(registryCertPath string, BaseName string) error { 152 regCertConfig := cert.Config{ 153 Path: registryCertPath, 154 BaseName: BaseName, 155 CommonName: BaseName, 156 DNSNames: []string{BaseName}, 157 Organization: []string{common.ExecBinaryFileName}, 158 Year: 100, 159 } 160 if BaseName != SeaHub { 161 regCertConfig.DNSNames = append(regCertConfig.DNSNames, SeaHub) 162 } 163 crt, key, err := cert.NewCaCertAndKey(regCertConfig) 164 if err != nil { 165 return err 166 } 167 return cert.WriteCertAndKey(regCertConfig.Path, regCertConfig.BaseName, crt, key) 168 }