toft-puppet 0.0.9

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.
Files changed (66) hide show
  1. data/Gemfile +3 -0
  2. data/Gemfile.lock +62 -0
  3. data/Rakefile +121 -0
  4. data/features/checker.feature +14 -0
  5. data/features/chef.feature +70 -0
  6. data/features/command.feature +20 -0
  7. data/features/node.feature +41 -0
  8. data/features/puppet.feature +40 -0
  9. data/features/step_definitions/centos/checks.rb +9 -0
  10. data/features/step_definitions/checker.rb +15 -0
  11. data/features/step_definitions/chef.rb +43 -0
  12. data/features/step_definitions/command.rb +28 -0
  13. data/features/step_definitions/node.rb +65 -0
  14. data/features/step_definitions/puppet.rb +7 -0
  15. data/features/support/env.rb +25 -0
  16. data/fixtures/chef/attributes.json +9 -0
  17. data/fixtures/chef/cookbooks/test/attributes/default.rb +4 -0
  18. data/fixtures/chef/cookbooks/test/recipes/attribute.rb +19 -0
  19. data/fixtures/chef/cookbooks/test/recipes/default.rb +4 -0
  20. data/fixtures/chef/cookbooks/test/recipes/role.rb +4 -0
  21. data/fixtures/chef/roles/test.rb +3 -0
  22. data/fixtures/puppet/conf/fileserver.conf +3 -0
  23. data/fixtures/puppet/conf/puppet.conf +15 -0
  24. data/fixtures/puppet/conf/puppet_exec.conf +9 -0
  25. data/fixtures/puppet/conf/puppet_fileserver.conf +8 -0
  26. data/fixtures/puppet/conf/puppet_modules.conf +7 -0
  27. data/fixtures/puppet/conf/puppet_template.conf +8 -0
  28. data/fixtures/puppet/manifests/fileserver/conf/test_fileserver +1 -0
  29. data/fixtures/puppet/manifests/nodes/test_node.pp +26 -0
  30. data/fixtures/puppet/manifests/site.pp +1 -0
  31. data/fixtures/puppet/manifests/templates/template_test +2 -0
  32. data/fixtures/puppet/manifests/test.pp +8 -0
  33. data/fixtures/puppet/manifests/test_fileserver.pp +14 -0
  34. data/fixtures/puppet/manifests/test_install.pp +5 -0
  35. data/fixtures/puppet/manifests/test_module.pp +5 -0
  36. data/fixtures/puppet/manifests/test_service.pp +11 -0
  37. data/fixtures/puppet/manifests/test_template.pp +12 -0
  38. data/fixtures/puppet/modules/test_module/manifests/init.pp +8 -0
  39. data/lib/toft.rb +39 -0
  40. data/lib/toft/chef/chef_attributes.rb +29 -0
  41. data/lib/toft/chef/chef_runner.rb +77 -0
  42. data/lib/toft/command_executor.rb +16 -0
  43. data/lib/toft/file_checker.rb +47 -0
  44. data/lib/toft/node.rb +243 -0
  45. data/lib/toft/node_controller.rb +32 -0
  46. data/lib/toft/puppet/puppet_runner.rb +38 -0
  47. data/lib/toft/version.rb +3 -0
  48. data/scripts/bin/centos/lxc-prepare-host +172 -0
  49. data/scripts/bin/centos/provision_vagrant +11 -0
  50. data/scripts/bin/share/install-chef-ubuntu.sh +19 -0
  51. data/scripts/bin/share/lxc-create-centos-image +60 -0
  52. data/scripts/bin/ubuntu/lxc-create-ubuntu-image +77 -0
  53. data/scripts/bin/ubuntu/lxc-prepare-host +199 -0
  54. data/scripts/bin/ubuntu/provision_vagrant +9 -0
  55. data/scripts/lxc-templates/files/rc.local +38 -0
  56. data/scripts/lxc-templates/lxc-centos-6 +279 -0
  57. data/scripts/lxc-templates/lxc-lenny +255 -0
  58. data/scripts/lxc-templates/lxc-lucid +313 -0
  59. data/scripts/lxc-templates/lxc-natty +237 -0
  60. data/spec/fixtures/illegal_syntax.json +1 -0
  61. data/spec/spec_helper.rb +6 -0
  62. data/spec/toft/chef/chef_attributes_spec.rb +39 -0
  63. data/spec/toft/chef/chef_runner_spec.rb +34 -0
  64. data/spec/toft/node_spec.rb +18 -0
  65. data/spec/toft/puppet/puppet_runner_spec.rb +26 -0
  66. metadata +234 -0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,62 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ toft (0.0.8)
