Saturday, November 5, 2016

Cyclomatic Complexity - A puppet lint plugin by Danzilio

#vDM30in30 Post #4!

One of the awesome things to come out of the Contributor's summit was David Danzilio and Henrik Lindberg collobrating on an Assignment Branch Prediction algorithm for Puppet code.  David recently released it as a plugin for puppet-lint!

I recently gave a little micro-demo of the plugin at our local DevOps Meetup.

There are two ways to run the plugin:  gem install it and run the command, or add it to your Gemfile in your module, and it will automatically be added to your rspec lint check.

The problem that I had with demoing the plugin was that the warning/error threshold level could only be set in your Rakefile.  So I had two options... find a sufficintly complex module, or lower the complexity warning level in the Rakefile for an existing module.

Fortunatly, there exists a complex module in the voxpupuli ecosystem, puppet-staging!

$ git clone
$ cd puppet-staging
$ find ./ -name '*.pp' | xargs puppet-lint | grep 'branch condition'
./manifests/file.pp - WARNING: assignment branch condition size is 76.69 on line 0

./manifests/extract.pp - WARNING: assignment branch condition size is 47.37 on line 0

If you wanted to modify the module to include those checks, and set a lower complexity threshold, you can make changes similar to the below.

$ git diff
diff --git a/Gemfile b/Gemfile
index 0571378..31f4ffa 100644
--- a/Gemfile
+++ b/Gemfile
@@ -22,6 +22,7 @@ group :test do
   gem 'puppet-lint-classes_and_types_beginning_with_digits-check',  :require => false
   gem 'puppet-lint-unquoted_string-check',                          :require => false
   gem 'puppet-lint-variable_contains_upcase',                       :require => false
+  gem 'puppet-lint-metrics-check',                                  :require => false
   gem 'metadata-json-lint',                                         :require => false
   gem 'puppet-blacksmith',                                          :require => false
   gem 'voxpupuli-release',                                          :require => false, :git => ''
diff --git a/Rakefile b/Rakefile
index d00f247..0a00e25 100644
--- a/Rakefile
+++ b/Rakefile
@@ -18,6 +18,7 @@ exclude_paths = %w(
 PuppetLint.configuration.ignore_paths = exclude_paths
+PuppetLint.configuration.metrics_abc_warning = 1
 PuppetSyntax.exclude_paths = exclude_paths

 desc 'Run acceptance tests'

Which will result in the following output when you run rake lint

$ bundle exec rake lint
examples/deploy.pp:0:abc_size:WARNING:assignment branch condition size is 2.24
examples/extract.pp:0:abc_size:WARNING:assignment branch condition size is 11.66
examples/file.pp:0:abc_size:WARNING:assignment branch condition size is 7.07
examples/init.pp:0:abc_size:WARNING:assignment branch condition size is 1.0
examples/scope_defaults.pp:0:abc_size:WARNING:assignment branch condition size is 3.32
examples/staging_parse.pp:0:abc_size:WARNING:assignment branch condition size is 12.53
manifests/deploy.pp:0:abc_size:WARNING:assignment branch condition size is 24.37
manifests/extract.pp:0:abc_size:WARNING:assignment branch condition size is 47.37
manifests/file.pp:0:abc_size:WARNING:assignment branch condition size is 76.69
manifests/init.pp:0:abc_size:WARNING:assignment branch condition size is 6.71

manifests/params.pp:0:abc_size:WARNING:assignment branch condition size is 25.73

Overall, it is a good idea to start applying different ideas that have been historically present in software development to Infrastructure As Code.  Thinking about the complexity of our code gives you insight into the testability and maintainability of your codebase.

No comments:

Post a Comment