chef 0.10.10.beta.1 → 0.10.10.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/README.rdoc +1 -1
  2. data/distro/common/html/chef-client.8.html +3 -3
  3. data/distro/common/html/chef-expander.8.html +3 -3
  4. data/distro/common/html/chef-expanderctl.8.html +3 -3
  5. data/distro/common/html/chef-server-webui.8.html +3 -3
  6. data/distro/common/html/chef-server.8.html +3 -3
  7. data/distro/common/html/chef-solo.8.html +3 -3
  8. data/distro/common/html/chef-solr.8.html +3 -3
  9. data/distro/common/html/knife-bootstrap.1.html +3 -3
  10. data/distro/common/html/knife-client.1.html +3 -3
  11. data/distro/common/html/knife-configure.1.html +3 -3
  12. data/distro/common/html/knife-cookbook-site.1.html +3 -3
  13. data/distro/common/html/knife-cookbook.1.html +3 -3
  14. data/distro/common/html/knife-data-bag.1.html +7 -3
  15. data/distro/common/html/knife-environment.1.html +3 -3
  16. data/distro/common/html/knife-exec.1.html +3 -3
  17. data/distro/common/html/knife-index.1.html +3 -3
  18. data/distro/common/html/knife-node.1.html +3 -3
  19. data/distro/common/html/knife-role.1.html +3 -3
  20. data/distro/common/html/knife-search.1.html +3 -3
  21. data/distro/common/html/knife-ssh.1.html +3 -3
  22. data/distro/common/html/knife-status.1.html +3 -3
  23. data/distro/common/html/knife-tag.1.html +3 -3
  24. data/distro/common/html/knife.1.html +3 -3
  25. data/distro/common/html/shef.1.html +3 -3
  26. data/distro/common/man/man1/knife-bootstrap.1 +1 -1
  27. data/distro/common/man/man1/knife-client.1 +1 -1
  28. data/distro/common/man/man1/knife-configure.1 +1 -1
  29. data/distro/common/man/man1/knife-cookbook-site.1 +1 -1
  30. data/distro/common/man/man1/knife-cookbook.1 +1 -1
  31. data/distro/common/man/man1/knife-data-bag.1 +7 -1
  32. data/distro/common/man/man1/knife-environment.1 +1 -1
  33. data/distro/common/man/man1/knife-exec.1 +1 -1
  34. data/distro/common/man/man1/knife-index.1 +1 -1
  35. data/distro/common/man/man1/knife-node.1 +1 -1
  36. data/distro/common/man/man1/knife-role.1 +1 -1
  37. data/distro/common/man/man1/knife-search.1 +1 -1
  38. data/distro/common/man/man1/knife-ssh.1 +1 -1
  39. data/distro/common/man/man1/knife-status.1 +1 -1
  40. data/distro/common/man/man1/knife-tag.1 +1 -1
  41. data/distro/common/man/man1/knife.1 +1 -1
  42. data/distro/common/man/man1/shef.1 +1 -1
  43. data/distro/common/man/man8/chef-client.8 +1 -1
  44. data/distro/common/man/man8/chef-expander.8 +1 -1
  45. data/distro/common/man/man8/chef-expanderctl.8 +1 -1
  46. data/distro/common/man/man8/chef-server-webui.8 +1 -1
  47. data/distro/common/man/man8/chef-server.8 +1 -1
  48. data/distro/common/man/man8/chef-solo.8 +1 -1
  49. data/distro/common/man/man8/chef-solr.8 +1 -1
  50. data/distro/common/markdown/man1/knife-data-bag.mkd +4 -0
  51. data/lib/chef/application/client.rb +15 -1
  52. data/lib/chef/application/solo.rb +15 -1
  53. data/lib/chef/application/windows_service.rb +15 -1
  54. data/lib/chef/certificate.rb +18 -51
  55. data/lib/chef/client.rb +31 -1
  56. data/lib/chef/json_compat.rb +1 -1
  57. data/lib/chef/knife.rb +23 -6
  58. data/lib/chef/knife/bootstrap.rb +7 -0
  59. data/lib/chef/knife/bootstrap/archlinux-gems.erb +1 -1
  60. data/lib/chef/knife/bootstrap/centos5-gems.erb +1 -1
  61. data/lib/chef/knife/bootstrap/chef-full.erb +1 -1
  62. data/lib/chef/knife/bootstrap/fedora13-gems.erb +1 -1
  63. data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +1 -1
  64. data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +1 -1
  65. data/lib/chef/knife/core/bootstrap_context.rb +4 -0
  66. data/lib/chef/knife/core/generic_presenter.rb +1 -1
  67. data/lib/chef/knife/core/object_loader.rb +39 -2
  68. data/lib/chef/knife/data_bag_from_file.rb +68 -19
  69. data/lib/chef/knife/ssh.rb +2 -1
  70. data/lib/chef/platform.rb +8 -0
  71. data/lib/chef/provider/cron.rb +70 -56
  72. data/lib/chef/provider/cron/solaris.rb +16 -143
  73. data/lib/chef/provider/deploy.rb +1 -1
  74. data/lib/chef/provider/group/groupadd.rb +1 -4
  75. data/lib/chef/provider/mdadm.rb +1 -1
  76. data/lib/chef/provider/mount/mount.rb +14 -2
  77. data/lib/chef/provider/package.rb +7 -1
  78. data/lib/chef/provider/package/freebsd.rb +30 -6
  79. data/lib/chef/provider/package/pacman.rb +1 -0
  80. data/lib/chef/provider/package/rubygems.rb +2 -4
  81. data/lib/chef/provider/remote_directory.rb +1 -1
  82. data/lib/chef/provider/service/freebsd.rb +32 -46
  83. data/lib/chef/provider/service/init.rb +8 -5
  84. data/lib/chef/provider/service/simple.rb +57 -48
  85. data/lib/chef/provider/service/upstart.rb +13 -5
  86. data/lib/chef/provider/user/useradd.rb +6 -1
  87. data/lib/chef/resource/mdadm.rb +9 -0
  88. data/lib/chef/resource/service.rb +9 -1
  89. data/lib/chef/rest.rb +9 -9
  90. data/lib/chef/version.rb +1 -1
  91. metadata +177 -28
