chef 12.4.0 → 12.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chef/api_client.rb +31 -129
  3. data/lib/chef/api_client_v1.rb +325 -0
  4. data/lib/chef/chef_class.rb +15 -7
  5. data/lib/chef/chef_fs/file_system/chef_server_root_dir.rb +2 -2
  6. data/lib/chef/dsl/resources.rb +6 -4
  7. data/lib/chef/exceptions.rb +2 -2
  8. data/lib/chef/guard_interpreter/resource_guard_interpreter.rb +2 -1
  9. data/lib/chef/knife/bootstrap/templates/chef-full.erb +4 -4
  10. data/lib/chef/knife/client_bulk_delete.rb +2 -2
  11. data/lib/chef/knife/client_create.rb +4 -4
  12. data/lib/chef/knife/client_delete.rb +3 -3
  13. data/lib/chef/knife/client_edit.rb +10 -2
  14. data/lib/chef/knife/client_list.rb +2 -2
  15. data/lib/chef/knife/client_reregister.rb +2 -2
  16. data/lib/chef/knife/client_show.rb +2 -2
  17. data/lib/chef/knife/osc_user_create.rb +3 -3
  18. data/lib/chef/knife/osc_user_delete.rb +2 -2
  19. data/lib/chef/knife/osc_user_edit.rb +3 -3
  20. data/lib/chef/knife/osc_user_list.rb +2 -2
  21. data/lib/chef/knife/osc_user_reregister.rb +2 -2
  22. data/lib/chef/knife/osc_user_show.rb +2 -2
  23. data/lib/chef/knife/user_create.rb +3 -3
  24. data/lib/chef/knife/user_delete.rb +4 -4
  25. data/lib/chef/knife/user_edit.rb +3 -3
  26. data/lib/chef/knife/user_list.rb +2 -2
  27. data/lib/chef/knife/user_reregister.rb +2 -2
  28. data/lib/chef/knife/user_show.rb +2 -2
  29. data/lib/chef/node_map.rb +14 -18
  30. data/lib/chef/platform/handler_map.rb +45 -0
  31. data/lib/chef/platform/priority_map.rb +19 -32
  32. data/lib/chef/platform/provider_handler_map.rb +29 -0
  33. data/lib/chef/platform/provider_mapping.rb +3 -2
  34. data/lib/chef/platform/resource_handler_map.rb +29 -0
  35. data/lib/chef/platform/resource_priority_map.rb +0 -6
  36. data/lib/chef/provider.rb +1 -1
  37. data/lib/chef/provider/dsc_resource.rb +2 -2
  38. data/lib/chef/provider/dsc_script.rb +1 -1
  39. data/lib/chef/provider/mount/aix.rb +1 -1
  40. data/lib/chef/provider/package.rb +0 -31
  41. data/lib/chef/provider/package/aix.rb +1 -0
  42. data/lib/chef/provider/package/apt.rb +1 -0
  43. data/lib/chef/provider/package/homebrew.rb +1 -0
  44. data/lib/chef/provider/package/ips.rb +1 -0
  45. data/lib/chef/provider/package/macports.rb +1 -0
  46. data/lib/chef/provider/package/openbsd.rb +1 -0
  47. data/lib/chef/provider/package/pacman.rb +1 -0
  48. data/lib/chef/provider/package/paludis.rb +1 -0
  49. data/lib/chef/provider/package/portage.rb +2 -0
  50. data/lib/chef/provider/package/smartos.rb +1 -0
  51. data/lib/chef/provider/package/solaris.rb +2 -0
  52. data/lib/chef/provider/package/yum.rb +1 -0
  53. data/lib/chef/provider/package/zypper.rb +1 -0
  54. data/lib/chef/provider/service.rb +4 -22
  55. data/lib/chef/provider/service/debian.rb +2 -0
  56. data/lib/chef/provider/service/insserv.rb +2 -0
  57. data/lib/chef/provider/service/invokercd.rb +2 -0
  58. data/lib/chef/provider/service/openbsd.rb +1 -1
  59. data/lib/chef/provider/service/redhat.rb +2 -0
  60. data/lib/chef/provider/service/upstart.rb +3 -0
  61. data/lib/chef/provider_resolver.rb +59 -53
  62. data/lib/chef/resource.rb +22 -73
  63. data/lib/chef/resource/dsc_script.rb +1 -1
  64. data/lib/chef/resource/ips_package.rb +1 -0
  65. data/lib/chef/resource/mount.rb +8 -0
  66. data/lib/chef/resource/openbsd_package.rb +0 -11
  67. data/lib/chef/resource/solaris_package.rb +1 -4
  68. data/lib/chef/resource_resolver.rb +54 -26
  69. data/lib/chef/run_list/versioned_recipe_list.rb +6 -5
  70. data/lib/chef/user.rb +52 -188
  71. data/lib/chef/user_v1.rb +335 -0
  72. data/lib/chef/version.rb +1 -1
  73. data/spec/data/trusted_certs/opscode.pem +53 -56
  74. data/spec/functional/provider/whyrun_safe_ruby_block_spec.rb +1 -1
  75. data/spec/functional/resource/package_spec.rb +0 -2
  76. data/spec/integration/recipes/recipe_dsl_spec.rb +661 -126
  77. data/spec/spec_helper.rb +19 -13
  78. data/spec/support/shared/unit/api_versioning.rb +2 -2
  79. data/spec/unit/api_client_spec.rb +22 -201
  80. data/spec/unit/api_client_v1_spec.rb +457 -0
  81. data/spec/unit/knife/client_bulk_delete_spec.rb +4 -4
  82. data/spec/unit/knife/client_create_spec.rb +1 -1
  83. data/spec/unit/knife/client_delete_spec.rb +3 -3
  84. data/spec/unit/knife/client_edit_spec.rb +14 -1
  85. data/spec/unit/knife/client_list_spec.rb +1 -1
  86. data/spec/unit/knife/client_reregister_spec.rb +2 -2
  87. data/spec/unit/knife/client_show_spec.rb +2 -2
  88. data/spec/unit/knife/osc_user_create_spec.rb +5 -5
  89. data/spec/unit/knife/osc_user_delete_spec.rb +1 -1
  90. data/spec/unit/knife/osc_user_edit_spec.rb +1 -1
  91. data/spec/unit/knife/osc_user_list_spec.rb +1 -1
  92. data/spec/unit/knife/osc_user_reregister_spec.rb +1 -1
  93. data/spec/unit/knife/osc_user_show_spec.rb +1 -1
  94. data/spec/unit/knife/user_create_spec.rb +1 -1
  95. data/spec/unit/knife/user_delete_spec.rb +2 -2
  96. data/spec/unit/knife/user_edit_spec.rb +2 -2
  97. data/spec/unit/knife/user_list_spec.rb +1 -1
  98. data/spec/unit/knife/user_reregister_spec.rb +1 -1
  99. data/spec/unit/knife/user_show_spec.rb +2 -2
  100. data/spec/unit/lwrp_spec.rb +146 -134
  101. data/spec/unit/node_map_spec.rb +12 -0
  102. data/spec/unit/platform_spec.rb +1 -1
  103. data/spec/unit/provider/deploy_spec.rb +1 -1
  104. data/spec/unit/provider/dsc_resource_spec.rb +3 -3
  105. data/spec/unit/provider/dsc_script_spec.rb +2 -2
  106. data/spec/unit/provider_resolver_spec.rb +170 -135
  107. data/spec/unit/recipe_spec.rb +3 -3
  108. data/spec/unit/resource/breakpoint_spec.rb +1 -1
  109. data/spec/unit/resource/cron_spec.rb +1 -1
  110. data/spec/unit/resource/directory_spec.rb +1 -1
  111. data/spec/unit/resource/dsc_resource_spec.rb +1 -1
  112. data/spec/unit/resource/dsc_script_spec.rb +2 -2
  113. data/spec/unit/resource/env_spec.rb +1 -1
  114. data/spec/unit/resource/erl_call_spec.rb +1 -1
  115. data/spec/unit/resource/file_spec.rb +1 -1
  116. data/spec/unit/resource/group_spec.rb +1 -1
  117. data/spec/unit/resource/link_spec.rb +1 -1
  118. data/spec/unit/resource/mdadm_spec.rb +1 -1
  119. data/spec/unit/resource/mount_spec.rb +1 -1
  120. data/spec/unit/resource/ohai_spec.rb +1 -1
  121. data/spec/unit/resource/registry_key_spec.rb +1 -1
  122. data/spec/unit/resource/route_spec.rb +1 -1
  123. data/spec/unit/resource/ruby_block_spec.rb +3 -3
  124. data/spec/unit/resource/user_spec.rb +1 -1
  125. data/spec/unit/resource/windows_service_spec.rb +1 -1
  126. data/spec/unit/resource_resolver_spec.rb +8 -4
  127. data/spec/unit/resource_spec.rb +89 -3
  128. data/spec/unit/run_list/versioned_recipe_list_spec.rb +115 -48
  129. data/spec/unit/user_spec.rb +97 -405
  130. data/spec/unit/user_v1_spec.rb +584 -0
  131. metadata +11 -6
  132. data/lib/chef/osc_user.rb +0 -194
  133. data/spec/unit/osc_user_spec.rb +0 -276
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7c24dee2aa13014a1cbc3ab4577f5a4460412f9f
4
- data.tar.gz: 7ee73735afc1e3effecd6b8eaff0d0016587462b
3
+ metadata.gz: b412e48cbc6936db73ed9f4b7031907a98773382
4
+ data.tar.gz: 01a4d8d8dd35cbc12dcb337483b76c8a6ea4dd4d
5
5
  SHA512:
