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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#
# Author:: Adam Jacob (<adam@chef.io>)
# Copyright:: Copyright 2008-2016, 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"
require "chef/mixin/user_identity"
class Chef
class Provider
class Execute < Chef::Provider
extend Forwardable
include Chef::Mixin::UserIdentity
provides :execute
def_delegators :@new_resource, :command, :returns, :environment, :user, :domain, :password, :group, :cwd, :umask, :creates
def load_current_resource
current_resource = Chef::Resource::Execute.new(new_resource.name)
current_resource
end
def whyrun_supported?
true
end
def define_resource_requirements
# @todo: this should change to raise in some appropriate major version bump.
requirements.assert(:all_actions) do |a|
a.assertion { validate_identity(new_resource.user, new_resource.password, new_resource.domain) }
end
if creates && creates_relative? && !cwd
Chef::Log.warn "Providing a relative path for the creates attribute without the cwd is deprecated and will be changed to fail in the future (CHEF-3819)"
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
# parse username if it's in the following format: domain/username or username@domain
identity = qualify_user(new_resource.user, new_resource.domain)
new_resource.user identity[:user]
new_resource.domain identity[:domain]
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!(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
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
|