chef-provisioning-ssh 0.0.9 → 0.1.0
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.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/README.md +155 -137
- data/chef-provisioning-ssh.gemspec +28 -0
- data/lib/chef/provisioning/ssh_driver/driver.rb +127 -120
- data/lib/chef/provisioning/ssh_driver/version.rb +1 -1
- metadata +14 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69a88cd11bc933287de011039d2e16e43b4ffbc1
|
4
|
+
data.tar.gz: 5eea7c73c739a5b6927a87a3acafd1ae8e5ed9ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9dce79bf1c666461cca81e59aa0e9a3aad48aa02f5d477114b14176aa5af3679e8edded22c25fd1fc981bda1db9950f17cf1566fa41387f3adbc3e7c0700331
|
7
|
+
data.tar.gz: 7be88e2785e107272b8459b27a13a79405c20ad50c1af8d207ed57bd9de4902ec459fd81d2132dc3537a8ff0ea15a42df73ff38329e8e4171e02698185471b41
|
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -1,181 +1,197 @@
|
|
1
|
-
[](http://badge.fury.io/rb/chef-provisioning-ssh)
|
2
|
-
|
3
1
|
# Chef::Provisioning::Ssh
|
4
2
|
|
5
|
-
|
3
|
+
[](https://travis-ci.org/chef/chef-provisioning-ssh) [](http://badge.fury.io/rb/chef-provisioning-ssh)
|
4
|
+
|
5
|
+
Provisions existing machines using SSH.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
9
9
|
Add this line to your application's Gemfile:
|
10
|
-
|
10
|
+
|
11
11
|
```ruby
|
12
12
|
gem 'chef-provisioning-ssh'
|
13
13
|
```
|
14
14
|
|
15
15
|
And then execute:
|
16
16
|
|
17
|
-
|
17
|
+
```
|
18
|
+
$ bundle
|
19
|
+
```
|
18
20
|
|
19
21
|
Or install it yourself as:
|
20
22
|
|
21
|
-
|
23
|
+
```
|
24
|
+
$ gem install chef-provisioning-ssh
|
25
|
+
```
|
22
26
|
|
23
27
|
## Usage
|
24
28
|
|
25
|
-
|
29
|
+
### driver_url
|
26
30
|
|
27
|
-
|
31
|
+
- `with_driver 'ssh'` will store machine data in a file in the directory `.chef/provisioning/ssh` on the provisioning machine, with a reference to the file in the node attribute `node['chef_provisioning']['reference']['ssh_machine_file']`
|
32
|
+
- `with_driver 'ssh:/some/path'` will store machine data in the specified directory, with a reference to the file as above.
|
33
|
+
- `with_driver 'ssh:chef'` will store all machine data in the node attribute `node['chef_provisioning']['reference']`.
|
28
34
|
|
29
|
-
|
35
|
+
### machine_options
|
30
36
|
|
31
|
-
The transport_options
|
37
|
+
The `machine_options` for provisioning ssh now use the key `transport_options` which line up directly with the `transport_options` for chef-provisioning proper.
|
32
38
|
|
33
|
-
|
34
|
-
|
35
|
-
The snippet from that link is:
|
39
|
+
The `transport_options` key and sub-keys may be strings or symbols.
|
36
40
|
|
37
|
-
|
38
|
-
- username: the username to connect with
|
39
|
-
- ssh_options: a list of options to Net::SSH.start
|
40
|
-
- options: a hash of options for the transport itself, including:
|
41
|
-
- :prefix: a prefix to send before each command (e.g. "sudo ")
|
42
|
-
- :ssh_pty_enable: set to false to disable pty (some instances don't
|
43
|
-
support this, most do)
|
44
|
-
- :ssh_gateway: the gateway to use, e.g. "jkeiser@145.14.51.45:222".
|
45
|
-
nil (the default) means no gateway. If the username is omitted,
|
46
|
-
then the default username is used instead (i.e. the user running
|
47
|
-
chef, or the username configured in .ssh/config).
|
48
|
-
|
49
|
-
The options are used in
|
50
|
-
Net::SSH.start(host, username, ssh_options, options)
|
41
|
+
The `transport_options` can be viewed in the code for chef-provisioning here:
|
51
42
|
|
52
|
-
|
43
|
+
<https://github.com/chef/chef-provisioning/blob/master/lib/chef/provisioning/transport/ssh.rb#L17-L34>
|
53
44
|
|
54
|
-
|
45
|
+
The snippet from that link is:
|
55
46
|
|
56
|
-
|
47
|
+
```
|
48
|
+
- host: the host to connect to, e.g. '145.14.51.45'
|
49
|
+
- username: the username to connect with
|
50
|
+
- ssh_options: a list of options to Net::SSH.start
|
51
|
+
- options: a hash of options for the transport itself, including:
|
52
|
+
- :prefix: a prefix to send before each command (e.g. "sudo ")
|
53
|
+
- :ssh_pty_enable: set to false to disable pty (some instances don't
|
54
|
+
support this, most do)
|
55
|
+
- :ssh_gateway: the gateway to use, e.g. "jkeiser@145.14.51.45:222".
|
56
|
+
nil (the default) means no gateway. If the username is omitted,
|
57
|
+
then the default username is used instead (i.e. the user running
|
58
|
+
chef, or the username configured in .ssh/config).
|
59
|
+
|
60
|
+
The options are used in
|
61
|
+
Net::SSH.start(host, username, ssh_options, options)
|
62
|
+
```
|
57
63
|
|
58
|
-
|
64
|
+
In addition to host, ip_address and hostname are also additional options.
|
59
65
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
'
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
with_driver 'ssh'
|
126
|
-
|
127
|
-
machine "ssh" do
|
128
|
-
action [:ready, :setup, :converge]
|
129
|
-
machine_options :transport_options => {
|
130
|
-
'ip_address' => '192.168.33.22',
|
131
|
-
'username' => 'vagrant',
|
132
|
-
'ssh_options' => {
|
133
|
-
'password' => 'vagrant'
|
134
|
-
}
|
135
|
-
}
|
136
|
-
recipe 'vagrant::sshone'
|
137
|
-
converge true
|
138
|
-
end
|
139
|
-
|
140
|
-
##
|
141
|
-
# With WinRM you must use a remote chef-server
|
142
|
-
# local-mode chef server is not currently supported
|
143
|
-
|
144
|
-
with_chef_server "https://api.opscode.com/organizations/double-z",
|
145
|
-
:client_name => Chef::Config[:node_name],
|
146
|
-
:signing_key_filename => Chef::Config[:client_key]
|
147
|
-
|
148
|
-
machine "winrm" do
|
149
|
-
action [:ready, :setup, :converge]
|
150
|
-
machine_options :transport_options => {
|
151
|
-
'is_windows' => true,
|
152
|
-
'host' => '192.168.33.23',
|
66
|
+
- the `ssh_options` key accepts options from Net::SSH.start, the full list can be seen here:
|
67
|
+
|
68
|
+
<http://net-ssh.github.io/ssh/v2/api/classes/Net/SSH.html#M000002>
|
69
|
+
|
70
|
+
- full machine_options for SSH example:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
with_machine_options :transport_options => {
|
74
|
+
'is_windows' => false,
|
75
|
+
'ip_address' => '192.168.33.23',
|
76
|
+
'host' => 'somehost',
|
77
|
+
'username' => 'vagrant',
|
78
|
+
'ssh_options' => {
|
79
|
+
'auth_methods' => '',
|
80
|
+
'bind_address' => '',
|
81
|
+
'compression' => '',
|
82
|
+
'compression_level' => '',
|
83
|
+
'config' => '',
|
84
|
+
'encryption' => '',
|
85
|
+
'forward_agent' => '',
|
86
|
+
'hmac' => '',
|
87
|
+
'host_key' => '',
|
88
|
+
'keepalive' => '',
|
89
|
+
'keepalive_interval' => '',
|
90
|
+
'kex' => '',
|
91
|
+
'keys' => ['/home/username/.vagrant.d/insecure_private_key'],
|
92
|
+
'key_data' => '',
|
93
|
+
'languages' => '',
|
94
|
+
'logger' => '',
|
95
|
+
'paranoid' => '',
|
96
|
+
'password' => '',
|
97
|
+
'port' => '',
|
98
|
+
'proxy' => '',
|
99
|
+
'rekey_blocks_limit' => '',
|
100
|
+
'rekey_limit' => '',
|
101
|
+
'rekey_packet_limit' => '',
|
102
|
+
'timeout' => '',
|
103
|
+
'verbose' => '',
|
104
|
+
'global_known_hosts_file' => '',
|
105
|
+
'user_known_hosts_file' => '',
|
106
|
+
'host_key_alias' => '',
|
107
|
+
'host_name' => '',
|
108
|
+
'user' => '',
|
109
|
+
'properties' => '',
|
110
|
+
'passphrase' => '',
|
111
|
+
'keys_only' => '',
|
112
|
+
'max_pkt_size' => '',
|
113
|
+
'max_win_size, :send_env' => '',
|
114
|
+
'use_agent' => ''
|
115
|
+
},
|
116
|
+
'options' => {
|
117
|
+
'prefix' => 'sudo ',
|
118
|
+
'ssh_pty_enable' => false,
|
119
|
+
'ssh_gateway' => 'yourgateway'
|
120
|
+
}
|
121
|
+
}
|
122
|
+
```
|
123
|
+
|
124
|
+
- full machine_options for WinRM example:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
with_machine_options :transport_options => {
|
128
|
+
'is_windows' => true,
|
129
|
+
'host' => '192.168.33.23',
|
153
130
|
'port' => 5985,
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
131
|
+
'username' => 'vagrant',
|
132
|
+
'password' => 'vagrant'
|
133
|
+
}
|
134
|
+
```
|
135
|
+
|
136
|
+
- machine resource example:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
require 'chef/provisioning/ssh_driver'
|
140
|
+
|
141
|
+
with_driver 'ssh'
|
142
|
+
|
143
|
+
machine "ssh" do
|
144
|
+
action [:ready, :setup, :converge]
|
145
|
+
machine_options :transport_options => {
|
146
|
+
'ip_address' => '192.168.33.22',
|
147
|
+
'username' => 'vagrant',
|
148
|
+
'ssh_options' => {
|
149
|
+
'password' => 'vagrant'
|
150
|
+
}
|
151
|
+
}
|
152
|
+
recipe 'vagrant::sshone'
|
153
|
+
converge true
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# With WinRM you must use a remote chef-server
|
158
|
+
# local-mode chef server is not currently supported
|
159
|
+
|
160
|
+
with_chef_server "https://api.opscode.com/organizations/double-z",
|
161
|
+
:client_name => Chef::Config[:node_name],
|
162
|
+
:signing_key_filename => Chef::Config[:client_key]
|
163
|
+
|
164
|
+
machine "winrm" do
|
165
|
+
action [:ready, :setup, :converge]
|
166
|
+
machine_options :transport_options => {
|
167
|
+
'is_windows' => true,
|
168
|
+
'host' => '192.168.33.23',
|
169
|
+
'port' => 5985,
|
170
|
+
'username' => 'vagrant',
|
171
|
+
'password' => 'vagrant'
|
172
|
+
}
|
173
|
+
recipe 'windows'
|
174
|
+
converge true
|
175
|
+
end
|
176
|
+
```
|
161
177
|
|
162
178
|
To test it out, clone the repo:
|
163
179
|
|
164
|
-
`git clone https://github.com/
|
180
|
+
`git clone https://github.com/chef/chef-provisioning-ssh.git`
|
165
181
|
|
166
|
-
in the test directory there is a Vagrantfile with 2 nodes.
|
182
|
+
in the test directory there is a Vagrantfile with 2 nodes.
|
167
183
|
|
168
184
|
Run:
|
169
185
|
|
170
186
|
`vagrant up`
|
171
187
|
|
172
|
-
which will bring up both nodes.
|
188
|
+
which will bring up both nodes.
|
173
189
|
|
174
190
|
Then run from the test directory:
|
175
191
|
|
176
|
-
`chef-client -z -o vagrant::
|
192
|
+
`chef-client -z -o vagrant::test_ssh`
|
177
193
|
|
178
|
-
NOTE: if the
|
194
|
+
NOTE: if the first machine fails it will likely be a result of issues with your vagrant key.
|
179
195
|
|
180
196
|
This will run chef-provisioning on each of the two vagrant nodes.
|
181
197
|
|
@@ -183,9 +199,11 @@ thats it.
|
|
183
199
|
|
184
200
|
party on wayne.
|
185
201
|
|
202
|
+
Be aware, the `test_ssh` recipe is designed for testing, not to illustrate good practice. For example, you do not need to list all three actions `[ :ready, :setup, :converge ]` or specify `converge true` if you want the normal 'bootstrap if needed, converge if changed' behavior.
|
203
|
+
|
186
204
|
## Contributing
|
187
205
|
|
188
|
-
1. Fork it ( http://github.com/
|
206
|
+
1. Fork it ( <http://github.com/chef/chef-provisioning-ssh/fork> )
|
189
207
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
190
208
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
191
209
|
4. Push to the branch (`git push origin my-new-feature`)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'chef/provisioning/ssh_driver/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "chef-provisioning-ssh"
|
8
|
+
s.version = Chef::Provisioning::SshDriver::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.author = "Zack Zondlo"
|
11
|
+
s.email = "zackzondlo@gmail.com"
|
12
|
+
s.extra_rdoc_files = ['README.md', 'LICENSE' ]
|
13
|
+
s.summary = 'Provisioner for managing servers using ssh in Chef Provisioning.'
|
14
|
+
s.description = s.summary
|
15
|
+
s.homepage = 'https://github.com/chef/chef-provisioning-ssh'
|
16
|
+
|
17
|
+
s.require_path = "lib"
|
18
|
+
s.bindir = "bin"
|
19
|
+
s.executables = %w( )
|
20
|
+
s.files = %w(Rakefile LICENSE README.md Gemfile) + Dir.glob("*.gemspec") +
|
21
|
+
Dir.glob("{distro,lib,tasks,spec}/**/*", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
|
22
|
+
|
23
|
+
s.add_runtime_dependency "chef-provisioning", ">= 1.0", "< 3.0"
|
24
|
+
|
25
|
+
s.add_development_dependency "bundler", "~> 1.5"
|
26
|
+
s.add_development_dependency "rspec"
|
27
|
+
s.add_development_dependency "rake"
|
28
|
+
end
|
@@ -22,7 +22,13 @@ class Chef
|
|
22
22
|
|
23
23
|
include Chef::Provisioning::SshDriver::Helpers
|
24
24
|
|
25
|
+
# cluster_path is where the driver stores machine data unless use_chef_store is true
|
25
26
|
attr_reader :cluster_path
|
27
|
+
|
28
|
+
# use_chef_store is true if the driver_url is 'ssh:chef'
|
29
|
+
# In this case, machine data is stored in chef
|
30
|
+
# under node['chef_provisioning']['reference']['machine_options']
|
31
|
+
attr_reader :use_chef_store
|
26
32
|
|
27
33
|
def self.from_url(driver_url, config)
|
28
34
|
Driver.new(driver_url, config)
|
@@ -32,43 +38,44 @@ class Chef
|
|
32
38
|
super(driver_url, config)
|
33
39
|
scheme, cluster_path = driver_url.split(':', 2)
|
34
40
|
@cluster_path = cluster_path
|
41
|
+
@use_chef_store = cluster_path == 'chef'
|
35
42
|
end
|
36
43
|
|
37
44
|
def self.canonicalize_url(driver_url, config)
|
38
45
|
scheme, cluster_path = driver_url.split(':', 2)
|
39
|
-
|
46
|
+
unless cluster_path == 'chef'
|
47
|
+
cluster_path = File.expand_path(cluster_path || File.join(Chef::Config.config_dir, 'provisioning/ssh'))
|
48
|
+
end
|
40
49
|
"ssh:#{cluster_path}"
|
41
50
|
end
|
42
51
|
|
43
52
|
def allocate_machine(action_handler, machine_spec, machine_options)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
machine_spec.
|
53
|
+
ssh_machine_options = prepare_machine_options(action_handler, machine_spec, machine_options)
|
54
|
+
log_info("current_machine_options = #{ssh_machine_options.to_s}")
|
55
|
+
|
56
|
+
unless ssh_machine_exists?(machine_spec)
|
57
|
+
machine_spec.reference = {
|
49
58
|
'driver_url' => driver_url,
|
50
59
|
'driver_version' => Chef::Provisioning::SshDriver::VERSION,
|
51
60
|
'target_name' => machine_spec.name,
|
52
|
-
'ssh_machine_file' => ssh_machine_file_updated,
|
53
61
|
'allocated_at' => Time.now.utc.to_s,
|
54
|
-
'updated_at' => Time.now.utc.to_s,
|
55
62
|
'host' => action_handler.host_node
|
56
63
|
}
|
57
|
-
elsif ssh_machine_file_updated
|
58
|
-
machine_spec.location['updated_at'] = Time.now.utc.to_s
|
59
64
|
end
|
65
|
+
|
66
|
+
update_ssh_machine(action_handler, machine_spec, ssh_machine_options)
|
60
67
|
|
61
|
-
if machine_spec.
|
62
|
-
machine_spec.
|
68
|
+
if machine_spec.reference &&
|
69
|
+
(machine_spec.reference['driver_version'] != Chef::Provisioning::SshDriver::VERSION)
|
70
|
+
machine_spec.reference['driver_version'] = Chef::Provisioning::SshDriver::VERSION
|
63
71
|
end
|
64
|
-
|
65
72
|
end
|
66
73
|
|
67
74
|
def ready_machine(action_handler, machine_spec, machine_options)
|
68
75
|
ssh_machine = existing_ssh_machine_to_sym(machine_spec)
|
69
76
|
|
70
|
-
|
71
|
-
raise "SSH Machine #{machine_spec.name} does not have
|
77
|
+
unless ssh_machine
|
78
|
+
raise "SSH Machine #{machine_spec.name} does not have machine options associated with it!"
|
72
79
|
end
|
73
80
|
|
74
81
|
wait_for_transport(action_handler, ssh_machine, machine_spec, machine_options)
|
@@ -83,25 +90,25 @@ class Chef
|
|
83
90
|
def destroy_machine(action_handler, machine_spec, machine_options)
|
84
91
|
ssh_machine = ssh_machine_exists?(machine_spec)
|
85
92
|
|
86
|
-
|
87
|
-
raise "SSH Machine #{machine_spec.name} does not have
|
88
|
-
|
93
|
+
unless ssh_machine
|
94
|
+
raise "SSH Machine #{machine_spec.name} does not have machine options associated with it!"
|
95
|
+
end
|
96
|
+
|
97
|
+
unless use_chef_store
|
89
98
|
Chef::Provisioning.inline_resource(action_handler) do
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
99
|
+
file machine_spec.reference['ssh_machine_file'] do
|
100
|
+
action :delete
|
101
|
+
backup false
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
98
105
|
end
|
99
106
|
|
100
107
|
def stop_machine(action_handler, machine_spec, machine_options)
|
101
108
|
ssh_machine = existing_ssh_machine_to_sym(machine_spec)
|
102
109
|
|
103
|
-
|
104
|
-
raise "SSH Machine #{machine_spec.name} does not have
|
110
|
+
unless ssh_machine && machine_spec.reference['machine_options']
|
111
|
+
raise "SSH Machine #{machine_spec.name} does not have machine options associated with it!"
|
105
112
|
end
|
106
113
|
|
107
114
|
action_handler.report_progress("SSH Machine #{machine_spec.name} is existing hardware login and power off.")
|
@@ -110,8 +117,8 @@ class Chef
|
|
110
117
|
def machine_for(machine_spec, machine_options)
|
111
118
|
ssh_machine = existing_ssh_machine_to_sym(machine_spec)
|
112
119
|
|
113
|
-
|
114
|
-
raise "SSH Machine #{machine_spec.name} does not have
|
120
|
+
unless ssh_machine
|
121
|
+
raise "SSH Machine #{machine_spec.name} does not have machine options associated with it!"
|
115
122
|
end
|
116
123
|
|
117
124
|
if ssh_machine[:transport_options][:is_windows]
|
@@ -189,65 +196,65 @@ class Chef
|
|
189
196
|
end
|
190
197
|
end
|
191
198
|
|
199
|
+
def validate_transport_fields(options, req_fields, opt_fields)
|
200
|
+
error_msgs = []
|
201
|
+
valid_fields = req_fields.flatten + opt_fields
|
202
|
+
one_of_fields = req_fields.select{ |i| i.kind_of?(Array)}
|
203
|
+
|
204
|
+
missing = req_fields.flatten - options.keys
|
205
|
+
|
206
|
+
one_of_fields.each do |oof|
|
207
|
+
if oof == oof & missing
|
208
|
+
error_msgs << ":transport_options => :#{oof.join(" or :")} required."
|
209
|
+
end
|
210
|
+
missing -= oof
|
211
|
+
end
|
212
|
+
|
213
|
+
missing.each do |missed|
|
214
|
+
error_msgs << ":transport_options => :#{missed} required."
|
215
|
+
valid = false
|
216
|
+
end
|
217
|
+
|
218
|
+
extras = options.keys - valid_fields
|
219
|
+
|
220
|
+
extras.each do |extra|
|
221
|
+
error_msgs << ":transport_options => :#{extra} not allowed."
|
222
|
+
valid = false
|
223
|
+
end
|
224
|
+
|
225
|
+
error_msgs
|
226
|
+
end
|
227
|
+
|
192
228
|
def validate_machine_options(action_handler, machine_spec, machine_options)
|
193
229
|
error_msgs = []
|
194
230
|
valid = true
|
195
|
-
|
196
|
-
|
231
|
+
|
232
|
+
unless machine_options[:transport_options]
|
197
233
|
error_msgs << ":transport_options required."
|
198
234
|
valid = false
|
199
235
|
else
|
200
236
|
if machine_options[:transport_options][:is_windows]
|
201
237
|
# Validate Windows Options.
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
if oof == oof & missing
|
209
|
-
error_msgs << ":transport_options => :#{oof.join(" or :")} required."
|
210
|
-
end
|
211
|
-
missing -= oof
|
212
|
-
end
|
213
|
-
|
214
|
-
missing.each do |missed|
|
215
|
-
error_msgs << ":transport_options => :#{missed} required."
|
216
|
-
valid = false
|
217
|
-
end
|
218
|
-
|
219
|
-
extras = machine_options[:transport_options].keys - req_and_valid_fields.flatten
|
220
|
-
|
221
|
-
extras.each do |extra|
|
222
|
-
error_msgs << ":transport_options => :#{extra} not allowed." unless extra == :port
|
238
|
+
field_errors = validate_transport_fields(
|
239
|
+
machine_options[:transport_options],
|
240
|
+
[:is_windows, [:host, :ip_address], :username, :password],
|
241
|
+
[:port]
|
242
|
+
)
|
243
|
+
unless field_errors.empty?
|
223
244
|
valid = false
|
245
|
+
error_msgs << field_errors
|
224
246
|
end
|
225
247
|
else
|
226
248
|
# Validate Unix Options
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
error_msgs << ":transport_options => :#{oof.join(" or :")} required."
|
235
|
-
end
|
236
|
-
missing -= oof
|
237
|
-
end
|
238
|
-
|
239
|
-
missing.each do |missed|
|
240
|
-
error_msgs << ":transport_options => :#{missed} required."
|
241
|
-
valid = false
|
242
|
-
end
|
243
|
-
|
244
|
-
valid_fields = [:is_windows, :host, :hostname, :ip_address, :username, :ssh_options, :options]
|
245
|
-
|
246
|
-
extras = machine_options[:transport_options].keys - valid_fields
|
247
|
-
|
248
|
-
extras.each do |extra|
|
249
|
-
error_msgs << ":transport_options => :#{extra} not allowed."
|
249
|
+
field_errors = validate_transport_fields(
|
250
|
+
machine_options[:transport_options],
|
251
|
+
[[:host, :hostname, :ip_address], :username],
|
252
|
+
[:is_windows, :host, :hostname, :ip_address, :username, :ssh_options, :options]
|
253
|
+
)
|
254
|
+
|
255
|
+
unless field_errors.empty?
|
250
256
|
valid = false
|
257
|
+
error_msgs << field_errors
|
251
258
|
end
|
252
259
|
|
253
260
|
if machine_options[:transport_options][:ssh_options]
|
@@ -262,7 +269,7 @@ class Chef
|
|
262
269
|
end
|
263
270
|
|
264
271
|
if machine_options[:transport_options][:options]
|
265
|
-
valid_fields = [:prefix, :ssh_pty_enable, :ssh_gateway]
|
272
|
+
valid_fields = [:prefix, :ssh_pty_enable, :ssh_gateway, :scp_temp_dir]
|
266
273
|
|
267
274
|
extras = machine_options[:transport_options][:options].keys - valid_fields
|
268
275
|
|
@@ -292,42 +299,14 @@ class Chef
|
|
292
299
|
end
|
293
300
|
end
|
294
301
|
|
295
|
-
def
|
302
|
+
def create_machine_file(action_handler, machine_spec, machine_options_hash)
|
296
303
|
ensure_ssh_cluster(action_handler)
|
297
304
|
|
298
|
-
machine_options_hash_for_sym = deep_hashify(machine_options)
|
299
|
-
symbolized_machine_options = symbolize_keys(machine_options_hash_for_sym)
|
300
|
-
validate_machine_options(action_handler, machine_spec, symbolized_machine_options)
|
301
|
-
# end
|
302
|
-
|
303
|
-
|
304
|
-
# def create_ssh_machine(action_handler, machine_spec, machine_options)
|
305
|
-
log_info("File is = #{ssh_machine_file(machine_spec)}")
|
306
|
-
log_info("current_machine_options = #{machine_options.to_s}")
|
307
|
-
|
308
|
-
machine_options_hash_for_s = deep_hashify(machine_options)
|
309
|
-
stringy_machine_options = stringify_keys(machine_options_hash_for_s)
|
310
|
-
given_machine_options = create_machine_hash(stringy_machine_options)
|
311
|
-
|
312
|
-
if ssh_machine_exists?(machine_spec)
|
313
|
-
existing_machine_hash = existing_ssh_machine(machine_spec)
|
314
|
-
if !existing_machine_hash.eql?(given_machine_options)
|
315
|
-
create_machine_file(action_handler, machine_spec, given_machine_options)
|
316
|
-
else
|
317
|
-
return false
|
318
|
-
end
|
319
|
-
else
|
320
|
-
file_updated = create_machine_file(action_handler, machine_spec, given_machine_options)
|
321
|
-
file_updated
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
def create_machine_file(action_handler, machine_spec, machine_options)
|
326
305
|
file_path = ssh_machine_file(machine_spec)
|
327
|
-
machine_options_hash = deep_hashify(machine_options)
|
328
306
|
stringy_machine_options = stringify_keys(machine_options_hash)
|
329
307
|
options_parsed = ::JSON.parse(stringy_machine_options.to_json)
|
330
308
|
json_machine_options = ::JSON.pretty_generate(options_parsed)
|
309
|
+
log_info("File is = #{file_path}")
|
331
310
|
Chef::Provisioning.inline_resource(action_handler) do
|
332
311
|
file file_path do
|
333
312
|
content json_machine_options
|
@@ -347,12 +326,15 @@ class Chef
|
|
347
326
|
end
|
348
327
|
|
349
328
|
def existing_ssh_machine(machine_spec)
|
350
|
-
|
351
|
-
existing_machine_hash = JSON.parse(File.read(ssh_machine_file(machine_spec)))
|
352
|
-
existing_machine_hash.to_hash
|
353
|
-
else
|
329
|
+
unless ssh_machine_exists?(machine_spec)
|
354
330
|
return {}
|
355
331
|
end
|
332
|
+
|
333
|
+
if use_chef_store
|
334
|
+
machine_spec.reference['machine_options']
|
335
|
+
else
|
336
|
+
JSON.parse(File.read(ssh_machine_file(machine_spec))).to_hash
|
337
|
+
end
|
356
338
|
end
|
357
339
|
|
358
340
|
def existing_ssh_machine_to_sym(machine_spec)
|
@@ -365,22 +347,47 @@ class Chef
|
|
365
347
|
end
|
366
348
|
|
367
349
|
def ssh_machine_exists?(machine_spec)
|
368
|
-
if
|
369
|
-
|
350
|
+
if use_chef_store
|
351
|
+
machine_spec.reference && machine_spec.reference['machine_options']
|
370
352
|
else
|
371
|
-
|
353
|
+
machine_spec.reference && ::File.exists?(ssh_machine_file(machine_spec))
|
372
354
|
end
|
373
355
|
end
|
374
356
|
|
375
357
|
def ssh_machine_file(machine_spec)
|
376
|
-
if machine_spec.
|
377
|
-
machine_spec.
|
358
|
+
if machine_spec.reference && machine_spec.reference['ssh_machine_file']
|
359
|
+
machine_spec.reference['ssh_machine_file']
|
378
360
|
else
|
379
361
|
ssh_machine_file = ::File.join(@cluster_path, "#{machine_spec.name}.json")
|
380
362
|
ssh_machine_file
|
381
363
|
end
|
382
364
|
end
|
383
365
|
|
366
|
+
def prepare_machine_options(action_handler, machine_spec, machine_options)
|
367
|
+
options_hash = symbolize_keys(deep_hashify(machine_options))
|
368
|
+
|
369
|
+
# if no transport options are specified, use the existing ones
|
370
|
+
unless options_hash[:transport_options]
|
371
|
+
ssh_machine = existing_ssh_machine_to_sym(machine_spec) || {}
|
372
|
+
options_hash[:transport_options] = ssh_machine[:transport_options] || {}
|
373
|
+
end
|
374
|
+
|
375
|
+
validate_machine_options(action_handler, machine_spec, options_hash)
|
376
|
+
create_machine_hash(stringify_keys(options_hash))
|
377
|
+
end
|
378
|
+
|
379
|
+
def update_ssh_machine(action_handler, machine_spec, ssh_machine_options)
|
380
|
+
unless existing_ssh_machine(machine_spec).eql? ssh_machine_options
|
381
|
+
if use_chef_store
|
382
|
+
machine_spec.reference['machine_options'] = ssh_machine_options
|
383
|
+
else
|
384
|
+
machine_spec.reference['ssh_machine_file'] =
|
385
|
+
create_machine_file(action_handler, machine_spec, ssh_machine_options)
|
386
|
+
end
|
387
|
+
machine_spec.reference['updated_at'] = Time.now.utc.to_s
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
384
391
|
def create_machine_hash(machine_options)
|
385
392
|
if !machine_options['transport_options']['host']
|
386
393
|
machine_options['transport_options']['host'] = machine_options['transport_options']['ip_address'] ||
|
@@ -390,7 +397,7 @@ class Chef
|
|
390
397
|
unless machine_options['transport_options']['is_windows']
|
391
398
|
machine_options['transport_options']['options'] ||= {}
|
392
399
|
unless machine_options['transport_options']['username'] == 'root'
|
393
|
-
machine_options['transport_options']['options']['prefix']
|
400
|
+
machine_options['transport_options']['options']['prefix'] ||= 'sudo '
|
394
401
|
end
|
395
402
|
end
|
396
403
|
ensure_has_keys_or_password(machine_options['transport_options'])
|
@@ -405,9 +412,11 @@ class Chef
|
|
405
412
|
if transport_hash['ssh_options']
|
406
413
|
ssh_hash = transport_hash['ssh_options']
|
407
414
|
keys = ssh_hash['keys'] || false
|
415
|
+
key_data = ssh_hash['key_data'] || false
|
408
416
|
password = ssh_hash['password'] || false
|
409
417
|
has_either = ((password && password.kind_of?(String)) ||
|
410
|
-
(keys && !keys.empty? && keys.kind_of?(Array))
|
418
|
+
(keys && !keys.empty? && keys.kind_of?(Array)) ||
|
419
|
+
(key_data && !key_data.empty? && key_data.kind_of?(Array)))
|
411
420
|
else
|
412
421
|
has_either = false
|
413
422
|
end
|
@@ -439,8 +448,6 @@ class Chef
|
|
439
448
|
|
440
449
|
raise 'Host is not a Valid IP or Resolvable Hostname' unless ( valid_ip || in_hosts_file || in_dns )
|
441
450
|
end
|
442
|
-
|
443
|
-
|
444
451
|
end
|
445
452
|
end
|
446
453
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-provisioning-ssh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zack Zondlo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-provisioning
|
@@ -16,14 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
19
|
+
version: '1.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '3.0'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
29
|
+
version: '1.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.0'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: bundler
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -74,9 +80,11 @@ extra_rdoc_files:
|
|
74
80
|
- README.md
|
75
81
|
- LICENSE
|
76
82
|
files:
|
83
|
+
- Gemfile
|
77
84
|
- LICENSE
|
78
85
|
- README.md
|
79
86
|
- Rakefile
|
87
|
+
- chef-provisioning-ssh.gemspec
|
80
88
|
- lib/chef/provider/ssh_cluster.rb
|
81
89
|
- lib/chef/provisioning/driver_init/ssh.rb
|
82
90
|
- lib/chef/provisioning/ssh_driver.rb
|
@@ -84,7 +92,7 @@ files:
|
|
84
92
|
- lib/chef/provisioning/ssh_driver/helpers.rb
|
85
93
|
- lib/chef/provisioning/ssh_driver/version.rb
|
86
94
|
- lib/chef/resource/ssh_cluster.rb
|
87
|
-
homepage: https://github.com/
|
95
|
+
homepage: https://github.com/chef/chef-provisioning-ssh
|
88
96
|
licenses: []
|
89
97
|
metadata: {}
|
90
98
|
post_install_message:
|
@@ -103,9 +111,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
111
|
version: '0'
|
104
112
|
requirements: []
|
105
113
|
rubyforge_project:
|
106
|
-
rubygems_version: 2.
|
114
|
+
rubygems_version: 2.6.7
|
107
115
|
signing_key:
|
108
116
|
specification_version: 4
|
109
117
|
summary: Provisioner for managing servers using ssh in Chef Provisioning.
|
110
118
|
test_files: []
|
111
|
-
has_rdoc:
|