1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#
# Author:: Adam Jacob (<adam@chef.io>)
# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require "chef/log"
require "chef/provider"
require "forwardable"
class Chef
class Provider
class Execute < Chef::Provider
extend Forwardable
provides :execute
def_delegators :new_resource, :command, :returns, :environment, :user, :domain, :password, :group, :cwd, :umask, :creates, :elevated
def load_current_resource
current_resource = Chef::Resource::Execute.new(new_resource.name)
current_resource
end
def define_resource_requirements
if creates && creates_relative? && !cwd
# FIXME? move this onto the resource?
raise Chef::Exceptions::Execute, "Please either specify a full path for the creates attribute, or specify a cwd property to the #{new_resource} resource"
end
end
def timeout
# original implementation did not specify a timeout, but ShellOut
# *always* times out. So, set a very long default timeout
new_resource.timeout || 3600
end
def action_run
if creates && sentinel_file.exist?
Chef::Log.debug("#{new_resource} sentinel file #{sentinel_file} exists - nothing to do")
return false
end
converge_by("execute #{description}") do
begin
shell_out_with_systems_locale!(command, opts)
rescue Mixlib::ShellOut::ShellCommandFailed
if sensitive?
raise Mixlib::ShellOut::ShellCommandFailed,
"Command execution failed. STDOUT/STDERR suppressed for sensitive resource"
else
raise
end
end
Chef::Log.info("#{new_resource} ran successfully")
end
end
private
def sensitive?
!!new_resource.sensitive
end
def live_stream?
Chef::Config[:stream_execute_output] || !!new_resource.live_stream
end
def stream_to_stdout?
STDOUT.tty? && !Chef::Config[:daemon]
end
def opts
opts = {}
opts[:timeout] = timeout
opts[:returns] = returns if returns
opts[:environment] = environment if environment
opts[:user] = user if user
opts[:domain] = domain if domain
opts[:password] = password if password
opts[:group] = group if group
opts[:cwd] = cwd if cwd
opts[:umask] = umask if umask
opts[:log_level] = :info
opts[:log_tag] = new_resource.to_s
if (Chef::Log.info? || live_stream?) && !sensitive?
if run_context.events.formatter?
opts[:live_stream] = Chef::EventDispatch::EventsOutputStream.new(run_context.events, :name => :execute)
elsif stream_to_stdout?
opts[:live_stream] = STDOUT
end
end
opts[:elevated] = elevated if elevated
opts
end
def description
sensitive? ? "sensitive resource" : command
end
def creates_relative?
Pathname(creates).relative?
end
def sentinel_file
Pathname.new(Chef::Util::PathHelper.cleanpath(
( cwd && creates_relative? ) ? ::File.join(cwd, creates) : creates
))
end
end
end
end
|