diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c9a5fae --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +Gemfile export-ignore +Berksfile export-ignore +Vagrantfile export-ignore +Thorfile export-ignore +Guardfile export-ignore +.gitattributes export-ignore +.gitignore export-ignore +.gitmodules export-ignore diff --git a/.gitignore b/.gitignore index 5598138..7fe508a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,57 @@ -metadata.json +# Ignore docs files +_gh_pages +_site +.ruby-version +.node-version +Gemfile.lock +# Numerous always-ignore extensions +*.diff +*.err +*.orig +*.log +*.rej +*.swo +*.swp +*.zip +*.vi +*~ + +# OS or Editor folders +.DS_Store +._* +Thumbs.db +.cache +.project +.settings +.tmproj +*.esproj +nbproject +*.sublime-project +*.sublime-workspace +.idea + +# Komodo +*.komodoproject +.komodotools + +# grunt-html-validation +validation-status.json +validation-report.json + +# Folders to ignore +bin +node_modules +tmp +vendor +.bundle + +# Chef specifics to ignore +.chef +.chefdk +.kitchen +.vagrant +Berksfile.lock +coverage/ +Policyfile.lock.json +nodes/ diff --git a/.kitchen.yml b/.kitchen.yml new file mode 100644 index 0000000..a9e0870 --- /dev/null +++ b/.kitchen.yml @@ -0,0 +1,19 @@ +--- +driver: + name: vagrant + +provisioner: + name: chef_zero + +platforms: + - name: ubuntu-14.04 + - name: ubuntu-12.04 + - name: ubuntu-10.04 + - name: centos-7.1 + - name: centos-6.7 + - name: centos-5.11 + +suites: + - name: default + run_list: + - recipe[collectd::default] diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..b4401c4 --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--default-path test/spec +--color diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..651a400 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,43 @@ +--- +AllCops: + Exclude: + - 'Guardfile' + - 'Rakefile' + - 'Vagrantfile' + - 'Policyfile.rb' + - 'Berksfile' + - 'Thorfile' + - 'Gemfile' + - 'test/**/*' + - 'bin/**' + - 'vendor/**/*' +AlignParameters: + Enabled: false +ClassLength: + Enabled: false +CyclomaticComplexity: + Enabled: false +Documentation: + Enabled: false +Encoding: + Enabled: false +Style/FileName: + Enabled: false +LineLength: + Enabled: false +MethodLength: + Enabled: false +Metrics/AbcSize: + Enabled: false +PerceivedComplexity: + Enabled: false +SingleSpaceBeforeFirstArg: + Enabled: false +Style/ClassAndModuleChildren: + Enabled: false +Style/FileName: + Enabled: false +Style/GuardClause: + Enabled: false +Style/PercentLiteralDelimiters: + Enabled: false diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3b2010c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +--- +language: ruby +sudo: false +notifications: + slack: bloomberg-rnd:eHp3Czg42iGzaTgG8sAFeD9v +script: bundle exec rake travis +rvm: + - 2.1 + - 2.2 +branches: + only: + - master +matrix: + fast_finish: true diff --git a/.yardopts b/.yardopts new file mode 100644 index 0000000..fed27a8 --- /dev/null +++ b/.yardopts @@ -0,0 +1,5 @@ +--plugin classmethods +--embed-mixin ClassMethods +--hide-api private +--markup markdown +--hide-void-return diff --git a/Berksfile b/Berksfile new file mode 100644 index 0000000..9099626 --- /dev/null +++ b/Berksfile @@ -0,0 +1,2 @@ +source 'https://supermarket.chef.io' +metadata diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..c978b2b --- /dev/null +++ b/Gemfile @@ -0,0 +1,44 @@ +source 'https://rubygems.org' +gem 'poise', '~> 2.2' +gem 'poise-service', '~> 1.0' +gem 'poise-boiler' + +group :lint do + gem 'rubocop' + gem 'foodcritic' +end + +group :kitchen_common do + gem 'test-kitchen', '~> 1.4' +end + +group :kitchen_vagrant do + gem 'kitchen-vagrant', '~> 0.19' +end + +group :kitchen_cloud do + gem 'kitchen-openstack', '~> 1.8' +end + +group :unit do + gem 'berkshelf' + gem 'chefspec' +end + +group :integration do + gem 'serverspec' +end + +group :development do + gem 'awesome_print' + gem 'guard' + gem 'guard-kitchen' + gem 'guard-rspec' + gem 'guard-rubocop' + gem 'rake' + gem 'stove' +end + +group :doc do + gem 'yard' +end diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000..d3e0d54 --- /dev/null +++ b/Guardfile @@ -0,0 +1,21 @@ +guard 'foodcritic', cookbook_paths: '.', cli: '-t ~FC023 -t ~FC005', all_on_start: false do + watch(%r{^(?:recipes|libraries|providers|resources)/.+\.rb$}) + watch('metadata.rb') +end + +# More info at https://github.com/guard/guard#readme +guard 'rubocop' do + watch(%r{^attributes/.+\.rb$}) + watch(%r{^providers/.+\.rb$}) + watch(%r{^recipes/.+\.rb$}) + watch(%r{^resources/.+\.rb$}) + watch(%r{^libraries/.+\.rb$}) + watch('metadata.rb') +end + +guard :rspec, cmd: 'bin/rspec', all_on_start: false, notification: false do + watch(%r{^(recipes|libraries|providers|resources)/(.+)\.rb$}) do |m| + "test/spec/#{m[0]}/#{m[1]}_spec.rb" + end + watch('test/spec/spec_helper.rb') { 'test/spec' } +end diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..efdfaec --- /dev/null +++ b/LICENSE @@ -0,0 +1,14 @@ +Copyright 2010, Atari, Inc +Copyright 2015, Bloomberg Finance L.P. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md index 10d7e5d..3f5373f 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,66 @@ -# DESCRIPTION # - -Configure and install the [collectd](http://collectd.org/) monitoring daemon. - -# REQUIREMENTS # - -This cookbook has only been tested on Ubuntu 10.04. - -To use the `collectd::collectd_web` recipe you need the [apache2](https://github.com/opscode/cookbooks/tree/master/apache2) cookbook. - -The [collectd_plugins](https://github.com/coderanger/chef-collectd_plugins) cookbook is not required, but provides many common plugin definitions for easy reuse. - -# ATTRIBUTES # - -* collectd.basedir - Base folder for collectd output data. -* collectd.plugin_dir - Base folder to find plugins. -* collectd.types_db - Array of files to read graph type information from. -* collectd.interval - Time period in seconds to wait between data reads. - -* collectd.collectd_web.path - Location to install collectd_web to. Defaults to /srv/collectd_web. -* collectd.collectd_web.hostname - Server name to use for collectd_web Apache site. - -# USAGE # - -Three main recipes are provided: - -* collectd - Install a standalone daemon. -* collectd::client - Install collectd and configure it to send data to a server. -* collectd::server - Install collectd and configure it to recieve data from clients. - -The client recipe will use the search index to automatically locate the server hosts, so no manual configuration is required. - -## Defines ## - -Several defines are provided to simplfy configuring plugins - -### collectd_plugin ### - -The `collectd_plugin` define configures and enables standard collect plugins. Example: - -```ruby -collectd_plugin "interface" do - options :interface=>"lo", :ignore_selected=>true -end -``` - -The options hash is converted to collectd-style settings automatically. Any symbol key will be converted to camel-case. In the above example :ignore_selected will be output as the -key "IgnoreSelected". If the key is already a string, this conversion is skipped. If the value is an array, it will be output as a separate line for each element. - -### collectd_python_plugin ### - -The `collectd_python_plugin` define configures and enables Python plugins using the collectd-python plugin. Example: - +# collectd-cookbook +[![Build Status](https://img.shields.io/travis/coderanger/chef-collectd.svg)](https://travis-ci.org/coderanger/chef-collectd) +[![Gem Version](https://img.shields.io/gem/v/poise.svg)](https://rubygems.org/gems/poise) +[![Cookbook Version](https://img.shields.io/cookbook/v/poise.svg)](https://supermarket.chef.io/cookbooks/poise) +[![Coverage](https://img.shields.io/codecov/c/github/coderanger/chef-collectd.svg)](https://codecov.io/github/coderanger/chef-collectd) +[![Gemnasium](https://img.shields.io/gemnasium/coderanger/chef-collectd.svg)](https://gemnasium.com/coderanger/chef-collectd) +[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +[Application cookbook][0] which installs and configures the +[collectd monitoring daemon][1]. + +This cookbook provides a dead-simple installation and configuration of +the collectd monitoring daemon. It provides two resources: the first +is for managing the collectd system service, and the second is for +configuring the daemon's plugins. Additionally, the +[collectd_plugins cookbook][4] may be used to configure many of the +common plugins that ship with the daemon. + +It is very important to note that distributions may ship different +major versions of the package, but the following platforms are tested +using the integration tests via [Test Kitchen][2]. +- Ubuntu ~> 10.04, 12.04, 14.04 +- CentOS ~> 5.8, 6.4, 7.1 +- RHEL ~> 5.8, 6.4, 7.1 + +## Basic Usage +The [default recipe](recipes/default.rb) in this cookbook simply +configures the monitoring daemon to run as a system service. The +configuration for this service can be tuned using the +[node attributes](attributes/default.rb). Additionally, a resource is +provided to configure plugins for the daemon. After a plugin has been +configured the daemon should be restarted. + +### Enabling Syslog +One of the simplest plugins to enable is the [collectd Syslog plugin][3] +which receives log messages from the daemon and dispatches them to the +to syslog. This allows the daemon's logs to easily integrate with +existing UNIX utilities. ```ruby -collectd_python_plugin "redis" do - options :host=>servers, :verbose=>true +collectd_plugin 'syslog' do + options do + log_level 'info' + notify_level 'OKAY' + end end ``` -Options are interpreted in the same way as with `collectd_plugin`. This define will not deploy the plugin script as well, so be sure to setup a cookbook_file resource -or other mechanism to handle distribution. Example: - +## Advanced Usage +In order to enable the full functionality of some of the more +intrusive collectd plugins the daemon will need to run as the root +user. Since this is obviously a security risk it is not the default. +To achieve this behavior you're required to write a +[wrapper cookbook][5] which overrides the service user with the proper +root user. ```ruby -cookbook_file File.join(node[:collectd][:plugin_dir], "redis.py") do - owner "root" - group "root" - mode "644" -end +node.default['collectd']['service_user'] = node['root_user'] +node.default['collectd']['service_group'] = node['root_group'] +include_recipe 'collectd::default' ``` -## Web frontend ## - -The `collectd::collectd_web` recipe will automatically deploy the [collectd_web](https://github.com/httpdss/collectd-web) frontend using Apache. The -[apache2](https://github.com/opscode/cookbooks/tree/master/apache2) cookbook is required for this and is *not* included automatically as this is an optional -component, so be sure to configure the node with the correct recipes. - -# LICENSE & AUTHOR # - -Author:: Noah Kantrowitz () -Copyright:: 2010, Atari, Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. +[0]: http://blog.vialstudios.com/the-environment-cookbook-pattern#theapplicationcookbook +[1]: https://collectd.org +[2]: https://github.com/test-kitchen/test-kitchen +[3]: https://collectd.org/wiki/index.php/Plugin:SysLog +[4]: https://github.com/coderanger/chef-collectd_plugins +[5]: http://blog.vialstudios.com/the-environment-cookbook-pattern/#thewrappercookbook diff --git a/Rakefile b/Rakefile new file mode 100755 index 0000000..a81d056 --- /dev/null +++ b/Rakefile @@ -0,0 +1,39 @@ +#!/usr/bin/env rake + +require 'bundler/setup' +require 'rspec/core/rake_task' +require 'rubocop/rake_task' +require 'foodcritic' +require 'kitchen' + +namespace :style do + desc 'Run Ruby style checks' + RuboCop::RakeTask.new(:ruby) + + desc 'Run Chef style checks' + FoodCritic::Rake::LintTask.new(:chef) +end + +desc 'Run all style checks' +task style: ['style:chef', 'style:ruby'] + +desc 'Run ChefSpec unit tests' +RSpec::Core::RakeTask.new(:unit) do |t| + t.pattern = 'test/spec/**{,/*/**}/*_spec.rb' +end + +# Integration tests. Kitchen.ci +desc 'Run Test Kitchen with Vagrant' +task :vagrant do + Kitchen.logger = Kitchen.default_file_logger + Kitchen::Config.new.instances.each do |instance| + instance.test(:always) + end +end + +desc 'Run style & unit tests on Travis' +task travis: %w(style unit) + +# Default +desc 'Run style, unit, and Vagrant-based integration tests' +task default: %w(style unit vagrant) diff --git a/attributes/default.rb b/attributes/default.rb index 0c81e17..a3ed947 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -1,28 +1,24 @@ # -# Cookbook Name:: collectd -# Attributes:: default +# Cookbook: collectd +# License: Apache 2.0 # -# Copyright 2010, Atari, Inc -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright 2010, Atari, Inc. +# Copyright 2015, Bloomberg Finance L.P. # +default['collectd']['service_name'] = 'collectd' +default['collectd']['service_user'] = 'collectd' +default['collectd']['service_group'] = 'collectd' -default[:collectd][:base_dir] = "/var/lib/collectd" -default[:collectd][:plugin_dir] = "/usr/lib/collectd" -default[:collectd][:types_db] = ["/usr/share/collectd/types.db"] -default[:collectd][:interval] = 10 -default[:collectd][:read_threads] = 5 -default[:collectd][:pkg_name] = "collectd-core" +if node['platform'] == 'ubuntu' + default['collectd']['service']['package_name'] = 'collectd-core' +else + default['collectd']['service']['package_name'] = 'collectd' +end -default[:collectd][:collectd_web][:path] = "/srv/collectd_web" -default[:collectd][:collectd_web][:hostname] = "collectd" +default['collectd']['service']['config_directory'] = '/etc/collectd.d' +default['collectd']['service']['configuration']['plugin_dir'] = '/usr/lib/collectd' +default['collectd']['service']['configuration']['types_d_b'] = '/usr/share/collectd/types.db' +default['collectd']['service']['configuration']['interval'] = 10 +default['collectd']['service']['configuration']['read_threads'] = 5 +default['collectd']['service']['configuration']['write_threads'] = 5 +default['collectd']['service']['configuration']['collect_internal_stats'] = true diff --git a/bin/berks b/bin/berks new file mode 100755 index 0000000..2d5e5fe --- /dev/null +++ b/bin/berks @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'berks' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('berkshelf', 'berks') diff --git a/bin/kitchen b/bin/kitchen new file mode 100755 index 0000000..a130b9b --- /dev/null +++ b/bin/kitchen @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'kitchen' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('test-kitchen', 'kitchen') diff --git a/bin/rspec b/bin/rspec new file mode 100755 index 0000000..0c86b5c --- /dev/null +++ b/bin/rspec @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'rspec' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('rspec-core', 'rspec') diff --git a/definitions/collectd_plugin.rb b/definitions/collectd_plugin.rb deleted file mode 100644 index 75c665f..0000000 --- a/definitions/collectd_plugin.rb +++ /dev/null @@ -1,52 +0,0 @@ -# -# Cookbook Name:: collectd -# Definition:: collectd_plugin -# -# Copyright 2010, Atari, Inc -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -define :collectd_plugin, :options => {}, :template => nil, :cookbook => nil do - template "/etc/collectd/plugins/#{params[:name]}.conf" do - owner "root" - group "root" - mode "644" - if params[:template].nil? - source "plugin.conf.erb" - cookbook params[:cookbook] || "collectd" - else - source params[:template] - cookbook params[:cookbook] - end - variables :name=>params[:name], :options=>params[:options] - notifies :restart, resources(:service => "collectd") - end -end - -define :collectd_python_plugin, :options => {}, :module => nil, :path => nil do - begin - t = resources(:template => "/etc/collectd/plugins/python.conf") - rescue ArgumentError,Chef::Exceptions::ResourceNotFound - collectd_plugin "python" do - options :paths=>[node[:collectd][:plugin_dir]], :modules=>{} - template "python_plugin.conf.erb" - cookbook "collectd" - end - retry - end - if not params[:path].nil? - t.variables[:options][:paths] << params[:path] - end - t.variables[:options][:modules][params[:module] || params[:name]] = params[:options] -end diff --git a/libraries/collectd_config.rb b/libraries/collectd_config.rb new file mode 100644 index 0000000..b65c70d --- /dev/null +++ b/libraries/collectd_config.rb @@ -0,0 +1,102 @@ +# +# Cookbook: collectd +# License: Apache 2.0 +# +# Copyright 2010, Atari, Inc. +# Copyright 2015, Bloomberg Finance L.P. +# +require 'poise' + +module CollectdCookbook + module Resource + # A resource which manages collectd daemon configurations. + # @since 1.0.0 + # @example + # collectd_config '/etc/collectd.conf' do + # configuration('read_threads' => 5, + # 'write_threads' => 5, + # 'interval' => 10 + # ) + # end + class CollectdConfig < Chef::Resource + include Poise(fused: true) + provides(:collectd_config) + + attribute(:path, kind_of: String, name_attribute: true) + attribute(:owner, kind_of: String, default: 'collectd') + attribute(:group, kind_of: String, default: 'collectd') + attribute(:mode, kind_of: String, default: '0644') + + attribute(:configuration, option_collector: true) + + # Produces collectd {configuration} elements from resource. + # @return [String] + def content + write_elements(configuration).concat("\n") + end + + # Converts from snake case to a camel case string. + # @param [String, Symbol] s + # @return [String] + def snake_to_camel(s) + s.to_s.split('_').map(&:capitalize).join('') + end + + # Recursively writes out configuration elements from + # {directives} and applies the appropriate {indent}. + # @param [Hash] directives + # @param [Integer] indent + # @return [String] + def write_elements(directives, indent = 0) + tabs = ("\t" * indent) + directives.dup.map do |key, value| + next if value.nil? + key = snake_to_camel(key) + if value.is_a?(Array) + value.map do |val| + if val.is_a?(String) + %(#{tabs}#{key} "#{val}") + else + %(#{tabs}#{key} #{val}) + end + end.join("\n") + elsif value.kind_of?(Hash) # rubocop:disable Style/ClassCheck + id = value.delete('id') + next if id.nil? + [%(#{tabs}<#{key} "#{id}">), + write_elements(value, indent.next), + %(#{tabs}) + ].join("\n") + elsif value.is_a?(String) + %(#{tabs}#{key} "#{value}") + else + %(#{tabs}#{key} #{value}) + end + end.flatten.join("\n") + end + + action(:create) do + notifying_block do + directory ::File.dirname(new_resource.path) do + recursive true + end + + file new_resource.path do + content new_resource.content + owner new_resource.owner + group new_resource.group + mode new_resource.mode + end + end + end + + action(:delete) do + notifying_block do + file new_resource.path do + action :delete + end + end + end + end + end +end diff --git a/libraries/collectd_plugin.rb b/libraries/collectd_plugin.rb new file mode 100644 index 0000000..f9ddf42 --- /dev/null +++ b/libraries/collectd_plugin.rb @@ -0,0 +1,82 @@ +# +# Cookbook: collectd +# License: Apache 2.0 +# +# Copyright 2010, Atari, Inc. +# Copyright 2015, Bloomberg Finance L.P. +# +require 'poise' + +module CollectdCookbook + module Resource + # A resource for managing collectd plugins. + # @since 2.0.0 + class CollectdPlugin < Chef::Resource + include Poise(fused: true) + provides(:collectd_plugin) + + # @!attribute plugin_name + # Name of the collectd plugin to install and configure. + # @return [String] + attribute(:plugin_name, kind_of: String, name_attribute: true) + + # @!attribute directory + # Name of directory where plugin configuration resides. Defaults to + # '/etc/collectd.d'. + # @return [String] + attribute(:directory, kind_of: String, default: '/etc/collectd.d') + + # @!attribute user + # User which the configuration for {#plugin_name} is owned by. + # Defaults to 'collectd.' + # @return [String] + attribute(:user, kind_of: String, default: 'collectd') + + # @!attribute group + # Group which the configuration for {#plugin_name} is owned by. + # Defaults to 'collectd.' + # @return [String] + attribute(:group, kind_of: String, default: 'collectd') + + # @!attribute options + # Set of key-value options to configure the plugin. + # @return [Hash, Mash] + attribute(:options, option_collector: true) + + # @return [String] + def config_filename + ::File.join(directory, "#{plugin_name}.conf") + end + + action(:create) do + notifying_block do + directory new_resource.directory do + recursive true + owner new_resource.user + group new_resource.group + mode '0755' + end + + collectd_config new_resource.config_filename do + owner new_resource.user + group new_resource.group + configuration( + 'load_plugin' => new_resource.plugin_name, + 'plugin' => { + 'id' => new_resource.plugin_name + }.merge(new_resource.options) + ) + end + end + end + + action(:delete) do + notifying_block do + collectd_config new_resource.config_filename do + action :delete + end + end + end + end + end +end diff --git a/libraries/collectd_plugin_file.rb b/libraries/collectd_plugin_file.rb new file mode 100644 index 0000000..78cc861 --- /dev/null +++ b/libraries/collectd_plugin_file.rb @@ -0,0 +1,93 @@ +# +# Cookbook: collectd +# License: Apache 2.0 +# +# Copyright 2015, Bloomberg Finance L.P. +# +require 'poise' + +module CollectdCookbook + module Resource + # A resource for managing collectd plugins. + # @since 2.0.0 + class CollectdPluginFile < Chef::Resource + include Poise(fused: true) + provides(:collectd_plugin_file) + + # @!attribute plugin_name + # Name of the collectd plugin to install and configure. + # @return [String] + attribute(:plugin_name, kind_of: String, name_attribute: true) + + # @!attribute plugin_instance_name + # Name of the plugin instance name + # @return [String] + attribute(:plugin_instance_name, kind_of: String) + + # @!attribute directory + # Name of directory where plugin configuration resides. Defaults to + # '/etc/collectd.d'. + # @return [String] + attribute(:directory, kind_of: String, default: '/etc/collectd.d') + + # @!attribute user + # User which the configuration for {#plugin_name} is owned by. + # Defaults to 'collectd.' + # @return [String] + attribute(:user, kind_of: String, default: 'collectd') + + # @!attribute group + # Group which the configuration for {#plugin_name} is owned by. + # Defaults to 'collectd.' + # @return [String] + attribute(:group, kind_of: String, default: 'collectd') + + # @!attribute cookbook + # The name of the cookbook where template file lives + # @return [String] + attribute(:cookbook, kind_of: String) + + # @!attribute source + # The name of the template file in templates directory + # @return [String] + attribute(:source, kind_of: String) + + # @!attribute variables + # A Hash of variables that are used to replace variables in the + # template file + attribute(:variables, kind_of: Hash) + + # @return [String] + def config_filename + ::File.join(directory, "#{plugin_name}_#{plugin_instance_name}.conf") + end + + action(:create) do + notifying_block do + directory new_resource.directory do + recursive true + owner new_resource.user + group new_resource.group + mode '0755' + end + + template new_resource.config_filename do + owner new_resource.user + group new_resource.group + cookbook new_resource.cookbook + source new_resource.source + variables new_resource.variables + end + end + end + + action(:delete) do + notifying_block do + collectd_config new_resource.config_filename do + action :delete + end + end + end + end + end +end diff --git a/libraries/collectd_service.rb b/libraries/collectd_service.rb new file mode 100644 index 0000000..7147428 --- /dev/null +++ b/libraries/collectd_service.rb @@ -0,0 +1,150 @@ +# +# Cookbook: collectd +# License: Apache 2.0 +# +# Copyright 2010, Atari, Inc. +# Copyright 2015, Bloomberg Finance L.P. +# +require 'poise_service/service_mixin' + +module CollectdCookbook + module Resource + # A resource for managing the collectd monitoring daemon. + # @since 2.0.0 + class CollectdService < Chef::Resource + include Poise + provides(:collectd_service) + include PoiseService::ServiceMixin + + attribute(:command, kind_of: String, default: lazy { default_command }) + + # @!attribute user + # User to run the collectd daemon as. Defaults to 'collectd.' + # @return [String] + attribute(:user, kind_of: String, default: 'collectd') + + # @!attribute group + # Group to run the collectd daemon as. Defaults to 'collectd.' + # @return [String] + attribute(:group, kind_of: String, default: 'collectd') + + # @!attribute directory + # The working directory for the service. Defaults to the data + # directory '/var/lib/collectd'. + # @return [String] + attribute(:directory, kind_of: String, default: '/var/lib/collectd') + + # @!attribute configuration_directory + # Name of directory where additional configurations reside. Defaults to + # '/etc/collectd.d'. + # @return [String] + attribute(:config_directory, kind_of: String, default: '/etc/collectd.d') + + # @!attribute config_filename + # The configuration file for the daemon service. Defaults to + # '/etc/collectd.conf'. + # @return [String] + attribute(:config_filename, kind_of: String, default: '/etc/collectd.conf') + + # @!attribute configuration + # Set of key-value options to write to {#config_filename}. + # @see {https://collectd.org/documentation/manpages/collectd.conf.5.shtml#global_options} + # @return [Hash, Mash] + attribute(:configuration, option_collector: true) + + # @!attribute package_name + # @return [String] + attribute(:package_name, kind_of: String, default: 'collectd') + + # @!attribute package_version + # @return [String] + attribute(:package_version, kind_of: String) + + # @!attribute package_source + # @return [String] + attribute(:package_source, kind_of: String) + + # @!attribute environment + # @return [String] + attribute(:environment, kind_of: Hash, default: { 'PATH' => '/usr/bin:/bin:/usr/sbin:/sbin' }) + + # @return [String] + def default_command + "/usr/sbin/collectd -C #{config_filename} -f" + end + end + end + + module Provider + # A provider for managing collectd daemon as a service. + # @since 2.0.0 + class CollectdService < Chef::Provider + include Poise + provides(:collectd_service) + include PoiseService::ServiceMixin + + def action_enable + notifying_block do + # TODO: (jbellone) Fix the package resource for AIX so that + # it is able to install from a URL. + package_path = if new_resource.package_source + url = new_resource.package_source % { version: new_resource.package_version } + basename = ::File.basename(url) + remote_file ::File.join(Chef::Config[:file_cache_path], basename) do + source url + end.path + end + + package new_resource.package_name do + provider Chef::Provider::Package::Dpkg if platform?('ubuntu') + provider Chef::Provider::Package::Solaris if platform?('solaris2') + action :upgrade + version new_resource.package_version + source package_path + notifies :restart, new_resource, :delayed + end + + [new_resource.directory, new_resource.config_directory].each do |dirname| + directory dirname do + recursive true + owner new_resource.user + group new_resource.group + mode '0755' + end + end + + collectd_config new_resource.config_filename do + owner new_resource.user + group new_resource.group + configuration new_resource.configuration.merge( + 'base_dir' => new_resource.directory, + 'include' => "#{new_resource.config_directory}/*.conf" + ) + notifies :restart, new_resource, :delayed + end + end + super + end + + def action_disable + notifying_block do + collectd_config new_resource.config_filename do + action :delete + end + end + super + end + + # Sets the tuning options for service management with {PoiseService::ServiceMixin}. + # @param [PoiseService::Service] service + def service_options(service) + service.command(new_resource.command) + service.environment(new_resource.environment) + service.directory(new_resource.directory) + service.user(new_resource.user) + service.environment(new_resource.environment) + service.restart_on_update(true) + end + end + end +end diff --git a/libraries/default.rb b/libraries/default.rb deleted file mode 100644 index 1f3e92b..0000000 --- a/libraries/default.rb +++ /dev/null @@ -1,47 +0,0 @@ -# -# Cookbook Name:: collectd -# Library:: default -# -# Copyright 2010, Atari, Inc -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -def collectd_key(option) - return option.to_s.split('_').map{|x| x.capitalize}.join() if option.instance_of?(Symbol) - "#{option}" -end - -def collectd_option(option) - return option if option.instance_of?(Fixnum) || option == true || option == false - "\"#{option}\"" -end - -def collectd_settings(options, level=0) - indent = ' ' * level - output = [] - options.each_pair do |key, value| - if value.is_a? Array - value.each do |subvalue| - output << "#{indent}#{collectd_key(key)} #{collectd_option(subvalue)}" - end - elsif value.is_a? Hash - value.each_pair do |name, suboptions| - output << "#{indent}<#{key} \"#{name}\">\n#{collectd_settings(suboptions, level+1)}\n#{indent}" - end - else - output << "#{indent}#{collectd_key(key)} #{collectd_option(value)}" - end - end - output.join("\n") -end diff --git a/metadata.rb b/metadata.rb index 3a0d763..d0847e3 100644 --- a/metadata.rb +++ b/metadata.rb @@ -1,8 +1,19 @@ -name "collectd" -maintainer "Noan Kantrowitz" -maintainer_email "noah@coderanger.net" -license "Apache 2.0" -description "Install and configure the collectd monitoring daemon" -long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version "1.0.0" -supports "ubuntu" +name 'collectd' +maintainer 'Noah Kantrowitz' +maintainer_email 'noah@coderanger.net' +license 'Apache 2.0' +description 'Installs and configures the collectd monitoring daemon.' +long_description 'Installs and configures the collectd monitoring daemon.' +version '2.1.3' +source_url 'https://github.com/bloomberg/collectd-cookbook' +issues_url 'https://github.com/bloomberg/collectd-cookbook/issues' + +supports 'ubuntu', '>= 10.04' +supports 'centos', '>= 5.8' +supports 'redhat', '>= 5.8' +supports 'aix' +supports 'solaris2' + +depends 'poise', '~> 2.2' +depends 'poise-service', '~> 1.0' +depends 'yum-epel' diff --git a/recipes/client.rb b/recipes/client.rb deleted file mode 100644 index d3b81dd..0000000 --- a/recipes/client.rb +++ /dev/null @@ -1,33 +0,0 @@ -# -# Cookbook Name:: collectd -# Recipe:: client -# -# Copyright 2010, Atari, Inc -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -include_recipe "collectd" - -servers = [] -search(:node, 'recipes:collectd\\:\\:server') do |n| - servers << n['fqdn'] -end - -if servers.empty? - raise "No servers found. Please configure at least one node with collectd::server." -end - -collectd_plugin "network" do - options :server=>servers -end diff --git a/recipes/collectd_web.rb b/recipes/collectd_web.rb deleted file mode 100644 index f0fd1a0..0000000 --- a/recipes/collectd_web.rb +++ /dev/null @@ -1,53 +0,0 @@ -# -# Cookbook Name:: collectd -# Recipe:: collectd_web -# -# Copyright 2010, Atari, Inc -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -include_recipe "collectd" -include_recipe "apache2" - -%w(libhtml-parser-perl liburi-perl librrds-perl libjson-perl).each do |name| - package name -end - -directory node[:collectd][:collectd_web][:path] do - owner "root" - group "root" - mode "755" -end - -bash "install_collectd_web" do - user "root" - cwd node[:collectd][:collectd_web][:path] - not_if do - File.exists?(File.join(node[:collectd][:collectd_web][:path], "index.html")) - end - code <<-EOH - wget --no-check-certificate -O collectd-web.tar.gz https://github.com/httpdss/collectd-web/tarball/master - tar --strip-components=1 -xzf collectd-web.tar.gz - rm collectd-web.tar.gz - EOH -end - -template "/etc/apache2/sites-available/collectd_web.conf" do - source "collectd_web.conf.erb" - owner "root" - group "root" - mode "644" -end - -apache_site "collectd_web.conf" diff --git a/recipes/default.rb b/recipes/default.rb index a34d2a8..9e03c36 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -1,89 +1,19 @@ # -# Cookbook Name:: collectd -# Recipe:: default +# Cookbook: collectd +# License: Apache 2.0 # -# Copyright 2010, Atari, Inc +# Copyright 2010, Atari, Inc. +# Copyright 2015, Bloomberg Finance L.P. # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package "collectd" do - package_name node[:collectd][:pkg_name] -end - -service "collectd" do - supports :restart => true, :status => true -end - -directory "/etc/collectd" do - owner "root" - group "root" - mode "755" -end - -directory "/etc/collectd/plugins" do - owner "root" - group "root" - mode "755" -end - -directory node[:collectd][:base_dir] do - owner "root" - group "root" - mode "755" - recursive true -end - -directory node[:collectd][:plugin_dir] do - owner "root" - group "root" - mode "755" - recursive true -end - -%w(collectd collection thresholds).each do |file| - template "/etc/collectd/#{file}.conf" do - source "#{file}.conf.erb" - owner "root" - group "root" - mode "644" - notifies :restart, resources(:service => "collectd") - end -end +include_recipe 'yum-epel::default' if platform_family?('redhat') -ruby_block "delete_old_plugins" do - block do - Dir['/etc/collectd/plugins/*.conf'].each do |path| - autogen = false - File.open(path).each_line do |line| - if line.start_with?('#') and line.include?('autogenerated') - autogen = true - break - end - end - if autogen - begin - resources(:template => path) - rescue ArgumentError, Chef::Exceptions::ResourceNotFound - # If the file is autogenerated and has no template it has likely been removed from the run list - Chef::Log.info("Deleting old plugin config in #{path}") - File.unlink(path) - end - end - end - end +poise_service_user node['collectd']['service_user'] do + group node['collectd']['service_group'] + not_if { node['collectd']['service_user'] == 'root' } end -service "collectd" do - action [:enable, :start] +collectd_service node['collectd']['service_name'] do |r| + user node['collectd']['service_user'] + group node['collectd']['service_group'] + node['collectd']['service'].each_pair { |k, v| r.send(k, v) } end diff --git a/recipes/server.rb b/recipes/server.rb deleted file mode 100644 index 08b6320..0000000 --- a/recipes/server.rb +++ /dev/null @@ -1,24 +0,0 @@ -# -# Cookbook Name:: collectd -# Recipe:: server -# -# Copyright 2010, Atari, Inc -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -include_recipe "collectd" - -collectd_plugin "network" do - options :listen=>'0.0.0.0' -end diff --git a/templates/default/collectd.conf.erb b/templates/default/collectd.conf.erb deleted file mode 100644 index b1e3964..0000000 --- a/templates/default/collectd.conf.erb +++ /dev/null @@ -1,18 +0,0 @@ -# Config file for collectd(1). -# -# Some plugins need additional configuration and are disabled by default. -# Please read collectd.conf(5) for details. -# -# You should also read /usr/share/doc/collectd/README.Debian.plugins before -# enabling any more plugins. - -Hostname "<%= @node[:fqdn] %>" -FQDNLookup true -BaseDir "<%= @node[:collectd][:base_dir] %>" -PluginDir "<%= @node[:collectd][:plugin_dir] %>" -TypesDB "<%= @node[:collectd][:types_db].join('", "') %>" -Interval <%= @node[:collectd][:interval] %> -ReadThreads <%= @node[:collectd][:read_threads] %> - -Include "/etc/collectd/plugins/*.conf" -Include "/etc/collectd/thresholds.conf" diff --git a/templates/default/collectd_web.conf.erb b/templates/default/collectd_web.conf.erb deleted file mode 100644 index a0757fc..0000000 --- a/templates/default/collectd_web.conf.erb +++ /dev/null @@ -1,32 +0,0 @@ - - ServerName <%= @node[:collectd][:collectd_web][:hostname] %> - - DocumentRoot <%= @node[:collectd][:collectd_web][:path] %> - - Options FollowSymLinks - AllowOverride None - - > - Options Indexes FollowSymLinks MultiViews - AllowOverride None - Order allow,deny - Allow from all - - - ScriptAlias /cgi-bin/ <%= @node[:collectd][:collectd_web][:path] %>/cgi-bin/ - /cgi-bin"> - AllowOverride None - Options ExecCGI -MultiViews - Order allow,deny - Allow from all - - - ErrorLog /var/log/apache2/error.log - - # Possible values include: debug, info, notice, warn, error, crit, - # alert, emerg. - LogLevel warn - - CustomLog /var/log/apache2/access.log combined - ServerSignature On - diff --git a/templates/default/collection.conf.erb b/templates/default/collection.conf.erb deleted file mode 100644 index a114511..0000000 --- a/templates/default/collection.conf.erb +++ /dev/null @@ -1,2 +0,0 @@ -datadir: "/var/lib/collectd/rrd/" -libdir: "/usr/lib/collectd/" diff --git a/templates/default/plugin.conf.erb b/templates/default/plugin.conf.erb deleted file mode 100644 index ac5a824..0000000 --- a/templates/default/plugin.conf.erb +++ /dev/null @@ -1,15 +0,0 @@ -# This file autogenerated by Chef -# Do not edit, changes will be overwritten -LoadPlugin "<%= @name %>" - -<% if not @options.empty? %> -"> - <% @options.each_pair do |key, value| - if value.is_a? Array - value.each do |subvalue| %> - <%= collectd_key(key) %> <%= collectd_option(subvalue) %> - <% end else %> - <%= collectd_key(key) %> <%= collectd_option(value) %> - <% end end %> - -<% end %> diff --git a/templates/default/python_plugin.conf.erb b/templates/default/python_plugin.conf.erb deleted file mode 100644 index 681d795..0000000 --- a/templates/default/python_plugin.conf.erb +++ /dev/null @@ -1,20 +0,0 @@ -# This file autogenerated by Chef -# Do not edit, changes will be overwritten - - Globals true - - - - <% @options[:paths].each do |path| %> - ModulePath "<%= path %>" - <% end %> - <% @options[:modules].each_key do |mod| %> - Import "<%= mod %>" - <% end %> - - <% @options[:modules].each_pair do |mod, config| %> - "> -<%= collectd_settings(config, 2) %> - - <% end %> - diff --git a/templates/default/thresholds.conf.erb b/templates/default/thresholds.conf.erb deleted file mode 100644 index 690d103..0000000 --- a/templates/default/thresholds.conf.erb +++ /dev/null @@ -1,37 +0,0 @@ -# Threshold configuration for collectd(1). -# -# See the section "THRESHOLD CONFIGURATION" in collectd.conf(5) for details. - -# -# -# WarningMin 0.00 -# WarningMax 1000.00 -# FailureMin 0 -# FailureMax 1200.00 -# Invert false -# Persist false -# Instance "some_instance" -# -# -# -# Instance "eth0" -# -# DataSource "rx" -# FailureMax 10000000 -# -# -# -# -# -# Instance "idle" -# FailureMin 10 -# -# -# -# -# Instance "cached" -# WarningMin 100000000 -# -# -# -# diff --git a/test/integration/default/serverspec/default_spec.rb b/test/integration/default/serverspec/default_spec.rb new file mode 100644 index 0000000..738b64c --- /dev/null +++ b/test/integration/default/serverspec/default_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe group('collectd') do + it { should exist } +end + +describe user('collectd') do + it { should exist } +end + +describe service('collectd') do + it { should be_enabled } + it { should be_running } +end + +describe file('/var/lib/collectd') do + it { should be_directory } + it { should be_owned_by 'collectd' } + it { should be_grouped_into 'collectd' } +end + +describe file('/etc/collectd.d') do + it { should be_directory } + it { should be_owned_by 'collectd' } + it { should be_grouped_into 'collectd' } +end + +describe file('/etc/collectd.conf') do + it { should be_file } + it { should be_owned_by 'collectd'} + it { should be_grouped_into 'collectd' } + it { should contain 'Interval 10' } + it { should contain 'ReadThreads 5' } + it { should contain 'WriteThreads 5' } + it { should_not contain 'Timeout' } + it { should_not contain 'WriteQueueLimitHigh' } + it { should_not contain 'WriteQueueLimitLow' } + it { should contain 'Include "/etc/collectd.d/*.conf"' } +end diff --git a/test/integration/helpers/serverspec/spec_helper.rb b/test/integration/helpers/serverspec/spec_helper.rb new file mode 100644 index 0000000..590c2fa --- /dev/null +++ b/test/integration/helpers/serverspec/spec_helper.rb @@ -0,0 +1,2 @@ +require 'serverspec' +set :backend, :exec diff --git a/test/spec/libraries/collectd_config_spec.rb b/test/spec/libraries/collectd_config_spec.rb new file mode 100644 index 0000000..71466e1 --- /dev/null +++ b/test/spec/libraries/collectd_config_spec.rb @@ -0,0 +1,61 @@ +require 'chefspec' +require 'chefspec/berkshelf' +require 'poise_boiler/spec_helper' +require_relative '../../../libraries/collectd_config' + +describe CollectdCookbook::Resource::CollectdConfig do + step_into(:collectd_config) + context '#snake_to_camel' do + recipe do + collectd_config '/etc/collectd.conf' do + configuration( + 'load_plugin' => 'foo', + 'format' => 'bar', + 'j_s_o_n' => 'baz' + ) + end + + it { expect(chef_run).to render_file('/etc/collectd.conf').with_content(<<-EOH.chomp) } +LoadPlugin "foo" +Format "bar" +JSON "baz" +EOH + end + end + + context '#write_elements' do + recipe do + collectd_config '/etc/collectd.conf' do + configuration('hash' => { + 'id' => 'id', + 'string' => 'string', + 'integer' => 1, + 'true_class' => true, + 'false_class' => false, + 'symbol' => :symbol, + 'array' => %w{1 2 3}, + 'hash' => { + 'id' => 'id', + 'string' => 'string' + } + }) + end + end + + it { expect(chef_run).to render_file('/etc/collectd.conf').with_content(<<-EOH.chomp) } + + String "string" + Integer 1 + TrueClass true + FalseClass false + Symbol symbol + Array "1" + Array "2" + Array "3" + + String "string" + + +EOH + end +end diff --git a/test/spec/libraries/collectd_plugin_spec.rb b/test/spec/libraries/collectd_plugin_spec.rb new file mode 100644 index 0000000..fa6afc4 --- /dev/null +++ b/test/spec/libraries/collectd_plugin_spec.rb @@ -0,0 +1,28 @@ +require 'chefspec' +require 'chefspec/berkshelf' +require 'poise_boiler/spec_helper' +require_relative '../../../libraries/collectd_plugin' + +describe CollectdCookbook::Resource::CollectdPlugin do + step_into(:collectd_plugin) + context 'enables syslog plugin' do + recipe do + collectd_plugin 'syslog' do + options do + log_level 'info' + end + end + end + + it do + expect(chef_run).to create_collectd_config('/etc/collectd.d/syslog.conf') + .with(configuration: { + 'load_plugin' => 'syslog', + 'plugin' => { + 'id' => 'syslog', + 'log_level' => 'info' + } + }) + end + end +end diff --git a/test/spec/libraries/collectd_service_spec.rb b/test/spec/libraries/collectd_service_spec.rb new file mode 100644 index 0000000..5801d77 --- /dev/null +++ b/test/spec/libraries/collectd_service_spec.rb @@ -0,0 +1,26 @@ +require 'chefspec' +require 'chefspec/berkshelf' +require 'poise_boiler/spec_helper' +require_relative '../../../libraries/collectd_service' + +describe CollectdCookbook::Resource::CollectdService do + step_into(:collectd_service) + context 'with default attributes' do + recipe do + collectd_service 'collectd' + end + + it do + expect(chef_run).to create_directory('/etc/collectd.d') + .with(owner: 'collectd', group: 'collectd', mode: '0755') + end + + it do + expect(chef_run).to create_collectd_config('/etc/collectd.conf') + .with(configuration: { + 'include' => '/etc/collectd.d/*.conf', + 'base_dir' => '/var/lib/collectd' + }) + end + end +end diff --git a/test/spec/recipes/default_spec.rb b/test/spec/recipes/default_spec.rb new file mode 100644 index 0000000..5f8680c --- /dev/null +++ b/test/spec/recipes/default_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe_recipe 'collectd::default' do + cached(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) } + it { expect(chef_run).to create_poise_service_user('collectd').with(group: 'collectd') } + it do + expect(chef_run).to enable_collectd_service('collectd') + .with(user: 'collectd') + .with(group: 'collectd') + end + + context 'with default attributes' do + it 'converges successfully' do + chef_run + end + end +end diff --git a/test/spec/spec_helper.rb b/test/spec/spec_helper.rb new file mode 100644 index 0000000..e31950c --- /dev/null +++ b/test/spec/spec_helper.rb @@ -0,0 +1,40 @@ +require 'chefspec' +require 'chefspec/berkshelf' +require 'chefspec/cacher' + +RSpec.configure do |config| + # Set default platform family and version for ChefSpec. + config.platform = 'redhat' + config.version = '6.4' + + config.color = true + config.alias_example_group_to :describe_recipe, type: :recipe + config.alias_example_group_to :describe_resource, type: :resource + + config.filter_run :focus + config.run_all_when_everything_filtered = true + + Kernel.srand config.seed + config.order = :random + + config.default_formatter = 'doc' if config.files_to_run.one? + + config.expect_with :rspec do |expectations| + expectations.syntax = :expect + end + + config.mock_with :rspec do |mocks| + mocks.syntax = :expect + mocks.verify_partial_doubles = true + end +end + +at_exit { ChefSpec::Coverage.report! } + +module ChefSpec::Macros + alias_method :described_resource, :described_recipe +end + +RSpec.shared_context 'recipe tests', type: :recipe do + let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) } +end