github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/registry/external.go (about)

     1  // Copyright © 2022 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 registry
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"net"
    21  	"os"
    22  	"strconv"
    23  
    24  	"github.com/containers/common/pkg/auth"
    25  	"github.com/sirupsen/logrus"
    26  
    27  	"github.com/sealerio/sealer/common"
    28  	containerruntime "github.com/sealerio/sealer/pkg/container-runtime"
    29  	"github.com/sealerio/sealer/pkg/infradriver"
    30  	v2 "github.com/sealerio/sealer/types/api/v2"
    31  )
    32  
    33  type externalConfigurator struct {
    34  	containerRuntimeInfo containerruntime.Info
    35  	infraDriver          infradriver.InfraDriver
    36  	endpoint             string
    37  	username             string
    38  	password             string
    39  }
    40  
    41  func (e *externalConfigurator) GetRegistryInfo() RegistryInfo {
    42  	clusterRegistry := e.infraDriver.GetClusterRegistry()
    43  	return RegistryInfo{
    44  		External: clusterRegistry.ExternalRegistry,
    45  	}
    46  }
    47  
    48  func (e *externalConfigurator) InstallOn(masters, nodes []net.IP) error {
    49  	hosts := append(masters, nodes...)
    50  	var (
    51  		username        = e.username
    52  		password        = e.password
    53  		endpoint        = e.endpoint
    54  		tmpAuthFilePath = "/tmp/config.json"
    55  		// todo we need this config file when kubelet pull images from registry. while, we could optimize the logic here.
    56  		remoteKubeletAuthFilePath = "/var/lib/kubelet/config.json"
    57  	)
    58  
    59  	if username == "" || password == "" {
    60  		return nil
    61  	}
    62  
    63  	err := auth.Login(context.TODO(),
    64  		nil,
    65  		&auth.LoginOptions{
    66  			AuthFile:           tmpAuthFilePath,
    67  			Password:           password,
    68  			Username:           username,
    69  			Stdout:             os.Stdout,
    70  			AcceptRepositories: true,
    71  		},
    72  		[]string{endpoint})
    73  
    74  	if err != nil {
    75  		return err
    76  	}
    77  
    78  	defer func() {
    79  		err = os.Remove(tmpAuthFilePath)
    80  		if err != nil {
    81  			logrus.Debugf("failed to remove tmp registry auth file:%s", tmpAuthFilePath)
    82  		}
    83  	}()
    84  
    85  	err = e.copy2RemoteHosts(tmpAuthFilePath, e.containerRuntimeInfo.ConfigFilePath, hosts)
    86  	if err != nil {
    87  		return err
    88  	}
    89  
    90  	err = e.copy2RemoteHosts(tmpAuthFilePath, remoteKubeletAuthFilePath, hosts)
    91  	if err != nil {
    92  		return err
    93  	}
    94  
    95  	return nil
    96  }
    97  
    98  func (e *externalConfigurator) copy2RemoteHosts(src, dest string, hosts []net.IP) error {
    99  	f := func(host net.IP) error {
   100  		err := e.infraDriver.Copy(host, src, dest)
   101  		if err != nil {
   102  			return fmt.Errorf("failed to copy local file %s to remote %s : %v", src, dest, err)
   103  		}
   104  		return nil
   105  	}
   106  
   107  	return e.infraDriver.Execute(hosts, f)
   108  }
   109  
   110  func (e *externalConfigurator) UninstallFrom(masters, nodes []net.IP) error {
   111  	if e.username == "" || e.password == "" {
   112  		return nil
   113  	}
   114  	hosts := append(masters, nodes...)
   115  	//todo use sdk to logout instead of shell cmd
   116  	logoutCmd := fmt.Sprintf("docker logout %s ", e.endpoint)
   117  	//nolint
   118  	if e.containerRuntimeInfo.Type != common.Docker {
   119  		logoutCmd = fmt.Sprintf("nerdctl logout %s ", e.endpoint)
   120  	}
   121  
   122  	for _, host := range hosts {
   123  		err := e.infraDriver.CmdAsync(host, nil, logoutCmd)
   124  		if err != nil {
   125  			return fmt.Errorf("failed to delete registry configuration: %v", err)
   126  		}
   127  	}
   128  
   129  	return nil
   130  }
   131  
   132  func (e *externalConfigurator) GetDriver() (Driver, error) {
   133  	return newExternalRegistryDriver(e.endpoint), nil
   134  }
   135  
   136  func NewExternalConfigurator(regConfig *v2.ExternalRegistry, containerRuntimeInfo containerruntime.Info, driver infradriver.InfraDriver) (Configurator, error) {
   137  	domain := regConfig.Domain
   138  	if regConfig.Port != 0 {
   139  		domain = net.JoinHostPort(regConfig.Domain, strconv.Itoa(regConfig.Port))
   140  	}
   141  	return &externalConfigurator{
   142  		endpoint:             domain,
   143  		username:             regConfig.Username,
   144  		password:             regConfig.Password,
   145  		infraDriver:          driver,
   146  		containerRuntimeInfo: containerRuntimeInfo,
   147  	}, nil
   148  }