blob: dc742d54ab6bd5c88d025dae70baedf0db9a48fe [file] [log] [blame]
Giorgi Lekveishvili7c427602024-01-04 00:13:55 +04001package installer
2
3import (
4 "fmt"
giof8843412024-05-22 16:38:05 +04005 "io"
6 "io/fs"
7 "path/filepath"
Giorgi Lekveishvili7c427602024-01-04 00:13:55 +04008
giof8843412024-05-22 16:38:05 +04009 "github.com/giolekva/pcloud/core/installer/soft"
10
11 "github.com/go-git/go-billy/v5/memfs"
12 "github.com/go-git/go-billy/v5/util"
13 "github.com/go-git/go-git/v5"
14 "github.com/go-git/go-git/v5/plumbing"
15 "github.com/go-git/go-git/v5/storage/memory"
Giorgi Lekveishvili7c427602024-01-04 00:13:55 +040016 "helm.sh/helm/v3/pkg/action"
17 "helm.sh/helm/v3/pkg/kube"
18)
19
20type ActionConfigFactory struct {
21 kubeConfigPath string
22}
23
24func NewActionConfigFactory(kubeConfigPath string) ActionConfigFactory {
25 return ActionConfigFactory{kubeConfigPath}
26}
27
28func (f ActionConfigFactory) New(namespace string) (*action.Configuration, error) {
29 config := new(action.Configuration)
30 if err := config.Init(
31 kube.GetConfig(f.kubeConfigPath, "", namespace),
32 namespace,
33 "",
34 func(fmtString string, args ...any) {
35 fmt.Printf(fmtString, args...)
36 fmt.Println()
37 },
38 ); err != nil {
39 return nil, err
40 }
41 return config, nil
42}
giof8843412024-05-22 16:38:05 +040043
44type HelmFetcher interface {
gio7fbd4ad2024-08-27 10:06:39 +040045 // TODO(gio): implement integrity check
giof8843412024-05-22 16:38:05 +040046 Pull(chart HelmChartGitRepo, rfs soft.RepoFS, root string) error
47}
48
gio9877f292024-08-17 15:11:15 +040049type RepoCloner interface {
50 Clone(addr, ref string) (*git.Repository, error)
giof8843412024-05-22 16:38:05 +040051}
52
gio9877f292024-08-17 15:11:15 +040053type cachingRepoCloner struct {
54 cache map[string]*git.Repository
55}
56
57func NewCachingRepoCloner() RepoCloner {
58 return &cachingRepoCloner{make(map[string]*git.Repository)}
59}
60
61func (rc *cachingRepoCloner) Clone(addr, ref string) (*git.Repository, error) {
62 key := fmt.Sprintf("%s:%s", addr, ref)
63 if ret, ok := rc.cache[key]; ok {
64 return ret, nil
65 }
giof8843412024-05-22 16:38:05 +040066 r, err := git.Clone(memory.NewStorage(), memfs.New(), &git.CloneOptions{
gio9877f292024-08-17 15:11:15 +040067 URL: addr,
giof8843412024-05-22 16:38:05 +040068 ReferenceName: plumbing.ReferenceName(ref),
69 SingleBranch: true,
70 Depth: 1,
71 })
72 if err != nil {
gio9877f292024-08-17 15:11:15 +040073 return nil, err
74 }
75 // TODO(gio): enable
76 // rc.cache[key] = r
77 return r, nil
78}
79
80type gitHelmFetcher struct {
81 rc RepoCloner
82}
83
84func NewGitHelmFetcher() *gitHelmFetcher {
85 // TODO(gio): take cloner as an argument
86 return &gitHelmFetcher{NewCachingRepoCloner()}
87}
88
89func (f *gitHelmFetcher) Pull(chart HelmChartGitRepo, rfs soft.RepoFS, root string) error {
90 ref := fmt.Sprintf("refs/heads/%s", chart.Branch)
91 r, err := f.rc.Clone(chart.Address, ref)
92 if err != nil {
giof8843412024-05-22 16:38:05 +040093 return err
94 }
95 wt, err := r.Worktree()
96 if err != nil {
97 return err
98 }
99 wtFS, err := wt.Filesystem.Chroot(chart.Path)
100 if err != nil {
101 return err
102 }
giof6ad2982024-08-23 17:42:49 +0400103 if err := rfs.RemoveAll(root); err != nil {
gio7fbd4ad2024-08-27 10:06:39 +0400104 return err
105 }
giof8843412024-05-22 16:38:05 +0400106 return util.Walk(wtFS, "/", func(path string, info fs.FileInfo, err error) error {
107 if info.IsDir() {
108 return nil
109 }
110 inp, err := wtFS.Open(path)
111 if err != nil {
112 return err
113 }
114 out, err := rfs.Writer(filepath.Join(root, path))
115 if err != nil {
116 return err
117 }
118 _, err = io.Copy(out, inp)
119 return err
120 })
121}