chef-dk 0.3.5 → 0.4.0

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +4 -4
  3. data/README.md +4 -4
  4. data/lib/chef-dk/builtin_commands.rb +4 -0
  5. data/lib/chef-dk/chef_runner.rb +7 -1
  6. data/lib/chef-dk/command/exec.rb +9 -0
  7. data/lib/chef-dk/command/export.rb +132 -0
  8. data/lib/chef-dk/command/generator_commands.rb +1 -1
  9. data/lib/chef-dk/command/generator_commands/app.rb +8 -0
  10. data/lib/chef-dk/command/generator_commands/base.rb +46 -4
  11. data/lib/chef-dk/command/generator_commands/cookbook.rb +8 -0
  12. data/lib/chef-dk/command/generator_commands/cookbook_code_file.rb +1 -0
  13. data/lib/chef-dk/command/push.rb +3 -6
  14. data/lib/chef-dk/command/shell_init.rb +28 -5
  15. data/lib/chef-dk/command/update.rb +106 -0
  16. data/lib/chef-dk/command/verify.rb +72 -0
  17. data/lib/chef-dk/component_test.rb +12 -1
  18. data/lib/chef-dk/configurable.rb +52 -0
  19. data/lib/chef-dk/cookbook_metadata.rb +10 -1
  20. data/lib/chef-dk/cookbook_profiler/git.rb +1 -1
  21. data/lib/chef-dk/exceptions.rb +17 -2
  22. data/lib/chef-dk/helpers.rb +2 -2
  23. data/lib/chef-dk/policyfile/community_cookbook_source.rb +1 -1
  24. data/lib/chef-dk/policyfile/dsl.rb +7 -0
  25. data/lib/chef-dk/policyfile/uploader.rb +25 -4
  26. data/lib/chef-dk/policyfile_compiler.rb +21 -1
  27. data/lib/chef-dk/policyfile_lock.rb +5 -0
  28. data/lib/chef-dk/policyfile_services/export_repo.rb +194 -0
  29. data/lib/chef-dk/policyfile_services/install.rb +8 -2
  30. data/lib/chef-dk/policyfile_services/push.rb +4 -1
  31. data/lib/chef-dk/service_exceptions.rb +6 -0
  32. data/lib/chef-dk/skeletons/code_generator/files/default/Berksfile +1 -1
  33. data/lib/chef-dk/skeletons/code_generator/files/default/repo/README.md +1 -1
  34. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/README.md +1 -1
  35. data/lib/chef-dk/skeletons/code_generator/files/default/repo/environments/README.md +2 -2
  36. data/lib/chef-dk/skeletons/code_generator/files/default/serverspec_spec_helper.rb +3 -0
  37. data/lib/chef-dk/skeletons/code_generator/files/default/spec_helper.rb +1 -7
  38. data/lib/chef-dk/skeletons/code_generator/metadata.rb +1 -1
  39. data/lib/chef-dk/skeletons/code_generator/recipes/app.rb +31 -1
  40. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook.rb +32 -2
  41. data/lib/chef-dk/skeletons/code_generator/recipes/recipe.rb +18 -0
  42. data/lib/chef-dk/skeletons/code_generator/templates/default/recipe.rb.erb +5 -0
  43. data/lib/chef-dk/skeletons/code_generator/templates/default/recipe_spec.rb.erb +23 -0
  44. data/lib/chef-dk/skeletons/code_generator/templates/default/serverspec_default_spec.rb.erb +12 -0
  45. data/lib/chef-dk/version.rb +1 -1
  46. data/lib/kitchen/provisioner/policyfile_zero.rb +149 -0
  47. data/spec/shared/a_file_generator.rb +1 -0
  48. data/spec/shared/command_with_ui_object.rb +11 -0
  49. data/spec/shared/custom_generator_cookbook.rb +117 -0
  50. data/spec/unit/chef_runner_spec.rb +26 -0
  51. data/spec/unit/command/exec_spec.rb +46 -5
  52. data/spec/unit/command/export_spec.rb +176 -0
  53. data/spec/unit/command/generator_commands/app_spec.rb +38 -0
  54. data/spec/unit/command/generator_commands/cookbook_spec.rb +37 -28
  55. data/spec/unit/command/generator_commands/recipe_spec.rb +4 -2
  56. data/spec/unit/command/install_spec.rb +3 -6
  57. data/spec/unit/command/push_spec.rb +3 -6
  58. data/spec/unit/command/shell_init_spec.rb +77 -49
  59. data/spec/unit/command/update_spec.rb +155 -0
  60. data/spec/unit/command/verify_spec.rb +22 -7
  61. data/spec/unit/cookbook_metadata_spec.rb +44 -8
  62. data/spec/unit/cookbook_profiler/git_spec.rb +12 -0
  63. data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/Berksfile +1 -1
  64. data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/Berksfile +1 -1
  65. data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/Berksfile +1 -1
  66. data/spec/unit/fixtures/cookbooks_api/small_universe.json +667 -667
  67. data/spec/unit/fixtures/cookbooks_api/universe.json +1 -1
  68. data/spec/unit/fixtures/cookbooks_api/update_fixtures.rb +1 -1
  69. data/spec/unit/fixtures/example_cookbook/Berksfile +1 -1
  70. data/spec/unit/fixtures/example_cookbook_metadata_json_only/.gitignore +17 -0
  71. data/spec/unit/fixtures/example_cookbook_metadata_json_only/.kitchen.yml +16 -0
  72. data/spec/unit/fixtures/example_cookbook_metadata_json_only/Berksfile +3 -0
  73. data/spec/unit/fixtures/example_cookbook_metadata_json_only/README.md +4 -0
  74. data/spec/unit/fixtures/example_cookbook_metadata_json_only/chefignore +96 -0
  75. data/spec/unit/fixtures/example_cookbook_metadata_json_only/metadata.json +5 -0
  76. data/spec/unit/fixtures/example_cookbook_metadata_json_only/recipes/default.rb +8 -0
  77. data/spec/unit/fixtures/example_cookbook_no_metadata/.gitignore +17 -0
  78. data/spec/unit/fixtures/example_cookbook_no_metadata/.kitchen.yml +16 -0
  79. data/spec/unit/fixtures/example_cookbook_no_metadata/Berksfile +3 -0
  80. data/spec/unit/fixtures/example_cookbook_no_metadata/README.md +4 -0
  81. data/spec/unit/fixtures/example_cookbook_no_metadata/chefignore +96 -0
  82. data/spec/unit/fixtures/example_cookbook_no_metadata/recipes/default.rb +8 -0
  83. data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/Berksfile +1 -1
  84. data/spec/unit/policyfile/community_cookbook_source_spec.rb +2 -2
  85. data/spec/unit/policyfile/cookbook_location_specification_spec.rb +3 -3
  86. data/spec/unit/policyfile/uploader_spec.rb +61 -25
  87. data/spec/unit/policyfile_demands_spec.rb +47 -0
  88. data/spec/unit/policyfile_evaluation_spec.rb +1 -1
  89. data/spec/unit/policyfile_lock_build_spec.rb +60 -3
  90. data/spec/unit/policyfile_services/export_repo_spec.rb +321 -0
  91. data/spec/unit/policyfile_services/install_spec.rb +20 -1
  92. data/spec/unit/policyfile_services/push_spec.rb +36 -9
  93. metadata +53 -38
  94. data/lib/chef-dk/skeletons/code_generator/files/default/converge_spec.rb +0 -9
  95. data/lib/chef-dk/skeletons/code_generator/templates/default/default_recipe.rb.erb +0 -5
