Issue #20997 has been updated by Andrew Parker.

Looking at that data structure, this is not the fault of the module tool. The 
interpretation of the response from the forge has to completely alter. Before 
the change the specification of that data structure could be stated as "a map 
of module name to the module's list of releases". That specification now no 
longer holds because there is now a special "module" ("_warnings") that isn't a 
module. Therefore any reasonable consumer of the API will no longer work now 
that "_warnings" has been introduced.

----------------------------------------
Bug #20997: `puppet module install` fails cryptically when served bad module 
information
https://projects.puppetlabs.com/issues/20997#change-91977

* Author: Adrien Thebo
* Status: In Topic Branch Pending Review
* Priority: Normal
* Assignee: 
* Category: module tool
* Target version: 
* Affected Puppet version: 3.0.0
* Keywords: 
* Branch: https://github.com/puppetlabs/puppet/pull/1684
----------------------------------------
If a Puppet module on the Forge has poorly formed metadata, querying for the 
module metadata can emit an extra field which breaks the Puppet module tool.

For instance, an early version of 
[adrien/pe_upgrade](http://forge.puppetlabs.com/adrien/pe_upgrade/0.1.0) had a 
malformed version specifier on a module dependency, using the Ruby Gems `'>= 
0'` specification instead of `'>= 0.0.0'`. When querying the module data from 
the forge, the following data is returned:

<pre>
{"adrien/pe_upgrade"=>
  [{"file"=>"/system/releases/a/adrien/adrien-pe_upgrade-0.4.0.tar.gz",
    "version"=>"0.4.0",
    "dependencies"=>
     [["nanliu/staging", "0.x"], ["puppetlabs/stdlib", ">= 2.5.1"]]},
   {"file"=>"/system/releases/a/adrien/adrien-pe_upgrade-0.4.2.tar.gz",
    "version"=>"0.4.2",
    "dependencies"=>
     [["nanliu/staging", "0.x"], ["puppetlabs/stdlib", ">= 2.5.1"]]}],
 "nanliu/staging"=>
  [{"file"=>"/system/releases/n/nanliu/nanliu-staging-0.1.0.tar.gz",
    "version"=>"0.1.0",
    "dependencies"=>[]},
   {"file"=>"/system/releases/n/nanliu/nanliu-staging-0.2.0.tar.gz",
    "version"=>"0.2.0",
    "dependencies"=>[]},
   {"file"=>"/system/releases/n/nanliu/nanliu-staging-0.2.1.tar.gz",
    "version"=>"0.2.1",
    "dependencies"=>[]},
   {"file"=>"/system/releases/n/nanliu/nanliu-staging-0.3.0.tar.gz",
    "version"=>"0.3.0",
    "dependencies"=>[]}],
 "puppetlabs/stdlib"=>
  [{"file"=>"/system/releases/p/puppetlabs/puppetlabs-stdlib-3.2.0.tar.gz",
    "version"=>"3.2.0",
    "dependencies"=>[]},
   {"file"=>"/system/releases/p/puppetlabs/puppetlabs-stdlib-4.1.0.tar.gz",
    "version"=>"4.1.0",
    "dependencies"=>[]}],
 "_warnings"=>
  ["Dependency nanliu/staging for module adrien/pe_upgrade had invalid version 
range \">= 0\"",
   "Dependency nanliu/staging for module adrien/pe_upgrade had invalid version 
range \">= 0\""]}
</pre>

(Metadata was truncated for brevity.)

When running `puppet module install adrien/pe_upgrade` this module metadata is 
fetched. 
https://github.com/puppetlabs/puppet/blob/3.0.0/lib/puppet/module_tool/shared_behaviors.rb#L34
 walks over this data structure, and it assumes that each entry in the hash is 
a key/value pair with the key being the module name and the value being an 
array of metadata for each version of that module. However the `_warnings` 
field only contains strings, which breaks the assumption that the PMT is making.

The the module tool is fetching this information it tries to fetch the version 
of the module 
(https://github.com/puppetlabs/puppet/blob/3.0.0/lib/puppet/module_tool/shared_behaviors.rb#L39).
 It assumes that the given value is a hash, tries to look up the version field, 
and if that fails then it falls back to using the SemVer `MIN` value.

There are three problems here:

  1. _warnings is not a module and shouldn't be treated as such when reading 
metadata
  1. The PMT shouldn't blindly rescue errors parsing the SemVer
  1. It's `SemVer::MIN`, not `SemVer.MIN`

For a long time the Puppet Forge would silently swallow errors with module 
metadata, but on May 23 it started handling that correctly and started emitting 
the `_warnings` field. Any module with malformed module

### Expected behavior

<pre>
puppet module install adrien/pe_upgrade --version 0.4.2
Notice: Preparing to install into /home/adrien/.puppet/modules ...
Notice: Downloading from https://forge.puppetlabs.com ...
Notice: Installing -- do not interrupt ...
Warning: Dependency nanliu/staging for module adrien/pe_upgrade had invalid 
version range ">= 0"
Warning: Dependency nanliu/staging for module adrien/pe_upgrade had invalid 
version range ">= 0"
/home/adrien/.puppet/modules
└─┬ adrien-pe_upgrade (v0.4.2)
  ├── nanliu-staging (v0.3.0)
  └── puppetlabs-stdlib (v4.1.0)
</pre>

### Actual behavior

<pre>
puppet module install adrien/pe_upgrade
Notice: Preparing to install into /home/adrien/.puppet/modules ...
Notice: Downloading from https://forge.puppetlabs.com ...
Error: undefined method `MIN' for SemVer:Class
Error: Try 'puppet help module install' for usage
</pre>

### Workaround

Installing the exact version of the faulty module works around this:

<pre>
puppet module install adrien/pe_upgrade --version 0.4.2
Notice: Preparing to install into /home/adrien/.puppet/modules ...
Notice: Downloading from https://forge.puppetlabs.com ...
Notice: Installing -- do not interrupt ...
/home/adrien/.puppet/modules
└─┬ adrien-pe_upgrade (v0.4.2)
  ├── nanliu-staging (v0.3.0)
  └── puppetlabs-stdlib (v4.1.0)
</pre>

- - -

#### Bonus stage:

The error message being emitted from the Forge is misleading:

    "Dependency nanliu/staging for module adrien/pe_upgrade had invalid version 
range ">= 0"

  1. adrien/pe_upgrade is the one with the invalid version range, not 
nanliu/staging
  1. the error message doesn't indicate which version of adrien/pe_upgrade has 
the bad version.


-- 
You have received this notification because you have either subscribed to it, 
or are involved in it.
To change your notification preferences, please click here: 
http://projects.puppetlabs.com/my/account

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Bugs" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/puppet-bugs?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to