6
- metadata.gz: f46d9c7c2748126570d681f2a75b4916e8e808a89556419d4b337bf8c290769f51468e44d3751f8747866271666c646bcdd5011cf8f453ff86b6a103024665d5
7
- data.tar.gz: 13564560eb4ede717eb2a8a23d3d15020fec529921b471639289b3b6f55d5505df85f0add82ad4852b3a8387aa6339fdedbffd347d56255d91de7a7f46894d5d
6
+ metadata.gz: 5a6a6df87ff0d2b7c0cbeea10f593a40de81154bc19b1ae9ab211ed71f743cb86f8ae34c6f765081aa5b3602928b8bdf90bc9f3539a563714fc654bfd0b8e942
7
+ data.tar.gz: 5d1d47d3188faaa4a9a78f1fa3f31de9d2f113022a163e02556f050b1de6804c7b70ec9f2bbc8b125570a3c6449455676c335363352a1ff7ccb90d5f34dd0aa1
@@ -1,7 +1,7 @@
1
1
  #
2
- # Author:: Adam Jacob (<adam@chef.io>)
3
- # Author:: Nuo Yan (<nuo@chef.io>)
4
- # Copyright:: Copyright (c) 2008, 2015 Chef Software, Inc.
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: Nuo Yan (<nuo@opscode.com>)
4
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
5
5
  # License:: Apache License, Version 2.0
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,18 +23,18 @@ require 'chef/mixin/from_file'
23
23
  require 'chef/mash'
