diff options
author | danielsdeleo <dan@opscode.com> | 2012-12-18 10:47:24 -0800 |
---|---|---|
committer | danielsdeleo <dan@opscode.com> | 2012-12-18 17:10:05 -0800 |
commit | a61c9865684466adcc9c933f05eebc1090624ea0 (patch) | |
tree | 224e1719aa7a49a2cd3e1e3c7265d204701121b5 /lib/chef/api_client | |
parent | 2de707d27251f38790a71043843749a570302aaf (diff) | |
download | chef-a61c9865684466adcc9c933f05eebc1090624ea0.tar.gz |
[CHEF-3689] Extract registration to a class
Diffstat (limited to 'lib/chef/api_client')
-rw-r--r-- | lib/chef/api_client/registration.rb | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/lib/chef/api_client/registration.rb b/lib/chef/api_client/registration.rb new file mode 100644 index 0000000000..d961e23ac2 --- /dev/null +++ b/lib/chef/api_client/registration.rb @@ -0,0 +1,110 @@ +# +# Author:: Daniel DeLeo (<dan@opscode.com>) +# Copyright:: Copyright (c) 2012 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/config' +require 'chef/rest' +require 'chef/exceptions' + +class Chef + class ApiClient + + # ==Chef::ApiClient::Registration + # Manages the process of creating or updating a Chef::ApiClient on the + # server and writing the resulting private key to disk. Registration uses + # the validator credentials for its API calls. This allows it to bootstrap + # a new client/node identity by borrowing the validator client identity + # when creating a new client. + class Registration + attr_reader :private_key + attr_reader :destination + attr_reader :name + + def initialize(name, destination) + @name = name + @destination = destination + @private_key = nil + end + + # Runs the client registration process, including creating the client on + # the chef-server and writing its private key to disk. + def run + assert_destination_writable! + retries = Config[:client_registration_retries] || 5 + begin + create_or_update + rescue Net::HTTPFatalError => e + # only retry 500s + raise if retries <= 0 or e.response.code != "500" + retries -= 1 + Chef::Log.warn("Failed to register new client, #{retries} tries remaining") + retry + end + write_key + end + + def assert_destination_writable! + if (File.exists?(destination) && !File.writable?(destination)) + raise Chef::Exceptions::CannotWritePrivateKey, "I cannot write your private key to #{destination} - check permissions?" + end + end + + def write_key + ::File.open(destination, File::CREAT|File::TRUNC|File::RDWR|File::NOFOLLOW, 0600) do |f| + f.print(private_key) + end + rescue IOError => e + raise Chef::Exceptions::CannotWritePrivateKey, "Error writing private key to #{destination}: #{e}" + end + + def create_or_update + create + rescue Net::HTTPServerException => e + # If create fails because the client exists, attempt to update. This + # requires admin privileges. + raise unless e.response.code == "409" + update + end + + def create + response = http_api.post("clients", :name => name, :admin => false) + @private_key = response["private_key"] + response + end + + def update + response = http_api.put("clients/#{name}", :name => name, + :admin => false, + :private_key => true) + if response.respond_to?(:private_key) # Chef 11 + @private_key = response.private_key + else # Chef 10 + @private_key = response["private_key"] + end + response + end + + def http_api + @http_api_as_validator ||= Chef::REST.new(Chef::Config[:chef_server_url], + Chef::Config[:validation_client_name], + Chef::Config[:validation_key]) + end + end + end +end + + |