@@ -0,0 +1,106 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2014 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef-dk/command/base'
19
+ require 'chef-dk/ui'
20
+ require 'chef-dk/policyfile_services/install'
21
+
22
+ module ChefDK
23
+ module Command
24
+
25
+ class Update < Base
26
+
27
+ banner(<<-BANNER)
28
+ Usage: chef update [ POLICY_FILE ] [options]
29
+
30
+ `chef update` reads your `Policyfile.rb`, applies any changes, re-solves the
31
+ dependencies and emits an updated `Policyfile.lock.json`. The new locked policy
32
+ will reflect any changes to the `run_list` and pull in any cookbook updates
33
+ that are compatible with the version constraints stated in your `Policyfile.rb`.
34
+
35
+ NOTE: `chef update` does not yet support granular updates (e.g., just updating
36
+ the `run_list` or a specific cookbook version). Support will be added in a
37
+ future version.
38
+
39
+ The Policyfile feature is incomplete and beta quality. See our detailed README
40
+ for more information.
41
+
42
+ https://github.com/opscode/chef-dk/blob/master/POLICYFILE_README.md
43
+
44
+ Options:
45
+
46
+ BANNER
47
+
48
+ option :debug,
49
+ short: "-D",
50
+ long: "--debug",
51
+ description: "Enable stacktraces and other debug output",
52
+ default: false
53
+
54
+ attr_reader :policyfile_relative_path
55
+
56
+ attr_accessor :ui
57
+
58
+ def initialize(*args)
59
+ super
60
+ @ui = UI.new
61
+
62
+ @policyfile_relative_path = nil
63
+ @installer = nil
64
+ end
65
+
66
+ def run(params = [])
67
+ apply_params!(params)
68
+ installer.run
69
+ 0
70
+ rescue PolicyfileServiceError => e
71
+ handle_error(e)
72
+ 1
73
+ end
74
+
75
+ def installer
76
+ @installer ||= PolicyfileServices::Install.new(policyfile: policyfile_relative_path, ui: ui, root_dir: Dir.pwd, overwrite: true)
77
+ end
78
+
79
+ def debug?
80
+ !!config[:debug]
81
+ end
82
+
83
+ def handle_error(error)
84
+ ui.err("Error: #{error.message}")
85
+ if error.respond_to?(:reason)
86
+ ui.err("Reason: #{error.reason}")
87
+ ui.err("")
88
+ ui.err(error.extended_error_info) if debug?
89
+ ui.err(error.cause.backtrace.join("\n")) if debug?
90
+ end
91
+ end
92
+
93
+ def apply_params!(params)
94
+ remaining_args = parse_options(params)
95
+ if remaining_args.size > 1
96
+ ui.err(banner)
97
+ return 1
98
+ else
99
+ @policyfile_relative_path = remaining_args.first
100
+ end
101
+ end
102
+
103
+ end
104
+ end
105
+ end
106
+
@@ -143,6 +143,78 @@ require 'spec_helper'
143
143
  end
