chef-metal-ssh 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +1 -0
- data/lib/chef_metal/provisioner_init/ssh_init.rb +4 -0
- data/lib/chef_metal_ssh.rb +2 -0
- data/lib/chef_metal_ssh/ssh_provisioner.rb +232 -0
- data/lib/chef_metal_ssh/version.rb +3 -0
- metadata +108 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 double-z
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# ChefMetalSsh
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'chef-metal-ssh'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install chef-metal-ssh
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
machine "one" do
|
22
|
+
action :create
|
23
|
+
converge true
|
24
|
+
provisioner ChefMetalSsh::SshProvisioner.new
|
25
|
+
provisioner_options 'target_ip' => '192.168.33.21',
|
26
|
+
'ssh_user' => 'vagrant',
|
27
|
+
'ssh_connect_options' => {
|
28
|
+
'ssh_pass' => 'vagrant'
|
29
|
+
}
|
30
|
+
recipe 'ssh_test::remote1'
|
31
|
+
notifies :create, 'machine[two]'
|
32
|
+
notifies :run, 'execute[run_touch1]'
|
33
|
+
end
|
34
|
+
|
35
|
+
To test it out, clone the repo:
|
36
|
+
|
37
|
+
`git clone https://github.com/double-z/chef-metal-ssh.git`
|
38
|
+
|
39
|
+
in the root there is a Vagrantfile with 3 nodes, 1 master and 2 targets. Run:
|
40
|
+
|
41
|
+
first run:
|
42
|
+
|
43
|
+
`rake build`
|
44
|
+
|
45
|
+
from the repo root to build the gem in the repo root `./pkg/` directory. then run:
|
46
|
+
|
47
|
+
`vagrant up`
|
48
|
+
|
49
|
+
which will bring up all 3 nodes. FYI, nothing will get installed on your local machine in this proces. So then ssh to the master:
|
50
|
+
|
51
|
+
`vagrant ssh master`
|
52
|
+
|
53
|
+
the repo test directory has a test cookbook and `run_zero` script. its located at `/vagrant/test`
|
54
|
+
|
55
|
+
cd into it:
|
56
|
+
|
57
|
+
`cd /vagrant/test`
|
58
|
+
|
59
|
+
then run:
|
60
|
+
|
61
|
+
`bash run_zero install`
|
62
|
+
|
63
|
+
this will install the prereqs. then run:
|
64
|
+
|
65
|
+
`bash run_zero both`
|
66
|
+
|
67
|
+
this will run the `ssh_test::both` recipe which will converge both targets, with target one
|
68
|
+
notifying target two. target one will converge the `ssh_test::remote1` recipe, target two the `ssh_test::remote2` recipe.
|
69
|
+
|
70
|
+
thats it.
|
71
|
+
|
72
|
+
party on wayne.
|
73
|
+
|
74
|
+
## Contributing
|
75
|
+
|
76
|
+
1. Fork it ( http://github.com/double-z/chef-metal-ssh/fork )
|
77
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
78
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
79
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
80
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,232 @@
|
|
1
|
+
require 'chef_metal/provisioner'
|
2
|
+
require 'chef_metal/version'
|
3
|
+
require 'chef_metal/machine/basic_machine'
|
4
|
+
require 'chef_metal/machine/unix_machine'
|
5
|
+
require 'chef_metal/convergence_strategy/install_cached'
|
6
|
+
require 'chef_metal/transport/ssh'
|
7
|
+
|
8
|
+
module ChefMetalSsh
|
9
|
+
# Provisions machines with ssh.
|
10
|
+
class SshProvisioner < ChefMetal::Provisioner
|
11
|
+
|
12
|
+
def initialize(target_host=nil)
|
13
|
+
@target_host = target_host
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :target_host
|
17
|
+
|
18
|
+
# Acquire a machine, generally by provisioning it. Returns a Machine
|
19
|
+
# object pointing at the machine, allowing useful actions like setup,
|
20
|
+
# converge, execute, file and directory. The Machine object will have a
|
21
|
+
# "node" property which must be saved to the server (if it is any
|
22
|
+
# different from the original node object).
|
23
|
+
#
|
24
|
+
# ## Parameters
|
25
|
+
# action_handler - the action_handler object that provides context.
|
26
|
+
# node - node object (deserialized json) representing this machine. If
|
27
|
+
# the node has a provisioner_options hash in it, these will be used
|
28
|
+
# instead of options provided by the provisioner. TODO compare and
|
29
|
+
# fail if different?
|
30
|
+
# node will have node['normal']['provisioner_options'] in it with any options.
|
31
|
+
# It is a hash with this format:
|
32
|
+
#
|
33
|
+
# -- provisioner_url: ssh:<ssh_path>
|
34
|
+
# -- target_ip: the IP address of the target machine - IP or FQDN is required
|
35
|
+
# -- target_fqdn: The Resolvable name of the target machine - IP or FQDN is required
|
36
|
+
# -- ssh_user: the user to ssh as
|
37
|
+
# -- ssh_config: options to pass the ssh command. available options are here - https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh.rb#L61
|
38
|
+
#
|
39
|
+
# node['normal']['provisioner_output'] will be populated with information
|
40
|
+
# about the created machine. For ssh, it is a hash with this
|
41
|
+
# format:
|
42
|
+
#
|
43
|
+
# -- provisioner_url: ssh:<ssh_path>
|
44
|
+
# -- name: container name
|
45
|
+
#
|
46
|
+
def acquire_machine(action_handler, node)
|
47
|
+
# TODO verify that the existing provisioner_url in the node is the same as ours
|
48
|
+
|
49
|
+
# Set up the modified node data
|
50
|
+
provisioner_options = node['normal']['provisioner_options']
|
51
|
+
|
52
|
+
Chef::Log.debug("======================================>")
|
53
|
+
Chef::Log.debug("acquire_machine - provisioner_options.inspect: #{provisioner_options.inspect}")
|
54
|
+
Chef::Log.debug("======================================>")
|
55
|
+
|
56
|
+
if @target_host.nil?
|
57
|
+
target_host = get_target_connection_method(node)
|
58
|
+
@target_host = target_host
|
59
|
+
end
|
60
|
+
|
61
|
+
Chef::Log.debug("======================================>")
|
62
|
+
Chef::Log.debug("acquire_machine - target_host: #{target_host}")
|
63
|
+
Chef::Log.debug("======================================>")
|
64
|
+
|
65
|
+
# Set up Provisioner Output
|
66
|
+
# TODO - make url the chef server url path? maybe disk path if zero?
|
67
|
+
provisioner_output = node['normal']['provisioner_output'] || {
|
68
|
+
'provisioner_url' => "ssh:#{target_host}",
|
69
|
+
'name' => node['name']
|
70
|
+
}
|
71
|
+
|
72
|
+
Chef::Log.debug("======================================>")
|
73
|
+
Chef::Log.debug("acquire_machine - provisioner_output.inspect: #{provisioner_output.inspect}")
|
74
|
+
Chef::Log.debug("======================================>")
|
75
|
+
|
76
|
+
node['normal']['provisioner_output'] = provisioner_output
|
77
|
+
|
78
|
+
# Create machine object for callers to use
|
79
|
+
machine_for(node)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Connect to machine without acquiring it
|
83
|
+
def connect_to_machine(node)
|
84
|
+
if @target_host.nil?
|
85
|
+
target_host = get_target_connection_method(node)
|
86
|
+
@target_host = target_host
|
87
|
+
end
|
88
|
+
|
89
|
+
Chef::Log.debug("======================================>")
|
90
|
+
Chef::Log.debug("connect_to_machine - target_host: #{target_host}")
|
91
|
+
Chef::Log.debug("======================================>")
|
92
|
+
|
93
|
+
machine_for(node)
|
94
|
+
end
|
95
|
+
|
96
|
+
def delete_machine(action_handler, node)
|
97
|
+
convergence_strategy_for(node).delete_chef_objects(action_handler, node)
|
98
|
+
end
|
99
|
+
|
100
|
+
def stop_machine(action_handler, node)
|
101
|
+
# What to do What to do.
|
102
|
+
# On one level there's really only one thing to do here,
|
103
|
+
# shellout and halt, or shutdown -h now,
|
104
|
+
# maybe provide abitily to pass some shutdown options
|
105
|
+
# But be vewwy vewwy careful, you better have console,
|
106
|
+
# or be close to your datacenter
|
107
|
+
true
|
108
|
+
end
|
109
|
+
|
110
|
+
def restart_machine(action_handler, node)
|
111
|
+
# Full Restart, POST BIOS and all
|
112
|
+
end
|
113
|
+
|
114
|
+
def reload_machine(action_handler, node)
|
115
|
+
# Use `kexec` here to skip POST and BIOS and all that noise.
|
116
|
+
end
|
117
|
+
|
118
|
+
# Not meant to be part of public interface
|
119
|
+
def transport_for(node)
|
120
|
+
create_ssh_transport(node)
|
121
|
+
end
|
122
|
+
|
123
|
+
protected
|
124
|
+
|
125
|
+
def get_target_connection_method(node)
|
126
|
+
|
127
|
+
provisioner_options = node['normal']['provisioner_options']
|
128
|
+
|
129
|
+
target_ip = ''
|
130
|
+
target_ip = provisioner_options['target_ip'] || nil
|
131
|
+
|
132
|
+
target_fqdn = ''
|
133
|
+
target_fqdn = provisioner_options['target_fqdn'] || nil
|
134
|
+
|
135
|
+
remote_host = ''
|
136
|
+
if @target_host
|
137
|
+
remote_host = @target_host
|
138
|
+
elsif target_ip
|
139
|
+
remote_host = target_ip
|
140
|
+
elsif target_fqdn
|
141
|
+
remote_host = target_fqdn
|
142
|
+
else
|
143
|
+
raise "aint got no target yo, that dog dont hunt"
|
144
|
+
end
|
145
|
+
|
146
|
+
Chef::Log.debug("======================================>")
|
147
|
+
Chef::Log.debug("get_target_connection_method - remote_host: #{remote_host}")
|
148
|
+
Chef::Log.debug("======================================>")
|
149
|
+
|
150
|
+
remote_host
|
151
|
+
end
|
152
|
+
|
153
|
+
def machine_for(node)
|
154
|
+
ChefMetal::Machine::UnixMachine.new(node, transport_for(node), convergence_strategy_for(node))
|
155
|
+
end
|
156
|
+
|
157
|
+
def convergence_strategy_for(node)
|
158
|
+
@convergence_strategy ||= begin
|
159
|
+
ChefMetal::ConvergenceStrategy::InstallCached.new
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Setup Ssh
|
164
|
+
def create_ssh_transport(node)
|
165
|
+
# TODO - verify target_host resolves
|
166
|
+
# Verify Valid IP
|
167
|
+
|
168
|
+
provisioner_options = node['normal']['provisioner_options']
|
169
|
+
|
170
|
+
##
|
171
|
+
# Ssh Target
|
172
|
+
target_host = ''
|
173
|
+
target_host = @target_host
|
174
|
+
|
175
|
+
Chef::Log.debug("======================================>")
|
176
|
+
Chef::Log.debug("create_ssh_transport - target_host: #{target_host}")
|
177
|
+
Chef::Log.debug("======================================>")
|
178
|
+
|
179
|
+
##
|
180
|
+
# Ssh Username
|
181
|
+
username = ''
|
182
|
+
username = provisioner_options['ssh_user'] || 'vagrant'
|
183
|
+
|
184
|
+
Chef::Log.debug("======================================>")
|
185
|
+
Chef::Log.debug("create_ssh_transport - username: #{username}")
|
186
|
+
Chef::Log.debug("======================================>")
|
187
|
+
|
188
|
+
##
|
189
|
+
# Ssh Password
|
190
|
+
ssh_pass = ''
|
191
|
+
ssh_pass = provisioner_options['ssh_connect_options']['ssh_pass']
|
192
|
+
|
193
|
+
Chef::Log.debug("======================================>")
|
194
|
+
Chef::Log.debug("create_ssh_transport - ssh_pass: #{ssh_pass}")
|
195
|
+
Chef::Log.debug("======================================>")
|
196
|
+
|
197
|
+
##
|
198
|
+
# Ssh Main Options
|
199
|
+
ssh_options = {}
|
200
|
+
ssh_options = {
|
201
|
+
# TODO create a user known hosts file
|
202
|
+
# :user_known_hosts_file => provisioner_options['ssh_connect_options']['UserKnownHostsFile'],
|
203
|
+
# :paranoid => true,
|
204
|
+
# :auth_methods => [ 'publickey' ],
|
205
|
+
:keys_only => false,
|
206
|
+
:password => ssh_pass
|
207
|
+
}
|
208
|
+
|
209
|
+
Chef::Log.debug("======================================>")
|
210
|
+
Chef::Log.debug("create_ssh_transport - ssh_options: #{ssh_options.inspect}")
|
211
|
+
Chef::Log.debug("======================================>")
|
212
|
+
|
213
|
+
|
214
|
+
##
|
215
|
+
# Ssh Additional Options
|
216
|
+
options = {}
|
217
|
+
#Enable pty by default
|
218
|
+
options[:ssh_pty_enable] = true
|
219
|
+
|
220
|
+
if username != 'root'
|
221
|
+
options[:prefix] = 'sudo '
|
222
|
+
end
|
223
|
+
|
224
|
+
Chef::Log.debug("======================================>")
|
225
|
+
Chef::Log.debug("create_ssh_transport - options: #{options.inspect}")
|
226
|
+
Chef::Log.debug("======================================>")
|
227
|
+
|
228
|
+
ChefMetal::Transport::SSH.new(target_host, username, ssh_options, options)
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chef-metal-ssh
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Zack Zondlo
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-04-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: chef
|
16
|
+
requirement: &6594860 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *6594860
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: chef-metal
|
27
|
+
requirement: &6650460 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.6'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *6650460
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: bundler
|
38
|
+
requirement: &6649080 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.5'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *6649080
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: &6647280 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *6647280
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rake
|
60
|
+
requirement: &6077260 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *6077260
|
69
|
+
description: Provisioner for converging servers using ssh ssh in Chef Metal.
|
70
|
+
email: zackzondlo@gmail.com
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files:
|
74
|
+
- README.md
|
75
|
+
- LICENSE.txt
|
76
|
+
files:
|
77
|
+
- Rakefile
|
78
|
+
- LICENSE.txt
|
79
|
+
- README.md
|
80
|
+
- lib/chef_metal/provisioner_init/ssh_init.rb
|
81
|
+
- lib/chef_metal_ssh.rb
|
82
|
+
- lib/chef_metal_ssh/ssh_provisioner.rb
|
83
|
+
- lib/chef_metal_ssh/version.rb
|
84
|
+
homepage: https://github.com/double-z/chef-metal-ssh
|
85
|
+
licenses: []
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.8.11
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: Provisioner for converging servers using ssh ssh in Chef Metal.
|
108
|
+
test_files: []
|