5
+ net-ssh
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ archive-tar-minitar (0.5.2)
11
+ builder (3.0.0)
12
+ cucumber (1.1.0)
13
+ builder (>= 2.1.2)
14
+ diff-lcs (>= 1.1.2)
15
+ gherkin (~> 2.5.0)
16
+ json (>= 1.4.6)
17
+ term-ansicolor (>= 1.0.6)
18
+ diff-lcs (1.1.3)
19
+ erubis (2.7.0)
20
+ ffi (1.0.9)
21
+ fpm (0.3.10)
22
+ json
23
+ gherkin (2.5.1)
24
+ json (>= 1.4.6)
25
+ i18n (0.6.0)
26
+ json (1.5.4)
27
+ net-scp (1.0.4)
28
+ net-ssh (>= 1.99.1)
29
+ net-ssh (2.1.4)
30
+ rake (0.9.2)
31
+ rspec (2.6.0)
32
+ rspec-core (~> 2.6.0)
33
+ rspec-expectations (~> 2.6.0)
34
+ rspec-mocks (~> 2.6.0)
35
+ rspec-core (2.6.4)
36
+ rspec-expectations (2.6.0)
37
+ diff-lcs (~> 1.1.2)
38
+ rspec-mocks (2.6.0)
39
+ term-ansicolor (1.0.6)
40
+ thor (0.14.6)
41
+ vagrant (0.8.7)
42
+ archive-tar-minitar (= 0.5.2)
43
+ erubis (~> 2.7.0)
44
+ i18n (~> 0.6.0)
45
+ json (~> 1.5.1)
46
+ net-scp (~> 1.0.4)
47
+ net-ssh (~> 2.1.4)
48
+ thor (~> 0.14.6)
49
+ virtualbox (~> 0.9.1)
50
+ virtualbox (0.9.2)
51
+ ffi (~> 1.0.9)
52
+
53
+ PLATFORMS
54
+ ruby
55
+
56
+ DEPENDENCIES
57
+ cucumber
58
+ fpm
59
+ rake
60
+ rspec
61
+ toft!
62
+ vagrant (>= 0.8.7)
data/Rakefile ADDED
@@ -0,0 +1,121 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ PROJECT_ROOT = File.dirname(__FILE__)
4
+ LXC_PACKAGE_NAME = "toft-lxc"
5
+
6
+ desc "clean artifacts"
7
+ task :clean do
8
+ `rm -rf pkg`
9
+ `rm -rf tmp`
10
+ end
11
+
12
+ desc "build gem and scripts package"
13
+ task :package => [:build, :package_deb, :package_rpm]
14
+
15
+ task :package_deb do
16
+ src_dir = "#{PROJECT_ROOT}/scripts"
17
+ content_dir = "#{PROJECT_ROOT}/pkg/#{LXC_PACKAGE_NAME}"
18
+ mkdir_p content_dir
19
+ mkdir_p "#{content_dir}/usr/bin"
20
+ mkdir_p "#{content_dir}/var/cache/lxc"
21
+ mkdir_p "#{content_dir}/usr/lib/lxc/templates"
22
+ cp_r Dir.glob("#{src_dir}/bin/share/*"), "#{content_dir}/usr/bin"
23
+ cp_r Dir.glob("#{src_dir}/bin/ubuntu/*"), "#{content_dir}/usr/bin"
24
+ cp_r Dir.glob("#{src_dir}/lxc-templates/*"), "#{content_dir}/usr/lib/lxc/templates"
25
+
26
+ post_install_script = <<-eos
27
+ #!/bin/sh -e
28
+ /usr/bin/lxc-prepare-host
29
+ eos
30
+ File.open("#{PROJECT_ROOT}/pkg/toft-lxc-post-install.sh", 'w') { |f| f.write(post_install_script) }
31
+
32
+ Dir.chdir("pkg") do
33
+ system <<-EOF
34
+ fpm -s dir \
35
+ -t deb \
36
+ -C #{content_dir} \
37
+ -a all \
38
+ -n #{LXC_PACKAGE_NAME} \
39
+ -v #{Toft::VERSION} \
40
+ -m "Huang Liang<exceedhl@gmail.com>" \
41
+ --description "lxc templates and helper provided by toft" \
42
+ -d sudo \
43
+ -d rpm \
44
+ -d dnsutils \
45
+ -d lxc \
46
+ -d bridge-utils \
47
+ -d debootstrap \
48
+ -d dhcp3-server \
49
+ -d bind9 \
50
+ -d ntp \
51
+ --replaces lxc \
52
+ --conflicts apparmor \
53
+ --conflicts apparmor-utils \
54
+ --post-install "#{PROJECT_ROOT}/pkg/toft-lxc-post-install.sh" \
55
+ .
56
+ EOF
57
+ end
58
+ end
59
+
60
+ task :package_rpm do
61
+ src_dir = "#{PROJECT_ROOT}/scripts"
62
+ content_dir = "#{PROJECT_ROOT}/pkg/#{LXC_PACKAGE_NAME}"
63
+ mkdir_p content_dir
64
+ mkdir_p "#{content_dir}/usr/bin"
65
+ mkdir_p "#{content_dir}/var/lib/lxc"
66
+ mkdir_p "#{content_dir}/var/cache/lxc"
67
+ mkdir_p "#{content_dir}/usr/lib/lxc/templates"
68
+ cp_r Dir.glob("#{src_dir}/bin/share/*"), "#{content_dir}/usr/bin"
69
+ cp_r Dir.glob("#{src_dir}/bin/centos/*"), "#{content_dir}/usr/bin"
70
+ cp_r Dir.glob("#{src_dir}/lxc-templates/*"), "#{content_dir}/usr/lib/lxc/templates"
71
+
72
+ pre_install_script = <<-eos
73
+ #!/bin/sh -e
74
+ # intsall lxc if not exist
75
+ if [[ ! -f /usr/bin/lxc-ls ]]; then
76
+ (cd /tmp && \
77
+ wget http://lxc.sourceforge.net/download/lxc/lxc-0.7.4.tar.gz && \
78
+ tar zxf lxc-0.7.4.tar.gz && \
79
+ cd lxc-0.7.4 && \
80
+ ./configure --prefix=/usr --with-config-path=/var/lib/lxc && \
81
+ make && \
82
+ make install)
83
+ fi
84
+ eos
85
+
86
+ post_install_script = <<-eos
87
+ #!/bin/sh -e
88
+ /usr/bin/lxc-prepare-host
89
+ eos
90
+ File.open("#{PROJECT_ROOT}/pkg/toft-lxc-pre-install.sh", 'w') { |f| f.write(pre_install_script) }
91
+ File.open("#{PROJECT_ROOT}/pkg/toft-lxc-post-install.sh", 'w') { |f| f.write(post_install_script) }
92
+
93
+ Dir.chdir("pkg") do
94
+ system <<-EOF
95
+ fpm -s dir \
96
+ -t rpm \
97
+ -C #{content_dir} \
98
+ -a all \
99
+ -n #{LXC_PACKAGE_NAME} \
100
+ -v #{Toft::VERSION} \
101
+ -m "Huang Liang<exceedhl@gmail.com>" \
102
+ --description "lxc templates and helper provided by toft" \
103
+ -d sudo \
104
+ -d bind-utils \
105
+ -d bridge-utils \
106
+ -d dhcp \
107
+ -d bind \
108
+ -d ntp \
109
+ -d libcap-devel \
110
+ --post-install "#{PROJECT_ROOT}/pkg/toft-lxc-post-install.sh" \
111
+ --pre-install "#{PROJECT_ROOT}/pkg/toft-lxc-pre-install.sh" \
112
+ .
113
+ EOF
114
+ end
115
+ end
116
+
117
+ desc "run all tests and features"
118
+ task :test do
119
+ `rspec spec`
120
+ `sudo cucumber features`
121
+ end
@@ -0,0 +1,14 @@
1
+ Feature: Checkers provided by Toft to help you verify system state
2
+
3
+ Scenario: Dir checker
4
+ Given I have a clean running node n1
5
+ Then Node "n1" should have "directory" "/tmp" owned by user "root" and group "root" with permission "1777"
6
+ Then Node "n1" should have not file or directory "/non-exist-dir"
7
+ Then Node "n1" should have file or directory "tmp"
8
+
9
+ Scenario: File checker
10
+ Given I have a clean running node n1
11
+ When Running ssh command "if getent passwd n1; then userdel -fr n1; fi; useradd -m n1" on "n1" should succeed
12
+ And Running ssh command "sudo -u n1 touch /tmp/a" on "n1" should succeed
13
+ Then Node "n1" should have file or directory "/tmp/a"
14
+ And Node "n1" should have "regular empty file" "/tmp/a" owned by user "n1" and group "n1" with permission "644"
@@ -0,0 +1,70 @@
1
+ Feature: Chef support
2
+
3
+ Scenario: Run chef recipe on nodes
4
+ Given I have a clean running node n1
5
+ When I run "recipe[test]" on node "n1"
6
+ Then Node "n1" should have file or directory "/tmp/stub/dir"
7
+
8
+ Scenario: Run chef recipe with attributes
9
+ Given I have a clean running node n1
10
+ When I run "recipe[test::attribute]" on node "n1" and overwrite attributes with:
11
+ |key|value|
12
+ |one|one|
13
+ |two.one|two_one|
14
+ |two.two|two_two|
15
+ |three|three|
16
+ Then Node "n1" should have file or directory "/tmp/stub/one"
17
+ Then Node "n1" should have file or directory "/tmp/stub/two_one"
18
+ Then Node "n1" should have file or directory "/tmp/stub/two_two"
19
+ Then Node "n1" should have file or directory "/tmp/stub/three"
20
+
21
+ Scenario: Run multiple chef recipes
22
+ Given I have a clean running node n1
23
+ When I run recipes on node "n1":
24
+ |recipe|
25
+ |recipe[test::role]|
26
+ |recipe[test]|
27
+ Then Node "n1" should have file or directory "/tmp/stub/dir"
28
+ Then Node "n1" should have file or directory "/tmp/stub/role"
29
+
30
+ Scenario: Run chef role
31
+ Given I have a clean running node n1
32
+ When I run "role[test]" on node "n1"
33
+ Then Node "n1" should have file or directory "/tmp/stub/role"
34
+
35
+ Scenario: Toft should not deal with empty cookbook and role path
36
+ Given I have a clean running node n1
37
+ When I set the role path to empty
38
+ Then Running chef "recipe[test]" on node "n1" should succeed
39
+ When I set the cookbook path to empty
40
+ Then Running chef "recipe[test]" on node "n1" should fail
41
+
42
+ Scenario: Run chef recipe with json attributes file
43
+ Given I have a clean running node n1
44
+ When I run "recipe[test::attribute]" on node "n1" and overwrite attributes with json file "attributes.json"
45
+ Then Node "n1" should have file or directory "/tmp/stub/one"
46
+ Then Node "n1" should have file or directory "/tmp/stub/two_one"
47
+ Then Node "n1" should have file or directory "/tmp/stub/two_two"
48
+ Then Node "n1" should have file or directory "/tmp/stub/three"
49
+
50
+ Scenario: Attributes table should override attributes in json file
51
+ Given I have a clean running node n1
52
+ When I run "recipe[test::attribute]" on node "n1" and overwrite attributes with json file "attributes.json" and chef attributes:
53
+ |key|value|
54
+ |one|override|
55
+ Then Node "n1" should have file or directory "/tmp/stub/override"
56
+ Then Node "n1" should have file or directory "/tmp/stub/two_one"
57
+ Then Node "n1" should have file or directory "/tmp/stub/two_two"
58
+ Then Node "n1" should have file or directory "/tmp/stub/three"
59
+
60
+ Scenario: Run non-exist recipe
61
+
62
+ Scenario: Run non-exist role
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
@@ -0,0 +1,20 @@
1
+ Feature: Run ssh command on node
2
+
3
+ Scenario: Run command on node successfully
4
+ Given I have a clean running node n1
5
+ Then Running ssh command "" on "n1" should fail
6
+ And Running ssh command "ps" on "n1" should succeed
7
+ And Running ssh command "non-exist-command" on "n1" should fail
8
+ And Running ssh command "netstat -nr" on "n1" should succeed
9
+
10
+ Scenario: Test rm
11
+ Given I have a clean running node n1
12
+ Then Rm "" on "n1" should fail
13
+ And Rm "tmp/*" on "n1" should fail
14
+ And Rm "/tmp/*" on "n1" should succeed
15
+
16
+ Scenario: Check ssh command result
17
+ Given I have a clean running node n1
18
+ Then the result of running ssh command "ps" on "n1" should contain "sshd"
19
+ Then the result of running ssh command "chef-solo" on "n1" should fail because of "No cookbook found"
20
+
@@ -0,0 +1,41 @@
1
+ Feature: Node management
2
+
3
+ Scenario: Start or stop node
4
+ Given I have a clean running node n1
5
+ Then the node "n1" should be running
6
+ When I stop node "n1"
7
+ Then the node "n1" should be stopped
8
+ When I start node "n1"
9
+ Then the node "n1" should be running
10
+
11
+ Scenario: Add and remove cnames for a node
12
+ Given I have a clean running node n1
13
+ And I add another node "n2"
14
+ When I add cname "cn1" to "n1"
15
+ Then Running ssh command "ping -c 1 cn1" on "n2" should succeed
16
+ When I remove cname "cn1" from "n1"
17
+ Then Running ssh command "ping -c 1 cn1" on "n2" should fail
18
+ And Node "n2" is destroyed
19
+
20
+ Scenario: Create node only by name and fetch their info
21
+ Given I have a clean running node n1
22
+ When I add another node "n3"
23
+ Then Running ssh command "ping -c 1 n1" on "n3" should succeed
24
+ And Running ssh command "ping -c 1 n3" on "n1" should succeed
25
+ And Node "n1" should have ip address same with that obtained from inside it through ssh
26
+ And Node "n3" should have ip address same with that obtained from inside it through ssh
27
+ And Hostname of Node "n1" should match its name
28
+ And Node "n3" is destroyed
29
+
30
+ Scenario: Create or destroy node
31
+ Given I have a clean running node n1
32
+ Then There should be 1 nodes in the environment
33
+ When I add another node "n2" with ip "192.168.20.3"
34
+ Then There should be 2 nodes in the environment
35
+ When I destroy node "n2"
36
+ Then There should be 1 nodes in the environment
37
+
38
+ Scenario: Change hostname used internally for a specific host
39
+ Given I have a clean running node n1
40
+ And I change the internal hostname for "n1" to "correct.puppet.com"
41
+ Then the result of running ssh command "hostname" on "n1" should contain "correct.puppet.com"
@@ -0,0 +1,40 @@
1
+ Feature: Puppet support
2
+
3
+ Scenario: Run Puppet manifest on nodes
4
+ Given I have a clean running node n1
5
+ When I run puppet manifest "test.pp" on node "n1"
6
+ Then Node "n1" should have file or directory "/tmp/puppet_test"
7
+
8
+ Scenario: Run puppet manifest with included nodes
9
+ Given I have a clean running node n1
10
+ And I change the internal hostname for "n1" to "correct.puppet.com"
11
+ And I run puppet manifest "site.pp" on node "n1"
12
+ Then Node "n1" should have file or directory "/tmp/puppet_test_correct"
13
+ And Node "n1" should have file or directory "/tmp/puppet_test_default"
14
+ And Node "n1" should have not file or directory "/tmp/puppet_test_incorrect"
15
+
16
+ Scenario: Run puppet manifest with modules
17
+ Given I have a clean running node n1
18
+ When I run puppet manifest "test_module.pp" with config file "puppet_modules.conf" on node "n1"
19
+ Then Node "n1" should have file or directory "/tmp/puppet_test_module"
20
+
21
+ Scenario: Run puppet manifest with static files being served by fileserver
22
+ Given I have a clean running node n1
23
+ When I run puppet manifest "test_fileserver.pp" with config file "puppet_fileserver.conf" on node "n1"
24
+ Then Node "n1" should have file or directory "/tmp/puppet_test_fileserver"
25
+
26
+ Scenario: Run puppet manifest with template dir configuration
27
+ Given I have a clean running node n1
28
+ When I run puppet manifest "test_template.pp" with config file "puppet_template.conf" on node "n1"
29
+ Then Node "n1" should have file or directory "/tmp/puppet_test_template"
30
+
31
+ Scenario: Check that package was installed on centos box
32
+ Given I have a clean running node n1
33
+ When I run puppet manifest "test_install.pp" on node "n1"
34
+ Then Node "n1" should have package "zip" installed in the centos box
35
+
36
+ Scenario: Check that service is running on centos box
37
+ Given I have a clean running node n1
38
+ When I run puppet manifest "test_service.pp" on node "n1"
39
+ Then Node "n1" should have service "named" running in the centos box
40
+
@@ -0,0 +1,9 @@
1
+ Then /^Node "([^"]*)" should have package "([^"]*)" installed in the centos box$/ do |node, package|
2
+ result = find(node).run_ssh("rpm -qa #{package}")
3
+ result.stdout.should include(package)
4
+ end
5
+
6
+ Then /^Node "([^"]*)" should have service "([^"]*)" running in the centos box$/ do |node, service|
7
+ result = find(node).run_ssh("ps -ef | grep -v grep | grep #{service} | wc -l")
8
+ result.stdout.strip!.should == "1"
9
+ end
@@ -0,0 +1,15 @@
1
+ Then /^Node "([^"]*)" should have not file or directory "([^"]*)"$/ do |node, dirpath|
2
+ find(node).file(dirpath).should_not be_exist
3
+ end
4
+
5
+ Then /^Node "([^"]*)" should have file or directory "([^"]*)"$/ do |node, dirpath|
6
+ find(node).file(dirpath).should be_exist
7
+ end
8
+
9
+ Then /^Node "([^"]*)" should have "([^"]*)" "([^"]*)" owned by user "([^"]*)" and group "([^"]*)" with permission "([^"]*)"$/ do |node, type, dirpath, user, group, mode|
10
+ file = find(node).file(dirpath)
11
+ file.filetype.should == type
12
+ file.owner.should == user
13
+ file.group.should == group
14
+ file.mode.should == mode
15
+ end
@@ -0,0 +1,43 @@
1
+ When /^I run "([^"]*)" on node "([^"]*)"$/ do |run_list, node|
2
+ find(node).run_chef run_list
3
+ end
4
+
5
+ When /^I run recipes on node "([^"]*)":$/ do |node, recipes_table|
6
+ recipes = []
7
+ recipes_table.hashes.each do |row|
8
+ recipes << row[:recipe]
9
+ end
10
+ find(node).run_chef recipes
11
+ end
12
+
13
+ When /^I run "([^"]*)" on node "([^"]*)" and overwrite attributes with:$/ do |run_list, node, table|
14
+ find(node).run_chef run_list, {:attributes => Toft::ChefAttributes.new(table)}
15
+ end
16
+
17
+ When /^I set the role path to empty$/ do
18
+ Toft.role_path = ""
19
+ @n1.rm "/tmp/*"
20
+ end
21
+
22
+ Then /^Running chef "([^"]*)" on node "([^"]*)" should succeed$/ do |run_list, node|
23
+ result = false
24
+ lambda { result = find(node).run_chef(run_list) }.should_not raise_error
25
+ result.should be_true
26
+ end
27
+
28
+ When /^I set the cookbook path to empty$/ do
29
+ Toft.cookbook_path = ""
30
+ @n1.rm "/tmp/*"
31
+ end
32
+
33
+ Then /^Running chef "([^"]*)" on node "([^"]*)" should fail$/ do |run_list, node|
34
+ lambda { find(node).run_chef(run_list) }.should raise_error
35
+ end
36
+
37
+ When /^I run "([^"]*)" on node "([^"]*)" and overwrite attributes with json file "([^"]*)"$/ do |run_list, node, json_file|
38
+ find(node).run_chef run_list, :json => CHEF_FIXTURE_PATH + '/attributes.json'
39
+ end
40
+
41
+ When /^I run "([^"]*)" on node "([^"]*)" and overwrite attributes with json file "([^"]*)" and chef attributes:$/ do |run_list, node, json_file, table|
42
+ find(node).run_chef run_list, {:json => CHEF_FIXTURE_PATH + '/attributes.json', :attributes => Toft::ChefAttributes.new(table)}
43
+ end