24
24
  require 'chef/json_compat'
25
25
  require 'chef/search/query'
26
- require 'chef/exceptions'
27
- require 'chef/mixin/api_version_request_handling'
28
26
  require 'chef/server_api'
29
27
 
28
+ # DEPRECATION NOTE
29
+ #
30
+ # This code will be removed in Chef 13 in favor of the code in Chef::ApiClientV1,
31
+ # which will be moved to this namespace. New development should occur in
32
+ # Chef::ApiClientV1 until the time before Chef 13.
30
33
  class Chef
31
34
  class ApiClient
32
35
 
33
36
  include Chef::Mixin::FromFile
34
37
  include Chef::Mixin::ParamsValidate
35
- include Chef::Mixin::ApiVersionRequestHandling
36
-
37
- SUPPORTED_API_VERSIONS = [0,1]
38
38
 
39
39
  # Create a new Chef::ApiClient object.
40
40
  def initialize
@@ -43,25 +43,6 @@ class Chef
43
43
  @private_key = nil
44
44
  @admin = false
45
45
  @validator = false
46
- @create_key = nil
47
- end
48
-
49
- def chef_rest_v0
50
- @chef_rest_v0 ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url], {:api_version => "0"})
51
- end
52
-
53
- def chef_rest_v1
54
- @chef_rest_v1 ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url], {:api_version => "1"})
55
- end
56
-
57
- # will default to the current version (Chef::Authenticator::DEFAULT_SERVER_API_VERSION)
58
- def http_api
59
- @http_api ||= Chef::REST.new(Chef::Config[:chef_server_url])
60
- end
61
-
62
- # will default to the current version (Chef::Authenticator::DEFAULT_SERVER_API_VERSION)
63
- def self.http_api
64
- Chef::REST.new(Chef::Config[:chef_server_url])
65
46
  end
