github.com/replicatedhq/ship@v0.55.0/pkg/lifecycle/render/helm/fetch.go (about) 1 package helm 2 3 import ( 4 "context" 5 "path" 6 7 "github.com/go-kit/kit/log" 8 "github.com/go-kit/kit/log/level" 9 "github.com/pkg/errors" 10 "github.com/replicatedhq/libyaml" 11 "github.com/replicatedhq/ship/pkg/api" 12 "github.com/replicatedhq/ship/pkg/constants" 13 "github.com/replicatedhq/ship/pkg/lifecycle/render/github" 14 "github.com/replicatedhq/ship/pkg/lifecycle/render/root" 15 "github.com/replicatedhq/ship/pkg/util" 16 "github.com/spf13/afero" 17 ) 18 19 // ChartFetcher fetches a chart based on an asset. it returns 20 // the location that the chart was unpacked to, usually a temporary directory 21 type ChartFetcher interface { 22 FetchChart( 23 ctx context.Context, 24 asset api.HelmAsset, 25 renderRoot string, 26 meta api.ReleaseMetadata, 27 configGroups []libyaml.ConfigGroup, 28 templateContext map[string]interface{}, 29 ) (string, error) 30 } 31 32 // ClientFetcher is a ChartFetcher that does all the pulling/cloning client side 33 type ClientFetcher struct { 34 Logger log.Logger 35 GitHub github.Renderer 36 FS afero.Afero 37 HelmCommands Commands 38 } 39 40 func (f *ClientFetcher) FetchChart( 41 ctx context.Context, 42 asset api.HelmAsset, 43 renderRoot string, 44 meta api.ReleaseMetadata, 45 configGroups []libyaml.ConfigGroup, 46 templateContext map[string]interface{}, 47 ) (string, error) { 48 debug := log.With(level.Debug(f.Logger), "fetcher", "client") 49 50 if asset.Local != nil { 51 debug.Log("event", "chart.fetch", "source", "local", "root", asset.Local.ChartRoot) 52 return asset.Local.ChartRoot, nil 53 } else if asset.GitHub != nil { 54 checkoutDir, err := f.FS.TempDir(constants.ShipPathInternalTmp, "helmchart") 55 if err != nil { 56 return "", errors.Wrap(err, "get chart checkout tmpdir") 57 } 58 asset.GitHub.Dest = checkoutDir 59 err = f.GitHub.Execute( 60 // just use the base FS, regardless of what renderRoot was specified, we're going to template+remove it 61 root.NewRootFS(f.FS, "."), 62 *asset.GitHub, 63 configGroups, 64 renderRoot, 65 meta, 66 templateContext, 67 )(ctx) 68 69 if err != nil { 70 return "", errors.Wrap(err, "fetch github asset") 71 } 72 73 return path.Join(checkoutDir, asset.GitHub.Path), nil 74 } else if asset.HelmFetch != nil { // TODO this branch could probably use a unittest 75 checkoutDir, err := f.FS.TempDir(constants.ShipPathInternalTmp, "helmchart") 76 if err != nil { 77 return "", errors.Wrap(err, "get chart checkout tmpdir") 78 } 79 80 err = f.HelmCommands.Init() 81 if err != nil { 82 return "", errors.Wrap(err, "init helm") 83 } 84 85 err = f.HelmCommands.Fetch( 86 asset.HelmFetch.ChartRef, 87 asset.HelmFetch.RepoURL, 88 asset.HelmFetch.Version, 89 checkoutDir, 90 constants.InternalTempHelmHome, 91 ) 92 if err != nil { 93 return "", errors.Wrap(err, "helm fetch") 94 } 95 96 // find the path that the chart was fetched to 97 chartDir, err := util.FindOnlySubdir(checkoutDir, f.FS) 98 if err != nil { 99 return "", errors.Wrap(err, "failed to find chart dir") 100 } 101 102 return chartDir, nil 103 } 104 105 debug.Log("event", "chart.fetch.fail", "reason", "unsupported") 106 return "", errors.New("only 'local', 'github' and 'helm_fetch' chart rendering is supported") 107 } 108 109 // NewFetcher makes a new chart fetcher 110 func NewFetcher( 111 logger log.Logger, 112 github github.Renderer, 113 fs afero.Afero, 114 helmCommands Commands, 115 ) ChartFetcher { 116 return &ClientFetcher{ 117 Logger: logger, 118 GitHub: github, 119 FS: fs, 120 HelmCommands: helmCommands, 121 } 122 }