cloud-toaster 1.1.5 → 1.1.6

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 (69) hide show
  1. checksums.yaml +8 -8
  2. data/Gemfile +5 -45
  3. data/README.md +2 -2
  4. data/VERSION +1 -1
  5. data/chef/cookbooks/lxc/recipes/setup_database.rb +12 -4
  6. data/chef/cookbooks/toaster/recipes/testing.rb +2 -2
  7. data/cloud-toaster.gemspec +94 -0
  8. data/config.json +3 -1
  9. data/lib/toaster/api.rb +25 -22
  10. data/lib/toaster/chef/chef_listener.rb +3 -3
  11. data/lib/toaster/chef/chef_node_inspector.rb +6 -4
  12. data/lib/toaster/chef/chef_util.rb +26 -8
  13. data/lib/toaster/chef/failsafe_resource_parser.rb +1 -0
  14. data/lib/toaster/chef/resource_inspector.rb +1 -1
  15. data/lib/toaster/model/automation.rb +26 -7
  16. data/lib/toaster/model/automation_run.rb +2 -11
  17. data/lib/toaster/model/key_value_pair.rb +13 -1
  18. data/lib/toaster/model/task.rb +3 -3
  19. data/lib/toaster/model/task_execution.rb +3 -2
  20. data/lib/toaster/model/task_parameter.rb +17 -24
  21. data/lib/toaster/state/convergence.rb +2 -2
  22. data/lib/toaster/state/idempotence.rb +13 -7
  23. data/lib/toaster/state/system_state.rb +1 -0
  24. data/lib/toaster/test/test_case.rb +10 -5
  25. data/lib/toaster/test/test_runner.rb +131 -124
  26. data/lib/toaster/test/test_suite.rb +1 -1
  27. data/lib/toaster/test_manager.rb +3 -9
  28. data/lib/toaster/toaster_app_service.rb +0 -4
  29. data/lib/toaster/util/config.rb +6 -1
  30. data/lib/toaster/util/lxc.rb +1 -1
  31. data/webapp/app/assets/javascripts/jstree.util.js +2 -1
  32. data/webapp/app/assets/stylesheets/application.css +21 -1
  33. data/webapp/app/assets/stylesheets/layout.css +1 -1
  34. data/webapp/app/controllers/analysis_controller.rb +12 -0
  35. data/webapp/app/controllers/application_controller.rb +11 -3
  36. data/webapp/app/controllers/base_controller.rb +1 -0
  37. data/webapp/app/controllers/execs_controller.rb +12 -4
  38. data/webapp/app/controllers/scripts_controller.rb +91 -52
  39. data/webapp/app/controllers/test_controller.rb +4 -4
  40. data/webapp/app/views/analysis/convergence.html.erb +14 -11
  41. data/webapp/app/views/analysis/idempotence.html.erb +40 -1
  42. data/webapp/app/views/analysis/index.html.erb +117 -0
  43. data/webapp/app/views/execs/automation_runs.html.erb +10 -4
  44. data/webapp/app/views/execs/task_executions.html.erb +20 -16
  45. data/webapp/app/views/layouts/application.html.erb +22 -9
  46. data/webapp/app/views/scripts/graph.html.erb +1 -1
  47. data/webapp/app/views/scripts/import_chef.html.erb +4 -0
  48. data/webapp/app/views/scripts/scripts.html.erb +5 -17
  49. data/webapp/app/views/settings/{index.html.erb → config.html.erb} +4 -6
  50. data/webapp/app/views/settings/containers.html.erb +7 -9
  51. data/webapp/app/views/test/gen.html.erb +1 -0
  52. data/webapp/app/views/test/suites.html.erb +1 -1
  53. data/webapp/app/views/util/chef.html.erb +2 -2
  54. data/webapp/config/initializers/devise.rb +4 -1
  55. data/webapp/config/routes.rb +15 -8
  56. data/webapp/log/development.log +39521 -0
  57. data/webapp/tmp/cache/assets/development/sprockets/0dc0562647e703ca0535da3b9fcad796 +0 -0
  58. data/webapp/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  59. data/webapp/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  60. data/webapp/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  61. data/webapp/tmp/cache/assets/development/sprockets/72cbfd5bf33945bcce154f7a4feaf04d +0 -0
  62. data/webapp/tmp/cache/assets/development/sprockets/7b2b7d9034fc7b77daf5da1436667e6f +0 -0
  63. data/webapp/tmp/cache/assets/development/sprockets/b6f1534bcdbff92a16c85487f363235a +0 -0
  64. data/webapp/tmp/cache/assets/development/sprockets/bfac6cd2984fbd5e0d762389e3c37164 +0 -0
  65. data/webapp/tmp/cache/assets/development/sprockets/c5907cfd07b24ad19b8c80e8af618a57 +0 -0
  66. data/webapp/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  67. data/webapp/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  68. data/webapp/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  69. metadata +53 -51
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZmI2MjQ0MGYzYjJhZmVhNjkwYjBiOWFiNWY2YjI5Y2EyZTRlNzE4Mg==
4
+ YWY2YTE5NDFmNjYyZjMwZmYzNjI0ZjQ0NGU1ZTJkNTRmNmJjNDRmMA==
5
5
  data.tar.gz: !binary |-
