...
1
15
16 package installer
17
18 import (
19 "fmt"
20 "log"
21 "net/http"
22 "os"
23 "path/filepath"
24 "strings"
25
26 "github.com/pkg/errors"
27
28 "helm.sh/helm/v3/pkg/plugin"
29 )
30
31
32 var ErrMissingMetadata = errors.New("plugin metadata (plugin.yaml) missing")
33
34
35 var Debug bool
36
37
38 type Installer interface {
39
40 Install() error
41
42 Path() string
43
44 Update() error
45 }
46
47
48 func Install(i Installer) error {
49 if err := os.MkdirAll(filepath.Dir(i.Path()), 0755); err != nil {
50 return err
51 }
52 if _, pathErr := os.Stat(i.Path()); !os.IsNotExist(pathErr) {
53 return errors.New("plugin already exists")
54 }
55 return i.Install()
56 }
57
58
59 func Update(i Installer) error {
60 if _, pathErr := os.Stat(i.Path()); os.IsNotExist(pathErr) {
61 return errors.New("plugin does not exist")
62 }
63 return i.Update()
64 }
65
66
67 func NewForSource(source, version string) (Installer, error) {
68
69 if isLocalReference(source) {
70 return NewLocalInstaller(source)
71 } else if isRemoteHTTPArchive(source) {
72 return NewHTTPInstaller(source)
73 }
74 return NewVCSInstaller(source, version)
75 }
76
77
78 func FindSource(location string) (Installer, error) {
79 installer, err := existingVCSRepo(location)
80 if err != nil && err.Error() == "Cannot detect VCS" {
81 return installer, errors.New("cannot get information about plugin source")
82 }
83 return installer, err
84 }
85
86
87 func isLocalReference(source string) bool {
88 _, err := os.Stat(source)
89 return err == nil
90 }
91
92
93
94
95
96 func isRemoteHTTPArchive(source string) bool {
97 if strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://") {
98 res, err := http.Head(source)
99 if err != nil {
100
101
102 return false
103 }
104
105
106
107 contentType := res.Header.Get("content-type")
108 foundSuffix, ok := mediaTypeToExtension(contentType)
109 if !ok {
110
111 return false
112 }
113
114 for suffix := range Extractors {
115 if strings.HasSuffix(foundSuffix, suffix) {
116 return true
117 }
118 }
119 }
120 return false
121 }
122
123
124 func isPlugin(dirname string) bool {
125 _, err := os.Stat(filepath.Join(dirname, plugin.PluginFileName))
126 return err == nil
127 }
128
129 var logger = log.New(os.Stderr, "[debug] ", log.Lshortfile)
130
131 func debug(format string, args ...interface{}) {
132 if Debug {
133 logger.Output(2, fmt.Sprintf(format, args...))
134 }
135 }
136
View as plain text