chef 12.0.0.rc.0-x86-mingw32 → 12.0.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +1 -1
  3. data/lib/chef/api_client/registration.rb +3 -1
  4. data/lib/chef/chef_fs/data_handler/group_data_handler.rb +4 -0
  5. data/lib/chef/config.rb +46 -38
  6. data/lib/chef/event_loggers/windows_eventlog.rb +5 -6
  7. data/lib/chef/exceptions.rb +13 -1
  8. data/lib/chef/file_content_management/tempfile.rb +33 -5
  9. data/lib/chef/knife.rb +11 -3
  10. data/lib/chef/knife/bootstrap.rb +8 -7
  11. data/lib/chef/mixin/deep_merge.rb +15 -54
  12. data/lib/chef/mixin/which.rb +37 -0
  13. data/lib/chef/node.rb +14 -25
  14. data/lib/chef/node/attribute.rb +227 -41
  15. data/lib/chef/node/attribute_collections.rb +117 -3
  16. data/lib/chef/node/immutable_collections.rb +6 -6
  17. data/lib/chef/platform/provider_priority_map.rb +3 -2
  18. data/lib/chef/platform/service_helpers.rb +37 -8
  19. data/lib/chef/provider/service/aixinit.rb +1 -1
  20. data/lib/chef/provider/service/arch.rb +1 -1
  21. data/lib/chef/provider/service/debian.rb +5 -1
  22. data/lib/chef/provider/service/init.rb +4 -0
  23. data/lib/chef/provider/service/insserv.rb +5 -1
  24. data/lib/chef/provider/service/invokercd.rb +5 -1
  25. data/lib/chef/provider/service/redhat.rb +5 -1
  26. data/lib/chef/provider/service/systemd.rb +50 -32
  27. data/lib/chef/provider/service/upstart.rb +5 -2
  28. data/lib/chef/provider_resolver.rb +30 -16
  29. data/lib/chef/resource.rb +2 -1
  30. data/lib/chef/resources.rb +7 -0
  31. data/lib/chef/run_context.rb +0 -5
  32. data/lib/chef/run_list/run_list_expansion.rb +2 -2
  33. data/lib/chef/shell.rb +2 -2
  34. data/lib/chef/util/selinux.rb +2 -10
  35. data/lib/chef/version.rb +1 -1
  36. data/lib/chef/workstation_config_loader.rb +1 -1
  37. data/spec/support/shared/unit/resource/static_provider_resolution.rb +1 -6
  38. data/spec/unit/api_client/registration_spec.rb +22 -0
  39. data/spec/unit/application/knife_spec.rb +6 -2
  40. data/spec/unit/chef_fs/data_handler/group_handler_spec.rb +63 -0
  41. data/spec/unit/config_spec.rb +5 -5
  42. data/spec/unit/knife/bootstrap_spec.rb +27 -1
  43. data/spec/unit/knife_spec.rb +5 -0
  44. data/spec/unit/mixin/deep_merge_spec.rb +0 -40
  45. data/spec/unit/node/attribute_spec.rb +37 -50
  46. data/spec/unit/node_spec.rb +321 -13
  47. data/spec/unit/provider/file/content_spec.rb +23 -2
  48. data/spec/unit/provider/service/systemd_service_spec.rb +173 -158
  49. data/spec/unit/provider_resolver_spec.rb +175 -10
  50. data/spec/unit/resource/timestamped_deploy_spec.rb +8 -29
  51. data/spec/unit/runner_spec.rb +3 -1
  52. metadata +147 -221
  53. data/spec/.DS_Store +0 -0
  54. data/spec/data/.DS_Store +0 -0
  55. data/spec/data/lwrp/.DS_Store +0 -0
  56. data/spec/data/lwrp/providers/.DS_Store +0 -0
  57. data/spec/data/lwrp/resources/.DS_Store +0 -0
  58. data/spec/data/lwrp_override/.DS_Store +0 -0
  59. data/spec/data/lwrp_override/providers/.DS_Store +0 -0
  60. data/spec/data/lwrp_override/resources/.DS_Store +0 -0