6
- NjdlYjdiMDA5Yzk0OWZkNzRmNDJjYjE0M2JhNWIyZjUxODg5N2ExZA==
6
+ YWE5ZjQzNzE5YTNhYWRkN2UwOTNiNDg0NjFjM2QwNTIyODc0MGZjMw==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- NGVjZjBiMDI2NDk4ZTZkYzc3YjY0YWRhMDFhNjgwN2ViZjc4Njg1ZGY1YzI5
10
- NDRjMmE1NDY3OGUzMThjNmMwNTE0YWZiNmUzNDkyODdmOWVlZWEyNjBjYWE4
11
- NTEyMGFmY2Q2Nzk1OGM2MjNmNjBmZDkwZDY5NTZkMGI5YzZjZTI=
9
+ NWVjNmM3ZTcwOGMxM2YyZDAzYzY3MDhkOWU5YmQ3OGZhNzJmOTQ5NzFiYzgw
10
+ ODdmMzMzZmExYzA3ZDcxYzU2ZDg5NGJhNzM1MDk1OTM4MTVkNDczNjhjNmQ4
11
+ OTY0MzUzZGM0MmE0NzExMjBlNGMxZDRjODc5NGQ1YzI2Y2EwZmE=
12
12
  data.tar.gz: !binary |-
13
- MGFlMDE4ZTBhOTE1YjRkNTA3Y2VlNDhmNDhiMWM2YThhMGNhOGM4N2Y4MzYz
14
- MGVkODAzMzkyYTRlNzQ3MTYxNDY2NjU3ZTE0ZmQ4MDBkMDI3YjAzNGJlODY0
15
- NGNjYzVlMWZjOWNhMjE0ZWU1MzE4YTgwMzU3NzlmYWVkNzdhMWY=
13
+ ZGY3NTg4YWY2ZjBlNTg3YmQ3NDE5MTJlZDRkNTRmMjQ4MzE4YWMzMjdjOTJl
14
+ Mzc2MGViYTFhN2NjYTU0ZWM3NTRkMDQxYTZjYThkNTAwMDFmM2MwNzU5NmE5
15
+ Mzc4N2RlYmI3MDczM2FmNmNiZjNjNDk3NmUyZThjZThlMTMzY2M=
data/Gemfile CHANGED
@@ -1,51 +1,11 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # RUBY ON RAILS DEPENDENCIES
4
-
5
- # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
6
- gem 'rails' #, '4.0.2'
7
- # Use sqlite3 as the database for Active Record
8
- gem 'sqlite3'
9
- # Use SCSS for stylesheets
10
- gem 'sass-rails' #, '~> 4.0.0'
11
- # Use Uglifier as compressor for JavaScript assets
12
- gem 'uglifier' #, '>= 1.3.0'
13
- # Use CoffeeScript for .js.coffee assets and views
14
- gem 'coffee-rails' #, '~> 4.0.0'
15
- # Use jquery as the JavaScript library
16
- gem 'jquery-rails'
17
- # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
18
- gem 'turbolinks'
19
- # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
20
- gem 'jbuilder' #, '~> 1.2'
21
- group :doc do
22
- # bundle exec rake doc:rails generates the API under doc/api.
23
- gem 'sdoc', require: false
3
+ # load gem dependencies from cloud-toaster.gemspec
4
+ deps = gemspec :name => 'cloud-toaster'
5
+ deps.each do |dep|
6
+ gem dep.name, dep.requirement
24
7
  end
