chef 13.3.42 → 13.4.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/VERSION +1 -1
  4. data/lib/chef/knife/core/ui.rb +1 -1
  5. data/lib/chef/mash.rb +6 -0
  6. data/lib/chef/mixin/deep_merge.rb +1 -1
  7. data/lib/chef/mixin/user_context.rb +52 -0
  8. data/lib/chef/node/attribute.rb +80 -14
  9. data/lib/chef/node/immutable_collections.rb +16 -19
  10. data/lib/chef/provider/apt_repository.rb +12 -10
  11. data/lib/chef/provider/git.rb +20 -3
  12. data/lib/chef/provider/ifconfig/redhat.rb +4 -0
  13. data/lib/chef/provider/launchd.rb +20 -0
  14. data/lib/chef/provider/package/dnf.rb +3 -1
  15. data/lib/chef/provider/remote_file.rb +19 -0
  16. data/lib/chef/provider/remote_file/fetcher.rb +3 -0
  17. data/lib/chef/provider/remote_file/network_file.rb +18 -5
  18. data/lib/chef/provider/service/macosx.rb +4 -3
  19. data/lib/chef/provider/windows_path.rb +62 -0
  20. data/lib/chef/provider/zypper_repository.rb +1 -1
  21. data/lib/chef/providers.rb +1 -0
  22. data/lib/chef/resource.rb +5 -1
  23. data/lib/chef/resource/apt_repository.rb +1 -1
  24. data/lib/chef/resource/ifconfig.rb +36 -0
  25. data/lib/chef/resource/remote_file.rb +60 -0
  26. data/lib/chef/resource/windows_path.rb +41 -0
  27. data/lib/chef/resource/zypper_repository.rb +1 -0
  28. data/lib/chef/resources.rb +1 -0
  29. data/lib/chef/shell.rb +1 -0
  30. data/lib/chef/shell/shell_session.rb +4 -4
  31. data/lib/chef/util/windows/logon_session.rb +126 -0
  32. data/lib/chef/version.rb +4 -3
  33. data/lib/chef/win32/api/security.rb +2 -0
  34. data/spec/functional/mixin/user_context_spec.rb +117 -0
  35. data/spec/functional/resource/remote_file_spec.rb +171 -0
  36. data/spec/functional/resource/windows_path_spec.rb +64 -0
  37. data/spec/unit/knife/client_delete_spec.rb +1 -1
  38. data/spec/unit/mixin/user_context_spec.rb +109 -0
  39. data/spec/unit/node/immutable_collections_spec.rb +12 -4
  40. data/spec/unit/node_spec.rb +7 -0
  41. data/spec/unit/provider/git_spec.rb +55 -0
  42. data/spec/unit/provider/ifconfig/redhat_spec.rb +8 -0
  43. data/spec/unit/provider/remote_file/fetcher_spec.rb +1 -0
  44. data/spec/unit/provider/remote_file/network_file_spec.rb +7 -2
  45. data/spec/unit/provider/service/macosx_spec.rb +4 -1
  46. data/spec/unit/provider/windows_path_spec.rb +65 -0
  47. data/spec/unit/resource/windows_path_spec.rb +38 -0
  48. data/spec/unit/resource_spec.rb +8 -0
  49. data/spec/unit/shell/shell_session_spec.rb +82 -58
  50. data/spec/unit/util/windows/logon_session_spec.rb +284 -0
  51. data/tasks/maintainers.rb +3 -3
  52. metadata +15 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 244f9d815246c3d954e9794813133b95395fac26
4
- data.tar.gz: beb5752e4b20493f5b754e20cbe118da4dadf2d6
3
+ metadata.gz: 103c769a6347776d48577798e5e82271b9f9b082
4
+ data.tar.gz: cfc8564484b034b788fbc8307f322c1acd3d61a9
5
5
  SHA512:
6
- metadata.gz: '091dcc6ee3ea1710e4998795452dec480e07b36db38c0b7e33054ee50c96462358a108a44cb9a86a8632d5f3a41c3b2301f07bc37d3fd192e17dcedaade45049'
7
- data.tar.gz: 488d579aed0dd49078cc89965ece8d61c815aa3cc0f085028ad6ef854272d494cf69b7fec18f0ce9a52f793d636c6612b6bb2d82f654fdd7614b2f2f699e4576
6
+ metadata.gz: a0b57f2f5e07eefa55e3510688b18a31bbb40dd2395b96cceb299a69fc8f434843afe64a4bea04eee8fe403e38a248a97b9504797ec10c2397ad46654e3143bf
7
+ data.tar.gz: 60446f65bc583b79e4a490cea2da2a221769aaae9d6c14298808970a44ff2a3c11f6fffaafc65760e16e59fb4d09af6e8f9d20955d8271ffcf35842ad0330c98
data/Gemfile CHANGED
@@ -16,6 +16,7 @@ group(:omnibus_package) do
16
16
  gem "appbundler"