@@ -29,9 +29,12 @@ class Chef
29
29
 
30
30
  provides :service, os: "linux"
31
31
 
32
+ def self.provides?(node, resource)
33
+ super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:upstart)
34
+ end
35
+
32
36
  def self.supports?(resource, action)
33
- Chef::Platform::ServiceHelpers.service_resource_providers.include?(:upstart) &&
34
- Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:upstart)
37
+ Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:upstart)
35
38
  end
36
39
 
37
40
  # Upstart does more than start or stop a service, creating multiple 'states' [1] that a service can be in.
@@ -23,22 +23,42 @@ class Chef
23
23
  class ProviderResolver
24
24
 
25
25
  attr_reader :node
26
+ attr_reader :resource
27
+ attr_reader :action
26
28
 
27
- def initialize(node)
29
+ def initialize(node, resource, action)
28
30
  @node = node
31
+ @resource = resource
32
+ @action = action
29
33
  end
30
34
 
31
35
  # return a deterministically sorted list of Chef::Provider subclasses
32
36
  def providers
33
- Chef::Provider.descendants.sort {|a,b| a.to_s <=> b.to_s }
37
+ @providers ||= Chef::Provider.descendants
34
38
  end
35
39
 
36
- def resolve(resource, action)
40
+ def resolve
37
41
  maybe_explicit_provider(resource) ||
38
42
  maybe_dynamic_provider_resolution(resource, action) ||
39
43
  maybe_chef_platform_lookup(resource)
40
44
  end
41
45
 
46
+ # this cut looks at if the provider can handle the resource type on the node
47
+ def enabled_handlers
48
+ @enabled_handlers ||=
49
+ providers.select do |klass|
50
+ klass.provides?(node, resource)
51
+ end.sort {|a,b| a.to_s <=> b.to_s }
52
+ end
53
+
54
+ # this cut looks at if the provider can handle the specific resource and action
55
+ def supported_handlers
56
+ @supported_handlers ||=
57
+ enabled_handlers.select do |klass|
58
+ klass.supports?(resource, action)
59
+ end
60
+ end
61
+
42
62
  private
43
63
 
44
64
  # if resource.provider is set, just return one of those objects
@@ -49,31 +69,23 @@ class Chef
49
69
 
50
70
  # try dynamically finding a provider based on querying the providers to see what they support
51
71
  def maybe_dynamic_provider_resolution(resource, action)
52
- # this cut only depends on the node value and is going to be static for all nodes
53
- # will contain all providers that could possibly support a resource on a node
54
- enabled_handlers = providers.select do |klass|
55
- klass.provides?(node, resource)
56
- end
57
-
58
72
  # log this so we know what providers will work for the generic resource on the node (early cut)
59
73
  Chef::Log.debug "providers for generic #{resource.resource_name} resource enabled on node include: #{enabled_handlers}"
60
74
 
61
- # ask all the enabled providers if they can actually support the resource
62
- supported_handlers = enabled_handlers.select do |klass|
63
- klass.supports?(resource, action)
64
- end
65
-
66
75
  # what providers were excluded by machine state (late cut)
67
76
  Chef::Log.debug "providers that refused resource #{resource} were: #{enabled_handlers - supported_handlers}"
68
77
  Chef::Log.debug "providers that support resource #{resource} include: #{supported_handlers}"
69
78
 
79
+ # if none of the providers specifically support the resource, we still need to pick one of the providers that are
80
+ # enabled on the node to handle the why-run use case.
70
81
  handlers = supported_handlers.empty? ? enabled_handlers : supported_handlers
82
+ Chef::Log.debug "no providers supported the resource, falling back to enabled handlers" if supported_handlers.empty?
71
83
 
72
84
  if handlers.count >= 2
