Merge pull request #1 from true-north-engineering/plugin-update--and-instal-version-handling

Updated plugin update and install to handle plugin versioning
pull/10971/head
Mihael Rodek 3 years ago committed by GitHub
commit 7a9d79f99b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -29,16 +29,22 @@ import (
) )
type pluginUpdateOptions struct { type pluginUpdateOptions struct {
names []string names map[string]string
version string
} }
const pluginUpdateDesc = `
This command allows you to update one or more Helm plugins.
`
func newPluginUpdateCmd(out io.Writer) *cobra.Command { func newPluginUpdateCmd(out io.Writer) *cobra.Command {
o := &pluginUpdateOptions{} o := &pluginUpdateOptions{}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "update <plugin>...", Use: "update <plugin:[version]>...",
Aliases: []string{"up"}, Aliases: []string{"up"},
Short: "update one or more Helm plugins", Short: "update one or more Helm plugins",
Long: pluginUpdateDesc,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compListPlugins(toComplete, args), cobra.ShellCompDirectiveNoFileComp return compListPlugins(toComplete, args), cobra.ShellCompDirectiveNoFileComp
}, },
@ -49,6 +55,7 @@ func newPluginUpdateCmd(out io.Writer) *cobra.Command {
return o.run(out) return o.run(out)
}, },
} }
cmd.Flags().StringVar(&o.version, "version", "", "specify a version constraint. If this is not specified, the latest version is installed")
return cmd return cmd
} }
@ -56,7 +63,14 @@ func (o *pluginUpdateOptions) complete(args []string) error {
if len(args) == 0 { if len(args) == 0 {
return errors.New("please provide plugin name to update") return errors.New("please provide plugin name to update")
} }
o.names = args o.names = make(map[string]string)
for _, arg := range args {
if strings.ContainsAny(arg, ":") {
o.names[arg[:strings.LastIndex(arg, ":")]] = arg[strings.LastIndex(arg, ":")+1:]
} else {
o.names[arg] = ""
}
}
return nil return nil
} }
@ -68,10 +82,9 @@ func (o *pluginUpdateOptions) run(out io.Writer) error {
return err return err
} }
var errorPlugins []string var errorPlugins []string
for name, version := range o.names {
for _, name := range o.names {
if found := findPlugin(plugins, name); found != nil { if found := findPlugin(plugins, name); found != nil {
if err := updatePlugin(found); err != nil { if err := updatePlugin(found, version); err != nil {
errorPlugins = append(errorPlugins, fmt.Sprintf("Failed to update plugin %s, got error (%v)", name, err)) errorPlugins = append(errorPlugins, fmt.Sprintf("Failed to update plugin %s, got error (%v)", name, err))
} else { } else {
fmt.Fprintf(out, "Updated plugin: %s\n", name) fmt.Fprintf(out, "Updated plugin: %s\n", name)
@ -86,7 +99,7 @@ func (o *pluginUpdateOptions) run(out io.Writer) error {
return nil return nil
} }
func updatePlugin(p *plugin.Plugin) error { func updatePlugin(p *plugin.Plugin, version string) error {
exactLocation, err := filepath.EvalSymlinks(p.Dir) exactLocation, err := filepath.EvalSymlinks(p.Dir)
if err != nil { if err != nil {
return err return err
@ -96,7 +109,7 @@ func updatePlugin(p *plugin.Plugin) error {
return err return err
} }
i, err := installer.FindSource(absExactLocation) i, err := installer.FindSource(absExactLocation, version)
if err != nil { if err != nil {
return err return err
} }

@ -75,8 +75,8 @@ func NewForSource(source, version string) (Installer, error) {
} }
// FindSource determines the correct Installer for the given source. // FindSource determines the correct Installer for the given source.
func FindSource(location string) (Installer, error) { func FindSource(location, version string) (Installer, error) {
installer, err := existingVCSRepo(location) installer, err := existingVCSRepo(location, version)
if err != nil && err.Error() == "Cannot detect VCS" { if err != nil && err.Error() == "Cannot detect VCS" {
return installer, errors.New("cannot get information about plugin source") return installer, errors.New("cannot get information about plugin source")
} }

@ -16,11 +16,11 @@ limitations under the License.
package installer // import "helm.sh/helm/v3/pkg/plugin/installer" package installer // import "helm.sh/helm/v3/pkg/plugin/installer"
import ( import (
"github.com/Masterminds/vcs"
"os" "os"
"sort" "sort"
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/Masterminds/vcs"
"github.com/pkg/errors" "github.com/pkg/errors"
"helm.sh/helm/v3/internal/third_party/dep/fs" "helm.sh/helm/v3/internal/third_party/dep/fs"
@ -35,14 +35,15 @@ type VCSInstaller struct {
base base
} }
func existingVCSRepo(location string) (Installer, error) { func existingVCSRepo(location, version string) (Installer, error) {
repo, err := vcs.NewRepo("", location) repo, err := vcs.NewRepo("", location)
if err != nil { if err != nil {
return nil, err return nil, err
} }
i := &VCSInstaller{ i := &VCSInstaller{
Repo: repo, Repo: repo,
base: newBase(repo.Remote()), Version: version,
base: newBase(repo.Remote()),
} }
return i, nil return i, nil
} }
@ -82,6 +83,8 @@ func (i *VCSInstaller) Install() error {
if err := i.setVersion(i.Repo, ref); err != nil { if err := i.setVersion(i.Repo, ref); err != nil {
return err return err
} }
} else if err := updateToLatest(i.Repo); err != nil {
return err
} }
if !isPlugin(i.Repo.LocalPath()) { if !isPlugin(i.Repo.LocalPath()) {
@ -98,7 +101,15 @@ func (i *VCSInstaller) Update() error {
if i.Repo.IsDirty() { if i.Repo.IsDirty() {
return errors.New("plugin repo was modified") return errors.New("plugin repo was modified")
} }
if err := i.Repo.Update(); err != nil { ref, err := i.solveVersion(i.Repo)
if err != nil {
return err
}
if ref != "" {
if err := i.setVersion(i.Repo, ref); err != nil {
debug(err.Error())
}
} else if err := updateToLatest(i.Repo); err != nil {
return err return err
} }
if !isPlugin(i.Repo.LocalPath()) { if !isPlugin(i.Repo.LocalPath()) {
@ -139,7 +150,6 @@ func (i *VCSInstaller) solveVersion(repo vcs.Repo) (string, error) {
if constraint.Check(v) { if constraint.Check(v) {
// If the constraint passes get the original reference // If the constraint passes get the original reference
ver := v.Original() ver := v.Original()
debug("setting to %s", ver)
return ver, nil return ver, nil
} }
} }
@ -174,3 +184,19 @@ func getSemVers(refs []string) []*semver.Version {
} }
return sv return sv
} }
func updateToLatest(repo vcs.Repo) error {
refs, err := repo.Tags()
if err != nil {
return err
}
debug("found refs: %s", refs)
// Convert and filter the list to semver.Version instances
semvers := getSemVers(refs)
// Sort semver list
sort.Sort(sort.Reverse(semver.Collection(semvers)))
latest := semvers[0].Original()
return repo.UpdateVersion(latest)
}

Loading…
Cancel
Save