Matt,
I can't speak for exactly what John was implying, but I've been
working on something similar recently, and facing more or less the
same problems that you're implying below, so I'll give you my take
on it.
1) Yes, it means factoring "all" possibly-shared resources out
into discrete classes. The definition of "all" is flexible
depending on how fine-grained your package management needs to be,
and how willing you are to possibly have some "extra" packages
floating around.
2) Including modules from the Forge is another beast. At this
point, at $work, we're moving in the direction of *only* writing
our own modules if there isn't a suitable Forge module. So, we've
ended up with a few cases where we have two conflicting modules
that can't be used on the same node (usually a Forge module that
is intended to replace an older in-house module as it's phased
out).
The "proper" way to manage this is when you add a Forge module
that replaces existing functionality, you should remove any
existing declarations of those resources and replace them with a
require, or something like that.
A specific example... we recently started using the
puppetlabs-postgresql Forge module
(
https://github.com/puppetlabs/puppetlabs-postgresql/). It has a
postgresql::lib::python class that installs the python-psycopg2
package (the python postgres driver), and a postgresql::lib::devel
class that installs postgresql-devel. So, when we decided we were
going to use the new Forge module, we grepped through all of our
existing modules, and replaced any Package resources for these
packages with "require postgresql::lib::python" and "require
postgresql::lib::devel", respectively.
I assume I speak for many in saying that I hope that with the
ever-increasing usefulness of the Forge, the community begins to
converge on a single "canonical" module for a given use case or
package.
-jason antman