runa-chef 0.8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. data/LICENSE +201 -0
  2. data/README.rdoc +136 -0
  3. data/bin/chef-client +26 -0
  4. data/bin/chef-solo +26 -0
  5. data/bin/knife +27 -0
  6. data/bin/shef +45 -0
  7. data/distro/README +2 -0
  8. data/distro/common/man/man1/chef-indexer.1 +42 -0
  9. data/distro/common/man/man1/chef-server.1 +108 -0
  10. data/distro/common/man/man8/chef-client.8 +61 -0
  11. data/distro/common/man/man8/chef-solo.8 +58 -0
  12. data/distro/common/man/man8/knife.8 +359 -0
  13. data/distro/debian/etc/init.d/chef-client +175 -0
  14. data/distro/debian/etc/init.d/chef-indexer +175 -0
  15. data/distro/debian/etc/init.d/chef-server +120 -0
  16. data/distro/redhat/etc/init.d/chef-client +78 -0
  17. data/distro/redhat/etc/init.d/chef-indexer +76 -0
  18. data/distro/redhat/etc/init.d/chef-server +78 -0
  19. data/distro/redhat/etc/sysconfig/chef-client +10 -0
  20. data/distro/redhat/etc/sysconfig/chef-indexer +8 -0
  21. data/distro/redhat/etc/sysconfig/chef-server +10 -0
  22. data/distro/suse/etc/init.d/chef-client +121 -0
  23. data/lib/chef.rb +49 -0
  24. data/lib/chef/api_client.rb +269 -0
  25. data/lib/chef/application.rb +98 -0
  26. data/lib/chef/application/agent.rb +18 -0
  27. data/lib/chef/application/client.rb +214 -0
  28. data/lib/chef/application/knife.rb +138 -0
  29. data/lib/chef/application/server.rb +19 -0
  30. data/lib/chef/application/solo.rb +214 -0
  31. data/lib/chef/cache.rb +61 -0
  32. data/lib/chef/cache/checksum.rb +70 -0
  33. data/lib/chef/certificate.rb +154 -0
  34. data/lib/chef/client.rb +323 -0
  35. data/lib/chef/compile.rb +158 -0
  36. data/lib/chef/config.rb +195 -0
  37. data/lib/chef/cookbook.rb +198 -0
  38. data/lib/chef/cookbook/metadata.rb +487 -0
  39. data/lib/chef/cookbook/metadata/version.rb +87 -0
  40. data/lib/chef/cookbook_loader.rb +180 -0
  41. data/lib/chef/couchdb.rb +273 -0
  42. data/lib/chef/daemon.rb +170 -0
  43. data/lib/chef/data_bag.rb +216 -0
  44. data/lib/chef/data_bag_item.rb +227 -0
  45. data/lib/chef/exceptions.rb +39 -0
  46. data/lib/chef/file_cache.rb +205 -0
  47. data/lib/chef/knife.rb +300 -0
  48. data/lib/chef/knife/client_bulk_delete.rb +41 -0
  49. data/lib/chef/knife/client_create.rb +55 -0
  50. data/lib/chef/knife/client_delete.rb +37 -0
  51. data/lib/chef/knife/client_edit.rb +37 -0
  52. data/lib/chef/knife/client_list.rb +40 -0
  53. data/lib/chef/knife/client_reregister.rb +48 -0
  54. data/lib/chef/knife/client_show.rb +42 -0
  55. data/lib/chef/knife/configure.rb +84 -0
  56. data/lib/chef/knife/cookbook_bulk_delete.rb +47 -0
  57. data/lib/chef/knife/cookbook_delete.rb +41 -0
  58. data/lib/chef/knife/cookbook_download.rb +57 -0
  59. data/lib/chef/knife/cookbook_list.rb +41 -0
  60. data/lib/chef/knife/cookbook_metadata.rb +87 -0
  61. data/lib/chef/knife/cookbook_show.rb +75 -0
  62. data/lib/chef/knife/cookbook_upload.rb +173 -0
  63. data/lib/chef/knife/data_bag_create.rb +43 -0
  64. data/lib/chef/knife/data_bag_delete.rb +43 -0
  65. data/lib/chef/knife/data_bag_edit.rb +49 -0
  66. data/lib/chef/knife/data_bag_list.rb +42 -0
  67. data/lib/chef/knife/data_bag_show.rb +40 -0
  68. data/lib/chef/knife/ec2_instance_data.rb +46 -0
  69. data/lib/chef/knife/node_bulk_delete.rb +44 -0
  70. data/lib/chef/knife/node_create.rb +39 -0
  71. data/lib/chef/knife/node_delete.rb +36 -0
  72. data/lib/chef/knife/node_edit.rb +36 -0
  73. data/lib/chef/knife/node_from_file.rb +42 -0
  74. data/lib/chef/knife/node_list.rb +41 -0
  75. data/lib/chef/knife/node_run_list_add.rb +64 -0
  76. data/lib/chef/knife/node_run_list_remove.rb +45 -0
  77. data/lib/chef/knife/node_show.rb +46 -0
  78. data/lib/chef/knife/role_bulk_delete.rb +45 -0
  79. data/lib/chef/knife/role_create.rb +44 -0
  80. data/lib/chef/knife/role_delete.rb +36 -0
  81. data/lib/chef/knife/role_edit.rb +37 -0
  82. data/lib/chef/knife/role_from_file.rb +46 -0
  83. data/lib/chef/knife/role_list.rb +40 -0
  84. data/lib/chef/knife/role_show.rb +43 -0
  85. data/lib/chef/knife/search.rb +94 -0
  86. data/lib/chef/log.rb +39 -0
  87. data/lib/chef/mixin/check_helper.rb +31 -0
  88. data/lib/chef/mixin/checksum.rb +32 -0
  89. data/lib/chef/mixin/command.rb +390 -0
  90. data/lib/chef/mixin/convert_to_class_name.rb +57 -0
  91. data/lib/chef/mixin/create_path.rb +56 -0
  92. data/lib/chef/mixin/deep_merge.rb +33 -0
  93. data/lib/chef/mixin/find_preferred_file.rb +92 -0
  94. data/lib/chef/mixin/from_file.rb +50 -0
  95. data/lib/chef/mixin/generate_url.rb +58 -0
  96. data/lib/chef/mixin/language.rb +107 -0
  97. data/lib/chef/mixin/language_include_attribute.rb +56 -0
  98. data/lib/chef/mixin/language_include_recipe.rb +53 -0
  99. data/lib/chef/mixin/params_validate.rb +197 -0
  100. data/lib/chef/mixin/recipe_definition_dsl_core.rb +79 -0
  101. data/lib/chef/mixin/template.rb +94 -0
  102. data/lib/chef/nanite.rb +100 -0
  103. data/lib/chef/node.rb +463 -0
  104. data/lib/chef/node/attribute.rb +412 -0
  105. data/lib/chef/openid_registration.rb +181 -0
  106. data/lib/chef/platform.rb +268 -0
  107. data/lib/chef/provider.rb +101 -0
  108. data/lib/chef/provider/breakpoint.rb +36 -0
  109. data/lib/chef/provider/cron.rb +184 -0
  110. data/lib/chef/provider/deploy.rb +314 -0
  111. data/lib/chef/provider/deploy/revision.rb +70 -0
  112. data/lib/chef/provider/deploy/timestamped.rb +33 -0
  113. data/lib/chef/provider/directory.rb +72 -0
  114. data/lib/chef/provider/erl_call.rb +72 -0
  115. data/lib/chef/provider/execute.rb +58 -0
  116. data/lib/chef/provider/file.rb +195 -0
  117. data/lib/chef/provider/git.rb +203 -0
  118. data/lib/chef/provider/group.rb +120 -0
  119. data/lib/chef/provider/group/dscl.rb +128 -0
  120. data/lib/chef/provider/group/gpasswd.rb +50 -0
  121. data/lib/chef/provider/group/groupadd.rb +78 -0
  122. data/lib/chef/provider/group/pw.rb +88 -0
  123. data/lib/chef/provider/group/usermod.rb +57 -0
  124. data/lib/chef/provider/http_request.rb +106 -0
  125. data/lib/chef/provider/ifconfig.rb +131 -0
  126. data/lib/chef/provider/link.rb +157 -0
  127. data/lib/chef/provider/mdadm.rb +88 -0
  128. data/lib/chef/provider/mount.rb +117 -0
  129. data/lib/chef/provider/mount/mount.rb +208 -0
  130. data/lib/chef/provider/package.rb +160 -0
  131. data/lib/chef/provider/package/apt.rb +110 -0
  132. data/lib/chef/provider/package/dpkg.rb +109 -0
  133. data/lib/chef/provider/package/easy_install.rb +106 -0
  134. data/lib/chef/provider/package/freebsd.rb +153 -0
  135. data/lib/chef/provider/package/macports.rb +105 -0
  136. data/lib/chef/provider/package/portage.rb +124 -0
  137. data/lib/chef/provider/package/rpm.rb +99 -0
  138. data/lib/chef/provider/package/rubygems.rb +136 -0
  139. data/lib/chef/provider/package/yum-dump.py +125 -0
  140. data/lib/chef/provider/package/yum.rb +175 -0
  141. data/lib/chef/provider/package/zypper.rb +132 -0
  142. data/lib/chef/provider/remote_directory.rb +126 -0
  143. data/lib/chef/provider/remote_file.rb +141 -0
  144. data/lib/chef/provider/route.rb +118 -0
  145. data/lib/chef/provider/ruby_block.rb +33 -0
  146. data/lib/chef/provider/script.rb +42 -0
  147. data/lib/chef/provider/service.rb +135 -0
  148. data/lib/chef/provider/service/debian.rb +64 -0
  149. data/lib/chef/provider/service/freebsd.rb +156 -0
  150. data/lib/chef/provider/service/gentoo.rb +54 -0
  151. data/lib/chef/provider/service/init.rb +71 -0
  152. data/lib/chef/provider/service/redhat.rb +62 -0
  153. data/lib/chef/provider/service/simple.rb +114 -0
  154. data/lib/chef/provider/subversion.rb +156 -0
  155. data/lib/chef/provider/template.rb +175 -0
  156. data/lib/chef/provider/user.rb +170 -0
  157. data/lib/chef/provider/user/dscl.rb +280 -0
  158. data/lib/chef/provider/user/pw.rb +113 -0
  159. data/lib/chef/provider/user/useradd.rb +108 -0
  160. data/lib/chef/recipe.rb +105 -0
  161. data/lib/chef/resource.rb +380 -0
  162. data/lib/chef/resource/apt_package.rb +34 -0
  163. data/lib/chef/resource/bash.rb +33 -0
  164. data/lib/chef/resource/breakpoint.rb +35 -0
  165. data/lib/chef/resource/cron.rb +179 -0
  166. data/lib/chef/resource/csh.rb +33 -0
  167. data/lib/chef/resource/deploy.rb +359 -0
  168. data/lib/chef/resource/deploy_revision.rb +35 -0
  169. data/lib/chef/resource/directory.rb +76 -0
  170. data/lib/chef/resource/dpkg_package.rb +34 -0
  171. data/lib/chef/resource/easy_install_package.rb +41 -0
  172. data/lib/chef/resource/erl_call.rb +83 -0
  173. data/lib/chef/resource/execute.rb +127 -0
  174. data/lib/chef/resource/file.rb +84 -0
  175. data/lib/chef/resource/gem_package.rb +41 -0
  176. data/lib/chef/resource/git.rb +36 -0
  177. data/lib/chef/resource/group.rb +70 -0
  178. data/lib/chef/resource/http_request.rb +52 -0
  179. data/lib/chef/resource/ifconfig.rb +134 -0
  180. data/lib/chef/resource/link.rb +78 -0
  181. data/lib/chef/resource/macports_package.rb +29 -0
  182. data/lib/chef/resource/mdadm.rb +82 -0
  183. data/lib/chef/resource/mount.rb +135 -0
  184. data/lib/chef/resource/package.rb +80 -0
  185. data/lib/chef/resource/perl.rb +33 -0
  186. data/lib/chef/resource/portage_package.rb +33 -0
  187. data/lib/chef/resource/python.rb +33 -0
  188. data/lib/chef/resource/remote_directory.rb +91 -0
  189. data/lib/chef/resource/remote_file.rb +60 -0
  190. data/lib/chef/resource/route.rb +135 -0
  191. data/lib/chef/resource/ruby.rb +33 -0
  192. data/lib/chef/resource/ruby_block.rb +39 -0
  193. data/lib/chef/resource/scm.rb +137 -0
  194. data/lib/chef/resource/script.rb +51 -0
  195. data/lib/chef/resource/service.rb +134 -0
  196. data/lib/chef/resource/subversion.rb +34 -0
  197. data/lib/chef/resource/template.rb +60 -0
  198. data/lib/chef/resource/timestamped_deploy.rb +31 -0
  199. data/lib/chef/resource/user.rb +101 -0
  200. data/lib/chef/resource_collection.rb +212 -0
  201. data/lib/chef/resource_collection/stepable_iterator.rb +124 -0
  202. data/lib/chef/resource_definition.rb +67 -0
  203. data/lib/chef/rest.rb +298 -0
  204. data/lib/chef/role.rb +301 -0
  205. data/lib/chef/run_list.rb +164 -0
  206. data/lib/chef/runner.rb +130 -0
  207. data/lib/chef/search/query.rb +71 -0
  208. data/lib/chef/shef.rb +220 -0
  209. data/lib/chef/shef/ext.rb +297 -0
  210. data/lib/chef/shef/shef_session.rb +175 -0
  211. data/lib/chef/streaming_cookbook_uploader.rb +185 -0
  212. data/lib/chef/tasks/chef_repo.rake +245 -0
  213. data/lib/chef/util/file_edit.rb +125 -0
  214. data/lib/chef/util/fileedit.rb +121 -0
  215. data/lib/chef/webui_user.rb +231 -0
  216. metadata +398 -0