144
144
  end
145
145
 
146
+ add_component "rubocop" do |c|
147
+ c.gem_base_dir = "rubocop"
148
+ c.smoke_test do
149
+ tmpdir do |cwd|
150
+ with_file(File.join(cwd, 'foo.rb')) do |f|
151
+ f.write <<-EOF
152
+ def foo
153
+ puts 'foo'
154
+ end
155
+ EOF
156
+ end
157
+ sh("rubocop foo.rb -l", cwd: cwd)
158
+ end
159
+ end
160
+ end
161
+
162
+ add_component "fauxhai" do |c|
163
+ c.gem_base_dir = "fauxhai"
164
+ c.smoke_test { sh("gem list fauxhai") }
165
+ end
166
+
167
+ add_component "knife-spork" do |c|
168
+ c.gem_base_dir = "knife-spork"
169
+ c.smoke_test { sh('knife spork info')}
170
+ end
171
+
172
+ add_component "kitchen-vagrant" do |c|
173
+ c.gem_base_dir = "kitchen-vagrant"
174
+ # The build is not passing in travis, so no tests
175
+ c.smoke_test { sh("gem list kitchen-vagrant") }
176
+ end
177
+
178
+ add_component "package installation" do |c|
179
+
180
+ c.base_dir = "chef-dk"
181
+
182
+ c.smoke_test do
183
+
184
+ if File.directory?("/usr/bin")
185
+ sh!("/usr/bin/berks -v")
186
+
187
+ sh!("/usr/bin/chef -v")
188
+
189
+ sh!("/usr/bin/chef-client -v")
190
+ sh!("/usr/bin/chef-solo -v")
191
+
192
+ # In `knife`, `knife -v` follows a different code path that skips
193
+ # command/plugin loading; `knife -h` loads commands and plugins, but
194
+ # it exits with code 1, which is the same as a load error. Running
195
+ # `knife exec` forces command loading to happen and this command
196
+ # exits 0, which runs most of the code.
197
+ #
198
+ # See also: https://github.com/opscode/chef-dk/issues/227
199
+ sh!("/usr/bin/knife exec -E true")
200
+
201
+ tmpdir do |dir|
202
+ # Kitchen tries to create a .kitchen dir even when just running
203
+ # `kitchen -v`:
204
+ sh!("/usr/bin/kitchen -v", cwd: dir)
205
+ end
206
+
207
+ sh!("/usr/bin/ohai -v")
208
+
209
+ sh!("/usr/bin/foodcritic -V")
210
+ end
211
+
212
+ # Test blocks are expected to return a Mixlib::ShellOut compatible
213
+ # object:
214
+ ComponentTest::NullTestResult.new
215
+ end
216
+ end
217
+
146
218
  attr_reader :verification_threads