@@ -26,16 +26,16 @@ require 'fileutils'
26
26
  class Chef
27
27
  class Certificate
28
28
  class << self
29
-
29
+
30
30
  # Generates a new CA Certificate and Key, and writes them out to
31
31
  # Chef::Config[:signing_ca_cert] and Chef::Config[:signing_ca_key].
32
32
  def generate_signing_ca
33
33
  ca_cert_file = Chef::Config[:signing_ca_cert]
34
- ca_keypair_file = Chef::Config[:signing_ca_key]
34
+ ca_keypair_file = Chef::Config[:signing_ca_key]
35
35
 
36
36
  unless File.exists?(ca_cert_file) && File.exists?(ca_keypair_file)
37
37
  Chef::Log.info("Creating new signing certificate")
38
-
38
+
39
39
  [ ca_cert_file, ca_keypair_file ].each do |f|
40
40
  ca_basedir = File.dirname(f)
41
41
  FileUtils.mkdir_p ca_basedir
@@ -47,11 +47,11 @@ class Chef
47
47
  ca_cert.version = 3
48
48
  ca_cert.serial = 1
49
49
  info = [
50
- ["C", Chef::Config[:signing_ca_country]],
51
- ["ST", Chef::Config[:signing_ca_state]],
52
- ["L", Chef::Config[:signing_ca_location]],
50
+ ["C", Chef::Config[:signing_ca_country]],
51
+ ["ST", Chef::Config[:signing_ca_state]],
52
+ ["L", Chef::Config[:signing_ca_location]],
53
53
  ["O", Chef::Config[:signing_ca_org]],
54
- ["OU", "Certificate Service"],
54
+ ["OU", "Certificate Service"],
55
55
  ["CN", "#{Chef::Config[:signing_ca_domain]}/emailAddress=#{Chef::Config[:signing_ca_email]}"]
56
56
  ]
