chef 12.1.2 → 12.2.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/chef/application/client.rb +2 -2
- data/lib/chef/audit/audit_reporter.rb +1 -1
- data/lib/chef/audit/runner.rb +15 -2
- data/lib/chef/client.rb +1 -1
- data/lib/chef/config.rb +6 -4
- data/lib/chef/dsl/powershell.rb +29 -0
- data/lib/chef/exceptions.rb +18 -3
- data/lib/chef/formatters/doc.rb +2 -2
- data/lib/chef/knife/bootstrap.rb +2 -1
- data/lib/chef/knife/bootstrap/templates/chef-full.erb +1 -1
- data/lib/chef/knife/core/subcommand_loader.rb +13 -5
- data/lib/chef/knife/exec.rb +2 -1
- data/lib/chef/knife/ssh.rb +12 -2
- data/lib/chef/mixin/params_validate.rb +42 -19
- data/lib/chef/mixin/powershell_type_coercions.rb +82 -0
- data/lib/chef/mixin/windows_architecture_helper.rb +8 -0
- data/lib/chef/node.rb +1 -1
- data/lib/chef/platform/provider_mapping.rb +0 -107
- data/lib/chef/platform/query_helpers.rb +7 -0
- data/lib/chef/provider/batch.rb +2 -0
- data/lib/chef/provider/cron.rb +2 -0
- data/lib/chef/provider/cron/aix.rb +2 -0
- data/lib/chef/provider/cron/unix.rb +2 -0
- data/lib/chef/provider/deploy.rb +104 -87
- data/lib/chef/provider/dsc_resource.rb +157 -0
- data/lib/chef/provider/env.rb +2 -0
- data/lib/chef/provider/env/windows.rb +2 -0
- data/lib/chef/provider/git.rb +4 -0
- data/lib/chef/provider/group.rb +5 -5
- data/lib/chef/provider/group/dscl.rb +2 -0
- data/lib/chef/provider/group/groupmod.rb +2 -0
- data/lib/chef/provider/group/usermod.rb +2 -0
- data/lib/chef/provider/group/windows.rb +2 -0
- data/lib/chef/provider/mdadm.rb +2 -0
- data/lib/chef/provider/mount/windows.rb +2 -0
- data/lib/chef/provider/package/homebrew.rb +1 -1
- data/lib/chef/provider/package/openbsd.rb +49 -18
- data/lib/chef/provider/package/rubygems.rb +7 -2
- data/lib/chef/provider/powershell_script.rb +2 -0
- data/lib/chef/provider/service/macosx.rb +1 -2
- data/lib/chef/provider/user/dscl.rb +7 -1
- data/lib/chef/provider/user/windows.rb +2 -0
- data/lib/chef/providers.rb +1 -0
- data/lib/chef/recipe.rb +2 -0
- data/lib/chef/resource.rb +9 -0
- data/lib/chef/resource/batch.rb +2 -0
- data/lib/chef/resource/cron.rb +3 -3
- data/lib/chef/resource/deploy.rb +52 -217
- data/lib/chef/resource/dsc_resource.rb +83 -0
- data/lib/chef/resource/env.rb +2 -0
- data/lib/chef/resource/git.rb +1 -1
- data/lib/chef/resource/group.rb +2 -0
- data/lib/chef/resource/homebrew_package.rb +1 -1
- data/lib/chef/resource/lwrp_base.rb +0 -8
- data/lib/chef/resource/mdadm.rb +2 -0
- data/lib/chef/resource/mount.rb +2 -0
- data/lib/chef/resource/powershell_script.rb +2 -0
- data/lib/chef/resource/user.rb +2 -0
- data/lib/chef/resources.rb +1 -0
- data/lib/chef/run_context.rb +1 -1
- data/lib/chef/shell.rb +7 -5
- data/lib/chef/util/dsc/resource_store.rb +110 -0
- data/lib/chef/util/path_helper.rb +76 -0
- data/lib/chef/util/powershell/cmdlet.rb +41 -7
- data/lib/chef/util/powershell/cmdlet_result.rb +18 -3
- data/lib/chef/util/powershell/ps_credential.rb +38 -0
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/api.rb +2 -0
- data/lib/chef/win32/api/crypto.rb +63 -0
- data/lib/chef/win32/api/installer.rb +1 -1
- data/lib/chef/win32/crypto.rb +49 -0
- data/lib/chef/workstation_config_loader.rb +4 -3
- data/spec/functional/file_content_management/deploy_strategies_spec.rb +1 -1
- data/spec/functional/resource/cookbook_file_spec.rb +1 -1
- data/spec/functional/resource/deploy_revision_spec.rb +35 -0
- data/spec/functional/resource/directory_spec.rb +1 -1
- data/spec/functional/resource/dsc_resource_spec.rb +93 -0
- data/spec/functional/resource/env_spec.rb +4 -3
- data/spec/functional/resource/file_spec.rb +1 -1
- data/spec/functional/resource/powershell_spec.rb +2 -1
- data/spec/functional/resource/remote_directory_spec.rb +1 -1
- data/spec/functional/resource/remote_file_spec.rb +1 -1
- data/spec/functional/resource/template_spec.rb +1 -1
- data/spec/functional/resource/user/dscl_spec.rb +1 -2
- data/spec/functional/resource/user/useradd_spec.rb +27 -13
- data/spec/functional/util/powershell/cmdlet_spec.rb +3 -3
- data/spec/functional/win32/crypto_spec.rb +57 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/platform_helpers.rb +14 -0
- data/spec/support/shared/functional/securable_resource_with_reporting.rb +5 -5
- data/spec/unit/application/client_spec.rb +4 -4
- data/spec/unit/audit/audit_reporter_spec.rb +1 -1
- data/spec/unit/audit/runner_spec.rb +10 -0
- data/spec/unit/config_spec.rb +2 -8
- data/spec/unit/knife/bootstrap_spec.rb +20 -8
- data/spec/unit/knife/core/subcommand_loader_spec.rb +29 -29
- data/spec/unit/mixin/params_validate_spec.rb +75 -61
- data/spec/unit/mixin/powershell_type_coercions_spec.rb +72 -0
- data/spec/unit/platform/query_helpers_spec.rb +22 -0
- data/spec/unit/platform_spec.rb +0 -5
- data/spec/unit/provider/dsc_resource_spec.rb +84 -0
- data/spec/unit/provider/package/openbsd_spec.rb +105 -17
- data/spec/unit/provider/service/macosx_spec.rb +3 -3
- data/spec/unit/provider_resolver_spec.rb +132 -0
- data/spec/unit/recipe_spec.rb +4 -0
- data/spec/unit/resource/deploy_spec.rb +27 -0
- data/spec/unit/resource/dsc_resource_spec.rb +85 -0
- data/spec/unit/shell_spec.rb +1 -1
- data/spec/unit/util/dsc/resource_store.rb +76 -0
- data/spec/unit/util/powershell/ps_credential_spec.rb +37 -0
- data/spec/unit/workstation_config_loader_spec.rb +1 -1
- metadata +159 -186
@@ -0,0 +1,83 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Edwards (<adamed@getchef.com>)
|
3
|
+
#
|
4
|
+
# Copyright:: 2014, Opscode, Inc.
|
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
|
+
require 'chef/dsl/powershell'
|
19
|
+
|
20
|
+
class Chef
|
21
|
+
class Resource
|
22
|
+
class DscResource < Chef::Resource
|
23
|
+
|
24
|
+
provides :dsc_resource, os: "windows"
|
25
|
+
|
26
|
+
include Chef::DSL::Powershell
|
27
|
+
|
28
|
+
def initialize(name, run_context)
|
29
|
+
super
|
30
|
+
@properties = {}
|
31
|
+
@resource_name = :dsc_resource
|
32
|
+
@resource = nil
|
33
|
+
@allowed_actions.push(:run)
|
34
|
+
@action = :run
|
35
|
+
end
|
36
|
+
|
37
|
+
def resource(value=nil)
|
38
|
+
if value
|
39
|
+
@resource = value
|
40
|
+
else
|
41
|
+
@resource
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def module_name(value=nil)
|
46
|
+
if value
|
47
|
+
@module_name = value
|
48
|
+
else
|
49
|
+
@module_name
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def property(property_name, value=nil)
|
54
|
+
if not property_name.is_a?(Symbol)
|
55
|
+
raise TypeError, "A property name of type Symbol must be specified, '#{property_name.to_s}' of type #{property_name.class.to_s} was given"
|
56
|
+
end
|
57
|
+
|
58
|
+
if value.nil?
|
59
|
+
value_of(@properties[property_name])
|
60
|
+
else
|
61
|
+
@properties[property_name] = value
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def properties
|
66
|
+
@properties.reduce({}) do |memo, (k, v)|
|
67
|
+
memo[k] = value_of(v)
|
68
|
+
memo
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def value_of(value)
|
75
|
+
if value.is_a?(DelayedEvaluator)
|
76
|
+
value.call
|
77
|
+
else
|
78
|
+
value
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/chef/resource/env.rb
CHANGED
data/lib/chef/resource/git.rb
CHANGED
data/lib/chef/resource/group.rb
CHANGED
@@ -70,14 +70,6 @@ class Chef
|
|
70
70
|
alias_method :resource_name=, :resource_name
|
71
71
|
end
|
72
72
|
|
73
|
-
# Define an attribute on this resource, including optional validation
|
74
|
-
# parameters.
|
75
|
-
def self.attribute(attr_name, validation_opts={})
|
76
|
-
define_method(attr_name) do |arg=nil|
|
77
|
-
set_or_return(attr_name.to_sym, arg, validation_opts)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
73
|
# Sets the default action
|
82
74
|
def self.default_action(action_name=NULL_ARG)
|
83
75
|
unless action_name.equal?(NULL_ARG)
|
data/lib/chef/resource/mdadm.rb
CHANGED
data/lib/chef/resource/mount.rb
CHANGED
@@ -21,6 +21,8 @@ class Chef
|
|
21
21
|
class Resource
|
22
22
|
class PowershellScript < Chef::Resource::WindowsScript
|
23
23
|
|
24
|
+
provides :powershell_script, os: "windows"
|
25
|
+
|
24
26
|
def initialize(name, run_context=nil)
|
25
27
|
super(name, run_context, :powershell_script, "powershell.exe")
|
26
28
|
@convert_boolean_return = false
|
data/lib/chef/resource/user.rb
CHANGED
data/lib/chef/resources.rb
CHANGED
@@ -29,6 +29,7 @@ require 'chef/resource/deploy_revision'
|
|
29
29
|
require 'chef/resource/directory'
|
30
30
|
require 'chef/resource/dpkg_package'
|
31
31
|
require 'chef/resource/dsc_script'
|
32
|
+
require 'chef/resource/dsc_resource'
|
32
33
|
require 'chef/resource/easy_install_package'
|
33
34
|
require 'chef/resource/env'
|
34
35
|
require 'chef/resource/erl_call'
|
data/lib/chef/run_context.rb
CHANGED
@@ -50,7 +50,7 @@ class Chef
|
|
50
50
|
# recipes, which is triggered by #load. (See also: CookbookCompiler)
|
51
51
|
attr_accessor :resource_collection
|
52
52
|
|
53
|
-
# The list of
|
53
|
+
# The list of control groups to execute during the audit phase
|
54
54
|
attr_accessor :audits
|
55
55
|
|
56
56
|
# A Hash containing the immediate notifications triggered by resources
|
data/lib/chef/shell.rb
CHANGED
@@ -29,6 +29,7 @@ require 'chef/config_fetcher'
|
|
29
29
|
require 'chef/shell/shell_session'
|
30
30
|
require 'chef/shell/ext'
|
31
31
|
require 'chef/json_compat'
|
32
|
+
require 'chef/util/path_helper'
|
32
33
|
|
33
34
|
# = Shell
|
34
35
|
# Shell is Chef in an IRB session. Shell can interact with a Chef server via the
|
@@ -101,7 +102,7 @@ module Shell
|
|
101
102
|
end
|
102
103
|
|
103
104
|
def self.configure_irb
|
104
|
-
irb_conf[:HISTORY_FILE] = "
|
105
|
+
irb_conf[:HISTORY_FILE] = Chef::Util::PathHelper.home(".chef", "chef_shell_history")
|
105
106
|
irb_conf[:SAVE_HISTORY] = 1000
|
106
107
|
|
107
108
|
irb_conf[:IRB_RC] = lambda do |conf|
|
@@ -295,18 +296,19 @@ FOOTER
|
|
295
296
|
private
|
296
297
|
|
297
298
|
def config_file_for_shell_mode(environment)
|
299
|
+
dot_chef_dir = Chef::Util::PathHelper.home('.chef')
|
298
300
|
if config[:config_file]
|
299
301
|
config[:config_file]
|
300
|
-
elsif environment
|
302
|
+
elsif environment
|
301
303
|
Shell.env = environment
|
302
|
-
config_file_to_try = ::File.join(
|
304
|
+
config_file_to_try = ::File.join(dot_chef_dir, environment, 'chef_shell.rb')
|
303
305
|
unless ::File.exist?(config_file_to_try)
|
304
306
|
puts "could not find chef-shell config for environment #{environment} at #{config_file_to_try}"
|
305
307
|
exit 1
|
306
308
|
end
|
307
309
|
config_file_to_try
|
308
|
-
elsif
|
309
|
-
File.join(
|
310
|
+
elsif dot_chef_dir && ::File.exist?(File.join(dot_chef_dir, 'chef_shell.rb'))
|
311
|
+
File.join(dot_chef_dir, 'chef_shell.rb')
|
310
312
|
elsif config[:solo]
|
311
313
|
Chef::Config.platform_specific_path("/etc/chef/solo.rb")
|
312
314
|
elsif config[:client]
|
@@ -0,0 +1,110 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Jay Mundrawala (<jdm@chef.io>)
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (c) 2015 Chef Software, Inc.
|
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/powershell/cmdlet'
|
20
|
+
require 'chef/util/powershell/cmdlet_result'
|
21
|
+
require 'chef/exceptions'
|
22
|
+
|
23
|
+
class Chef
|
24
|
+
class Util
|
25
|
+
class DSC
|
26
|
+
class ResourceStore
|
27
|
+
|
28
|
+
def self.instance
|
29
|
+
@@instance ||= ResourceStore.new.tap do |store|
|
30
|
+
store.send(:populate_cache)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def resources
|
35
|
+
@resources ||= []
|
36
|
+
end
|
37
|
+
|
38
|
+
def find(name, module_name=nil)
|
39
|
+
found = find_resources(name, module_name, resources)
|
40
|
+
|
41
|
+
# We don't have it, query for the resource...it might
|
42
|
+
# have been added since we last queried
|
43
|
+
if found.length == 0
|
44
|
+
rs = query_resource(name)
|
45
|
+
add_resources(rs)
|
46
|
+
found = find_resources(name, module_name, rs)
|
47
|
+
end
|
48
|
+
|
49
|
+
found
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def add_resource(new_r)
|
55
|
+
count = resources.count do |r|
|
56
|
+
r['ResourceType'].casecmp(new_r['ResourceType']) == 0
|
57
|
+
end
|
58
|
+
if count == 0
|
59
|
+
resources << new_r
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_resources(rs)
|
64
|
+
rs.each do |r|
|
65
|
+
add_resource(r)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def populate_cache
|
70
|
+
@resources = query_resources
|
71
|
+
end
|
72
|
+
|
73
|
+
def find_resources(name, module_name, rs)
|
74
|
+
found = rs.find_all do |r|
|
75
|
+
name_matches = r['Name'].casecmp(name) == 0
|
76
|
+
if name_matches
|
77
|
+
module_name == nil || (r['Module'] and r['Module']['Name'].casecmp(module_name) == 0)
|
78
|
+
else
|
79
|
+
false
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
# Returns a list of dsc resources
|
86
|
+
def query_resources
|
87
|
+
cmdlet = Chef::Util::Powershell::Cmdlet.new(nil, 'get-dscresource',
|
88
|
+
:object)
|
89
|
+
result = cmdlet.run
|
90
|
+
result.return_value
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns a list of dsc resources matching the provided name
|
94
|
+
def query_resource(resource_name)
|
95
|
+
cmdlet = Chef::Util::Powershell::Cmdlet.new(nil, "get-dscresource #{resource_name}",
|
96
|
+
:object)
|
97
|
+
result = cmdlet.run
|
98
|
+
ret_val = result.return_value
|
99
|
+
if ret_val.nil?
|
100
|
+
[]
|
101
|
+
elsif ret_val.is_a? Array
|
102
|
+
ret_val
|
103
|
+
else
|
104
|
+
[ret_val]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -142,6 +142,82 @@ class Chef
|
|
142
142
|
def self.relative_path_from(from, to)
|
143
143
|
pathname = Pathname.new(Chef::Util::PathHelper.cleanpath(to)).relative_path_from(Pathname.new(Chef::Util::PathHelper.cleanpath(from)))
|
144
144
|
end
|
145
|
+
|
146
|
+
# Retrieves the "home directory" of the current user while trying to ascertain the existence
|
147
|
+
# of said directory. The path returned uses / for all separators (the ruby standard format).
|
148
|
+
# If the home directory doesn't exist or an error is otherwise encountered, nil is returned.
|
149
|
+
#
|
150
|
+
# If a set of path elements is provided, they are appended as-is to the home path if the
|
151
|
+
# homepath exists.
|
152
|
+
#
|
153
|
+
# If an optional block is provided, the joined path is passed to that block if the home path is
|
154
|
+
# valid and the result of the block is returned instead.
|
155
|
+
#
|
156
|
+
# Home-path discovery is performed once. If a path is discovered, that value is memoized so
|
157
|
+
# that subsequent calls to home_dir don't bounce around.
|
158
|
+
#
|
159
|
+
# See self.all_homes.
|
160
|
+
def self.home(*args)
|
161
|
+
@@home_dir ||= self.all_homes { |p| break p }
|
162
|
+
if @@home_dir
|
163
|
+
path = File.join(@@home_dir, *args)
|
164
|
+
block_given? ? (yield path) : path
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# See self.home. This method performs a similar operation except that it yields all the different
|
169
|
+
# possible values of 'HOME' that one could have on this platform. Hence, on windows, if
|
170
|
+
# HOMEDRIVE\HOMEPATH and USERPROFILE are different, the provided block will be called twice.
|
171
|
+
# This method goes out and checks the existence of each location at the time of the call.
|
172
|
+
#
|
173
|
+
# The return is a list of all the returned values from each block invocation or a list of paths
|
174
|
+
# if no block is provided.
|
175
|
+
def self.all_homes(*args)
|
176
|
+
paths = []
|
177
|
+
if Chef::Platform.windows?
|
178
|
+
# By default, Ruby uses the the following environment variables to determine Dir.home:
|
179
|
+
# HOME
|
180
|
+
# HOMEDRIVE HOMEPATH
|
181
|
+
# USERPROFILE
|
182
|
+
# Ruby only checks to see if the variable is specified - not if the directory actually exists.
|
183
|
+
# On Windows, HOMEDRIVE HOMEPATH can point to a different location (such as an unavailable network mounted drive)
|
184
|
+
# while USERPROFILE points to the location where the user application settings and profile are stored. HOME
|
185
|
+
# is not defined as an environment variable (usually). If the home path actually uses UNC, then the prefix is
|
186
|
+
# HOMESHARE instead of HOMEDRIVE.
|
187
|
+
#
|
188
|
+
# We instead walk down the following and only include paths that actually exist.
|
189
|
+
# HOME
|
190
|
+
# HOMEDRIVE HOMEPATH
|
191
|
+
# HOMESHARE HOMEPATH
|
192
|
+
# USERPROFILE
|
193
|
+
|
194
|
+
paths << ENV['HOME']
|
195
|
+
paths << ENV['HOMEDRIVE'] + ENV['HOMEPATH'] if ENV['HOMEDRIVE'] && ENV['HOMEPATH']
|
196
|
+
paths << ENV['HOMESHARE'] + ENV['HOMEPATH'] if ENV['HOMESHARE'] && ENV['HOMEPATH']
|
197
|
+
paths << ENV['USERPROFILE']
|
198
|
+
end
|
199
|
+
paths << Dir.home
|
200
|
+
|
201
|
+
# Depending on what environment variables we're using, the slashes can go in any which way.
|
202
|
+
# Just change them all to / to keep things consistent.
|
203
|
+
# Note: Maybe this is a bad idea on some unixy systems where \ might be a valid character depending on
|
204
|
+
# the particular brand of kool-aid you consume. This code assumes that \ and / are both
|
205
|
+
# path separators on any system being used.
|
206
|
+
paths = paths.map { |home_path| home_path.gsub(path_separator, ::File::SEPARATOR) if home_path }
|
207
|
+
|
208
|
+
# Filter out duplicate paths and paths that don't exist.
|
209
|
+
valid_paths = paths.select { |home_path| home_path && Dir.exists?(home_path) }
|
210
|
+
valid_paths = valid_paths.uniq
|
211
|
+
|
212
|
+
# Join all optional path elements at the end.
|
213
|
+
# If a block is provided, invoke it - otherwise just return what we've got.
|
214
|
+
joined_paths = valid_paths.map { |home_path| File.join(home_path, *args) }
|
215
|
+
if block_given?
|
216
|
+
joined_paths.each { |p| yield p }
|
217
|
+
else
|
218
|
+
joined_paths
|
219
|
+
end
|
220
|
+
end
|
145
221
|
end
|
146
222
|
end
|
147
223
|
end
|
@@ -20,7 +20,9 @@ require 'mixlib/shellout'
|
|
20
20
|
require 'chef/mixin/windows_architecture_helper'
|
21
21
|
require 'chef/util/powershell/cmdlet_result'
|
22
22
|
|
23
|
-
class Chef
|
23
|
+
class Chef
|
24
|
+
class Util
|
25
|
+
class Powershell
|
24
26
|
class Cmdlet
|
25
27
|
def initialize(node, cmdlet, output_format=nil, output_format_options={})
|
26
28
|
@output_format = output_format
|
@@ -46,6 +48,10 @@ class Chef::Util::Powershell
|
|
46
48
|
attr_reader :output_format
|
47
49
|
|
48
50
|
def run(switches={}, execution_options={}, *arguments)
|
51
|
+
streams = { :json => CmdletStream.new('json'),
|
52
|
+
:verbose => CmdletStream.new('verbose'),
|
53
|
+
}
|
54
|
+
|
49
55
|
arguments_string = arguments.join(' ')
|
50
56
|
|
51
57
|
switches_string = command_switches_string(switches)
|
@@ -56,21 +62,25 @@ class Chef::Util::Powershell
|
|
56
62
|
json_depth = @output_format_options[:depth]
|
57
63
|
end
|
58
64
|
|
59
|
-
json_command = @json_format ? " | convertto-json -compress -depth #{json_depth}
|
60
|
-
|
65
|
+
json_command = @json_format ? " | convertto-json -compress -depth #{json_depth} "\
|
66
|
+
"> #{streams[:json].path}" : ""
|
67
|
+
redirections = "4> '#{streams[:verbose].path}'"
|
68
|
+
command_string = "powershell.exe -executionpolicy bypass -noprofile -noninteractive "\
|
69
|
+
"-command \"trap [Exception] {write-error -exception "\
|
70
|
+
"($_.Exception.Message);exit 1};#{@cmdlet} #{switches_string} "\
|
71
|
+
"#{arguments_string} #{redirections}"\
|
72
|
+
"#{json_command}\";if ( ! $? ) { exit 1 }"
|
61
73
|
|
62
74
|
augmented_options = {:returns => [0], :live_stream => false}.merge(execution_options)
|
63
75
|
command = Mixlib::ShellOut.new(command_string, augmented_options)
|
64
76
|
|
65
|
-
os_architecture = "#{ENV['PROCESSOR_ARCHITEW6432']}" == 'AMD64' ? :x86_64 : :i386
|
66
|
-
|
67
77
|
status = nil
|
68
78
|
|
69
79
|
with_os_architecture(@node) do
|
70
80
|
status = command.run_command
|
71
81
|
end
|
72
82
|
|
73
|
-
CmdletResult.new(status, @output_format)
|
83
|
+
CmdletResult.new(status, streams, @output_format)
|
74
84
|
end
|
75
85
|
|
76
86
|
def run!(switches={}, execution_options={}, *arguments)
|
@@ -131,6 +141,30 @@ class Chef::Util::Powershell
|
|
131
141
|
|
132
142
|
command_switches.join(' ')
|
133
143
|
end
|
144
|
+
|
145
|
+
class CmdletStream
|
146
|
+
def initialize(name)
|
147
|
+
@filename = Dir::Tmpname.create(name) {}
|
148
|
+
ObjectSpace.define_finalizer(self, self.class.destroy(@filename))
|
149
|
+
end
|
150
|
+
|
151
|
+
def path
|
152
|
+
@filename
|
153
|
+
end
|
154
|
+
|
155
|
+
def read
|
156
|
+
if File.exist? @filename
|
157
|
+
File.open(@filename, 'rb:bom|UTF-16LE') do |f|
|
158
|
+
f.read.encode('UTF-8')
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.destroy(name)
|
164
|
+
proc { File.delete(name) if File.exists? name }
|
165
|
+
end
|
166
|
+
end
|
134
167
|
end
|
135
168
|
end
|
136
|
-
|
169
|
+
end
|
170
|
+
end
|