chef 11.10.0.alpha.1 → 11.10.0.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +57 -36
- data/distro/common/html/chef-client.8.html +4 -4
- data/distro/common/html/chef-expander.8.html +4 -4
- data/distro/common/html/chef-expanderctl.8.html +4 -4
- data/distro/common/html/chef-server-webui.8.html +4 -4
- data/distro/common/html/chef-server.8.html +4 -4
- data/distro/common/html/chef-shell.1.html +4 -4
- data/distro/common/html/chef-solo.8.html +4 -4
- data/distro/common/html/chef-solr.8.html +5 -5
- data/distro/common/html/knife-bootstrap.1.html +4 -4
- data/distro/common/html/knife-client.1.html +4 -4
- data/distro/common/html/knife-configure.1.html +4 -4
- data/distro/common/html/knife-cookbook-site.1.html +4 -4
- data/distro/common/html/knife-cookbook.1.html +4 -4
- data/distro/common/html/knife-data-bag.1.html +4 -4
- data/distro/common/html/knife-environment.1.html +4 -4
- data/distro/common/html/knife-exec.1.html +4 -4
- data/distro/common/html/knife-index.1.html +4 -4
- data/distro/common/html/knife-node.1.html +4 -4
- data/distro/common/html/knife-role.1.html +4 -4
- data/distro/common/html/knife-search.1.html +4 -4
- data/distro/common/html/knife-ssh.1.html +4 -4
- data/distro/common/html/knife-status.1.html +4 -4
- data/distro/common/html/knife-tag.1.html +4 -4
- data/distro/common/html/knife.1.html +4 -4
- data/distro/common/man/man1/knife-bootstrap.1 +58 -64
- data/distro/common/man/man1/knife-client.1 +19 -22
- data/distro/common/man/man1/knife-configure.1 +37 -46
- data/distro/common/man/man1/knife-cookbook-site.1 +14 -17
- data/distro/common/man/man1/knife-cookbook.1 +15 -18
- data/distro/common/man/man1/knife-data-bag.1 +14 -17
- data/distro/common/man/man1/knife-delete.1 +38 -47
- data/distro/common/man/man1/knife-deps.1 +39 -48
- data/distro/common/man/man1/knife-diff.1 +43 -52
- data/distro/common/man/man1/knife-download.1 +47 -53
- data/distro/common/man/man1/knife-edit.1 +32 -41
- data/distro/common/man/man1/knife-environment.1 +14 -17
- data/distro/common/man/man1/knife-exec.1 +52 -61
- data/distro/common/man/man1/knife-index-rebuild.1 +1 -61
- data/distro/common/man/man1/knife-list.1 +47 -59
- data/distro/common/man/man1/knife-node.1 +15 -18
- data/distro/common/man/man1/knife-raw.1 +28 -46
- data/distro/common/man/man1/knife-recipe-list.1 +1 -61
- data/distro/common/man/man1/knife-role.1 +19 -25
- data/distro/common/man/man1/knife-search.1 +53 -62
- data/distro/common/man/man1/knife-show.1 +36 -28
- data/distro/common/man/man1/knife-ssh.1 +55 -61
- data/distro/common/man/man1/knife-status.1 +34 -43
- data/distro/common/man/man1/knife-tag.1 +14 -17
- data/distro/common/man/man1/knife-upload.1 +47 -56
- data/distro/common/man/man1/knife-user.1 +17 -20
- data/distro/common/man/man1/knife-xargs.1 +60 -69
- data/lib/chef/application.rb +3 -1
- data/lib/chef/application/windows_service.rb +0 -1
- data/lib/chef/client.rb +41 -152
- data/lib/chef/config.rb +19 -23
- data/lib/chef/data_bag.rb +1 -1
- data/lib/chef/data_bag_item.rb +1 -1
- data/lib/chef/exceptions.rb +8 -0
- data/lib/chef/formatters/doc.rb +15 -0
- data/lib/chef/formatters/error_inspectors/api_error_formatting.rb +2 -1
- data/lib/chef/http.rb +18 -8
- data/lib/chef/http/authenticator.rb +4 -0
- data/lib/chef/http/cookie_manager.rb +3 -0
- data/lib/chef/http/decompressor.rb +4 -0
- data/lib/chef/http/json_input.rb +4 -0
- data/lib/chef/http/json_output.rb +4 -0
- data/lib/chef/http/validate_content_length.rb +94 -0
- data/lib/chef/knife.rb +0 -1
- data/lib/chef/knife/configure.rb +6 -6
- data/lib/chef/knife/cookbook_create.rb +2 -2
- data/lib/chef/knife/core/subcommand_loader.rb +49 -3
- data/lib/chef/knife/ssh.rb +34 -4
- data/lib/chef/mixin/path_sanity.rb +1 -0
- data/lib/chef/monologger.rb +1 -2
- data/lib/chef/node.rb +7 -0
- data/lib/chef/policy_builder.rb +49 -0
- data/lib/chef/policy_builder/expand_node_object.rb +230 -0
- data/lib/chef/policy_builder/policyfile.rb +338 -0
- data/lib/chef/provider/file.rb +15 -5
- data/lib/chef/provider/group.rb +6 -2
- data/lib/chef/provider/group/windows.rb +12 -2
- data/lib/chef/provider/http_request.rb +3 -2
- data/lib/chef/provider/package.rb +1 -0
- data/lib/chef/provider/package/aix.rb +1 -1
- data/lib/chef/provider/service/debian.rb +7 -2
- data/lib/chef/resource/file.rb +8 -1
- data/lib/chef/resource/package.rb +9 -0
- data/lib/chef/resource/service.rb +0 -1
- data/lib/chef/rest.rb +2 -0
- data/lib/chef/run_context.rb +1 -1
- data/lib/chef/util/file_edit.rb +1 -1
- data/lib/chef/util/windows/net_group.rb +7 -6
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/version.rb +31 -18
- data/spec/data/cookbooks/preseed/templates/default/preseed-template-variables.seed +1 -0
- data/spec/functional/resource/file_spec.rb +0 -1
- data/spec/functional/resource/group_spec.rb +96 -16
- data/spec/functional/resource/package_spec.rb +17 -0
- data/spec/functional/resource/user_spec.rb +2 -2
- data/spec/functional/win32/versions_spec.rb +39 -0
- data/spec/integration/client/client_spec.rb +27 -28
- data/spec/spec_helper.rb +2 -0
- data/spec/support/platform_helpers.rb +7 -1
- data/spec/support/shared/functional/file_resource.rb +83 -43
- data/spec/unit/application_spec.rb +7 -5
- data/spec/unit/client_spec.rb +10 -3
- data/spec/unit/config_spec.rb +0 -30
- data/spec/unit/cookbook_spec.rb +1 -0
- data/spec/unit/data_bag_item_spec.rb +8 -0
- data/spec/unit/data_bag_spec.rb +6 -0
- data/spec/unit/http_spec.rb +48 -0
- data/spec/unit/knife/core/subcommand_loader_spec.rb +77 -1
- data/spec/unit/knife/ssh_spec.rb +107 -0
- data/spec/unit/mixin/path_sanity_spec.rb +6 -0
- data/spec/unit/mixin/securable_spec.rb +77 -3
- data/spec/unit/monologger_spec.rb +45 -0
- data/spec/unit/node_spec.rb +16 -0
- data/spec/unit/policy_builder/expand_node_object_spec.rb +320 -0
- data/spec/unit/policy_builder/policyfile_spec.rb +399 -0
- data/spec/unit/policy_builder_spec.rb +26 -0
- data/spec/unit/provider/deploy_spec.rb +3 -0
- data/spec/unit/provider/group/windows_spec.rb +1 -0
- data/spec/unit/provider/http_request_spec.rb +23 -1
- data/spec/unit/provider/service/debian_service_spec.rb +50 -19
- data/spec/unit/recipe_spec.rb +4 -0
- data/spec/unit/resource/package_spec.rb +5 -0
- data/spec/unit/rest_spec.rb +375 -278
- data/spec/unit/run_context_spec.rb +4 -0
- metadata +96 -59
- checksums.yaml +0 -7
data/lib/chef/provider/file.rb
CHANGED
@@ -352,16 +352,27 @@ class Chef
|
|
352
352
|
if tempfile.path.nil? || !::File.exists?(tempfile.path)
|
353
353
|
raise "chef-client is confused, trying to deploy a file that has no path or does not exist..."
|
354
354
|
end
|
355
|
+
|
355
356
|
# the file? on the next line suppresses the case in why-run when we have a not-file here that would have otherwise been removed
|
356
357
|
if ::File.file?(@new_resource.path) && contents_changed?
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
358
|
+
description = [ "update content in file #{@new_resource.path} from \
|
359
|
+
#{short_cksum(@current_resource.checksum)} to #{short_cksum(checksum(tempfile.path))}" ]
|
360
|
+
|
361
|
+
# Hide the diff output if the resource is marked as a sensitive resource
|
362
|
+
if @new_resource.sensitive
|
363
|
+
@new_resource.diff("suppressed sensitive resource")
|
364
|
+
description << "suppressed sensitive resource"
|
365
|
+
else
|
366
|
+
diff.diff(@current_resource.path, tempfile.path)
|
367
|
+
@new_resource.diff( diff.for_reporting ) unless file_created?
|
368
|
+
description << diff.for_output
|
369
|
+
end
|
370
|
+
|
361
371
|
converge_by(description) do
|
362
372
|
update_file_contents
|
363
373
|
end
|
364
374
|
end
|
375
|
+
|
365
376
|
# unlink necessary to clean up in why-run mode
|
366
377
|
tempfile.unlink
|
367
378
|
end
|
@@ -420,4 +431,3 @@ class Chef
|
|
420
431
|
end
|
421
432
|
end
|
422
433
|
end
|
423
|
-
|
data/lib/chef/provider/group.rb
CHANGED
@@ -91,7 +91,7 @@ class Chef
|
|
91
91
|
if(@new_resource.append)
|
92
92
|
missing_members = []
|
93
93
|
@new_resource.members.each do |member|
|
94
|
-
next if
|
94
|
+
next if has_current_group_member?(member)
|
95
95
|
missing_members << member
|
96
96
|
end
|
97
97
|
if missing_members.length > 0
|
@@ -100,7 +100,7 @@ class Chef
|
|
100
100
|
|
101
101
|
members_to_be_removed = []
|
102
102
|
@new_resource.excluded_members.each do |member|
|
103
|
-
if
|
103
|
+
if has_current_group_member?(member)
|
104
104
|
members_to_be_removed << member
|
105
105
|
end
|
106
106
|
end
|
@@ -116,6 +116,10 @@ class Chef
|
|
116
116
|
!@change_desc.empty?
|
117
117
|
end
|
118
118
|
|
119
|
+
def has_current_group_member?(member)
|
120
|
+
@current_resource.members.include?(member)
|
121
|
+
end
|
122
|
+
|
119
123
|
def action_create
|
120
124
|
case @group_exists
|
121
125
|
when false
|
@@ -59,7 +59,7 @@ class Chef
|
|
59
59
|
if @new_resource.append
|
60
60
|
members_to_be_added = [ ]
|
61
61
|
@new_resource.members.each do |member|
|
62
|
-
members_to_be_added << member if
|
62
|
+
members_to_be_added << member if ! has_current_group_member?(member)
|
63
63
|
end
|
64
64
|
|
65
65
|
# local_add_members will raise ERROR_MEMBER_IN_ALIAS if a
|
@@ -68,7 +68,8 @@ class Chef
|
|
68
68
|
|
69
69
|
members_to_be_removed = [ ]
|
70
70
|
@new_resource.excluded_members.each do |member|
|
71
|
-
|
71
|
+
member_sid = local_group_name_to_sid(member)
|
72
|
+
members_to_be_removed << member if has_current_group_member?(member)
|
72
73
|
end
|
73
74
|
@net_group.local_delete_members(members_to_be_removed) unless members_to_be_removed.empty?
|
74
75
|
else
|
@@ -76,10 +77,19 @@ class Chef
|
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
80
|
+
def has_current_group_member?(member)
|
81
|
+
member_sid = local_group_name_to_sid(member)
|
82
|
+
@current_resource.members.include?(member_sid)
|
83
|
+
end
|
84
|
+
|
79
85
|
def remove_group
|
80
86
|
@net_group.local_delete
|
81
87
|
end
|
82
88
|
|
89
|
+
def local_group_name_to_sid(group_name)
|
90
|
+
locally_qualified_name = group_name.include?("\\") ? group_name : "#{ENV['COMPUTERNAME']}\\#{group_name}"
|
91
|
+
Chef::ReservedNames::Win32::Security.lookup_account_name(locally_qualified_name)[1].to_s
|
92
|
+
end
|
83
93
|
end
|
84
94
|
end
|
85
95
|
end
|
@@ -36,7 +36,8 @@ class Chef
|
|
36
36
|
# Send a HEAD request to @new_resource.url, with ?message=@new_resource.message
|
37
37
|
def action_head
|
38
38
|
message = check_message(@new_resource.message)
|
39
|
-
#
|
39
|
+
# CHEF-4762: we expect a nil return value from Chef::HTTP for a "200 Success" response
|
40
|
+
# and false for a "304 Not Modified" response
|
40
41
|
modified = @http.head(
|
41
42
|
"#{@new_resource.url}?message=#{message}",
|
42
43
|
@new_resource.headers
|
@@ -44,7 +45,7 @@ class Chef
|
|
44
45
|
Chef::Log.info("#{@new_resource} HEAD to #{@new_resource.url} successful")
|
45
46
|
Chef::Log.debug("#{@new_resource} HEAD request response: #{modified}")
|
46
47
|
# :head is usually used to trigger notifications, which converge_by now does
|
47
|
-
if modified
|
48
|
+
if modified != false
|
48
49
|
converge_by("#{@new_resource} HEAD to #{@new_resource.url} returned modified, trigger notifications") {}
|
49
50
|
end
|
50
51
|
end
|
@@ -202,6 +202,7 @@ class Chef
|
|
202
202
|
if template_available?(@new_resource.response_file)
|
203
203
|
Chef::Log.debug("#{@new_resource} fetching preseed file via Template")
|
204
204
|
remote_file = Chef::Resource::Template.new(cache_seed_to, run_context)
|
205
|
+
remote_file.variables(@new_resource.response_file_variables)
|
205
206
|
elsif cookbook_file_available?(@new_resource.response_file)
|
206
207
|
Chef::Log.debug("#{@new_resource} fetching preseed file via cookbook_file")
|
207
208
|
remote_file = Chef::Resource::CookbookFile.new(cache_seed_to, run_context)
|
@@ -88,7 +88,7 @@ class Chef
|
|
88
88
|
status = popen4("installp -L -d #{@new_resource.source}") do |pid, stdin, stdout, stderr|
|
89
89
|
stdout.each_line do |line|
|
90
90
|
case line
|
91
|
-
when /\w
|
91
|
+
when /\w:#{Regexp.escape(@new_resource.package_name)}:(.*)/
|
92
92
|
fields = line.split(":")
|
93
93
|
@candidate_version = fields[2]
|
94
94
|
@new_resource.version(fields[2])
|
@@ -103,7 +103,7 @@ class Chef
|
|
103
103
|
priority.each { |runlevel, arguments|
|
104
104
|
Chef::Log.debug("#{@new_resource} runlevel #{runlevel}, action #{arguments[0]}, priority #{arguments[1]}")
|
105
105
|
# if we are in a update-rc.d default startup runlevel && we start in this runlevel
|
106
|
-
if
|
106
|
+
if %w[ 1 2 3 4 5 S ].include?(runlevel) && arguments[0] == :start
|
107
107
|
enabled = true
|
108
108
|
end
|
109
109
|
}
|
@@ -113,7 +113,12 @@ class Chef
|
|
113
113
|
|
114
114
|
# Override method from parent to ensure priority is up-to-date
|
115
115
|
def action_enable
|
116
|
-
if @
|
116
|
+
if @new_resource.priority.nil?
|
117
|
+
priority_ok = true
|
118
|
+
else
|
119
|
+
priority_ok = @current_resource.priority == @new_resource.priority
|
120
|
+
end
|
121
|
+
if @current_resource.enabled and priority_ok
|
117
122
|
Chef::Log.debug("#{@new_resource} already enabled - nothing to do")
|
118
123
|
else
|
119
124
|
converge_by("enable service #{@new_resource}") do
|
data/lib/chef/resource/file.rb
CHANGED
@@ -52,9 +52,9 @@ class Chef
|
|
52
52
|
@force_unlink = false
|
53
53
|
@manage_symlink_source = nil
|
54
54
|
@diff = nil
|
55
|
+
@sensitive = false
|
55
56
|
end
|
56
57
|
|
57
|
-
|
58
58
|
def content(arg=nil)
|
59
59
|
set_or_return(
|
60
60
|
:content,
|
@@ -119,6 +119,13 @@ class Chef
|
|
119
119
|
)
|
120
120
|
end
|
121
121
|
|
122
|
+
def sensitive(arg=nil)
|
123
|
+
set_or_return(
|
124
|
+
:sensitive,
|
125
|
+
arg,
|
126
|
+
:kind_of => [ TrueClass, FalseClass ]
|
127
|
+
)
|
128
|
+
end
|
122
129
|
end
|
123
130
|
end
|
124
131
|
end
|
@@ -36,6 +36,7 @@ class Chef
|
|
36
36
|
@package_name = name
|
37
37
|
@resource_name = :package
|
38
38
|
@response_file = nil
|
39
|
+
@response_file_variables = Hash.new
|
39
40
|
@source = nil
|
40
41
|
@version = nil
|
41
42
|
end
|
@@ -64,6 +65,14 @@ class Chef
|
|
64
65
|
)
|
65
66
|
end
|
66
67
|
|
68
|
+
def response_file_variables(arg=nil)
|
69
|
+
set_or_return(
|
70
|
+
:response_file_variables,
|
71
|
+
arg,
|
72
|
+
:kind_of => [ Hash ]
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
67
76
|
def source(arg=nil)
|
68
77
|
set_or_return(
|
69
78
|
:source,
|
@@ -43,7 +43,6 @@ class Chef
|
|
43
43
|
@init_command = nil
|
44
44
|
@priority = nil
|
45
45
|
@action = "nothing"
|
46
|
-
@startup_type = :automatic
|
47
46
|
@supports = { :restart => false, :reload => false, :status => false }
|
48
47
|
@allowed_actions.push(:enable, :disable, :start, :stop, :restart, :reload)
|
49
48
|
end
|
data/lib/chef/rest.rb
CHANGED
@@ -32,6 +32,7 @@ require 'chef/http/decompressor'
|
|
32
32
|
require 'chef/http/json_input'
|
33
33
|
require 'chef/http/json_to_model_output'
|
34
34
|
require 'chef/http/cookie_manager'
|
35
|
+
require 'chef/http/validate_content_length'
|
35
36
|
require 'chef/config'
|
36
37
|
require 'chef/exceptions'
|
37
38
|
require 'chef/platform/query_helpers'
|
@@ -62,6 +63,7 @@ class Chef
|
|
62
63
|
@decompressor = Decompressor.new(options)
|
63
64
|
@authenticator = Authenticator.new(options)
|
64
65
|
|
66
|
+
@middlewares << ValidateContentLength.new(options)
|
65
67
|
@middlewares << JSONInput.new(options)
|
66
68
|
@middlewares << JSONToModelOutput.new(options)
|
67
69
|
@middlewares << CookieManager.new(options)
|
data/lib/chef/run_context.rb
CHANGED
data/lib/chef/util/file_edit.rb
CHANGED
@@ -33,7 +33,7 @@ class Chef
|
|
33
33
|
@file_edited = false
|
34
34
|
|
35
35
|
raise ArgumentError, "File doesn't exist" unless File.exist? @original_pathname
|
36
|
-
@contents = File.new(@original_pathname).readlines
|
36
|
+
@contents = File.new(@original_pathname){ |f| f.readlines }
|
37
37
|
end
|
38
38
|
|
39
39
|
#search the file line by line and match each line with the given regex
|
@@ -55,19 +55,20 @@ class Chef::Util::Windows::NetGroup < Chef::Util::Windows
|
|
55
55
|
nread = 0.chr * PTR_SIZE
|
56
56
|
total = 0.chr * PTR_SIZE
|
57
57
|
|
58
|
-
rc = NetLocalGroupGetMembers.call(nil, @name,
|
58
|
+
rc = NetLocalGroupGetMembers.call(nil, @name, 0, ptr, -1,
|
59
59
|
nread, total, handle)
|
60
60
|
if (rc == NERR_Success) || (rc == ERROR_MORE_DATA)
|
61
61
|
ptr = ptr.unpack('L')[0]
|
62
62
|
nread = nread.unpack('i')[0]
|
63
|
-
members = 0.chr * (nread *
|
63
|
+
members = 0.chr * (nread * PTR_SIZE ) #nread * sizeof(LOCALGROUP_MEMBERS_INFO_0)
|
64
64
|
memcpy(members, ptr, members.size)
|
65
65
|
|
66
|
-
#
|
66
|
+
# 1 pointer field in LOCALGROUP_MEMBERS_INFO_0, offset 0 is lgrmi0_sid
|
67
67
|
nread.times do |i|
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
sid_address = members[i * PTR_SIZE, PTR_SIZE].unpack('L')[0]
|
69
|
+
sid_ptr = FFI::Pointer.new(sid_address)
|
70
|
+
member_sid = Chef::ReservedNames::Win32::Security::SID.new(sid_ptr)
|
71
|
+
group_members << member_sid.to_s
|
71
72
|
end
|
72
73
|
NetApiBufferFree(ptr)
|
73
74
|
else
|
data/lib/chef/version.rb
CHANGED
data/lib/chef/win32/version.rb
CHANGED
@@ -35,20 +35,25 @@ class Chef
|
|
35
35
|
Win32API.new('user32', 'GetSystemMetrics', 'I', 'I').call(n_index)
|
36
36
|
end
|
37
37
|
|
38
|
+
def self.method_name_from_marketing_name(marketing_name)
|
39
|
+
"#{marketing_name.gsub(/\s/, '_').gsub(/\./, '_').downcase}?"
|
40
|
+
# "#{marketing_name.gsub(/\s/, '_').gsub(//, '_').downcase}?"
|
41
|
+
end
|
42
|
+
|
38
43
|
public
|
39
44
|
|
40
45
|
WIN_VERSIONS = {
|
41
|
-
"Windows 8.1" => {:major => 6, :minor => 3, :callable => lambda{
|
42
|
-
"Windows Server 2012 R2" => {:major => 6, :minor => 3, :callable => lambda{
|
43
|
-
"Windows 8" => {:major => 6, :minor => 2, :callable => lambda{
|
44
|
-
"Windows Server 2012" => {:major => 6, :minor => 2, :callable => lambda{
|
45
|
-
"Windows 7" => {:major => 6, :minor => 1, :callable => lambda{
|
46
|
-
"Windows Server 2008 R2" => {:major => 6, :minor => 1, :callable => lambda{
|
47
|
-
"Windows Server 2008" => {:major => 6, :minor => 0, :callable => lambda{
|
48
|
-
"Windows Vista" => {:major => 6, :minor => 0, :callable => lambda{
|
49
|
-
"Windows Server 2003 R2" => {:major => 5, :minor => 2, :callable => lambda{ get_system_metrics(SM_SERVERR2) != 0 }},
|
50
|
-
"Windows Home Server" => {:major => 5, :minor => 2, :callable => lambda{
|
51
|
-
"Windows Server 2003" => {:major => 5, :minor => 2, :callable => lambda{ get_system_metrics(SM_SERVERR2) == 0 }},
|
46
|
+
"Windows 8.1" => {:major => 6, :minor => 3, :callable => lambda{ |product_type, suite_mask| product_type == VER_NT_WORKSTATION }},
|
47
|
+
"Windows Server 2012 R2" => {:major => 6, :minor => 3, :callable => lambda {|product_type, suite_mask| product_type != VER_NT_WORKSTATION }},
|
48
|
+
"Windows 8" => {:major => 6, :minor => 2, :callable => lambda{ |product_type, suite_mask| product_type == VER_NT_WORKSTATION }},
|
49
|
+
"Windows Server 2012" => {:major => 6, :minor => 2, :callable => lambda{ |product_type, suite_mask| product_type != VER_NT_WORKSTATION }},
|
50
|
+
"Windows 7" => {:major => 6, :minor => 1, :callable => lambda{ |product_type, suite_mask| product_type == VER_NT_WORKSTATION }},
|
51
|
+
"Windows Server 2008 R2" => {:major => 6, :minor => 1, :callable => lambda{ |product_type, suite_mask| product_type != VER_NT_WORKSTATION }},
|
52
|
+
"Windows Server 2008" => {:major => 6, :minor => 0, :callable => lambda{ |product_type, suite_mask| product_type != VER_NT_WORKSTATION }},
|
53
|
+
"Windows Vista" => {:major => 6, :minor => 0, :callable => lambda{ |product_type, suite_mask| product_type == VER_NT_WORKSTATION }},
|
54
|
+
"Windows Server 2003 R2" => {:major => 5, :minor => 2, :callable => lambda{ |product_type, suite_mask| get_system_metrics(SM_SERVERR2) != 0 }},
|
55
|
+
"Windows Home Server" => {:major => 5, :minor => 2, :callable => lambda{ |product_type, suite_mask| (suite_mask & VER_SUITE_WH_SERVER) == VER_SUITE_WH_SERVER }},
|
56
|
+
"Windows Server 2003" => {:major => 5, :minor => 2, :callable => lambda{ |product_type, suite_mask| get_system_metrics(SM_SERVERR2) == 0 }},
|
52
57
|
"Windows XP" => {:major => 5, :minor => 1},
|
53
58
|
"Windows 2000" => {:major => 5, :minor => 0}
|
54
59
|
}
|
@@ -77,11 +82,11 @@ class Chef
|
|
77
82
|
|
78
83
|
# General Windows checks
|
79
84
|
WIN_VERSIONS.each do |k,v|
|
80
|
-
method_name =
|
85
|
+
method_name = method_name_from_marketing_name(k)
|
81
86
|
define_method(method_name) do
|
82
87
|
(@major_version == v[:major]) &&
|
83
88
|
(@minor_version == v[:minor]) &&
|
84
|
-
(v[:callable] ? v[:callable].call : true)
|
89
|
+
(v[:callable] ? v[:callable].call(@product_type, @suite_mask) : true)
|
85
90
|
end
|
86
91
|
marketing_names << [k, method_name]
|
87
92
|
end
|
@@ -105,11 +110,19 @@ class Chef
|
|
105
110
|
private
|
106
111
|
|
107
112
|
def get_version
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
+
# Use WMI here because API's like GetVersion return faked
|
114
|
+
# version numbers on Windows Server 2012 R2 and Windows 8.1 --
|
115
|
+
# WMI always returns the truth. See article at
|
116
|
+
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
|
117
|
+
require 'ruby-wmi'
|
118
|
+
|
119
|
+
os_info = WMI::Win32_OperatingSystem.find(:first)
|
120
|
+
os_version = os_info.send('Version')
|
121
|
+
|
122
|
+
# The operating system version is a string in the following form
|
123
|
+
# that can be split into components based on the '.' delimiter:
|
124
|
+
# MajorVersionNumber.MinorVersionNumber.BuildNumber
|
125
|
+
os_version.split('.').collect { | version_string | version_string.to_i }
|
113
126
|
end
|
114
127
|
|
115
128
|
def get_version_ex
|
@@ -0,0 +1 @@
|
|
1
|
+
chef-integration-test chef-integration-test/sample-var string "<%= @template_variable -%>"
|
@@ -38,7 +38,8 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte
|
|
38
38
|
def user_exist_in_group?(user)
|
39
39
|
case ohai[:platform_family]
|
40
40
|
when "windows"
|
41
|
-
|
41
|
+
user_sid = sid_string_from_user(user)
|
42
|
+
user_sid.nil? ? false : Chef::Util::Windows::NetGroup.new(group_name).local_get_members.include?(user_sid)
|
42
43
|
else
|
43
44
|
Etc::getgrnam(group_name).mem.include?(user)
|
44
45
|
end
|
@@ -57,6 +58,25 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte
|
|
57
58
|
return resource.gid == Etc::getgrnam(resource.name).gid if unix?
|
58
59
|
end
|
59
60
|
|
61
|
+
def sid_string_from_user(user)
|
62
|
+
begin
|
63
|
+
sid = Chef::ReservedNames::Win32::Security.lookup_account_name(user)
|
64
|
+
rescue Chef::Exceptions::Win32APIError
|
65
|
+
sid = nil
|
66
|
+
end
|
67
|
+
|
68
|
+
sid.nil? ? nil : sid[1].to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
def windows_domain_user?(user_name)
|
72
|
+
domain, user = user_name.split('\\')
|
73
|
+
|
74
|
+
if user && domain != '.'
|
75
|
+
computer_name = ENV['computername']
|
76
|
+
domain.downcase != computer_name.downcase
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
60
80
|
def user(username)
|
61
81
|
usr = Chef::Resource::User.new("#{username}", run_context)
|
62
82
|
if ohai[:platform_family] == "windows"
|
@@ -66,12 +86,12 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte
|
|
66
86
|
end
|
67
87
|
|
68
88
|
def create_user(username)
|
69
|
-
user(username).run_action(:create)
|
89
|
+
user(username).run_action(:create) if ! windows_domain_user?(username)
|
70
90
|
# TODO: User shouldn't exist
|
71
91
|
end
|
72
92
|
|
73
93
|
def remove_user(username)
|
74
|
-
user(username).run_action(:remove)
|
94
|
+
user(username).run_action(:remove) if ! windows_domain_user?(username)
|
75
95
|
# TODO: User shouldn't exist
|
76
96
|
end
|
77
97
|
|
@@ -108,24 +128,24 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte
|
|
108
128
|
end
|
109
129
|
|
110
130
|
describe "when append is not set" do
|
111
|
-
let(:included_members) { [
|
131
|
+
let(:included_members) { [spec_members[1]] }
|
112
132
|
|
113
133
|
before do
|
114
|
-
create_user(
|
115
|
-
create_user(
|
116
|
-
add_members_to_group([
|
134
|
+
create_user(spec_members[1])
|
135
|
+
create_user(spec_members[0])
|
136
|
+
add_members_to_group([spec_members[0]])
|
117
137
|
end
|
118
138
|
|
119
139
|
after do
|
120
|
-
remove_user(
|
121
|
-
remove_user(
|
140
|
+
remove_user(spec_members[1])
|
141
|
+
remove_user(spec_members[0])
|
122
142
|
end
|
123
143
|
|
124
144
|
it "should remove the existing users and add the new users to the group" do
|
125
145
|
group_resource.run_action(tested_action)
|
126
146
|
|
127
|
-
user_exist_in_group?(
|
128
|
-
user_exist_in_group?(
|
147
|
+
user_exist_in_group?(spec_members[1]).should == true
|
148
|
+
user_exist_in_group?(spec_members[0]).should == false
|
129
149
|
end
|
130
150
|
end
|
131
151
|
|
@@ -160,7 +180,7 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte
|
|
160
180
|
|
161
181
|
describe "when group contains some users" do
|
162
182
|
before(:each) do
|
163
|
-
add_members_to_group([
|
183
|
+
add_members_to_group([ spec_members[0], spec_members[2] ])
|
164
184
|
end
|
165
185
|
|
166
186
|
it "should add the included users and remove excluded users" do
|
@@ -192,6 +212,42 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte
|
|
192
212
|
end
|
193
213
|
end
|
194
214
|
|
215
|
+
shared_examples_for "an expected invalid domain error case" do
|
216
|
+
let(:invalid_domain_user_name) { "no space\\administrator" }
|
217
|
+
let(:nonexistent_domain_user_name) { "xxfakedom\\administrator" }
|
218
|
+
before(:each) do
|
219
|
+
group_resource.members []
|
220
|
+
group_resource.excluded_members []
|
221
|
+
group_resource.append(true)
|
222
|
+
group_resource.run_action(:create)
|
223
|
+
group_should_exist(group_name)
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "when updating membership" do
|
227
|
+
it "raises an error for a non well-formed domain name" do
|
228
|
+
group_resource.members [invalid_domain_user_name]
|
229
|
+
lambda { group_resource.run_action(tested_action) }.should raise_error Chef::Exceptions::Win32APIError
|
230
|
+
end
|
231
|
+
|
232
|
+
it "raises an error for a nonexistent domain" do
|
233
|
+
group_resource.members [nonexistent_domain_user_name]
|
234
|
+
lambda { group_resource.run_action(tested_action) }.should raise_error Chef::Exceptions::Win32APIError
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "when removing members" do
|
239
|
+
it "raises an error for a non well-formed domain name" do
|
240
|
+
group_resource.excluded_members [invalid_domain_user_name]
|
241
|
+
lambda { group_resource.run_action(tested_action) }.should raise_error Chef::Exceptions::Win32APIError
|
242
|
+
end
|
243
|
+
|
244
|
+
it "raises an error for a nonexistent domain" do
|
245
|
+
group_resource.excluded_members [nonexistent_domain_user_name]
|
246
|
+
lambda { group_resource.run_action(tested_action) }.should raise_error Chef::Exceptions::Win32APIError
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
195
251
|
let(:group_name) { "cheftest-#{SecureRandom.random_number(9999)}" }
|
196
252
|
let(:included_members) { nil }
|
197
253
|
let(:excluded_members) { nil }
|
@@ -274,8 +330,9 @@ downthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreeQQQQQQ" }
|
|
274
330
|
end
|
275
331
|
|
276
332
|
describe "group modify action", :not_supported_on_solaris do
|
277
|
-
let(:
|
278
|
-
let(:
|
333
|
+
let(:spec_members){ ["spec-Gordon", "spec-Eric", "spec-Anthony"] }
|
334
|
+
let(:included_members) { [spec_members[0], spec_members[1]] }
|
335
|
+
let(:excluded_members) { [spec_members[2]] }
|
279
336
|
let(:tested_action) { :modify }
|
280
337
|
|
281
338
|
describe "when there is no group" do
|
@@ -287,11 +344,23 @@ downthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreeQQQQQQ" }
|
|
287
344
|
describe "when there is a group" do
|
288
345
|
it_behaves_like "correct group management"
|
289
346
|
end
|
347
|
+
|
348
|
+
describe "when running on Windows", :windows_only do
|
349
|
+
describe "when members are Active Directory domain identities", :windows_domain_joined_only do
|
350
|
+
let(:computer_domain) { ohai[:kernel]['cs_info']['domain'].split('.')[0] }
|
351
|
+
let(:spec_members){ ["#{computer_domain}\\Domain Admins", "#{computer_domain}\\Domain Users", "#{computer_domain}\\Domain Computers"] }
|
352
|
+
|
353
|
+
include_examples "correct group management"
|
354
|
+
end
|
355
|
+
|
356
|
+
it_behaves_like "an expected invalid domain error case"
|
357
|
+
end
|
290
358
|
end
|
291
359
|
|
292
360
|
describe "group manage action", :not_supported_on_solaris do
|
293
|
-
let(:
|
294
|
-
let(:
|
361
|
+
let(:spec_members){ ["spec-Gordon", "spec-Eric", "spec-Anthony"] }
|
362
|
+
let(:included_members) { [spec_members[0], spec_members[1]] }
|
363
|
+
let(:excluded_members) { [spec_members[2]] }
|
295
364
|
let(:tested_action) { :manage }
|
296
365
|
|
297
366
|
describe "when there is no group" do
|
@@ -304,6 +373,17 @@ downthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreeQQQQQQ" }
|
|
304
373
|
describe "when there is a group" do
|
305
374
|
it_behaves_like "correct group management"
|
306
375
|
end
|
376
|
+
|
377
|
+
describe "running on windows", :windows_only do
|
378
|
+
describe "when members are Windows domain identities", :windows_domain_joined_only do
|
379
|
+
let(:computer_domain) { ohai[:kernel]['cs_info']['domain'].split('.')[0] }
|
380
|
+
let(:spec_members){ ["#{computer_domain}\\Domain Admins", "#{computer_domain}\\Domain Users", "#{computer_domain}\\Domain Computers"] }
|
381
|
+
|
382
|
+
include_examples "correct group management"
|
383
|
+
end
|
384
|
+
|
385
|
+
it_behaves_like "an expected invalid domain error case"
|
386
|
+
end
|
307
387
|
end
|
308
388
|
|
309
389
|
describe "group resource with Usermod provider", :solaris_only do
|