From 0d668485789031f7e9ad02ac6f57f683b00872ed Mon Sep 17 00:00:00 2001 From: Lucas Bajolet Date: Thu, 14 Mar 2024 15:42:38 -0400 Subject: [PATCH] plugins: rely more on version lib for checks When discovering the installed plugins locally, we perform a couple of checks on the version, namely that it is valid, if it is a prerelease, it needs to be a dev, and that the self-reported version matches the one hinted at through the name of the binary. This was done through regexes, but those were a wee bit simple when dealing with versions that have metadata. Those binaries would be completely ignored by Packer, and never loaded, although they are a valid use case. The version library we already used supports those however, and comparisons are more reliable with them. So, in order to simplify our code, and make it more reliable, we're exclusively using this library to perform parsing and comparisons of versions during the discovery phase. --- packer/plugin-getter/plugins.go | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/packer/plugin-getter/plugins.go b/packer/plugin-getter/plugins.go index c18e7d1a1..fdfeaae7c 100644 --- a/packer/plugin-getter/plugins.go +++ b/packer/plugin-getter/plugins.go @@ -100,8 +100,6 @@ func (opts BinaryInstallationOptions) FilenameSuffix() string { return "_" + opts.OS + "_" + opts.ARCH + opts.Ext } -var pluginVersionRegex = regexp.MustCompile(`^v([0-9]+\.[0-9]+\.[0-9]+)(-dev)?$`) - // ListInstallations lists unique installed versions of plugin Requirement pr // with opts as a filter. // @@ -170,30 +168,35 @@ func (pr Requirement) ListInstallations(opts ListInstallationsOptions) (InstallL continue } - matches := pluginVersionRegex.FindStringSubmatch(pluginVersionStr) - if matches == nil { - log.Printf("invalid version found: %q, ignoring", pluginVersionStr) + rawVersion, err := version.NewVersion(pluginVersionStr) + if err != nil { + log.Printf("malformed version string in filename %q: %s, ignoring", pluginVersionStr, err) continue } - absVersion := matches[1] - if len(matches) == 3 { - absVersion = fmt.Sprintf("%s%s", absVersion, matches[2]) + descVersion, err := version.NewVersion(describeInfo.Version) + if err != nil { + log.Printf("malformed reported version string %q: %s, ignoring", describeInfo.Version, err) + continue } - if absVersion != describeInfo.Version { - log.Printf("plugin %q reported version %s while its name implies version %s, ignoring", path, describeInfo.Version, absVersion) + if rawVersion.Compare(descVersion) != 0 { + log.Printf("plugin %q reported version %q while its name implies version %q, ignoring", path, describeInfo.Version, pluginVersionStr) continue } - rawVersion, _ := version.NewVersion(matches[1]) + preRel := descVersion.Prerelease() + if preRel != "" && preRel != "dev" { + log.Printf("invalid plugin pre-release version %q, only development or release binaries are accepted", pluginVersionStr) + } + // no constraint means always pass, this will happen for implicit // plugin requirements and when we list all plugins. // // Note: we use the raw version name here, without the pre-release // suffix, as otherwise constraints reject them, which is not // what we want by default. - if !pr.VersionConstraints.Check(rawVersion) { + if !pr.VersionConstraints.Check(rawVersion.Core()) { log.Printf("[TRACE] version %q of file %q does not match constraint %q", pluginVersionStr, path, pr.VersionConstraints.String()) continue }