runa-chef 0.8.0.1

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.
Files changed (216) hide show
  1. data/LICENSE +201 -0
  2. data/README.rdoc +136 -0
  3. data/bin/chef-client +26 -0
  4. data/bin/chef-solo +26 -0
  5. data/bin/knife +27 -0
  6. data/bin/shef +45 -0
  7. data/distro/README +2 -0
  8. data/distro/common/man/man1/chef-indexer.1 +42 -0
  9. data/distro/common/man/man1/chef-server.1 +108 -0
  10. data/distro/common/man/man8/chef-client.8 +61 -0
  11. data/distro/common/man/man8/chef-solo.8 +58 -0
  12. data/distro/common/man/man8/knife.8 +359 -0
  13. data/distro/debian/etc/init.d/chef-client +175 -0
  14. data/distro/debian/etc/init.d/chef-indexer +175 -0
  15. data/distro/debian/etc/init.d/chef-server +120 -0
  16. data/distro/redhat/etc/init.d/chef-client +78 -0
  17. data/distro/redhat/etc/init.d/chef-indexer +76 -0
  18. data/distro/redhat/etc/init.d/chef-server +78 -0
  19. data/distro/redhat/etc/sysconfig/chef-client +10 -0
  20. data/distro/redhat/etc/sysconfig/chef-indexer +8 -0
  21. data/distro/redhat/etc/sysconfig/chef-server +10 -0
  22. data/distro/suse/etc/init.d/chef-client +121 -0
  23. data/lib/chef.rb +49 -0
  24. data/lib/chef/api_client.rb +269 -0
  25. data/lib/chef/application.rb +98 -0
  26. data/lib/chef/application/agent.rb +18 -0
  27. data/lib/chef/application/client.rb +214 -0
  28. data/lib/chef/application/knife.rb +138 -0
  29. data/lib/chef/application/server.rb +19 -0
  30. data/lib/chef/application/solo.rb +214 -0
  31. data/lib/chef/cache.rb +61 -0
  32. data/lib/chef/cache/checksum.rb +70 -0
  33. data/lib/chef/certificate.rb +154 -0
  34. data/lib/chef/client.rb +323 -0
  35. data/lib/chef/compile.rb +158 -0
  36. data/lib/chef/config.rb +195 -0
  37. data/lib/chef/cookbook.rb +198 -0
  38. data/lib/chef/cookbook/metadata.rb +487 -0
  39. data/lib/chef/cookbook/metadata/version.rb +87 -0
  40. data/lib/chef/cookbook_loader.rb +180 -0
  41. data/lib/chef/couchdb.rb +273 -0
  42. data/lib/chef/daemon.rb +170 -0
  43. data/lib/chef/data_bag.rb +216 -0
  44. data/lib/chef/data_bag_item.rb +227 -0
  45. data/lib/chef/exceptions.rb +39 -0
  46. data/lib/chef/file_cache.rb +205 -0
  47. data/lib/chef/knife.rb +300 -0
  48. data/lib/chef/knife/client_bulk_delete.rb +41 -0
  49. data/lib/chef/knife/client_create.rb +55 -0
  50. data/lib/chef/knife/client_delete.rb +37 -0
  51. data/lib/chef/knife/client_edit.rb +37 -0
  52. data/lib/chef/knife/client_list.rb +40 -0
  53. data/lib/chef/knife/client_reregister.rb +48 -0
  54. data/lib/chef/knife/client_show.rb +42 -0
  55. data/lib/chef/knife/configure.rb +84 -0
  56. data/lib/chef/knife/cookbook_bulk_delete.rb +47 -0
  57. data/lib/chef/knife/cookbook_delete.rb +41 -0
  58. data/lib/chef/knife/cookbook_download.rb +57 -0
  59. data/lib/chef/knife/cookbook_list.rb +41 -0
  60. data/lib/chef/knife/cookbook_metadata.rb +87 -0
  61. data/lib/chef/knife/cookbook_show.rb +75 -0
  62. data/lib/chef/knife/cookbook_upload.rb +173 -0
  63. data/lib/chef/knife/data_bag_create.rb +43 -0
  64. data/lib/chef/knife/data_bag_delete.rb +43 -0
  65. data/lib/chef/knife/data_bag_edit.rb +49 -0
  66. data/lib/chef/knife/data_bag_list.rb +42 -0
  67. data/lib/chef/knife/data_bag_show.rb +40 -0
  68. data/lib/chef/knife/ec2_instance_data.rb +46 -0
  69. data/lib/chef/knife/node_bulk_delete.rb +44 -0
  70. data/lib/chef/knife/node_create.rb +39 -0
  71. data/lib/chef/knife/node_delete.rb +36 -0
  72. data/lib/chef/knife/node_edit.rb +36 -0
  73. data/lib/chef/knife/node_from_file.rb +42 -0
  74. data/lib/chef/knife/node_list.rb +41 -0
  75. data/lib/chef/knife/node_run_list_add.rb +64 -0
  76. data/lib/chef/knife/node_run_list_remove.rb +45 -0
  77. data/lib/chef/knife/node_show.rb +46 -0
  78. data/lib/chef/knife/role_bulk_delete.rb +45 -0
  79. data/lib/chef/knife/role_create.rb +44 -0
  80. data/lib/chef/knife/role_delete.rb +36 -0
  81. data/lib/chef/knife/role_edit.rb +37 -0
  82. data/lib/chef/knife/role_from_file.rb +46 -0
  83. data/lib/chef/knife/role_list.rb +40 -0
  84. data/lib/chef/knife/role_show.rb +43 -0
  85. data/lib/chef/knife/search.rb +94 -0
  86. data/lib/chef/log.rb +39 -0
  87. data/lib/chef/mixin/check_helper.rb +31 -0
  88. data/lib/chef/mixin/checksum.rb +32 -0
  89. data/lib/chef/mixin/command.rb +390 -0
  90. data/lib/chef/mixin/convert_to_class_name.rb +57 -0
  91. data/lib/chef/mixin/create_path.rb +56 -0
  92. data/lib/chef/mixin/deep_merge.rb +33 -0
  93. data/lib/chef/mixin/find_preferred_file.rb +92 -0
  94. data/lib/chef/mixin/from_file.rb +50 -0
  95. data/lib/chef/mixin/generate_url.rb +58 -0
  96. data/lib/chef/mixin/language.rb +107 -0
  97. data/lib/chef/mixin/language_include_attribute.rb +56 -0
  98. data/lib/chef/mixin/language_include_recipe.rb +53 -0
  99. data/lib/chef/mixin/params_validate.rb +197 -0
  100. data/lib/chef/mixin/recipe_definition_dsl_core.rb +79 -0
  101. data/lib/chef/mixin/template.rb +94 -0
  102. data/lib/chef/nanite.rb +100 -0
  103. data/lib/chef/node.rb +463 -0
  104. data/lib/chef/node/attribute.rb +412 -0
  105. data/lib/chef/openid_registration.rb +181 -0
  106. data/lib/chef/platform.rb +268 -0
  107. data/lib/chef/provider.rb +101 -0
  108. data/lib/chef/provider/breakpoint.rb +36 -0
  109. data/lib/chef/provider/cron.rb +184 -0
  110. data/lib/chef/provider/deploy.rb +314 -0
  111. data/lib/chef/provider/deploy/revision.rb +70 -0
  112. data/lib/chef/provider/deploy/timestamped.rb +33 -0
  113. data/lib/chef/provider/directory.rb +72 -0
  114. data/lib/chef/provider/erl_call.rb +72 -0
  115. data/lib/chef/provider/execute.rb +58 -0
  116. data/lib/chef/provider/file.rb +195 -0
  117. data/lib/chef/provider/git.rb +203 -0
  118. data/lib/chef/provider/group.rb +120 -0
  119. data/lib/chef/provider/group/dscl.rb +128 -0
  120. data/lib/chef/provider/group/gpasswd.rb +50 -0
  121. data/lib/chef/provider/group/groupadd.rb +78 -0
  122. data/lib/chef/provider/group/pw.rb +88 -0
  123. data/lib/chef/provider/group/usermod.rb +57 -0
  124. data/lib/chef/provider/http_request.rb +106 -0
  125. data/lib/chef/provider/ifconfig.rb +131 -0
  126. data/lib/chef/provider/link.rb +157 -0
  127. data/lib/chef/provider/mdadm.rb +88 -0
  128. data/lib/chef/provider/mount.rb +117 -0
  129. data/lib/chef/provider/mount/mount.rb +208 -0
  130. data/lib/chef/provider/package.rb +160 -0
  131. data/lib/chef/provider/package/apt.rb +110 -0
  132. data/lib/chef/provider/package/dpkg.rb +109 -0
  133. data/lib/chef/provider/package/easy_install.rb +106 -0
  134. data/lib/chef/provider/package/freebsd.rb +153 -0
  135. data/lib/chef/provider/package/macports.rb +105 -0
  136. data/lib/chef/provider/package/portage.rb +124 -0
  137. data/lib/chef/provider/package/rpm.rb +99 -0
  138. data/lib/chef/provider/package/rubygems.rb +136 -0
  139. data/lib/chef/provider/package/yum-dump.py +125 -0
  140. data/lib/chef/provider/package/yum.rb +175 -0
  141. data/lib/chef/provider/package/zypper.rb +132 -0
  142. data/lib/chef/provider/remote_directory.rb +126 -0
  143. data/lib/chef/provider/remote_file.rb +141 -0
  144. data/lib/chef/provider/route.rb +118 -0
  145. data/lib/chef/provider/ruby_block.rb +33 -0
  146. data/lib/chef/provider/script.rb +42 -0
  147. data/lib/chef/provider/service.rb +135 -0
  148. data/lib/chef/provider/service/debian.rb +64 -0
  149. data/lib/chef/provider/service/freebsd.rb +156 -0
  150. data/lib/chef/provider/service/gentoo.rb +54 -0
  151. data/lib/chef/provider/service/init.rb +71 -0
  152. data/lib/chef/provider/service/redhat.rb +62 -0
  153. data/lib/chef/provider/service/simple.rb +114 -0
  154. data/lib/chef/provider/subversion.rb +156 -0
  155. data/lib/chef/provider/template.rb +175 -0
  156. data/lib/chef/provider/user.rb +170 -0
  157. data/lib/chef/provider/user/dscl.rb +280 -0
  158. data/lib/chef/provider/user/pw.rb +113 -0
  159. data/lib/chef/provider/user/useradd.rb +108 -0
  160. data/lib/chef/recipe.rb +105 -0
  161. data/lib/chef/resource.rb +380 -0
  162. data/lib/chef/resource/apt_package.rb +34 -0
  163. data/lib/chef/resource/bash.rb +33 -0
  164. data/lib/chef/resource/breakpoint.rb +35 -0
  165. data/lib/chef/resource/cron.rb +179 -0
  166. data/lib/chef/resource/csh.rb +33 -0
  167. data/lib/chef/resource/deploy.rb +359 -0
  168. data/lib/chef/resource/deploy_revision.rb +35 -0
  169. data/lib/chef/resource/directory.rb +76 -0
  170. data/lib/chef/resource/dpkg_package.rb +34 -0
  171. data/lib/chef/resource/easy_install_package.rb +41 -0
  172. data/lib/chef/resource/erl_call.rb +83 -0
  173. data/lib/chef/resource/execute.rb +127 -0
  174. data/lib/chef/resource/file.rb +84 -0
  175. data/lib/chef/resource/gem_package.rb +41 -0
  176. data/lib/chef/resource/git.rb +36 -0
  177. data/lib/chef/resource/group.rb +70 -0
  178. data/lib/chef/resource/http_request.rb +52 -0
  179. data/lib/chef/resource/ifconfig.rb +134 -0
  180. data/lib/chef/resource/link.rb +78 -0
  181. data/lib/chef/resource/macports_package.rb +29 -0
  182. data/lib/chef/resource/mdadm.rb +82 -0
  183. data/lib/chef/resource/mount.rb +135 -0
  184. data/lib/chef/resource/package.rb +80 -0
  185. data/lib/chef/resource/perl.rb +33 -0
  186. data/lib/chef/resource/portage_package.rb +33 -0
  187. data/lib/chef/resource/python.rb +33 -0
  188. data/lib/chef/resource/remote_directory.rb +91 -0
  189. data/lib/chef/resource/remote_file.rb +60 -0
  190. data/lib/chef/resource/route.rb +135 -0
  191. data/lib/chef/resource/ruby.rb +33 -0
  192. data/lib/chef/resource/ruby_block.rb +39 -0
  193. data/lib/chef/resource/scm.rb +137 -0
  194. data/lib/chef/resource/script.rb +51 -0
  195. data/lib/chef/resource/service.rb +134 -0
  196. data/lib/chef/resource/subversion.rb +34 -0
  197. data/lib/chef/resource/template.rb +60 -0
  198. data/lib/chef/resource/timestamped_deploy.rb +31 -0
  199. data/lib/chef/resource/user.rb +101 -0
  200. data/lib/chef/resource_collection.rb +212 -0
  201. data/lib/chef/resource_collection/stepable_iterator.rb +124 -0
  202. data/lib/chef/resource_definition.rb +67 -0
  203. data/lib/chef/rest.rb +298 -0
  204. data/lib/chef/role.rb +301 -0
  205. data/lib/chef/run_list.rb +164 -0
  206. data/lib/chef/runner.rb +130 -0
  207. data/lib/chef/search/query.rb +71 -0
  208. data/lib/chef/shef.rb +220 -0
  209. data/lib/chef/shef/ext.rb +297 -0
  210. data/lib/chef/shef/shef_session.rb +175 -0
  211. data/lib/chef/streaming_cookbook_uploader.rb +185 -0
  212. data/lib/chef/tasks/chef_repo.rake +245 -0
  213. data/lib/chef/util/file_edit.rb +125 -0
  214. data/lib/chef/util/fileedit.rb +121 -0
  215. data/lib/chef/webui_user.rb +231 -0
  216. metadata +398 -0