57
57
  ca_cert.subject = ca_cert.issuer = OpenSSL::X509::Name.new(info)
@@ -80,52 +80,19 @@ class Chef
80
80
  end
81
81
 
82
82
  # Creates a new key pair, and signs them with the signing certificate
83
- # and key generated from generate_signing_ca above.
83
+ # and key generated from generate_signing_ca above.
84
84
  #
85
- # @param [String] The common name for the key pair.
86
- # @param [Optional String] The subject alternative name.
87
- # @return [Object, Object] The public and private key objects.
88
- def gen_keypair(common_name, subject_alternative_name = nil)
85
+ # All arguments are unused, though two arguments are accepted for compatibility.
86
+ #
87
+ # returns an array of [public_key, private_key]
88
+ def gen_keypair(common_name=nil, subject_alternative_name = nil)
89
89
 
90
90
  Chef::Log.info("Creating new key pair for #{common_name}")
91
91
 
92
92
  # generate client keypair
93
93
  client_keypair = OpenSSL::PKey::RSA.generate(2048)
94
94
 
95
- client_cert = OpenSSL::X509::Certificate.new
96
-
97
- ca_cert = OpenSSL::X509::Certificate.new(File.read(Chef::Config[:signing_ca_cert]))
98
-
99
- info = [
100
- ["C", Chef::Config[:signing_ca_country]],
101
- ["ST", Chef::Config[:signing_ca_state]],
102
- ["L", Chef::Config[:signing_ca_location]],
103
- ["O", Chef::Config[:signing_ca_org]],
104
- ["OU", "Certificate Service"],
105
- ["CN", common_name ]
106
- ]
107
-
108
- client_cert.subject = OpenSSL::X509::Name.new(info)
109
- client_cert.issuer = ca_cert.subject
110
- client_cert.not_before = Time.now
111
- client_cert.not_after = Time.now + 10 * 365 * 24 * 60 * 60 # 10 years
112
- client_cert.public_key = client_keypair.public_key
113
- client_cert.serial = 1
114
- client_cert.version = 3
115
-
116
- ef = OpenSSL::X509::ExtensionFactory.new
117
- ef.subject_certificate = client_cert
118
- ef.issuer_certificate = ca_cert
119
-
120
- client_cert.extensions = [
121
- ef.create_extension("basicConstraints", "CA:FALSE", true),
122
- ef.create_extension("subjectKeyIdentifier", "hash")
123
- ]
124
- client_cert.add_extension ef.create_extension("subjectAltName", subject_alternative_name) if subject_alternative_name
125
-
126
- client_cert.sign(OpenSSL::PKey::RSA.new(File.read(Chef::Config[:signing_ca_key])), OpenSSL::Digest::SHA1.new)
127
-
128
- return client_cert.public_key, client_keypair
95
+ return client_keypair.public_key, client_keypair
129
96
  end
130
97
 
131
98
  def gen_validation_key(name=Chef::Config[:validation_client_name], key_file=Chef::Config[:validation_key], admin=false)
@@ -133,12 +100,12 @@ class Chef
133
100
  api_client = Chef::ApiClient.new
134
101
  api_client.name(name)
135
102
  api_client.admin(admin)
136
-
103
+
137
104
  begin
138
105
  # If both the couch record and file exist, don't do anything. Otherwise,
139
106
  # re-generate the validation key.
140
107
  Chef::ApiClient.cdb_load(name)
141
-
108
+
142
109
  # The couch document was loaded successfully if we got to here; if we
143
110
  # can't also load the file on the filesystem, we'll regenerate it all.
144
111
  File.open(key_file, "r") do |file|
@@ -155,14 +122,14 @@ class Chef
155
122
  Chef::Log.fatal("Could not de-index (to rabbitmq) previous validation key - rabbitmq is down! Start rabbitmq then restart chef-server to re-generate it")
156
123
  raise
157
124
  end
158
-
125
+
159
126
  create_validation_key(api_client, key_file)
