github.com/replicatedhq/ship@v0.55.0/pkg/lifecycle/render/helm/dependency.go (about)

     1  package helm
     2  
     3  import (
     4  	"context"
     5  	"net/url"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"github.com/go-kit/kit/log"
    10  	"github.com/go-kit/kit/log/level"
    11  	"github.com/pkg/errors"
    12  	"github.com/replicatedhq/ship/pkg/api"
    13  	"github.com/replicatedhq/ship/pkg/constants"
    14  	"github.com/replicatedhq/ship/pkg/specs/apptype"
    15  	"github.com/replicatedhq/ship/pkg/specs/githubclient"
    16  	"github.com/replicatedhq/ship/pkg/specs/gogetter"
    17  	"github.com/replicatedhq/ship/pkg/util"
    18  	"k8s.io/helm/pkg/chartutil"
    19  )
    20  
    21  func (f *LocalTemplater) addDependencies(
    22  	dependencies []*chartutil.Dependency,
    23  	helmHome string,
    24  	chartRoot string,
    25  	asset api.HelmAsset,
    26  ) (depPaths []string, err error) {
    27  	for _, dependency := range dependencies {
    28  		if dependency.Repository != "" {
    29  			if strings.HasPrefix(dependency.Repository, "@") || strings.HasPrefix(dependency.Repository, "alias:") {
    30  				// The repository is an alias. Assume it has already been added.
    31  				continue
    32  			}
    33  			repoURL, err := url.Parse(dependency.Repository)
    34  			if err != nil {
    35  				return depPaths, errors.Wrapf(err, "parse dependency repo %s", dependency.Repository)
    36  			}
    37  			if repoURL.Scheme == "file" {
    38  				depPath, err := f.getLocalDependency(dependency.Repository, chartRoot, asset, helmHome)
    39  				if err != nil {
    40  					return depPaths, errors.Wrapf(err, "get local dep %s", dependency.Repository)
    41  				}
    42  				depPaths = append(depPaths, depPath)
    43  			} else {
    44  				repoName := strings.Split(repoURL.Hostname(), ".")[0]
    45  				if err := f.Commands.RepoAdd(repoName, dependency.Repository, helmHome); err != nil {
    46  					return depPaths, errors.Wrapf(err, "add helm repo %s", dependency.Repository)
    47  				}
    48  			}
    49  		}
    50  	}
    51  
    52  	return depPaths, nil
    53  }
    54  
    55  func (f *LocalTemplater) getLocalDependency(repo string, chartRoot string, originalAsset api.HelmAsset, helmHome string) (string, error) {
    56  	debug := level.Debug(log.With(f.Logger, "method", "getLocalDependency"))
    57  	var depPath string
    58  	var err error
    59  	p := strings.TrimPrefix(repo, "file://")
    60  
    61  	// root path is absolute
    62  	if strings.HasPrefix(p, "/") {
    63  		if depPath, err = filepath.Abs(p); err != nil {
    64  			return "", err
    65  		}
    66  	} else {
    67  		depPath = filepath.Join(chartRoot, p)
    68  	}
    69  
    70  	depPathExists, err := f.FS.DirExists(depPath)
    71  	if err != nil || !depPathExists {
    72  		depUpstream, err := f.createDependencyUpstreamFromAsset(originalAsset, p)
    73  		if err != nil {
    74  			return "", errors.Wrap(err, "create dependency upstream")
    75  		}
    76  		debug.Log("event", "fetchLocalHelmDependency", "depUpstream", depUpstream)
    77  		savedPath, err := f.fetchLocalHelmDependency(depUpstream, constants.HelmLocalDependencyPath)
    78  		if err != nil {
    79  			return "", errors.Wrap(err, "fetch local helm dependency")
    80  		}
    81  		if err := f.FS.MkdirAll(filepath.Dir(depPath), 0755); err != nil {
    82  			return "", errors.Wrap(err, "mkdirall dep path")
    83  		}
    84  		if err := f.FS.Rename(savedPath, depPath); err != nil {
    85  			return "", errors.Wrap(err, "rename to dep path")
    86  		}
    87  		if err := f.FS.RemoveAll(constants.HelmLocalDependencyPath); err != nil {
    88  			return "", errors.Wrap(err, "remove tmp local helm dependency")
    89  		}
    90  	}
    91  
    92  	return depPath, nil
    93  }
    94  
    95  func (f *LocalTemplater) createDependencyUpstreamFromAsset(originalAsset api.HelmAsset, path string) (string, error) {
    96  	upstream := originalAsset.Upstream
    97  	if util.IsGithubURL(upstream) {
    98  		githubURL, err := util.ParseGithubURL(upstream, "master")
    99  		if err != nil {
   100  			return "", errors.Wrap(err, "parse github url")
   101  		}
   102  
   103  		depPath := filepath.Join(githubURL.Subdir, path)
   104  		githubURL.Subdir = depPath
   105  		return githubURL.URL(), nil
   106  	}
   107  
   108  	return "", nil
   109  }
   110  
   111  func (f *LocalTemplater) fetchLocalHelmDependency(upstream string, fetchPath string) (string, error) {
   112  	var fetcher apptype.FileFetcher = githubclient.NewGithubClient(f.FS, f.Logger)
   113  	if f.Viper.GetBool("prefer-git") {
   114  		var isSingleFile bool
   115  		var subdir string
   116  		upstream, subdir, isSingleFile = gogetter.UntreeGithub(upstream)
   117  		fetcher = &gogetter.GoGetter{Logger: f.Logger, FS: f.FS, Subdir: subdir, IsSingleFile: isSingleFile}
   118  	}
   119  
   120  	savedPath, err := fetcher.GetFiles(context.Background(), upstream, fetchPath)
   121  	if err != nil {
   122  		return "", errors.Wrap(err, "get files")
   123  	}
   124  
   125  	return savedPath, nil
   126  }