25
- # Authentication module
26
- gem 'devise'
27
- # Use thin server (faster; prints less rails output/warnings)
28
- gem 'thin', '~> 1.6' # 14-07-08: default version 2.0.0.pre is incompatible
29
- # http://stackoverflow.com/questions/19579984/sinatra-server-wont-start-wrong-number-of-arguments
30
8
 
31
- # TOASTER DEPENDENCIES
32
- gem 'hashdiff' # diff hashes
33
- gem 'json'
34
- gem 'aquarium'
35
- gem 'jsonpath'
36
- gem 'open4' # open processes with stdin/stdout
37
- gem 'chef'
38
- gem 'ohai'
39
- gem 'rspec' # tests
40
- gem 'ruby_parser' # parse Ruby code
41
- gem 'bson'
42
- gem 'bson_ext'
43
- gem 'logger'
44
- gem 'thor' # CLI generator
45
- gem 'tidy' # tidy XML library
46
- gem 'diffy' # comparing source files
47
- gem 'mysql2' # for DB access
48
- gem 'therubyracer' # required by execjs
49
- gem 'railties'
9
+ # some overrides
50
10
  gem 'activesupport', :require => "active_support"
51
11
  gem 'activerecord', :require => "active_record"
data/README.md CHANGED
@@ -21,13 +21,13 @@ Automated testing of Infrastructure as Code automation scripts (e.g., Chef).
21
21
  sudo su -
22
22
 
23
23
  # prerequisites:
24
- apt-get -y install wget make bzip2 curl patch screen libgdbm-dev libyaml-dev libxml2-dev libxslt-dev libmysqlclient-dev libsqlite3-dev
24
+ apt-get -y install wget make bzip2 curl patch screen libgdbm-dev libyaml-dev libxml2-dev libxslt-dev libmysqlclient-dev libsqlite3-dev g++
25
25
  curl -L https://get.rvm.io | bash -s stable --ruby
26
26
  # (OR: install stable ruby versions from repo: apt-get install -y ruby ruby-dev)
27
27
  source /usr/local/rvm/scripts/rvm
28
28
 
29
29
  # install toaster gem:
30
- gem build toaster.gemspec
30
+ gem build cloud-toaster.gemspec
31
31
  gem install --no-ri --no-rdoc cloud-toaster-*version*.gem
32
32
 
33
33
  # (OR: install directly using rubygems.org: gem install cloud-toaster)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.5
1
+ 1.1.6
@@ -1,14 +1,22 @@
1
1
 
2
2
  if platform_family?("debian")
3
3
 
4
- node.set['mysql']['server_root_password'] = "root"
5
- include_recipe "mysql::server"
6
-
7
4
  root_dir = File.join(File.dirname(__FILE__), "..","..","..","..")
5
+ $LOAD_PATH << File.join(root_dir, "lib")
6
+ require 'toaster/util/config'
7
+
8
+ cfg_db_pass = Toaster::Config.get("db.password")
9
+ cfg_db_pass = "root" if "#{cfg_db_pass}".empty?
10
+ node.set['mysql']['server_root_password'] = cfg_db_pass
11
+ include_recipe "mysql::server"
8
12
 
9
13
  bash 'db_create' do
10
14
  code <<-EOH
11
- echo 'create database toaster;' | mysql -u root -p#{node['mysql']['server_root_password']}
15
+ db_pass=#{node['mysql']['server_root_password']}
16
+ ip_pattern=#{node["network"]["ip_pattern"].gsub('*','%')}
17
+ echo 'create database toaster;' | mysql -u root -p$db_pass
18
+ echo "GRANT ALL ON toaster.* TO 'root'@'$ip_pattern' IDENTIFIED BY '$db_pass';" | mysql -u root -p$db_pass
19
+ echo "FLUSH PRIVILEGES;" | mysql -u root -p$db_pass
12
20
  cd #{root_dir}/webapp && ./bin/rake db:migrate RAILS_ENV=development