160
127
  else
161
128
  raise
162
129
  end
163
130
  end
164
131
  end
165
-
132
+
166
133
  private
167
134
  def create_validation_key(api_client, key_file)
168
135
  Chef::Log.info("Creating validation key...")
@@ -178,7 +145,7 @@ class Chef
178
145
  # re-raise so the error bubbles out and nukes chef-server
179
146
  raise e
180
147
  end
181
-
148
+
182
149
  key_dir = File.dirname(key_file)
183
150
  FileUtils.mkdir_p(key_dir) unless File.directory?(key_dir)
184
151
  File.open(key_file, File::WRONLY|File::CREAT, 0600) do |f|
@@ -124,12 +124,14 @@ class Chef
124
124
  attr_reader :run_status
125
125
 
126
126
  # Creates a new Chef::Client.
127
- def initialize(json_attribs=nil)
127
+ def initialize(json_attribs=nil, args={})
128
128
  @json_attribs = json_attribs
129
129
  @node = nil
130
130
  @run_status = nil
131
131
  @runner = nil
132
132
  @ohai = Ohai::System.new
133
+ @override_runlist = args.delete(:override_runlist)
134
+ runlist_override_sanity_check!
133
135
  end
134
136
 
135
137
  # Do a full run for this Chef::Client. Calls:
@@ -193,6 +195,7 @@ class Chef
193
195
  run_context = Chef::RunContext.new(node, Chef::CookbookCollection.new(cookbook_hash))
194
196
  end
195
197
  run_status.run_context = run_context
198
+
196
199
  run_context.load(@run_list_expansion)
197
200
  assert_cookbook_path_not_empty(run_context)
198
201
  run_context
@@ -201,6 +204,10 @@ class Chef
201
204
  def save_updated_node
202
205
  unless Chef::Config[:solo]
203
206
  Chef::Log.debug("Saving the current state of node #{node_name}")
207
+ if(@original_runlist)
208
+ @node.run_list(*@original_original)
209
+ @node[:runlist_override_history] = {Time.now.to_i => @override_runlist.inspect}
210
+ end
204
211
  @node.save
205
212
  end
206
213
  end
@@ -246,6 +253,16 @@ class Chef
246
253
  # determine which versions of cookbooks to use.
247
254
  @node.reset_defaults_and_overrides
248
255
  @node.consume_external_attrs(ohai.data, @json_attribs)
256
+
257
+ unless(@override_runlist.empty?)
258
+ @original_runlist = @node.run_list.run_list_items.dup
259
+ runlist_override_sanity_check!
260
+ @node.run_list(*@override_runlist)
261
+ Chef::Log.warn "Run List override has been provided."
262
+ Chef::Log.warn "Original Run List: [#{@original_runlist.join(', ')}]"
263
+ Chef::Log.warn "Overridden Run List: [#{@node.run_list}]"
264
+ end
265
+
249
266
  if Chef::Config[:solo]
250
267
  @run_list_expansion = @node.expand!('disk')
251
268
  else
@@ -316,6 +333,19 @@ class Chef
316
333
 
317
334
  private
318
335
 
336
+ # Ensures runlist override contains RunListItem instances
337
+ def runlist_override_sanity_check!
338
+ @override_runlist = @override_runlist.split(',') if @override_runlist.is_a?(String)
339
+ @override_runlist = [@override_runlist].flatten.compact
340
+ @override_runlist.map! do |item|
341
+ if(item.is_a?(Chef::RunList::RunListItem))
342
+ item
343
+ else
344
+ Chef::RunList::RunListItem.new(item)
345
+ end
346
+ end
347
+ end
348
+
319
349
  def directory_not_empty?(path)
320
350
  File.exists?(path) && (Dir.entries(path).size > 2)
321
351
  end
@@ -17,7 +17,7 @@
17
17
 
18
18
  # Wrapper class for interacting with JSON.
19
19
 
20
- require 'json'
20
+ require 'yajl/json_gem'
21
21
 
22
22
  class Chef
23
23
  class JSONCompat
