chefspec-bootstrap 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +61 -5
- data/bin/chefspec-bootstrap +2 -3
- data/chefspec-bootstrap.gemspec +2 -3
- data/lib/chefspec-bootstrap.rb +91 -15
- data/templates/default.erb +5 -1
- metadata +3 -19
    
        data/README.md
    CHANGED
    
    | @@ -1,11 +1,67 @@ | |
| 1 1 | 
             
            chefspec-bootstrap
         | 
| 2 2 | 
             
            ==================
         | 
| 3 3 |  | 
| 4 | 
            -
            A tool to get started with ChefSpec.  | 
| 4 | 
            +
            A command line tool to get started with ChefSpec. Generates spec files for your untested recipes.
         | 
| 5 5 |  | 
| 6 | 
            -
             | 
| 6 | 
            +
            Given a cookbook called `cookbook` with a recipe called `recipe.rb`:
         | 
| 7 | 
            +
            ```ruby
         | 
| 8 | 
            +
            package "apache2"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            file "/etc/apache2/sites-available/default" do
         | 
| 11 | 
            +
              action :delete
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            template "/etc/apache2/sites-available/mysite" do
         | 
| 15 | 
            +
              source "mysite.conf.erb"
         | 
| 16 | 
            +
            end
         | 
| 17 | 
            +
            ```
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            The command line tool will generate the following spec file at `spec/cookbook/recipe_spec.rb`:
         | 
| 20 | 
            +
            ```ruby
         | 
| 21 | 
            +
            require 'chefspec'
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            describe 'cookbook::recipe' do
         | 
| 24 | 
            +
              let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) }
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              it 'runs successfully' do
         | 
| 27 | 
            +
                expect{chef_run}.not_to raise_error
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
              
         | 
| 30 | 
            +
              it "installs the apache2 package" do
         | 
| 31 | 
            +
                expect(chef_run).to install_package("apache2")
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              it "deletes the /etc/apache2/conf.d/python.conf file" do
         | 
| 35 | 
            +
                expect(chef_run).to delete_file("/etc/apache2/conf.d/python.conf")
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              it "creates the /etc/apache2/sites-available/mysite template" do
         | 
| 39 | 
            +
                expect(chef_run).to create_template("/etc/apache2/sites-available/mysite")
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
| 7 42 | 
             
            ```
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 43 | 
            +
             | 
| 44 | 
            +
             | 
| 45 | 
            +
            Getting Started
         | 
| 46 | 
            +
            ---
         | 
| 47 | 
            +
            Install the gem
         | 
| 11 48 | 
             
            ```
         | 
| 49 | 
            +
            gem install chefspec-bootstrap
         | 
| 50 | 
            +
            ```
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            Run the command-line tool
         | 
| 53 | 
            +
            ```
         | 
| 54 | 
            +
            chefspec-bootstrap
         | 
| 55 | 
            +
            ```
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            Options
         | 
| 58 | 
            +
            ---
         | 
| 59 | 
            +
            ```
         | 
| 60 | 
            +
            --cookbooks-dir, -c <s>:   Your site cookbooks directory (default: site-cookbooks)
         | 
| 61 | 
            +
            --spec-dir, -s <s>:        Your spec directory (default: spec)
         | 
| 62 | 
            +
            --template, -t <s>:        ERB template file used to generate specs
         | 
| 63 | 
            +
            ```
         | 
| 64 | 
            +
             | 
| 65 | 
            +
            Creating a custom template
         | 
| 66 | 
            +
            ---
         | 
| 67 | 
            +
            A custom erb template can be passsed using the `-t` flag. See the included default template for an example.
         | 
    
        data/bin/chefspec-bootstrap
    CHANGED
    
    | @@ -9,6 +9,5 @@ opts = Trollop::options do | |
| 9 9 | 
             
              opt :template, "ERB template file used to generate specs", :type => :string
         | 
| 10 10 | 
             
            end
         | 
| 11 11 |  | 
| 12 | 
            -
            bootstrap = ChefSpec::Bootstrap.new
         | 
| 13 | 
            -
             | 
| 14 | 
            -
            bootstrap.generate(opts[:cookbooks_dir], opts[:spec_dir], opts[:template])
         | 
| 12 | 
            +
            bootstrap = ChefSpec::Bootstrap.new(opts[:cookbooks_dir], opts[:spec_dir], opts[:template])
         | 
| 13 | 
            +
            bootstrap.generate()
         | 
    
        data/chefspec-bootstrap.gemspec
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            Gem::Specification.new do |s|
         | 
| 2 2 | 
             
              s.name        = 'chefspec-bootstrap'
         | 
| 3 | 
            -
              s.version     = '0.0. | 
| 3 | 
            +
              s.version     = '0.0.2'
         | 
| 4 4 | 
             
              s.date        = '2014-06-02'
         | 
| 5 5 | 
             
              s.summary     = "Bootstrap your ChefSpec tests."
         | 
| 6 6 | 
             
              s.description = "Automatically generate ChefSpec tests based on your recipes."
         | 
