云原生应用管理:原理与实践
上QQ阅读APP看书,第一时间看更新

4.1.1 locateChartPath

我们先看一下主要的源代码。


func locateChartPath(repoURL, username, password, name, version string, verify bool, keyring,
  certFile, keyFile, caFile string) (string, error) {
  
  // 第一优先级是当前目录,对传入的目录去掉左右空行后,通过库函数判断当前文件夹是否存在,如果存在,则返回当前文件夹的全局绝对路径
  name = strings.TrimSpace(name)
  version = strings.TrimSpace(version)
  if fi, err := os.Stat(name); err == nil {
    abs, err := filepath.Abs(name)
    if err != nil {
      return abs, err
    }
    return abs, nil
  }
  
  // 如果传入的是绝对路径或者是以.开头的路径,则直接返回失败
  if filepath.IsAbs(name) || strings.HasPrefix(name, ".") {
    return name, fmt.Errorf("path %q not found", name)
  }
  
  // 如果前面两种都不是,则从HELM_HOME中寻找对应的文件,并返回对应的绝对路径
  crepo := filepath.Join(settings.Home.Repository(), name)
  if _, err := os.Stat(crepo); err == nil {
    return filepath.Abs(crepo)
  }
  
  // 除了如上3种情况外,下面提供一个URL,需要从URL下载
  dl := downloader.ChartDownloader{
    HelmHome: settings.Home,
    Out:      os.Stdout,
    Keyring:  keyring,
    Getters:  getter.All(settings),
    Username: username,
    Password: password,
  }
  
  // 如果设置了Chart repo,就会从对应的Chart repo处查找Chart,下面具体看一下这个函数内部的实现
  if repoURL != "" {
    ChartURL, err := repo.FindChartInAuthRepoURL(repoURL, username, password, name, version,
      certFile, keyFile, caFile, getter.All(settings))
    name = ChartURL
  }
func FindChartInAuthRepoURL(repoURL, username, password, ChartName, ChartVersion, certFile, keyFile, caFile string, getters getter.Providers) (string, error) {

  // 首先创建一个临时文件,用来存放index.yaml
  tempIndexFile, err := ioutil.TempFile("", "tmp-repo-file")
  // 退出后将这个临时文件删除
  defer os.Remove(tempIndexFile.Name())

  // 将repoURL、用户名、密码等设置到对象中,方便后面下载
  c := Entry{
    URL:      repoURL,
    Username: username,
    Password: password,
    CertFile: certFile,
    KeyFile:  keyFile,
    CAFile:   caFile,
  }
  
  // 创建对应的Chart repo 实例对象
  r, err := NewChartRepository(&c, getters)
  
  // 将URL对应的index.yaml文件下载到本地的临时文件中
  if err := r.DownloadIndexFile(tempIndexFile.Name()); err != nil {
    return "", fmt.Errorf("Looks like %q is not a valid Chart repository or cannot be reached: %s", repoURL, err)
  }

  // 读取该文件,并寻找对应的Chart和URL
  repoIndex, err := LoadIndexFile(tempIndexFile.Name())
  if err != nil {
    return "", err
  }

  // 将index.yaml内提供的Chart名字和URL拼接好,形成一个完整路径的文件
  errMsg := fmt.Sprintf("Chart %q", ChartName)
  if ChartVersion != "" {
    errMsg = fmt.Sprintf("%s version %q", errMsg, ChartVersion)
  }
  cv, err := repoIndex.Get(ChartName, ChartVersion)
  ChartURL := cv.URLs[0]
  absoluteChartURL, err := ResolveReferenceURL(repoURL, ChartURL)
  
  // 返回对应的全局含有URL路径的文件
  return absoluteChartURL, nil

下面回到主流程中。

如果默认设置的下载路径没有对应的文件夹,那么先创建对应的文件夹。


if _, err := os.Stat(settings.Home.Archive()); os.IsNotExist(err) {
    os.MkdirAll(settings.Home.Archive(), 0744)
  }

将前面拼接好的带有URL路径的文件,或者用户直接提供的全路径http文件下载到对应的文件夹中,最后返回这个下载到本地路径的文件。


filename,_ err:=dl.DownloadTo(name,version,settings.Home.Archive())

该函数的流程如图4-1所示。

图4-1 Chart流程下载