@@ -281,14 +281,31 @@ class Chef
281
281
 
282
282
  def configure_chef
283
283
  unless config[:config_file]
284
+ candidate_configs = []
285
+
286
+ # Look for $KNIFE_HOME/knife.rb (allow multiple knives config on same machine)
287
+ if ENV['KNIFE_HOME']
288
+ candidate_configs << File.join(ENV['KNIFE_HOME'], 'knife.rb')
289
+ end
290
+ # Look for $PWD/knife.rb
291
+ if Dir.pwd
292
+ candidate_configs << File.join(Dir.pwd, 'knife.rb')
293
+ end
294
+ # Look for $UPWARD/.chef/knife.rb
284
295
  if self.class.chef_config_dir
285
- candidate_config = File.expand_path('knife.rb',self.class.chef_config_dir)
286
- config[:config_file] = candidate_config if File.exist?(candidate_config)
296
+ candidate_configs << File.join(self.class.chef_config_dir, 'knife.rb')
297
+ end
298
+ # Look for $HOME/.chef/knife.rb
299
+ if ENV['HOME']
300
+ candidate_configs << File.join(ENV['HOME'], '.chef', 'knife.rb')
287
301
  end
288
- # If we haven't set a config yet and $HOME is set, and the home
289
- # knife.rb exists, use it:
290
- if (!config[:config_file]) && ENV['HOME'] && File.exist?(File.join(ENV['HOME'], '.chef', 'knife.rb'))
291
- config[:config_file] = File.join(ENV['HOME'], '.chef', 'knife.rb')
302
+
303
+ candidate_configs.each do | candidate_config |
304
+ candidate_config = File.expand_path(candidate_config)
305
+ if File.exist?(candidate_config)
306
+ config[:config_file] = candidate_config
307
+ break
308
+ end
292
309
  end
293
310
  end
294
311
 
@@ -105,6 +105,13 @@ class Chef
105
105
  :description => "Comma separated list of roles/recipes to apply",
106
106
  :proc => lambda { |o| o.split(/[\s,]+/) },
107
107
  :default => []
108
+
109
+ option :first_boot_attributes,
110
+ :short => "-j JSON_ATTRIBS",
111
+ :long => "--json-attributes",
112
+ :description => "A JSON string to be added to the first run of chef-client",
113
+ :proc => lambda { |o| JSON.parse(o) },
114
+ :default => {}
108
115
 
109
116
  option :host_key_verify,
110
117
  :long => "--[no-]host-key-verify",
@@ -53,7 +53,7 @@ EOP
53
53
 
54
54
  (
55
55
  cat <<'EOP'
56
- <%= { "run_list" => @run_list }.to_json %>
56
+ <%= first_boot.to_json %>
57
57
  EOP
58
58
  ) > /etc/chef/first-boot.json
59
59
 
@@ -49,7 +49,7 @@ EOP
49
49
 
50
50
  (
51
51
  cat <<'EOP'
52
- <%= { "run_list" => @run_list }.to_json %>
52
+ <%= first_boot.to_json %>
53
53
  EOP
54
54
  ) > /etc/chef/first-boot.json
55
55
 
@@ -52,7 +52,7 @@ EOP
52
52
 
53
53
  (
54
54
  cat <<'EOP'
55
- <%= { "run_list" => @run_list }.to_json %>
55
+ <%= first_boot.to_json %>
56
56
  EOP
57
57
  ) > /etc/chef/first-boot.json
58
58
 
@@ -36,7 +36,7 @@ EOP
36
36
 
37
37
  (
38
38
  cat <<'EOP'
39
- <%= { "run_list" => @run_list }.to_json %>
39
+ <%= first_boot.to_json %>
40
40
  EOP
41
41
  ) > /etc/chef/first-boot.json
42
42
 
@@ -43,7 +43,7 @@ echo 'https_proxy "knife_config[:bootstrap_proxy]"' >> /etc/chef/client.rb
43
43
 
