chef 0.7.10
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/LICENSE +201 -0
- data/README.rdoc +135 -0
- data/bin/chef-client +26 -0
- data/bin/chef-solo +26 -0
- data/lib/chef.rb +49 -0
- data/lib/chef/application.rb +98 -0
- data/lib/chef/application/agent.rb +18 -0
- data/lib/chef/application/client.rb +209 -0
- data/lib/chef/application/indexer.rb +141 -0
- data/lib/chef/application/server.rb +18 -0
- data/lib/chef/application/solo.rb +214 -0
- data/lib/chef/client.rb +396 -0
- data/lib/chef/compile.rb +138 -0
- data/lib/chef/config.rb +141 -0
- data/lib/chef/cookbook.rb +144 -0
- data/lib/chef/cookbook/metadata.rb +407 -0
- data/lib/chef/cookbook/metadata/version.rb +87 -0
- data/lib/chef/cookbook_loader.rb +168 -0
- data/lib/chef/couchdb.rb +172 -0
- data/lib/chef/daemon.rb +170 -0
- data/lib/chef/exceptions.rb +36 -0
- data/lib/chef/file_cache.rb +205 -0
- data/lib/chef/log.rb +39 -0
- data/lib/chef/mixin/check_helper.rb +31 -0
- data/lib/chef/mixin/checksum.rb +37 -0
- data/lib/chef/mixin/command.rb +351 -0
- data/lib/chef/mixin/create_path.rb +56 -0
- data/lib/chef/mixin/deep_merge.rb +36 -0
- data/lib/chef/mixin/find_preferred_file.rb +99 -0
- data/lib/chef/mixin/from_file.rb +36 -0
- data/lib/chef/mixin/generate_url.rb +48 -0
- data/lib/chef/mixin/language.rb +79 -0
- data/lib/chef/mixin/params_validate.rb +197 -0
- data/lib/chef/mixin/template.rb +84 -0
- data/lib/chef/node.rb +406 -0
- data/lib/chef/node/attribute.rb +412 -0
- data/lib/chef/openid_registration.rb +181 -0
- data/lib/chef/platform.rb +253 -0
- data/lib/chef/provider.rb +40 -0
- data/lib/chef/provider/cron.rb +137 -0
- data/lib/chef/provider/directory.rb +72 -0
- data/lib/chef/provider/execute.rb +58 -0
- data/lib/chef/provider/file.rb +191 -0
- data/lib/chef/provider/group.rb +120 -0
- data/lib/chef/provider/group/groupadd.rb +92 -0
- data/lib/chef/provider/group/pw.rb +88 -0
- data/lib/chef/provider/http_request.rb +102 -0
- data/lib/chef/provider/ifconfig.rb +131 -0
- data/lib/chef/provider/link.rb +157 -0
- data/lib/chef/provider/mount.rb +121 -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 +113 -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 +130 -0
- data/lib/chef/provider/package/yum-dump.py +104 -0
- data/lib/chef/provider/package/yum.rb +175 -0
- data/lib/chef/provider/remote_directory.rb +126 -0
- data/lib/chef/provider/remote_file.rb +134 -0
- data/lib/chef/provider/route.rb +118 -0
- data/lib/chef/provider/ruby_block.rb +15 -0
- data/lib/chef/provider/script.rb +42 -0
- data/lib/chef/provider/service.rb +129 -0
- data/lib/chef/provider/service/debian.rb +64 -0
- data/lib/chef/provider/service/freebsd.rb +157 -0
- data/lib/chef/provider/service/gentoo.rb +54 -0
- data/lib/chef/provider/service/init.rb +126 -0
- data/lib/chef/provider/service/redhat.rb +62 -0
- data/lib/chef/provider/template.rb +141 -0
- data/lib/chef/provider/user.rb +170 -0
- data/lib/chef/provider/user/pw.rb +113 -0
- data/lib/chef/provider/user/useradd.rb +107 -0
- data/lib/chef/queue.rb +145 -0
- data/lib/chef/recipe.rb +210 -0
- data/lib/chef/resource.rb +256 -0
- data/lib/chef/resource/apt_package.rb +34 -0
- data/lib/chef/resource/bash.rb +33 -0
- data/lib/chef/resource/cron.rb +143 -0
- data/lib/chef/resource/csh.rb +33 -0
- data/lib/chef/resource/directory.rb +76 -0
- data/lib/chef/resource/dpkg_package.rb +34 -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/group.rb +68 -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/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 +20 -0
- data/lib/chef/resource/script.rb +51 -0
- data/lib/chef/resource/service.rb +134 -0
- data/lib/chef/resource/template.rb +60 -0
- data/lib/chef/resource/user.rb +98 -0
- data/lib/chef/resource_collection.rb +176 -0
- data/lib/chef/resource_definition.rb +67 -0
- data/lib/chef/rest.rb +238 -0
- data/lib/chef/role.rb +231 -0
- data/lib/chef/run_list.rb +156 -0
- data/lib/chef/runner.rb +123 -0
- data/lib/chef/search.rb +88 -0
- data/lib/chef/search/result.rb +64 -0
- data/lib/chef/search_index.rb +77 -0
- data/lib/chef/tasks/chef_repo.rake +345 -0
- data/lib/chef/util/file_edit.rb +125 -0
- data/lib/chef/util/fileedit.rb +121 -0
- metadata +262 -0
@@ -0,0 +1,84 @@
|
|
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 'tempfile'
|
20
|
+
require 'erubis'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
module Mixin
|
24
|
+
module Template
|
25
|
+
|
26
|
+
# Render a template with Erubis. Takes a template as a string, and a
|
27
|
+
# context hash.
|
28
|
+
def render_template(template, context)
|
29
|
+
begin
|
30
|
+
eruby = Erubis::Eruby.new(template)
|
31
|
+
output = eruby.evaluate(context)
|
32
|
+
rescue Object => e
|
33
|
+
raise TemplateError.new(e, template, context)
|
34
|
+
end
|
35
|
+
final_tempfile = Tempfile.new("chef-rendered-template")
|
36
|
+
final_tempfile.print(output)
|
37
|
+
final_tempfile.close
|
38
|
+
final_tempfile
|
39
|
+
end
|
40
|
+
|
41
|
+
class TemplateError < RuntimeError
|
42
|
+
attr_reader :original_exception, :context
|
43
|
+
SOURCE_CONTEXT_WINDOW = 2 unless defined? SOURCE_CONTEXT_WINDOW
|
44
|
+
|
45
|
+
def initialize(original_exception, template, context)
|
46
|
+
@original_exception, @template, @context = original_exception, template, context
|
47
|
+
end
|
48
|
+
|
49
|
+
def message
|
50
|
+
@original_exception.message
|
51
|
+
end
|
52
|
+
|
53
|
+
def line_number
|
54
|
+
@line_number ||= $1.to_i if original_exception.backtrace.find {|line| line =~ /\(erubis\):(\d+)/ }
|
55
|
+
end
|
56
|
+
|
57
|
+
def source_location
|
58
|
+
"on line ##{line_number}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def source_listing
|
62
|
+
@source_listing ||= begin
|
63
|
+
line_index = line_number - 1
|
64
|
+
beginning_line = line_index <= SOURCE_CONTEXT_WINDOW ? 0 : line_index - SOURCE_CONTEXT_WINDOW
|
65
|
+
source_size = SOURCE_CONTEXT_WINDOW * 2 + 1
|
66
|
+
lines = @template.split(/\n/)
|
67
|
+
contextual_lines = lines[beginning_line, source_size]
|
68
|
+
output = []
|
69
|
+
contextual_lines.each_with_index do |line, index|
|
70
|
+
line_number = (index+beginning_line+1).to_s.rjust(3)
|
71
|
+
output << "#{line_number}: #{line}"
|
72
|
+
end
|
73
|
+
output.join("\n")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_s
|
78
|
+
"\n\n#{self.class} (#{message}) #{source_location}:\n\n" +
|
79
|
+
"#{source_listing}\n\n #{original_exception.backtrace.join("\n ")}\n\n"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/chef/node.rb
ADDED
@@ -0,0 +1,406 @@
|
|
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/config'
|
20
|
+
require 'chef/mixin/check_helper'
|
21
|
+
require 'chef/mixin/params_validate'
|
22
|
+
require 'chef/mixin/from_file'
|
23
|
+
require 'chef/couchdb'
|
24
|
+
require 'chef/queue'
|
25
|
+
require 'chef/run_list'
|
26
|
+
require 'chef/node/attribute'
|
27
|
+
require 'extlib'
|
28
|
+
require 'json'
|
29
|
+
|
30
|
+
class Chef
|
31
|
+
class Node
|
32
|
+
|
33
|
+
attr_accessor :attribute, :recipe_list, :couchdb_rev, :run_state, :run_list, :override, :default
|
34
|
+
|
35
|
+
include Chef::Mixin::CheckHelper
|
36
|
+
include Chef::Mixin::FromFile
|
37
|
+
include Chef::Mixin::ParamsValidate
|
38
|
+
|
39
|
+
DESIGN_DOCUMENT = {
|
40
|
+
"version" => 8,
|
41
|
+
"language" => "javascript",
|
42
|
+
"views" => {
|
43
|
+
"all" => {
|
44
|
+
"map" => <<-EOJS
|
45
|
+
function(doc) {
|
46
|
+
if (doc.chef_type == "node") {
|
47
|
+
emit(doc.name, doc);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
EOJS
|
51
|
+
},
|
52
|
+
"all_id" => {
|
53
|
+
"map" => <<-EOJS
|
54
|
+
function(doc) {
|
55
|
+
if (doc.chef_type == "node") {
|
56
|
+
emit(doc.name, doc.name);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
EOJS
|
60
|
+
},
|
61
|
+
"status" => {
|
62
|
+
"map" => <<-EOJS
|
63
|
+
function(doc) {
|
64
|
+
if (doc.chef_type == "node") {
|
65
|
+
var to_emit = { "name": doc.name };
|
66
|
+
if (doc["attributes"]["fqdn"]) {
|
67
|
+
to_emit["fqdn"] = doc["attributes"]["fqdn"];
|
68
|
+
} else {
|
69
|
+
to_emit["fqdn"] = "Undefined";
|
70
|
+
}
|
71
|
+
if (doc["attributes"]["ipaddress"]) {
|
72
|
+
to_emit["ipaddress"] = doc["attributes"]["ipaddress"];
|
73
|
+
} else {
|
74
|
+
to_emit["ipaddress"] = "Undefined";
|
75
|
+
}
|
76
|
+
if (doc["attributes"]["ohai_time"]) {
|
77
|
+
to_emit["ohai_time"] = doc["attributes"]["ohai_time"];
|
78
|
+
} else {
|
79
|
+
to_emit["ohai_time"] = "Undefined";
|
80
|
+
}
|
81
|
+
if (doc["attributes"]["uptime"]) {
|
82
|
+
to_emit["uptime"] = doc["attributes"]["uptime"];
|
83
|
+
} else {
|
84
|
+
to_emit["uptime"] = "Undefined";
|
85
|
+
}
|
86
|
+
if (doc["attributes"]["platform"]) {
|
87
|
+
to_emit["platform"] = doc["attributes"]["platform"];
|
88
|
+
} else {
|
89
|
+
to_emit["platform"] = "Undefined";
|
90
|
+
}
|
91
|
+
if (doc["attributes"]["platform_version"]) {
|
92
|
+
to_emit["platform_version"] = doc["attributes"]["platform_version"];
|
93
|
+
} else {
|
94
|
+
to_emit["platform_version"] = "Undefined";
|
95
|
+
}
|
96
|
+
if (doc["run_list"]) {
|
97
|
+
to_emit["run_list"] = doc["run_list"];
|
98
|
+
} else {
|
99
|
+
to_emit["run_list"] = "Undefined";
|
100
|
+
}
|
101
|
+
emit(doc.name, to_emit);
|
102
|
+
}
|
103
|
+
}
|
104
|
+
EOJS
|
105
|
+
},
|
106
|
+
"by_run_list" => {
|
107
|
+
"map" => <<-EOJS
|
108
|
+
function(doc) {
|
109
|
+
if (doc.chef_type == "node") {
|
110
|
+
if (doc['run_list']) {
|
111
|
+
for (var i=0; i < doc.run_list.length; i++) {
|
112
|
+
emit(doc['run_list'][i], doc.name);
|
113
|
+
}
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
EOJS
|
118
|
+
}
|
119
|
+
},
|
120
|
+
}
|
121
|
+
|
122
|
+
# Create a new Chef::Node object.
|
123
|
+
def initialize()
|
124
|
+
@name = nil
|
125
|
+
|
126
|
+
@attribute = Mash.new
|
127
|
+
@override = Mash.new
|
128
|
+
@default = Mash.new
|
129
|
+
@run_list = Chef::RunList.new
|
130
|
+
|
131
|
+
@couchdb_rev = nil
|
132
|
+
@couchdb = Chef::CouchDB.new
|
133
|
+
@run_state = {
|
134
|
+
:template_cache => Hash.new,
|
135
|
+
:seen_recipes => Hash.new
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
# Find a recipe for this Chef::Node by fqdn. Will search first for
|
140
|
+
# Chef::Config["node_path"]/fqdn.rb, then hostname.rb, then default.rb.
|
141
|
+
#
|
142
|
+
# Returns a new Chef::Node object.
|
143
|
+
#
|
144
|
+
# Raises an ArgumentError if it cannot find the node.
|
145
|
+
def find_file(fqdn)
|
146
|
+
node_file = nil
|
147
|
+
host_parts = fqdn.split(".")
|
148
|
+
hostname = host_parts[0]
|
149
|
+
|
150
|
+
if File.exists?(File.join(Chef::Config[:node_path], "#{fqdn}.rb"))
|
151
|
+
node_file = File.join(Chef::Config[:node_path], "#{fqdn}.rb")
|
152
|
+
elsif File.exists?(File.join(Chef::Config[:node_path], "#{hostname}.rb"))
|
153
|
+
node_file = File.join(Chef::Config[:node_path], "#{hostname}.rb")
|
154
|
+
elsif File.exists?(File.join(Chef::Config[:node_path], "default.rb"))
|
155
|
+
node_file = File.join(Chef::Config[:node_path], "default.rb")
|
156
|
+
end
|
157
|
+
unless node_file
|
158
|
+
raise ArgumentError, "Cannot find a node matching #{fqdn}, not even with default.rb!"
|
159
|
+
end
|
160
|
+
self.from_file(node_file)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Set the name of this Node, or return the current name.
|
164
|
+
def name(arg=nil)
|
165
|
+
if arg != nil
|
166
|
+
validate(
|
167
|
+
{ :name => arg },
|
168
|
+
{
|
169
|
+
:name => {
|
170
|
+
:kind_of => String
|
171
|
+
}
|
172
|
+
}
|
173
|
+
)
|
174
|
+
@name = arg
|
175
|
+
else
|
176
|
+
@name
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# Return an attribute of this node. Returns nil if the attribute is not found.
|
181
|
+
def [](attrib)
|
182
|
+
attrs = Chef::Node::Attribute.new(@attribute, @default, @override)
|
183
|
+
attrs[attrib]
|
184
|
+
end
|
185
|
+
|
186
|
+
# Set an attribute of this node
|
187
|
+
def []=(attrib, value)
|
188
|
+
attrs = Chef::Node::Attribute.new(@attribute, @default, @override)
|
189
|
+
attrs[attrib] = value
|
190
|
+
end
|
191
|
+
|
192
|
+
# Set an attribute of this node, but auto-vivifiy any Mashes that might
|
193
|
+
# be missing
|
194
|
+
def set
|
195
|
+
attrs = Chef::Node::Attribute.new(@attribute, @default, @override)
|
196
|
+
attrs.auto_vivifiy_on_read = true
|
197
|
+
attrs
|
198
|
+
end
|
199
|
+
|
200
|
+
# Set an attribute of this node, auto-vivifiying any mashes that are
|
201
|
+
# missing, but if the final value already exists, don't set it
|
202
|
+
def set_unless
|
203
|
+
attrs = Chef::Node::Attribute.new(@attribute, @default, @override)
|
204
|
+
attrs.auto_vivifiy_on_read = true
|
205
|
+
attrs.set_unless_value_present = true
|
206
|
+
attrs
|
207
|
+
end
|
208
|
+
|
209
|
+
alias_method :default, :set_unless
|
210
|
+
|
211
|
+
# Return true if this Node has a given attribute, false if not. Takes either a symbol or
|
212
|
+
# a string.
|
213
|
+
#
|
214
|
+
# Only works on the top level. Preferred way is to use the normal [] style
|
215
|
+
# lookup and call attribute?()
|
216
|
+
def attribute?(attrib)
|
217
|
+
attrs = Chef::Node::Attribute.new(@attribute, @default, @override)
|
218
|
+
attrs.attribute?(attrib)
|
219
|
+
end
|
220
|
+
|
221
|
+
# Yield each key of the top level to the block.
|
222
|
+
def each(&block)
|
223
|
+
attrs = Chef::Node::Attribute.new(@attribute, @default, @override)
|
224
|
+
attrs.each(&block)
|
225
|
+
end
|
226
|
+
|
227
|
+
# Iterates over each attribute, passing the attribute and value to the block.
|
228
|
+
def each_attribute(&block)
|
229
|
+
attrs = Chef::Node::Attribute.new(@attribute, @default, @override)
|
230
|
+
attrs.each_attribute(&block)
|
231
|
+
end
|
232
|
+
|
233
|
+
# Set an attribute based on the missing method. If you pass an argument, we'll use that
|
234
|
+
# to set the attribute values. Otherwise, we'll wind up just returning the attributes
|
235
|
+
# value.
|
236
|
+
def method_missing(symbol, *args)
|
237
|
+
attrs = Chef::Node::Attribute.new(@attribute, @default, @override)
|
238
|
+
attrs.send(symbol, *args)
|
239
|
+
end
|
240
|
+
|
241
|
+
# Returns true if this Node expects a given recipe, false if not.
|
242
|
+
def recipe?(recipe_name)
|
243
|
+
if @run_list.include?(recipe_name)
|
244
|
+
true
|
245
|
+
else
|
246
|
+
if @run_state[:seen_recipes].include?(recipe_name)
|
247
|
+
true
|
248
|
+
else
|
249
|
+
false
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
# Returns an Array of recipes. If you call it with arguments, they will become the new
|
255
|
+
# list of recipes.
|
256
|
+
def recipes(*args)
|
257
|
+
if args.length > 0
|
258
|
+
@run_list.reset(args)
|
259
|
+
else
|
260
|
+
@run_list
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Returns true if this Node expects a given role, false if not.
|
265
|
+
def role?(role_name)
|
266
|
+
@run_list.include?("role[#{role_name}]")
|
267
|
+
end
|
268
|
+
|
269
|
+
# Returns an Array of roles and recipes, in the order they will be applied.
|
270
|
+
# If you call it with arguments, they will become the new list of roles and recipes.
|
271
|
+
def run_list(*args)
|
272
|
+
if args.length > 0
|
273
|
+
@run_list.reset(args)
|
274
|
+
else
|
275
|
+
@run_list
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# Returns true if this Node expects a given role, false if not.
|
280
|
+
def run_list?(item)
|
281
|
+
@run_list.detect { |r| r == item } ? true : false
|
282
|
+
end
|
283
|
+
|
284
|
+
# Turns the node into an object that we can index. I apologize up front for the
|
285
|
+
# super confusion that is the recursive index_flatten hash, which comes up next.
|
286
|
+
# Faith, young one, faith.
|
287
|
+
#
|
288
|
+
# === Returns
|
289
|
+
# index_hash<Hash>:: A flattened hash of all the nodes attributes, suitable for indexing.
|
290
|
+
def to_index
|
291
|
+
index_hash = {
|
292
|
+
"index_name" => "node",
|
293
|
+
"id" => "node_#{@name}",
|
294
|
+
"name" => @name,
|
295
|
+
}
|
296
|
+
@attribute.each do |key, value|
|
297
|
+
if value.kind_of?(Hash) || value.kind_of?(Mash)
|
298
|
+
index_flatten_hash(key, value).each do |to_index|
|
299
|
+
to_index.each do |nk, nv|
|
300
|
+
index_hash[nk] = nv
|
301
|
+
end
|
302
|
+
end
|
303
|
+
else
|
304
|
+
index_hash[key] = value
|
305
|
+
end
|
306
|
+
end
|
307
|
+
index_hash["recipe"] = @run_list.recipes if @run_list.recipes.length > 0
|
308
|
+
index_hash["roles"] = @run_list.roles if @run_list.roles.length > 0
|
309
|
+
index_hash["run_list"] = @run_list.run_list if @run_list.run_list.length > 0
|
310
|
+
index_hash
|
311
|
+
end
|
312
|
+
|
313
|
+
# Ah, song of my heart, index_flatten_hash. This method flattens a hash in preparation
|
314
|
+
# for indexing, by appending the name of it's parent to a current key with an _. Hence,
|
315
|
+
# node[:bar][:baz] = 'monkey' becomes bar_baz:monkey.
|
316
|
+
#
|
317
|
+
# === Returns
|
318
|
+
# results<Array>:: An array of hashes with one element.
|
319
|
+
def index_flatten_hash(parent_name, hash)
|
320
|
+
results = Array.new
|
321
|
+
hash.each do |k, v|
|
322
|
+
if v.kind_of?(Hash) || v.kind_of?(Mash)
|
323
|
+
results << index_flatten_hash("#{parent_name}_#{k}", v)
|
324
|
+
else
|
325
|
+
results << { "#{parent_name}_#{k}", v }
|
326
|
+
end
|
327
|
+
end
|
328
|
+
results.flatten
|
329
|
+
end
|
330
|
+
|
331
|
+
# Serialize this object as a hash
|
332
|
+
def to_json(*a)
|
333
|
+
result = {
|
334
|
+
"name" => @name,
|
335
|
+
'json_class' => self.class.name,
|
336
|
+
"attributes" => @attribute,
|
337
|
+
"chef_type" => "node",
|
338
|
+
"run_list" => @run_list.run_list,
|
339
|
+
}
|
340
|
+
result["_rev"] = @couchdb_rev if @couchdb_rev
|
341
|
+
result.to_json(*a)
|
342
|
+
end
|
343
|
+
|
344
|
+
# Create a Chef::Node from JSON
|
345
|
+
def self.json_create(o)
|
346
|
+
node = new
|
347
|
+
node.name(o["name"])
|
348
|
+
o["attributes"].each do |k,v|
|
349
|
+
node[k] = v
|
350
|
+
end
|
351
|
+
if o.has_key?("defaults")
|
352
|
+
node.default = o["defaults"]
|
353
|
+
end
|
354
|
+
if o.has_key?("overrides")
|
355
|
+
node.override = o["overrides"]
|
356
|
+
end
|
357
|
+
if o.has_key?("run_list")
|
358
|
+
node.run_list.reset(o["run_list"])
|
359
|
+
else
|
360
|
+
o["recipes"].each { |r| node.recipes << r }
|
361
|
+
end
|
362
|
+
node.couchdb_rev = o["_rev"] if o.has_key?("_rev")
|
363
|
+
node
|
364
|
+
end
|
365
|
+
|
366
|
+
# List all the Chef::Node objects in the CouchDB. If inflate is set to true, you will get
|
367
|
+
# the full list of all Nodes, fully inflated.
|
368
|
+
def self.list(inflate=false)
|
369
|
+
rs = Chef::CouchDB.new.list("nodes", inflate)
|
370
|
+
if inflate
|
371
|
+
rs["rows"].collect { |r| r["value"] }
|
372
|
+
else
|
373
|
+
rs["rows"].collect { |r| r["key"] }
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
# Load a node by name from CouchDB
|
378
|
+
def self.load(name)
|
379
|
+
Chef::CouchDB.new.load("node", name)
|
380
|
+
end
|
381
|
+
|
382
|
+
# Remove this node from the CouchDB
|
383
|
+
def destroy
|
384
|
+
Chef::Queue.send_msg(:queue, :remove, self)
|
385
|
+
@couchdb.delete("node", @name, @couchdb_rev)
|
386
|
+
end
|
387
|
+
|
388
|
+
# Save this node to the CouchDB
|
389
|
+
def save
|
390
|
+
Chef::Queue.send_msg(:queue, :index, self)
|
391
|
+
results = @couchdb.store("node", @name, self)
|
392
|
+
@couchdb_rev = results["rev"]
|
393
|
+
end
|
394
|
+
|
395
|
+
# Set up our CouchDB design document
|
396
|
+
def self.create_design_document
|
397
|
+
Chef::CouchDB.new.create_design_document("nodes", DESIGN_DOCUMENT)
|
398
|
+
end
|
399
|
+
|
400
|
+
# As a string
|
401
|
+
def to_s
|
402
|
+
"node[#{@name}]"
|
403
|
+
end
|
404
|
+
|
405
|
+
end
|
406
|
+
end
|