17
17
  gem "rb-readline"
18
18
  gem "inspec"
19
+ gem "chef-vault"
19
20
  end
20
21
 
21
22
  group(:omnibus_package, :pry) do
data/VERSION CHANGED
@@ -1 +1 @@
1
- 13.3.42
1
+ 13.4.19
@@ -172,7 +172,7 @@ class Chef
172
172
  tf.sync = true
173
173
  tf.puts output
174
174
  tf.close
175
- raise "Please set EDITOR environment variable" unless system("#{config[:editor]} #{tf.path}")
175
+ raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_using.html for details." unless system("#{config[:editor]} #{tf.path}")
176
176
 
177
177
  output = IO.read(tf.path)
178
178
  end
@@ -105,6 +105,12 @@ class Mash < Hash
105
105
  regular_writer(convert_key(key), convert_value(value))
106
106
  end
107
107
 
108
+ # internal API for use by Chef's deep merge cache
109
+ # @api private
110
+ def internal_set(key, value)
111
+ regular_writer(key, convert_value(value))
112
+ end
113
+
108
114
  # @param other_hash<Hash>
109
115
  # A hash to update values in the mash with. The keys and the values will be
110
116
  # converted to Mash format.
@@ -64,7 +64,7 @@ class Chef
64
64
  when Hash
65
65
  if dest.kind_of?(Hash)
66
66
  source.each do |src_key, src_value|
67
- if dest[src_key]
67
+ if dest.key?(src_key)
68
68
  dest[src_key] = deep_merge!(src_value, dest[src_key])
69
69
  else # dest[src_key] doesn't exist so we take whatever source has
70
70
  dest[src_key] = src_value
@@ -0,0 +1,52 @@
1
+ #
2
+ # Author:: Adam Edwards (<adamed@chef.io>)
3
+ # Copyright:: Copyright (c) 2016 Chef Software, 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 "chef/util/windows/logon_session" if Chef::Platform.windows?
20
+
21
+ class Chef
22
+ module Mixin
23
+ module UserContext
24
+
25
+ def with_user_context(user, password, domain = nil, &block)
26
+ if node["platform_family"] != "windows"
27
+ raise Exceptions::UnsupportedPlatform, "User context impersonation is supported only on the Windows platform"
28
+ end
29
+
30
+ if ! block_given?
31
+ raise ArgumentError, "You must supply a block to `with_user_context`"
32
+ end
33
+
34
+ login_session = nil
35
+
36
+ begin
37
+ if user
38
+ logon_session = Chef::Util::Windows::LogonSession.new(user, password, domain)
39
+ logon_session.open
40
+ logon_session.set_user_context
41
+ end
42
+ yield
43
+ ensure
44
+ logon_session.close if logon_session
45
+ end
46
+ end
47
+
48
+ protected(:with_user_context)
49
+
50
+ end
51
+ end
52
+ end
@@ -399,7 +399,7 @@ class Chef
399
399
  #
400
400
 
401
401
  def merged_attributes(*path)
402
- immutablize(merge_all(path))
402
+ merge_all(path)
403
403
  end
404
404
 
405
405
  def combined_override(*path)
@@ -536,15 +536,10 @@ class Chef
536
536
  apply_path(@automatic, path),
537
537
  ]
538
538
 
539
- components.map! do |component|
540
- safe_dup(component)
541
- end
542
-
543
- return nil if components.compact.empty?
544
-
545
- components.inject(ImmutableMash.new({}, self, __node__, :merged)) do |merged, component|
546
- Chef::Mixin::DeepMerge.hash_only_merge!(merged, component)
539
+ ret = components.inject(NIL) do |merged, component|
540
+ hash_only_merge!(merged, component)
547
541
  end
542
+ ret == NIL ? nil : ret
548
543
  end
549
544
 
550
545
  # Deep merge the default attribute levels with array merging.
@@ -554,10 +549,11 @@ class Chef
554
549
  # @param path [Array] Array of args to method chain to descend into the node object
555
550
  # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
556
551
  def merge_defaults(path)
