├── .foodcritic ├── .rspec ├── spec ├── support │ └── matchers.rb ├── spec_helper.rb └── unit │ └── recipes │ ├── default_spec.rb │ ├── t_resource_name_symbol_spec.rb │ ├── t_basic_spec.rb │ ├── t_basic_reversed_spec.rb │ ├── test_directories_spec.rb │ └── test_spec.rb ├── Berksfile ├── test └── integration │ ├── helpers │ └── serverspec │ │ └── spec_helper.rb │ └── default │ └── serverspec │ ├── default_spec.rb │ ├── test_directories_spec.rb │ └── test_spec.rb ├── .travis.yml ├── libraries └── matchers.rb ├── .gitignore ├── recipes ├── t_basic.rb ├── t_basic_reversed.rb ├── t_resource_name_symbol.rb ├── default.rb ├── test_directories.rb └── test.rb ├── .kitchen.yml ├── metadata.rb ├── .rubocop.yml ├── Gemfile ├── chefignore ├── resources └── default.rb ├── CHANGELOG.md ├── Rakefile ├── providers └── default.rb ├── README.md └── Gemfile.lock /.foodcritic: -------------------------------------------------------------------------------- 1 | ~FC023 2 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --require spec_helper 2 | -------------------------------------------------------------------------------- /spec/support/matchers.rb: -------------------------------------------------------------------------------- 1 | # Put your custom matchers here 2 | -------------------------------------------------------------------------------- /Berksfile: -------------------------------------------------------------------------------- 1 | source 'https://supermarket.chef.io' 2 | 3 | metadata 4 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'chefspec' 2 | require 'chefspec/berkshelf' 3 | require 'yarjuf' 4 | -------------------------------------------------------------------------------- /test/integration/helpers/serverspec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'serverspec' 2 | 3 | set :backend, :exec 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - '2.1.6' 4 | 5 | install: 6 | - bundle install --path vendor/bundler --without integration 7 | 8 | script: 9 | - bundle exec rake 10 | -------------------------------------------------------------------------------- /libraries/matchers.rb: -------------------------------------------------------------------------------- 1 | # ChefSpec matchers 2 | 3 | if defined?(ChefSpec) 4 | def clean_managed_directory(resource_name) 5 | ChefSpec::Matchers::ResourceMatcher.new(:managed_directory, :clean, resource_name) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | Berksfile.lock 3 | *~ 4 | *# 5 | .#* 6 | \#*# 7 | .*.sw[a-z] 8 | *.un~ 9 | pkg/ 10 | 11 | # Bundler 12 | Gemfile.lock 13 | bin/* 14 | .bundle/* 15 | 16 | .kitchen/ 17 | .kitchen.local.yml 18 | vendor/* 19 | tmp/* 20 | -------------------------------------------------------------------------------- /recipes/t_basic.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Recipe:: t_basic 4 | # 5 | # used by chefspec 6 | 7 | # Create a File resource for 'a' 8 | file '/tmp/foo/a' do 9 | action :touch 10 | end 11 | 12 | # Define the managed_directory 13 | managed_directory '/tmp/foo' do 14 | action :clean 15 | end 16 | -------------------------------------------------------------------------------- /recipes/t_basic_reversed.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Recipe:: t_basic_reversed 4 | # 5 | # used by chefspec 6 | 7 | # Define the managed_directory 8 | managed_directory '/tmp/foo' do 9 | action :clean 10 | end 11 | 12 | # Create a File resource for 'a' 13 | file '/tmp/foo/a' do 14 | action :touch 15 | end 16 | -------------------------------------------------------------------------------- /.kitchen.yml: -------------------------------------------------------------------------------- 1 | driver: 2 | name: vagrant 3 | 4 | provisioner: 5 | name: chef_zero 6 | 7 | platforms: 8 | - name: centos-6.6 9 | # - name: ubuntu-14.04 10 | 11 | suites: 12 | - name: default 13 | run_list: 14 | - recipe[managed_directory::test] 15 | - recipe[managed_directory::test_directories] 16 | attributes: 17 | -------------------------------------------------------------------------------- /metadata.rb: -------------------------------------------------------------------------------- 1 | name "managed_directory" 2 | maintainer "Zachary Stevens" 3 | maintainer_email "zts@cryptocracy.com" 4 | license "Apache 2.0" 5 | description "Provides the managed_directory resource" 6 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) 7 | source_url 'https://github.com/zts/chef-cookbook-managed_directory' 8 | issues_url 'https://github.com/zts/chef-cookbook-managed_directory/issues' 9 | version "0.2.1" 10 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AlignParameters: 2 | Enabled: false 3 | ClassAndModuleChildren: 4 | Enabled: false 5 | Encoding: 6 | Enabled: false 7 | SingleSpaceBeforeFirstArg: 8 | Enabled: false 9 | LineLength: 10 | Max: 200 11 | NumericLiterals: 12 | Enabled: false 13 | HashSyntax: 14 | Enabled: false 15 | # EnforcedStyle: hash_rockets 16 | AllCops: 17 | Exclude: 18 | - Rakefile 19 | - Gemfile 20 | - Guardfile 21 | - Vagrantfile 22 | - metadata.rb 23 | - spec/**/* 24 | - vendor/**/* 25 | -------------------------------------------------------------------------------- /recipes/t_resource_name_symbol.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Recipe:: t_resource_name_symbol 4 | # 5 | # used by chefspec 6 | 7 | testdir = '/tmp/baz' 8 | 9 | # Create the directory for our test files, during the compile phase. 10 | directory testdir do 11 | action :nothing 12 | end.run_action(:create) 13 | 14 | # Define the managed_directory 15 | managed_directory testdir do 16 | action :clean 17 | end 18 | 19 | log :test do 20 | message 'LOG: t_resource_name_symbol test.' 21 | end 22 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # This is primarily here for the CI server, so that it can create 2 | # the necessary environment to run the tests in. If you are using ChefDK, 3 | # you do not need to run `bundle install`, as all these tools are already 4 | # included (via `chef exec`) 5 | 6 | source 'https://rubygems.org' 7 | 8 | gem 'berkshelf' 9 | gem 'semverse' 10 | gem 'chef' 11 | gem 'chef-zero' 12 | gem 'foodcritic' 13 | gem 'rake-chef-syntax' 14 | gem 'chefspec' 15 | gem 'rubocop' 16 | gem 'stove' 17 | gem 'yarjuf' 18 | 19 | group :integration do 20 | gem 'test-kitchen' 21 | gem 'kitchen-vagrant' 22 | gem 'kitchen-docker' 23 | end 24 | -------------------------------------------------------------------------------- /test/integration/default/serverspec/default_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'managed_directory::default' do 4 | # Serverspec examples can be found at 5 | # http://serverspec.org/resource_types.html 6 | 7 | # if %w(linux redhat fedora ubuntu debian).include?(os[:family]) 8 | # # Tests for Linux 9 | # it 'does something in linux' do 10 | # skip 'Replace this with meaningful tests' 11 | # end 12 | # 13 | # elsif %w(windows).include?(os[:family]) 14 | # # Tests for Windows 15 | # it 'does something in windows' do 16 | # skip 'Replace this with meaningful tests' 17 | # end 18 | # end 19 | end 20 | -------------------------------------------------------------------------------- /recipes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Recipe:: default 4 | # 5 | # Copyright 2012, Zachary Stevens 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | -------------------------------------------------------------------------------- /spec/unit/recipes/default_spec.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Spec:: default 4 | # 5 | # Copyright (c) 2015 The Authors, All Rights Reserved. 6 | 7 | require 'spec_helper' 8 | 9 | describe 'managed_directory::default' do 10 | context 'When all attributes are default, on CentOS 6.6' do 11 | let(:chef_run) do 12 | runner = ChefSpec::SoloRunner.new( 13 | platform: 'centos', 14 | version: '6.6' 15 | ) do |node| 16 | # Set/override attributes here 17 | # node.automatic['virtualization']['role'] = 'guest' 18 | end 19 | runner.converge(described_recipe) 20 | end 21 | 22 | it 'converges successfully' do 23 | chef_run # This should not raise an error 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /test/integration/default/serverspec/test_directories_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'managed_directory::test_directories' do 4 | # Serverspec examples can be found at 5 | # http://serverspec.org/resource_types.html 6 | 7 | if %w(linux redhat fedora ubuntu debian).include?(os[:family]) 8 | # Tests for Linux 9 | describe file('/tmp/bar/a_dir') do 10 | it { should be_directory } 11 | end 12 | 13 | describe file('/tmp/bar/b_dir') do 14 | it { should be_directory } 15 | end 16 | 17 | describe file('/tmp/bar/c_dir') do 18 | it { should_not be_directory } 19 | end 20 | 21 | elsif %w(windows).include?(os[:family]) 22 | # Tests for Windows 23 | it 'does something in windows' do 24 | skip 'Replace this with meaningful tests' 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/unit/recipes/t_resource_name_symbol_spec.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Spec:: t_resource_name_symbol 4 | # 5 | # Copyright (c) 2015 The Authors, All Rights Reserved. 6 | 7 | require 'spec_helper' 8 | 9 | describe 'managed_directory::t_resource_name_symbol' do 10 | context 'When all attributes are default, on CentOS 6.6' do 11 | let(:chef_run) do 12 | runner = ChefSpec::SoloRunner.new( 13 | step_into: ['managed_directory'], 14 | platform: 'centos', 15 | version: '6.6' 16 | ) do |node| 17 | # Set/override attributes here 18 | end 19 | runner.converge(described_recipe) 20 | end 21 | 22 | before(:each) do 23 | allow(Dir).to receive(:glob).and_call_original 24 | allow(Dir).to receive(:glob).with('/tmp/foo/*').and_return(['/tmp/foo/a']) 25 | end 26 | 27 | it 'converges successfully' do 28 | chef_run # This should not raise an error 29 | end 30 | 31 | it 'should log a test message' do 32 | expect(chef_run).to write_log('LOG: t_resource_name_symbol test.') 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /test/integration/default/serverspec/test_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'managed_directory::test' do 4 | # Serverspec examples can be found at 5 | # http://serverspec.org/resource_types.html 6 | 7 | if %w(linux redhat fedora ubuntu debian).include?(os[:family]) 8 | # Tests for Linux 9 | describe file('/tmp/foo/a') do 10 | it { should be_file } 11 | end 12 | 13 | describe file('/tmp/foo/a_link') do 14 | it { should be_file } 15 | it { should be_linked_to '/tmp/foo/a' } 16 | end 17 | 18 | describe file('/tmp/foo/b') do 19 | it { should be_file } 20 | end 21 | 22 | describe file('/tmp/foo/b_link') do 23 | it { should_not be_file } 24 | end 25 | 26 | describe file('/tmp/foo/c') do 27 | it { should_not be_file } 28 | end 29 | 30 | describe file('/tmp/foo/d') do 31 | it { should be_file } 32 | end 33 | 34 | describe file('/tmp/foo/c_dir') do 35 | it { should be_directory } 36 | end 37 | 38 | elsif %w(windows).include?(os[:family]) 39 | # Tests for Windows 40 | it 'does something in windows' do 41 | skip 'Replace this with meaningful tests' 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /chefignore: -------------------------------------------------------------------------------- 1 | # Put files/directories that should be ignored in this file when uploading 2 | # or sharing to the community site. 3 | # Lines that start with '# ' are comments. 4 | 5 | # OS generated files # 6 | ###################### 7 | .DS_Store 8 | Icon? 9 | nohup.out 10 | ehthumbs.db 11 | Thumbs.db 12 | 13 | # SASS # 14 | ######## 15 | .sass-cache 16 | 17 | # EDITORS # 18 | ########### 19 | \#* 20 | .#* 21 | *~ 22 | *.sw[a-z] 23 | *.bak 24 | REVISION 25 | TAGS* 26 | tmtags 27 | *_flymake.* 28 | *_flymake 29 | *.tmproj 30 | .project 31 | .settings 32 | mkmf.log 33 | 34 | ## COMPILED ## 35 | ############## 36 | a.out 37 | *.o 38 | *.pyc 39 | *.so 40 | *.com 41 | *.class 42 | *.dll 43 | *.exe 44 | */rdoc/ 45 | 46 | # Testing # 47 | ########### 48 | .watchr 49 | .rspec 50 | spec/* 51 | spec/fixtures/* 52 | test/* 53 | features/* 54 | Guardfile 55 | Procfile 56 | 57 | # SCM # 58 | ####### 59 | .git 60 | */.git 61 | .gitignore 62 | .gitmodules 63 | .gitconfig 64 | .gitattributes 65 | .svn 66 | */.bzr/* 67 | */.hg/* 68 | */.svn/* 69 | 70 | # Berkshelf # 71 | ############# 72 | Berksfile 73 | Berksfile.lock 74 | cookbooks/* 75 | tmp 76 | 77 | # Cookbooks # 78 | ############# 79 | CONTRIBUTING 80 | 81 | # Strainer # 82 | ############ 83 | Colanderfile 84 | Strainerfile 85 | .colander 86 | .strainer 87 | 88 | # Vagrant # 89 | ########### 90 | .vagrant 91 | Vagrantfile 92 | 93 | # Travis # 94 | ########## 95 | .travis.yml 96 | -------------------------------------------------------------------------------- /resources/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Provider:: default 4 | # 5 | # Copyright 2012, Zachary Stevens 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | # Implement a single action, and make that the default. 21 | actions :clean 22 | 23 | def initialize(*args) 24 | super 25 | @action = :clean 26 | end 27 | 28 | # Path of the directory we'll manage. 29 | attribute :path, :kind_of => String, :name_attribute => true 30 | 31 | # Should we clean files out of our managed directory? Default, yes 32 | attribute :clean_files, :kind_of => [TrueClass, FalseClass], :default => true 33 | 34 | # Should we clean links out of our managed directory? Default, yes 35 | attribute :clean_links, :kind_of => [TrueClass, FalseClass], :default => true 36 | 37 | # Should we clean subdirectories out of our managed directory? Default, no 38 | attribute :clean_directories, :kind_of => [TrueClass, FalseClass], :default => false 39 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | MANAGED_DIRECTORY CHANGELOG 2 | =========================== 3 | 4 | This file is used to list changes made in each version of the managed_directory cookbook. 5 | 6 | v0.2.1 7 | ------ 8 | - Fix bug for subdirectories when clean_directories is false. This would cause 9 | the subdirectory to be handed to the `file` resource in the provider, which 10 | would then cause chef-client to abort. 11 | 12 | v0.2.0 13 | ------ 14 | - Added cleaning of subdirectories 15 | - Added separate handling of links, which were formerly handled by the file 16 | resource, as managing links via file resources is deprecated 17 | - Added attributes to control handling of files, directories and links 18 | - `clean_files` and `clean_links` default to `true` to preserve existing 19 | behavior 20 | - `clean_directories` defaults to `false` to preserve existing behavior 21 | - Updated tests to current ChefSpec and ServerSpec, following examples from 22 | ChefDK's `chef generate cookbook` output 23 | - Updated Test Kitchen to current CentOS (6.6) 24 | - Updated README.md for new behaviors 25 | - Added ChefSpec matchers for test-ability 26 | 27 | v0.1.0 28 | ----- 29 | - add chefspec tests 30 | - FIX don't blow up when resource names are symbols 31 | - Thanks to Mark Friedgan (hubrix) for this fix. 32 | 33 | - - - 34 | Check the [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax) for help with Markdown. 35 | 36 | The [Github Flavored Markdown page](http://github.github.com/github-flavored-markdown/) describes the differences between markdown on github and standard markdown. 37 | -------------------------------------------------------------------------------- /recipes/test_directories.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Recipe:: test 4 | # 5 | # A simple demonstration of managed_directory, also used by chefspec. 6 | 7 | testdir = '/tmp/bar' 8 | 9 | # Setup the test. 10 | # 1. Create the directory for our test files, during the compile phase. 11 | directory testdir do 12 | action :nothing 13 | end.run_action(:create) 14 | 15 | # 2. Put some files in it, without using Chef, before convergence 16 | unless defined?(ChefSpec) 17 | %w(a b c).each do |d| 18 | Chef::Log.warn("Creating test directory #{testdir}/#{d}_dir") 19 | ::Dir.mkdir("#{testdir}/#{d}_dir") unless ::Dir.exist?("#{testdir}/#{d}_dir") 20 | end 21 | # stuff some files into c_dir 22 | %w(a b c).each do |f| 23 | Chef::Log.warn("Creating test file #{testdir}/c_dir/#{f}") 24 | ::File.new("#{testdir}/c_dir/#{f}", 'w+') unless ::File.exist?("#{testdir}/c_dir/#{f}") 25 | end 26 | end 27 | 28 | # Create a directory resource for 'a_dir' 29 | directory "#{testdir}/a_dir" do 30 | action :create 31 | end 32 | 33 | # Define the managed_directory and have it clean directories, too 34 | managed_directory testdir do 35 | action :clean 36 | clean_directories true 37 | clean_files false 38 | end 39 | 40 | # Create a directory resource for 'b_dir' 41 | # Note that the order of resources doesn't matter - managed_directory will 42 | # not clean up this file. 43 | directory "#{testdir}/b_dir" do 44 | action :create 45 | end 46 | 47 | # At the end of a Chef run containing this recipe, /tmp/foo should contain 48 | # subdirectories "a_dir" and "b_dir". Subdirectory "c_dir" should have been 49 | # removed. 50 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | require 'rubocop/rake_task' 3 | require 'foodcritic' 4 | require 'rspec/core/rake_task' 5 | require 'stove/rake_task' 6 | require 'chef/knife' 7 | 8 | desc 'Run all tests except Kitchen (default task)' 9 | task integration: [:rubocop, :foodcritic, :spec] 10 | task default: :integration 11 | 12 | desc 'Run linters' 13 | task lint: [:rubocop, :foodcritic] 14 | 15 | desc 'Run all tests' 16 | task test: [:integration, :acceptance] 17 | 18 | # ChefSpec 19 | desc 'Run ChefSpec tests' 20 | task :spec do 21 | puts 'Running chefspec tests...' 22 | RSpec::Core::RakeTask.new(:spec) do |t| 23 | # t.rspec_opts = %w[-f JUnit -o results.xml] 24 | t.rspec_opts = %w[--color] 25 | end 26 | end 27 | 28 | # Foodcritic 29 | desc 'Run foodcritic lint checks' 30 | task :foodcritic do 31 | puts 'Running foodcritic...' 32 | FoodCritic::Rake::LintTask.new do |t| 33 | t.options = { :fail_tags => ["correctness"] } 34 | puts 'done.' 35 | end 36 | end 37 | 38 | # Rubocop 39 | desc 'Run Rubocop lint checks' 40 | task :rubocop do 41 | RuboCop::RakeTask.new 42 | end 43 | 44 | # Test Kitchen 45 | begin 46 | require 'kitchen/rake_tasks' 47 | Kitchen::RakeTasks.new 48 | 49 | desc 'Alias for kitchen:all' 50 | task acceptance: 'kitchen:all' 51 | 52 | rescue LoadError 53 | puts '>>>>> Kitchen gem not loaded, omitting tasks' # unless ENV['CI'] 54 | end 55 | 56 | desc 'Release and Publish' 57 | task :release do 58 | if File.exist?("#{ENV['HOME']}/.stove") 59 | require 'stove/rake_task' 60 | Stove::RakeTask.new(:release) 61 | else 62 | puts "Please use 'stove login' before attempting to release." 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /recipes/test.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Recipe:: test 4 | # 5 | # A simple demonstration of managed_directory, also used by chefspec. 6 | 7 | testdir = '/tmp/foo' 8 | 9 | # Setup the test. 10 | # 1. Create the directory for our test files, during the compile phase. 11 | directory testdir do 12 | action :nothing 13 | end.run_action(:create) 14 | 15 | # 2. Put some files in it, without using Chef, before convergence 16 | unless defined?(ChefSpec) 17 | %w(a b c d e).each do |f| 18 | Chef::Log.warn("Creating test file #{testdir}/#{f}") 19 | ::File.new("#{testdir}/#{f}", 'w+') unless ::File.exist?("#{testdir}/#{f}") 20 | end 21 | 22 | Chef::Log.warn("Creating test symlink #{testdir}/b_link to #{testdir}/b") 23 | ::File.symlink("#{testdir}/b", "#{testdir}/b_link") unless ::File.exist?("#{testdir}/b_link") 24 | 25 | Chef::Log.warn("Creating test directory #{testdir}/c_dir") 26 | ::Dir.mkdir("#{testdir}/c_dir") unless ::Dir.exist?("#{testdir}/c_dir") 27 | end 28 | 29 | # Create a File resource for 'a' 30 | file "#{testdir}/a" do 31 | action :touch 32 | end 33 | 34 | link "#{testdir}/a_link" do 35 | action :create 36 | to "#{testdir}/a" 37 | link_type :symbolic 38 | end 39 | 40 | # Define the managed_directory 41 | managed_directory testdir do 42 | action :clean 43 | end 44 | 45 | # Create a File resource for 'b' 46 | # Note that the order of resources doesn't matter - managed_directory will 47 | # not clean up this file. 48 | file "#{testdir}/b" do 49 | action :touch 50 | end 51 | 52 | # Create a File resource for 'd' by using the `path` method and 53 | # having the resource name itself not match our managed_directory path. 54 | file 'named_file_resource' do 55 | path "#{testdir}/d" 56 | action :touch 57 | end 58 | 59 | # At the end of a Chef run containing this recipe, /tmp/foo should contain 60 | # files "a", "b", and "d" and symbolic link "a_link". File "c" and symlink 61 | # "b_link" will have been removed. 62 | -------------------------------------------------------------------------------- /spec/unit/recipes/t_basic_spec.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Spec:: default 4 | # 5 | # Copyright (c) 2015 The Authors, All Rights Reserved. 6 | 7 | require 'spec_helper' 8 | 9 | describe 'managed_directory::t_basic' do 10 | context 'When all attributes are default, on CentOS 6.6' do 11 | let(:chef_run) do 12 | runner = ChefSpec::SoloRunner.new( 13 | step_into: ['managed_directory'], 14 | platform: 'centos', 15 | version: '6.6' 16 | ) do |node| 17 | # Set/override attributes here 18 | end 19 | runner.converge(described_recipe) 20 | end 21 | 22 | before(:each) do 23 | allow(Dir).to receive(:glob).and_call_original 24 | end 25 | 26 | describe 'given only file a' do 27 | before(:each) do 28 | allow(Dir).to receive(:glob).with('/tmp/foo/*').and_return(['/tmp/foo/a']) 29 | end 30 | it 'should not remove file a' do 31 | expect(chef_run).to_not delete_file('/tmp/foo/a') 32 | end 33 | end 34 | 35 | describe 'given file b' do 36 | before(:each) do 37 | allow(Dir).to receive(:glob).with('/tmp/foo/*').and_return(['/tmp/foo/b']) 38 | end 39 | 40 | it 'should remove file b' do 41 | expect(chef_run).to delete_file '/tmp/foo/b' 42 | end 43 | end 44 | 45 | describe 'given files a and b' do 46 | before(:each) do 47 | allow(Dir).to receive(:glob).with('/tmp/foo/*').and_return(['/tmp/foo/a','/tmp/foo/b']) 48 | end 49 | 50 | it 'should not remove file a' do 51 | expect(chef_run).to_not delete_file '/tmp/foo/a' 52 | end 53 | 54 | it 'should remove file b' do 55 | expect(chef_run).to delete_file '/tmp/foo/b' 56 | end 57 | end 58 | 59 | describe 'given no files' do 60 | before(:each) do 61 | allow(Dir).to receive(:glob).with('/tmp/foo/*').and_return([]) 62 | end 63 | 64 | it 'should not remove file a' do 65 | expect(chef_run).to_not delete_file '/tmp/foo/a' 66 | end 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /spec/unit/recipes/t_basic_reversed_spec.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Spec:: default 4 | # 5 | # Copyright (c) 2015 The Authors, All Rights Reserved. 6 | 7 | require 'spec_helper' 8 | 9 | describe 'managed_directory::t_basic_reversed' do 10 | context 'When all attributes are default, on CentOS 6.6' do 11 | let(:chef_run) do 12 | runner = ChefSpec::SoloRunner.new( 13 | step_into: ['managed_directory'], 14 | platform: 'centos', 15 | version: '6.6' 16 | ) do |node| 17 | # Set/override attributes here 18 | end 19 | runner.converge(described_recipe) 20 | end 21 | 22 | before(:each) do 23 | allow(Dir).to receive(:glob).and_call_original 24 | end 25 | 26 | describe 'given only file a' do 27 | before(:each) do 28 | allow(Dir).to receive(:glob).with('/tmp/foo/*').and_return(['/tmp/foo/a']) 29 | end 30 | 31 | it 'should not remove file a' do 32 | expect(chef_run).to_not delete_file '/tmp/foo/a' 33 | end 34 | end 35 | 36 | describe 'given file b' do 37 | before(:each) do 38 | allow(Dir).to receive(:glob).with('/tmp/foo/*').and_return(['/tmp/foo/b']) 39 | end 40 | 41 | it 'should remove file b' do 42 | expect(chef_run).to delete_file '/tmp/foo/b' 43 | end 44 | end 45 | 46 | describe 'given files a and b' do 47 | before(:each) do 48 | allow(Dir).to receive(:glob).with('/tmp/foo/*').and_return(['/tmp/foo/a','/tmp/foo/b']) 49 | end 50 | 51 | it 'should not remove file a' do 52 | expect(chef_run).to_not delete_file '/tmp/foo/a' 53 | end 54 | 55 | it 'should remove file b' do 56 | expect(chef_run).to delete_file '/tmp/foo/b' 57 | end 58 | end 59 | 60 | describe 'given no files' do 61 | before(:each) do 62 | allow(Dir).to receive(:glob).with('/tmp/foo/*').and_return([]) 63 | end 64 | 65 | it 'should not remove file a' do 66 | expect(chef_run).to_not delete_file '/tmp/foo/a' 67 | end 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /spec/unit/recipes/test_directories_spec.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Spec:: test_directories 4 | # 5 | # Copyright (c) 2015 The Authors, All Rights Reserved. 6 | 7 | require 'spec_helper' 8 | 9 | describe 'managed_directory::test_directories' do 10 | context 'When all attributes are default, on CentOS 6.6' do 11 | let(:chef_run) do 12 | runner = ChefSpec::SoloRunner.new( 13 | step_into: ['managed_directory'], 14 | platform: 'centos', 15 | version: '6.6' 16 | ) do |node| 17 | # Set/override attributes here 18 | end 19 | runner.converge(described_recipe) 20 | end 21 | 22 | before do 23 | testdir_contents = [ 24 | '/tmp/bar/a', 25 | '/tmp/bar/a_dir', 26 | '/tmp/bar/b_dir', 27 | '/tmp/bar/c_dir' 28 | ] 29 | allow(Dir).to receive(:glob).and_call_original 30 | allow(Dir).to receive(:glob).with('/tmp/bar/*').and_return(testdir_contents) 31 | allow(File).to receive(:directory?).and_call_original 32 | allow(File).to receive(:directory?).with('/tmp/bar/a_dir').and_return(true) 33 | allow(File).to receive(:directory?).with('/tmp/bar/b_dir').and_return(true) 34 | allow(File).to receive(:directory?).with('/tmp/bar/c_dir').and_return(true) 35 | end 36 | 37 | it 'should clean managed_directory /tmp/bar' do 38 | expect(chef_run).to clean_managed_directory('/tmp/bar').with( 39 | clean_directories: true, 40 | clean_files: false 41 | ) 42 | end 43 | 44 | # The file /tmp/bar/a shouldn't be removed for this test since we've 45 | # disabled cleaning files in this recipe 46 | it 'should not remove file a' do 47 | expect(chef_run).to_not delete_file('/tmp/bar/a') 48 | end 49 | 50 | it 'should not remove directory a_dir' do 51 | expect(chef_run).to_not delete_directory('/tmp/bar/a_dir') 52 | end 53 | 54 | it 'should not remove directory b_dir' do 55 | expect(chef_run).to_not delete_directory('/tmp/bar/b_dir') 56 | end 57 | 58 | it 'should remove directory c_dir' do 59 | expect(chef_run).to delete_directory('/tmp/bar/c_dir') 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /spec/unit/recipes/test_spec.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Spec:: test 4 | # 5 | # Copyright (c) 2015 The Authors, All Rights Reserved. 6 | 7 | require 'spec_helper' 8 | 9 | describe 'managed_directory::test' do 10 | context 'When all attributes are default, on CentOS 6.6' do 11 | let(:chef_run) do 12 | runner = ChefSpec::SoloRunner.new( 13 | step_into: ['managed_directory'], 14 | platform: 'centos', 15 | version: '6.6' 16 | ) do |node| 17 | # Set/override attributes here 18 | end 19 | runner.converge(described_recipe) 20 | end 21 | 22 | before do 23 | testdir_contents = [ 24 | '/tmp/foo/a', 25 | '/tmp/foo/a_link', 26 | '/tmp/foo/b', 27 | '/tmp/foo/b_link', 28 | '/tmp/foo/c', 29 | '/tmp/foo/c_dir' 30 | ] 31 | allow(Dir).to receive(:glob).and_call_original 32 | allow(Dir).to receive(:glob).with('/tmp/foo/*').and_return(testdir_contents) 33 | allow(File).to receive(:directory?).and_call_original 34 | allow(File).to receive(:directory?).with('/tmp/foo/c_dir').and_return(true) 35 | allow(File).to receive(:symlink?).and_call_original 36 | allow(File).to receive(:symlink?).with('/tmp/foo/a_link').and_return(true) 37 | allow(File).to receive(:symlink?).with('/tmp/foo/b_link').and_return(true) 38 | end 39 | 40 | it 'should clean managed_directory' do 41 | expect(chef_run).to clean_managed_directory('/tmp/foo') 42 | end 43 | 44 | it 'should not remove file a' do 45 | expect(chef_run).to_not delete_file('/tmp/foo/a') 46 | end 47 | 48 | it 'should not remove link a_link' do 49 | expect(chef_run).to_not delete_file('/tmp/foo/a_link') 50 | end 51 | 52 | it 'should not remove file b' do 53 | expect(chef_run).to_not delete_file('/tmp/foo/b') 54 | end 55 | 56 | it 'should remove link b_link' do 57 | expect(chef_run).to delete_link('/tmp/foo/b_link') 58 | end 59 | 60 | it 'should remove file c' do 61 | expect(chef_run).to delete_file('/tmp/foo/c') 62 | end 63 | 64 | # It shouldn't remove c_dir because in this test we haven't told 65 | # managed_directory to clean directories. 66 | it 'should not remove directory c_dir' do 67 | expect(chef_run).to_not delete_directory('/tmp/foo/c_dir') 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /providers/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: managed_directory 3 | # Provider:: default 4 | # 5 | # Copyright 2012, Zachary Stevens 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | action :clean do 21 | # get the contents of the managed_directory on disk 22 | directory_contents = ::Dir.glob("#{new_resource.path}/*") 23 | 24 | # Walk the resource collection to find resources that appear to be 25 | # contained by the managed_directory. This depends on the resource's 26 | # name attribute containing the full path to the file. 27 | managed_entries = run_context.resource_collection.all_resources.map do |r| 28 | r.name.to_s if r.name.to_s.start_with?("#{new_resource.path}/") 29 | end.compact 30 | 31 | # Remove any contents that appear to be unmanaged. 32 | entries_to_remove = directory_contents - managed_entries 33 | entries_to_remove.each do |e| 34 | if ::File.directory?(e) 35 | if new_resource.clean_directories 36 | directory e do 37 | recursive true 38 | action :delete 39 | Chef::Log.info "Removing unmanaged directory in #{new_resource.path}: #{e}" 40 | end 41 | end 42 | elsif ::File.symlink?(e) 43 | # Manage links as links to avoid warnings, as 'manage_symlink_source' 44 | # will eventually be disabled for File resources. 45 | if new_resource.clean_links 46 | link e do 47 | action :delete 48 | Chef::Log.info "Removing unmanaged symlink in #{new_resource.path}: #{e}" 49 | end 50 | end 51 | else 52 | if new_resource.clean_files 53 | file e do 54 | action :delete 55 | Chef::Log.info "Removing unmanaged file in #{new_resource.path}: #{e}" 56 | end 57 | end 58 | end 59 | end 60 | 61 | # If any files were removed, mark the resource as updated. 62 | new_resource.updated_by_last_action(true) unless entries_to_remove.empty? 63 | end 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Description 2 | =========== 3 | 4 | Provides an LWRP to declare that a directory's contents are entirely 5 | managed by Chef. When a node is converged, any files present in the 6 | `managed_directory` that are not managed by Chef will be removed. 7 | 8 | 9 | Requirements 10 | ============ 11 | 12 | Platform 13 | -------- 14 | 15 | Known to work on CentOS and OS X. Should work on other Unix-like 16 | systems. 17 | 18 | 19 | Resource/Provider 20 | ================= 21 | 22 | `managed_directory` 23 | --------------------------- 24 | 25 | Ensure that a directory contains only files put there by Chef in this 26 | run. Any other files will be removed. 27 | 28 | ### Actions 29 | 30 | - `:clean` - Remove any unmanaged files. 31 | 32 | ### Attribute Parameters 33 | 34 | - `path` - (name attribute) The absolute path to the directory to be managed. 35 | - `clean_files` - Boolean to determine whether unmanaged files should be 36 | removed. Default is `true`. 37 | - `clean_links` - Boolean to determine whether unmanaged links should be 38 | removed. Default is `true`. 39 | - `clean_directories` - Boolean to determine whether unmanaged subdirectories 40 | should be removed. Default is `false`. 41 | 42 | 43 | Usage 44 | ===== 45 | 46 | default 47 | ------- 48 | 49 | Include the default recipe in a run list to make the resource 50 | available in your run. 51 | 52 | test 53 | ---- 54 | 55 | The 'test' recipe illustrates use of the `managed_directory` resource. 56 | 57 | test_directories 58 | ---------------- 59 | 60 | The 'test_directories' recipe illustrates use of the `managed_directory` 61 | resource when having it clean up unwanted subdirectories. 62 | 63 | 64 | Caveats 65 | ======= 66 | 67 | * The directory to be managed must already exist. If you also need 68 | to ensure that the directory exists, use the Directory resource 69 | separately. 70 | 71 | * If you require subdirectories to be managed as well, be sure to set the 72 | `clean_directories` attribute to `true` 73 | 74 | * A file is considered to be managed if there is a resource with a 75 | name attribute equal to the file's full path. It will do the wrong 76 | thing if this assumption is not true for the contents of your 77 | directory. 78 | 79 | * Files managed by resources created after this LWRP is converged 80 | (eg, from within a `ruby_block` or LWRP later in the run list) will 81 | be incorrectly identified as "unmanaged", and then deleted. They 82 | will be recreated later in the run, but this creates a window where 83 | the file is missing. 84 | 85 | 86 | License and Author 87 | ================== 88 | 89 | Authors: 90 | - Zachary Stevens ([zts](https://github.com/zts)) 91 | - Gregory Ruiz-Ade ([gkra](https://github.com/gkra)) 92 | 93 | Licensed under the Apache License, Version 2.0 (the "License"); 94 | you may not use this file except in compliance with the License. 95 | You may obtain a copy of the License at 96 | 97 | http://www.apache.org/licenses/LICENSE-2.0 98 | 99 | Unless required by applicable law or agreed to in writing, software 100 | distributed under the License is distributed on an "AS IS" BASIS, 101 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 102 | See the License for the specific language governing permissions and 103 | limitations under the License. 104 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.3.8) 5 | ast (2.0.0) 6 | astrolabe (1.3.0) 7 | parser (>= 2.2.0.pre.3, < 3.0) 8 | berkshelf (3.2.4) 9 | addressable (~> 2.3.4) 10 | berkshelf-api-client (~> 1.2) 11 | buff-config (~> 1.0) 12 | buff-extensions (~> 1.0) 13 | buff-shell_out (~> 0.1) 14 | celluloid (~> 0.16.0) 15 | celluloid-io (~> 0.16.1) 16 | cleanroom (~> 1.0) 17 | faraday (~> 0.9.0) 18 | minitar (~> 0.5.4) 19 | octokit (~> 3.0) 20 | retryable (~> 2.0) 21 | ridley (~> 4.0) 22 | solve (~> 1.1) 23 | thor (~> 0.19) 24 | berkshelf-api-client (1.3.0) 25 | faraday (~> 0.9.0) 26 | httpclient (~> 2.6.0) 27 | buff-config (1.0.1) 28 | buff-extensions (~> 1.0) 29 | varia_model (~> 0.4) 30 | buff-extensions (1.0.0) 31 | buff-ignore (1.1.1) 32 | buff-ruby_engine (0.1.0) 33 | buff-shell_out (0.2.0) 34 | buff-ruby_engine (~> 0.1.0) 35 | builder (3.2.2) 36 | celluloid (0.16.0) 37 | timers (~> 4.0.0) 38 | celluloid-io (0.16.2) 39 | celluloid (>= 0.16.0) 40 | nio4r (>= 1.1.0) 41 | chef (12.4.0) 42 | chef-config (= 12.4.0) 43 | chef-zero (~> 4.2, >= 4.2.2) 44 | diff-lcs (~> 1.2, >= 1.2.4) 45 | erubis (~> 2.7) 46 | ffi-yajl (~> 2.2) 47 | highline (~> 1.6, >= 1.6.9) 48 | mixlib-authentication (~> 1.3) 49 | mixlib-cli (~> 1.4) 50 | mixlib-log (~> 1.3) 51 | mixlib-shellout (>= 2.0.0.rc.0, < 3.0) 52 | net-ssh (~> 2.6) 53 | net-ssh-multi (~> 1.1) 54 | ohai (~> 8.0) 55 | plist (~> 3.1.0) 56 | pry (~> 0.9) 57 | rspec-core (~> 3.2) 58 | rspec-expectations (~> 3.2) 59 | rspec-mocks (~> 3.2) 60 | rspec_junit_formatter (~> 0.2.0) 61 | serverspec (~> 2.7) 62 | specinfra (~> 2.10) 63 | syslog-logger (~> 1.6) 64 | chef-api (0.5.0) 65 | logify (~> 0.1) 66 | mime-types 67 | chef-config (12.4.0) 68 | mixlib-config (~> 2.0) 69 | mixlib-shellout (~> 2.0) 70 | chef-zero (4.2.3) 71 | ffi-yajl (>= 1.1, < 3.0) 72 | hashie (~> 2.0) 73 | mixlib-log (~> 1.3) 74 | rack 75 | uuidtools (~> 2.1) 76 | chefspec (4.2.0) 77 | chef (>= 11.14) 78 | fauxhai (~> 2.0) 79 | rspec (~> 3.0) 80 | cleanroom (1.0.0) 81 | coderay (1.1.0) 82 | dep-selector-libgecode (1.0.2) 83 | dep_selector (1.0.3) 84 | dep-selector-libgecode (~> 1.0) 85 | ffi (~> 1.9) 86 | diff-lcs (1.2.5) 87 | erubis (2.7.0) 88 | faraday (0.9.1) 89 | multipart-post (>= 1.2, < 3) 90 | fauxhai (2.3.0) 91 | net-ssh 92 | ohai 93 | ffi (1.9.9) 94 | ffi-yajl (2.2.0) 95 | libyajl2 (~> 1.2) 96 | foodcritic (4.0.0) 97 | erubis 98 | gherkin (~> 2.11) 99 | nokogiri (~> 1.5) 100 | rake 101 | rufus-lru (~> 1.0) 102 | treetop (~> 1.4) 103 | yajl-ruby (~> 1.1) 104 | gherkin (2.12.2) 105 | multi_json (~> 1.3) 106 | hashie (2.1.2) 107 | highline (1.7.2) 108 | hitimes (1.2.2) 109 | httpclient (2.6.0.1) 110 | ipaddress (0.8.0) 111 | json (1.8.3) 112 | kitchen-docker (2.1.0) 113 | test-kitchen (>= 1.0.0) 114 | kitchen-vagrant (0.18.0) 115 | test-kitchen (~> 1.4) 116 | libyajl2 (1.2.0) 117 | logify (0.2.0) 118 | method_source (0.8.2) 119 | mime-types (2.6.1) 120 | mini_portile (0.6.2) 121 | minitar (0.5.4) 122 | mixlib-authentication (1.3.0) 123 | mixlib-log 124 | mixlib-cli (1.5.0) 125 | mixlib-config (2.2.1) 126 | mixlib-log (1.6.0) 127 | mixlib-shellout (2.1.0) 128 | multi_json (1.11.1) 129 | multipart-post (2.0.0) 130 | net-http-persistent (2.9.4) 131 | net-scp (1.2.1) 132 | net-ssh (>= 2.6.5) 133 | net-ssh (2.9.2) 134 | net-ssh-gateway (1.2.0) 135 | net-ssh (>= 2.6.5) 136 | net-ssh-multi (1.2.1) 137 | net-ssh (>= 2.6.5) 138 | net-ssh-gateway (>= 1.2.0) 139 | nio4r (1.1.0) 140 | nokogiri (1.6.6.2) 141 | mini_portile (~> 0.6.0) 142 | octokit (3.8.0) 143 | sawyer (~> 0.6.0, >= 0.5.3) 144 | ohai (8.5.0) 145 | ffi (~> 1.9) 146 | ffi-yajl (~> 2.2) 147 | ipaddress 148 | mime-types (~> 2.0) 149 | mixlib-cli 150 | mixlib-config (~> 2.0) 151 | mixlib-log 152 | mixlib-shellout (~> 2.0) 153 | rake (~> 10.1) 154 | systemu (~> 2.6.4) 155 | wmi-lite (~> 1.0) 156 | parser (2.3.0.pre.2) 157 | ast (>= 1.1, < 3.0) 158 | plist (3.1.0) 159 | polyglot (0.3.5) 160 | powerpack (0.1.1) 161 | pry (0.10.1) 162 | coderay (~> 1.1.0) 163 | method_source (~> 0.8.1) 164 | slop (~> 3.4) 165 | rack (1.6.4) 166 | rainbow (2.0.0) 167 | rake (10.4.2) 168 | rake-chef-syntax (0.0.2) 169 | chef 170 | rake 171 | retryable (2.0.1) 172 | ridley (4.2.0) 173 | addressable 174 | buff-config (~> 1.0) 175 | buff-extensions (~> 1.0) 176 | buff-ignore (~> 1.1) 177 | buff-shell_out (~> 0.1) 178 | celluloid (~> 0.16.0) 179 | celluloid-io (~> 0.16.1) 180 | erubis 181 | faraday (~> 0.9.0) 182 | hashie (>= 2.0.2, < 3.0.0) 183 | json (>= 1.7.7) 184 | mixlib-authentication (>= 1.3.0) 185 | net-http-persistent (>= 2.8) 186 | retryable (~> 2.0) 187 | semverse (~> 1.1) 188 | varia_model (~> 0.4) 189 | rspec (3.3.0) 190 | rspec-core (~> 3.3.0) 191 | rspec-expectations (~> 3.3.0) 192 | rspec-mocks (~> 3.3.0) 193 | rspec-core (3.3.1) 194 | rspec-support (~> 3.3.0) 195 | rspec-expectations (3.3.0) 196 | diff-lcs (>= 1.2.0, < 2.0) 197 | rspec-support (~> 3.3.0) 198 | rspec-its (1.2.0) 199 | rspec-core (>= 3.0.0) 200 | rspec-expectations (>= 3.0.0) 201 | rspec-mocks (3.3.1) 202 | diff-lcs (>= 1.2.0, < 2.0) 203 | rspec-support (~> 3.3.0) 204 | rspec-support (3.3.0) 205 | rspec_junit_formatter (0.2.3) 206 | builder (< 4) 207 | rspec-core (>= 2, < 4, != 2.12.0) 208 | rubocop (0.32.1) 209 | astrolabe (~> 1.3) 210 | parser (>= 2.2.2.5, < 3.0) 211 | powerpack (~> 0.1) 212 | rainbow (>= 1.99.1, < 3.0) 213 | ruby-progressbar (~> 1.4) 214 | ruby-progressbar (1.7.5) 215 | rufus-lru (1.0.5) 216 | safe_yaml (1.0.4) 217 | sawyer (0.6.0) 218 | addressable (~> 2.3.5) 219 | faraday (~> 0.8, < 0.10) 220 | semverse (1.2.1) 221 | serverspec (2.19.0) 222 | multi_json 223 | rspec (~> 3.0) 224 | rspec-its 225 | specinfra (~> 2.35) 226 | slop (3.6.0) 227 | solve (1.2.1) 228 | dep_selector (~> 1.0) 229 | semverse (~> 1.1) 230 | specinfra (2.36.6) 231 | net-scp 232 | net-ssh 233 | stove (3.2.7) 234 | chef-api (~> 0.5) 235 | logify (~> 0.2) 236 | syslog-logger (1.6.8) 237 | systemu (2.6.5) 238 | test-kitchen (1.4.1) 239 | mixlib-shellout (>= 1.2, < 3.0) 240 | net-scp (~> 1.1) 241 | net-ssh (~> 2.7) 242 | safe_yaml (~> 1.0) 243 | thor (~> 0.18) 244 | thor (0.19.1) 245 | timers (4.0.1) 246 | hitimes 247 | treetop (1.6.2) 248 | polyglot (~> 0.3) 249 | uuidtools (2.1.5) 250 | varia_model (0.4.0) 251 | buff-extensions (~> 1.0) 252 | hashie (>= 2.0.2, < 3.0.0) 253 | wmi-lite (1.0.0) 254 | yajl-ruby (1.2.1) 255 | yarjuf (2.0.0) 256 | builder 257 | rspec (~> 3) 258 | 259 | PLATFORMS 260 | ruby 261 | 262 | DEPENDENCIES 263 | berkshelf 264 | chef 265 | chef-zero 266 | chefspec 267 | foodcritic 268 | kitchen-docker 269 | kitchen-vagrant 270 | rake-chef-syntax 271 | rubocop 272 | semverse 273 | stove 274 | test-kitchen 275 | yarjuf 276 | --------------------------------------------------------------------------------