knife-windows 0.8.2 → 0.8.3.rc.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,206 +1,207 @@
1
- #
2
- # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
- # Copyright:: Copyright (c) 2011 Opscode, Inc.
4
- # License:: Apache License, Version 2.0
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.
17
- #
18
-
19
- require 'chef/knife'
20
- require 'chef/encrypted_data_bag_item'
21
- require 'chef/knife/core/windows_bootstrap_context'
22
-
23
- class Chef
24
- class Knife
25
- module BootstrapWindowsBase
26
-
27
- # :nodoc:
28
- # Would prefer to do this in a rational way, but can't be done b/c of
29
- # Mixlib::CLI's design :(
30
- def self.included(includer)
31
- includer.class_eval do
32
-
33
- deps do
34
- require 'readline'
35
- require 'chef/json_compat'
36
- end
37
-
38
- option :chef_node_name,
39
- :short => "-N NAME",
40
- :long => "--node-name NAME",
41
- :description => "The Chef node name for your new node"
42
-
43
- option :prerelease,
44
- :long => "--prerelease",
45
- :description => "Install the pre-release chef gems"
46
-
47
- option :bootstrap_version,
48
- :long => "--bootstrap-version VERSION",
49
- :description => "The version of Chef to install",
50
- :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
51
-
52
- option :bootstrap_proxy,
53
- :long => "--bootstrap-proxy PROXY_URL",
54
- :description => "The proxy server for the node being bootstrapped",
55
- :proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
56
-
57
- option :bootstrap_no_proxy,
58
- :long => "--bootstrap-no-proxy ",
59
- :description => "Avoid a proxy server for the given addresses",
60
- :proc => Proc.new { |np| Chef::Config[:knife][:bootstrap_no_proxy] = np }
61
-
62
- option :distro,
63
- :short => "-d DISTRO",
64
- :long => "--distro DISTRO",
65
- :description => "Bootstrap a distro using a template",
66
- :default => "windows-chef-client-msi"
67
-
68
- option :template_file,
69
- :long => "--template-file TEMPLATE",
70
- :description => "Full path to location of template to use",
71
- :default => false
72
-
73
- option :run_list,
74
- :short => "-r RUN_LIST",
75
- :long => "--run-list RUN_LIST",
76
- :description => "Comma separated list of roles/recipes to apply",
77
- :proc => lambda { |o| o.split(",") },
78
- :default => []
79
-
80
- option :first_boot_attributes,
81
- :short => "-j JSON_ATTRIBS",
82
- :long => "--json-attributes",
83
- :description => "A JSON string to be added to the first run of chef-client",
84
- :proc => lambda { |o| JSON.parse(o) },
85
- :default => {}
86
-
87
- option :encrypted_data_bag_secret,
88
- :short => "-s SECRET",
89
- :long => "--secret ",
90
- :description => "The secret key to use to decrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config.",
91
- :default => false
92
-
93
- option :encrypted_data_bag_secret_file,
94
- :long => "--secret-file SECRET_FILE",
95
- :description => "A file containing the secret key to use to encrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config."
96
-
97
- option :auth_timeout,
98
- :long => "--auth-timeout MINUTES",
99
- :description => "The maximum time in minutes to wait to for authentication over the transport to the node to succeed. The default value is 2 minutes.",
100
- :default => 2
101
- end
102
- end
103
-
104
- # TODO: This should go away when CHEF-2193 is fixed
105
- def load_template(template=nil)
106
- # Are we bootstrapping using an already shipped template?
107
- if config[:template_file]
108
- bootstrap_files = config[:template_file]
109
- else
110
- bootstrap_files = []
111
- bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap', "#{config[:distro]}.erb")
112
- bootstrap_files << File.join(Dir.pwd, ".chef", "bootstrap", "#{config[:distro]}.erb")
113
- bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{config[:distro]}.erb")
114
- bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{config[:distro]}.erb"))
115
- bootstrap_files.flatten!
116
- end
117
-
118
- template = Array(bootstrap_files).find do |bootstrap_template|
119
- Chef::Log.debug("Looking for bootstrap template in #{File.dirname(bootstrap_template)}")
120
- ::File.exists?(bootstrap_template)
121
- end
122
-
123
- unless template
124
- ui.info("Can not find bootstrap definition for #{config[:distro]}")
125
- raise Errno::ENOENT
126
- end
127
-
128
- Chef::Log.debug("Found bootstrap template in #{File.dirname(template)}")
129
-
130
- IO.read(template).chomp
131
- end
132
-
133
- def render_template(template=nil)
134
- if config[:encrypted_data_bag_secret_file]
135
- config[:encrypted_data_bag_secret] = Chef::EncryptedDataBagItem.load_secret(config[:encrypted_data_bag_secret_file])
136
- end
137
- context = Knife::Core::WindowsBootstrapContext.new(config, config[:run_list], Chef::Config)
138
- Erubis::Eruby.new(template).evaluate(context)
139
- end
140
-
141
- def bootstrap(proto=nil)
142
- validate_name_args!
143
-
144
- @node_name = Array(@name_args).first
145
- # back compat--templates may use this setting:
146
- config[:server_name] = @node_name
147
-
148
- STDOUT.sync = STDERR.sync = true
149
-
150
- wait_for_remote_response( config[:auth_timeout].to_i )
151
- ui.info("Bootstrapping Chef on #{ui.color(@node_name, :bold)}")
152
- # create a bootstrap.bat file on the node
153
- # we have to run the remote commands in 2047 char chunks
154
- create_bootstrap_bat_command do |command_chunk, chunk_num|
155
- begin
156
- render_command_result = run_command(%Q!cmd.exe /C echo "Rendering #{bootstrap_bat_file} chunk #{chunk_num}" && #{command_chunk}!)
157
- ui.error("Batch render command returned #{render_command_result}") if render_command_result != 0
158
- render_command_result
159
- rescue SystemExit => e
160
- raise unless e.success?
161
- end
162
- end
163
-
164
- # execute the bootstrap.bat file
165
- bootstrap_command_result = run_command(bootstrap_command)
166
- ui.error("Bootstrap command returned #{bootstrap_command_result}") if bootstrap_command_result != 0
167
- bootstrap_command_result
168
- end
169
-
170
- protected
171
-
172
- # Default implementation -- override only if required by the transport
173
- def wait_for_remote_response(wait_max_minutes)
174
- end
175
-
176
- def bootstrap_command
177
- @bootstrap_command ||= "cmd.exe /C #{bootstrap_bat_file}"
178
- end
179
-
180
- def create_bootstrap_bat_command(&block)
181
- bootstrap_bat = []
182
- chunk_num = 0
183
- render_template(load_template(config[:bootstrap_template])).each_line do |line|
184
- # escape WIN BATCH special chars
185
- line.gsub!(/[(<|>)^]/).each{|m| "^#{m}"}
186
- # windows commands are limited to 2047 characters
187
- if((bootstrap_bat + [line]).join(" && ").size > 2047 )
188
- yield bootstrap_bat.join(" && "), chunk_num += 1
189
- bootstrap_bat = []
190
- end
191
- bootstrap_bat << ">> #{bootstrap_bat_file} (echo.#{line.chomp.strip})"
192
- end
193
- yield bootstrap_bat.join(" && "), chunk_num += 1
194
- end
195
-
196
- def bootstrap_bat_file
197
- @bootstrap_bat_file ||= "\"%TEMP%\\bootstrap-#{Process.pid}-#{Time.now.to_i}.bat\""
198
- end
199
-
200
- def locate_config_value(key)
201
- key = key.to_sym
202
- Chef::Config[:knife][key] || config[key]
203
- end
204
- end
205
- end
206
- end
1
+ #
2
+ # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
+ # Copyright:: Copyright (c) 2011 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
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.
17
+ #
18
+
19
+ require 'chef/knife'
20
+ require 'chef/knife/bootstrap'
21
+ require 'chef/encrypted_data_bag_item'
22
+ require 'chef/knife/core/windows_bootstrap_context'
23
+
24
+ class Chef
25
+ class Knife
26
+ module BootstrapWindowsBase
27
+
28
+ # :nodoc:
29
+ # Would prefer to do this in a rational way, but can't be done b/c of
30
+ # Mixlib::CLI's design :(
31
+ def self.included(includer)
32
+ includer.class_eval do
33
+
34
+ deps do
35
+ require 'readline'
36
+ require 'chef/json_compat'
37
+ end
38
+
39
+ option :chef_node_name,
40
+ :short => "-N NAME",
41
+ :long => "--node-name NAME",
42
+ :description => "The Chef node name for your new node"
43
+
44
+ option :prerelease,
45
+ :long => "--prerelease",
46
+ :description => "Install the pre-release chef gems"
47
+
48
+ option :bootstrap_version,
49
+ :long => "--bootstrap-version VERSION",
50
+ :description => "The version of Chef to install",
51
+ :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
52
+
53
+ option :bootstrap_proxy,
54
+ :long => "--bootstrap-proxy PROXY_URL",
55
+ :description => "The proxy server for the node being bootstrapped",
56
+ :proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
57
+
58
+ option :bootstrap_no_proxy,
59
+ :long => "--bootstrap-no-proxy ",
60
+ :description => "Avoid a proxy server for the given addresses",
61
+ :proc => Proc.new { |np| Chef::Config[:knife][:bootstrap_no_proxy] = np }
62
+
63
+ option :distro,
64
+ :short => "-d DISTRO",
65
+ :long => "--distro DISTRO",
66
+ :description => "Bootstrap a distro using a template",
67
+ :default => "windows-chef-client-msi"
68
+
69
+ option :template_file,
70
+ :long => "--template-file TEMPLATE",
71
+ :description => "Full path to location of template to use",
72
+ :default => false
73
+
74
+ option :run_list,
75
+ :short => "-r RUN_LIST",
76
+ :long => "--run-list RUN_LIST",
77
+ :description => "Comma separated list of roles/recipes to apply",
78
+ :proc => lambda { |o| o.split(",") },
79
+ :default => []
80
+
81
+ option :first_boot_attributes,
82
+ :short => "-j JSON_ATTRIBS",
83
+ :long => "--json-attributes",
84
+ :description => "A JSON string to be added to the first run of chef-client",
85
+ :proc => lambda { |o| JSON.parse(o) },
86
+ :default => {}
87
+
88
+ option :encrypted_data_bag_secret,
89
+ :short => "-s SECRET",
90
+ :long => "--secret ",
91
+ :description => "The secret key to use to decrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config.",
92
+ :default => false
93
+
94
+ option :encrypted_data_bag_secret_file,
95
+ :long => "--secret-file SECRET_FILE",
96
+ :description => "A file containing the secret key to use to encrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config."
97
+
98
+ option :auth_timeout,
99
+ :long => "--auth-timeout MINUTES",
100
+ :description => "The maximum time in minutes to wait to for authentication over the transport to the node to succeed. The default value is 2 minutes.",
101
+ :default => 2
102
+ end
103
+ end
104
+
105
+ # TODO: This should go away when CHEF-2193 is fixed
106
+ def load_template(template=nil)
107
+ # Are we bootstrapping using an already shipped template?
108
+ if config[:template_file]
109
+ bootstrap_files = config[:template_file]
110
+ else
111
+ bootstrap_files = []
112
+ bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap', "#{config[:distro]}.erb")
113
+ bootstrap_files << File.join(Dir.pwd, ".chef", "bootstrap", "#{config[:distro]}.erb")
114
+ bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{config[:distro]}.erb")
115
+ bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{config[:distro]}.erb"))
116
+ bootstrap_files.flatten!
117
+ end
118
+
119
+ template = Array(bootstrap_files).find do |bootstrap_template|
120
+ Chef::Log.debug("Looking for bootstrap template in #{File.dirname(bootstrap_template)}")
121
+ ::File.exists?(bootstrap_template)
122
+ end
123
+
124
+ unless template
125
+ ui.info("Can not find bootstrap definition for #{config[:distro]}")
126
+ raise Errno::ENOENT
127
+ end
128
+
129
+ Chef::Log.debug("Found bootstrap template in #{File.dirname(template)}")
130
+
131
+ IO.read(template).chomp
132
+ end
133
+
134
+ def render_template(template=nil)
135
+ if config[:encrypted_data_bag_secret_file]
136
+ config[:encrypted_data_bag_secret] = Chef::EncryptedDataBagItem.load_secret(config[:encrypted_data_bag_secret_file])
137
+ end
138
+ context = Knife::Core::WindowsBootstrapContext.new(config, config[:run_list], Chef::Config)
139
+ Erubis::Eruby.new(template).evaluate(context)
140
+ end
141
+
142
+ def bootstrap(proto=nil)
143
+ validate_name_args!
144
+
145
+ @node_name = Array(@name_args).first
146
+ # back compat--templates may use this setting:
147
+ config[:server_name] = @node_name
148
+
149
+ STDOUT.sync = STDERR.sync = true
150
+
151
+ wait_for_remote_response( config[:auth_timeout].to_i )
152
+ ui.info("Bootstrapping Chef on #{ui.color(@node_name, :bold)}")
153
+ # create a bootstrap.bat file on the node
154
+ # we have to run the remote commands in 2047 char chunks
155
+ create_bootstrap_bat_command do |command_chunk, chunk_num|
156
+ begin
157
+ render_command_result = run_command(%Q!cmd.exe /C echo "Rendering #{bootstrap_bat_file} chunk #{chunk_num}" && #{command_chunk}!)
158
+ ui.error("Batch render command returned #{render_command_result}") if render_command_result != 0
159
+ render_command_result
160
+ rescue SystemExit => e
161
+ raise unless e.success?
162
+ end
163
+ end
164
+
165
+ # execute the bootstrap.bat file
166
+ bootstrap_command_result = run_command(bootstrap_command)
167
+ ui.error("Bootstrap command returned #{bootstrap_command_result}") if bootstrap_command_result != 0
168
+ bootstrap_command_result
169
+ end
170
+
171
+ protected
172
+
173
+ # Default implementation -- override only if required by the transport
174
+ def wait_for_remote_response(wait_max_minutes)
175
+ end
176
+
177
+ def bootstrap_command
178
+ @bootstrap_command ||= "cmd.exe /C #{bootstrap_bat_file}"
179
+ end
180
+
181
+ def create_bootstrap_bat_command(&block)
182
+ bootstrap_bat = []
183
+ chunk_num = 0
184
+ render_template(load_template(config[:bootstrap_template])).each_line do |line|
185
+ # escape WIN BATCH special chars
186
+ line.gsub!(/[(<|>)^]/).each{|m| "^#{m}"}
187
+ # windows commands are limited to 2047 characters
188
+ if((bootstrap_bat + [line]).join(" && ").size > 2047 )
189
+ yield bootstrap_bat.join(" && "), chunk_num += 1
190
+ bootstrap_bat = []
191
+ end
192
+ bootstrap_bat << ">> #{bootstrap_bat_file} (echo.#{line.chomp.strip})"
193
+ end
194
+ yield bootstrap_bat.join(" && "), chunk_num += 1
195
+ end
196
+
197
+ def bootstrap_bat_file
198
+ @bootstrap_bat_file ||= "\"%TEMP%\\bootstrap-#{Process.pid}-#{Time.now.to_i}.bat\""
199
+ end
200
+
201
+ def locate_config_value(key)
202
+ key = key.to_sym
203
+ Chef::Config[:knife][key] || config[key]
204
+ end
205
+ end
206
+ end
207
+ end
@@ -1,93 +1,93 @@
1
- #
2
- # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
- # Copyright:: Copyright (c) 2011 Opscode, Inc.
4
- # License:: Apache License, Version 2.0
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.
17
- #
18
-
19
- require 'chef/knife/bootstrap_windows_base'
20
-
21
- class Chef
22
- class Knife
23
- class BootstrapWindowsSsh < Bootstrap
24
-
25
- include Chef::Knife::BootstrapWindowsBase
26
-
27
- deps do
28
- require 'chef/knife/core/windows_bootstrap_context'
29
- require 'chef/json_compat'
30
- require 'tempfile'
31
- require 'highline'
32
- require 'net/ssh'
33
- require 'net/ssh/multi'
34
- Chef::Knife::Ssh.load_deps
35
- end
36
-
37
- banner "knife bootstrap windows ssh FQDN (options)"
38
-
39
- option :ssh_user,
40
- :short => "-x USERNAME",
41
- :long => "--ssh-user USERNAME",
42
- :description => "The ssh username",
43
- :default => "root"
44
-
45
- option :ssh_password,
46
- :short => "-P PASSWORD",
47
- :long => "--ssh-password PASSWORD",
48
- :description => "The ssh password"
49
-
50
- option :ssh_port,
51
- :short => "-p PORT",
52
- :long => "--ssh-port PORT",
53
- :description => "The ssh port",
54
- :default => "22",
55
- :proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key }
56
-
57
- option :ssh_gateway,
58
- :short => "-G GATEWAY",
59
- :long => "--ssh-gateway GATEWAY",
60
- :description => "The ssh gateway",
61
- :proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key }
62
-
63
- option :identity_file,
64
- :short => "-i IDENTITY_FILE",
65
- :long => "--identity-file IDENTITY_FILE",
66
- :description => "The SSH identity file used for authentication"
67
-
68
- option :host_key_verification,
69
- :long => "--[no-]host-key-verification",
70
- :description => "Disable host key verification",
71
- :boolean => true,
72
- :default => true
73
-
74
- def run
75
- bootstrap
76
- end
77
-
78
- def run_command(command = '')
79
- ssh = Chef::Knife::Ssh.new
80
- ssh.name_args = [ server_name, command ]
81
- ssh.config[:ssh_user] = locate_config_value(:ssh_user)
82
- ssh.config[:ssh_password] = locate_config_value(:ssh_password)
83
- ssh.config[:ssh_port] = locate_config_value(:ssh_port)
84
- ssh.config[:ssh_gateway] = locate_config_value(:ssh_gateway)
85
- ssh.config[:identity_file] = config[:identity_file]
86
- ssh.config[:manual] = true
87
- ssh.config[:host_key_verify] = config[:host_key_verify]
88
- ssh.run
89
- end
90
-
91
- end
92
- end
93
- end
1
+ #
2
+ # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
+ # Copyright:: Copyright (c) 2011 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
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.
17
+ #
18
+
19
+ require 'chef/knife/bootstrap_windows_base'
20
+
21
+ class Chef
22
+ class Knife
23
+ class BootstrapWindowsSsh < Bootstrap
24
+
25
+ include Chef::Knife::BootstrapWindowsBase
26
+
27
+ deps do
28
+ require 'chef/knife/core/windows_bootstrap_context'
29
+ require 'chef/json_compat'
30
+ require 'tempfile'
31
+ require 'highline'
32
+ require 'net/ssh'
33
+ require 'net/ssh/multi'
34
+ Chef::Knife::Ssh.load_deps
35
+ end
36
+
37
+ banner "knife bootstrap windows ssh FQDN (options)"
38
+
39
+ option :ssh_user,
40
+ :short => "-x USERNAME",
41
+ :long => "--ssh-user USERNAME",
42
+ :description => "The ssh username",
43
+ :default => "root"
44
+
45
+ option :ssh_password,
46
+ :short => "-P PASSWORD",
47
+ :long => "--ssh-password PASSWORD",
48
+ :description => "The ssh password"
49
+
50
+ option :ssh_port,
51
+ :short => "-p PORT",
52
+ :long => "--ssh-port PORT",
53
+ :description => "The ssh port",
54
+ :default => "22",
55
+ :proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key }
56
+
57
+ option :ssh_gateway,
58
+ :short => "-G GATEWAY",
59
+ :long => "--ssh-gateway GATEWAY",
60
+ :description => "The ssh gateway",
61
+ :proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key }
62
+
63
+ option :identity_file,
64
+ :short => "-i IDENTITY_FILE",
65
+ :long => "--identity-file IDENTITY_FILE",
66
+ :description => "The SSH identity file used for authentication"
67
+
68
+ option :host_key_verification,
69
+ :long => "--[no-]host-key-verification",
70
+ :description => "Disable host key verification",
71
+ :boolean => true,
72
+ :default => true
73
+
74
+ def run
75
+ bootstrap
76
+ end
77
+
78
+ def run_command(command = '')
79
+ ssh = Chef::Knife::Ssh.new
80
+ ssh.name_args = [ server_name, command ]
81
+ ssh.config[:ssh_user] = locate_config_value(:ssh_user)
82
+ ssh.config[:ssh_password] = locate_config_value(:ssh_password)
83
+ ssh.config[:ssh_port] = locate_config_value(:ssh_port)
84
+ ssh.config[:ssh_gateway] = locate_config_value(:ssh_gateway)
85
+ ssh.config[:identity_file] = config[:identity_file]
86
+ ssh.config[:manual] = true
87
+ ssh.config[:host_key_verify] = config[:host_key_verify]
88
+ ssh.run
89
+ end
90
+
91
+ end
92
+ end
93
+ end