@@ -0,0 +1,170 @@
1
+ #
2
+ # Author:: AJ Christensen (<aj@junglist.gen.nz>)
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
+ # I love you Merb (lib/merb-core/server.rb)
19
+
20
+ require 'chef/config'
21
+ require 'etc'
22
+
23
+ class Chef
24
+ class Daemon
25
+ class << self
26
+ attr_accessor :name
27
+
28
+ # Daemonize the current process, managing pidfiles and process uid/gid
29
+ #
30
+ # === Parameters
31
+ # name<String>:: The name to be used for the pid file
32
+ #
33
+ def daemonize(name)
34
+ @name = name
35
+ pid = pid_from_file
36
+ unless running?
37
+ remove_pid_file()
38
+ Chef::Log.info("Daemonizing..")
39
+ begin
40
+ exit if fork
41
+ Process.setsid
42
+ exit if fork
43
+ Chef::Log.info("Forked, in #{Process.pid}. Priveleges: #{Process.euid} #{Process.egid}")
44
+ File.umask Chef::Config[:umask]
45
+ $stdin.reopen("/dev/null")
46
+ $stdout.reopen("/dev/null", "a")
47
+ $stdout.reopen($stdout)
48
+ save_pid_file
49
+ at_exit { remove_pid_file }
50
+ rescue NotImplementedError => e
51
+ Chef::Application.fatal!("There is no fork: #{e.message}")
52
+ end
53
+ else
54
+ Chef::Application.fatal!("Chef is already running pid #{pid}")
55
+ end
56
+ end
57
+
58
+ # Check if Chef is running based on the pid_file
59
+ # ==== Returns
60
+ # Boolean::
61
+ # True if Chef is running
62
+ # False if Chef is not running
63
+ #
64
+ def running?
65
+ if pid_from_file.nil?
66
+ false
67
+ else
68
+ Process.kill(0, pid_from_file)
69
+ true
70
+ end
71
+ rescue Errno::ESRCH, Errno::ENOENT
72
+ false
73
+ rescue Errno::EACCES => e
74
+ Chef::Application.fatal!("You don't have access to the PID file at #{pid_file}: #{e.message}")
75
+ end
76
+
77
+ # Gets the pid file for @name
78
+ # ==== Returns
79
+ # String::
80
+ # Location of the pid file for @name
81
+ def pid_file
82
+ Chef::Config[:pid_file] or "/tmp/#{@name}.pid"
83
+ end
84
+
85
+ # Suck the pid out of pid_file
86
+ # ==== Returns
87
+ # Integer::
88
+ # The PID from pid_file
89
+ # nil::
90
+ # Returned if the pid_file does not exist.
91
+ #
92
+ def pid_from_file
93
+ File.read(pid_file).chomp.to_i
94
+ rescue Errno::ENOENT, Errno::EACCES
95
+ nil
96
+ end
97
+
98
+ # Store the PID on the filesystem
99
+ # This uses the Chef::Config[:pid_file] option, or "/tmp/name.pid" otherwise
100
+ #
101
+ def save_pid_file
102
+ file = pid_file
103
+ begin
104
+ FileUtils.mkdir_p(File.dirname(file))
105
+ rescue Errno::EACCES => e
106
+ Chef::Application.fatal!("Failed store pid in #{File.dirname(file)}, permission denied: #{e.message}")
107
+ end
108
+
109
+ begin
110
+ File.open(file, "w") { |f| f.write(Process.pid.to_s) }
111
+ rescue Errno::EACCES => e
112
+ Chef::Application.fatal!("Couldn't write to pidfile #{file}, permission denied: #{e.message}")
113
+ end
114
+ end
115
+
116
+ # Delete the PID from the filesystem
117
+ def remove_pid_file
118
+ FileUtils.rm(pid_file) if File.exists?(pid_file)
119
+ end
120
+
121
+ # Change process user/group to those specified in Chef::Config
122
+ #
123
+ def change_privilege
124
+ if Chef::Config[:user] and Chef::Config[:group]
125
+ Chef::Log.info("About to change privilege to #{Chef::Config[:user]}:#{Chef::Config[:group]}")
126
+ _change_privilege(Chef::Config[:user], Chef::Config[:group])
127
+ elsif Chef::Config[:user]
128
+ Chef::Log.info("About to change privilege to #{Chef::Config[:user]}")
129
+ _change_privilege(Chef::Config[:user])
130
+ end
131
+ end
132
+
133
+ # Change privileges of the process to be the specified user and group
134
+ #
135
+ # ==== Parameters
136
+ # user<String>:: The user to change the process to.
137
+ # group<String>:: The group to change the process to.
138
+ #
139
+ # ==== Alternatives
140
+ # If group is left out, the user will be used (changing to user:user)
141
+ #
142
+ def _change_privilege(user, group=user)
143
+ uid, gid = Process.euid, Process.egid
144
+
145
+ begin
146
+ target_uid = Etc.getpwnam(user).uid
147
+ rescue ArgumentError => e
148
+ Chef::Application.fatal!("Failed to get UID for user #{user}, does it exist? #{e.message}")
149
+ return false
150
+ end
151
+
152
+ begin
153
+ target_gid = Etc.getgrnam(group).gid
154
+ rescue ArgumentError => e
155
+ Chef::Application.fatal!("Failed to get GID for group #{group}, does it exist? #{e.message}")
156
+ return false
157
+ end
158
+
159
+ if (uid != target_uid) or (gid != target_gid)
160
+ Process.initgroups(user, target_gid)
161
+ Process::GID.change_privilege(target_gid)
162
+ Process::UID.change_privilege(target_uid)
163
+ end
164
+ true
165
+ rescue Errno::EPERM => e
166
+ Chef::Application.fatal!("Permission denied when trying to change #{uid}:#{gid} to #{target_uid}:#{target_gid}. #{e.message}")
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,216 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: Nuo Yan (<nuo@opscode.com>)
4
+ # Copyright:: Copyright (c) 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/config'
21
+ require 'chef/mixin/params_validate'
22
+ require 'chef/mixin/from_file'
23
+ require 'chef/couchdb'
24
+ require 'chef/data_bag_item'
25
+ require 'extlib'
26
+ require 'json'
27
+
28
+ class Chef
29
+ class DataBag
30
+
31
+ include Chef::Mixin::FromFile
32
+ include Chef::Mixin::ParamsValidate
33
+
34
+ DESIGN_DOCUMENT = {
35
+ "version" => 2,
36
+ "language" => "javascript",
37
+ "views" => {
38
+ "all" => {
39
+ "map" => <<-EOJS
40
+ function(doc) {
41
+ if (doc.chef_type == "data_bag") {
42
+ emit(doc.name, doc);
43
+ }
44
+ }
45
+ EOJS
46
+ },
47
+ "all_id" => {
48
+ "map" => <<-EOJS
49
+ function(doc) {
50
+ if (doc.chef_type == "data_bag") {
51
+ emit(doc.name, doc.name);
52
+ }
53
+ }
54
+ EOJS
55
+ },
56
+ "entries" => {
57
+ "map" => <<-EOJS
58
+ function(doc) {
59
+ if (doc.chef_type == "data_bag_item") {
60
+ emit(doc.data_bag, doc.raw_data.id);
61
+ }
62
+ }
63
+ EOJS
64
+ }
65
+ }
66
+ }
67
+
68
+ attr_accessor :couchdb_rev, :couchdb_id
69
+
70
+ # Create a new Chef::DataBag
71
+ def initialize
72
+ @name = ''
73
+ @couchdb_rev = nil
74
+ @couchdb_id = nil
75
+ @couchdb = Chef::CouchDB.new
76
+ end
77
+
78
+ def name(arg=nil)
79
+ set_or_return(
80
+ :name,
81
+ arg,
82
+ :regex => /^[\-[:alnum:]_]+$/
83
+ )
84
+ end
85
+
86
+ def to_hash
87
+ result = {
88
+ "name" => @name,
89
+ 'json_class' => self.class.name,
90
+ "chef_type" => "data_bag",
91
+ }
92
+ result["_rev"] = @couchdb_rev if @couchdb_rev
93
+ result
94
+ end
95
+
96
+ # Serialize this object as a hash
97
+ def to_json(*a)
98
+ to_hash.to_json(*a)
99
+ end
100
+
101
+ # Create a Chef::Role from JSON
102
+ def self.json_create(o)
103
+ bag = new
104
+ bag.name(o["name"])
105
+ bag.couchdb_rev = o["_rev"] if o.has_key?("_rev")
106
+ bag.couchdb_id = o["_id"] if o.has_key?("_id")
107
+ bag
108
+ end
109
+
110
+ # List all the Chef::DataBag objects in the CouchDB. If inflate is set to true, you will get
111
+ # the full list of all Roles, fully inflated.
112
+ def self.cdb_list(inflate=false)
113
+ couchdb = Chef::CouchDB.new
114
+ rs = couchdb.list("data_bags", inflate)
115
+ if inflate
116
+ rs["rows"].collect { |r| r["value"] }
117
+ else
118
+ rs["rows"].collect { |r| r["key"] }
119
+ end
120
+ end
121
+
122
+ def self.list(inflate=false)
123
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
124
+ if inflate
125
+ response = Hash.new
126
+ Chef::Search::Query.new.search(:data) do |n|
127
+ response[n.name] = n
128
+ end
129
+ response
130
+ else
131
+ r.get_rest("data")
132
+ end
133
+ end
134
+
135
+ # Load a Data Bag by name from CouchDB
136
+ def self.cdb_load(name)
137
+ couchdb = Chef::CouchDB.new
138
+ couchdb.load("data_bag", name)
139
+ end
140
+
141
+ # Load a Data Bag by name via the RESTful API
142
+ def self.load(name)
143
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
144
+ r.get_rest("data/#{name}")
145
+ end
146
+
147
+ # Remove this Data Bag from CouchDB
148
+ def cdb_destroy
149
+ removed = @couchdb.delete("data_bag", @name, @couchdb_rev)
150
+ rs = @couchdb.get_view("data_bags", "entries", :include_docs => true, :startkey => @name, :endkey => @name)
151
+ rs["rows"].each do |row|
152
+ row["doc"].cdb_destroy
153
+ end
154
+ removed
155
+ end
156
+
157
+ def destroy
158
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
159
+ r.delete_rest("data/#{@name}")
160
+ end
161
+
162
+ # Save this Data Bag to the CouchDB
163
+ def cdb_save
164
+ results = @couchdb.store("data_bag", @name, self)
165
+ @couchdb_rev = results["rev"]
166
+ end
167
+
168
+ # Save the Data Bag via RESTful API
169
+ def save
170
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
171
+ begin
172
+ r.put_rest("data/#{@name}", self)
173
+ rescue Net::HTTPServerException => e
174
+ if e.response.code == "404"
175
+ r.post_rest("data", self)
176
+ else
177
+ raise e
178
+ end
179
+ end
180
+ self
181
+ end
182
+
183
+ #create a data bag via RESTful API
184
+ def create
185
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
186
+ r.post_rest("data", self)
187
+ self
188
+ end
189
+
190
+ # List all the items in this Bag from CouchDB
191
+ # The self.load method does this through the REST API
192
+ def list(inflate=false)
193
+ rs = nil
194
+ if inflate
195
+ rs = @couchdb.get_view("data_bags", "entries", :include_docs => true, :startkey => @name, :endkey => @name)
196
+ rs["rows"].collect { |r| r["doc"] }
197
+ else
198
+ rs = @couchdb.get_view("data_bags", "entries", :startkey => @name, :endkey => @name)
199
+ rs["rows"].collect { |r| r["value"] }
200
+ end
201
+ end
202
+
203
+ # Set up our CouchDB design document
204
+ def self.create_design_document
205
+ couchdb = Chef::CouchDB.new
206
+ couchdb.create_design_document("data_bags", DESIGN_DOCUMENT)
207
+ end
208
+
209
+ # As a string
210
+ def to_s
211
+ "data_bag[#{@name}]"
212
+ end
213
+
214
+ end
215
+ end
216
+
@@ -0,0 +1,227 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: Nuo Yan (<nuo@opscode.com>)
4
+ # Copyright:: Copyright (c) 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/config'
21
+ require 'chef/mixin/params_validate'
22
+ require 'chef/mixin/from_file'
23
+ require 'chef/couchdb'
24
+ require 'extlib'
25
+ require 'json'
26
+
27
+ class Chef
28
+ class DataBagItem
29
+
30
+ include Chef::Mixin::FromFile
31
+ include Chef::Mixin::ParamsValidate
32
+
33
+ DESIGN_DOCUMENT = {
34
+ "version" => 1,
35
+ "language" => "javascript",
36
+ "views" => {
37
+ "all" => {
38
+ "map" => <<-EOJS
39
+ function(doc) {
40
+ if (doc.chef_type == "data_bag_item") {
41
+ emit(doc.name, doc);
42
+ }
43
+ }
44
+ EOJS
45
+ },
46
+ "all_id" => {
47
+ "map" => <<-EOJS
48
+ function(doc) {
49
+ if (doc.chef_type == "data_bag_item") {
50
+ emit(doc.name, doc.name);
51
+ }
52
+ }
53
+ EOJS
54
+ }
55
+ }
56
+ }
57
+
58
+ attr_accessor :couchdb_rev, :raw_data, :couchdb_id
59
+
60
+ # Create a new Chef::DataBagItem
61
+ def initialize(couchdb=nil)
62
+ @couchdb_rev = nil
63
+ @couchdb_id = nil
64
+ @data_bag = nil
65
+ @raw_data = Mash.new
66
+ @couchdb = Chef::CouchDB.new
67
+ end
68
+
69
+ def raw_data
70
+ @raw_data
71
+ end
72
+
73
+ def raw_data=(new_data)
74
+ unless new_data.kind_of?(Hash) || new_data.kind_of?(Mash)
75
+ raise ArgumentError, "Data Bag Items must contain a Hash or Mash!"
76
+ end
77
+ unless new_data.has_key?("id")
78
+ raise ArgumentError, "Data Bag Items must have an id key in the hash! #{new_data.inspect}"
79
+ end
80
+ unless new_data["id"] =~ /^[\-[:alnum:]_]+$/
81
+ raise ArgumentError, "Data Bag Item id does not match alphanumeric/-/_!"
82
+ end
83
+ @raw_data = new_data
84
+ end
85
+
86
+ def data_bag(arg=nil)
87
+ set_or_return(
88
+ :data_bag,
89
+ arg,
90
+ :regex => /^[\-[:alnum:]_]+$/
91
+ )
92
+ end
93
+
94
+ def name
95
+ object_name
96
+ end
97
+
98
+ def object_name
99
+ if raw_data.has_key?('id')
100
+ id = raw_data['id']
101
+ else
102
+ raise ArgumentError, "You must have an 'id' or :id key in the raw data"
103
+ end
104
+
105
+ data_bag_name = self.data_bag
106
+ unless data_bag_name
107
+ raise ArgumentError, "You must have declared what bag this item belongs to!"
108
+ end
109
+ "data_bag_item_#{data_bag_name}_#{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
+ o.delete("_id")
152
+ end
153
+ bag_item.raw_data = Mash.new(o["raw_data"])
154
+ bag_item
155
+ end
156
+
157
+ # The Data Bag Item behaves like a hash - we pass all that stuff along to @raw_data.
158
+ def method_missing(method_symbol, *args, &block)
159
+ self.raw_data.send(method_symbol, *args, &block)
160
+ end
161
+
162
+ # Load a Data Bag Item by name from CouchDB
163
+ def self.cdb_load(data_bag, name)
164
+ couchdb = Chef::CouchDB.new
165
+ couchdb.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
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
171
+ r.get_rest("data/#{data_bag}/#{name}")
172
+ end
173
+
174
+ # Remove this Data Bag Item from CouchDB
175
+ def cdb_destroy
176
+ removed = @couchdb.delete("data_bag_item", object_name, @couchdb_rev)
177
+ removed
178
+ end
179
+
180
+ def destroy(data_bag=data_bag, databag_item=name)
181
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
182
+ r.delete_rest("data/#{data_bag}/#{databag_item}")
183
+ end
184
+
185
+ # Save this Data Bag Item to CouchDB
186
+ def cdb_save
187
+ results = @couchdb.store("data_bag_item", object_name, self)
188
+ @couchdb_rev = results["rev"]
189
+ end
190
+
191
+ # Save this Data Bag Item via RESTful API
192
+ def save(item_id=@raw_data['id'])
193
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
194
+ begin
195
+ r.put_rest("data/#{data_bag}/#{item_id}", @raw_data)
196
+ rescue Net::HTTPServerException => e
197
+ if e.response.code == "404"
198
+ r.post_rest("data/#{data_bag}", @raw_data)
199
+ else
200
+ raise e
201
+ end
202
+ end
203
+ self
204
+ end
205
+
206
+ # Create this Data Bag Item via RESTful API
207
+ def create
208
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
209
+ r.post_rest("data/#{data_bag}", @raw_data)
210
+ self
211
+ end
212
+
213
+ # Set up our CouchDB design document
214
+ def self.create_design_document
215
+ couchdb = Chef::CouchDB.new
216
+ couchdb.create_design_document("data_bag_items", DESIGN_DOCUMENT)
217
+ end
218
+
219
+ # As a string
220
+ def to_s
221
+ "data_bag_item[#{@name}]"
222
+ end
223
+
224
+ end
225
+ end
226
+
227
+