147
219
  attr_reader :verification_results
148
220
  attr_reader :verification_status
@@ -88,6 +88,17 @@ module ChefDK
88
88
  system_command(command, combined_opts)
89
89
  end
90
90
 
91
+ # Just like #sh but raises an error if the the command returns an
92
+ # unexpected exit code.
93
+ #
94
+ # Most verification steps just run a single command, then
95
+ # ChefDK::Command::Verify#invoke_tests handles the results by inspecting
96
+ # the return value of the test block. For tests that run a lot of commands,
97
+ # this is inconvenient so you can use #sh! instead.
98
+ def sh!(*args)
99
+ sh(*args).tap { |result| result.error! }
100
+ end
101
+
91
102
  def run_in_tmpdir(command, options={})
92
103
  tmpdir do |dir|
93
104
  options[:cwd] = dir
@@ -103,7 +114,7 @@ module ChefDK
103
114
 
104
115
  def assert_present!
105
116
  unless File.exists?( component_path )
106
- raise MissingComponentError.new(name)
117
+ raise MissingComponentError.new(name, component_path)
107
118
  end
108
119
  end
109
120
 
@@ -0,0 +1,52 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2014 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef/config'
19
+ require 'chef/workstation_config_loader'
20
+
21
+ # Define a config context for ChefDK
22
+ class Chef::Config
23
+
24
+ default(:policy_document_native_api, false)
25
+
26
+ config_context(:chefdk) do
27
+
28
+ default(:generator_cookbook, File.expand_path("../skeletons/code_generator", __FILE__))
29
+
30
+ end
31
+ end
32
+
33
+ module ChefDK
34
+ module Configurable
35
+
36
+ def chef_config
37
+ return @chef_config if @chef_config
38
+ config_loader.load
39
+ @chef_config = Chef::Config
40
+ end
41
+
42
+ def chefdk_config
43
+ chef_config.chefdk
44
+ end
45
+
46
+ def config_loader
47
+ @config_loader ||= Chef::WorkstationConfigLoader.new(config[:config_file])
48
+ end
49
+
50
+ end
51
+ end
52
+
@@ -15,6 +15,7 @@
15
15
  # limitations under the License.
16
16
  #
17
17
 
18
+ require 'chef-dk/exceptions'
18
19
  require 'chef/cookbook/metadata'
19
20
 
20
21
  module ChefDK
@@ -24,8 +25,16 @@ module ChefDK
24
25
  class CookbookMetadata < Chef::Cookbook::Metadata
25
26
 
26
27
  def self.from_path(path)
28
+ metadata_json_path = File.join(path, "metadata.json")
27
29
  metadata_rb_path = File.join(path, "metadata.rb")
