giraffesoft-chef 0.7.15
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +201 -0
- data/README.rdoc +135 -0
- data/bin/chef-client +26 -0
- data/bin/chef-solo +26 -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/debian/man/man1/chef-indexer.1 +42 -0
- data/distro/debian/man/man1/chef-server.1 +108 -0
- data/distro/debian/man/man8/chef-client.8 +61 -0
- data/distro/debian/man/man8/chef-solo.8 +58 -0
- data/distro/redhat/etc/chef/client.rb +16 -0
- data/distro/redhat/etc/chef/indexer.rb +10 -0
- data/distro/redhat/etc/chef/server.rb +22 -0
- data/distro/redhat/etc/init.d/chef-client +74 -0
- data/distro/redhat/etc/init.d/chef-indexer +76 -0
- data/distro/redhat/etc/init.d/chef-server +77 -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 +421 -0
- data/lib/chef/compile.rb +170 -0
- data/lib/chef/config.rb +141 -0
- data/lib/chef/cookbook.rb +171 -0
- data/lib/chef/cookbook/metadata.rb +407 -0
- data/lib/chef/cookbook/metadata/version.rb +87 -0
- data/lib/chef/cookbook_loader.rb +180 -0
- data/lib/chef/couchdb.rb +176 -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 +386 -0
- data/lib/chef/mixin/convert_to_class_name.rb +48 -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 +92 -0
- data/lib/chef/mixin/from_file.rb +50 -0
- data/lib/chef/mixin/generate_url.rb +49 -0
- data/lib/chef/mixin/language.rb +79 -0
- data/lib/chef/mixin/params_validate.rb +197 -0
- data/lib/chef/mixin/recipe_definition_dsl_core.rb +77 -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 +254 -0
- data/lib/chef/provider.rb +101 -0
- data/lib/chef/provider/cron.rb +187 -0
- data/lib/chef/provider/deploy.rb +281 -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/execute.rb +58 -0
- data/lib/chef/provider/file.rb +191 -0
- data/lib/chef/provider/git.rb +198 -0
- data/lib/chef/provider/group.rb +120 -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 +102 -0
- data/lib/chef/provider/ifconfig.rb +131 -0
- data/lib/chef/provider/link.rb +157 -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/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 +106 -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 +141 -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 +135 -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 +71 -0
- data/lib/chef/provider/service/redhat.rb +62 -0
- data/lib/chef/provider/service/simple.rb +115 -0
- data/lib/chef/provider/subversion.rb +148 -0
- data/lib/chef/provider/template.rb +143 -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 +144 -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/cron.rb +179 -0
- data/lib/chef/resource/csh.rb +33 -0
- data/lib/chef/resource/deploy.rb +350 -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/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/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/scm.rb +129 -0
- data/lib/chef/resource/script.rb +51 -0
- data/lib/chef/resource/service.rb +134 -0
- data/lib/chef/resource/subversion.rb +33 -0
- data/lib/chef/resource/template.rb +60 -0
- data/lib/chef/resource/timestamped_deploy.rb +31 -0
- data/lib/chef/resource/user.rb +98 -0
- data/lib/chef/resource_collection.rb +204 -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 +130 -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 +347 -0
- data/lib/chef/util/file_edit.rb +125 -0
- data/lib/chef/util/fileedit.rb +121 -0
- metadata +293 -0
data/lib/chef/queue.rb
ADDED
@@ -0,0 +1,145 @@
|
|
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/mixin/params_validate'
|
20
|
+
require 'json'
|
21
|
+
require 'stomp'
|
22
|
+
|
23
|
+
class Chef
|
24
|
+
class Queue
|
25
|
+
|
26
|
+
@client = nil
|
27
|
+
@queue_retry_delay = Chef::Config[:queue_retry_delay]
|
28
|
+
@queue_retry_count = Chef::Config[:queue_retry_count]
|
29
|
+
|
30
|
+
class << self
|
31
|
+
include Chef::Mixin::ParamsValidate
|
32
|
+
|
33
|
+
def connect
|
34
|
+
queue_user = Chef::Config[:queue_user]
|
35
|
+
queue_password = Chef::Config[:queue_password]
|
36
|
+
queue_host = Chef::Config[:queue_host]
|
37
|
+
queue_port = Chef::Config[:queue_port]
|
38
|
+
queue_retries = 1 unless queue_retries
|
39
|
+
|
40
|
+
# Connection.open(login = "", passcode = "", host='localhost', port=61613, reliable=FALSE, reconnectDelay=5)
|
41
|
+
@client = Stomp::Connection.open(queue_user, queue_password, queue_host, queue_port, false)
|
42
|
+
|
43
|
+
rescue Errno::ECONNREFUSED
|
44
|
+
Chef::Log.error("Connection refused connecting to stomp queue at #{queue_host}:#{queue_port}, retry #{queue_retries}/#{@queue_retry_count}")
|
45
|
+
sleep(@queue_retry_delay)
|
46
|
+
retry if (queue_retries += 1) < @queue_retry_count
|
47
|
+
raise Errno::ECONNREFUSED, "Connection refused connecting to stomp queue at #{queue_host}:#{queue_port}, giving up"
|
48
|
+
rescue Timeout::Error
|
49
|
+
Chef::Log.error("Timeout connecting to stomp queue at #{queue_host}:#{queue_port}, retry #{queue_retries}/#{@queue_retry_count}")
|
50
|
+
sleep(@queue_retry_delay)
|
51
|
+
retry if (queue_retries += 1) < @queue_retry_count
|
52
|
+
raise Timeout::Error, "Timeout connecting to stomp queue at #{queue_host}:#{queue_port}, giving up"
|
53
|
+
else
|
54
|
+
queue_retries = 1 # reset the number of retries on success
|
55
|
+
end
|
56
|
+
|
57
|
+
def make_url(type, name)
|
58
|
+
validate(
|
59
|
+
{
|
60
|
+
:queue_type => type.to_sym,
|
61
|
+
:queue_name => name.to_sym,
|
62
|
+
},
|
63
|
+
{
|
64
|
+
:queue_type => {
|
65
|
+
:equal_to => [ :topic, :queue ],
|
66
|
+
},
|
67
|
+
:queue_name => {
|
68
|
+
:kind_of => [ String, Symbol ],
|
69
|
+
}
|
70
|
+
}
|
71
|
+
)
|
72
|
+
if Chef::Config[:queue_prefix]
|
73
|
+
queue_prefix = Chef::Config[:queue_prefix]
|
74
|
+
queue_url = "/#{type}/#{queue_prefix}/chef/#{name}"
|
75
|
+
else
|
76
|
+
queue_url = "/#{type}/chef/#{name}"
|
77
|
+
end
|
78
|
+
queue_url
|
79
|
+
end
|
80
|
+
|
81
|
+
def subscribe(type, name)
|
82
|
+
queue_url = make_url(type, name)
|
83
|
+
Chef::Log.debug("Subscribing to #{queue_url}")
|
84
|
+
connect if @client == nil
|
85
|
+
@client.subscribe(queue_url)
|
86
|
+
end
|
87
|
+
|
88
|
+
def send_msg(type, name, msg)
|
89
|
+
queue_retries = 1 unless queue_retries
|
90
|
+
validate(
|
91
|
+
{
|
92
|
+
:message => msg,
|
93
|
+
},
|
94
|
+
{
|
95
|
+
:message => {
|
96
|
+
:respond_to => :to_json
|
97
|
+
}
|
98
|
+
}
|
99
|
+
)
|
100
|
+
queue_url = make_url(type, name)
|
101
|
+
json = msg.to_json
|
102
|
+
connect if @client == nil
|
103
|
+
Chef::Log.debug("Sending to #{queue_url}: #{json}")
|
104
|
+
begin
|
105
|
+
@client.send(queue_url, json)
|
106
|
+
rescue Errno::EPIPE
|
107
|
+
Chef::Log.debug("Lost connection to stomp queue, reconnecting")
|
108
|
+
connect
|
109
|
+
retry if (queue_retries += 1) < @queue_retry_count
|
110
|
+
raise Errno::EPIPE, "Lost connection to stomp queue, giving up"
|
111
|
+
else
|
112
|
+
queue_retries = 1 # reset the number of retries on success
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def receive_msg
|
117
|
+
connect if @client == nil
|
118
|
+
begin
|
119
|
+
raw_msg = @client.receive()
|
120
|
+
Chef::Log.debug("Received Message from #{raw_msg.headers["destination"]} containing: #{raw_msg.body}")
|
121
|
+
rescue
|
122
|
+
Chef::Log.debug("Received nil message from stomp, retrying")
|
123
|
+
retry
|
124
|
+
end
|
125
|
+
msg = JSON.parse(raw_msg.body)
|
126
|
+
return msg, raw_msg.headers
|
127
|
+
end
|
128
|
+
|
129
|
+
def poll_msg
|
130
|
+
connect if @client == nil
|
131
|
+
raw_msg = @client.poll()
|
132
|
+
if raw_msg
|
133
|
+
msg = JSON.parse(raw_msg.body)
|
134
|
+
else
|
135
|
+
nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def disconnect
|
140
|
+
raise ArgumentError, "You must call connect before you can disconnect!" unless @client
|
141
|
+
@client.disconnect
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/chef/recipe.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Author:: Christopher Walters (<cw@opscode.com>)
|
4
|
+
# Copyright:: Copyright (c) 2008, 2009 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'chef/resource'
|
21
|
+
Dir[File.join(File.dirname(__FILE__), 'resource/**/*.rb')].sort.each { |lib| require lib }
|
22
|
+
require 'chef/mixin/from_file'
|
23
|
+
require 'chef/mixin/language'
|
24
|
+
require 'chef/mixin/recipe_definition_dsl_core'
|
25
|
+
require 'chef/resource_collection'
|
26
|
+
require 'chef/cookbook_loader'
|
27
|
+
require 'chef/rest'
|
28
|
+
require 'chef/search/result'
|
29
|
+
|
30
|
+
class Chef
|
31
|
+
class Recipe
|
32
|
+
|
33
|
+
include Chef::Mixin::FromFile
|
34
|
+
include Chef::Mixin::Language
|
35
|
+
include Chef::Mixin::RecipeDefinitionDSLCore
|
36
|
+
|
37
|
+
attr_accessor :cookbook_name, :recipe_name, :recipe, :node, :collection,
|
38
|
+
:definitions, :params, :cookbook_loader
|
39
|
+
|
40
|
+
def initialize(cookbook_name, recipe_name, node, collection=nil, definitions=nil, cookbook_loader=nil)
|
41
|
+
@cookbook_name = cookbook_name
|
42
|
+
@recipe_name = recipe_name
|
43
|
+
@node = node
|
44
|
+
@collection = collection || Chef::ResourceCollection.new
|
45
|
+
@definitions = definitions || Hash.new
|
46
|
+
@cookbook_loader = cookbook_loader || Chef::CookbookLoader.new
|
47
|
+
@params = Hash.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def include_recipe(*args)
|
51
|
+
args.flatten.each do |recipe|
|
52
|
+
if @node.run_state[:seen_recipes].has_key?(recipe)
|
53
|
+
Chef::Log.debug("I am not loading #{recipe}, because I have already seen it.")
|
54
|
+
next
|
55
|
+
end
|
56
|
+
|
57
|
+
Chef::Log.debug("Loading Recipe #{recipe} via include_recipe")
|
58
|
+
@node.run_state[:seen_recipes][recipe] = true
|
59
|
+
|
60
|
+
rmatch = recipe.match(/(.+?)::(.+)/)
|
61
|
+
if rmatch
|
62
|
+
cookbook = @cookbook_loader[rmatch[1]]
|
63
|
+
cookbook.load_recipe(rmatch[2], @node, @collection, @definitions, @cookbook_loader)
|
64
|
+
else
|
65
|
+
cookbook = @cookbook_loader[recipe]
|
66
|
+
cookbook.load_recipe("default", @node, @collection, @definitions, @cookbook_loader)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def require_recipe(*args)
|
72
|
+
include_recipe(*args)
|
73
|
+
end
|
74
|
+
|
75
|
+
def resources(*args)
|
76
|
+
@collection.resources(*args)
|
77
|
+
end
|
78
|
+
|
79
|
+
def search(type, query, attributes=[], &block)
|
80
|
+
Chef::Log.debug("Searching #{type} index with #{query}")
|
81
|
+
r = Chef::REST.new(Chef::Config[:search_url])
|
82
|
+
|
83
|
+
results = r.get_rest("search/#{type}?q=#{query}&a=#{attributes.join(',')}")
|
84
|
+
Chef::Log.debug("Searching #{type} index with #{query} returned #{results.length} entries")
|
85
|
+
if block
|
86
|
+
results.each do |sr|
|
87
|
+
block.call(sr)
|
88
|
+
end
|
89
|
+
else
|
90
|
+
results
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Sets a tag, or list of tags, for this node. Syntactic sugar for
|
95
|
+
# @node[:tags].
|
96
|
+
#
|
97
|
+
# With no arguments, returns the list of tags.
|
98
|
+
#
|
99
|
+
# === Parameters
|
100
|
+
# tags<Array>:: A list of tags to add - can be a single string
|
101
|
+
#
|
102
|
+
# === Returns
|
103
|
+
# tags<Array>:: The contents of @node[:tags]
|
104
|
+
def tag(*args)
|
105
|
+
if args.length > 0
|
106
|
+
args.each do |tag|
|
107
|
+
@node[:tags] << tag unless @node[:tags].include?(tag)
|
108
|
+
end
|
109
|
+
@node[:tags]
|
110
|
+
else
|
111
|
+
@node[:tags]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns true if the node is tagged with the supplied list of tags.
|
116
|
+
#
|
117
|
+
# === Parameters
|
118
|
+
# tags<Array>:: A list of tags
|
119
|
+
#
|
120
|
+
# === Returns
|
121
|
+
# true<TrueClass>:: If all the parameters are present
|
122
|
+
# false<FalseClass>:: If any of the parameters are missing
|
123
|
+
def tagged?(*args)
|
124
|
+
args.each do |tag|
|
125
|
+
return false unless @node[:tags].include?(tag)
|
126
|
+
end
|
127
|
+
true
|
128
|
+
end
|
129
|
+
|
130
|
+
# Removes the list of tags from the node.
|
131
|
+
#
|
132
|
+
# === Parameters
|
133
|
+
# tags<Array>:: A list of tags
|
134
|
+
#
|
135
|
+
# === Returns
|
136
|
+
# tags<Array>:: The current list of @node[:tags]
|
137
|
+
def untag(*args)
|
138
|
+
args.each do |tag|
|
139
|
+
@node[:tags].delete(tag)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,380 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Author:: Christopher Walters (<cw@opscode.com>)
|
4
|
+
# Copyright:: Copyright (c) 2008 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'chef/mixin/params_validate'
|
21
|
+
require 'chef/mixin/check_helper'
|
22
|
+
require 'chef/mixin/language'
|
23
|
+
require 'chef/mixin/convert_to_class_name'
|
24
|
+
require 'chef/resource_collection'
|
25
|
+
require 'chef/node'
|
26
|
+
|
27
|
+
class Chef
|
28
|
+
class Resource
|
29
|
+
|
30
|
+
include Chef::Mixin::CheckHelper
|
31
|
+
include Chef::Mixin::ParamsValidate
|
32
|
+
include Chef::Mixin::Language
|
33
|
+
include Chef::Mixin::ConvertToClassName
|
34
|
+
|
35
|
+
attr_accessor :actions, :params, :provider, :updated, :allowed_actions, :collection, :cookbook_name, :recipe_name, :enclosing_provider
|
36
|
+
attr_reader :resource_name, :source_line, :node
|
37
|
+
|
38
|
+
def initialize(name, collection=nil, node=nil)
|
39
|
+
@name = name
|
40
|
+
if collection
|
41
|
+
@collection = collection
|
42
|
+
else
|
43
|
+
@collection = Chef::ResourceCollection.new()
|
44
|
+
end
|
45
|
+
@node = node ? node : Chef::Node.new
|
46
|
+
@noop = nil
|
47
|
+
@before = nil
|
48
|
+
@actions = Hash.new
|
49
|
+
@params = Hash.new
|
50
|
+
@provider = nil
|
51
|
+
@allowed_actions = [ :nothing ]
|
52
|
+
@action = :nothing
|
53
|
+
@updated = false
|
54
|
+
@supports = {}
|
55
|
+
@ignore_failure = false
|
56
|
+
@not_if = nil
|
57
|
+
@only_if = nil
|
58
|
+
sline = caller(4).shift
|
59
|
+
if sline
|
60
|
+
@source_line = sline.gsub!(/^(.+):(.+):.+$/, '\1 line \2')
|
61
|
+
@source_line = ::File.expand_path(@source_line) if @source_line
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# If an unknown method is invoked, determine whether the enclosing Provider's
|
66
|
+
# lexical scope can fulfill the request. E.g. This happens when the Resource's
|
67
|
+
# block invokes new_resource.
|
68
|
+
def method_missing(method_symbol, *args, &block)
|
69
|
+
if enclosing_provider && enclosing_provider.respond_to?(method_symbol)
|
70
|
+
enclosing_provider.send(method_symbol, *args, &block)
|
71
|
+
else
|
72
|
+
raise NoMethodError, "undefined method `#{method_symbol.to_s}' for #{self.class.to_s}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def load_prior_resource
|
77
|
+
begin
|
78
|
+
prior_resource = @collection.lookup(self.to_s)
|
79
|
+
Chef::Log.debug("Setting #{self.to_s} to the state of the prior #{self.to_s}")
|
80
|
+
prior_resource.instance_variables.each do |iv|
|
81
|
+
unless iv == "@source_line" || iv == "@action"
|
82
|
+
self.instance_variable_set(iv, prior_resource.instance_variable_get(iv))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
true
|
86
|
+
rescue ArgumentError => e
|
87
|
+
true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def supports(args={})
|
92
|
+
if args.any?
|
93
|
+
@supports = args
|
94
|
+
else
|
95
|
+
@supports
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def provider(arg=nil)
|
100
|
+
klass = if arg.kind_of?(String) || arg.kind_of?(Symbol)
|
101
|
+
lookup_provider_constant(arg)
|
102
|
+
else
|
103
|
+
arg
|
104
|
+
end
|
105
|
+
set_or_return(
|
106
|
+
:provider,
|
107
|
+
klass,
|
108
|
+
:kind_of => [ Class ]
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
def action(arg=nil)
|
113
|
+
if arg
|
114
|
+
action_list = arg.kind_of?(Array) ? arg : [ arg ]
|
115
|
+
action_list = action_list.collect { |a| a.to_sym }
|
116
|
+
action_list.each do |action|
|
117
|
+
validate(
|
118
|
+
{
|
119
|
+
:action => action,
|
120
|
+
},
|
121
|
+
{
|
122
|
+
:action => { :kind_of => Symbol, :equal_to => @allowed_actions },
|
123
|
+
}
|
124
|
+
)
|
125
|
+
end
|
126
|
+
@action = action_list
|
127
|
+
else
|
128
|
+
@action
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def name(name=nil)
|
133
|
+
set_if_args(@name, name) do
|
134
|
+
raise ArgumentError, "name must be a string!" unless name.kind_of?(String)
|
135
|
+
@name = name
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def noop(tf=nil)
|
140
|
+
set_if_args(@noop, tf) do
|
141
|
+
raise ArgumentError, "noop must be true or false!" unless tf == true || tf == false
|
142
|
+
@noop = tf
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def ignore_failure(arg=nil)
|
147
|
+
set_or_return(
|
148
|
+
:ignore_failure,
|
149
|
+
arg,
|
150
|
+
:kind_of => [ TrueClass, FalseClass ]
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
def epic_fail(arg=nil)
|
155
|
+
ignore_failure(arg)
|
156
|
+
end
|
157
|
+
|
158
|
+
def notifies(*args)
|
159
|
+
raise ArgumentError, "Wrong number of arguments (should be 1, 2, or 3)" unless ( args.size > 0 && args.size < 4)
|
160
|
+
if args.size > 1
|
161
|
+
notifies_helper(*args)
|
162
|
+
else
|
163
|
+
resources_array = *args
|
164
|
+
resources_array.each do |resource|
|
165
|
+
resource.each do |key, value|
|
166
|
+
notifies_helper(value[0], key, value[1])
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def resources(*args)
|
173
|
+
@collection.resources(*args)
|
174
|
+
end
|
175
|
+
|
176
|
+
def subscribes(action, resources, timing=:delayed)
|
177
|
+
timing = check_timing(timing)
|
178
|
+
rarray = resources.kind_of?(Array) ? resources : [ resources ]
|
179
|
+
rarray.each do |resource|
|
180
|
+
action_sym = action.to_sym
|
181
|
+
if resource.actions.has_key?(action_sym)
|
182
|
+
resource.actions[action_sym][timing] << self
|
183
|
+
else
|
184
|
+
resource.actions[action_sym] = Hash.new
|
185
|
+
resource.actions[action_sym][:delayed] = Array.new
|
186
|
+
resource.actions[action_sym][:immediate] = Array.new
|
187
|
+
resource.actions[action_sym][timing] << self
|
188
|
+
end
|
189
|
+
end
|
190
|
+
true
|
191
|
+
end
|
192
|
+
|
193
|
+
def is(*args)
|
194
|
+
return *args
|
195
|
+
end
|
196
|
+
|
197
|
+
def to_s
|
198
|
+
"#{@resource_name}[#{@name}]"
|
199
|
+
end
|
200
|
+
|
201
|
+
# Serialize this object as a hash
|
202
|
+
def to_json(*a)
|
203
|
+
instance_vars = Hash.new
|
204
|
+
self.instance_variables.each do |iv|
|
205
|
+
instance_vars[iv] = self.instance_variable_get(iv) unless iv == "@collection"
|
206
|
+
end
|
207
|
+
results = {
|
208
|
+
'json_class' => self.class.name,
|
209
|
+
'instance_vars' => instance_vars
|
210
|
+
}
|
211
|
+
results.to_json(*a)
|
212
|
+
end
|
213
|
+
|
214
|
+
def to_hash
|
215
|
+
instance_vars = Hash.new
|
216
|
+
self.instance_variables.each do |iv|
|
217
|
+
instance_vars[iv.sub(/^@/,'').to_sym] = self.instance_variable_get(iv) unless iv == "@collection"
|
218
|
+
end
|
219
|
+
instance_vars
|
220
|
+
end
|
221
|
+
|
222
|
+
def only_if(arg=nil, &blk)
|
223
|
+
if Kernel.block_given?
|
224
|
+
@only_if = blk
|
225
|
+
else
|
226
|
+
@only_if = arg if arg
|
227
|
+
end
|
228
|
+
@only_if
|
229
|
+
end
|
230
|
+
|
231
|
+
def not_if(arg=nil, &blk)
|
232
|
+
if Kernel.block_given?
|
233
|
+
@not_if = blk
|
234
|
+
else
|
235
|
+
@not_if = arg if arg
|
236
|
+
end
|
237
|
+
@not_if
|
238
|
+
end
|
239
|
+
|
240
|
+
def run_action(action)
|
241
|
+
provider = Chef::Platform.provider_for_node(@node, self)
|
242
|
+
provider.load_current_resource
|
243
|
+
provider.send("action_#{action}")
|
244
|
+
end
|
245
|
+
|
246
|
+
class << self
|
247
|
+
|
248
|
+
def json_create(o)
|
249
|
+
resource = self.new(o["instance_vars"]["@name"])
|
250
|
+
o["instance_vars"].each do |k,v|
|
251
|
+
resource.instance_variable_set(k.to_sym, v)
|
252
|
+
end
|
253
|
+
resource
|
254
|
+
end
|
255
|
+
|
256
|
+
include Chef::Mixin::ConvertToClassName
|
257
|
+
|
258
|
+
def attribute(attr_name, validation_opts={})
|
259
|
+
# This atrocity is the only way to support 1.8 and 1.9 at the same time
|
260
|
+
# When you're ready to drop 1.8 support, do this:
|
261
|
+
# define_method attr_name.to_sym do |arg=nil|
|
262
|
+
# etc.
|
263
|
+
shim_method=<<-SHIM
|
264
|
+
def #{attr_name}(arg=nil)
|
265
|
+
_set_or_return_#{attr_name}(arg)
|
266
|
+
end
|
267
|
+
SHIM
|
268
|
+
class_eval(shim_method)
|
269
|
+
|
270
|
+
define_method("_set_or_return_#{attr_name.to_s}".to_sym) do |arg|
|
271
|
+
set_or_return(attr_name.to_sym, arg, validation_opts)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def build_from_file(cookbook_name, filename)
|
276
|
+
rname = filename_to_qualified_string(cookbook_name, filename)
|
277
|
+
|
278
|
+
new_resource_class = Class.new self do |cls|
|
279
|
+
|
280
|
+
# default initialize method that ensures that when initialize is finally
|
281
|
+
# wrapped (see below), super is called in the event that the resource
|
282
|
+
# definer does not implement initialize
|
283
|
+
def initialize(name, collection=nil, node=nil)
|
284
|
+
super(name, collection, node)
|
285
|
+
end
|
286
|
+
|
287
|
+
@actions_to_create = []
|
288
|
+
|
289
|
+
class << cls
|
290
|
+
include Chef::Mixin::FromFile
|
291
|
+
|
292
|
+
def actions_to_create
|
293
|
+
@actions_to_create
|
294
|
+
end
|
295
|
+
|
296
|
+
define_method(:actions) do |*action_names|
|
297
|
+
actions_to_create.push(*action_names)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# load resource definition from file
|
302
|
+
cls.class_from_file(filename)
|
303
|
+
|
304
|
+
# create a new constructor that wraps the old one and adds the actions
|
305
|
+
# specified in the DSL
|
306
|
+
old_init = instance_method(:initialize)
|
307
|
+
|
308
|
+
define_method(:initialize) do |name, *optional_args|
|
309
|
+
collection = optional_args.shift
|
310
|
+
node = optional_args.shift
|
311
|
+
@resource_name = rname.to_sym
|
312
|
+
old_init.bind(self).call(name, collection, node)
|
313
|
+
allowed_actions.push(self.class.actions_to_create).flatten!
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
# register new class as a Chef::Resource
|
318
|
+
class_name = convert_to_class_name(rname)
|
319
|
+
Chef::Resource.const_set(class_name, new_resource_class)
|
320
|
+
Chef::Log.debug("Loaded contents of #{filename} into a resource named #{rname} defined in Chef::Resource::#{class_name}")
|
321
|
+
|
322
|
+
new_resource_class
|
323
|
+
end
|
324
|
+
|
325
|
+
# Resources that want providers namespaced somewhere other than
|
326
|
+
# Chef::Provider can set the namespace with +provider_base+
|
327
|
+
# Ex:
|
328
|
+
# class MyResource < Chef::Resource
|
329
|
+
# provider_base Chef::Provider::Deploy
|
330
|
+
# # ...other stuff
|
331
|
+
# end
|
332
|
+
def provider_base(arg=nil)
|
333
|
+
@provider_base ||= arg
|
334
|
+
@provider_base ||= Chef::Provider
|
335
|
+
end
|
336
|
+
|
337
|
+
end
|
338
|
+
|
339
|
+
private
|
340
|
+
|
341
|
+
def lookup_provider_constant(name)
|
342
|
+
begin
|
343
|
+
self.class.provider_base.const_get(convert_to_class_name(name.to_s))
|
344
|
+
rescue NameError => e
|
345
|
+
if e.to_s =~ /#{self.class.provider_base.to_s}/
|
346
|
+
raise ArgumentError, "No provider found to match '#{name}'"
|
347
|
+
else
|
348
|
+
raise e
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
def check_timing(timing)
|
354
|
+
unless timing == :delayed || timing == :immediate || timing == :immediately
|
355
|
+
raise ArgumentError, "Timing must be :delayed or :immediate(ly), you said #{timing}"
|
356
|
+
end
|
357
|
+
if timing == :immediately
|
358
|
+
timing = :immediate
|
359
|
+
end
|
360
|
+
timing
|
361
|
+
end
|
362
|
+
|
363
|
+
def notifies_helper(action, resources, timing=:delayed)
|
364
|
+
timing = check_timing(timing)
|
365
|
+
rarray = resources.kind_of?(Array) ? resources : [ resources ]
|
366
|
+
rarray.each do |resource|
|
367
|
+
action_sym = action.to_sym
|
368
|
+
if @actions.has_key?(action_sym)
|
369
|
+
@actions[action_sym][timing] << resource
|
370
|
+
else
|
371
|
+
@actions[action_sym] = Hash.new
|
372
|
+
@actions[action_sym][:delayed] = Array.new
|
373
|
+
@actions[action_sym][:immediate] = Array.new
|
374
|
+
@actions[action_sym][timing] << resource
|
375
|
+
end
|
376
|
+
end
|
377
|
+
true
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|