557
- DEFAULT_COMPONENTS.inject(nil) do |merged, component_ivar|
552
+ ret = DEFAULT_COMPONENTS.inject(NIL) do |merged, component_ivar|
558
553
  component_value = apply_path(instance_variable_get(component_ivar), path)
559
- Chef::Mixin::DeepMerge.deep_merge(component_value, merged)
554
+ deep_merge!(merged, component_value)
560
555
  end
556
+ ret == NIL ? nil : ret
561
557
  end
562
558
 
563
559
  # Deep merge the override attribute levels with array merging.
@@ -567,10 +563,11 @@ class Chef
567
563
  # @param path [Array] Array of args to method chain to descend into the node object
568
564
  # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
569
565
  def merge_overrides(path)
570
- OVERRIDE_COMPONENTS.inject(nil) do |merged, component_ivar|
566
+ ret = OVERRIDE_COMPONENTS.inject(NIL) do |merged, component_ivar|
571
567
  component_value = apply_path(instance_variable_get(component_ivar), path)
572
- Chef::Mixin::DeepMerge.deep_merge(component_value, merged)
568
+ deep_merge!(merged, component_value)
573
569
  end
570
+ ret == NIL ? nil : ret
574
571
  end
575
572
 
576
573
  # needed for __path__
@@ -578,7 +575,76 @@ class Chef
578
575
  key.kind_of?(Symbol) ? key.to_s : key
579
576
  end
580
577
 
581
- end
578
+ NIL = Object.new
579
+
580
+ # @api private
581
+ def deep_merge!(merge_onto, merge_with)
582
+ # If there are two Hashes, recursively merge.
583
+ if merge_onto.kind_of?(Hash) && merge_with.kind_of?(Hash)
584
+ merge_with.each do |key, merge_with_value|
585
+ value =
586
+ if merge_onto.has_key?(key)
587
+ deep_merge!(safe_dup(merge_onto[key]), merge_with_value)
588
+ else
589
+ merge_with_value
590
+ end
591
+
592
+ # internal_set bypasses converting keys, does convert values and allows writing to immutable mashes
593
+ merge_onto.internal_set(key, value)
594
+ end
595
+ merge_onto
596
+
597
+ elsif merge_onto.kind_of?(Array) && merge_with.kind_of?(Array)
598
+ merge_onto |= merge_with
599
+
600
+ # If merge_with is nil, don't replace merge_onto
601
+ elsif merge_with.nil?
602
+ merge_onto
603
+
604
+ # In all other cases, replace merge_onto with merge_with
605
+ else
606
+ if merge_with.kind_of?(Hash)
607
+ Chef::Node::VividMash.new(merge_with)
608
+ elsif merge_with.kind_of?(Array)
609
+ Chef::Node::AttrArray.new(merge_with)
610
+ else
611
+ merge_with
612
+ end
613
+ end
614
+ end
582
615
 
616
+ # @api private
617
+ def hash_only_merge!(merge_onto, merge_with)
618
+ # If there are two Hashes, recursively merge.
619
+ if merge_onto.kind_of?(Hash) && merge_with.kind_of?(Hash)
620
+ merge_with.each do |key, merge_with_value|
621
+ value =
622
+ if merge_onto.has_key?(key)
623
+ hash_only_merge!(safe_dup(merge_onto[key]), merge_with_value)
624
+ else
625
+ merge_with_value
626
+ end
627
+
628
+ # internal_set bypasses converting keys, does convert values and allows writing to immutable mashes
629
+ merge_onto.internal_set(key, value)
630
+ end
631
+ merge_onto
632
+
633
+ # If merge_with is nil, don't replace merge_onto
634
+ elsif merge_with.nil?
635
+ merge_onto
636
+
637
+ # In all other cases, replace merge_onto with merge_with
638
+ else
639
+ if merge_with.kind_of?(Hash)
640
+ Chef::Node::ImmutableMash.new(merge_with)
641
+ elsif merge_with.kind_of?(Array)
642
+ Chef::Node::ImmutableArray.new(merge_with)
643
+ else
644
+ merge_with
645
+ end
646
+ end
647
+ end
648
+ end
583
649
  end
584
650
  end
@@ -30,16 +30,22 @@ class Chef
30
30
  e
31
31
  end
32
32
 
33
- def immutablize(value)
33
+ def convert_value(value)
34
34
  case value
35
35
  when Hash
36
36
  ImmutableMash.new(value, __root__, __node__, __precedence__)
37
37
  when Array
38
38
  ImmutableArray.new(value, __root__, __node__, __precedence__)