66
47
 
67
48
  # Gets or sets the client name.
@@ -113,8 +94,7 @@ class Chef
113
94
  )
114
95
  end
115
96
 
116
- # Private key. The server will return it as a string.
117
- # Set to true under API V0 to have the server regenerate the default key.
97
+ # Gets or sets the private key.
118
98
  #
119
99
  # @params [Optional String] The string representation of the private key.
120
100
  # @return [String] The current value.
@@ -122,19 +102,7 @@ class Chef
122
102
  set_or_return(
123
103
  :private_key,
124
104
  arg,
125
- :kind_of => [String, TrueClass, FalseClass]
126
- )
127
- end
128
-
129
- # Used to ask server to generate key pair under api V1
130
- #
131
- # @params [Optional True/False] Should be true or false - default is false.
132
- # @return [True/False] The current value
133
- def create_key(arg=nil)
134
- set_or_return(
135
- :create_key,
136
- arg,
137
- :kind_of => [ TrueClass, FalseClass ]
105
+ :kind_of => [String, FalseClass]
138
106
  )
139
107
  end
140
108
 
@@ -145,14 +113,13 @@ class Chef
145
113
  def to_hash
146
114
  result = {
147
115
  "name" => @name,
116
+ "public_key" => @public_key,
148
117
  "validator" => @validator,
149
118
  "admin" => @admin,
150
119
  'json_class' => self.class.name,
151
120
  "chef_type" => "client"
152
121
  }
153
- result["private_key"] = @private_key unless @private_key.nil?
154
- result["public_key"] = @public_key unless @public_key.nil?
155
- result["create_key"] = @create_key unless @create_key.nil?
122
+ result["private_key"] = @private_key if @private_key
156
123
  result
157
124
  end
158
125
 
@@ -166,11 +133,10 @@ class Chef
166
133
  def self.from_hash(o)
167
134
  client = Chef::ApiClient.new
168
135
  client.name(o["name"] || o["clientname"])
136
+ client.private_key(o["private_key"]) if o.key?("private_key")
137
+ client.public_key(o["public_key"])
169
138
  client.admin(o["admin"])
170
139
  client.validator(o["validator"])
171
- client.private_key(o["private_key"]) if o.key?("private_key")
172
- client.public_key(o["public_key"]) if o.key?("public_key")
173
- client.create_key(o["create_key"]) if o.key?("create_key")
174
140
  client
175
141
  end
176
142
 
@@ -182,6 +148,10 @@ class Chef
182
148
  from_hash(Chef::JSONCompat.parse(j))
183
149
  end
184
150
 
151
+ def self.http_api
152
+ Chef::ServerAPI.new(Chef::Config[:chef_server_url], {:api_version => "0"})
153
+ end
154
+
185
155
  def self.reregister(name)
186
156
  api_client = load(name)
187
157
  api_client.reregister
@@ -218,11 +188,11 @@ class Chef
218
188
  # Save this client via the REST API, returns a hash including the private key
219
189
  def save
220
190
  begin
221
- update
191
+ http_api.put("clients/#{name}", { :name => self.name, :admin => self.admin, :validator => self.validator})
222
192
  rescue Net::HTTPServerException => e
223
193
  # If that fails, go ahead and try and update it
224
194
  if e.response.code == "404"
225
- create
195
+ http_api.post("clients", {:name => self.name, :admin => self.admin, :validator => self.validator })
226
196
  else