85
+ # this magic stack ranks the providers by where they appear in the provider_priority_map, it is mostly used
86
+ # to pick amongst N different ways to start init scripts on different debian/ubuntu systems.
73
87
  priority_list = [ get_provider_priority_map(resource.resource_name, node) ].flatten.compact
74
-
75
88
  handlers = handlers.sort_by { |x| i = priority_list.index x; i.nil? ? Float::INFINITY : i }
76
-
77
89
  handlers = [ handlers.first ]
78
90
  end
79
91
 
@@ -81,6 +93,8 @@ class Chef
81
93
 
82
94
  raise Chef::Exceptions::AmbiguousProviderResolution.new(resource, handlers) if handlers.count >= 2
83
95
 
96
+ Chef::Log.debug "dynamic provider resolver FAILED to resolve a provider" if handlers.empty?
97
+
84
98
  return nil if handlers.empty?
85
99
 
86
100
  handlers[0]
@@ -29,6 +29,7 @@ require 'chef/resource/conditional_action_not_nothing'
29
29
  require 'chef/resource_collection'
30
30
  require 'chef/node_map'
31
31
  require 'chef/node'
32
+ require 'chef/provider_resolver'
32
33
  require 'chef/platform'
33
34
 
34
35
  require 'chef/mixin/deprecation'
@@ -679,7 +680,7 @@ F
679
680
  end
680
681
 
681
682
  def provider_for_action(action)
682
- provider = run_context.provider_resolver.resolve(self, action).new(self, run_context)
683
+ provider = Chef::ProviderResolver.new(node, self, action).resolve.new(self, run_context)
683
684
  provider.action = action
684
685
  provider
685
686
  end
@@ -78,3 +78,10 @@ require 'chef/resource/windows_package'
78
78
  require 'chef/resource/yum_package'
79
79
  require 'chef/resource/lwrp_base'
80
80
  require 'chef/resource/bff_package'
81
+
82
+ begin
83
+ # Optional resources chef_node, chef_client, machine, machine_image, etc.
84
+ require 'cheffish'
85
+ require 'chef/provisioning'
86
+ rescue LoadError
87
+ end
@@ -18,7 +18,6 @@
18
18
  # limitations under the License.
19
19
 
20
20
  require 'chef/resource_collection'
21
- require 'chef/provider_resolver'
22
21
  require 'chef/cookbook_version'
23
22
  require 'chef/node'
24
23
  require 'chef/role'
@@ -51,9 +50,6 @@ class Chef
51
50
  # recipes, which is triggered by #load. (See also: CookbookCompiler)
52
51
  attr_accessor :resource_collection
53
52
 
54
- # Chef::ProviderResolver for this run
55
- attr_accessor :provider_resolver
56
-
57
53
  # A Hash containing the immediate notifications triggered by resources
58
54
  # during the converge phase of the chef run.
59
55
  attr_accessor :immediate_notification_collection
@@ -87,7 +83,6 @@ class Chef
87
83
 
88
84
  @node.run_context = self
89
85
  @cookbook_compiler = nil
90
- @provider_resolver = Chef::ProviderResolver.new(@node)
91
86
  end
92
87
 
93
88
  # Triggers the compile phase of the chef run. Implemented by
@@ -96,8 +96,8 @@ class Chef
96
96
  end
97
97
 
98
98
  def apply_role_attributes(role)
99
- @default_attrs = Chef::Mixin::DeepMerge.role_merge(@default_attrs, role.default_attributes)
100
- @override_attrs = Chef::Mixin::DeepMerge.role_merge(@override_attrs, role.override_attributes)
99
+ @default_attrs = Chef::Mixin::DeepMerge.merge(@default_attrs, role.default_attributes)
100
+ @override_attrs = Chef::Mixin::DeepMerge.merge(@override_attrs, role.override_attributes)
101
101
  end
102
102
 
103
103
  def applied_role?(role_name)
