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,175 @@
1
+ # Author:: Daniel DeLeo (<dan@kallistec.com>)
2
+ # Copyright:: Copyright (c) 2009 Daniel DeLeo
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ module Shef
19
+ class ShefSession
20
+ include Singleton
21
+
22
+ attr_accessor :node, :compile, :recipe
23
+ attr_reader :node_attributes, :client
24
+
25
+ def initialize
26
+ @node_built = false
27
+ end
28
+
29
+ def node_built?
30
+ !!@node_built
31
+ end
32
+
33
+ def reset!
34
+ loading do
35
+ rebuild_node
36
+ @node = client.node
37
+ node.consume_attributes(node_attributes) if node_attributes
38
+ shorten_node_inspect
39
+ @recipe = Chef::Recipe.new(nil, nil, @node)
40
+ @node_built = true
41
+ end
42
+ end
43
+
44
+ def node_attributes=(attrs)
45
+ @node_attributes = attrs
46
+ @node.consume_attributes(@node_attributes)
47
+ end
48
+
49
+ def collection
50
+ @collection || rebuild_collection
51
+ end
52
+
53
+ def definitions
54
+ nil
55
+ end
56
+
57
+ def cookbook_loader
58
+ nil
59
+ end
60
+
61
+ def save_node
62
+ raise "Not Supported! #{self.class.name} doesn't support #save_node, maybe you need to run shef in client mode?"
63
+ end
64
+
65
+ def rebuild_collection
66
+ raise "Not Implemented! :rebuild_collection should be implemented by subclasses"
67
+ end
68
+
69
+ private
70
+
71
+ def loading
72
+ show_loading_progress
73
+ begin
74
+ yield
75
+ rescue => e
76
+ loading_complete(false)
77
+ raise e
78
+ else
79
+ loading_complete(true)
80
+ end
81
+ end
82
+
83
+ def show_loading_progress
84
+ print "Loading"
85
+ @loading = true
86
+ @dot_printer = Thread.new do
87
+ while @loading
88
+ print "."
89
+ sleep 0.5
90
+ end
91
+ end
92
+ end
93
+
94
+ def loading_complete(success)
95
+ @loading = false
96
+ @dot_printer.join
97
+ msg = success ? "done.\n\n" : "epic fail!\n\n"
98
+ print msg
99
+ end
100
+
101
+ def shorten_node_inspect
102
+ def @node.inspect
103
+ "<Chef::Node:0x#{self.object_id.to_s(16)} @name=\"#{self.name}\">"
104
+ end
105
+ end
106
+
107
+ def rebuild_node
108
+ raise "Not Implemented! :rebuild_node should be implemented by subclasses"
109
+ end
110
+
111
+ end
112
+
113
+ class StandAloneSession < ShefSession
114
+
115
+ def rebuild_collection
116
+ @collection = @recipe.collection
117
+ end
118
+
119
+ private
120
+
121
+ def rebuild_node
122
+ @client = Chef::Client.new
123
+ @client.determine_node_name
124
+ @client.build_node(@client.node_name, true)
125
+ end
126
+
127
+ end
128
+
129
+ class SoloSession < ShefSession
130
+
131
+ def definitions
132
+ @compile.definitions
133
+ end
134
+
135
+ def cookbook_loader
136
+ @compile.cookbook_loader
137
+ end
138
+
139
+ def rebuild_collection
140
+ @compile = Chef::Compile.new(@client.node)
141
+
142
+ @collection = @compile.collection
143
+ @collection << @recipe.collection.all_resources
144
+ @collection
145
+ end
146
+
147
+ private
148
+
149
+ def rebuild_node
150
+ @client = Chef::Client.new
151
+ @client.determine_node_name
152
+ @client.build_node(@client.node_name, true)
153
+ end
154
+
155
+ end
156
+
157
+ class ClientSession < SoloSession
158
+
159
+ def save_node
160
+ @client.save_node
161
+ end
162
+
163
+ private
164
+
165
+ def rebuild_node
166
+ @client = Chef::Client.new
167
+ @client.determine_node_name
168
+ @client.register
169
+ @client.build_node(@client.node_name, false)
170
+
171
+ @client.sync_cookbooks
172
+ end
173
+
174
+ end
175
+ end
@@ -0,0 +1,185 @@
1
+ require 'net/http'
2
+ require 'mixlib/authentication/signedheaderauth'
3
+ require 'openssl'
4
+
5
+ # inspired by/cargo-culted from http://stanislavvitvitskiy.blogspot.com/2008/12/multipart-post-in-ruby.html
6
+ # TODO: confirm that code is public domain
7
+ class Chef
8
+ class StreamingCookbookUploader
9
+
10
+ DefaultHeaders = { 'accept' => 'application/json' }
11
+
12
+ class << self
13
+
14
+ def post(to_url, user_id, secret_key_filename, params = {}, headers = {})
15
+ make_request(:post, to_url, user_id, secret_key_filename, params, headers)
16
+ end
17
+
18
+ def put(to_url, user_id, secret_key_filename, params = {}, headers = {})
19
+ make_request(:put, to_url, user_id, secret_key_filename, params, headers)
20
+ end
21
+
22
+ def make_request(http_verb, to_url, user_id, secret_key_filename, params = {}, headers = {})
23
+ boundary = '----RubyMultipartClient' + rand(1000000).to_s + 'ZZZZZ'
24
+ parts = []
25
+ content_file = nil
26
+ content_body = nil
27
+
28
+ timestamp = Time.now.utc.iso8601
29
+ secret_key = OpenSSL::PKey::RSA.new(File.read(secret_key_filename))
30
+
31
+ unless params.nil? || params.empty?
32
+ params.each do |key, value|
33
+ if value.kind_of?(File)
34
+ content_file = value
35
+ filepath = value.path
36
+ filename = File.basename(filepath)
37
+ parts << StringPart.new( "--" + boundary + "\r\n" +
38
+ "Content-Disposition: form-data; name=\"" + key.to_s + "\"; filename=\"" + filename + "\"\r\n" +
39
+ "Content-Type: application/octet-stream\r\n\r\n")
40
+ parts << StreamPart.new(value, File.size(filepath))
41
+ parts << StringPart.new("\r\n")
42
+ else
43
+ content_body = value.to_s
44
+ parts << StringPart.new( "--" + boundary + "\r\n" +
45
+ "Content-Disposition: form-data; name=\"" + key.to_s + "\"\r\n\r\n")
46
+ parts << StringPart.new(content_body + "\r\n")
47
+ end
48
+ end
49
+ parts << StringPart.new("--" + boundary + "--\r\n")
50
+ end
51
+
52
+ body_stream = MultipartStream.new(parts)
53
+
54
+ timestamp = Time.now.utc.iso8601
55
+
56
+ Chef::Log.logger.debug("Signing: method: #{http_verb}, file: #{content_file}, User-id: #{user_id}, Timestamp: #{timestamp}")
57
+
58
+ signing_options = {
59
+ :http_method=>http_verb,
60
+ :user_id=>user_id,
61
+ :timestamp=>timestamp}
62
+ (content_file && signing_options[:file] = content_file) || (signing_options[:body] = (content_body || ""))
63
+
64
+ headers.merge!(Mixlib::Authentication::SignedHeaderAuth.signing_object(signing_options).sign(secret_key))
65
+
66
+ content_file.rewind if content_file
67
+
68
+ # net/http doesn't like symbols for header keys, so we'll to_s each one just in case
69
+ headers = DefaultHeaders.merge(Hash[*headers.map{ |k,v| [k.to_s, v] }.flatten])
70
+
71
+ url = URI.parse(to_url)
72
+ req = case http_verb
73
+ when :put
74
+ Net::HTTP::Put.new(url.path, headers)
75
+ when :post
76
+ Net::HTTP::Post.new(url.path, headers)
77
+ end
78
+ req.content_length = body_stream.size
79
+ req.content_type = 'multipart/form-data; boundary=' + boundary unless parts.empty?
80
+ req.body_stream = body_stream
81
+
82
+ http = Net::HTTP.new(url.host, url.port)
83
+ if url.scheme == "https"
84
+ http.use_ssl = true
85
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
86
+ end
87
+ res = http.request(req)
88
+ #res = http.start {|http_proc| http_proc.request(req) }
89
+
90
+ # alias status to code and to_s to body for test purposes
91
+ # TODO: stop the following madness!
92
+ class << res
93
+ alias :to_s :body
94
+
95
+ # BUGBUG this makes the response compatible with what respsonse_steps expects to test headers (response.headers[] -> response[])
96
+ def headers
97
+ self
98
+ end
99
+
100
+ def status
101
+ code.to_i
102
+ end
103
+ end
104
+ res
105
+ end
106
+
107
+ end
108
+
109
+ class StreamPart
110
+ def initialize(stream, size)
111
+ @stream, @size = stream, size
112
+ end
113
+
114
+ def size
115
+ @size
116
+ end
117
+
118
+ # read the specified amount from the stream
119
+ def read(offset, how_much)
120
+ @stream.read(how_much)
121
+ end
122
+ end
123
+
124
+ class StringPart
125
+ def initialize(str)
126
+ @str = str
127
+ end
128
+
129
+ def size
130
+ @str.length
131
+ end
132
+
133
+ # read the specified amount from the string startiung at the offset
134
+ def read(offset, how_much)
135
+ @str[offset, how_much]
136
+ end
137
+ end
138
+
139
+ class MultipartStream
140
+ def initialize(parts)
141
+ @parts = parts
142
+ @part_no = 0
143
+ @part_offset = 0
144
+ end
145
+
146
+ def size
147
+ @parts.inject(0) {|size, part| size + part.size}
148
+ end
149
+
150
+ def read(how_much)
151
+ return nil if @part_no >= @parts.size
152
+
153
+ how_much_current_part = @parts[@part_no].size - @part_offset
154
+
155
+ how_much_current_part = if how_much_current_part > how_much
156
+ how_much
157
+ else
158
+ how_much_current_part
159
+ end
160
+
161
+ how_much_next_part = how_much - how_much_current_part
162
+
163
+ current_part = @parts[@part_no].read(@part_offset, how_much_current_part)
164
+
165
+ # recurse into the next part if the current one was not large enough
166
+ if how_much_next_part > 0
167
+ @part_no += 1
168
+ @part_offset = 0
169
+ next_part = read(how_much_next_part)
170
+ current_part + if next_part
171
+ next_part
172
+ else
173
+ ''
174
+ end
175
+ else
176
+ @part_offset += how_much_current_part
177
+ current_part
178
+ end
179
+ end
180
+ end
181
+
182
+ end
183
+
184
+
185
+ end
@@ -0,0 +1,245 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Copyright:: Copyright (c) 2008, 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 'rubygems'
20
+ require 'json'
21
+ require 'chef'
22
+ require 'chef/role'
23
+ require 'chef/cookbook/metadata'
24
+ require 'tempfile'
25
+ require 'rake'
26
+
27
+ # Allow REMOTE options to be overridden on the command line
28
+ REMOTE_HOST = ENV["REMOTE_HOST"] if ENV["REMOTE_HOST"] != nil
29
+ REMOTE_SUDO = ENV["REMOTE_SUDO"] if ENV["REMOTE_SUDO"] != nil
30
+ if defined? REMOTE_HOST
31
+ REMOTE_PATH_PREFIX = "#{REMOTE_HOST}:"
32
+ REMOTE_EXEC_PREFIX = "ssh #{REMOTE_HOST}"
33
+ REMOTE_EXEC_PREFIX += " sudo" if defined? REMOTE_SUDO
34
+ LOCAL_EXEC_PREFIX = ""
35
+ else
36
+ REMOTE_PATH_PREFIX = ""
37
+ REMOTE_EXEC_PREFIX = ""
38
+ LOCAL_EXEC_PREFIX = "sudo"
39
+ end
40
+
41
+ desc "Update your repository from source control"
42
+ task :update do
43
+ puts "** Updating your repository"
44
+
45
+ case $vcs
46
+ when :svn
47
+ sh %{svn up}
48
+ when :git
49
+ pull = false
50
+ IO.foreach(File.join(TOPDIR, ".git", "config")) do |line|
51
+ pull = true if line =~ /\[remote "origin"\]/
52
+ end
53
+ if pull
54
+ sh %{git pull}
55
+ else
56
+ puts "* Skipping git pull, no origin specified"
57
+ end
58
+ else
59
+ puts "* No SCM configured, skipping update"
60
+ end
61
+ end
62
+
63
+ desc "Install the latest copy of the repository on this Chef Server"
64
+ task :install => [ :update, :roles, :upload_cookbooks ] do
65
+ if File.exists?(File.join(TOPDIR, "config", "server.rb"))
66
+ puts "* Installing new Chef Server Config"
67
+ sh "#{LOCAL_EXEC_PREFIX} rsync -rlt --delete --exclude '.svn' --exclude '.git*' config/server.rb #{REMOTE_PATH_PREFIX}#{CHEF_SERVER_CONFIG}"
68
+ end
69
+ if File.exists?(File.join(TOPDIR, "config", "client.rb"))
70
+ puts "* Installing new Chef Client Config"
71
+ sh "#{LOCAL_EXEC_PREFIX} rsync -rlt --delete --exclude '.svn' --exclude '.git*' config/client.rb #{REMOTE_PATH_PREFIX}#{CHEF_CLIENT_CONFIG}"
72
+ end
73
+ end
74
+
75
+ desc "By default, run rake test"
76
+ task :default => [ :test ]
77
+
78
+ desc "Create a new cookbook (with COOKBOOK=name, optional CB_PREFIX=site-)"
79
+ task :new_cookbook do
80
+ create_cookbook(File.join(TOPDIR, "#{ENV["CB_PREFIX"]}cookbooks"))
81
+ create_readme(File.join(TOPDIR, "#{ENV["CB_PREFIX"]}cookbooks"))
82
+ create_metadata(File.join(TOPDIR, "#{ENV["CB_PREFIX"]}cookbooks"))
83
+ end
84
+
85
+ def create_cookbook(dir)
86
+ raise "Must provide a COOKBOOK=" unless ENV["COOKBOOK"]
87
+ puts "** Creating cookbook #{ENV["COOKBOOK"]}"
88
+ sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "attributes")}"
89
+ sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "recipes")}"
90
+ sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "definitions")}"
91
+ sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "libraries")}"
92
+ sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "resources")}"
93
+ sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "providers")}"
94
+ sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "files", "default")}"
95
+ sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "templates", "default")}"
96
+ unless File.exists?(File.join(dir, ENV["COOKBOOK"], "recipes", "default.rb"))
97
+ open(File.join(dir, ENV["COOKBOOK"], "recipes", "default.rb"), "w") do |file|
98
+ file.puts <<-EOH
99
+ #
100
+ # Cookbook Name:: #{ENV["COOKBOOK"]}
101
+ # Recipe:: default
102
+ #
103
+ # Copyright #{Time.now.year}, #{COMPANY_NAME}
104
+ #
105
+ EOH
106
+ case NEW_COOKBOOK_LICENSE
107
+ when :apachev2
108
+ file.puts <<-EOH
109
+ # Licensed under the Apache License, Version 2.0 (the "License");
110
+ # you may not use this file except in compliance with the License.
111
+ # You may obtain a copy of the License at
112
+ #
113
+ # http://www.apache.org/licenses/LICENSE-2.0
114
+ #
115
+ # Unless required by applicable law or agreed to in writing, software
116
+ # distributed under the License is distributed on an "AS IS" BASIS,
117
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118
+ # See the License for the specific language governing permissions and
119
+ # limitations under the License.
120
+ #
121
+ EOH
122
+ when :none
123
+ file.puts <<-EOH
124
+ # All rights reserved - Do Not Redistribute
125
+ #
126
+ EOH
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ def create_readme(dir)
133
+ raise "Must provide a COOKBOOK=" unless ENV["COOKBOOK"]
134
+ puts "** Creating README for cookbook: #{ENV["COOKBOOK"]}"
135
+ unless File.exists?(File.join(dir, ENV["COOKBOOK"], "README.rdoc"))
136
+ open(File.join(dir, ENV["COOKBOOK"], "README.rdoc"), "w") do |file|
137
+ file.puts <<-EOH
138
+ = DESCRIPTION:
139
+
140
+ = REQUIREMENTS:
141
+
142
+ = ATTRIBUTES:
143
+
144
+ = USAGE:
145
+
146
+ EOH
147
+ end
148
+ end
149
+ end
150
+
151
+ def create_metadata(dir)
152
+ raise "Must provide a COOKBOOK=" unless ENV["COOKBOOK"]
153
+ puts "** Creating metadata for cookbook: #{ENV["COOKBOOK"]}"
154
+
155
+ case NEW_COOKBOOK_LICENSE
156
+ when :apachev2
157
+ license = "Apache 2.0"
158
+ when :none
159
+ license = "All rights reserved"
160
+ end
161
+
162
+ unless File.exists?(File.join(dir, ENV["COOKBOOK"], "metadata.rb"))
163
+ open(File.join(dir, ENV["COOKBOOK"], "metadata.rb"), "w") do |file|
164
+ if File.exists?(File.join(dir, ENV["COOKBOOK"], 'README.rdoc'))
165
+ long_description = "long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))"
166
+ end
167
+ file.puts <<-EOH
168
+ maintainer "#{COMPANY_NAME}"
169
+ maintainer_email "#{SSL_EMAIL_ADDRESS}"
170
+ license "#{license}"
171
+ description "Installs/Configures #{ENV["COOKBOOK"]}"
172
+ #{long_description}
173
+ version "0.1"
174
+ EOH
175
+ end
176
+ end
177
+ end
178
+
179
+ desc "Create a new self-signed SSL certificate for FQDN=foo.example.com"
180
+ task :ssl_cert do
181
+ $expect_verbose = true
182
+ fqdn = ENV["FQDN"]
183
+ fqdn =~ /^(.+?)\.(.+)$/
184
+ hostname = $1
185
+ domain = $2
186
+ keyfile = fqdn.gsub("*", "wildcard")
187
+ raise "Must provide FQDN!" unless fqdn && hostname && domain
188
+ puts "** Creating self signed SSL Certificate for #{fqdn}"
189
+ sh("(cd #{CADIR} && openssl genrsa 2048 > #{keyfile}.key)")
190
+ sh("(cd #{CADIR} && chmod 644 #{keyfile}.key)")
191
+ puts "* Generating Self Signed Certificate Request"
192
+ tf = Tempfile.new("#{keyfile}.ssl-conf")
193
+ ssl_config = <<EOH
194
+ [ req ]
195
+ distinguished_name = req_distinguished_name
196
+ prompt = no
197
+
198
+ [ req_distinguished_name ]
199
+ C = #{SSL_COUNTRY_NAME}
200
+ ST = #{SSL_STATE_NAME}
201
+ L = #{SSL_LOCALITY_NAME}
202
+ O = #{COMPANY_NAME}
203
+ OU = #{SSL_ORGANIZATIONAL_UNIT_NAME}
204
+ CN = #{fqdn}
205
+ emailAddress = #{SSL_EMAIL_ADDRESS}
206
+ EOH
207
+ tf.puts(ssl_config)
208
+ tf.close
209
+ sh("(cd #{CADIR} && openssl req -config '#{tf.path}' -new -x509 -nodes -sha1 -days 3650 -key #{keyfile}.key > #{keyfile}.crt)")
210
+ sh("(cd #{CADIR} && openssl x509 -noout -fingerprint -text < #{keyfile}.crt > #{keyfile}.info)")
211
+ sh("(cd #{CADIR} && cat #{keyfile}.crt #{keyfile}.key > #{keyfile}.pem)")
212
+ sh("(cd #{CADIR} && chmod 644 #{keyfile}.pem)")
213
+ end
214
+
215
+ rule(%r{\b(?:site-)?cookbooks/[^/]+/metadata\.json\Z} => [ proc { |task_name| task_name.sub(/\.[^.]+$/, '.rb') } ]) do |t|
216
+ system("knife cookbook metadata #{t.source}")
217
+ end
218
+
219
+ desc "Build cookbook metadata.json from metadata.rb"
220
+ task :metadata => FileList[File.join(TOPDIR, '*cookbooks', ENV['COOKBOOK'] || '*', 'metadata.rb')].pathmap('%X.json')
221
+
222
+ rule(%r{\broles/\S+\.json\Z} => [ proc { |task_name| task_name.sub(/\.[^.]+$/, '.rb') } ]) do |t|
223
+ system("knife role from file #{t.source}")
224
+ end
225
+
226
+ desc "Update roles"
227
+ task :roles => FileList[File.join(TOPDIR, 'roles', '**', '*.rb')].pathmap('%X.json')
228
+
229
+ desc "Update a specific role"
230
+ task :role, :role_name do |t, args|
231
+ system("knife role from file #{args.cookbook}")
232
+ end
233
+
234
+ desc "Upload all cookbooks"
235
+ task :upload_cookbooks => [ :metadata ]
236
+ task :upload_cookbooks do
237
+ system("knife cookbook upload --all")
238
+ end
239
+
240
+ desc "Upload a single cookbook"
241
+ task :upload_cookbook => [ :metadata ]
242
+ task :upload_cookbook, :cookbook do |t, args|
243
+ system("knife cookbook upload #{args.cookbook}")
244
+ end
245
+