227
197
  raise e
228
198
  end
@@ -230,95 +200,18 @@ class Chef
230
200
  end
231
201
 
232
202
  def reregister
233
- # Try API V0 and if it fails due to V0 not being supported, raise the proper error message.
234
- # reregister only supported in API V0 or lesser.
235
- reregistered_self = chef_rest_v0.put("clients/#{name}", { :name => name, :admin => admin, :validator => validator, :private_key => true })
203
+ reregistered_self = http_api.put("clients/#{name}", { :name => name, :admin => admin, :validator => validator, :private_key => true })
236
204
  if reregistered_self.respond_to?(:[])
237
205
  private_key(reregistered_self["private_key"])
238
206
  else
239
207
  private_key(reregistered_self.private_key)
240
208
  end
241
209
  self
242
- rescue Net::HTTPServerException => e
243
- # if there was a 406 related to versioning, give error explaining that
244
- # only API version 0 is supported for reregister command
245
- if e.response.code == "406" && e.response["x-ops-server-api-version"]
246
- version_header = Chef::JSONCompat.from_json(e.response["x-ops-server-api-version"])
247
- min_version = version_header["min_version"]
248
- max_version = version_header["max_version"]
249
- error_msg = reregister_only_v0_supported_error_msg(max_version, min_version)
250
- raise Chef::Exceptions::OnlyApiVersion0SupportedForAction.new(error_msg)
251
- else
252
- raise e
253
- end
254
- end
255
-
256
- # Updates the client via the REST API
257
- def update
258
- # NOTE: API V1 dropped support for updating client keys via update (aka PUT),
259
- # but this code never supported key updating in the first place. Since
260
- # it was never implemented, we will simply ignore that functionality
261
- # as it is being deprecated.
262
- # Delete this comment after V0 support is dropped.
263
- payload = { :name => name }
264
- payload[:validator] = validator unless validator.nil?
265
-
266
- # DEPRECATION
267
- # This field is ignored in API V1, but left for backwards-compat,
268
- # can remove after API V0 is no longer supported.
269
- payload[:admin] = admin unless admin.nil?
270
-
271
- begin
272
- new_client = chef_rest_v1.put("clients/#{name}", payload)
273
- rescue Net::HTTPServerException => e
274
- # rescue API V0 if 406 and the server supports V0
275
- supported_versions = server_client_api_version_intersection(e, SUPPORTED_API_VERSIONS)
276
- raise e unless supported_versions && supported_versions.include?(0)
277
- new_client = chef_rest_v0.put("clients/#{name}", payload)
278
- end
279
-
280
- new_client
281
210
  end
282
211
 
283
212
  # Create the client via the REST API
284
213
  def create
285
- payload = {
286
- :name => name,
287
- :validator => validator,
288
- # this field is ignored in API V1, but left for backwards-compat,
289
- # can remove after OSC 11 support is finished?
290
- :admin => admin
291
- }
292
- begin
293
- # try API V1
294
- raise Chef::Exceptions::InvalidClientAttribute, "You cannot set both public_key and create_key for create." if !create_key.nil? && !public_key.nil?
295
-
296
- payload[:public_key] = public_key unless public_key.nil?
297
- payload[:create_key] = create_key unless create_key.nil?
298
-
299
- new_client = chef_rest_v1.post("clients", payload)
300
-
301
- # get the private_key out of the chef_key hash if it exists
302
- if new_client['chef_key']
303
- if new_client['chef_key']['private_key']
304
- new_client['private_key'] = new_client['chef_key']['private_key']
305
- end
306
- new_client['public_key'] = new_client['chef_key']['public_key']
307
- new_client.delete('chef_key')
308
- end
309
-
310
- rescue Net::HTTPServerException => e
311
- # rescue API V0 if 406 and the server supports V0
312
- supported_versions = server_client_api_version_intersection(e, SUPPORTED_API_VERSIONS)
313
- raise e unless supported_versions && supported_versions.include?(0)
314
-
315
- # under API V0, a key pair will always be created unless public_key is
316
- # passed on initial POST
317
- payload[:public_key] = public_key unless public_key.nil?
318
-
319
- new_client = chef_rest_v0.post("clients", payload)
320
- end
321
- Chef::ApiClient.from_hash(self.to_hash.merge(new_client))
214
+ http_api.post("clients", self)
322
215
  end