28
- new.tap { |m| m.from_file(metadata_rb_path) }
30
+
31
+ if File.exist?(metadata_json_path)
32
+ new.tap { |m| m.from_json(File.read(metadata_json_path)) }
33
+ elsif File.exist?(metadata_rb_path)
34
+ new.tap { |m| m.from_file(metadata_rb_path) }
35
+ else
36
+ raise MalformedCookbook, "Cookbook at #{path} has neither metadata.json or metadata.rb"
37
+ end
29
38
  end
30
39
 
31
40
  def cookbook_name
@@ -74,7 +74,7 @@ module ChefDK
74
74
  end
75
75
 
76
76
  def have_remote?
77
- !remote_name.empty?
77
+ !remote_name.empty? && remote_name != '.'
78
78
  end
79
79
 
80
80
  def current_branch
@@ -39,8 +39,8 @@ module ChefDK
39
39
  end
40
40
 
41
41
  class MissingComponentError < RuntimeError
42
- def initialize(component_name)
43
- super("Component #{component_name} is missing.")
42
+ def initialize(component_name, path_checked)
43
+ super("Component #{component_name} is missing. \nReason: Could not find #{path_checked}.")
44
44
  end
45
45
  end
46
46
 
@@ -65,4 +65,19 @@ module ChefDK
65
65
  class InvalidPolicyfileFilename < StandardError
66
66
  end
67
67
 
68
+ class ChefRunnerError < StandardError
69
+
70
+ attr_reader :cause
71
+
72
+ def initialize(message, cause)
73
+ super(message)
74
+ @cause = cause
75
+ end
76
+
77
+ end
78
+
79
+ class CookbookNotFound < ChefRunnerError; end
80
+
81
+ class ChefConvergeError < ChefRunnerError; end
82
+
68
83
  end
@@ -96,9 +96,9 @@ module ChefDK
96
96
  user_bin_dir = File.expand_path(File.join(Gem.user_dir, 'bin'))
97
97
  {
98
98
  'PATH' => [ omnibus_bin_dir, user_bin_dir, omnibus_embedded_bin_dir, ENV['PATH'] ].join(File::PATH_SEPARATOR),
99
- 'GEM_ROOT' => Gem.default_dir.inspect,
99
+ 'GEM_ROOT' => Gem.default_dir,
100
100
  'GEM_HOME' => Gem.user_dir,
101
- 'GEM_PATH' => Gem.path.join(':'),
101
+ 'GEM_PATH' => Gem.path.join(File::PATH_SEPARATOR),
102
102
  }
103
103
  end
104
104
  end
@@ -31,7 +31,7 @@ module ChefDK
31
31
  attr_reader :uri
32
32
 
33
33
  def initialize(uri = nil)
34
- @uri = uri || "https://supermarket.getchef.com"
34
+ @uri = uri || "https://supermarket.chef.io"
35
35
  @http_connections = {}
36
36
  end
37
37
 
@@ -32,12 +32,15 @@ module ChefDK
32
32
  attr_reader :default_source
33
33
  attr_reader :cookbook_location_specs
34
34
 
35
+ attr_reader :named_run_lists
36
+
35
37
  attr_reader :storage_config
36
38
 
37
39
  def initialize(storage_config)
38
40
  @name = nil
39
41
  @errors = []
40
42
  @run_list = []
43
+ @named_run_lists = {}
41
44
  @default_source = NullCookbookSource.new
42
45
  @cookbook_location_specs = {}
43
46
  @storage_config = storage_config
@@ -56,6 +59,10 @@ module ChefDK
56
59
  @run_list
57
60
  end
58
61
 
62
+ def named_run_list(name, *run_list_items)
63
+ @named_run_lists[name] = run_list_items.flatten
64
+ end
65
+
59
66
  def default_source(source_type = nil, source_uri = nil)
60
67
  return @default_source if source_type.nil?
61
68
  case source_type
@@ -34,21 +34,38 @@ module ChefDK
34
34
  attr_reader :http_client