| @@ -12,7 +12,6 @@ Gem::Specification.new do |s| | |
| 12 12 | 
             
              s.executables   = ["chefspec-bootstrap"]
         | 
| 13 13 | 
             
              s.required_ruby_version = '>= 1.9'
         | 
| 14 14 |  | 
| 15 | 
            -
              s.add_dependency ' | 
| 16 | 
            -
              s.add_dependency 'chefspec', '~> 3.1.0'
         | 
| 15 | 
            +
              s.add_dependency 'chefspec', '~> 3.4.0'
         | 
| 17 16 | 
             
              s.add_dependency 'trollop', '~> 2.0.0'
         | 
| 18 17 | 
             
            end
         | 
    
        data/lib/chefspec-bootstrap.rb
    CHANGED
    
    | @@ -1,37 +1,69 @@ | |
| 1 | 
            -
            #!/usr/bin/env ruby
         | 
| 2 | 
            -
             | 
| 3 1 | 
             
            require 'erb'
         | 
| 4 2 | 
             
            require 'fileutils'
         | 
| 5 3 | 
             
            require 'ostruct'
         | 
| 4 | 
            +
            require 'chefspec'
         | 
| 6 5 |  | 
| 7 6 | 
             
            module ChefSpec
         | 
| 8 7 | 
             
              class Bootstrap
         | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 8 | 
            +
             | 
| 9 | 
            +
                def initialize(cookbooks_dir, spec_dir, template_file)
         | 
| 10 | 
            +
                  @cookbooks_dir = cookbooks_dir
         | 
| 11 | 
            +
                  @spec_dir = spec_dir
         | 
| 12 | 
            +
                  @template_file = template_file
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def setup
         | 
| 16 | 
            +
                  if not Dir.exist?(@cookbooks_dir)
         | 
| 17 | 
            +
                    abort "Unable to locate your cookbooks directory (#{@cookbooks_dir})"
         | 
| 12 18 | 
             
                  end
         | 
| 13 19 |  | 
| 14 | 
            -
                  if not template_file
         | 
| 15 | 
            -
                    template_file = root.join('templates', 'default.erb')
         | 
| 20 | 
            +
                  if not @template_file
         | 
| 21 | 
            +
                    @template_file = root.join('templates', 'default.erb')
         | 
| 16 22 | 
             
                  end
         | 
| 17 23 |  | 
| 18 | 
            -
                  if not File.exist?(template_file)
         | 
| 19 | 
            -
                    abort "Unable to locate template file (#{template_file})"
         | 
| 24 | 
            +
                  if not File.exist?(@template_file)
         | 
| 25 | 
            +
                    abort "Unable to locate template file (#{@template_file})"
         | 
| 20 26 | 
             
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def generate
         | 
| 30 | 
            +
                  setup()
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  erb = ERB.new(File.read(@template_file))
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  # begin
         | 
| 35 | 
            +
                  #   require "#{@spec_dir}/spec_helper.rb"
         | 
| 36 | 
            +
                  # rescue LoadError
         | 
| 21 37 |  | 
| 22 | 
            -
                   | 
| 38 | 
            +
                  # end
         | 
| 23 39 |  | 
| 24 | 
            -
                   | 
| 40 | 
            +
                  ::RSpec.configure { |config| config.cookbook_path = [@cookbooks_dir, 'cookbooks'] }
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  Dir.glob("#{@cookbooks_dir}/*/recipes/*").each do |path|
         | 
| 25 43 | 
             
                    path, recipe_file = File.split(path)
         | 
| 26 44 | 
             
                    recipe = recipe_file.split('.')[0]
         | 
| 27 45 | 
             
                    cookbook = path.split(File::SEPARATOR)[1]
         | 
| 28 46 |  | 
| 29 | 
            -
                    filename = "#{spec_dir}/#{cookbook}/#{recipe}_spec.rb"
         | 
| 47 | 
            +
                    filename = "#{@spec_dir}/#{cookbook}/#{recipe}_spec.rb"
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    puts filename
         | 
| 30 50 |  | 
| 31 | 
            -
                    if  | 
| 32 | 
            -
                       | 
| 51 | 
            +
                    if File.exist?(filename)
         | 
| 52 | 
            +
                      puts "    spec already exists. Skipping."
         | 
| 53 | 
            +
                    else
         | 
| 54 | 
            +
                      FileUtils.mkdir_p "#{@spec_dir}/#{cookbook}"
         | 
| 33 55 |  | 
| 34 | 
            -
                      puts " | 
| 56 | 
            +
                      puts "    executing recipe with ChefSpec..."
         | 
| 57 | 
            +
                      chef_run = get_chef_run(cookbook, recipe)
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                      if chef_run
         | 
| 60 | 
            +
                        puts "    execution suceeded. Creating spec file."
         | 
| 61 | 
            +
                      else
         | 
| 62 | 
            +
                        puts "    execution failed. Creating empty spec file."
         | 
| 63 | 
            +
                      end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                      resources = get_resources(chef_run)
         | 