39
+ when ImmutableMash, ImmutableArray
40
+ value
39
41
  else
40
42
  safe_dup(value).freeze
41
43
  end
42
44
  end
45
+
46
+ def immutablize(value)
47
+ convert_value(value)
48
+ end
43
49
  end
44
50
 
45
51
  # == ImmutableArray
@@ -90,7 +96,9 @@ class Chef
90
96
 
91
97
  alias_method :to_array, :to_a
92
98
 
93
- # for consistency's sake -- integers 'converted' to integers
99
+ private
100
+
101
+ # needed for __path__
94
102
  def convert_key(key)
95
103
  key
96
104
  end
@@ -115,31 +123,20 @@ class Chef
115
123
  include Immutablize
116
124
  include CommonAPI
117
125
 
118
- alias :internal_set :[]=
119
- private :internal_set
126
+ # this is for deep_merge usage, chef users must never touch this API
127
+ # @api private
128
+ def internal_set(key, value)
129
+ regular_writer(key, convert_value(value))
130
+ end
120
131
 
121
132
  def initialize(mash_data = {})
122
133
  mash_data.each do |key, value|
123
- internal_set(key, immutablize(value))
134
+ internal_set(key, value)
124
135
  end
125
136
  end
126
137
 
127
- def public_method_that_only_deep_merge_should_use(key, value)
128
- internal_set(key, immutablize(value))
129
- end
130
-
131
138
  alias :attribute? :has_key?
132
139
 
133
- # Mash uses #convert_value to mashify values on input.
134
- # Since we're handling this ourselves, override it to be a no-op
135
- #
136
- # FIXME? this seems wrong to do and i think is responsible for
137
- # #dup needing to be more complicated than Mash.new(self)?
138
- #
139
- def convert_value(value)
140
- value
141
- end
142
-
143
140
  # NOTE: #default and #default= are likely to be pretty confusing. For a
144
141
  # regular ruby Hash, they control what value is returned for, e.g.,
145
142
  # hash[:no_such_key] #=> hash.default
@@ -41,10 +41,12 @@ class Chef
41
41
 
42
42
  action :add do
43
43
  unless new_resource.key.nil?
44
- if is_key_id?(new_resource.key) && !has_cookbook_file?(new_resource.key)
45
- install_key_from_keyserver
46
- else
47
- install_key_from_uri
44
+ new_resource.key.each do |k|
45
+ if is_key_id?(k) && !has_cookbook_file?(k)
46
+ install_key_from_keyserver(k)
47
+ else
48
+ install_key_from_uri(k)
49
+ end
48
50
  end
49
51
  end
50
52
 
@@ -151,19 +153,19 @@ class Chef
151
153
  (installed_keys & proposed_keys).sort == proposed_keys.sort
152
154
  end
153
155
 
154
- def install_key_from_uri
155
- key_name = new_resource.key.gsub(/[^0-9A-Za-z\-]/, "_")
156
+ def install_key_from_uri(key)
157
+ key_name = key.gsub(/[^0-9A-Za-z\-]/, "_")
156
158
  cached_keyfile = ::File.join(Chef::Config[:file_cache_path], key_name)
157
- type = if new_resource.key.start_with?("http")
159
+ type = if key.start_with?("http")
158
160
  :remote_file
159
- elsif has_cookbook_file?(new_resource.key)
161
+ elsif has_cookbook_file?(key)
160
162
  :cookbook_file
161
163
  else
162
164
  raise Chef::Exceptions::FileNotFound, "Cannot locate key file"
163
165
  end
164
166
 
165
167
  declare_resource(type, cached_keyfile) do
166
- source new_resource.key
168
+ source key
167
169
  mode "0644"
168
170
  sensitive new_resource.sensitive
169
171
  action :create
@@ -181,7 +183,7 @@ class Chef
181
183
  end
182
184
  end
183
185
 
184
- def install_key_from_keyserver(key = new_resource.key, keyserver = new_resource.keyserver)
186
+ def install_key_from_keyserver(key, keyserver = new_resource.keyserver)
185
187
  cmd = "apt-key adv --recv"
186
188
  cmd << " --keyserver-options http-proxy=#{new_resource.key_proxy}" if new_resource.key_proxy
187
189
  cmd << " --keyserver "
@@ -28,6 +28,8 @@ class Chef
28
28
  extend Forwardable
29
29
  provides :git
30
30
 
31
+ GIT_VERSION_PATTERN = Regexp.compile('git version (\d+\.\d+.\d+)')
32
+
31
33
  def_delegator :new_resource, :destination, :cwd
