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 }