| 66 | 
            +
                      test_cases = generate_test_cases(resources)
         | 
| 35 67 |  | 
| 36 68 | 
             
                      File.open(filename, "w") do |spec_file|
         | 
| 37 69 | 
             
                        spec_file.write(erb.result(binding))
         | 
| @@ -43,5 +75,49 @@ module ChefSpec | |
| 43 75 | 
             
                def root
         | 
| 44 76 | 
             
                  @root ||= Pathname.new(File.expand_path('../../', __FILE__))
         | 
| 45 77 | 
             
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                def get_chef_run(cookbook, recipe)
         | 
| 80 | 
            +
                  begin
         | 
| 81 | 
            +
                    return ChefSpec::Runner.new.converge("#{cookbook}::#{recipe}")
         | 
| 82 | 
            +
                  rescue
         | 
| 83 | 
            +
                    return nil
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                def get_resource_name(resource)
         | 
| 88 | 
            +
                  return resource.name || resource.identity
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                def get_resources(chef_run)
         | 
| 92 | 
            +
                  if chef_run
         | 
| 93 | 
            +
                    return chef_run.resource_collection.all_resources
         | 
| 94 | 
            +
                  else
         | 
| 95 | 
            +
                    return []
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
                end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                def generate_test_cases(resources)
         | 
| 100 | 
            +
                  test_cases = []
         | 
| 101 | 
            +
                  resources.each do |resource|
         | 
| 102 | 
            +
                    verbs = resource.action
         | 
| 103 | 
            +
                    if not verbs.respond_to?(:each)
         | 
| 104 | 
            +
                      verbs = [verbs]
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                    noun = resource.resource_name
         | 
| 108 | 
            +
                    adjective = resource.name
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                    verbs.each do |verb|
         | 
| 111 | 
            +
                      if not verb == :nothing
         | 
| 112 | 
            +
                        test_cases.push({
         | 
| 113 | 
            +
                          :it => "#{verb}s the #{adjective} #{noun}",
         | 
| 114 | 
            +
                          :action => "#{verb}_#{noun}",
         | 
| 115 | 
            +
                          :name => adjective
         | 
| 116 | 
            +
                        })
         | 
| 117 | 
            +
                      end
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
                  return test_cases
         | 
| 121 | 
            +
                end
         | 
| 46 122 | 
             
              end
         | 
| 47 123 | 
             
            end
         | 
    
        data/templates/default.erb
    CHANGED
    
    | @@ -5,5 +5,9 @@ describe '<%= cookbook %>::<%= recipe %>' do | |
| 5 5 |  | 
| 6 6 | 
             
              it 'runs successfully' do
         | 
| 7 7 | 
             
                expect{chef_run}.not_to raise_error
         | 
| 8 | 
            -
              end
         | 
| 8 | 
            +
              end<% if test_cases %><% test_cases.each do |test_case| %>
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              it "<%= test_case[:it] %>" do
         | 
| 11 | 
            +
                expect(chef_run).to <%= test_case[:action] %>("<%= test_case[:name] %>")
         | 
| 12 | 
            +
              end<% end %><% end %>
         | 
| 9 13 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: chefspec-bootstrap
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.2
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -11,22 +11,6 @@ bindir: bin | |
| 11 11 | 
             
            cert_chain: []
         | 
| 12 12 | 
             
            date: 2014-06-02 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 15 | 
            -
              name: chef
         | 
| 16 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 17 | 
            -
                none: false
         | 
| 18 | 
            -
                requirements:
         | 
| 19 | 
            -
                - - ~>
         | 
| 20 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 21 | 
            -
                    version: '11.0'
         | 
| 22 | 
            -
              type: :runtime
         | 
| 23 | 
            -
              prerelease: false
         | 
| 24 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 25 | 
            -
                none: false
         | 
| 26 | 
            -
                requirements:
         | 
| 27 | 
            -
                - - ~>
         | 
| 28 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 29 | 
            -
                    version: '11.0'
         | 
| 30 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 31 15 | 
             
              name: chefspec
         | 
| 32 16 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -34,7 +18,7 @@ dependencies: | |
| 34 18 | 
             
                requirements:
         | 
| 35 19 | 
             
                - - ~>
         | 
| 36 20 | 
             
                  - !ruby/object:Gem::Version
         | 
| 37 | 
            -
                    version: 3. | 
| 21 | 
            +
                    version: 3.4.0
         | 
| 38 22 | 
             
              type: :runtime
         | 
| 39 23 | 
             
              prerelease: false
         | 
| 40 24 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| @@ -42,7 +26,7 @@ dependencies: | |
| 42 26 | 
             
                requirements:
         | 
| 43 27 | 
             
                - - ~>
         | 
| 44 28 | 
             
                  - !ruby/object:Gem::Version
         | 
| 45 | 
            -
                    version: 3. | 
| 29 | 
            +
                    version: 3.4.0
         | 
| 46 30 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 47 31 | 
             
              name: trollop
         | 
| 48 32 | 
             
              requirement: !ruby/object:Gem::Requirement
         |