ridley-connectors 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +10 -0
  5. data/CHANGELOG.md +8 -0
  6. data/Gemfile +18 -0
  7. data/Guardfile +22 -0
  8. data/LICENSE +16 -0
  9. data/README.md +107 -0
  10. data/Thorfile +39 -0
  11. data/lib/ridley-connectors/chef_objects/node_object.rb +17 -0
  12. data/lib/ridley-connectors/client.rb +54 -0
  13. data/lib/ridley-connectors/host_commander.rb +231 -0
  14. data/lib/ridley-connectors/host_connector/response.rb +27 -0
  15. data/lib/ridley-connectors/host_connector/ssh.rb +211 -0
  16. data/lib/ridley-connectors/host_connector/winrm/command_uploader.rb +87 -0
  17. data/lib/ridley-connectors/host_connector/winrm.rb +218 -0
  18. data/lib/ridley-connectors/host_connector.rb +83 -0
  19. data/lib/ridley-connectors/resources/node_resource.rb +198 -0
  20. data/lib/ridley-connectors/version.rb +5 -0
  21. data/lib/ridley-connectors.rb +11 -0
  22. data/ridley-connectors.gemspec +27 -0
  23. data/spec/fixtures/encrypted_data_bag_secret +1 -0
  24. data/spec/fixtures/my-fake.pem +27 -0
  25. data/spec/spec_helper.rb +40 -0
  26. data/spec/support/actor_mocking.rb +9 -0
  27. data/spec/support/spec_helpers.rb +20 -0
  28. data/spec/unit/ridley-connectors/chef_objects/node_object_spec.rb +22 -0
  29. data/spec/unit/ridley-connectors/client_spec.rb +32 -0
  30. data/spec/unit/ridley-connectors/host_commander_spec.rb +173 -0
  31. data/spec/unit/ridley-connectors/host_connector/ssh_spec.rb +57 -0
  32. data/spec/unit/ridley-connectors/host_connector/winrm/command_uploader_spec.rb +67 -0
  33. data/spec/unit/ridley-connectors/host_connector/winrm_spec.rb +145 -0
  34. data/spec/unit/ridley-connectors/host_connector_spec.rb +50 -0
  35. data/spec/unit/ridley-connectors/resources/node_resource_spec.rb +139 -0
  36. metadata +178 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c1d5f17ffd3feb5cafb982a127e2395f533e8413