35
35
  attr_reader :ui
36
36
 
37
- def initialize(policyfile_lock, policy_group, ui: nil, http_client: nil)
37
+ def initialize(policyfile_lock, policy_group, ui: nil, http_client: nil, policy_document_native_api: false)
38
38
  @policyfile_lock = policyfile_lock
39
39
  @policy_group = policy_group
40
40
  @http_client = http_client
41
41
  @ui = ui || UI.null
42
+ @policy_document_native_api = policy_document_native_api
42
43
 
43
44
  @cookbook_versions_for_policy = nil
44
45
  end
45
46
 
47
+ def policy_name
48
+ policyfile_lock.name
49
+ end
50
+
46
51
  def upload
47
52
  ui.msg("WARN: Uploading policy to policy group #{policy_group} in compatibility mode")
48
53
 
49
54
  upload_cookbooks
50
- data_bag_create
51
- data_bag_item_create
55
+ upload_policy
56
+ end
57
+
58
+ def upload_policy
59
+ if using_policy_document_native_api?
60
+ upload_policy_native
61
+ else
62
+ data_bag_create
63
+ data_bag_item_create
64
+ end
65
+ end
66
+
67
+ def upload_policy_native
68
+ http_client.put("/policies/#{policy_group}/#{policy_name}", policyfile_lock.to_lock)
52
69
  end
53
70
 
54
71
  def data_bag_create
@@ -58,7 +75,7 @@ module ChefDK
58
75
  end
59
76
 
60
77
  def data_bag_item_create
61
- policy_id = "#{policyfile_lock.name}-#{policy_group}"
78
+ policy_id = "#{policy_name}-#{policy_group}"
62
79
  lock_data = policyfile_lock.to_lock.dup
63
80
 
64
81
  lock_data["id"] = policy_id
@@ -114,6 +131,10 @@ module ChefDK
114
131
  end
115
132
  end
116
133
 
134
+ def using_policy_document_native_api?
135
+ @policy_document_native_api
136
+ end
137
+
117
138
  private
118
139
 
119
140
  def upload_cookbooks
@@ -44,6 +44,8 @@ module ChefDK
44
44
 
45
45
  def_delegator :@dsl, :name
46
46
  def_delegator :@dsl, :run_list
47
+ def_delegator :@dsl, :named_run_list
48
+ def_delegator :@dsl, :named_run_lists
47
49
  def_delegator :@dsl, :errors
48
50
  def_delegator :@dsl, :default_source
49
51
  def_delegator :@dsl, :cookbook_location_specs
@@ -81,6 +83,20 @@ module ChefDK
81
83
  expanded_run_list.map { |i| normalize_recipe(i) }
82
84
  end
83
85
 
86
+ def expanded_named_run_lists
87
+ named_run_lists.inject({}) do |expanded, (name, run_list_items)|
88
+ expanded[name] = Chef::RunList.new(*run_list_items)
89
+ expanded
90
+ end
91
+ end
92
+
93
+ def normalized_named_run_lists
94
+ expanded_named_run_lists.inject({}) do |normalized,(name, run_list)|
95
+ normalized[name] = run_list.map { |i| normalize_recipe(i) }
96
+ normalized
97
+ end
98
+ end
99
+
84
100
  def lock
85
101
  @policyfile_lock ||= PolicyfileLock.build_from_compiler(self, storage_config)
86
102
  end
@@ -205,7 +221,11 @@ module ChefDK
205
221
  end
206
222
 
207
223
  def cookbooks_in_run_list
208
- recipes = expanded_run_list.map {|recipe| recipe.name }
224
+ combined_run_lists = expanded_named_run_lists.values.inject(expanded_run_list.to_a) do |accum_run_lists, run_list|
225
+ accum_run_lists |= run_list.to_a
226
+ end
227
+
228
+ recipes = combined_run_lists.map {|recipe| recipe.name }
209
229
  recipes.map { |r| r[/^([^:]+)/, 1] }
210
230
  end
211
231