32
34
 
33
35
  def load_current_resource
@@ -103,8 +105,21 @@ class Chef
103
105
  end
104
106
  end
105
107
 
106
- def git_minor_version
107
- @git_minor_version ||= Gem::Version.new( git("--version").stdout.split.last )
108
+ def git_has_single_branch_option?
109
+ @git_has_single_branch_option ||= !git_gem_version.nil? && git_gem_version >= Gem::Version.new("1.7.10")
110
+ end
111
+
112
+ def git_gem_version
113
+ return @git_gem_version if defined?(@git_gem_version)
114
+ output = git("--version").stdout
115
+ match = GIT_VERSION_PATTERN.match(output)
116
+ if match
117
+ @git_gem_version = Gem::Version.new(match[1])
118
+ else
119
+ Chef::Log.warn "Unable to parse git version from '#{output}'"
120
+ @git_gem_version = nil
121
+ end
122
+ @git_gem_version
108
123
  end
109
124
 
110
125
  def existing_git_clone?
@@ -142,7 +157,7 @@ class Chef
142
157
  clone_cmd = ["clone"]
143
158
  clone_cmd << "-o #{remote}" unless remote == "origin"
144
159
  clone_cmd << "--depth #{new_resource.depth}" if new_resource.depth
145
- clone_cmd << "--no-single-branch" if new_resource.depth && git_minor_version >= Gem::Version.new("1.7.10")
160
+ clone_cmd << "--no-single-branch" if new_resource.depth && git_has_single_branch_option?
146
161
  clone_cmd << "\"#{new_resource.repository}\""
147
162
  clone_cmd << "\"#{cwd}\""
148
163
 
@@ -285,6 +300,8 @@ class Chef
285
300
  refs.find_all { |m| m[1] == pattern }
286
301
  end
287
302
 
303
+ alias git_minor_version git_gem_version
304
+
288
305
  private
289
306
 
290
307
  def run_options(run_opts = {})
@@ -38,6 +38,10 @@ class Chef
38
38
  <% if new_resource.hwaddr %>HWADDR=<%= new_resource.hwaddr %><% end %>
39
39
  <% if new_resource.metric %>METRIC=<%= new_resource.metric %><% end %>
40
40
  <% if new_resource.mtu %>MTU=<%= new_resource.mtu %><% end %>
41
+ <% if new_resource.ethtool_opts %>ETHTOOL_OPTS="<%= new_resource.ethtool_opts %>"<% end %>
42
+ <% if new_resource.bonding_opts %>BONDING_OPTS="<%= new_resource.bonding_opts %>"<% end %>
43
+ <% if new_resource.master %>MASTER=<%= new_resource.master %><% end %>
44
+ <% if new_resource.slave %>SLAVE=<%= new_resource.slave %><% end %>
41
45
  }
42
46
  @config_path = "/etc/sysconfig/network-scripts/ifcfg-#{new_resource.device}"
43
47
  end
@@ -90,6 +90,7 @@ class Chef
90
90
  end
91
91
 
92
92
  def manage_plist(action)
93
+ return unless manage_agent?(action)
93
94
  if source
94
95
  res = cookbook_file_resource
95
96
  else
@@ -101,11 +102,30 @@ class Chef
101
102
  end
102
103
 
103
104
  def manage_service(action)
105
+ return unless manage_agent?(action)
104
106
  res = service_resource
105
107
  res.run_action(action)
106
108
  new_resource.updated_by_last_action(true) if res.updated?
107
109
  end
108
110
 
111
+ def manage_agent?(action)
112
+ # Gets UID of console_user and converts to string.
113
+ console_user = Etc.getpwuid(::File.stat("/dev/console").uid).name
114
+ root = console_user == "root"
115
+ agent = type == "agent"
116
+ invalid_action = [:delete, :disable, :enable, :restart].include?(action)
117
+ lltstype = ""
118
+ if new_resource.limit_load_to_session_type
119
+ lltstype = new_resource.limit_load_to_session_type
120
+ end
121
+ invalid_type = lltstype != "LoginWindow"
122
+ if root && agent && invalid_action && invalid_type
123
+ Chef::Log.debug("#{label}: Aqua LaunchAgents shouldn't be loaded as root")
124
+ return false
125
+ end
126
+ true
127
+ end
128
+
109
129
  def service_resource
110
130
  res = Chef::Resource::MacosxService.new(label, run_context)
111
131
  res.name(label) if label