cloud-toaster 1.1.5 → 1.1.6

Sign up to get free protection for your applications and to get access to all the features.
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