foodtaster 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/README.md CHANGED
@@ -12,14 +12,28 @@ initial 'clean' state which removes any modifications made by
12
12
  previously executed specs. It allows you to independently test different
13
13
  cookbooks on a single VM.
14
14
 
15
- Of course, you aren't limited by just one VM for your specs, you may
15
+ You aren't limited by just one VM for your specs, you may
16
16
  run as many as you need. PostgreSQL replication, load balancing and
17
17
  even entire application environments becomes testable (of course, if
18
- you have enought amount of RAM).
18
+ you have enought amount of RAM for all your VMs).
19
+
20
+ Check out
21
+ [foodtaster-example repository](http://github.com/mlapshin/foodtaster-example)
22
+ to see Foodtaster in action.
19
23
 
20
24
  Foodtaster is on early development stage, so feedback is very
21
25
  appreciated.
22
26
 
27
+ ## Documentation
28
+
29
+ To get more information about FT, read
30
+ [Wiki](https://github.com/mlapshin/foodtaster/wiki) or refer to
31
+ [RDoc](http://rdoc.info/github/mlapshin/foodtaster/master/frames).
32
+
33
+ If you have any questions or got in trouble, feel free to ask
34
+ community in
35
+ [Foodtaster Google Group](http://groups.google.com/d/forum/foodtaster).
36
+
23
37
  ## Quick Example
24
38
 
25
39
  ```ruby
@@ -34,11 +48,12 @@ describe "nginx::default" do
34
48
  it "should install nginx as a daemon" do
35
49
  vm0.should have_package 'nginx'
36
50
  vm0.should have_user('www-data').in_group('www-data')
51
+ vm0.should have_running_process('nginx')
37
52
  vm0.should listen_port(80)
38
- vm0.should open_page("http://localhost/")
39
53
 
40
- vm0.should have_file("/etc/init.d/nginx")
41
- vm0.should have_file("/etc/nginx/nginx.conf").with_content(/gzip on/).with_mode(0644)
54
+ vm0.should have_file("/etc/nginx/nginx.conf")
55
+ .with_content(/gzip on/)
56
+ .with_mode(0644)
42
57
  end
43
58
 
44
59
  it "should have valid nginx config" do
@@ -52,49 +67,33 @@ end
52
67
 
53
68
  ## Installation
54
69
 
55
- First, install Vagrant for your system following [official
56
- instructions](http://docs.vagrantup.com/v2/installation/index.html).
57
- Then, install two Vagrant plugins:
58
- [sahara](http://github.com/jedi4ever/sahara) and
59
- [vagrant-foodtaster-server](http://github.com/mlapshin/vagrant-foodtaster-server):
70
+ First, install [VirtualBox](http://www.virtualbox.org/) and
71
+ [Vagrant](http://docs.vagrantup.com/v2/installation/index.html). Then
72
+ install
73
+ [vagrant-foodtaster-server](http://github.com/mlapshin/vagrant-foodtaster-server)
74
+ plugin:
60
75
 
61
- vagrant plugin install sahara
62
76
  vagrant plugin install vagrant-foodtaster-server
63
77
 
64
- That's all, you are ready to go.
65
-
66
78
  ## Usage
67
79
 
68
- Check out [foodtaster-example
69
- repository](http://github.com/mlapshin/foodtaster-example) or
70
- follow this instructions.
71
-
72
- In your Chef repository, create a basic Gemfile:
80
+ In your Chef or Cookbook repository, create a basic Gemfile:
73
81
 
74
82
  source 'https://rubygems.org/'
75
83
 
76
- gem 'rspec'
77
84
  gem 'foodtaster'
78
85
 
79
- Then, create a Vagrantfile describing VMs you need for specs. Here is
80
- [example
81
- Vagrantfile](http://raw.github.com/mlapshin/foodtaster-example/master/Vagrantfile).
86
+ Create a Vagrantfile describing VMs you need for specs. [Read
87
+ Wiki](https://github.com/mlapshin/foodtaster/wiki/Vagrantfile-Requirements)
88
+ for detailed explanation and examples.
82
89
 
83
- Create `spec` folder with `spec_helper.rb` file:
90
+ Create `spec` folder with basic `spec_helper.rb` file:
84
91
 
85
92
  ```ruby
86
93
  require 'foodtaster'
87
-
88
- RSpec.configure do |config|
89
- config.color_enabled = true
90
- end
91
-
92
- Foodtaster.configure do |config|
93
- config.log_level = :info
94
- end
95
94
  ```
96
95
 
97
- You are ready to write cookbook specs. Run them as usual with command:
96
+ You are now ready to write cookbook specs. Run them as usual with command:
98
97
 
99
98
  bundle exec rspec spec
100
99
 
data/lib/foodtaster.rb CHANGED
@@ -20,5 +20,14 @@ module Foodtaster
20
20
  end
21
21
  end
22
22
  end
23
+
24
+ def config
25
+ @config ||= Config.default
26
+ end
27
+
28
+ def configure(&config_block)
29
+ Foodtaster::RSpec.configure
30
+ config.configure(&config_block) if config_block
31
+ end
23
32
  end
24
33
  end
@@ -66,7 +66,12 @@ module Foodtaster
66
66
  server_version = @v.version
67
67
 
68
68
  if server_version != Foodtaster::VERSION
69
- Foodtaster.logger.warn "Warning: Foodtaster DRb Server version doesn't match Foodtaster Gem version.\n\nDRb Server version: #{server_version}\nFoodtaster Gem version: #{Foodtaster::VERSION}\n"
69
+ Foodtaster.logger.warn <<-TEXT
70
+ Warning: Foodtaster DRb Server version doesn't match Foodtaster Gem version.
71
+
72
+ DRb Server version: #{server_version}
73
+ Foodtaster Gem version: #{Foodtaster::VERSION}
74
+ TEXT
70
75
  end
71
76
  end
72
77
  end
@@ -1,35 +1,26 @@
1
1
  module Foodtaster
2
2
  class Config
3
- %w(log_level drb_port vagrant_binary shutdown_vms
4
- skip_rollback start_server).each do |attr|
5
- attr_accessor attr.to_sym
3
+ attr_accessor :log_level, :drb_port, :vagrant_binary,
4
+ :shutdown_vms, :skip_rollback, :start_server
5
+
6
+ def self.default
7
+ self.new
6
8
  end
7
9
 
10
+ def configure
11
+ yield(self)
12
+ self
13
+ end
14
+
15
+ private
16
+
8
17
  def initialize
9
- @log_level = :info
18
+ @log_level = :warn
10
19
  @drb_port = 35672
11
20
  @vagrant_binary = 'vagrant'
12
21
  @shutdown_vms = false
13
22
  @skip_rollback = false
14
23
  @start_server = true
15
24
  end
16
-
17
- def self.default
18
- self.new
19
- end
20
- end
21
-
22
- class << self
23
- def config
24
- @config ||= Config.default
25
- end
26
-
27
- def configure
28
- if block_given?
29
- yield(self.config)
30
- else
31
- raise ArgumentError, "No block given"
32
- end
33
- end
34
25
  end
35
26
  end
@@ -2,11 +2,24 @@ module Foodtaster
2
2
  module RSpec
3
3
  autoload :ExampleMethods, "foodtaster/rspec/example_methods"
4
4
  autoload :DslMethods, "foodtaster/rspec/dsl_methods"
5
+
6
+ def self.configure
7
+ ::RSpec::configure do |config|
8
+ config.include Foodtaster::RSpec::ExampleMethods
9
+ config.extend Foodtaster::RSpec::DslMethods
10
+
11
+ config.before(:suite) do
12
+ Foodtaster::RSpecRun.current.start
13
+ end
14
+
15
+ config.after(:suite) do
16
+ Foodtaster::RSpecRun.current.stop
17
+ end
18
+ end
19
+ end
5
20
  end
6
21
  end
7
22
 
8
- require 'foodtaster/rspec/config'
9
-
10
23
  # require all matchers
11
24
  Dir[File.dirname(__FILE__) + "/rspec/matchers/*.rb"].each do |f|
12
25
  require f
@@ -1,10 +1,8 @@
1
1
  require 'timeout'
2
2
 
3
- # RSpec::Matchers.send(:include, VagrantHelper::Matchers::MatcherMethods)
4
-
5
3
  RSpec::Matchers.define :have_running_process do |process|
6
4
  match do |vm|
7
- vm.execute("pgrep #{process}").successful?
5
+ vm.execute("pgrep -f #{process}").successful?
8
6
  end
9
7
 
10
8
  failure_message_for_should do |vm|
@@ -74,26 +72,6 @@ RSpec::Matchers.define :have_group do |group|
74
72
  end
75
73
  end
76
74
 
77
- RSpec::Matchers.define :open_page do |address|
78
- match do |vm|
79
- result = vm.execute("wget #{address} -O /tmp/test-page").successful?
80
- vm.execute("rm /tmp/test-page")
81
- result
82
- end
83
-
84
- failure_message_for_should do |vm|
85
- "expected that #{vm.name} should open page '#{address}'"
86
- end
87
-
88
- failure_message_for_should_not do |vm|
89
- "expected that #{vm.name} should not open page '#{address}'"
90
- end
91
-
92
- description do
93
- "open page '#{address}'"
94
- end
95
- end
96
-
97
75
  def wait_until(_timeout = 5)
98
76
  begin
99
77
  timeout _timeout do
@@ -116,4 +94,3 @@ RSpec::Matchers.define :be_successful do |opts = {}|
116
94
  end
117
95
  end
118
96
  end
119
-
@@ -12,15 +12,11 @@ module Foodtaster
12
12
  setup_signal_handlers
13
13
  start_server_and_connect_client
14
14
 
15
- if (@server_process.nil? || @server_process.alive?) && @client
16
- # prepare_required_vms
17
- else
18
- if @server_process
19
- Foodtaster.logger.fatal "Failed to start Foodtaster DRb Server:\n\n#{@server_process.output}"
20
- else
21
- Foodtaster.logger.fatal "Failed to connect to Foodtaster DRb Server"
22
- end
23
-
15
+ if @client && @server_process && !@server_process.alive?
16
+ Foodtaster.logger.fatal "Failed to start Foodtaster DRb Server:\n\n#{@server_process.output}"
17
+ exit 1
18
+ elsif !@client || !@server_process
19
+ Foodtaster.logger.fatal "Failed to connect to Foodtaster DRb Server"
24
20
  exit 1
25
21
  end
26
22
  end
@@ -65,12 +61,12 @@ module Foodtaster
65
61
  def start_server_and_connect_client
66
62
  drb_port = Foodtaster.config.drb_port
67
63
 
68
- start_server(drb_port) if Foodtaster.config.start_server
69
- connect_client(drb_port)
64
+ @server_process = start_server(drb_port) if Foodtaster.config.start_server
65
+ @client = connect_client(drb_port)
70
66
  end
71
67
 
72
68
  def start_server(drb_port)
73
- @server_process = Foodtaster::ServerProcess.new(drb_port)
69
+ Foodtaster::ServerProcess.new(drb_port)
74
70
  end
75
71
 
76
72
  def terminate_server
@@ -78,7 +74,7 @@ module Foodtaster
78
74
  end
79
75
 
80
76
  def connect_client(drb_port)
81
- @client = Foodtaster::Client.connect(drb_port, @server_process)
77
+ Foodtaster::Client.connect(drb_port, @server_process)
82
78
  end
83
79
  end
84
80
  end
@@ -1,3 +1,3 @@
1
1
  module Foodtaster
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
data/lib/foodtaster/vm.rb CHANGED
@@ -8,9 +8,11 @@ module Foodtaster
8
8
  attr_reader :exit_status
9
9
 
10
10
  def initialize(hash)
11
- @stderr = hash[:stderr].to_s
12
- @stdout = hash[:stdout].to_s
13
- @exit_status = hash[:exit_status]
11
+ if hash
12
+ @stderr = hash[:stderr].to_s.chomp
13
+ @stdout = hash[:stdout].to_s.chomp
14
+ @exit_status = hash[:exit_status]
15
+ end
14
16
  end
15
17
 
16
18
  def successful?
@@ -38,13 +40,14 @@ module Foodtaster
38
40
  end
39
41
 
40
42
  def get(vm_name)
41
- find_by_name(vm_name) || self.new(vm_name)
43
+ find_by_name(vm_name) ||
44
+ self.new(vm_name, Foodtaster::RSpecRun.current.client)
42
45
  end
43
46
  end
44
47
 
45
- def initialize(name)
48
+ def initialize(name, client)
46
49
  @name = name
47
- @client = Foodtaster::RSpecRun.current.client
50
+ @client = client
48
51
 
49
52
  unless @client.vm_defined?(name)
50
53
  raise ArgumentError, "No machine defined with name #{name}"
@@ -112,10 +115,11 @@ module Foodtaster
112
115
  def execute(command)
113
116
  Foodtaster.logger.debug "#{name}: Executing #{command}"
114
117
  exec_result_hash = @client.execute_command_on_vm(name, command)
118
+ exec_result = ExecResult.new(exec_result_hash)
115
119
 
116
- Foodtaster.logger.debug "#{name}: Finished with #{exec_result_hash[:exit_status]}"
117
- Foodtaster.logger.debug "#{name}: STDOUT: #{exec_result_hash[:stdout].to_s.chomp}"
118
- Foodtaster.logger.debug "#{name}: STDERR: #{exec_result_hash[:stderr].to_s.chomp}"
120
+ Foodtaster.logger.debug "#{name}: Finished with #{exec_result.exit_status}"
121
+ Foodtaster.logger.debug "#{name}: STDOUT: #{exec_result.stdout}"
122
+ Foodtaster.logger.debug "#{name}: STDERR: #{exec_result.stderr}"
119
123
 
120
124
  ExecResult.new(exec_result_hash)
121
125
  end
@@ -126,6 +130,8 @@ module Foodtaster
126
130
  end
127
131
 
128
132
  def run_chef(config)
133
+ fail ArgumentError, "#{config.inspect} should have :run_list." unless config[:run_list]
134
+
129
135
  Foodtaster.logger.info "#{name}: Running Chef with Run List #{config[:run_list].join(', ')}"
130
136
  Foodtaster.logger.debug "#{name}: with JSON: #{config[:json].inspect}"
131
137
  @client.run_chef_on_vm(name, config)
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Foodtaster::Client do
4
+ before(:each) { TestServer.start }
5
+ after(:each) { TestServer.stop }
6
+
7
+ it 'should connect to server' do
8
+ client = described_class.connect(TestServer::PORT)
9
+ expect(client).not_to be(nil)
10
+ end
11
+ end
@@ -0,0 +1,38 @@
1
+ require 'foodtaster/config'
2
+
3
+ describe Foodtaster::Config do
4
+ context 'default options' do
5
+ subject { described_class.new }
6
+
7
+ its(:log_level) { should == :warn }
8
+ its(:drb_port) { should == 35672 }
9
+ its(:vagrant_binary) { should == 'vagrant' }
10
+ its(:shutdown_vms) { should == false }
11
+ its(:skip_rollback) { should == false }
12
+ its(:start_server) { should == true }
13
+ end
14
+
15
+ context 'option overrides' do
16
+ subject do
17
+ described_class.new
18
+ end
19
+
20
+ before(:each) do
21
+ subject.configure do |conf|
22
+ conf.log_level = :debug
23
+ conf.drb_port = 31415
24
+ conf.vagrant_binary = '/some/vagrant'
25
+ conf.shutdown_vms = true
26
+ conf.skip_rollback = true
27
+ conf.start_server = false
28
+ end
29
+ end
30
+
31
+ its(:log_level) { should == :debug }
32
+ its(:drb_port) { should == 31415 }
33
+ its(:vagrant_binary) { should == '/some/vagrant' }
34
+ its(:shutdown_vms) { should == true }
35
+ its(:skip_rollback) { should == true }
36
+ its(:start_server) { should == false }
37
+ end
38
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ describe Foodtaster::Vm do
4
+ let(:vm_name) { "vm" }
5
+ let(:client) { double("client", vm_defined?: true) }
6
+ subject { described_class.new(vm_name, client) }
7
+
8
+ context 'invoking client methods' do
9
+ it '#running?' do
10
+ with_mocked(:vm_running?) do
11
+ subject.running?
12
+ end
13
+ end
14
+
15
+ it '#initial_snapshot_made?' do
16
+ with_mocked(:initial_snapshot_made_on_vm?) do
17
+ subject.initial_snapshot_made?
18
+ end
19
+ end
20
+
21
+ it '#start!' do
22
+ with_mocked(:start_vm) do
23
+ subject.start!
24
+ end
25
+ end
26
+
27
+ it '#make_initial_snapshot!' do
28
+ with_mocked(:make_initial_snapshot_on_vm) do
29
+ subject.make_initial_snapshot!
30
+ end
31
+ end
32
+
33
+ it 'should start machine and make initial snapshot on prepare' do
34
+ with_mocked(:vm_running?, :start_vm, :initial_snapshot_made_on_vm?, :make_initial_snapshot_on_vm) do
35
+ subject.prepare
36
+ end
37
+ end
38
+
39
+ it 'should check if machine is running and snapshot was made on prepared?' do
40
+ with_mocked(:initial_snapshot_made_on_vm?) do
41
+ allow(client).to receive(:vm_running?).and_return(true)
42
+ subject.prepared?
43
+ expect(client).to have_received(:vm_running?)
44
+ end
45
+ end
46
+
47
+ it '#ip' do
48
+ with_mocked(:vm_ip) do
49
+ subject.ip
50
+ end
51
+ end
52
+
53
+ it '#put_file' do
54
+ with_mocked(:put_file_to_vm) do
55
+ subject.put_file('/path', '/path')
56
+ end
57
+ end
58
+
59
+ it '#get_file' do
60
+ with_mocked(:get_file_from_vm) do
61
+ subject.get_file('/path', '/path')
62
+ end
63
+ end
64
+
65
+ it '#shutdown' do
66
+ with_mocked(:shutdown_vm) do
67
+ subject.shutdown
68
+ end
69
+ end
70
+
71
+ it '#rollback' do
72
+ with_mocked(:rollback_vm) do
73
+ subject.rollback
74
+ end
75
+ end
76
+
77
+ it '#execute' do
78
+ with_mocked(:execute_command_on_vm) do
79
+ subject.execute('echo 1')
80
+ end
81
+ end
82
+
83
+ it '#execute_as' do
84
+ with_mocked(:execute_command_on_vm) do
85
+ subject.execute_as(:root, 'echo 1')
86
+ end
87
+ end
88
+
89
+ it '#run_chef' do
90
+ with_mocked(:run_chef_on_vm) do
91
+ subject.run_chef({run_list: []})
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,12 @@
1
+ require 'foodtaster'
2
+ require 'support/test_server'
3
+
4
+ def with_mocked(*method_names)
5
+ method_names.each do |method_name|
6
+ allow(client).to receive(method_name)
7
+ end
8
+ yield
9
+ method_names.each do |method_name|
10
+ expect(client).to have_received(method_name)
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ require 'drb'
2
+
3
+ class TestServer
4
+ PORT = 4444
5
+
6
+ def self.start
7
+ DRb.start_service("druby://localhost:#{PORT}", self.new)
8
+ end
9
+
10
+ def self.stop
11
+ DRb.stop_service
12
+ end
13
+
14
+ def redirect_stdstreams(stdout, stderr)
15
+ end
16
+
17
+ def version
18
+ Foodtaster::VERSION
19
+ end
20
+ end
21
+
22
+
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: foodtaster
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.8
5
+ version: 0.0.9
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mike Lapshin
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-11-08 00:00:00.000000000 Z
13
+ date: 2013-12-03 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  prerelease: false
@@ -36,6 +36,7 @@ extensions: []
36
36
  extra_rdoc_files: []
37
37
  files:
38
38
  - .gitignore
39
+ - .rspec
39
40
  - Gemfile
40
41
  - LICENSE
41
42
  - README.md
@@ -45,7 +46,6 @@ files:
45
46
  - lib/foodtaster/client.rb
46
47
  - lib/foodtaster/config.rb
47
48
  - lib/foodtaster/rspec.rb
48
- - lib/foodtaster/rspec/config.rb
49
49
  - lib/foodtaster/rspec/dsl_methods.rb
50
50
  - lib/foodtaster/rspec/example_methods.rb
51
51
  - lib/foodtaster/rspec/matchers/file_matcher.rb
@@ -56,6 +56,11 @@ files:
56
56
  - lib/foodtaster/server_process.rb
57
57
  - lib/foodtaster/version.rb
58
58
  - lib/foodtaster/vm.rb
59
+ - spec/foodtaster/client_spec.rb
60
+ - spec/foodtaster/config_spec.rb
61
+ - spec/foodtaster/vm_spec.rb
62
+ - spec/spec_helper.rb
63
+ - spec/support/test_server.rb
59
64
  homepage: http://github.com/mlapshin/foodtaster
60
65
  licenses:
61
66
  - MIT
@@ -81,5 +86,10 @@ rubygems_version: 1.8.25
81
86
  signing_key:
82
87
  specification_version: 3
83
88
  summary: Foodtaster is a library for testing your Chef code with RSpec.
84
- test_files: []
89
+ test_files:
90
+ - spec/foodtaster/client_spec.rb
91
+ - spec/foodtaster/config_spec.rb
92
+ - spec/foodtaster/vm_spec.rb
93
+ - spec/spec_helper.rb
94
+ - spec/support/test_server.rb
85
95
  has_rdoc:
@@ -1,12 +0,0 @@
1
- RSpec::configure do |config|
2
- config.include Foodtaster::RSpec::ExampleMethods
3
- config.extend Foodtaster::RSpec::DslMethods
4
-
5
- config.before(:suite) do
6
- Foodtaster::RSpecRun.current.start
7
- end
8
-
9
- config.after(:suite) do
10
- Foodtaster::RSpecRun.current.stop
11
- end
12
- end