chef 12.4.0-universal-mingw32 → 12.4.1-universal-mingw32

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 (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: bcb980c409f1addd0865425c6e6a2f2ca023392a
4
- data.tar.gz: 397ce0b10766fd3d13482f68cd6949d9cc33caf3
3
+ metadata.gz: b62abc59f169a26e583a4a04ace42b7feb5f7a74
4
+ data.tar.gz: f09491db90a4b0fd6ca253a46d4859a922b1e5a3
5
5
  SHA512:
6
- metadata.gz: e9fa764de5bd4b56e3b1faf5887e2dadd1b1b9a0a8fc590f2f451d8cffe535661f03634364c83686c60d8a8a925b593167ccd9169dfe7af9aed5ffd471264b9c
7
- data.tar.gz: 4452f6a6cf351c1efa9d9f1e96bf913bc77893f0eca035921b78aa64a0535c03705002363b1910a2bad65a09d3ceb57f205194ba72bda5f625f6e0ae9d69c955
6
+ metadata.gz: 1f5d531e917b520e43c230202965443e5002b11f73363e3b237127547c0f34b4720fa38fc705fa0468fcf1644717616449fadd51e61f26956cb0b5df423fd576
7
+ data.tar.gz: 5e57366bb87b9f38bb53060818e5950c28de944383261e86d7445a923054d5fc9e97febc61b961a641f5a096a1c1d96c1c5e6b01939ddab949bddc9cdb6b627d
@@ -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