@@ -308,9 +308,9 @@ FOOTER
308
308
  elsif ENV['HOME'] && ::File.exist?(File.join(ENV['HOME'], '.chef', 'chef_shell.rb'))
309
309
  File.join(ENV['HOME'], '.chef', 'chef_shell.rb')
310
310
  elsif config[:solo]
311
- "/etc/chef/solo.rb"
311
+ Chef::Config.platform_specific_path("/etc/chef/solo.rb")
312
312
  elsif config[:client]
313
- "/etc/chef/client.rb"
313
+ Chef::Config.platform_specific_path("/etc/chef/client.rb")
314
314
  else
315
315
  nil
316
316
  end
@@ -21,6 +21,7 @@
21
21
  # limitations under the License.
22
22
 
23
23
  require 'chef/mixin/shell_out'
24
+ require 'chef/mixin/which'
24
25
 
25
26
  class Chef
26
27
  class Util
@@ -32,6 +33,7 @@ class Chef
32
33
  module Selinux
33
34
 
34
35
  include Chef::Mixin::ShellOut
36
+ include Chef::Mixin::Which
35
37
 
36
38
  # We want to initialize below variables once during a
37
39
  # chef-client run therefore they are class variables.
@@ -67,15 +69,6 @@ class Chef
67
69
  @@selinuxenabled_path
68
70
  end
69
71
 
70
- def which(cmd)
71
- paths = ENV['PATH'].split(File::PATH_SEPARATOR) + [ '/bin', '/usr/bin', '/sbin', '/usr/sbin' ]
72
- paths.each do |path|
73
- filename = File.join(path, cmd)
74
- return filename if File.executable?(filename)
75
- end
76
- false
77
- end
78
-
79
72
  def check_selinux_enabled?
80
73
  if selinuxenabled_path
81
74
  cmd = shell_out!(selinuxenabled_path, :returns => [0,1])
@@ -97,4 +90,3 @@ class Chef
97
90
  end
98
91
  end
99
92
  end
100
-
@@ -17,7 +17,7 @@
17
17
 
18
18
  class Chef
19
19
  CHEF_ROOT = File.dirname(File.expand_path(File.dirname(__FILE__)))
20
- VERSION = '12.0.0.rc.0'
20
+ VERSION = '12.0.0'
21
21
  end
22
22
 
23
23
  #
@@ -25,7 +25,7 @@ class Chef
25
25
  class WorkstationConfigLoader
26
26
 
27
27
  # Path to a config file requested by user, (e.g., via command line option). Can be nil
28
- attr_reader :explicit_config_file
28
+ attr_accessor :explicit_config_file
29
29
 
30
30
  # TODO: initialize this with a logger for Chef and Knife
31
31
  def initialize(explicit_config_file, logger=nil)
@@ -43,12 +43,7 @@ def static_provider_resolution(opts={})
43
43
  node
44
44
  }
45
45
  let(:events) { Chef::EventDispatch::Dispatcher.new }
46
- let(:provider_resolver) { Chef::ProviderResolver.new(node) }
47
- let(:run_context) {
48
- run_context = Chef::RunContext.new(node, {}, events)
49
- run_context.provider_resolver = provider_resolver
50
- run_context
51
- }
46
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
52
47
  let(:resource) { resource_class.new("foo", run_context) }
53
48
 
54
49
  it "should return a #{resource_class}" do
@@ -209,6 +209,28 @@ describe Chef::ApiClient::Registration do
209
209
  registration.write_key
210
210
  IO.read(key_location).should == "--begin rsa key etc--"
211
211
  end