13
21
  EOH
14
22
  not_if "echo \"show databases;\" | mysql -u root -p#{node['mysql']['server_root_password']} | grep toaster"
@@ -156,8 +156,8 @@ ruby_block $last_toaster_resource_name do
156
156
  {
157
157
  "db_type" => db_type,
158
158
  db_type => node['toaster'][db_type],
159
- "user_id" => node['user_id'],
160
- "automation_uuid" => node['automation_uuid'],
159
+ "user_id" => node['toaster']['user_id'],
160
+ "automation_uuid" => node['toaster']['automation_uuid'],
161
161
  "cookbook_paths" => node['toaster']['cookbook_paths'],
162
162
  "skip_tasks" => node['toaster']['skip_tasks'],
163
163
  "repeat_tasks" => node['toaster']['repeat_tasks'],
@@ -0,0 +1,94 @@
1
+ require 'date'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{cloud-toaster}
5
+ s.version = File.exist?('VERSION') ? File.read('VERSION').strip : ""
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = [ %q{Waldemar Hummer} ]
9
+ s.date = DateTime.now.strftime("%Y-%m-%d")
10
+ s.description = %q{A tool for automated testing and debugging of automation scripts (e.g., Chef).}
11
+ s.email = [%q{hummer@infosys.tuwien.ac.at}]
12
+ s.extra_rdoc_files = [
13
+ "LICENSE",
14
+ "Rakefile",
15
+ "README.md",
16
+ "VERSION"
17
+ ]
18
+ s.files = Dir.glob("lib/**/*") + Dir.glob("bin/*") +
19
+ Dir.glob("bin/strace-4.8_patched/strace-x86_64") +
20
+ Dir.glob("bin/strace-4.8_patched/strace-i686") +
21
+ Dir.glob("chef/**/*") + Dir.glob("webapp/**/*") +
22
+ Dir.glob("config.json") + Dir.glob("Gemfile") +
23
+ Dir.glob("cloud-toaster.gemspec")
24
+
25
+ deps = {
26
+ 'bundler' => '~> 1.3',
27
+ # RUBY ON RAILS DEPENDENCIES
28
+ 'rails' => '>= 0', #, '4.0.2'
29
+ 'sqlite3' => '>= 0',
30
+ 'sass-rails' => '>= 0', #, '~> 4.0.0'
31
+ 'uglifier' => '>= 0', #, '>= 1.3.0'
32
+ 'coffee-rails' => '>= 0', #, '~> 4.0.0'
33
+ 'jquery-rails' => '>= 0',
34
+ 'turbolinks' => '>= 0',
35
+ 'jbuilder' => '>= 0', #, '~> 1.2'
36
+ 'devise' => '>= 0',
37
+ 'thin' => '~> 1.6', # 14-07-08: default version 2.0.0.pre is incompatible
38
+ # http://stackoverflow.com/questions/19579984/sinatra-server-wont-start-wrong-number-of-arguments
39
+
40
+ # TOASTER DEPENDENCIES
41
+ 'hashdiff' => '>= 0', # diff hashes
42
+ 'json' => '>= 0',
43
+ 'aquarium' => '>= 0',
44
+ 'jsonpath' => '>= 0',
45
+ 'open4' => '>= 0', # open processes with stdin/stdout
46
+ 'chef' => '>= 0',
47
+ 'ohai' => '>= 0',
48
+ 'rspec' => '>= 0', # tests
49
+ 'ruby_parser' => '>= 0', # parse Ruby code
50
+ 'bson' => '>= 0',
51
+ 'bson_ext' => '>= 0',
52
+ 'logger' => '>= 0',
53
+ 'thor' => '>= 0', # CLI generator
54
+ 'tidy' => '>= 0', # tidy XML library
55
+ 'diffy' => '>= 0', # comparing source files
56
+ 'mysql2' => '>= 0', # for DB access
57
+ 'therubyracer' => '>= 0', # required by execjs
58
+ 'railties' => '>= 0',
59
+ 'activesupport' => '>= 0',
60
+ 'activerecord' => '>= 0'
61
+ }
62
+
63
+ #deps = File.read('Gemfile').scan(/^\s*gem\s*['"]([^'"]+)['"]/).uniq
64
+
65
+ deps.each do |dep,version|
66
+ #dep = matched_dep[0]
67
+ #version = matched_dep[2]
68
+ #puts "#{dep} - #{version}"
69
+ if version && !version.empty?
70
+ #s.add_runtime_dependency dep, version
71
+ s.add_development_dependency dep, version
72
+ else
73
+ #s.add_runtime_dependency dep
74
+ s.add_development_dependency dep
75
+ end
76
+
77
+ end
78
+
79
+ # further project dependencies:
80
+ # * MySQL server
81
+ # * Squid proxy server # License: GNU GPL v2.0
82
+ # * docker.io # License: Apache v2.0
83
+ # * strace # License: BSD
84
+
85
+
86
+ s.homepage = %q{https://github.com/whummer/toaster}
87
+ s.licenses = [%q{Apache v2.0}]
88
+ s.require_paths = [%q{lib}]
89
+ s.rubygems_version = %q{1.8.9}
90
+ s.summary = %q{Automated Testing/Debugging of Automation Scripts.}
91
+ s.executables << "toaster"
92
+
93
+ end
94
+
@@ -19,10 +19,12 @@
19
19
 
20
20
  "testing": {
21
21
  "timeservice_url" : "http://www.infosys.tuwien.ac.at/staff/hummer/tmp/time.php",
22
- "test_hosts" : ["localhost"]
22
+ "test_hosts" : ["localhost"],
23
+ "max_threads" : 8
23
24
  },
24
25
  "db": {
25
26
  "host": "localhost",
27
+ "host_from_container": "192.168.100.2",
26
28
  "port": 3306,
27
29
  "database": "toaster",
28
30
  "username": "root",
@@ -182,14 +182,14 @@ module Toaster
182
182
  else
183
183
  puts "INFO: Running/continuing tests for test suite '#{test_suite_uuid}'"
184
184
  test_suite = test_suites[0]
185
- test_suite.coverage_goal.idempotence = idem_N if idem_N
186
- test_suite.coverage_goal.combinations[Toaster::CombinationCoverage::SKIP_N] = skip_N if skip_N
187
- test_suite.coverage_goal.combinations[Toaster::CombinationCoverage::SKIP_N_SUCCESSIVE] = skip_N_succ if skip_N_succ
188
- test_suite.coverage_goal.combinations[Toaster::CombinationCoverage::COMBINE_N] = combine_N if combine_N
189
- test_suite.coverage_goal.combinations[Toaster::CombinationCoverage::COMBINE_N_SUCCESSIVE] = combine_N_succ if combine_N_succ
190
- test_suite.save()
185
+ # test_suite.coverage_goal.idempotence = idem_N if idem_N
186
+ # test_suite.coverage_goal.combinations[Toaster::CombinationCoverage::SKIP_N] = skip_N if skip_N
187
+ # test_suite.coverage_goal.combinations[Toaster::CombinationCoverage::SKIP_N_SUCCESSIVE] = skip_N_succ if skip_N_succ
188
+ # test_suite.coverage_goal.combinations[Toaster::CombinationCoverage::COMBINE_N] = combine_N if combine_N
189
+ # test_suite.coverage_goal.combinations[Toaster::CombinationCoverage::COMBINE_N_SUCCESSIVE] = combine_N_succ if combine_N_succ
190
+ # test_suite.save()
191
191
  orch = Toaster::TestOrchestrator.new
192
- orch.generate_tests_for_suite(test_suite)
192
+ # orch.generate_tests_for_suite(test_suite)
193
193
  if Config.get("testing.test_hosts").kind_of?(Array)
194
194
  Config.get("testing.test_hosts").each do |test_host|
195
195
  orch.add_host(test_host)
@@ -264,7 +264,7 @@ module Toaster
264
264
  require "toaster/toaster_app_service"
265
265
  ToasterAppService.start_service()
266
266
  end
267
-
267
+
268
268
  # Clean spawned containers
269
269
  desc "clean", "Clean all spawned containers (prototypes will be preserved)."
270
270
  def clean()
@@ -272,15 +272,25 @@ module Toaster
272
272
  Toaster::LXC.clean()
273
273
  end
274
274
 
275
+ # Print version information
276
+ desc "version", "Print version of ToASTER."
277
+ def version()
278
+ file = File.join(File.dirname(__FILE__), "..", "..", "VERSION")
279
+ version = File.read(file)
280
+ puts version
281
+ return "#{version}".strip
282
+ end
283
+
275
284
  # Start web app
276
285
  desc "web", "Start the Web application. (params: --detached=false)"
277
- #option :detached, :type => :boolean, :aliases => ["-d"]
286
+ option :detached, :type => :boolean, :aliases => ["-d"]
278
287
  def web(detached=false)
279
288
  puts "INFO: Starting Web application on port 8080"
280
289
  dir = File.join(File.dirname(__FILE__), "..", "..")
281
290
  cmd = "cd \"#{dir}\" && #{dir}/webapp/bin/rails server thin"
291
+ detached ||= options[:detached]
282
292
  if detached
283
- Kernel::exec("screen -d -m #{cmd}")
293
+ Kernel::exec("screen -d -m bash -c '#{cmd}'")
284
294
  else
285
295
  Kernel::exec("#{cmd}")
286
296
  end
@@ -305,8 +315,7 @@ module Toaster
305
315
  test_case_uuids = test_case_uuid.split(/[ ;,]+/)
306
316
  test_cases = TestCase.find(:uuid => test_case_uuids[0]).to_a
307
317
  if !test_cases || test_cases.empty?
308
- puts "ERROR: Invalid test case id(s) specified: '#{test_case_uuid}'"
309
- puts "database: #{Toaster::Config.get("db.host")}"
318
+ puts "ERROR: Invalid test case id(s) specified: '#{test_case_uuid}' (DB host: #{Toaster::Config.get("db.host")})"
310
319
  else
311
320
 
312
321
  # set the start time of all test cases. This is important
@@ -328,15 +337,8 @@ module Toaster
328
337
  TestRunner.execute_test(test_case, destroy_container, print_output)
329
338
  else
330
339
  puts "INFO: Scheduling test cases #{test_case_uuids} for test suite uuid '#{test_suite_uuid}'"
331
- if $test_runners[test_suite_uuid]
332
- runner = $test_runners[test_suite_uuid]
333
- runner.schedule_tests(test_suite, test_case_uuids)
334
- else
335
- runner = TestRunner.new(test_suite, num_threads, true)
336
- runner.schedule_tests(test_suite, test_case_uuids)
337
- runner.start_worker_threads()
338
- $test_runners[test_suite_uuid] = runner
339
- end
340
+ runner = TestRunner.instance
341
+ runner.schedule_tests(test_suite, test_case_uuids)
340
342
  end
341
343
  end
342
344
  end
@@ -366,8 +368,9 @@ module Toaster
366
368
  EOF
367
369
  )
368
370
  end
369
- puts "INFO: Running Chef scripts..."
370
371
  require "toaster/chef/chef_util"
372
+ Toaster::ChefUtil.create_chef_config(CHEF_TMP_SOLO_FILE)
373
+ puts "INFO: Running Chef scripts..."
371
374
  Toaster::ChefUtil.run_chef(CHEF_TMP_SOLO_FILE, CHEF_TMP_NODE_FILE, print_output)
372
375
  end
373
376
  def parse_recipes(arg)
@@ -148,9 +148,9 @@ module Toaster
148
148
  # try to retrieve automation from DB, if it exists..
149
149
  if File.exist?(json_file)
150
150
  attribs = JSON.parse(File.read(json_file))
151
- if attribs["automation_uuid"]
151
+ if attribs["toaster"] && attribs["toaster"]["automation_uuid"]
152
152
  autos = Toaster::Automation.find(
153
- :uuid => attribs["automation_uuid"]).to_a
153
+ :uuid => attribs["toaster"]["automation_uuid"]).to_a
154
154
  if !autos.empty?
155
155
  run.automation = autos[0]
156
156
  return
@@ -432,7 +432,7 @@ module Toaster
432
432
  end
433
433
  end
434
434
  task = get_task_from_sourcecode_line(resource, action, source_line_spec)
435
- puts "get task #{resource} #{action} #{source_line_spec}: #{task}"
435
+ #puts "get task #{resource} #{action} #{source_line_spec}: #{task}"
436
436
  end
437
437
 
438
438
  # check if we execute within an "immediate notification"
@@ -110,7 +110,8 @@ module Toaster
110
110
  public
111
111
 
112
112
  # * chef_paths - Chef dirs on local filesystem
113
- def initialize(chef_paths, processor = nil, &error_reporting)
113
+ def initialize(chef_paths = [ChefUtil.DEFAULT_OPSCODE_TMP_DIR,
114
+ ChefUtil.DEFAULT_COOKBOOKS_DIR], processor = nil, &error_reporting)
114
115
  @chef_paths = chef_paths
115
116
  @processor = processor
116
117
  raise "Invalid 'error_reporting'" if error_reporting.nil?
@@ -125,10 +126,11 @@ module Toaster
125
126
  return {}
126
127
  end
127
128
 
128
- default_file = get_filename("cookbooks/" + cookbook_name + "/attributes/#{recipe_name}.rb")
129
+ file_name = cookbook_name + "/attributes/#{recipe_name}.rb"
130
+ default_file = get_filename(file_name)
129
131
 
130
132
  if default_file.nil?
131
- @error_reporting.call(Logger::INFO, "Unknown default file #{("cookbooks/" + cookbook_name + "/attributes/#{recipe_name}.rb").inspect}")
133
+ @error_reporting.call(Logger::INFO, "Unknown attribute file '#{file_name.inspect}'")
132
134
  return {}
133
135
  end
134
136
 
@@ -156,7 +158,7 @@ module Toaster
156
158
  end
157
159
 
158
160
  # No such file
159
- @@logger.info "File not found '#{filename}'"
161
+ @@logger.info "File not found '#{filename}' in paths #{@chef_paths}"
160
162
  return nil
161
163
  end
162
164
 
@@ -43,6 +43,17 @@ module Toaster
43
43
 
44
44
  @@DEFAULT_CHEF_DIR = "/tmp/toaster_cookbooks/"
45
45
  @@DEFAULT_COOKBOOKS_DIR = "#{@@DEFAULT_CHEF_DIR}/cookbooks/"
46
+ @@DEFAULT_OPSCODE_TMP_DIR = "/tmp/opscode_cookbooks/" # TODO merge with above?
47
+
48
+ def self.DEFAULT_CHEF_DIR
49
+ @@DEFAULT_CHEF_DIR
50
+ end
51
+ def self.DEFAULT_COOKBOOKS_DIR
52
+ @@DEFAULT_COOKBOOKS_DIR
53
+ end
54
+ def self.DEFAULT_OPSCODE_TMP_DIR
55
+ @@DEFAULT_OPSCODE_TMP_DIR
56
+ end
46
57
 
47
58
  def self.guess_cookbook_from_runlist(runlist)
48
59
  guess_cookbook_or_recipe_from_runlist(runlist, "cookbook")
@@ -322,7 +333,7 @@ module Toaster
322
333
 
323
334
  cookbooks_after = Dir.entries(target_dir)
324
335
  new_cb = cookbooks_after - cookbooks_before
325
- puts "INFO: Downloaded and installed new cookbooks: #{new_cb}"
336
+ puts "INFO: Downloaded and installed new cookbooks: #{new_cb}" if !new_cb.empty?
326
337
 
327
338
  # download dependencies
328
339
  new_cb.each do |cb|
@@ -591,7 +602,7 @@ module Toaster
591
602
  end
592
603
 
593
604
  def self.available_recipes_from_opscode(cookbook_name, version="latest",
594
- overwrite_downloads=false, target_dir="/tmp/opscode_cookbooks/")
605
+ overwrite_downloads=false, target_dir=@@DEFAULT_OPSCODE_TMP_DIR)
595
606
  if target_dir
596
607
  FileUtils.mkpath(target_dir) if !File.directory?(target_dir)
597
608
  # check if cookbook folder already exists
@@ -699,6 +710,12 @@ module Toaster
699
710
  url = "#{OPSCODE_API_URL}cookbooks/#{cookbook_name}/"
700
711
  json = `curl '#{url}' 2> /dev/null`
701
712
  details = MarkupUtil.parse_json(json.strip)
713
+ if !details['latest_version']
714
+ if details['error_code']
715
+ raise "WARN: Unable to fetch cookbook metadata from #{url}: " +
716
+ "#{details['error_code']} - #{details['error_messages']}"
717
+ end
718
+ end
702
719
  latest_version = details['latest_version'].gsub(/.*\/([^\/]+)/, '\1')
703
720
  cbook['_latest_version'] = latest_version
704
721
  versions = []
@@ -747,7 +764,7 @@ module Toaster
747
764
  fetch_cookbook_details(cookbook_name)["_versions"].uniq
748
765
  end
749
766
 
750
- def self.download_all_from_opscode(target_dir="/tmp/opscode_cookbooks/", overwrite_downloads=false)
767
+ def self.download_all_from_opscode(target_dir=@@DEFAULT_OPSCODE_TMP_DIR, overwrite_downloads=false)
751
768
  target_dir = "/tmp/opscode_cookbooks/" if !target_dir
752
769
  if overwrite_downloads || !File.exist?(target_dir)
753
770
  `mkdir -p "#{target_dir}"`
@@ -760,7 +777,8 @@ module Toaster
760
777
  end
761
778
  end
762
779
 
763
- def self.parse_resources(cookbook, recipe_name, version="latest", result = {}, cookbook_dir="/tmp/opscode_cookbooks/")
780
+ def self.parse_resources(cookbook, recipe_name, version="latest",
781
+ result = {}, cookbook_dir=@@DEFAULT_OPSCODE_TMP_DIR)
764
782
  recipe_file = "#{cookbook_dir}/#{cookbook}/recipes/#{recipe_name}.rb"
765
783
  attributes_file = "#{cookbook_dir}/#{cookbook}/attributes/#{recipe_name}.rb"
766
784
  recipe_file_relative = "#{cookbook}/recipes/#{recipe_name}.rb"
@@ -795,7 +813,7 @@ module Toaster
795
813
 
796
814
  File.open(recipe_file) do |io|
797
815
  io.each_with_index { |line,idx|
798
- #if line.match(/^\s*((#{resource_names.join(")|(")}))\s+.*((do)|(\{)).*$/)
816
+ idx += 1 # index is 0-based, line should be 1-based
799
817
  if line.match(/^(\s*[0-9a-zA-Z_]+\s*=\s*)?\s*((#{resource_names.join(")|(")}))((\s+)|($)|(\s*\())/)
800
818
  resource_lines << idx
801
819
  elsif line.match(/execute.*do/) && !line.match(/^\s*#/)
@@ -803,9 +821,9 @@ module Toaster
803
821
  end
804
822
  }
805
823
  resource_lines.each do |line|
806
- code = read_sourcecode_from_line(recipe_file, line + 1)
824
+ code = read_sourcecode_from_line(recipe_file, line)
807
825
  if !code
808
- puts "WARN: Could not parse code file #{recipe_file} : #{line + 1}"
826
+ puts "WARN: Could not parse code file #{recipe_file} : #{line}"
809
827
  else
810
828
  resource_obj = ResourceInspector.get_resource_from_source(code, attributes_source)
811
829
  result[cookbook][recipe_name]["resources"][line] = code
@@ -822,7 +840,7 @@ module Toaster
822
840
  return result
823
841
  end
824
842
 
825
- def self.parse_all_resources(recipe_pattern="default.rb", cookbook_dir="/tmp/opscode_cookbooks/")
843
+ def self.parse_all_resources(recipe_pattern="default.rb", cookbook_dir=@@DEFAULT_OPSCODE_TMP_DIR)
826
844
  # cookbook_name -> recipe_file -> line_no -> resource_code
827
845
  result = {}
828
846
  scanned_files = 0