chef 0.9.18 → 0.10.0.beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +0 -3
- data/distro/arch/etc/rc.d/chef-server +0 -4
- data/distro/arch/etc/rc.d/chef-server-webui +0 -4
- data/distro/arch/etc/rc.d/chef-solr +0 -4
- data/distro/arch/etc/rc.d/chef-solr-indexer +0 -4
- data/lib/chef.rb +3 -3
- data/lib/chef/api_client.rb +1 -1
- data/lib/chef/application.rb +11 -1
- data/lib/chef/application/client.rb +18 -22
- data/lib/chef/application/knife.rb +28 -29
- data/lib/chef/application/solo.rb +14 -12
- data/lib/chef/client.rb +112 -54
- data/lib/chef/config.rb +4 -0
- data/lib/chef/cookbook/chefignore.rb +66 -0
- data/lib/chef/cookbook/cookbook_collection.rb +6 -5
- data/lib/chef/cookbook/cookbook_version_loader.rb +151 -0
- data/lib/chef/cookbook/file_system_file_vendor.rb +10 -8
- data/lib/chef/cookbook/metadata.rb +200 -108
- data/lib/chef/cookbook_loader.rb +39 -163
- data/lib/chef/cookbook_uploader.rb +100 -78
- data/lib/chef/cookbook_version.rb +92 -47
- data/lib/chef/cookbook_version_selector.rb +163 -0
- data/lib/chef/couchdb.rb +9 -1
- data/lib/chef/data_bag.rb +1 -1
- data/lib/chef/data_bag_item.rb +1 -1
- data/lib/chef/encrypted_data_bag_item.rb +126 -0
- data/lib/chef/environment.rb +386 -0
- data/lib/chef/exceptions.rb +82 -1
- data/lib/chef/index_queue/amqp_client.rb +15 -12
- data/lib/chef/index_queue/indexable.rb +38 -4
- data/lib/chef/json_compat.rb +3 -3
- data/lib/chef/knife.rb +97 -202
- data/lib/chef/knife/bootstrap.rb +27 -61
- data/lib/chef/knife/bootstrap/archlinux-gems.erb +4 -2
- data/lib/chef/knife/bootstrap/centos5-gems.erb +6 -15
- data/lib/chef/knife/bootstrap/fedora13-gems.erb +3 -4
- data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +2 -2
- data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +6 -5
- data/lib/chef/knife/client_bulk_delete.rb +6 -3
- data/lib/chef/knife/client_create.rb +13 -10
- data/lib/chef/knife/client_delete.rb +10 -7
- data/lib/chef/knife/client_edit.rb +9 -6
- data/lib/chef/knife/client_list.rb +8 -5
- data/lib/chef/knife/client_reregister.rb +9 -6
- data/lib/chef/knife/client_show.rb +9 -6
- data/lib/chef/knife/configure.rb +15 -19
- data/lib/chef/knife/configure_client.rb +4 -4
- data/lib/chef/knife/cookbook_bulk_delete.rb +11 -8
- data/lib/chef/knife/cookbook_create.rb +120 -55
- data/lib/chef/knife/cookbook_delete.rb +18 -12
- data/lib/chef/knife/cookbook_download.rb +10 -6
- data/lib/chef/knife/cookbook_list.rb +15 -6
- data/lib/chef/knife/cookbook_metadata.rb +41 -21
- data/lib/chef/knife/cookbook_metadata_from_file.rb +4 -0
- data/lib/chef/knife/cookbook_show.rb +16 -5
- data/lib/chef/knife/cookbook_site_download.rb +2 -2
- data/lib/chef/knife/cookbook_site_share.rb +18 -13
- data/lib/chef/knife/cookbook_site_unshare.rb +7 -4
- data/lib/chef/knife/cookbook_site_vendor.rb +21 -18
- data/lib/chef/knife/cookbook_test.rb +14 -14
- data/lib/chef/knife/cookbook_upload.rb +91 -40
- data/lib/chef/knife/data_bag_create.rb +41 -6
- data/lib/chef/knife/data_bag_delete.rb +5 -3
- data/lib/chef/knife/data_bag_edit.rb +55 -11
- data/lib/chef/knife/data_bag_from_file.rb +47 -7
- data/lib/chef/knife/data_bag_list.rb +4 -1
- data/lib/chef/knife/data_bag_show.rb +44 -4
- data/lib/chef/knife/environment_create.rb +53 -0
- data/lib/chef/knife/environment_delete.rb +45 -0
- data/lib/chef/knife/environment_edit.rb +45 -0
- data/lib/chef/knife/environment_from_file.rb +39 -0
- data/lib/chef/knife/environment_list.rb +42 -0
- data/lib/chef/knife/environment_show.rb +46 -0
- data/lib/chef/knife/exec.rb +1 -1
- data/lib/chef/knife/index_rebuild.rb +8 -9
- data/lib/chef/knife/node_bulk_delete.rb +9 -6
- data/lib/chef/knife/node_create.rb +9 -6
- data/lib/chef/knife/node_delete.rb +10 -7
- data/lib/chef/knife/node_edit.rb +129 -10
- data/lib/chef/knife/node_from_file.rb +10 -7
- data/lib/chef/knife/node_list.rb +11 -6
- data/lib/chef/knife/node_run_list_add.rb +10 -7
- data/lib/chef/knife/node_run_list_remove.rb +9 -6
- data/lib/chef/knife/node_show.rb +15 -7
- data/lib/chef/knife/recipe_list.rb +4 -3
- data/lib/chef/knife/role_bulk_delete.rb +9 -6
- data/lib/chef/knife/role_create.rb +9 -6
- data/lib/chef/knife/role_delete.rb +10 -7
- data/lib/chef/knife/role_edit.rb +11 -8
- data/lib/chef/knife/role_from_file.rb +10 -7
- data/lib/chef/knife/role_list.rb +8 -5
- data/lib/chef/knife/role_show.rb +11 -8
- data/lib/chef/knife/search.rb +33 -10
- data/lib/chef/knife/ssh.rb +33 -61
- data/lib/chef/knife/status.rb +7 -4
- data/lib/chef/knife/subcommand_loader.rb +101 -0
- data/lib/chef/knife/tag_create.rb +31 -0
- data/lib/chef/knife/tag_delete.rb +31 -0
- data/lib/chef/knife/tag_list.rb +29 -0
- data/lib/chef/knife/ui.rb +229 -0
- data/lib/chef/knife/windows_bootstrap.rb +8 -5
- data/lib/chef/log.rb +5 -59
- data/lib/chef/mash.rb +211 -0
- data/lib/chef/mixins.rb +1 -2
- data/lib/chef/nil_argument.rb +3 -0
- data/lib/chef/node.rb +96 -34
- data/lib/chef/platform.rb +27 -0
- data/lib/chef/provider/cookbook_file.rb +21 -20
- data/lib/chef/provider/deploy/revision.rb +3 -0
- data/lib/chef/provider/file.rb +20 -11
- data/lib/chef/provider/git.rb +26 -26
- data/lib/chef/provider/group/aix.rb +70 -0
- data/lib/chef/provider/group/groupadd.rb +7 -4
- data/lib/chef/provider/group/usermod.rb +1 -1
- data/lib/chef/provider/package.rb +28 -28
- data/lib/chef/provider/package/dpkg.rb +1 -1
- data/lib/chef/provider/package/portage.rb +50 -39
- data/lib/chef/provider/package/rubygems.rb +1 -1
- data/lib/chef/provider/package/zypper.rb +3 -20
- data/lib/chef/provider/remote_directory.rb +0 -2
- data/lib/chef/provider/remote_file.rb +2 -3
- data/lib/chef/provider/service/arch.rb +28 -35
- data/lib/chef/provider/service/simple.rb +1 -1
- data/lib/chef/provider/subversion.rb +22 -22
- data/lib/chef/providers.rb +1 -0
- data/lib/chef/recipe.rb +10 -12
- data/lib/chef/resource.rb +49 -42
- data/lib/chef/resource/gem_package.rb +7 -3
- data/lib/chef/resource/git.rb +5 -5
- data/lib/chef/resource/package.rb +7 -7
- data/lib/chef/resource/scm.rb +2 -1
- data/lib/chef/resource/solaris_package.rb +0 -1
- data/lib/chef/resource/yum_package.rb +0 -1
- data/lib/chef/rest.rb +7 -16
- data/lib/chef/rest/rest_request.rb +0 -16
- data/lib/chef/role.rb +67 -13
- data/lib/chef/run_context.rb +37 -21
- data/lib/chef/run_list.rb +30 -15
- data/lib/chef/run_list/run_list_expansion.rb +41 -20
- data/lib/chef/run_list/run_list_item.rb +20 -6
- data/lib/chef/run_list/versioned_recipe_list.rb +68 -0
- data/lib/chef/runner.rb +7 -15
- data/lib/chef/search/query.rb +12 -7
- data/lib/chef/shef.rb +6 -7
- data/lib/chef/shef/shef_session.rb +40 -35
- data/lib/chef/shell_out.rb +22 -201
- data/lib/chef/shell_out/unix.rb +224 -0
- data/lib/chef/shell_out/windows.rb +95 -0
- data/lib/chef/solr_query.rb +187 -0
- data/lib/chef/solr_query/lucene.treetop +145 -0
- data/lib/chef/solr_query/lucene_nodes.rb +285 -0
- data/lib/chef/solr_query/query_transform.rb +65 -0
- data/lib/chef/solr_query/solr_http_request.rb +118 -0
- data/lib/chef/version.rb +4 -2
- data/lib/chef/version_class.rb +70 -0
- data/lib/chef/version_constraint.rb +116 -0
- metadata +68 -37
- data/lib/chef/cookbook/metadata/version.rb +0 -87
- data/lib/chef/knife/bluebox_images_list.rb +0 -54
- data/lib/chef/knife/bluebox_server_create.rb +0 -157
- data/lib/chef/knife/bluebox_server_delete.rb +0 -63
- data/lib/chef/knife/bluebox_server_list.rb +0 -59
- data/lib/chef/knife/ec2_instance_data.rb +0 -46
- data/lib/chef/knife/ec2_server_create.rb +0 -218
- data/lib/chef/knife/ec2_server_delete.rb +0 -87
- data/lib/chef/knife/ec2_server_list.rb +0 -89
- data/lib/chef/knife/rackspace_server_create.rb +0 -184
- data/lib/chef/knife/rackspace_server_delete.rb +0 -57
- data/lib/chef/knife/rackspace_server_list.rb +0 -59
- data/lib/chef/knife/slicehost_images_list.rb +0 -53
- data/lib/chef/knife/slicehost_server_create.rb +0 -103
- data/lib/chef/knife/slicehost_server_delete.rb +0 -61
- data/lib/chef/knife/slicehost_server_list.rb +0 -64
- data/lib/chef/knife/terremark_server_create.rb +0 -152
- data/lib/chef/knife/terremark_server_delete.rb +0 -87
- data/lib/chef/knife/terremark_server_list.rb +0 -77
- data/lib/chef/mixin/find_preferred_file.rb +0 -92
data/lib/chef/shef.rb
CHANGED
|
@@ -15,15 +15,14 @@
|
|
|
15
15
|
# limitations under the License.
|
|
16
16
|
#
|
|
17
17
|
|
|
18
|
-
require
|
|
19
|
-
require
|
|
20
|
-
require
|
|
21
|
-
require
|
|
18
|
+
require 'singleton'
|
|
19
|
+
require 'pp'
|
|
20
|
+
require 'etc'
|
|
21
|
+
require 'mixlib/cli'
|
|
22
22
|
|
|
23
|
-
require 'chef'
|
|
24
23
|
require 'chef/version'
|
|
25
|
-
require
|
|
26
|
-
require
|
|
24
|
+
require 'chef/client'
|
|
25
|
+
require 'chef/config'
|
|
27
26
|
|
|
28
27
|
require 'chef/shef/shef_session'
|
|
29
28
|
require 'chef/shef/ext'
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
#--
|
|
2
2
|
# Author:: Daniel DeLeo (<dan@kallistec.com>)
|
|
3
|
+
# Author:: Tim Hinderliter (<tim@opscode.com>)
|
|
3
4
|
# Copyright:: Copyright (c) 2009 Daniel DeLeo
|
|
5
|
+
# Copyright:: Copyright (c) 2011 Opscode, Inc.
|
|
4
6
|
# License:: Apache License, Version 2.0
|
|
5
7
|
#
|
|
6
8
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
9
|
# you may not use this file except in compliance with the License.
|
|
8
10
|
# You may obtain a copy of the License at
|
|
9
|
-
#
|
|
11
|
+
#
|
|
10
12
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
-
#
|
|
13
|
+
#
|
|
12
14
|
# Unless required by applicable law or agreed to in writing, software
|
|
13
15
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
16
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
@@ -22,11 +24,12 @@ require 'chef/config'
|
|
|
22
24
|
require 'chef/client'
|
|
23
25
|
require 'chef/cookbook/cookbook_collection'
|
|
24
26
|
require 'chef/cookbook_loader'
|
|
27
|
+
require 'chef/run_list/run_list_expansion'
|
|
25
28
|
|
|
26
29
|
module Shef
|
|
27
30
|
class ShefSession
|
|
28
31
|
include Singleton
|
|
29
|
-
|
|
32
|
+
|
|
30
33
|
def self.session_type(type=nil)
|
|
31
34
|
@session_type = type if type
|
|
32
35
|
@session_type
|
|
@@ -37,13 +40,13 @@ module Shef
|
|
|
37
40
|
def initialize
|
|
38
41
|
@node_built = false
|
|
39
42
|
end
|
|
40
|
-
|
|
43
|
+
|
|
41
44
|
def node_built?
|
|
42
45
|
!!@node_built
|
|
43
46
|
end
|
|
44
|
-
|
|
47
|
+
|
|
45
48
|
def reset!
|
|
46
|
-
loading do
|
|
49
|
+
loading do
|
|
47
50
|
rebuild_node
|
|
48
51
|
@node = client.node
|
|
49
52
|
shorten_node_inspect
|
|
@@ -55,12 +58,12 @@ module Shef
|
|
|
55
58
|
@node_built = true
|
|
56
59
|
end
|
|
57
60
|
end
|
|
58
|
-
|
|
61
|
+
|
|
59
62
|
def node_attributes=(attrs)
|
|
60
63
|
@node_attributes = attrs
|
|
61
64
|
@node.consume_attributes(@node_attributes)
|
|
62
65
|
end
|
|
63
|
-
|
|
66
|
+
|
|
64
67
|
def resource_collection
|
|
65
68
|
run_context.resource_collection
|
|
66
69
|
end
|
|
@@ -68,25 +71,25 @@ module Shef
|
|
|
68
71
|
def run_context
|
|
69
72
|
@run_context ||= rebuild_context
|
|
70
73
|
end
|
|
71
|
-
|
|
74
|
+
|
|
72
75
|
def definitions
|
|
73
76
|
nil
|
|
74
77
|
end
|
|
75
|
-
|
|
78
|
+
|
|
76
79
|
def cookbook_loader
|
|
77
80
|
nil
|
|
78
81
|
end
|
|
79
|
-
|
|
82
|
+
|
|
80
83
|
def save_node
|
|
81
84
|
raise "Not Supported! #{self.class.name} doesn't support #save_node, maybe you need to run shef in client mode?"
|
|
82
85
|
end
|
|
83
|
-
|
|
86
|
+
|
|
84
87
|
def rebuild_context
|
|
85
88
|
raise "Not Implemented! :rebuild_collection should be implemented by subclasses"
|
|
86
89
|
end
|
|
87
|
-
|
|
90
|
+
|
|
88
91
|
private
|
|
89
|
-
|
|
92
|
+
|
|
90
93
|
def loading
|
|
91
94
|
show_loading_progress
|
|
92
95
|
begin
|
|
@@ -98,7 +101,7 @@ module Shef
|
|
|
98
101
|
loading_complete(true)
|
|
99
102
|
end
|
|
100
103
|
end
|
|
101
|
-
|
|
104
|
+
|
|
102
105
|
def show_loading_progress
|
|
103
106
|
print "Loading"
|
|
104
107
|
@loading = true
|
|
@@ -109,61 +112,63 @@ module Shef
|
|
|
109
112
|
end
|
|
110
113
|
end
|
|
111
114
|
end
|
|
112
|
-
|
|
115
|
+
|
|
113
116
|
def loading_complete(success)
|
|
114
117
|
@loading = false
|
|
115
118
|
@dot_printer.join
|
|
116
119
|
msg = success ? "done.\n\n" : "epic fail!\n\n"
|
|
117
120
|
print msg
|
|
118
121
|
end
|
|
119
|
-
|
|
122
|
+
|
|
120
123
|
def shorten_node_inspect
|
|
121
124
|
def @node.inspect
|
|
122
125
|
"<Chef::Node:0x#{self.object_id.to_s(16)} @name=\"#{self.name}\">"
|
|
123
126
|
end
|
|
124
127
|
end
|
|
125
|
-
|
|
128
|
+
|
|
126
129
|
def rebuild_node
|
|
127
130
|
raise "Not Implemented! :rebuild_node should be implemented by subclasses"
|
|
128
131
|
end
|
|
129
|
-
|
|
132
|
+
|
|
130
133
|
end
|
|
131
|
-
|
|
134
|
+
|
|
132
135
|
class StandAloneSession < ShefSession
|
|
133
136
|
|
|
134
137
|
session_type :standalone
|
|
135
|
-
|
|
138
|
+
|
|
136
139
|
def rebuild_context
|
|
137
140
|
@run_context = Chef::RunContext.new(@node, {}) # no recipes
|
|
141
|
+
@run_context.load(Chef::RunList::RunListExpansionFromDisk.new("_default", [])) # empty recipe list
|
|
138
142
|
end
|
|
139
|
-
|
|
143
|
+
|
|
140
144
|
private
|
|
141
|
-
|
|
145
|
+
|
|
142
146
|
def rebuild_node
|
|
143
147
|
Chef::Config[:solo] = true
|
|
144
148
|
@client = Chef::Client.new
|
|
145
149
|
@client.run_ohai
|
|
146
150
|
@client.build_node
|
|
147
151
|
end
|
|
148
|
-
|
|
152
|
+
|
|
149
153
|
end
|
|
150
|
-
|
|
154
|
+
|
|
151
155
|
class SoloSession < ShefSession
|
|
152
156
|
|
|
153
157
|
session_type :solo
|
|
154
|
-
|
|
158
|
+
|
|
155
159
|
def definitions
|
|
156
160
|
@run_context.definitions
|
|
157
161
|
end
|
|
158
|
-
|
|
162
|
+
|
|
159
163
|
def rebuild_context
|
|
160
|
-
Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) }
|
|
161
|
-
@run_context = Chef::RunContext.new(@node, Chef::CookbookCollection.new(Chef::CookbookLoader.new))
|
|
164
|
+
Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, Chef::Config[:cookbook_path]) }
|
|
165
|
+
@run_context = Chef::RunContext.new(@node, Chef::CookbookCollection.new(Chef::CookbookLoader.new(Chef::Config[:cookbook_path])))
|
|
166
|
+
@run_context.load(Chef::RunList::RunListExpansionFromDisk.new("_default", []))
|
|
162
167
|
run_status.run_context = run_context
|
|
163
168
|
end
|
|
164
|
-
|
|
169
|
+
|
|
165
170
|
private
|
|
166
|
-
|
|
171
|
+
|
|
167
172
|
def rebuild_node
|
|
168
173
|
# Tell the client we're chef solo so it won't try to contact the server
|
|
169
174
|
Chef::Config[:solo] = true
|
|
@@ -171,13 +176,13 @@ module Shef
|
|
|
171
176
|
@client.run_ohai
|
|
172
177
|
@client.build_node
|
|
173
178
|
end
|
|
174
|
-
|
|
179
|
+
|
|
175
180
|
end
|
|
176
|
-
|
|
181
|
+
|
|
177
182
|
class ClientSession < SoloSession
|
|
178
183
|
|
|
179
184
|
session_type :client
|
|
180
|
-
|
|
185
|
+
|
|
181
186
|
def save_node
|
|
182
187
|
@client.save_node
|
|
183
188
|
end
|
|
@@ -187,6 +192,7 @@ module Shef
|
|
|
187
192
|
Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::RemoteFileVendor.new(manifest, Chef::REST.new(Chef::Config[:server_url])) }
|
|
188
193
|
cookbook_hash = @client.sync_cookbooks
|
|
189
194
|
@run_context = Chef::RunContext.new(node, Chef::CookbookCollection.new(cookbook_hash))
|
|
195
|
+
@run_context.load(Chef::RunList::RunListExpansionFromAPI.new("_default", []))
|
|
190
196
|
@run_status.run_context = run_context
|
|
191
197
|
end
|
|
192
198
|
|
|
@@ -228,7 +234,6 @@ module Shef
|
|
|
228
234
|
ohai_data = @ohai.data.merge(@node.automatic_attrs)
|
|
229
235
|
|
|
230
236
|
@node.consume_external_attrs(ohai_data,nil)
|
|
231
|
-
@node.reset_defaults_and_overrides
|
|
232
237
|
|
|
233
238
|
@node
|
|
234
239
|
end
|
data/lib/chef/shell_out.rb
CHANGED
|
@@ -21,6 +21,7 @@ require 'tmpdir'
|
|
|
21
21
|
require 'chef/log'
|
|
22
22
|
require 'fcntl'
|
|
23
23
|
require 'chef/exceptions'
|
|
24
|
+
require 'chef/shell_out/unix'
|
|
24
25
|
|
|
25
26
|
class Chef
|
|
26
27
|
|
|
@@ -42,7 +43,20 @@ class Chef
|
|
|
42
43
|
DEFAULT_READ_TIMEOUT = 60
|
|
43
44
|
DEFAULT_ENVIRONMENT = {'LC_ALL' => 'C'}
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
if RUBY_PLATFORM =~ /mswin|mingw32|windows/
|
|
47
|
+
require 'chef/shell_out/windows'
|
|
48
|
+
include ShellOut::Windows
|
|
49
|
+
else
|
|
50
|
+
require 'chef/shell_out/unix'
|
|
51
|
+
include ShellOut::Unix
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
attr_accessor :user
|
|
55
|
+
attr_accessor :group
|
|
56
|
+
attr_accessor :cwd
|
|
57
|
+
attr_accessor :valid_exit_codes
|
|
58
|
+
attr_accessor :live_stream
|
|
59
|
+
|
|
46
60
|
attr_reader :command, :umask, :environment
|
|
47
61
|
attr_writer :timeout
|
|
48
62
|
attr_reader :execution_time
|
|
@@ -96,6 +110,7 @@ class Chef
|
|
|
96
110
|
# cmd.run_command # etc.
|
|
97
111
|
def initialize(*command_args)
|
|
98
112
|
@stdout, @stderr = '', ''
|
|
113
|
+
@live_stream = nil
|
|
99
114
|
@environment = DEFAULT_ENVIRONMENT
|
|
100
115
|
@cwd = nil
|
|
101
116
|
@valid_exit_codes = [0]
|
|
@@ -154,56 +169,9 @@ class Chef
|
|
|
154
169
|
# * Chef::Exceptions::CommandTimeout when the command does not complete
|
|
155
170
|
# within +timeout+ seconds (default: 60s)
|
|
156
171
|
def run_command
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
configure_parent_process_file_descriptors
|
|
161
|
-
propagate_pre_exec_failure
|
|
162
|
-
|
|
163
|
-
@result = nil
|
|
164
|
-
@execution_time = 0
|
|
165
|
-
|
|
166
|
-
# Ruby 1.8.7 and 1.8.6 from mid 2009 try to allocate objects during GC
|
|
167
|
-
# when calling IO.select and IO#read. Some OS Vendors are not interested
|
|
168
|
-
# in updating their ruby packages (Apple, *cough*) and we *have to*
|
|
169
|
-
# make it work. So I give you this epic hack:
|
|
170
|
-
GC.disable
|
|
171
|
-
until @status
|
|
172
|
-
ready = IO.select(open_pipes, nil, nil, READ_WAIT_TIME)
|
|
173
|
-
unless ready
|
|
174
|
-
@execution_time += READ_WAIT_TIME
|
|
175
|
-
if @execution_time >= timeout && !@result
|
|
176
|
-
raise Chef::Exceptions::CommandTimeout, "command timed out:\n#{format_for_exception}"
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
if ready && ready.first.include?(child_stdout)
|
|
181
|
-
read_stdout_to_buffer
|
|
182
|
-
end
|
|
183
|
-
if ready && ready.first.include?(child_stderr)
|
|
184
|
-
read_stderr_to_buffer
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
unless @status
|
|
188
|
-
# make one more pass to get the last of the output after the
|
|
189
|
-
# child process dies
|
|
190
|
-
if results = Process.waitpid2(@child_pid, Process::WNOHANG)
|
|
191
|
-
@status = results.last
|
|
192
|
-
redo
|
|
193
|
-
end
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
self
|
|
197
|
-
rescue Exception
|
|
198
|
-
# do our best to kill zombies
|
|
199
|
-
Process.waitpid2(@child_pid, Process::WNOHANG) rescue nil
|
|
200
|
-
raise
|
|
201
|
-
ensure
|
|
202
|
-
# no matter what happens, turn the GC back on, and hope whatever busted
|
|
203
|
-
# version of ruby we're on doesn't allocate some objects during the next
|
|
204
|
-
# GC run.
|
|
205
|
-
GC.enable
|
|
206
|
-
close_all_pipes
|
|
172
|
+
# Implemented by unix/windows backend module, we just want to define it
|
|
173
|
+
# here for documentation purposes
|
|
174
|
+
super
|
|
207
175
|
end
|
|
208
176
|
|
|
209
177
|
# Checks the +exitstatus+ against the set of +valid_exit_codes+. If
|
|
@@ -255,164 +223,17 @@ class Chef
|
|
|
255
223
|
self.timeout = setting
|
|
256
224
|
when 'returns'
|
|
257
225
|
self.valid_exit_codes = Array(setting)
|
|
226
|
+
when 'live_stream'
|
|
227
|
+
self.live_stream = setting
|
|
258
228
|
when 'environment', 'env'
|
|
259
229
|
# passing :environment => nil means don't set any new ENV vars
|
|
260
|
-
setting.nil? ?
|
|
230
|
+
@environment = setting.nil? ? {} : @environment.dup.merge!(setting)
|
|
261
231
|
else
|
|
262
232
|
raise Chef::Exceptions::InvalidCommandOption, "option '#{option.inspect}' is not a valid option for #{self.class.name}"
|
|
263
233
|
end
|
|
264
234
|
end
|
|
265
235
|
end
|
|
266
236
|
|
|
267
|
-
def set_user
|
|
268
|
-
if user
|
|
269
|
-
Process.euid = uid
|
|
270
|
-
Process.uid = uid
|
|
271
|
-
end
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
def set_group
|
|
275
|
-
if group
|
|
276
|
-
Process.egid = gid
|
|
277
|
-
Process.gid = gid
|
|
278
|
-
end
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
def set_environment
|
|
282
|
-
environment.each do |env_var,value|
|
|
283
|
-
ENV[env_var] = value
|
|
284
|
-
end
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
def set_umask
|
|
288
|
-
File.umask(umask) if umask
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
def set_cwd
|
|
292
|
-
Dir.chdir(cwd) if cwd
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
def initialize_ipc
|
|
296
|
-
@stdout_pipe, @stderr_pipe, @process_status_pipe = IO.pipe, IO.pipe, IO.pipe
|
|
297
|
-
@process_status_pipe.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
def child_stdout
|
|
301
|
-
@stdout_pipe[0]
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
def child_stderr
|
|
305
|
-
@stderr_pipe[0]
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
def child_process_status
|
|
309
|
-
@process_status_pipe[0]
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
def close_all_pipes
|
|
313
|
-
child_stdout.close unless child_stdout.closed?
|
|
314
|
-
child_stderr.close unless child_stderr.closed?
|
|
315
|
-
child_process_status.close unless child_process_status.closed?
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
# replace stdout, and stderr with pipes to the parent, and close the
|
|
319
|
-
# reader side of the error marshaling side channel. Close STDIN so when we
|
|
320
|
-
# exec, the new program will know it's never getting input ever.
|
|
321
|
-
def configure_subprocess_file_descriptors
|
|
322
|
-
process_status_pipe.first.close
|
|
323
|
-
|
|
324
|
-
# HACK: for some reason, just STDIN.close isn't good enough when running
|
|
325
|
-
# under ruby 1.9.2, so make it good enough:
|
|
326
|
-
stdin_reader, stdin_writer = IO.pipe
|
|
327
|
-
stdin_writer.close
|
|
328
|
-
STDIN.reopen stdin_reader
|
|
329
|
-
stdin_reader.close
|
|
330
|
-
|
|
331
|
-
stdout_pipe.first.close
|
|
332
|
-
STDOUT.reopen stdout_pipe.last
|
|
333
|
-
stdout_pipe.last.close
|
|
334
|
-
|
|
335
|
-
stderr_pipe.first.close
|
|
336
|
-
STDERR.reopen stderr_pipe.last
|
|
337
|
-
stderr_pipe.last.close
|
|
338
|
-
|
|
339
|
-
STDOUT.sync = STDERR.sync = true
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
def configure_parent_process_file_descriptors
|
|
343
|
-
# Close the sides of the pipes we don't care about
|
|
344
|
-
stdout_pipe.last.close
|
|
345
|
-
stderr_pipe.last.close
|
|
346
|
-
process_status_pipe.last.close
|
|
347
|
-
# Get output as it happens rather than buffered
|
|
348
|
-
child_stdout.sync = true
|
|
349
|
-
child_stderr.sync = true
|
|
350
|
-
|
|
351
|
-
true
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
# Some patch levels of ruby in wide use (in particular the ruby 1.8.6 on OSX)
|
|
355
|
-
# segfault when you IO.select a pipe that's reached eof. Weak sauce.
|
|
356
|
-
def open_pipes
|
|
357
|
-
@open_pipes ||= [child_stdout, child_stderr]
|
|
358
|
-
end
|
|
359
|
-
|
|
360
|
-
def read_stdout_to_buffer
|
|
361
|
-
while chunk = child_stdout.read_nonblock(READ_SIZE)
|
|
362
|
-
@stdout << chunk
|
|
363
|
-
end
|
|
364
|
-
rescue Errno::EAGAIN
|
|
365
|
-
rescue EOFError
|
|
366
|
-
open_pipes.delete_at(0)
|
|
367
|
-
end
|
|
368
|
-
|
|
369
|
-
def read_stderr_to_buffer
|
|
370
|
-
while chunk = child_stderr.read_nonblock(READ_SIZE)
|
|
371
|
-
@stderr << chunk
|
|
372
|
-
end
|
|
373
|
-
rescue Errno::EAGAIN
|
|
374
|
-
rescue EOFError
|
|
375
|
-
open_pipes.delete_at(1)
|
|
376
|
-
end
|
|
377
|
-
|
|
378
|
-
def fork_subprocess
|
|
379
|
-
initialize_ipc
|
|
380
|
-
|
|
381
|
-
fork do
|
|
382
|
-
configure_subprocess_file_descriptors
|
|
383
|
-
|
|
384
|
-
set_user
|
|
385
|
-
set_group
|
|
386
|
-
set_environment
|
|
387
|
-
set_umask
|
|
388
|
-
set_cwd
|
|
389
|
-
|
|
390
|
-
begin
|
|
391
|
-
command.kind_of?(Array) ? exec(*command) : exec(command)
|
|
392
|
-
|
|
393
|
-
raise 'forty-two' # Should never get here
|
|
394
|
-
rescue Exception => e
|
|
395
|
-
Marshal.dump(e, process_status_pipe.last)
|
|
396
|
-
process_status_pipe.last.flush
|
|
397
|
-
end
|
|
398
|
-
process_status_pipe.last.close unless (process_status_pipe.last.closed?)
|
|
399
|
-
exit!
|
|
400
|
-
end
|
|
401
|
-
end
|
|
402
|
-
|
|
403
|
-
# Attempt to get a Marshaled error from the side-channel.
|
|
404
|
-
# If it's there, un-marshal it and raise. If it's not there,
|
|
405
|
-
# assume everything went well.
|
|
406
|
-
def propagate_pre_exec_failure
|
|
407
|
-
begin
|
|
408
|
-
e = Marshal.load child_process_status
|
|
409
|
-
raise(Exception === e ? e : "unknown failure: #{e.inspect}")
|
|
410
|
-
rescue EOFError # If we get an EOF error, then the exec was successful
|
|
411
|
-
true
|
|
412
|
-
ensure
|
|
413
|
-
child_process_status.close
|
|
414
|
-
end
|
|
415
|
-
end
|
|
416
237
|
|
|
417
238
|
end
|
|
418
239
|
end
|