chef 0.7.16 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of chef might be problematic. Click here for more details.
- data/README.rdoc +11 -10
- data/bin/chef-client +2 -2
- data/bin/chef-solo +1 -1
- data/bin/knife +27 -0
- data/bin/shef +49 -0
- data/distro/README +2 -0
- data/distro/{debian → common}/man/man1/chef-indexer.1 +0 -0
- data/distro/{debian → common}/man/man1/chef-server.1 +0 -0
- data/distro/{debian → common}/man/man8/chef-client.8 +0 -0
- data/distro/{debian → common}/man/man8/chef-solo.8 +0 -0
- data/distro/common/man/man8/knife.8 +375 -0
- data/distro/redhat/etc/init.d/chef-client +8 -4
- data/distro/redhat/etc/init.d/chef-server +16 -15
- data/distro/redhat/etc/init.d/chef-server-webui +78 -0
- data/distro/redhat/etc/init.d/chef-solr +76 -0
- data/distro/redhat/etc/init.d/chef-solr-indexer +75 -0
- data/distro/redhat/etc/sysconfig/chef-client +10 -0
- data/distro/redhat/etc/sysconfig/chef-server +10 -0
- data/distro/redhat/etc/sysconfig/chef-server-webui +10 -0
- data/distro/redhat/etc/sysconfig/chef-solr +9 -0
- data/distro/redhat/etc/sysconfig/chef-solr-indexer +7 -0
- data/distro/suse/etc/init.d/chef-client +121 -0
- data/lib/chef.rb +1 -1
- data/lib/chef/api_client.rb +263 -0
- data/lib/chef/application.rb +1 -1
- data/lib/chef/application/client.rb +21 -3
- data/lib/chef/application/knife.rb +144 -0
- data/lib/chef/application/server.rb +2 -1
- data/lib/chef/application/solo.rb +9 -2
- 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 +123 -220
- data/lib/chef/compile.rb +9 -21
- data/lib/chef/config.rb +67 -10
- data/lib/chef/cookbook.rb +49 -22
- data/lib/chef/cookbook/metadata.rb +85 -5
- data/lib/chef/cookbook_loader.rb +4 -4
- data/lib/chef/couchdb.rb +99 -30
- data/lib/chef/daemon.rb +1 -1
- data/lib/chef/data_bag.rb +215 -0
- data/lib/chef/data_bag_item.rb +219 -0
- data/lib/chef/exceptions.rb +3 -0
- data/lib/chef/index_queue.rb +29 -0
- data/lib/chef/index_queue/amqp_client.rb +106 -0
- data/lib/chef/index_queue/consumer.rb +76 -0
- data/lib/chef/index_queue/indexable.rb +74 -0
- data/lib/chef/knife.rb +309 -0
- data/lib/chef/knife/client_bulk_delete.rb +40 -0
- data/lib/chef/knife/client_create.rb +62 -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 +123 -0
- data/lib/chef/knife/cookbook_bulk_delete.rb +46 -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 +179 -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/index_rebuild.rb +51 -0
- data/lib/chef/knife/node_bulk_delete.rb +43 -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 +44 -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/knife/ssh.rb +170 -0
- data/lib/chef/log.rb +30 -8
- data/lib/chef/mixin/checksum.rb +2 -7
- data/lib/chef/mixin/command.rb +32 -13
- data/lib/chef/mixin/convert_to_class_name.rb +15 -0
- data/lib/chef/mixin/deep_merge.rb +199 -11
- data/lib/chef/mixin/generate_url.rb +18 -9
- data/lib/chef/mixin/language.rb +29 -1
- 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 +25 -12
- data/lib/chef/mixin/recipe_definition_dsl_core.rb +2 -0
- data/lib/chef/mixin/template.rb +11 -1
- data/lib/chef/mixin/xml_escape.rb +87 -0
- data/lib/chef/node.rb +144 -122
- data/lib/chef/openid_registration.rb +12 -5
- data/lib/chef/platform.rb +89 -47
- data/lib/chef/provider/breakpoint.rb +36 -0
- data/lib/chef/provider/cron.rb +5 -6
- data/lib/chef/provider/deploy.rb +43 -10
- data/lib/chef/provider/deploy/revision.rb +2 -3
- data/lib/chef/provider/erl_call.rb +72 -0
- data/lib/chef/provider/file.rb +8 -4
- data/lib/chef/provider/git.rb +10 -5
- data/lib/chef/provider/group/dscl.rb +128 -0
- data/lib/chef/provider/http_request.rb +6 -2
- data/lib/chef/provider/ifconfig.rb +1 -0
- data/lib/chef/provider/link.rb +1 -1
- data/lib/chef/provider/log.rb +53 -0
- data/lib/chef/provider/mdadm.rb +88 -0
- data/lib/chef/provider/mount/mount.rb +1 -1
- data/lib/chef/provider/package.rb +1 -1
- data/lib/chef/provider/package/easy_install.rb +106 -0
- data/lib/chef/provider/package/pacman.rb +101 -0
- data/lib/chef/provider/package/portage.rb +1 -1
- data/lib/chef/provider/package/rpm.rb +10 -8
- data/lib/chef/provider/package/yum-dump.py +22 -3
- data/lib/chef/provider/package/yum.rb +32 -8
- data/lib/chef/provider/package/zypper.rb +132 -0
- data/lib/chef/provider/remote_directory.rb +58 -49
- data/lib/chef/provider/remote_file.rb +1 -1
- data/lib/chef/provider/route.rb +136 -80
- data/lib/chef/provider/ruby_block.rb +18 -1
- data/lib/chef/provider/service/arch.rb +109 -0
- data/lib/chef/provider/service/freebsd.rb +0 -1
- data/lib/chef/provider/service/simple.rb +2 -3
- data/lib/chef/provider/service/upstart.rb +191 -0
- data/lib/chef/provider/subversion.rb +12 -4
- data/lib/chef/provider/template.rb +85 -53
- data/lib/chef/provider/user.rb +1 -1
- data/lib/chef/provider/user/dscl.rb +277 -0
- data/lib/chef/provider/user/useradd.rb +1 -0
- data/lib/chef/recipe.rb +2 -41
- data/lib/chef/resource.rb +9 -3
- data/lib/chef/resource/breakpoint.rb +35 -0
- data/lib/chef/resource/deploy.rb +16 -2
- data/lib/chef/resource/easy_install_package.rb +41 -0
- data/lib/chef/resource/erl_call.rb +83 -0
- data/lib/chef/resource/freebsd_package.rb +35 -0
- data/lib/chef/resource/log.rb +62 -0
- data/lib/chef/resource/mdadm.rb +82 -0
- data/lib/chef/resource/pacman_package.rb +33 -0
- data/lib/chef/resource/ruby_block.rb +21 -2
- data/lib/chef/resource/scm.rb +8 -0
- data/lib/chef/resource/subversion.rb +1 -0
- data/lib/chef/resource/user.rb +5 -2
- data/lib/chef/resource/yum_package.rb +36 -0
- data/lib/chef/resource_collection.rb +17 -9
- data/lib/chef/resource_collection/stepable_iterator.rb +124 -0
- data/lib/chef/rest.rb +166 -81
- data/lib/chef/role.rb +114 -38
- data/lib/chef/run_list.rb +15 -6
- data/lib/chef/runner.rb +13 -11
- data/lib/chef/search/query.rb +60 -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 +187 -0
- data/lib/chef/tasks/chef_repo.rake +53 -155
- data/lib/chef/util/file_edit.rb +94 -96
- data/lib/chef/webui_user.rb +233 -0
- metadata +219 -63
- data/distro/debian/etc/init.d/chef-indexer +0 -175
- data/distro/redhat/etc/chef/client.rb +0 -16
- data/distro/redhat/etc/chef/indexer.rb +0 -10
- data/distro/redhat/etc/chef/server.rb +0 -22
- data/distro/redhat/etc/init.d/chef-indexer +0 -76
- data/lib/chef/application/indexer.rb +0 -141
- data/lib/chef/queue.rb +0 -145
- data/lib/chef/search.rb +0 -88
- data/lib/chef/search/result.rb +0 -64
- data/lib/chef/search_index.rb +0 -77
- data/lib/chef/util/fileedit.rb +0 -121
@@ -0,0 +1,219 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Author:: Nuo Yan (<nuo@opscode.com>)
|
4
|
+
# Author:: Christopher Brown (<cb@opscode.com>)
|
5
|
+
# Copyright:: Copyright (c) 2009 Opscode, Inc.
|
6
|
+
# License:: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'chef/config'
|
22
|
+
require 'chef/mixin/params_validate'
|
23
|
+
require 'chef/mixin/from_file'
|
24
|
+
require 'chef/couchdb'
|
25
|
+
require 'chef/data_bag_item'
|
26
|
+
require 'extlib'
|
27
|
+
require 'json'
|
28
|
+
|
29
|
+
class Chef
|
30
|
+
class DataBagItem
|
31
|
+
|
32
|
+
include Chef::Mixin::FromFile
|
33
|
+
include Chef::Mixin::ParamsValidate
|
34
|
+
include Chef::IndexQueue::Indexable
|
35
|
+
|
36
|
+
DESIGN_DOCUMENT = {
|
37
|
+
"version" => 1,
|
38
|
+
"language" => "javascript",
|
39
|
+
"views" => {
|
40
|
+
"all" => {
|
41
|
+
"map" => <<-EOJS
|
42
|
+
function(doc) {
|
43
|
+
if (doc.chef_type == "data_bag_item") {
|
44
|
+
emit(doc.name, doc);
|
45
|
+
}
|
46
|
+
}
|
47
|
+
EOJS
|
48
|
+
},
|
49
|
+
"all_id" => {
|
50
|
+
"map" => <<-EOJS
|
51
|
+
function(doc) {
|
52
|
+
if (doc.chef_type == "data_bag_item") {
|
53
|
+
emit(doc.name, doc.name);
|
54
|
+
}
|
55
|
+
}
|
56
|
+
EOJS
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
attr_accessor :couchdb_rev, :couchdb_id, :couchdb
|
62
|
+
attr_reader :raw_data
|
63
|
+
|
64
|
+
# Create a new Chef::DataBagItem
|
65
|
+
def initialize(couchdb=nil)
|
66
|
+
@couchdb_rev = nil
|
67
|
+
@couchdb_id = nil
|
68
|
+
@data_bag = nil
|
69
|
+
@raw_data = Mash.new
|
70
|
+
@couchdb = couchdb || Chef::CouchDB.new
|
71
|
+
end
|
72
|
+
|
73
|
+
def chef_server_rest
|
74
|
+
Chef::REST.new(Chef::Config[:chef_server_url])
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.chef_server_rest
|
78
|
+
Chef::REST.new(Chef::Config[:chef_server_url])
|
79
|
+
end
|
80
|
+
|
81
|
+
def raw_data
|
82
|
+
@raw_data
|
83
|
+
end
|
84
|
+
|
85
|
+
def raw_data=(new_data)
|
86
|
+
raise ArgumentError, "Data Bag Items must contain a Hash or Mash!" unless new_data.kind_of?(Hash) || new_data.kind_of?(Mash)
|
87
|
+
raise ArgumentError, "Data Bag Items must have an id key in the hash! #{new_data.inspect}" unless new_data.has_key?("id")
|
88
|
+
raise ArgumentError, "Data Bag Item id does not match alphanumeric/-/_!" unless new_data["id"] =~ /^[\-[:alnum:]_]+$/
|
89
|
+
@raw_data = new_data
|
90
|
+
end
|
91
|
+
|
92
|
+
def data_bag(arg=nil)
|
93
|
+
set_or_return(
|
94
|
+
:data_bag,
|
95
|
+
arg,
|
96
|
+
:regex => /^[\-[:alnum:]_]+$/
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
def name
|
101
|
+
object_name
|
102
|
+
end
|
103
|
+
|
104
|
+
def object_name
|
105
|
+
raise ArgumentError, "You must have an 'id' or :id key in the raw data" unless raw_data.has_key?('id')
|
106
|
+
raise ArgumentError, "You must have declared what bag this item belongs to!" unless data_bag
|
107
|
+
|
108
|
+
id = raw_data['id']
|
109
|
+
"data_bag_item_#{data_bag}_#{id}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.object_name(data_bag_name, id)
|
113
|
+
"data_bag_item_#{data_bag_name}_#{id}"
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_hash
|
117
|
+
result = self.raw_data
|
118
|
+
result["chef_type"] = "data_bag_item"
|
119
|
+
result["data_bag"] = self.data_bag
|
120
|
+
result["_rev"] = @couchdb_rev if @couchdb_rev
|
121
|
+
result
|
122
|
+
end
|
123
|
+
|
124
|
+
# Serialize this object as a hash
|
125
|
+
def to_json(*a)
|
126
|
+
result = {
|
127
|
+
"name" => self.object_name,
|
128
|
+
"json_class" => self.class.name,
|
129
|
+
"chef_type" => "data_bag_item",
|
130
|
+
"data_bag" => self.data_bag,
|
131
|
+
"raw_data" => self.raw_data
|
132
|
+
}
|
133
|
+
result["_rev"] = @couchdb_rev if @couchdb_rev
|
134
|
+
result.to_json(*a)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Create a Chef::DataBagItem from JSON
|
138
|
+
def self.json_create(o)
|
139
|
+
bag_item = new
|
140
|
+
bag_item.data_bag(o["data_bag"])
|
141
|
+
o.delete("data_bag")
|
142
|
+
o.delete("chef_type")
|
143
|
+
o.delete("json_class")
|
144
|
+
o.delete("name")
|
145
|
+
if o.has_key?("_rev")
|
146
|
+
bag_item.couchdb_rev = o["_rev"]
|
147
|
+
o.delete("_rev")
|
148
|
+
end
|
149
|
+
if o.has_key?("_id")
|
150
|
+
bag_item.couchdb_id = o["_id"]
|
151
|
+
bag_item.index_id = bag_item.couchdb_id
|
152
|
+
o.delete("_id")
|
153
|
+
end
|
154
|
+
bag_item.raw_data = Mash.new(o["raw_data"])
|
155
|
+
bag_item
|
156
|
+
end
|
157
|
+
|
158
|
+
# The Data Bag Item behaves like a hash - we pass all that stuff along to @raw_data.
|
159
|
+
def method_missing(method_symbol, *args, &block)
|
160
|
+
self.raw_data.send(method_symbol, *args, &block)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Load a Data Bag Item by name from CouchDB
|
164
|
+
def self.cdb_load(data_bag, name, couchdb=nil)
|
165
|
+
(couchdb || Chef::CouchDB.new).load("data_bag_item", object_name(data_bag, name))
|
166
|
+
end
|
167
|
+
|
168
|
+
# Load a Data Bag Item by name via RESTful API
|
169
|
+
def self.load(data_bag, name)
|
170
|
+
Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("data/#{data_bag}/#{name}")
|
171
|
+
end
|
172
|
+
|
173
|
+
# Remove this Data Bag Item from CouchDB
|
174
|
+
def cdb_destroy
|
175
|
+
Chef::Log.debug "destroying data bag item: #{self.inspect}"
|
176
|
+
@couchdb.delete("data_bag_item", object_name, @couchdb_rev)
|
177
|
+
end
|
178
|
+
|
179
|
+
def destroy(data_bag=data_bag, databag_item=name)
|
180
|
+
chef_server_rest.delete_rest("data/#{data_bag}/#{databag_item}")
|
181
|
+
end
|
182
|
+
|
183
|
+
# Save this Data Bag Item to CouchDB
|
184
|
+
def cdb_save
|
185
|
+
@couchdb_rev = @couchdb.store("data_bag_item", object_name, self)["rev"]
|
186
|
+
end
|
187
|
+
|
188
|
+
# Save this Data Bag Item via RESTful API
|
189
|
+
def save(item_id=@raw_data['id'])
|
190
|
+
r = chef_server_rest
|
191
|
+
begin
|
192
|
+
r.put_rest("data/#{data_bag}/#{item_id}", @raw_data)
|
193
|
+
rescue Net::HTTPServerException => e
|
194
|
+
raise e unless e.response.code == "404"
|
195
|
+
r.post_rest("data/#{data_bag}", @raw_data)
|
196
|
+
end
|
197
|
+
self
|
198
|
+
end
|
199
|
+
|
200
|
+
# Create this Data Bag Item via RESTful API
|
201
|
+
def create
|
202
|
+
chef_server_rest.post_rest("data/#{data_bag}", @raw_data)
|
203
|
+
self
|
204
|
+
end
|
205
|
+
|
206
|
+
# Set up our CouchDB design document
|
207
|
+
def self.create_design_document(couchdb=nil)
|
208
|
+
(couchdb || Chef::CouchDB.new).create_design_document("data_bag_items", DESIGN_DOCUMENT)
|
209
|
+
end
|
210
|
+
|
211
|
+
# As a string
|
212
|
+
def to_s
|
213
|
+
"data_bag_item[#{@name}]"
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
|
data/lib/chef/exceptions.rb
CHANGED
@@ -32,5 +32,8 @@ class Chef
|
|
32
32
|
class Group < RuntimeError; end
|
33
33
|
class Link < RuntimeError; end
|
34
34
|
class Mount < RuntimeError; end
|
35
|
+
class CouchDBNotFound < RuntimeError; end
|
36
|
+
class PrivateKeyMissing < RuntimeError; end
|
37
|
+
class CannotWritePrivateKey < RuntimeError; end
|
35
38
|
end
|
36
39
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Daniel DeLeo (<dan@kallistec.com>)
|
3
|
+
# Copyright:: Copyright (c) 2009 Daniel DeLeo
|
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 "singleton"
|
20
|
+
require "bunny"
|
21
|
+
|
22
|
+
require "chef/index_queue/amqp_client"
|
23
|
+
require "chef/index_queue/indexable"
|
24
|
+
require "chef/index_queue/consumer"
|
25
|
+
|
26
|
+
class Chef
|
27
|
+
module IndexQueue
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Daniel DeLeo (<dan@kallistec.com>)
|
3
|
+
# Copyright:: Copyright (c) 2009 Daniel DeLeo
|
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
|
+
class Chef
|
20
|
+
module IndexQueue
|
21
|
+
class AmqpClient
|
22
|
+
include Singleton
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
reset!
|
26
|
+
end
|
27
|
+
|
28
|
+
def reset!
|
29
|
+
@amqp_client && amqp_client.connected? && amqp_client.stop
|
30
|
+
@amqp_client = nil
|
31
|
+
@exchange = nil
|
32
|
+
@queue = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def stop
|
36
|
+
@queue && @queue.subscription && @queue.unsubscribe
|
37
|
+
@amqp_client && @amqp_client.stop
|
38
|
+
end
|
39
|
+
|
40
|
+
def amqp_client
|
41
|
+
unless @amqp_client
|
42
|
+
begin
|
43
|
+
@amqp_client = Bunny.new(amqp_opts)
|
44
|
+
Chef::Log.debug "Starting AMQP connection with client settings: #{@amqp_client.inspect}"
|
45
|
+
@amqp_client.start
|
46
|
+
@amqp_client.qos(:prefetch_count => 1)
|
47
|
+
rescue Bunny::ServerDownError => e
|
48
|
+
Chef::Log.fatal "Could not connect to rabbitmq. Is it running, reachable, and configured correctly?"
|
49
|
+
raise e
|
50
|
+
rescue Bunny::ProtocolError => e
|
51
|
+
Chef::Log.fatal "Connection to rabbitmq refused. Check your rabbitmq configuration and chef's amqp* settings"
|
52
|
+
raise e
|
53
|
+
end
|
54
|
+
end
|
55
|
+
@amqp_client
|
56
|
+
end
|
57
|
+
|
58
|
+
def exchange
|
59
|
+
@exchange ||= amqp_client.exchange("chef-indexer", :durable => true, :type => :fanout)
|
60
|
+
end
|
61
|
+
|
62
|
+
def queue
|
63
|
+
unless @queue
|
64
|
+
@queue = amqp_client.queue("chef-index-consumer-" + consumer_id, :durable => durable_queue?)
|
65
|
+
@queue.bind(exchange)
|
66
|
+
end
|
67
|
+
@queue
|
68
|
+
end
|
69
|
+
|
70
|
+
def disconnected!
|
71
|
+
@amqp_client = nil
|
72
|
+
reset!
|
73
|
+
end
|
74
|
+
|
75
|
+
def send_action(action, data)
|
76
|
+
begin
|
77
|
+
exchange.publish({"action" => action.to_s, "payload" => data}.to_json)
|
78
|
+
rescue Bunny::ServerDownError, Bunny::ConnectionError, Errno::ECONNRESET => e
|
79
|
+
Chef::Log.error("Disconnected from the AMQP Broker, cannot queue data to the indexer")
|
80
|
+
disconnected!
|
81
|
+
raise e
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def durable_queue?
|
88
|
+
!!Chef::Config[:amqp_consumer_id]
|
89
|
+
end
|
90
|
+
|
91
|
+
def consumer_id
|
92
|
+
Chef::Config[:amqp_consumer_id] || UUIDTools::UUID.random_create.to_s
|
93
|
+
end
|
94
|
+
|
95
|
+
def amqp_opts
|
96
|
+
{ :spec => '08',
|
97
|
+
:host => Chef::Config[:amqp_host],
|
98
|
+
:port => Chef::Config[:amqp_port],
|
99
|
+
:user => Chef::Config[:amqp_user],
|
100
|
+
:pass => Chef::Config[:amqp_pass],
|
101
|
+
:vhost => Chef::Config[:amqp_vhost]}
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Daniel DeLeo (<dan@kallistec.com>)
|
3
|
+
# Copyright:: Copyright (c) 2009 Daniel DeLeo
|
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
|
+
class Chef
|
20
|
+
module IndexQueue
|
21
|
+
module Consumer
|
22
|
+
module ClassMethods
|
23
|
+
def expose(*methods)
|
24
|
+
@exposed_methods = Array(@exposed_methods)
|
25
|
+
@exposed_methods += methods
|
26
|
+
end
|
27
|
+
|
28
|
+
def exposed_methods
|
29
|
+
@exposed_methods || []
|
30
|
+
end
|
31
|
+
|
32
|
+
def whitelisted?(method_name)
|
33
|
+
exposed_methods.include?(method_name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.included(including_class)
|
38
|
+
including_class.send(:extend, ClassMethods)
|
39
|
+
end
|
40
|
+
|
41
|
+
def run
|
42
|
+
Chef::Log.debug("Starting Index Queue Consumer")
|
43
|
+
AmqpClient.instance.queue # triggers connection setup
|
44
|
+
|
45
|
+
begin
|
46
|
+
AmqpClient.instance.queue.subscribe(:ack => true, :timeout => false) do |message|
|
47
|
+
call_action_for_message(message)
|
48
|
+
end
|
49
|
+
rescue Bunny::ConnectionError, Errno::ECONNRESET, Bunny::ServerDownError
|
50
|
+
AmqpClient.instance.disconnected!
|
51
|
+
Chef::Log.warn "Connection to rabbitmq lost. attempting to reconnect"
|
52
|
+
sleep 1
|
53
|
+
retry
|
54
|
+
end
|
55
|
+
end
|
56
|
+
alias :start :run
|
57
|
+
|
58
|
+
def call_action_for_message(message)
|
59
|
+
amqp_payload = JSON.parse(message[:payload])
|
60
|
+
action = amqp_payload["action"].to_sym
|
61
|
+
app_payload = amqp_payload["payload"]
|
62
|
+
assert_method_whitelisted(action)
|
63
|
+
send(action, app_payload)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def assert_method_whitelisted(method_name)
|
69
|
+
unless self.class.whitelisted?(method_name)
|
70
|
+
raise ArgumentError, "non-exposed method #{method_name} called via index queue"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Daniel DeLeo (<dan@kallistec.com>)
|
3
|
+
# Copyright:: Copyright (c) 2009 Daniel DeLeo
|
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
|
+
class Chef
|
20
|
+
module IndexQueue
|
21
|
+
module Indexable
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
|
25
|
+
def index_object_type(explicit_type_name=nil)
|
26
|
+
@index_object_type = explicit_type_name.to_s if explicit_type_name
|
27
|
+
@index_object_type
|
28
|
+
end
|
29
|
+
|
30
|
+
# Resets all metadata used for indexing to nil. Used for testing
|
31
|
+
def reset_index_metadata!
|
32
|
+
@index_object_type = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.included(including_class)
|
38
|
+
including_class.send(:extend, ClassMethods)
|
39
|
+
end
|
40
|
+
|
41
|
+
attr_accessor :index_id
|
42
|
+
|
43
|
+
def index_object_type
|
44
|
+
self.class.index_object_type || Mixin::ConvertToClassName.snake_case_basename(self.class.name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def with_indexer_metadata(with_metadata={})
|
48
|
+
# changing input param symbol keys to strings, as the keys in hash that goes to solr are expected to be strings [cb]
|
49
|
+
with_metadata.each do |key,value|
|
50
|
+
with_metadata[key.to_s] = with_metadata.delete(key)
|
51
|
+
end
|
52
|
+
|
53
|
+
with_metadata["type"] ||= self.index_object_type
|
54
|
+
with_metadata["id"] ||= self.index_id
|
55
|
+
with_metadata["database"] ||= Chef::Config[:couchdb_database]
|
56
|
+
with_metadata["item"] ||= self
|
57
|
+
|
58
|
+
raise ArgumentError, "Type, Id, or Database missing in index operation: #{with_metadata.inspect}" if (with_metadata["id"].nil? or with_metadata["type"].nil?)
|
59
|
+
with_metadata
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_to_index(metadata={})
|
63
|
+
Chef::Log.debug("pushing item to index queue for addition: #{self.with_indexer_metadata(metadata)}")
|
64
|
+
AmqpClient.instance.send_action(:add, self.with_indexer_metadata(metadata))
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete_from_index(metadata={})
|
68
|
+
Chef::Log.debug("pushing item to index queue for deletion: #{self.with_indexer_metadata(metadata)}")
|
69
|
+
AmqpClient.instance.send_action(:delete, self.with_indexer_metadata(metadata))
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|