Puppet Itemize

Count the number of types, classes, functions used in manifest(s)

Run this command with a space separated list of either manifest file paths, or directories containing manifests. If omitted, it will default to inspecting all manifests in the manifests directory, so you can just run this in the root of a Puppet module and it will do the right thing.

Installation

Install as either a gem:

$ gem install puppet-itemize

Or as a Puppet module:

$ puppet module install binford2k/itemize

Usage

Depending on how it's installed, there are two ways to run this. As the command line tool, puppet-itemize, or as the Puppet subcommand, puppet parser itemize. There are slight, but mostly insignificant differences in behaviour based on which way you run it.

Basically, just invoke the tool with a list of manifest(s), or directories of manifests, or just let it default to the ./manifests directory.

If you'd like machine parsable outputs, then use the --render-as flag and pass in a format of json or yaml.

Command-line examples:

Available when installed via either gem or Puppet module.

$ puppet-itemize
$ puppet-itemize manifests
$ puppet-itemize manifests/init.pp
$ puppet-itemize manifests/init.pp manifests/example/path.pp

Puppet subcommand examples:

Available only when installed via Puppet module.

$ puppet parser itemize
$ puppet parser itemize manifests
$ puppet parser itemize manifests/init.pp
$ puppet parser itemize manifests/init.pp manifests/example/path.pp

Module dependency validation

If the tool can identify that you're running this on manifests within a Puppet module, then it will validate the dependencies listed in the metadata.json. By default, it will print out warnings for resources or classes that come from modules that aren't declared as dependencies. Facts and Puppet 3.x style functions aren't namespaced in the same way, so they cannot be identified, but Puppet 4.x namespaced functions will trigger the same validation.

You can also use the --external argument. This will filter the output to only show elements which are either global or from other modules. This can be used to help identify how dependencies are being used.

Programatic use

You can choose to render the output in either JSON or YAML for consumption by other tools or testing pipelines by simply passing the --render-as argument:

$ puppet parser itemize ~/Projects/puppetlabs-apache/manifests/ --render-as json
$ puppet parser itemize ~/Projects/puppetlabs-apache/manifests/ --render-as yaml

It's also reasonably easy to invoke this as a library from Ruby tools. See the bin/puppet-itemize script for an example.

Example output:

Because this is static analysis prior to compilation, no variables can be resolved. Because of that, when a class name is calculated dynamically, any variable parts of the name will be represented as <??>. See an example of that below in the class list as apache::mod::<??>.

$ puppet parser itemize ~/Projects/puppetlabs-apache/manifests/
Warning: Undeclared module dependancy: portage::makeconf
Warning: Undeclared module dependancy: portage::makeconf
Warning: Undeclared module dependancy: portage::makeconf
Warning: Undeclared module dependancy: portage::makeconf
Warning: Undeclared module dependancy: portage::makeconf
Warning: Undeclared module dependancy: portage::makeconf
Warning: create_resources detected. Please update to use iteration instead.
Resource usage analysis:
=======================================
>> types:
                          concat |   3
                concat::fragment |  49
                            file |  81
                            exec |   8
                     apache::mod | 134
      apache::default_mods::load |   1
                         package |  11
                            user |   1
                           group |   1
               portage::makeconf |   8
                   apache::vhost |   3
                          anchor |   1
                     apache::mpm |   8
                       file_line |   3
                         yumrepo |   1
    apache::peruser::multiplexer |   1
     apache::security::rule_link |   1
                         service |   1
           apache::custom_config |   1

>> classes:
     apache::mod::proxy_balancer |   1
          apache::confd::no_accf |   1
               apache::mod::<??> |   2
         apache::mod::authn_core |   4
         apache::mod::reqtimeout |   2
            apache::mod::actions |   2
              apache::mod::cache |   2
         apache::mod::ext_filter |   1
               apache::mod::mime |   6
         apache::mod::mime_magic |   2
            apache::mod::rewrite |   3
            apache::mod::speling |   2
             apache::mod::suexec |   2
            apache::mod::version |   2
        apache::mod::vhost_alias |   3
         apache::mod::disk_cache |   1
            apache::mod::headers |   2
               apache::mod::info |   1
            apache::mod::userdir |   1
             apache::mod::filter |   5
                apache::mod::cgi |   1
               apache::mod::cgid |   1
              apache::mod::alias |   2
         apache::mod::authn_file |   1
          apache::mod::autoindex |   1
                apache::mod::dav |   2
             apache::mod::dav_fs |   1
            apache::mod::deflate |   1
                apache::mod::dir |   2
        apache::mod::negotiation |   1
           apache::mod::setenvif |   2
      apache::mod::authz_default |   1
         apache::mod::authz_user |   1
            apache::mod::fastcgi |   2
                 apache::service |   1
            apache::default_mods |   2
     apache::default_confd_files |   1
                          apache |  39
                apache::mod::dbd |   1
               apache::mod::ldap |   1
                     apache::dev |   1
            apache::mod::prefork |   1
              apache::mod::proxy |   4
         apache::mod::proxy_http |   2
                  apache::params |   2
      apache::mod::socache_shmcb |   1
                 apache::package |   1
                apache::mod::php |   1
             apache::mod::python |   1
                apache::mod::ssl |   2
          apache::mod::auth_kerb |   1
               apache::mod::wsgi |   1
          apache::mod::passenger |   3

>> functions:
                      versioncmp |  47
                 ensure_resource |   3
                 inline_template |   2
                        template |  94
                            fail |  58
                     validate_re |  20
                   validate_bool |  23
                        regsubst |   6
                         defined |  55
                is_absolute_path |   1
       validate_apache_log_level |   2
                         warning |  16
                        is_array |   9
                          concat |   2
          validate_absolute_path |   2
                            pick |  11
                 validate_string |   4
                  validate_array |   4
                        downcase |   4
                   validate_hash |   7
                       is_string |   2
                         has_key |   4
                         is_bool |   1
                           split |   2
                           empty |  20
                    enclose_ipv6 |   1
                          suffix |   2
                       any2array |   2
                         is_hash |   5
                           merge |   1
                create_resources |   1

Limitations

This is super early in development and has not yet been battle tested.

Disclaimer

I take no liability for the use of this tool.

Contact

[email protected]