lib/ridley/resources/node_resource.rb in ridley-0.10.0.rc1 vs lib/ridley/resources/node_resource.rb in ridley-0.10.0.rc2

- old
+ new

@@ -1,6 +1,6 @@ -module Ridley +module Ridley # @author Jamie Winsor <reset@riotgames.com> class NodeResource < Ridley::Resource class << self # @overload bootstrap(client, nodes, options = {}) # @param [Ridley::Client] client @@ -52,10 +52,69 @@ options = default_options.merge(options) Bootstrapper.new(args, options).run end + # Executes a Chef run using the best worker available for the given + # host. + # + # @param [Ridley::Client] client + # @param [String] host + # + # @return [HostConnector::Response] + def chef_run(client, host) + worker = configured_worker_for(client, host) + worker.chef_client + ensure + worker.terminate if worker && worker.alive? + end + + # Puts a secret on the host using the best worker available for + # the given host. + # + # @param [Ridley::Client] client + # @param [String] host + # @param [String] encrypted_data_bag_secret_path + # + # @return [HostConnector::Response] + def put_secret(client, host, encrypted_data_bag_secret_path) + worker = configured_worker_for(client, host) + worker.put_secret(encrypted_data_bag_secret_path) + ensure + worker.terminate if worker && worker.alive? + end + + # Executes an arbitrary ruby script using the best worker available + # for the given host. + # + # @param [Ridley::Client] client + # @param [String] host + # @param [Array<String>] command_lines + # + # @return [HostConnector::Response] + def ruby_script(client, host, command_lines) + worker = configured_worker_for(client, host) + worker.ruby_script(command_lines) + ensure + worker.terminate if worker && worker.alive? + end + + # Executes the given command on a node using the best worker + # available for the given host. + # + # @param [Ridley::Client] client + # @param [String] host + # @param [String] command + # + # @return [Array<Symbol, HostConnector::Response>] + def execute_command(client, host, command) + worker = configured_worker_for(client, host) + worker.run(command) + ensure + worker.terminate if worker && worker.alive? + end + # Merges the given data with the the data of the target node on the remote # # @param [Ridley::Client] client # @param [Ridley::NodeResource, String] target # node or identifier of the node to merge @@ -70,12 +129,29 @@ # # @return [Ridley::NodeResource] def merge_data(client, target, options = {}) find!(client, target).merge_data(options) end + + private + # @param [Ridley::Client] client + # @param [String] host + # + # @return [SSH::Worker, WinRM::Worker] + def configured_worker_for(client, host) + connector_options = Hash.new + connector_options[:ssh] = client.ssh + connector_options[:winrm] = client.winrm + + HostConnector.best_connector_for(host, connector_options) do |host_connector| + host_connector::Worker.new(host, connector_options) + end + end end + include Ridley::Logging + set_chef_id "name" set_chef_type "node" set_chef_json_class "Chef::Node" set_resource_path "nodes" @@ -112,12 +188,12 @@ # Set a node level normal attribute given the dotted path representation of the Chef # attribute and value. # # @note It is not possible to set any other attribute level on a node and have it persist after - # a Chef Run. This is because all other attribute levels are truncated at the start of a Chef Run. - # + # a Chef Run. This is because all other attribute levels are truncated at the start of a Chef Run. + # # @example setting and saving a node level normal attribute # # obj = node.find("jwinsor-1") # obj.set_chef_attribute("my_app.billing.enabled", false) # obj.save @@ -163,11 +239,11 @@ # node_3.cloud_provider => "rackspace" # node_4.cloud_provider => nil # # @return [nil, String] def cloud_provider - self.cloud? ? self.automatic[:cloud][:provider] : nil + self.cloud? ? self.automatic[:cloud][:provider] : nil end # Returns true if the node is identified as a cloud node. # # @return [Boolean] @@ -194,46 +270,57 @@ # @return [Boolean] def rackspace? self.cloud_provider == "rackspace" end - # Run Chef-Client on the instantiated node + # Run Chef-Client on the instantiated node. # # @param [Hash] options - # a hash of options to pass to {Ridley::SSH.start} + # a hash of options to pass to the best {Ridley::HostConnector} # - # @return [SSH::Response] + # @return [HostConnector::Response] def chef_client(options = {}) - options = client.ssh.merge(options) + connector_options = Hash.new + connector_options[:ssh] = client.ssh + connector_options[:winrm] = client.winrm + connector_options.merge(options) - Ridley.log.debug "Running Chef Client on: #{self.public_hostname}" - Ridley::SSH.start(self, options) do |ssh| - ssh.run("sudo chef-client").first + log.debug "Running Chef Client on: #{self.public_hostname}" + + HostConnector.best_connector_for(self.public_hostname, connector_options) do |host_connector| + host_connector.start(self, connector_options) do |connector| + _, response = connector.chef_client + response + end end end # Put the client's encrypted data bag secret onto the instantiated node. If no # encrypted data bag key path is set on the resource's client then nil will be # returned # # @param [Hash] options - # a hash of options to pass to {Ridley::SSH.start} + # a hash of options to pass to the best {Ridley::HostConnector} # - # @return [SSH::Response, nil] + # @return [HostConnector::Response, nil] def put_secret(options = {}) if client.encrypted_data_bag_secret_path.nil? || !File.exists?(client.encrypted_data_bag_secret_path) return nil end - options = client.ssh.merge(options) - secret = File.read(client.encrypted_data_bag_secret_path).chomp - command = "echo '#{secret}' > /etc/chef/encrypted_data_bag_secret; chmod 0600 /etc/chef/encrypted_data_bag_secret" + connector_options = Hash.new + connector_options[:ssh] = client.ssh + connector_options[:winrm] = client.winrm - Ridley.log.debug "Writing Encrypted Data Bag Secret to: #{self.public_hostname}" - Ridley::SSH.start(self, options) do |ssh| - ssh.run(command).first + log.debug "Writing Encrypted Data Bag Secret to: #{self.public_hostname}" + + HostConnector.best_connector_for(self.public_hostname, connector_options) do |host_connector| + host_connector.start(self, connector_options) do |connector| + _, response = connector.put_secret(client.encrypted_data_bag_secret_path) + response + end end end # Merges the instaniated nodes data with the given data and updates # the remote with the merged results