1
15
16 package getter
17
18 import (
19 "bytes"
20 "fmt"
21 "os"
22 "os/exec"
23 "path/filepath"
24 "strings"
25
26 "github.com/pkg/errors"
27
28 "helm.sh/helm/v3/pkg/cli"
29 "helm.sh/helm/v3/pkg/plugin"
30 )
31
32
33
34 func collectPlugins(settings *cli.EnvSettings) (Providers, error) {
35 plugins, err := plugin.FindPlugins(settings.PluginsDirectory)
36 if err != nil {
37 return nil, err
38 }
39 var result Providers
40 for _, plugin := range plugins {
41 for _, downloader := range plugin.Metadata.Downloaders {
42 result = append(result, Provider{
43 Schemes: downloader.Protocols,
44 New: NewPluginGetter(
45 downloader.Command,
46 settings,
47 plugin.Metadata.Name,
48 plugin.Dir,
49 ),
50 })
51 }
52 }
53 return result, nil
54 }
55
56
57
58 type pluginGetter struct {
59 command string
60 settings *cli.EnvSettings
61 name string
62 base string
63 opts options
64 }
65
66 func (p *pluginGetter) setupOptionsEnv(env []string) []string {
67 env = append(env, fmt.Sprintf("HELM_PLUGIN_USERNAME=%s", p.opts.username))
68 env = append(env, fmt.Sprintf("HELM_PLUGIN_PASSWORD=%s", p.opts.password))
69 env = append(env, fmt.Sprintf("HELM_PLUGIN_PASS_CREDENTIALS_ALL=%t", p.opts.passCredentialsAll))
70 return env
71 }
72
73
74 func (p *pluginGetter) Get(href string, options ...Option) (*bytes.Buffer, error) {
75 for _, opt := range options {
76 opt(&p.opts)
77 }
78 commands := strings.Split(p.command, " ")
79 argv := append(commands[1:], p.opts.certFile, p.opts.keyFile, p.opts.caFile, href)
80 prog := exec.Command(filepath.Join(p.base, commands[0]), argv...)
81 plugin.SetupPluginEnv(p.settings, p.name, p.base)
82 prog.Env = p.setupOptionsEnv(os.Environ())
83 buf := bytes.NewBuffer(nil)
84 prog.Stdout = buf
85 prog.Stderr = os.Stderr
86 if err := prog.Run(); err != nil {
87 if eerr, ok := err.(*exec.ExitError); ok {
88 os.Stderr.Write(eerr.Stderr)
89 return nil, errors.Errorf("plugin %q exited with error", p.command)
90 }
91 return nil, err
92 }
93 return buf, nil
94 }
95
96
97 func NewPluginGetter(command string, settings *cli.EnvSettings, name, base string) Constructor {
98 return func(options ...Option) (Getter, error) {
99 result := &pluginGetter{
100 command: command,
101 settings: settings,
102 name: name,
103 base: base,
104 }
105 for _, opt := range options {
106 opt(&result.opts)
107 }
108 return result, nil
109 }
110 }
111
View as plain text