4
+ data.tar.gz: 489a86773e6532a1e39896062c4057625cd64d0e
5
+ SHA512:
6
+ metadata.gz: 0e0d43263f510aafd2f797e00d6401af61bd6f98dce4461804de9d6c538808b709c45eef96ed2ea963ad61af8255da5cd0a19936b84fd6293a747a5f0792568d
7
+ data.tar.gz: b4e15afa128530307f6b21c8dc857a6c26c1807d5ed53aecd3461efd68a126fee293eb6395bcb2be96522a71cd4374d766473f712a158d5624906af228ec8d31
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.sw[op]
19
+ .DS_Store
20
+ .rspec
21
+ .bin/
22
+ vendor/
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0-p247
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ script: "bundle exec thor spec:all"
2
+ language: ruby
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - jruby-19mode
7
+ matrix:
8
+ allow_failures:
9
+ - rvm: jruby-19mode
10
+ bundler_args: --without development
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ ## v.1.0.1
2
+
3
+ * [#3](https://github.com/RiotGames/ridley-connectors/pull/3) Fix the broken Ridley::Client
4
+
5
+ ## v.1.0.0
6
+
7
+ * [Ridley #227](https://github.com/RiotGames/ridley/pull/227) Move code out of Ridley and into its own gem
8
+ * See the [Ridley 2.0.0 Changelog](https://github.com/RiotGames/ridley/blob/v2.0.0/CHANGELOG.md) for more details.
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'yard'
7
+ gem 'spork'
8
+ gem 'guard', '>= 1.5.0'
9
+ gem 'guard-yard'
10
+ gem 'guard-rspec'
11
+ gem 'guard-spork', platforms: :ruby
12
+ end
13
+
14
+ group :test do
15
+ gem 'rspec', '~> 2.14.0'
16
+ gem 'webmock'
17
+ gem 'thor'
18
+ end
data/Guardfile ADDED
@@ -0,0 +1,22 @@
1
+ notification :off
2
+
3
+ guard 'spork' do
4
+ watch('Gemfile')
5
+ watch('spec/spec_helper.rb') { :rspec }
6
+ watch(%r{^spec/support/.+\.rb$}) { :rspec }
7
+ end
8
+
9
+ guard 'yard', stdout: '/dev/null', stderr: '/dev/null' do
10
+ watch(%r{app/.+\.rb})
11
+ watch(%r{lib/.+\.rb})
12
+ watch(%r{ext/.+\.c})
13
+ end
14
+
15
+ guard 'rspec', cli: "--color --drb --format Fuubar", all_on_start: false, all_after_pass: false do
16
+ watch(%r{^spec/unit/.+_spec\.rb$})
17
+ watch(%r{^spec/acceptance/.+_spec\.rb$})
18
+
19
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
20
+ watch('spec/spec_helper.rb') { "spec" }
21
+ watch(%r{^spec/support/.+\.rb$}) { "spec" }
22
+ end
data/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ Copyright 2012-2013 Riot Games
2
+
3
+ Jamie Winsor (<jamie@vialstudios.com>)
4
+ Kyle Allan (<kallan@riotgames.com>)
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # Ridley Connectors
2
+ [![Gem Version](https://badge.fury.io/rb/ridley-connectors.png)](http://badge.fury.io/rb/ridley-connectors)
3
+ [![Build Status](https://secure.travis-ci.org/RiotGames/ridley-connectors.png?branch=master)](http://travis-ci.org/RiotGames/ridley-connectors)
4
+ [![Dependency Status](https://gemnasium.com/RiotGames/ridley-connectors.png?travis)](https://gemnasium.com/RiotGames/ridley-connectors)
5
+ [![Code Climate](https://codeclimate.com/github/RiotGames/ridley-connectors.png)](https://codeclimate.com/github/RiotGames/ridley-connectors)
6
+
7
+ An extension on [Ridley](https://github.com/RiotGames/ridley) adding support for connecting and communicating with nodes in Chef.
8
+
9
+ Installation
10
+ ------------
11
+ Add ridley-connectors to your `Gemfile`:
12
+
13
+ ```ruby
14
+ gem 'ridley-connectors'
15
+ ```
16
+
17
+ And run the `bundle` command to install. Alternatively, you can install the gem directly:
18
+
19
+ $ gem install ridley-connectors
20
+
21
+ Usage
22
+ -----
23
+ You can use ridley-connectors just like using Ridley.
24
+
25
+ ```ruby
26
+ require 'ridley'
27
+ ```
28
+
29
+ ### Creating a new Ridley client
30
+
31
+ ```ruby
32
+ ridley = Ridley.new(
33
+ server_url: "https://api.opscode.com/organizations/ridley",
34
+ client_name: "me",
35
+ client_key: "/Users/me/.chef/me.pem"
36
+ )
37
+ ```
38
+
39
+ ridley-connectors exposes all the usual features of Ridley, but adds some sugar for interacting with nodes.
40
+
41
+ ```ruby
42
+ ridley.node.bootstrap("hostname.to.bootstrap.com") # Bootstraps a hostname or IP
43
+ ridley.node.put_secret("hostname") # Puts your configured encrypted data bag secret onto a hostname or IP
44
+ ridley.node.chef_run("hostname") # Runs Chef on a hostname or IP
45
+
46
+ ```
47
+ Node Resource
48
+ -------------
49
+
50
+ ### Bootstrapping Unix nodes
51
+
52
+ ```ruby
53
+ ridley = Ridley.new(
54
+ server_url: "https://api.opscode.com",
55
+ organization: "vialstudios",
56
+ validator_client: "vialstudios-validator",
57
+ validator_path: "/Users/reset/.chef/vialstudios-validator.pem",
58
+ ssh: {
59
+ user: "vagrant",
60
+ password: "vagrant"
61
+ }
62
+ )
63
+
64
+ ridley.node.bootstrap("33.33.33.10", "33.33.33.11")
65
+ ```
66
+
67
+ ### Bootstrapping Windows Nodes
68
+
69
+ Windows Nodes are bootstrapped using a combination of WinRM, Batch, and PowerShell. You will probably need to tweak some settings on your Windows servers to ensure the commands are successful.
70
+
71
+ #### WinRM Settings
72
+
73
+ 1. Enable WinRM: `winrm quickconfig` and say Yes.
74
+ 2. Set some WinRM settings to ensure that you don't get 401 Unauthorized responses and 500 Responses because of timeouts.
75
+
76
+ ```
77
+ winrm set winrm/config/service/auth @{Basic="true"}
78
+ winrm set winrm/config/service @{AllowUnencrypted="true"}
79
+ winrm set winrm/config/service @{EnumerationTimeoutms="600000"}
80
+ winrm set winrm/config @{MaxTimeoutms="600000"}
81
+ winrm set winrm/config/client @{TrustedHosts="*"}
82
+ ```
83
+
84
+ #### PowerShell Settings
85
+
86
+ 1. You should also configure your PowerShell profile, so that PowerShell commands have a more lenient timeout period.
87
+
88
+ ```
89
+ mkdir C:\Users\my_user\Documents\WindowsPowerShell
90
+ echo "$PSSessionOption = New-PSSessionOption -OpenTimeout 0 -CancelTimeout 0 -IdleTimeout 0 -OperationTimeout 0" > C:\Users\my_user\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
91
+ ```
92
+
93
+ Verify the PowerShell settings by opening up the PowerShell Console and entering `$PSSessionOption` and ensure those values are set, and that there are no errors output.
94
+
95
+ The following links offer some information about configuring a machine's PowerShell settings:
96
+ - [PowerShell Profiles](http://technet.microsoft.com/en-us/library/ee692764.aspx)
97
+ - [The $PSSessionOptions Preference Variable](http://technet.microsoft.com/library/hh847796.aspx)
98
+ - [Creating a new PSSessionOption](http://technet.microsoft.com/en-us/library/hh849703.aspx)
99
+
100
+ You may also want to tweak your Windows boxes a bit more ex: turning UAC off, turning off the Windows Firewall.
101
+
102
+ Authors and Contributors
103
+ ------------------------
104
+ - Jamie Winsor (<jamie@vialstudios.com>)
105
+ - Kyle Allan (<kallan@riotgames.com>)
106
+
107
+ Thank you to all of our [Contributors](https://github.com/RiotGames/ridley-connectors/graphs/contributors), testers, and users.
data/Thorfile ADDED
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ require 'bundler'
5
+ require 'bundler/setup'
6
+ require 'ridley-connectors'
7
+
8
+ class Default < Thor
9
+
10
+ require 'thor/rake_compat'
11
+
12
+ include Thor::RakeCompat
13
+ Bundler::GemHelper.install_tasks
14
+
15
+ desc "build", "Build ridley-connectors-#{Ridley::Connectors::VERSION}.gem into the pkg directory"
16
+ def build
17
+ Rake::Task["build"].execute
18
+ end
19
+
20
+ desc "install", "Build and install ridley-connectors-#{Ridley::Connectors::VERSION}.gem into system gems"
21
+ def install
22
+ Rake::Task["install"].execute
23
+ end
24
+
25
+ desc "release", "Create tag v#{Ridley::Connectors::VERSION} and build and push ridley-connectors-#{Ridley::Connectors::VERSION}.gem to Rubygems"
26
+ def release
27
+ Rake::Task["release"].execute
28
+ end
29
+
30
+ class Spec < Thor
31
+ namespace :spec
32
+ default_task :all
33
+
34
+ desc "all", "run all tests"
35
+ def all
36
+ exec "rspec --color --format=documentation spec"
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,17 @@
1
+ module Ridley
2
+ class NodeObject
3
+ # Executes a Chef run on the node
4
+ #
5
+ # @return [HostConnector::Response]
6
+ def chef_run
7
+ resource.chef_run(self.public_hostname)
8
+ end
9
+
10
+ # Puts the configured encrypted data bag secret on the node
11
+ #
12
+ # @return [HostConnector::Response]
13
+ def put_secret
14
+ resource.put_secret(self.public_hostname)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,54 @@
1
+ module Ridley
2
+ class Client
3
+ attr_accessor :ssh
4
+ attr_accessor :winrm
5
+
6
+ # @option options [String] :server_url
7
+ # URL to the Chef API
8
+ # @option options [String] :client_name
9
+ # name of the client used to authenticate with the Chef API
10
+ # @option options [String] :client_key
11
+ # filepath to the client's private key used to authenticate with the Chef API
12
+ # @option options [String] :validator_client (nil)
13
+ # @option options [String] :validator_path (nil)
14
+ # @option options [String] :encrypted_data_bag_secret_path (nil)
15
+ # @option options [Hash] :ssh (Hash.new)
16
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on (required)
17
+ # * :password (String) the password for the shell user that will perform the bootstrap
18
+ # * :keys (Array, String) an array of keys (or a single key) to authenticate the ssh user with instead of a password
19
+ # * :timeout (Float) [5.0] timeout value for SSH bootstrap
20
+ # * :sudo (Boolean) [true] bootstrap with sudo
21
+ # @option options [Hash] :winrm (Hash.new)
22
+ # * :user (String) a user that will login to each node and perform the bootstrap command on (required)
23
+ # * :password (String) the password for the user that will perform the bootstrap
24
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
25
+ # @option options [String] :chef_version
26
+ # the version of Chef to use when bootstrapping
27
+ # @option options [Hash] :params
28
+ # URI query unencoded key/value pairs
29
+ # @option options [Hash] :headers
30
+ # unencoded HTTP header key/value pairs
31
+ # @option options [Hash] :request
32
+ # request options
33
+ # @option options [Hash] :ssl
34
+ # * :verify (Boolean) [true] set to false to disable SSL verification
35
+ # @option options [URI, String, Hash] :proxy
36
+ # URI, String, or Hash of HTTP proxy options
37
+ # @option options [Integer] :pool_size (4)
38
+ # size of the connection pool
39
+ #
40
+ # @raise [Errors::ClientKeyFileNotFoundOrInvalid] if the option for :client_key does not contain
41
+ # a file path pointing to a readable client key, or is a string containing a valid key
42
+ alias_method :old_initialize, :initialize
43
+ def initialize(options = {})
44
+ old_initialize(options)
45
+ @options = options.reverse_merge(
46
+ ssh: Hash.new,
47
+ winrm: Hash.new,
48
+ ).deep_symbolize_keys
49
+
50
+ @ssh = @options[:ssh]
51
+ @winrm = @options[:winrm]
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,231 @@
1
+ module Ridley
2
+ class ConnectorSupervisor < ::Celluloid::SupervisionGroup
3
+ # @param [Celluloid::Registry] registry
4
+ def initialize(registry)
5
+ super(registry)
6
+ supervise_as :ssh, HostConnector::SSH
7
+ supervise_as :winrm, HostConnector::WinRM
8
+ end
9
+ end
10
+
11
+ class HostCommander
12
+ include Celluloid
13
+ include Ridley::Logging
14
+
15
+ PORT_CHECK_TIMEOUT = 3
16
+
17
+ finalizer :finalize_callback
18
+
19
+ def initialize
20
+ @connector_registry = Celluloid::Registry.new
21
+ @connector_supervisor = ConnectorSupervisor.new_link(@connector_registry)
22
+ end
23
+
24
+ # Execute a shell command on a node
25
+ #
26
+ # @param [String] host
27
+ # the host to perform the action on
28
+ # @param [String] command
29
+ #
30
+ # @option options [Hash] :ssh
31
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on
32
+ # * :password (String) the password for the shell user that will perform the bootstrap
33
+ # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
34
+ # * :timeout (Float) timeout value for SSH bootstrap (5.0)
35
+ # * :sudo (Boolean) run as sudo
36
+ # @option options [Hash] :winrm
37
+ # * :user (String) a user that will login to each node and perform the bootstrap command on
38
+ # * :password (String) the password for the user that will perform the bootstrap (required)
39
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
40
+ #
41
+ # @return [HostConnector::Response]
42
+ def run(host, command, options = {})
43
+ execute(__method__, host, command, options)
44
+ end
45
+
46
+ # Bootstrap a node
47
+ #
48
+ # @param [String] host
49
+ # the host to perform the action on
50
+ #
51
+ # @option options [Hash] :ssh
52
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on
53
+ # * :password (String) the password for the shell user that will perform the bootstrap
54
+ # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
55
+ # * :timeout (Float) timeout value for SSH bootstrap (5.0)
56
+ # * :sudo (Boolean) run as sudo
57
+ # @option options [Hash] :winrm
58
+ # * :user (String) a user that will login to each node and perform the bootstrap command on
59
+ # * :password (String) the password for the user that will perform the bootstrap (required)
60
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
61
+ #
62
+ # @return [HostConnector::Response]
63
+ def bootstrap(host, options = {})
64
+ execute(__method__, host, options)
65
+ end
66
+
67
+ # Perform a chef client run on a node
68
+ #
69
+ # @param [String] host
70
+ # the host to perform the action on
71
+ #
72
+ # @option options [Hash] :ssh
73
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on
74
+ # * :password (String) the password for the shell user that will perform the bootstrap
75
+ # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
76
+ # * :timeout (Float) timeout value for SSH bootstrap (5.0)
77
+ # * :sudo (Boolean) run as sudo
78
+ # @option options [Hash] :winrm
79
+ # * :user (String) a user that will login to each node and perform the bootstrap command on
80
+ # * :password (String) the password for the user that will perform the bootstrap (required)
81
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
82
+ #
83
+ # @return [HostConnector::Response]
84
+ def chef_client(host, options = {})
85
+ execute(__method__, host, options)
86
+ end
87
+
88
+ # Write your encrypted data bag secret on a node
89
+ #
90
+ # @param [String] host
91
+ # the host to perform the action on
92
+ # @param [String] secret
93
+ # your organization's encrypted data bag secret
94
+ #
95
+ # @option options [Hash] :ssh
96
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on
97
+ # * :password (String) the password for the shell user that will perform the bootstrap
98
+ # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
99
+ # * :timeout (Float) timeout value for SSH bootstrap (5.0)
100
+ # * :sudo (Boolean) run as sudo
101
+ # @option options [Hash] :winrm
102
+ # * :user (String) a user that will login to each node and perform the bootstrap command on
103
+ # * :password (String) the password for the user that will perform the bootstrap (required)
104
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
105
+ #
106
+ # @return [HostConnector::Response]
107
+ def put_secret(host, secret, options = {})
108
+ execute(__method__, host, secret, options)
109
+ end
110
+
111
+ # Execute line(s) of Ruby code on a node using Chef's embedded Ruby
112
+ #
113
+ # @param [String] host
114
+ # the host to perform the action on
115
+ # @param [Array<String>] command_lines
116
+ # An Array of lines of the command to be executed
117
+ #
118
+ # @option options [Hash] :ssh
119
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on
120
+ # * :password (String) the password for the shell user that will perform the bootstrap
121
+ # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
122
+ # * :timeout (Float) timeout value for SSH bootstrap (5.0)
123
+ # * :sudo (Boolean) run as sudo
124
+ # @option options [Hash] :winrm
125
+ # * :user (String) a user that will login to each node and perform the bootstrap command on
126
+ # * :password (String) the password for the user that will perform the bootstrap (required)
127
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
128
+ #
129
+ # @return [HostConnector::Response]
130
+ def ruby_script(host, command_lines, options = {})
131
+ execute(__method__, host, command_lines, options)
132
+ end
133
+
134
+ # Uninstall Chef from a node
135
+ #
136
+ # @param [String] host
137
+ # the host to perform the action on
138
+ #
139
+ # @option options [Boolena] :skip_chef (false)
140
+ # skip removal of the Chef package and the contents of the installation
141
+ # directory. Setting this to true will only remove any data and configurations
142
+ # generated by running Chef client.
143
+ # @option options [Hash] :ssh
144
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on
145
+ # * :password (String) the password for the shell user that will perform the bootstrap
146
+ # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
147
+ # * :timeout (Float) timeout value for SSH bootstrap (5.0)
148
+ # * :sudo (Boolean) run as sudo (true)
149
+ # @option options [Hash] :winrm
150
+ # * :user (String) a user that will login to each node and perform the bootstrap command on
151
+ # * :password (String) the password for the user that will perform the bootstrap (required)
152
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
153
+ #
154
+ # @return [HostConnector::Response]
155
+ def uninstall_chef(host, options = {})
156
+ execute(__method__, host, options)
157
+ end
158
+
159
+ # Finds and returns the best HostConnector for a given host
160
+ #
161
+ # @param [String] host
162
+ # the host to attempt to connect to
163
+ # @option options [Hash] :ssh
164
+ # * :port (Fixnum) the ssh port to connect on the node the bootstrap will be performed on (22)
165
+ # * :timeout (Float) [5.0] timeout value for testing SSH connection
166
+ # @option options [Hash] :winrm
167
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
168
+ # @param block [Proc]
169
+ # an optional block that is yielded the best HostConnector
170
+ #
171
+ # @return [HostConnector::SSH, HostConnector::WinRM]
172
+ def connector_for(host, options = {})
173
+ options = options.reverse_merge(ssh: Hash.new, winrm: Hash.new)
174
+ options[:ssh][:port] ||= HostConnector::SSH::DEFAULT_PORT
175
+ options[:winrm][:port] ||= HostConnector::WinRM::DEFAULT_PORT
176
+
177
+ if connector_port_open?(host, options[:winrm][:port])
178
+ options.delete(:ssh)
179
+ winrm
180
+ elsif connector_port_open?(host, options[:ssh][:port], options[:ssh][:timeout])
181
+ options.delete(:winrm)
182
+ ssh
183
+ else
184
+ raise Errors::HostConnectionError, "No connector ports open on '#{host}'"
185
+ end
186
+ end
187
+
188
+ private
189
+
190
+ def execute(method, host, *args)
191
+ options = args.last.is_a?(Hash) ? args.pop : Hash.new
192
+
193
+ connector_for(host, options).send(method, host, *args, options)
194
+ rescue Errors::HostConnectionError => ex
195
+ abort(ex)
196
+ rescue Resolv::ResolvError => ex
197
+ abort Errors::DNSResolvError.new(ex)
198
+ end
199
+
200
+ # Checks to see if the given port is open for TCP connections
201
+ # on the given host.
202
+ #
203
+ # @param [String] host
204
+ # the host to attempt to connect to
205
+ # @param [Fixnum] port
206
+ # the port to attempt to connect on
207
+ # @param [Float] wait_time ({PORT_CHECK_TIMEOUT})
208
+ # the number of seconds to wait
209
+ #
210
+ # @return [Boolean]
211
+ def connector_port_open?(host, port, wait_time = nil)
212
+ defer {
213
+ Timeout.timeout(wait_time || PORT_CHECK_TIMEOUT) { Celluloid::IO::TCPSocket.new(host, port).close; true }
214
+ }
215
+ rescue Errno::ETIMEDOUT, Timeout::Error, SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::EADDRNOTAVAIL => ex
216
+ false
217
+ end
218
+
219
+ def finalize_callback
220
+ @connector_supervisor.async.terminate if @connector_supervisor && @connector_supervisor.alive?
221
+ end
222
+
223
+ def ssh
224
+ @connector_registry[:ssh]
225
+ end
226
+
227
+ def winrm
228
+ @connector_registry[:winrm]
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,27 @@
1
+ module Ridley
2
+ module HostConnector
3
+ class Response
4
+ attr_reader :host
5
+
6
+ attr_accessor :stdout
7
+ attr_accessor :stderr
8
+ attr_accessor :exit_code
9
+ attr_accessor :exit_signal
10
+
11
+ def initialize(host, options = {})
12
+ @host = host
13
+ @stdout = options[:stdout] || String.new
14
+ @stderr = options[:stderr] || String.new
15
+ @exit_code = options[:exit_code] || -1
16
+ @exit_signal = options[:exit_signal] || nil
17
+ end
18
+
19
+ # Return true if the response was not successful
20
+ #
21
+ # @return [Boolean]
22
+ def error?
23
+ self.exit_code != 0
24
+ end
25
+ end
26
+ end
27
+ end