All the development in Puppet should be done in modules, and each such module should serve as specific a purpose as possible. Most modules comprise only manifests. This suffices to provide very effective and readable node manifests that clearly and concisely express their intent by including aptly named classes and instantiating defined types.
Modules can also contain Puppet plugins in the form of resource types and providers, parser functions, or facts. All of these are usually Ruby code. External facts can be written in any language, though. Writing your own types and providers is not required, but it can boost your performance and management flexibility.
It is not necessary to write all your modules yourself. On the contrary, it's advisable to rely on the open source modules from the Puppet Forge as much as possible. The Puppet Forge is an ever-growing collection...