44
44
  (
45
45
  cat <<'EOP'
46
- <%= { "run_list" => @run_list }.to_json %>
46
+ <%= first_boot.to_json %>
47
47
  EOP
48
48
  ) > /etc/chef/first-boot.json
49
49
 
@@ -43,7 +43,7 @@ EOP
43
43
 
44
44
  (
45
45
  cat <<'EOP'
46
- <%= { "run_list" => @run_list }.to_json %>
46
+ <%= first_boot.to_json %>
47
47
  EOP
48
48
  ) > /etc/chef/first-boot.json
49
49
 
@@ -94,6 +94,10 @@ CONFIG
94
94
  def chef_version
95
95
  knife_config[:bootstrap_version] || Chef::VERSION
96
96
  end
97
+
98
+ def first_boot
99
+ (@config[:first_boot_attributes] || {}).merge(:run_list => @run_list)
100
+ end
97
101
 
98
102
  end
99
103
  end
@@ -70,7 +70,7 @@ class Chef
70
70
  require 'stringio'
71
71
  # If you were looking for some attribute and there is only one match
72
72
  # just dump the attribute value
73
- if data.length == 1 and config[:attribute]
73
+ if config[:attribute] and data.length == 1
74
74
  data.values[0]
75
75
  else
76
76
  out = StringIO.new
@@ -24,6 +24,11 @@ class Chef
24
24
  attr_reader :ui
25
25
  attr_reader :klass
26
26
 
27
+ class ObjectType
28
+ FILE = 1
29
+ FOLDER = 2
30
+ end
31
+
27
32
  def initialize(klass, ui)
28
33
  @klass = klass
29
34
  @ui = ui
@@ -31,12 +36,13 @@ class Chef
31
36
 
32
37
  def load_from(repo_location, *components)
33
38
  unless object_file = find_file(repo_location, *components)
34
- ui.error "Could not find or open file for #{components.join(' ')}"
39
+ ui.error "Could not find or open file '#{components.last}' in current directory or in '#{repo_location}/#{components.join('/')}'"
35
40
  exit 1
36
41
  end
37
42
  object_from_file(object_file)
38
43
  end
39
44
 
45
+ # When someone makes this awesome, please update the above error message.
40
46
  def find_file(repo_location, *components)
41
47
  if file_exists_and_is_readable?(File.expand_path( components.last ))
42
48
  File.expand_path( components.last )
@@ -50,10 +56,41 @@ class Chef
50
56
  end
51
57
  end
52
58
 
59
+ # Find all objects in the given location
60
+ # If the object type is File it will look for all *.{json,rb}
61
+ # files, otherwise it will lookup for folders only (useful for
62
+ # data_bags)
63
+ #
64
+ # @param [String] path - base look up location
65
+ #
66
+ # @return [Array<String>] basenames of the found objects
67
+ #
68
+ # @api public
69
+ def find_all_objects(path)
70
+ path = File.join(path, '*')
71
+ path << '.{json,rb}'
72
+ objects = Dir.glob(File.expand_path(path))
73
+ objects.map { |o| File.basename(o) }
74
+ end
75
+
76
+ def find_all_object_dirs(path)
77
+ path = File.join(path, '*')
78
+ objects = Dir.glob(File.expand_path(path))
79
+ objects.delete_if { |o| !File.directory?(o) }
80
+ objects.map { |o| File.basename(o) }
81
+ end
82
+
53
83
  def object_from_file(filename)
54
84
  case filename
55
85
  when /\.(js|json)$/
56
- Chef::JSONCompat.from_json(IO.read(filename))
86
+ r = Yajl::Parser.parse(IO.read(filename))
87
+
88
+ # Chef::DataBagItem doesn't work well with the json_create method
89
+ if @klass == Chef::DataBagItem
90
+ r
91
+ else
92
+ @klass.json_create(r)
93
+ end
57
94
  when /\.rb$/
58
95
  r = klass.new
59
96
  r.from_file(filename)
@@ -7,9 +7,9 @@
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
9
9
  # You may obtain a copy of the License at
10
- #
10
+ #
11
11
  # http://www.apache.org/licenses/LICENSE-2.0
