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.
- data/LICENSE +201 -0
- data/README.rdoc +136 -0
- data/bin/chef-client +26 -0
- data/bin/chef-solo +26 -0
- data/bin/knife +27 -0
- data/bin/shef +45 -0
- data/distro/README +2 -0
- data/distro/common/man/man1/chef-indexer.1 +42 -0
- data/distro/common/man/man1/chef-server.1 +108 -0
- data/distro/common/man/man8/chef-client.8 +61 -0
- data/distro/common/man/man8/chef-solo.8 +58 -0
- data/distro/common/man/man8/knife.8 +359 -0
- data/distro/debian/etc/init.d/chef-client +175 -0
- data/distro/debian/etc/init.d/chef-indexer +175 -0
- data/distro/debian/etc/init.d/chef-server +120 -0
- data/distro/redhat/etc/init.d/chef-client +78 -0
- data/distro/redhat/etc/init.d/chef-indexer +76 -0
- data/distro/redhat/etc/init.d/chef-server +78 -0
- data/distro/redhat/etc/sysconfig/chef-client +10 -0
- data/distro/redhat/etc/sysconfig/chef-indexer +8 -0
- data/distro/redhat/etc/sysconfig/chef-server +10 -0
- data/distro/suse/etc/init.d/chef-client +121 -0
- data/lib/chef.rb +49 -0
- data/lib/chef/api_client.rb +269 -0
- data/lib/chef/application.rb +98 -0
- data/lib/chef/application/agent.rb +18 -0
- data/lib/chef/application/client.rb +214 -0
- data/lib/chef/application/knife.rb +138 -0
- data/lib/chef/application/server.rb +19 -0
- data/lib/chef/application/solo.rb +214 -0
- data/lib/chef/cache.rb +61 -0
- data/lib/chef/cache/checksum.rb +70 -0
- data/lib/chef/certificate.rb +154 -0
- data/lib/chef/client.rb +323 -0
- data/lib/chef/compile.rb +158 -0
- data/lib/chef/config.rb +195 -0
- data/lib/chef/cookbook.rb +198 -0
- data/lib/chef/cookbook/metadata.rb +487 -0
- data/lib/chef/cookbook/metadata/version.rb +87 -0
- data/lib/chef/cookbook_loader.rb +180 -0
- data/lib/chef/couchdb.rb +273 -0
- data/lib/chef/daemon.rb +170 -0
- data/lib/chef/data_bag.rb +216 -0
- data/lib/chef/data_bag_item.rb +227 -0
- data/lib/chef/exceptions.rb +39 -0
- data/lib/chef/file_cache.rb +205 -0
- data/lib/chef/knife.rb +300 -0
- data/lib/chef/knife/client_bulk_delete.rb +41 -0
- data/lib/chef/knife/client_create.rb +55 -0
- data/lib/chef/knife/client_delete.rb +37 -0
- data/lib/chef/knife/client_edit.rb +37 -0
- data/lib/chef/knife/client_list.rb +40 -0
- data/lib/chef/knife/client_reregister.rb +48 -0
- data/lib/chef/knife/client_show.rb +42 -0
- data/lib/chef/knife/configure.rb +84 -0
- data/lib/chef/knife/cookbook_bulk_delete.rb +47 -0
- data/lib/chef/knife/cookbook_delete.rb +41 -0
- data/lib/chef/knife/cookbook_download.rb +57 -0
- data/lib/chef/knife/cookbook_list.rb +41 -0
- data/lib/chef/knife/cookbook_metadata.rb +87 -0
- data/lib/chef/knife/cookbook_show.rb +75 -0
- data/lib/chef/knife/cookbook_upload.rb +173 -0
- data/lib/chef/knife/data_bag_create.rb +43 -0
- data/lib/chef/knife/data_bag_delete.rb +43 -0
- data/lib/chef/knife/data_bag_edit.rb +49 -0
- data/lib/chef/knife/data_bag_list.rb +42 -0
- data/lib/chef/knife/data_bag_show.rb +40 -0
- data/lib/chef/knife/ec2_instance_data.rb +46 -0
- data/lib/chef/knife/node_bulk_delete.rb +44 -0
- data/lib/chef/knife/node_create.rb +39 -0
- data/lib/chef/knife/node_delete.rb +36 -0
- data/lib/chef/knife/node_edit.rb +36 -0
- data/lib/chef/knife/node_from_file.rb +42 -0
- data/lib/chef/knife/node_list.rb +41 -0
- data/lib/chef/knife/node_run_list_add.rb +64 -0
- data/lib/chef/knife/node_run_list_remove.rb +45 -0
- data/lib/chef/knife/node_show.rb +46 -0
- data/lib/chef/knife/role_bulk_delete.rb +45 -0
- data/lib/chef/knife/role_create.rb +44 -0
- data/lib/chef/knife/role_delete.rb +36 -0
- data/lib/chef/knife/role_edit.rb +37 -0
- data/lib/chef/knife/role_from_file.rb +46 -0
- data/lib/chef/knife/role_list.rb +40 -0
- data/lib/chef/knife/role_show.rb +43 -0
- data/lib/chef/knife/search.rb +94 -0
- data/lib/chef/log.rb +39 -0
- data/lib/chef/mixin/check_helper.rb +31 -0
- data/lib/chef/mixin/checksum.rb +32 -0
- data/lib/chef/mixin/command.rb +390 -0
- data/lib/chef/mixin/convert_to_class_name.rb +57 -0
- data/lib/chef/mixin/create_path.rb +56 -0
- data/lib/chef/mixin/deep_merge.rb +33 -0
- data/lib/chef/mixin/find_preferred_file.rb +92 -0
- data/lib/chef/mixin/from_file.rb +50 -0
- data/lib/chef/mixin/generate_url.rb +58 -0
- data/lib/chef/mixin/language.rb +107 -0
- data/lib/chef/mixin/language_include_attribute.rb +56 -0
- data/lib/chef/mixin/language_include_recipe.rb +53 -0
- data/lib/chef/mixin/params_validate.rb +197 -0
- data/lib/chef/mixin/recipe_definition_dsl_core.rb +79 -0
- data/lib/chef/mixin/template.rb +94 -0
- data/lib/chef/nanite.rb +100 -0
- data/lib/chef/node.rb +463 -0
- data/lib/chef/node/attribute.rb +412 -0
- data/lib/chef/openid_registration.rb +181 -0
- data/lib/chef/platform.rb +268 -0
- data/lib/chef/provider.rb +101 -0
- data/lib/chef/provider/breakpoint.rb +36 -0
- data/lib/chef/provider/cron.rb +184 -0
- data/lib/chef/provider/deploy.rb +314 -0
- data/lib/chef/provider/deploy/revision.rb +70 -0
- data/lib/chef/provider/deploy/timestamped.rb +33 -0
- data/lib/chef/provider/directory.rb +72 -0
- data/lib/chef/provider/erl_call.rb +72 -0
- data/lib/chef/provider/execute.rb +58 -0
- data/lib/chef/provider/file.rb +195 -0
- data/lib/chef/provider/git.rb +203 -0
- data/lib/chef/provider/group.rb +120 -0
- data/lib/chef/provider/group/dscl.rb +128 -0
- data/lib/chef/provider/group/gpasswd.rb +50 -0
- data/lib/chef/provider/group/groupadd.rb +78 -0
- data/lib/chef/provider/group/pw.rb +88 -0
- data/lib/chef/provider/group/usermod.rb +57 -0
- data/lib/chef/provider/http_request.rb +106 -0
- data/lib/chef/provider/ifconfig.rb +131 -0
- data/lib/chef/provider/link.rb +157 -0
- data/lib/chef/provider/mdadm.rb +88 -0
- data/lib/chef/provider/mount.rb +117 -0
- data/lib/chef/provider/mount/mount.rb +208 -0
- data/lib/chef/provider/package.rb +160 -0
- data/lib/chef/provider/package/apt.rb +110 -0
- data/lib/chef/provider/package/dpkg.rb +109 -0
- data/lib/chef/provider/package/easy_install.rb +106 -0
- data/lib/chef/provider/package/freebsd.rb +153 -0
- data/lib/chef/provider/package/macports.rb +105 -0
- data/lib/chef/provider/package/portage.rb +124 -0
- data/lib/chef/provider/package/rpm.rb +99 -0
- data/lib/chef/provider/package/rubygems.rb +136 -0
- data/lib/chef/provider/package/yum-dump.py +125 -0
- data/lib/chef/provider/package/yum.rb +175 -0
- data/lib/chef/provider/package/zypper.rb +132 -0
- data/lib/chef/provider/remote_directory.rb +126 -0
- data/lib/chef/provider/remote_file.rb +141 -0
- data/lib/chef/provider/route.rb +118 -0
- data/lib/chef/provider/ruby_block.rb +33 -0
- data/lib/chef/provider/script.rb +42 -0
- data/lib/chef/provider/service.rb +135 -0
- data/lib/chef/provider/service/debian.rb +64 -0
- data/lib/chef/provider/service/freebsd.rb +156 -0
- data/lib/chef/provider/service/gentoo.rb +54 -0
- data/lib/chef/provider/service/init.rb +71 -0
- data/lib/chef/provider/service/redhat.rb +62 -0
- data/lib/chef/provider/service/simple.rb +114 -0
- data/lib/chef/provider/subversion.rb +156 -0
- data/lib/chef/provider/template.rb +175 -0
- data/lib/chef/provider/user.rb +170 -0
- data/lib/chef/provider/user/dscl.rb +280 -0
- data/lib/chef/provider/user/pw.rb +113 -0
- data/lib/chef/provider/user/useradd.rb +108 -0
- data/lib/chef/recipe.rb +105 -0
- data/lib/chef/resource.rb +380 -0
- data/lib/chef/resource/apt_package.rb +34 -0
- data/lib/chef/resource/bash.rb +33 -0
- data/lib/chef/resource/breakpoint.rb +35 -0
- data/lib/chef/resource/cron.rb +179 -0
- data/lib/chef/resource/csh.rb +33 -0
- data/lib/chef/resource/deploy.rb +359 -0
- data/lib/chef/resource/deploy_revision.rb +35 -0
- data/lib/chef/resource/directory.rb +76 -0
- data/lib/chef/resource/dpkg_package.rb +34 -0
- data/lib/chef/resource/easy_install_package.rb +41 -0
- data/lib/chef/resource/erl_call.rb +83 -0
- data/lib/chef/resource/execute.rb +127 -0
- data/lib/chef/resource/file.rb +84 -0
- data/lib/chef/resource/gem_package.rb +41 -0
- data/lib/chef/resource/git.rb +36 -0
- data/lib/chef/resource/group.rb +70 -0
- data/lib/chef/resource/http_request.rb +52 -0
- data/lib/chef/resource/ifconfig.rb +134 -0
- data/lib/chef/resource/link.rb +78 -0
- data/lib/chef/resource/macports_package.rb +29 -0
- data/lib/chef/resource/mdadm.rb +82 -0
- data/lib/chef/resource/mount.rb +135 -0
- data/lib/chef/resource/package.rb +80 -0
- data/lib/chef/resource/perl.rb +33 -0
- data/lib/chef/resource/portage_package.rb +33 -0
- data/lib/chef/resource/python.rb +33 -0
- data/lib/chef/resource/remote_directory.rb +91 -0
- data/lib/chef/resource/remote_file.rb +60 -0
- data/lib/chef/resource/route.rb +135 -0
- data/lib/chef/resource/ruby.rb +33 -0
- data/lib/chef/resource/ruby_block.rb +39 -0
- data/lib/chef/resource/scm.rb +137 -0
- data/lib/chef/resource/script.rb +51 -0
- data/lib/chef/resource/service.rb +134 -0
- data/lib/chef/resource/subversion.rb +34 -0
- data/lib/chef/resource/template.rb +60 -0
- data/lib/chef/resource/timestamped_deploy.rb +31 -0
- data/lib/chef/resource/user.rb +101 -0
- data/lib/chef/resource_collection.rb +212 -0
- data/lib/chef/resource_collection/stepable_iterator.rb +124 -0
- data/lib/chef/resource_definition.rb +67 -0
- data/lib/chef/rest.rb +298 -0
- data/lib/chef/role.rb +301 -0
- data/lib/chef/run_list.rb +164 -0
- data/lib/chef/runner.rb +130 -0
- data/lib/chef/search/query.rb +71 -0
- data/lib/chef/shef.rb +220 -0
- data/lib/chef/shef/ext.rb +297 -0
- data/lib/chef/shef/shef_session.rb +175 -0
- data/lib/chef/streaming_cookbook_uploader.rb +185 -0
- data/lib/chef/tasks/chef_repo.rake +245 -0
- data/lib/chef/util/file_edit.rb +125 -0
- data/lib/chef/util/fileedit.rb +121 -0
- data/lib/chef/webui_user.rb +231 -0
- 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
|
+
|