212
+
213
+ context 'when the client key location is a symlink' do
214
+ it 'does not follow the symlink', :unix_only do
215
+ expected_flags = (File::CREAT|File::TRUNC|File::RDWR)
216
+
217
+ if defined?(File::NOFOLLOW)
218
+ expected_flags |= File::NOFOLLOW
219
+ end
220
+
221
+ expect(registration.file_flags).to eq(expected_flags)
222
+ end
223
+
224
+ context 'with follow_client_key_symlink set to true' do
225
+ before do
226
+ Chef::Config[:follow_client_key_symlink] = true
227
+ end
228
+
229
+ it 'follows the symlink', :unix_only do
230
+ expect(registration.file_flags).to eq(File::CREAT|File::TRUNC|File::RDWR)
231
+ end
232
+ end
233
+ end
212
234
  end
213
235
 
214
236
  describe "when registering a client" do
@@ -33,6 +33,11 @@ describe Chef::Application::Knife do
33
33
  end
34
34
  end
35
35
 
36
+ after(:each) do
37
+ # reset some really nasty global state
38
+ NoopKnifeCommand.reset_config_loader!
39
+ end
40
+
36
41
  before(:each) do
37
42
  # Prevent code from getting loaded on every test invocation.
38
43
  Chef::Knife.stub(:load_commands)
@@ -109,7 +114,6 @@ describe Chef::Application::Knife do
109
114
  end
110
115
  Chef::Config[:client_key].should == full_path
111
116
  end
112
-
113
117
  end
114
118
 
115
119
  describe "with environment configuration" do
@@ -168,6 +172,6 @@ describe Chef::Application::Knife do
168
172
  @knife.run
169
173
  end
170
174
  end
171
-
172
175
  end
176
+
173
177
  end
@@ -0,0 +1,63 @@
1
+ #
2
+ # Author:: Ryan Cragun (<ryan@getchef.com>)
3
+ # Copyright:: Copyright (c) 2014 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'spec_helper'
20
+ require 'lib/chef/chef_fs/data_handler/group_data_handler'
21
+
22
+ class TestEntry < Mash
23
+ attr_accessor :name, :org
24
+
25
+ def initialize(name, org)
26
+ @name = name
27
+ @org = org
28
+ end
29
+ end
30
+
31
+ describe Chef::ChefFS::DataHandler::GroupDataHandler do
32
+ describe '#normalize_for_post' do
33
+ let(:entry) do
34
+ TestEntry.new('workers.json', 'hive')
35
+ end
36
+
37
+ let(:group) do
38
+ { 'name' => 'worker_bees',
39
+ 'clients' => %w(honey sting),
40
+ 'users' => %w(fizz buzz),
41
+ 'actors' => %w(honey)
42
+ }
43
+ end
44
+
45
+ let(:normalized) do
46
+ { 'actors' =>
47
+ { 'users' => %w(fizz buzz),
48
+ 'clients'=> %w(honey sting),
49
+ 'groups'=> []
50
+ },
51
+ 'groupname' => 'workers',
52
+ 'name' => 'worker_bees',
53
+ 'orgname' => 'hive'
54
+ }
55
+ end
56
+
57
+ let(:handler) { described_class.new }
58
+
59
+ it 'normalizes the users, clients and groups into actors' do
60
+ expect(handler.normalize_for_post(group, entry)).to eq(normalized)
61
+ end
62
+ end
63
+ end
@@ -426,7 +426,7 @@ describe Chef::Config do
426
426
  let(:locales) { locale_array.join("\n") }
427
427
 
428
428
  before do
429
- allow(Chef::Config).to receive(:shell_out_with_systems_locale).with("locale -a").and_return(shell_out)
429
+ allow(Chef::Config).to receive(:shell_out_with_systems_locale!).with("locale -a").and_return(shell_out)
430
430
  end
431
431
 
432
432
  shared_examples_for "a suitable locale" do
@@ -434,7 +434,7 @@ describe Chef::Config do
434
434
  expect(Chef::Log).to_not receive(:warn).with(/Please install an English UTF-8 locale for Chef to use/)
435
435
  expect(Chef::Log).to_not receive(:debug).with(/Defaulting to locale en_US.UTF-8 on Windows/)
436
436
  expect(Chef::Log).to_not receive(:debug).with(/No usable locale -a command found/)
