blob: 8370b4e2c1de49d164ea182efda40d540b9831a5 [file] [log] [blame]
package installer
import (
"fmt"
"io"
"io/fs"
"path/filepath"
"github.com/giolekva/pcloud/core/installer/soft"
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-billy/v5/util"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/storage/memory"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/kube"
)
type ActionConfigFactory struct {
kubeConfigPath string
}
func NewActionConfigFactory(kubeConfigPath string) ActionConfigFactory {
return ActionConfigFactory{kubeConfigPath}
}
func (f ActionConfigFactory) New(namespace string) (*action.Configuration, error) {
config := new(action.Configuration)
if err := config.Init(
kube.GetConfig(f.kubeConfigPath, "", namespace),
namespace,
"",
func(fmtString string, args ...any) {
fmt.Printf(fmtString, args...)
fmt.Println()
},
); err != nil {
return nil, err
}
return config, nil
}
type HelmFetcher interface {
Pull(chart HelmChartGitRepo, rfs soft.RepoFS, root string) error
}
type RepoCloner interface {
Clone(addr, ref string) (*git.Repository, error)
}
type cachingRepoCloner struct {
cache map[string]*git.Repository
}
func NewCachingRepoCloner() RepoCloner {
return &cachingRepoCloner{make(map[string]*git.Repository)}
}
func (rc *cachingRepoCloner) Clone(addr, ref string) (*git.Repository, error) {
key := fmt.Sprintf("%s:%s", addr, ref)
if ret, ok := rc.cache[key]; ok {
return ret, nil
}
r, err := git.Clone(memory.NewStorage(), memfs.New(), &git.CloneOptions{
URL: addr,
ReferenceName: plumbing.ReferenceName(ref),
SingleBranch: true,
Depth: 1,
})
if err != nil {
return nil, err
}
// TODO(gio): enable
// rc.cache[key] = r
return r, nil
}
type gitHelmFetcher struct {
rc RepoCloner
}
func NewGitHelmFetcher() *gitHelmFetcher {
// TODO(gio): take cloner as an argument
return &gitHelmFetcher{NewCachingRepoCloner()}
}
func (f *gitHelmFetcher) Pull(chart HelmChartGitRepo, rfs soft.RepoFS, root string) error {
ref := fmt.Sprintf("refs/heads/%s", chart.Branch)
r, err := f.rc.Clone(chart.Address, ref)
if err != nil {
return err
}
wt, err := r.Worktree()
if err != nil {
return err
}
wtFS, err := wt.Filesystem.Chroot(chart.Path)
if err != nil {
return err
}
return util.Walk(wtFS, "/", func(path string, info fs.FileInfo, err error) error {
if info.IsDir() {
return nil
}
inp, err := wtFS.Open(path)
if err != nil {
return err
}
out, err := rfs.Writer(filepath.Join(root, path))
if err != nil {
return err
}
_, err = io.Copy(out, inp)
return err
})
}