I decided to do something simple for now, and work on it as I go. That way I have a better idea of requirements and how I will actually use it. My thinking was simple, I want to boot something, ssh into it, run tests against the structure, and shut it down. I don't want to boot/terminate it every run though, so I separate that piece. So here's what I put together this morning, I installed rspec, and created the following folder/file structure: spec ├── cookbooks │ ├── build_essentials_spec.rb │ └── generic_users_spec.rb ├── spec_helper.rb └── support ├── matchers └── models └── host.rb Here are the files: spec_helper.rb require 'bundler' begin Bundler.setup rescue Bundler::BundlerError => e $stderr.puts e.message $stderr.puts "Run `bundle install` to install missing gems" exit e.status_code end # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. Dir.glob("./spec/support/**/*.rb").each {|f| require f} RSpec.configure do |config| config.before(:all) do # Note: I use vagrant with chef-client provisioning, this is what it uses to run chef-client host.run_chef("chef-client -c /tmp/vagrant-chef-1/client.rb -j /tmp/vagrant-chef-1/dna.json") end config.after(:all) do host.close end end # start an instance to test # run chef # test the structure looks as we want it # This represents the host we're running tests against def host # I set up this hostname using vagrant ssh-config @host ||= Host.new 'cc.local', 'vagrant', :port => '2222' end host.rb require 'net/ssh' class Host def initialize(host, user, options={}) @ssh = Net::SSH.start(host, user, options) end def close @ssh.close end def run_chef(chef_command="sudo chef-client") @ssh.exec! chef_command end def installed_packages @packages ||= @ssh.exec! 'dpkg --get-selections' @packages.split("\n").collect {|pkg| pkg.split(" ")[0] } end def users @users ||= @ssh.exec! 'cat /etc/passwd' @users.split("\n").collect {|u| u.split(":")[0] } end end Vagrantfile Vagrant::Config.run do |config| config.vm.define :cc do |host| host.vm.box = "cc.dev" host.vm.forward_port 80, 8080 host.vm.forward_port 22, 2222 host.vm.network :hostonly, "33.33.33.220" host.vm.provision :chef_client do |chef| # chef.log_level = :debug chef.node_name = "cc.dev" chef.chef_server_url = "https://api.opscode.com/organizations/#{ENV['ORG']}" chef.environment = "develop" chef.validation_client_name = ENV['validation_key_name'] chef.validation_key_path = ENV['my_key_location'] chef.add_role 'base' end end end Rakefile task :go => ["vagrant:up", "spec"] task :setup => ["vagrant:up"] task :teardown => ["vagrant:destroy", "knife:client_delete", "knife:node_delete"] task :spec do sh 'bundle exec rspec spec/cookbooks/*.rb' end namespace :vagrant do task :up do safe_task do sh 'bundle exec vagrant up cc' end end task :destroy do safe_task do sh 'bundle exec vagrant destroy' end end task :provision do safe_task do sh 'bundle exec vagrant provision' end end end namespace :knife do task :client_delete do safe_task do sh 'bundle exec knife client delete cc.dev -y' end end task :node_delete do safe_task do sh 'bundle exec knife node delete cc.dev -y' end end end def safe_task(&block) begin yield rescue puts "Command failed. Next!" end end Gemfile source :rubygems gem 'vagrant', '= 0.9.7' # stop a clash between net-ssh dependencies (vagrant requires a higher version) gem "chef", :git => "https://github.com/opscode/chef.git", :ref => "ba4d58f4223" gem 'rspec', '= 2.8.0' Obviously this is the start of something, not a finished idea. It's just to show whoever wants to try this out, how easy it actually is. The Host class is the start of something that needs more thinking, or might just end up being replaced with something else. Thoughts? Cheers Jamie van Dyke On Mar 1, 2012, at 5:28 PM, Bryan Baugher wrote: I had similar thoughts about these methods. I really hoped I could make cucumber-chef work but we don't use EC2 here. |
Archive powered by MHonArc 2.6.16.