323
216
 
324
217
  # As a string
@@ -326,5 +219,14 @@ class Chef
326
219
  "client[#{@name}]"
327
220
  end
328
221
 
222
+ def inspect
223
+ "Chef::ApiClient name:'#{name}' admin:'#{admin.inspect}' validator:'#{validator}' " +
224
+ "public_key:'#{public_key}' private_key:'#{private_key}'"
225
+ end
226
+
227
+ def http_api
228
+ @http_api ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url], {:api_version => "0"})
229
+ end
230
+
329
231
  end
330
232
  end
@@ -0,0 +1,325 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@chef.io>)
3
+ # Author:: Nuo Yan (<nuo@chef.io>)
4
+ # Copyright:: Copyright (c) 2008, 2015 Chef Software, 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/mash'
24
+ require 'chef/json_compat'
25
+ require 'chef/search/query'
26
+ require 'chef/exceptions'
27
+ require 'chef/mixin/api_version_request_handling'
28
+ require 'chef/server_api'
29
+ require 'chef/api_client'
30
+
31
+ # COMPATIBILITY NOTE
32
+ #
33
+ # This ApiClientV1 code attempts to make API V1 requests and falls back to
34
+ # API V0 requests when it fails. New development should occur here instead
35
+ # of Chef::ApiClient as this will replace that namespace when Chef 13 is released.
36
+ #
37
+ # If you need to default to API V0 behavior (i.e. you need GET client to return
38
+ # a public key, etc), please use Chef::ApiClient and update your code to support
39
+ # API V1 before you pull in Chef 13.
40
+ class Chef
41
+ class ApiClientV1
42
+
43
+ include Chef::Mixin::FromFile
44
+ include Chef::Mixin::ParamsValidate
45
+ include Chef::Mixin::ApiVersionRequestHandling
46
+
47
+ SUPPORTED_API_VERSIONS = [0,1]
48
+
49
+ # Create a new Chef::ApiClientV1 object.
50
+ def initialize
51
+ @name = ''
52
+ @public_key = nil
53
+ @private_key = nil
54
+ @admin = false
55
+ @validator = false
56
+ @create_key = nil
57
+ end
58
+
59
+ def chef_rest_v0
60
+ @chef_rest_v0 ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url], {:api_version => "0", :inflate_json_class => false})
61
+ end
62
+
63
+ def chef_rest_v1
64
+ @chef_rest_v1 ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url], {:api_version => "1", :inflate_json_class => false})
65
+ end
66
+
67
+ def self.http_api
68
+ Chef::ServerAPI.new(Chef::Config[:chef_server_url], {:api_version => "1", :inflate_json_class => false})
69
+ end
70
+
71
+ # Gets or sets the client name.
72
+ #
73
+ # @params [Optional String] The name must be alpha-numeric plus - and _.
74
+ # @return [String] The current value of the name.
75
+ def name(arg=nil)
76
+ set_or_return(
77
+ :name,
78
+ arg,
79
+ :regex => /^[\-[:alnum:]_\.]+$/
80
+ )
81
+ end
82
+
83
+ # Gets or sets whether this client is an admin.
84
+ #
85
+ # @params [Optional True/False] Should be true or false - default is false.
86
+ # @return [True/False] The current value
87
+ def admin(arg=nil)
88
+ set_or_return(
89
+ :admin,
90
+ arg,
91
+ :kind_of => [ TrueClass, FalseClass ]
92
+ )
93
+ end
94
+
95
+ # Gets or sets the public key.
96
+ #
97
+ # @params [Optional String] The string representation of the public key.
98
+ # @return [String] The current value.
99
+ def public_key(arg=nil)
100
+ set_or_return(
101
+ :public_key,
102
+ arg,
103
+ :kind_of => String
104
+ )
105
+ end
106
+
107
+ # Gets or sets whether this client is a validator.
108
+ #
109
+ # @params [Boolean] whether or not the client is a validator. If
110
+ # `nil`, retrieves the already-set value.
111
+ # @return [Boolean] The current value
112
+ def validator(arg=nil)
113
+ set_or_return(
114
+ :validator,
115
+ arg,
116
+ :kind_of => [TrueClass, FalseClass]
117
+ )
118
+ end
119
+
120
+ # Private key. The server will return it as a string.
121
+ # Set to true under API V0 to have the server regenerate the default key.
122
+ #
123
+ # @params [Optional String] The string representation of the private key.
124
+ # @return [String] The current value.
125
+ def private_key(arg=nil)
126
+ set_or_return(
127
+ :private_key,
128
+ arg,
129
+ :kind_of => [String, TrueClass, FalseClass]
130
+ )
131
+ end
132
+
133
+ # Used to ask server to generate key pair under api V1
134
+ #
135
+ # @params [Optional True/False] Should be true or false - default is false.
136
+ # @return [True/False] The current value
137
+ def create_key(arg=nil)
138
+ set_or_return(
139
+ :create_key,
140
+ arg,
141
+ :kind_of => [ TrueClass, FalseClass ]
142
+ )
143
+ end
144
+
145
+ # The hash representation of the object. Includes the name and public_key.
146
+ # Private key is included if available.
147
+ #
148
+ # @return [Hash]
149
+ def to_hash
150
+ result = {
151
+ "name" => @name,
152
+ "validator" => @validator,
153
+ "admin" => @admin,
154
+ "chef_type" => "client"
155
+ }
156
+ result["private_key"] = @private_key unless @private_key.nil?
157
+ result["public_key"] = @public_key unless @public_key.nil?
158
+ result["create_key"] = @create_key unless @create_key.nil?
159
+ result
160
+ end
161
+
162
+ # The JSON representation of the object.
163
+ #
164
+ # @return [String] the JSON string.
165
+ def to_json(*a)
166
+ Chef::JSONCompat.to_json(to_hash, *a)
167
+ end
168
+
169
+ def self.from_hash(o)
170
+ client = Chef::ApiClientV1.new
171
+ client.name(o["name"] || o["clientname"])
172
+ client.admin(o["admin"])
173
+ client.validator(o["validator"])
174
+ client.private_key(o["private_key"]) if o.key?("private_key")
175
+ client.public_key(o["public_key"]) if o.key?("public_key")
176
+ client.create_key(o["create_key"]) if o.key?("create_key")
177
+ client
178
+ end
179
+
180
+ def self.from_json(j)
181
+ Chef::ApiClientV1.from_hash(Chef::JSONCompat.from_json(j))
182
+ end
183
+
184
+ def self.reregister(name)
185
+ api_client = Chef::ApiClientV1.load(name)
186
+ api_client.reregister
187
+ end
188
+
189
+ def self.list(inflate=false)
190
+ if inflate
191
+ response = Hash.new
192
+ Chef::Search::Query.new.search(:client) do |n|
193
+ n = self.from_hash(n) if n.instance_of?(Hash)
194
+ response[n.name] = n
195
+ end
196
+ response
197
+ else
198
+ http_api.get("clients")
199
+ end
200
+ end
201
+
202
+ # Load a client by name via the API
203
+ def self.load(name)
204
+ response = http_api.get("clients/#{name}")
205
+ Chef::ApiClientV1.from_hash(response)
206
+ end
207
+
208
+ # Remove this client via the REST API
209
+ def destroy
210
+ chef_rest_v1.delete("clients/#{@name}")
211
+ end
212
+
213
+ # Save this client via the REST API, returns a hash including the private key
214
+ def save
215
+ begin
216
+ update
217
+ rescue Net::HTTPServerException => e
218
+ # If that fails, go ahead and try and update it
219
+ if e.response.code == "404"
220
+ create
221
+ else
222
+ raise e
223
+ end
224
+ end
225
+ end
226
+
227
+ def reregister
228
+ # Try API V0 and if it fails due to V0 not being supported, raise the proper error message.
229
+ # reregister only supported in API V0 or lesser.
230
+ reregistered_self = chef_rest_v0.put("clients/#{name}", { :name => name, :admin => admin, :validator => validator, :private_key => true })
231
+ if reregistered_self.respond_to?(:[])
232
+ private_key(reregistered_self["private_key"])
233
+ else
234
+ private_key(reregistered_self.private_key)
235
+ end
236
+ self
237
+ rescue Net::HTTPServerException => e
238
+ # if there was a 406 related to versioning, give error explaining that
239
+ # only API version 0 is supported for reregister command
240
+ if e.response.code == "406" && e.response["x-ops-server-api-version"]
241
+ version_header = Chef::JSONCompat.from_json(e.response["x-ops-server-api-version"])
242
+ min_version = version_header["min_version"]
243
+ max_version = version_header["max_version"]
244
+ error_msg = reregister_only_v0_supported_error_msg(max_version, min_version)
245
+ raise Chef::Exceptions::OnlyApiVersion0SupportedForAction.new(error_msg)
246
+ else
247
+ raise e
248
+ end
249
+ end
250
+
251
+ # Updates the client via the REST API
252
+ def update
253
+ # NOTE: API V1 dropped support for updating client keys via update (aka PUT),
254
+ # but this code never supported key updating in the first place. Since
255
+ # it was never implemented, we will simply ignore that functionality
256
+ # as it is being deprecated.
257
+ # Delete this comment after V0 support is dropped.
258
+ payload = { :name => name }
259
+ payload[:validator] = validator unless validator.nil?
260
+
261
+ # DEPRECATION
262
+ # This field is ignored in API V1, but left for backwards-compat,
263
+ # can remove after API V0 is no longer supported.
264
+ payload[:admin] = admin unless admin.nil?
265
+
266
+ begin
267
+ new_client = chef_rest_v1.put("clients/#{name}", payload)
268
+ rescue Net::HTTPServerException => e
269
+ # rescue API V0 if 406 and the server supports V0
270
+ supported_versions = server_client_api_version_intersection(e, SUPPORTED_API_VERSIONS)
271
+ raise e unless supported_versions && supported_versions.include?(0)
272
+ new_client = chef_rest_v0.put("clients/#{name}", payload)
273
+ end
274
+
275
+ Chef::ApiClientV1.from_hash(new_client)
276
+ end
277
+
278
+ # Create the client via the REST API
279
+ def create
280
+ payload = {
281
+ :name => name,
282
+ :validator => validator,
283
+ # this field is ignored in API V1, but left for backwards-compat,
284
+ # can remove after OSC 11 support is finished?
285
+ :admin => admin
286
+ }
287
+ begin
288
+ # try API V1
289
+ raise Chef::Exceptions::InvalidClientAttribute, "You cannot set both public_key and create_key for create." if !create_key.nil? && !public_key.nil?
290
+
291
+ payload[:public_key] = public_key unless public_key.nil?
292
+ payload[:create_key] = create_key unless create_key.nil?
293
+
294
+ new_client = chef_rest_v1.post("clients", payload)
295
+
296
+ # get the private_key out of the chef_key hash if it exists
297
+ if new_client['chef_key']
298
+ if new_client['chef_key']['private_key']
299
+ new_client['private_key'] = new_client['chef_key']['private_key']
300
+ end
301
+ new_client['public_key'] = new_client['chef_key']['public_key']
302
+ new_client.delete('chef_key')
303
+ end
304
+
305
+ rescue Net::HTTPServerException => e
306
+ # rescue API V0 if 406 and the server supports V0
307
+ supported_versions = server_client_api_version_intersection(e, SUPPORTED_API_VERSIONS)
308
+ raise e unless supported_versions && supported_versions.include?(0)
309
+
310
+ # under API V0, a key pair will always be created unless public_key is
311
+ # passed on initial POST
312
+ payload[:public_key] = public_key unless public_key.nil?
313
+
314
+ new_client = chef_rest_v0.post("clients", payload)
315
+ end
316
+ Chef::ApiClientV1.from_hash(self.to_hash.merge(new_client))
317
+ end
318
+
319
+ # As a string
320
+ def to_s
321
+ "client[#{@name}]"
322
+ end
323
+
324
+ end
325
+ end