@@ -0,0 +1,94 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Copyright:: Copyright (c) 2009 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
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/knife'
20
+ require 'chef/data_bag_item'
21
+
22
+ class Chef
23
+ class Knife
24
+ class Search < Knife
25
+
26
+ banner "Sub-Command: search INDEX QUERY (options)"
27
+
28
+ option :sort,
29
+ :short => "-o SORT",
30
+ :long => "--sort SORT",
31
+ :description => "The order to sort the results in",
32
+ :default => nil
33
+
34
+ option :start,
35
+ :short => "-b ROW",
36
+ :long => "--start ROW",
37
+ :description => "The row to start returning results at",
38
+ :default => 0,
39
+ :proc => lambda { |i| i.to_i }
40
+
41
+ option :rows,
42
+ :short => "-R INT",
43
+ :long => "--rows INT",
44
+ :description => "The number of rows to return",
45
+ :default => 20,
46
+ :proc => lambda { |i| i.to_i }
47
+
48
+ option :attribute,
49
+ :short => "-a [ATTR]",
50
+ :long => "--attribute [ATTR]",
51
+ :description => "Show only one attribute"
52
+
53
+ option :run_list,
54
+ :short => "-r",
55
+ :long => "--run-list",
56
+ :description => "Show only the run list"
57
+
58
+ option :id_only,
59
+ :short => "-i",
60
+ :long => "--id-only",
61
+ :description => "Show only the ID of matching objects"
62
+
63
+ def run
64
+ q = Chef::Search::Query.new
65
+ display = { :total => 0, :start => config[:start] ? config[:start] : 0, :rows => [ ] }
66
+
67
+ q.search(@name_args[0], @name_args[1], config[:sort], config[:start] ? config[:start] : 0, config[:rows] ? config[:rows] : 20) do |item|
68
+ formatted_item = format_for_display(item)
69
+ if formatted_item.respond_to?(:has_key?) && !formatted_item.has_key?('id')
70
+ formatted_item['id'] = item.has_key?('id') ? item['id'] : item.name
71
+ end
72
+ display[:rows] << formatted_item
73
+ display[:total] += 1
74
+ end
75
+
76
+ if config[:id_only]
77
+ if config[:attribute]
78
+ display[:rows].each do |row|
79
+ puts row[config[:attribute]] if row.has_key?(config[:attribute]) && !row[config[:attribute]].nil?
80
+ end
81
+ else
82
+ puts display[:rows].join("\n")
83
+ end
84
+ else
85
+ json_pretty_print(display)
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+
93
+
94
+
@@ -0,0 +1,39 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: AJ Christensen (<@aj@opsocde.com>)
4
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require 'chef'
20
+ require 'mixlib/log'
21
+
22
+ class Chef
23
+ class Log
24
+ extend Mixlib::Log
25
+
26
+ # This is here for compatability, before we moved to
27
+ # Mixlib::Log.
28
+ class Formatter
29
+ def self.show_time=(arg)
30
+ Mixlib::Log::Formatter.show_time = arg
31
+ end
32
+
33
+ def self.show_time
34
+ Mixlib::Log::Formatter.show_time
35
+ end
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,31 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
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
+ class Chef
19
+ module Mixin
20
+ module CheckHelper
21
+ def set_if_args(thing, arguments)
22
+ raise ArgumentError, "Must call set_if_args with a block!" unless Kernel.block_given?
23
+ if arguments != nil
24
+ yield(arguments)
25
+ else
26
+ thing
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
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 'digest/sha2'
20
+ require 'chef/cache/checksum'
21
+
22
+ class Chef
23
+ module Mixin
24
+ module Checksum
25
+
26
+ def checksum(file)
27
+ Chef::Cache::Checksum.checksum_for_file(file)
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,390 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
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/log'
20
+ require 'chef/exceptions'
21
+ require 'tmpdir'
22
+ require 'fcntl'
23
+ require 'etc'
24
+ require 'io/wait'
25
+
26
+ class Chef
27
+ module Mixin
28
+ module Command
29
+
30
+ # If command is a block, returns true if the block returns true, false if it returns false.
31
+ # ("Only run this resource if the block is true")
32
+ #
33
+ # If the command is not a block, executes the command. If it returns any status other than
34
+ # 0, it returns false (clearly, a 0 status code is true)
35
+ #
36
+ # === Parameters
37
+ # command<Block>, <String>:: A block to check, or a string to execute
38
+ #
39
+ # === Returns
40
+ # true:: Returns true if the block is true, or if the command returns 0
41
+ # false:: Returns false if the block is false, or if the command returns a non-zero exit code.
42
+ def only_if(command)
43
+ if command.kind_of?(Proc)
44
+ res = command.call
45
+ unless res
46
+ return false
47
+ end
48
+ else
49
+ status = run_command(:command => command, :ignore_failure => true)
50
+ if status.exitstatus != 0
51
+ return false
52
+ end
53
+ end
54
+ true
55
+ end
56
+
57
+ module_function :only_if
58
+
59
+ # If command is a block, returns false if the block returns true, true if it returns false.
60
+ # ("Do not run this resource if the block is true")
61
+ #
62
+ # If the command is not a block, executes the command. If it returns a 0 exitstatus, returns false.
63
+ # ("Do not run this resource if the command returns 0")
64
+ #
65
+ # === Parameters
66
+ # command<Block>, <String>:: A block to check, or a string to execute
67
+ #
68
+ # === Returns
69
+ # true:: Returns true if the block is false, or if the command returns a non-zero exit status.
70
+ # false:: Returns false if the block is true, or if the command returns a 0 exit status.
71
+ def not_if(command)
72
+ if command.kind_of?(Proc)
73
+ res = command.call
74
+ if res
75
+ return false
76
+ end
77
+ else
78
+ status = run_command(:command => command, :ignore_failure => true)
79
+ if status.exitstatus == 0
80
+ return false
81
+ end
82
+ end
83
+ true
84
+ end
85
+
86
+ module_function :not_if
87
+
88
+ # === Parameters
89
+ # args<Hash>: A number of required and optional arguments
90
+ # command<String>, <Array>: A complete command with options to execute or a command and options as an Array
91
+ # creates<String>: The absolute path to a file that prevents the command from running if it exists
92
+ # cwd<String>: Working directory to execute command in, defaults to Dir.tmpdir
93
+ # timeout<String>: How many seconds to wait for the command to execute before timing out
94
+ # returns<String>: The single exit value command is expected to return, otherwise causes an exception
95
+ # ignore_failure<Boolean>: Whether to raise an exception on failure, or just return the status
96
+ #
97
+ # user<String>: The UID or user name of the user to execute the command as
98
+ # group<String>: The GID or group name of the group to execute the command as
99
+ # environment<Hash>: Pairs of environment variable names and their values to set before execution
100
+ #
101
+ # === Returns
102
+ # Returns the exit status of args[:command]
103
+ def run_command(args={})
104
+ command_output = ""
105
+
106
+ args[:ignore_failure] ||= false
107
+
108
+ if args.has_key?(:creates)
109
+ if File.exists?(args[:creates])
110
+ Chef::Log.debug("Skipping #{args[:command]} - creates #{args[:creates]} exists.")
111
+ return false
112
+ end
113
+ end
114
+
115
+ status, stdout, stderr = output_of_command(args[:command], args)
116
+ command_output << "STDOUT: #{stdout}"
117
+ command_output << "STDERR: #{stderr}"
118
+ handle_command_failures(status, command_output, args)
119
+
120
+ status
121
+ end
122
+
123
+ module_function :run_command
124
+
125
+ def output_of_command(command, args)
126
+ Chef::Log.debug("Executing #{command}")
127
+ stderr_string, stdout_string, status = "", "", nil
128
+
129
+ exec_processing_block = lambda do |pid, stdin, stdout, stderr|
130
+ stdout_string, stderr_string = stdout.string.chomp, stderr.string.chomp
131
+ end
132
+
133
+ args[:cwd] ||= Dir.tmpdir
134
+ unless File.directory?(args[:cwd])
135
+ raise Chef::Exceptions::Exec, "#{args[:cwd]} does not exist or is not a directory"
136
+ end
137
+
138
+ Dir.chdir(args[:cwd]) do
139
+ if args[:timeout]
140
+ begin
141
+ Timeout.timeout(args[:timeout]) do
142
+ status = popen4(command, args, &exec_processing_block)
143
+ end
144
+ rescue Timeout::Error => e
145
+ Chef::Log.error("#{command} exceeded timeout #{args[:timeout]}")
146
+ raise(e)
147
+ end
148
+ else
149
+ status = popen4(command, args, &exec_processing_block)
150
+ end
151
+
152
+ Chef::Log.debug("---- Begin output of #{command} ----")
153
+ Chef::Log.debug("STDOUT: #{stdout_string}")
154
+ Chef::Log.debug("STDERR: #{stderr_string}")
155
+ Chef::Log.debug("---- End output of #{command} ----")
156
+ Chef::Log.debug("Ran #{command} returned #{status.exitstatus}")
157
+ end
158
+
159
+ return status, stdout_string, stderr_string
160
+ end
161
+
162
+ module_function :output_of_command
163
+
164
+ def handle_command_failures(status, command_output, args={})
165
+ unless args[:ignore_failure]
166
+ args[:returns] ||= 0
167
+ if status.exitstatus != args[:returns]
168
+ # if the log level is not debug, through output of command when we fail
169
+ output = ""
170
+ if Chef::Log.logger.level > 0
171
+ output << "\n---- Begin output of #{args[:command]} ----\n"
172
+ output << "#{command_output}"
173
+ output << "---- End output of #{args[:command]} ----\n"
174
+ end
175
+ raise Chef::Exceptions::Exec, "#{args[:command]} returned #{status.exitstatus}, expected #{args[:returns]}#{output}"
176
+ end
177
+ end
178
+ end
179
+
180
+ module_function :handle_command_failures
181
+
182
+ # Call #run_command but set LC_ALL to the system's current environment so it doesn't get changed to C.
183
+ #
184
+ # === Parameters
185
+ # args<Hash>: A number of required and optional arguments that will be handed out to #run_command
186
+ #
187
+ # === Returns
188
+ # Returns the result of #run_command
189
+ def run_command_with_systems_locale(args={})
190
+ args[:environment] ||= {}
191
+ args[:environment]["LC_ALL"] = ENV["LC_ALL"]
192
+ run_command args
193
+ end
194
+
195
+ module_function :run_command_with_systems_locale
196
+
197
+ # This is taken directly from Ara T Howard's Open4 library, and then
198
+ # modified to suit the needs of Chef. Any bugs here are most likely
199
+ # my own, and not Ara's.
200
+ #
201
+ # The original appears in external/open4.rb in its unmodified form.
202
+ #
203
+ # Thanks Ara!
204
+ def popen4(cmd, args={}, &b)
205
+
206
+ # Waitlast - this is magic.
207
+ #
208
+ # Do we wait for the child process to die before we yield
209
+ # to the block, or after? That is the magic of waitlast.
210
+ #
211
+ # By default, we are waiting before we yield the block.
212
+ args[:waitlast] ||= false
213
+
214
+ args[:user] ||= nil
215
+ unless args[:user].kind_of?(Integer)
216
+ args[:user] = Etc.getpwnam(args[:user]).uid if args[:user]
217
+ end
218
+ args[:group] ||= nil
219
+ unless args[:group].kind_of?(Integer)
220
+ args[:group] = Etc.getgrnam(args[:group]).gid if args[:group]
221
+ end
222
+ args[:environment] ||= {}
223
+
224
+ # Default on C locale so parsing commands output can be done
225
+ # independently of the node's default locale.
226
+ # "LC_ALL" could be set to nil, in which case we also must ignore it.
227
+ unless args[:environment].has_key?("LC_ALL")
228
+ args[:environment]["LC_ALL"] = "C"
229
+ end
230
+
231
+ pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe
232
+
233
+ verbose = $VERBOSE
234
+ begin
235
+ $VERBOSE = nil
236
+ ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
237
+
238
+ cid = fork {
239
+ pw.last.close
240
+ STDIN.reopen pw.first
241
+ pw.first.close
242
+
243
+ pr.first.close
244
+ STDOUT.reopen pr.last
245
+ pr.last.close
246
+
247
+ pe.first.close
248
+ STDERR.reopen pe.last
249
+ pe.last.close
250
+
251
+ STDOUT.sync = STDERR.sync = true
252
+
253
+ if args[:group]
254
+ Process.egid = args[:group]
255
+ Process.gid = args[:group]
256
+ end
257
+
258
+ if args[:user]
259
+ Process.euid = args[:user]
260
+ Process.uid = args[:user]
261
+ end
262
+
263
+ args[:environment].each do |key,value|
264
+ ENV[key] = value
265
+ end
266
+
267
+ if args[:umask]
268
+ umask = ((args[:umask].respond_to?(:oct) ? args[:umask].oct : args[:umask].to_i) & 007777)
269
+ File.umask(umask)
270
+ end
271
+
272
+ begin
273
+ if cmd.kind_of?(Array)
274
+ exec(*cmd)
275
+ else
276
+ exec(cmd)
277
+ end
278
+ raise 'forty-two'
279
+ rescue Exception => e
280
+ Marshal.dump(e, ps.last)
281
+ ps.last.flush
282
+ end
283
+ ps.last.close unless (ps.last.closed?)
284
+ exit!
285
+ }
286
+ ensure
287
+ $VERBOSE = verbose
288
+ end
289
+
290
+ [pw.first, pr.last, pe.last, ps.last].each{|fd| fd.close}
291
+
292
+ begin
293
+ e = Marshal.load ps.first
294
+ raise(Exception === e ? e : "unknown failure!")
295
+ rescue EOFError # If we get an EOF error, then the exec was successful
296
+ 42
297
+ ensure
298
+ ps.first.close
299
+ end
300
+
301
+ pw.last.sync = true
302
+
303
+ pi = [pw.last, pr.first, pe.first]
304
+
305
+ if b
306
+ begin
307
+ if args[:waitlast]
308
+ b[cid, *pi]
309
+ # send EOF so that if the child process is reading from STDIN
310
+ # it will actually finish up and exit
311
+ pi[0].close_write
312
+ Process.waitpid2(cid).last
313
+ else
314
+ # This took some doing.
315
+ # The trick here is to close STDIN
316
+ # Then set our end of the childs pipes to be O_NONBLOCK
317
+ # Then wait for the child to die, which means any IO it
318
+ # wants to do must be done - it's dead. If it isn't,
319
+ # it's because something totally skanky is happening,
320
+ # and we don't care.
321
+ o = StringIO.new
322
+ e = StringIO.new
323
+
324
+ pi[0].close
325
+
326
+ stdout = pi[1]
327
+ stderr = pi[2]
328
+
329
+ stdout.sync = true
330
+ stderr.sync = true
331
+
332
+ stdout.fcntl(Fcntl::F_SETFL, pi[1].fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
333
+ stderr.fcntl(Fcntl::F_SETFL, pi[2].fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
334
+
335
+ stdout_finished = false
336
+ stderr_finished = false
337
+
338
+ results = nil
339
+
340
+ while !stdout_finished || !stderr_finished
341
+ begin
342
+ channels_to_watch = []
343
+ channels_to_watch << stdout if !stdout_finished
344
+ channels_to_watch << stderr if !stderr_finished
345
+ ready = IO.select(channels_to_watch, nil, nil, 1.0)
346
+ rescue Errno::EAGAIN
347
+ ensure
348
+ results = Process.waitpid2(cid, Process::WNOHANG)
349
+ if results
350
+ stdout_finished = true
351
+ stderr_finished = true
352
+ end
353
+ end
354
+
355
+ if ready && ready.first.include?(stdout)
356
+ line = results ? stdout.gets(nil) : stdout.gets
357
+ if line
358
+ o.write(line)
359
+ else
360
+ stdout_finished = true
361
+ end
362
+ end
363
+ if ready && ready.first.include?(stderr)
364
+ line = results ? stderr.gets(nil) : stderr.gets
365
+ if line
366
+ e.write(line)
367
+ else
368
+ stderr_finished = true
369
+ end
370
+ end
371
+ end
372
+ results = Process.waitpid2(cid) unless results
373
+ o.rewind
374
+ e.rewind
375
+ b[cid, pi[0], o, e]
376
+ results.last
377
+ end
378
+ ensure
379
+ pi.each{|fd| fd.close unless fd.closed?}
380
+ end
381
+ else
382
+ [cid, pw.last, pr.first, pe.first]
383
+ end
384
+ end
385
+
386
+ module_function :popen4
387
+
388
+ end
389
+ end
390
+ end