12
- #
12
+ #
13
13
  # Unless required by applicable law or agreed to in writing, software
14
14
  # distributed under the License is distributed on an "AS IS" BASIS,
15
15
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -31,7 +31,7 @@ class Chef
31
31
  require 'chef/encrypted_data_bag_item'
32
32
  end
33
33
 
34
- banner "knife data bag from file BAG FILE (options)"
34
+ banner "knife data bag from file BAG FILE|FOLDER [FILE|FOLDER..] (options)"
35
35
  category "data bag"
36
36
 
37
37
  option :secret,
@@ -43,6 +43,11 @@ class Chef
43
43
  :long => "--secret-file SECRET_FILE",
44
44
  :description => "A file containing the secret key to use to encrypt data bag item values"
45
45
 
46
+ option :all,
47
+ :short => "-a",
48
+ :long => "--all",
49
+ :description => "Upload all data bags"
50
+
46
51
  def read_secret
47
52
  if config[:secret]
48
53
  config[:secret]
@@ -64,23 +69,67 @@ class Chef
64
69
  end
65
70
 
66
71
  def run
67
- if @name_args.size != 2
68
- ui.msg(opt_parser)
69
- exit(1)
72
+ if config[:all] == true
73
+ load_all_data_bags(@name_args)
74
+ else
75
+ if @name_args.size < 2
76
+ ui.msg(opt_parser)
77
+ exit(1)
78
+ end
79
+ @data_bag = @name_args.shift
80
+ load_data_bag_items(@data_bag, @name_args)
81
+ end
82
+ end
83
+
84
+ private
85
+ def data_bags_path
86
+ @data_bag_path ||= "data_bags"
87
+ end
88
+
89
+ def find_all_data_bags
90
+ loader.find_all_object_dirs("./#{data_bags_path}")
91
+ end
92
+
93
+ def find_all_data_bag_items(data_bag)
94
+ loader.find_all_objects("./#{data_bags_path}/#{data_bag}")
95
+ end
96
+
97
+ def load_all_data_bags(args)
98
+ data_bags = args.empty? ? find_all_data_bags : [args.shift]
99
+ data_bags.each do |data_bag|
100
+ load_data_bag_items(data_bag)
101
+ end
102
+ end
103
+
104
+ def load_data_bag_items(data_bag, items = nil)
105
+ items ||= find_all_data_bag_items(data_bag)
106
+ item_paths = normalize_item_paths(items)
107
+ item_paths.each do |item_path|
108
+ item = loader.load_from("#{data_bags_path}", data_bag, item_path)
109
+ item = if use_encryption
110
+ secret = read_secret
111
+ Chef::EncryptedDataBagItem.encrypt_data_bag_item(item, secret)
112
+ else
113
+ item
114
+ end
115
+ dbag = Chef::DataBagItem.new
116
+ dbag.data_bag(data_bag)
117
+ dbag.raw_data = item
118
+ dbag.save
119
+ ui.info("Updated data_bag_item[#{dbag.data_bag}::#{dbag.id}]")
120
+ end
121
+ end
122
+
123
+ def normalize_item_paths(args)
124
+ paths = Array.new
125
+ args.each do |path|
126
+ if File.directory?(path)
127
+ paths.concat(Dir.glob(File.join(path, "*.json")))
128
+ else
129
+ paths << path
130
+ end
70
131
  end
71
- @data_bag, @item_path = @name_args[0], @name_args[1]
72
- item = loader.load_from("data_bags", @data_bag, @item_path)
73
- item = if use_encryption
74
- secret = read_secret
75
- Chef::EncryptedDataBagItem.encrypt_data_bag_item(item, secret)
76
- else
77
- item
78
- end
79
- dbag = Chef::DataBagItem.new
80
- dbag.data_bag(@name_args[0])
81
- dbag.raw_data = item
82
- dbag.save
83
- ui.info("Updated data_bag_item[#{dbag.data_bag}::#{dbag.id}]")
132
+ paths
84
133
  end
85
134
  end
86
135
  end