437
- expect(Chef::Config[:internal_locale]).to eq expected_locale
437
+ expect(Chef::Config.guess_internal_locale).to eq expected_locale
438
438
  end
439
439
  end
440
440
 
@@ -485,7 +485,7 @@ describe Chef::Config do
485
485
 
486
486
  it "should fall back to C locale" do
487
487
  expect(Chef::Log).to receive(:warn).with("Please install an English UTF-8 locale for Chef to use, falling back to C locale and disabling UTF-8 support.")
488
- expect(Chef::Config[:internal_locale]).to eq 'C'
488
+ expect(Chef::Config.guess_internal_locale).to eq 'C'
489
489
  end
490
490
  end
491
491
 
@@ -493,7 +493,7 @@ describe Chef::Config do
493
493
  let(:locale_array) { [] }
494
494
 
495
495
  before do
496
- allow(Chef::Config).to receive(:shell_out_with_systems_locale).and_raise("THIS IS AN ERROR")
496
+ allow(Chef::Config).to receive(:shell_out_with_systems_locale!).and_raise("THIS IS AN ERROR")
497
497
  end
498
498
 
499
499
  it "should default to 'en_US.UTF-8'" do
@@ -502,7 +502,7 @@ describe Chef::Config do
502
502
  else
503
503
  expect(Chef::Log).to receive(:debug).with("No usable locale -a command found, assuming you have en_US.UTF-8 installed.")
504
504
  end
505
- expect(Chef::Config[:internal_locale]).to eq "en_US.UTF-8"
505
+ expect(Chef::Config.guess_internal_locale).to eq "en_US.UTF-8"
506
506
  end
507
507
  end
508
508
  end
@@ -29,7 +29,7 @@ describe Chef::Knife::Bootstrap do
29
29
  Chef::Log.logger = Logger.new(StringIO.new)
30
30
  Chef::Config[:knife][:bootstrap_template] = bootstrap_template unless bootstrap_template.nil?
31
31
 
32
- k = Chef::Knife::Bootstrap.new
32
+ k = Chef::Knife::Bootstrap.new(bootstrap_cli_options)
33
33
  k.merge_configs
34
34
 
35
35
  k.ui.stub(:stderr).and_return(stderr)
@@ -41,11 +41,37 @@ describe Chef::Knife::Bootstrap do
41
41
 
42
42
  let(:bootstrap_template) { nil }
43
43
 
44
+ let(:bootstrap_cli_options) { [ ] }
45
+
44
46
  it "should use chef-full as default template" do
45
47
  knife.bootstrap_template.should be_a_kind_of(String)
46
48
  File.basename(knife.bootstrap_template).should eq("chef-full")
47
49
  end
48
50
 
51
+ context "with :distro and :bootstrap_template cli options" do
52
+ let(:bootstrap_cli_options) { [ "--bootstrap-template", "my-template", "--distro", "other-template" ] }
53
+
54
+ it "should select bootstrap template" do
55
+ expect(File.basename(knife.bootstrap_template)).to eq("my-template")
56
+ end
57
+ end
58
+
59
+ context "with :distro and :template_file cli options" do
60
+ let(:bootstrap_cli_options) { [ "--distro", "my-template", "--template-file", "other-template" ] }
61
+
62
+ it "should select bootstrap template" do
63
+ expect(File.basename(knife.bootstrap_template)).to eq("other-template")
64
+ end
65
+ end
66
+
67
+ context "with :bootstrap_template and :template_file cli options" do
68
+ let(:bootstrap_cli_options) { [ "--bootstrap-template", "my-template", "--template-file", "other-template" ] }
69
+
70
+ it "should select bootstrap template" do
71
+ expect(File.basename(knife.bootstrap_template)).to eq("my-template")
72
+ end
73
+ end
74
+
49
75
  context "when finding templates" do
50
76
  context "when :bootstrap_template config is set to a file" do
51
77
  context "that doesn't exist" do