chef-provisioning-fog 0.10 → 0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chef/provisioning/fog_driver.rb +1 -0
- data/lib/chef/provisioning/fog_driver/driver.rb +37 -18
- data/lib/chef/provisioning/fog_driver/providers/aws.rb +97 -0
- data/lib/chef/provisioning/fog_driver/version.rb +1 -1
- data/lib/chef/resource/fog_key_pair.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe71d09d45a8426eb7af5b9367aac358cf752124
|
4
|
+
data.tar.gz: 0c454ebeb8827924742c91f1c566c90f6d6f3560
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 121ff3e73fefe9f6b401727831a46d47b2a7550c07fe0f6ec71915883e7ff7da8626a0989758b674768593149046ecb3a3ba49cb55fffcd112dd2a1d7364b9e8
|
7
|
+
data.tar.gz: 34447372a2c4605cc90b4a476aef6454be76892ccfd88b27a85d93edce61d86e810888d115cadba6425f8cd7706579bad125850e8473af1ebda42b542a0f5aa2
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'chef/provisioning/fog_driver/driver'
|
@@ -10,7 +10,9 @@ require 'chef/provisioning/convergence_strategy/install_sh'
|
|
10
10
|
require 'chef/provisioning/convergence_strategy/install_cached'
|
11
11
|
require 'chef/provisioning/convergence_strategy/no_converge'
|
12
12
|
require 'chef/provisioning/transport/ssh'
|
13
|
+
require 'chef/provisioning/transport/winrm'
|
13
14
|
require 'chef/provisioning/fog_driver/version'
|
15
|
+
|
14
16
|
require 'fog'
|
15
17
|
require 'fog/core'
|
16
18
|
require 'fog/compute'
|
@@ -258,9 +260,15 @@ module FogDriver
|
|
258
260
|
end
|
259
261
|
|
260
262
|
# Not meant to be part of public interface
|
261
|
-
def transport_for(machine_spec, machine_options, server)
|
262
|
-
|
263
|
-
|
263
|
+
def transport_for(machine_spec, machine_options, server, action_handler = nil)
|
264
|
+
if machine_spec.location['is_windows']
|
265
|
+
action_handler.report_progress "Waiting for admin password on #{machine_spec.name} to be ready (may take up to 15 minutes)..." if action_handler
|
266
|
+
transport = create_winrm_transport(machine_spec, machine_options, server)
|
267
|
+
action_handler.report_progress 'Admin password available ...' if action_handler
|
268
|
+
transport
|
269
|
+
else
|
270
|
+
create_ssh_transport(machine_spec, machine_options, server)
|
271
|
+
end
|
264
272
|
end
|
265
273
|
|
266
274
|
protected
|
@@ -400,7 +408,8 @@ module FogDriver
|
|
400
408
|
end
|
401
409
|
|
402
410
|
def wait_for_transport(action_handler, machine_spec, machine_options, server)
|
403
|
-
|
411
|
+
|
412
|
+
transport = transport_for(machine_spec, machine_options, server, action_handler)
|
404
413
|
if !transport.available?
|
405
414
|
if action_handler.should_perform_actions
|
406
415
|
action_handler.report_progress "waiting for #{machine_spec.name} (#{server.id} on #{driver_url}) to be connectable (transport up and running) ..."
|
@@ -560,37 +569,43 @@ module FogDriver
|
|
560
569
|
end
|
561
570
|
end
|
562
571
|
|
563
|
-
|
564
|
-
|
565
|
-
#
|
566
|
-
#
|
567
|
-
#
|
568
|
-
|
569
|
-
:keys_only => true,
|
570
|
-
:host_key_alias => "#{server.id}.#{provider}"
|
571
|
-
}.merge(machine_options[:ssh_options] || {})
|
572
|
+
# Get the private key for a machine - prioritize the server data, fall back to the
|
573
|
+
# the machine spec data, and if that doesn't work, raise an exception.
|
574
|
+
# @param [Hash] machine_spec Machine spec data
|
575
|
+
# @param [Chef::Provisioning::Machine] server a Machine representing the server
|
576
|
+
# @return [String] PEM-encoded private key
|
577
|
+
def private_key_for(machine_spec, server)
|
572
578
|
if server.respond_to?(:private_key) && server.private_key
|
573
|
-
|
579
|
+
server.private_key
|
574
580
|
elsif server.respond_to?(:key_name) && server.key_name
|
575
581
|
key = get_private_key(server.key_name)
|
576
582
|
if !key
|
577
583
|
raise "Server has key name '#{server.key_name}', but the corresponding private key was not found locally. Check if the key is in Chef::Config.private_key_paths: #{Chef::Config.private_key_paths.join(', ')}"
|
578
584
|
end
|
579
|
-
|
585
|
+
key
|
580
586
|
elsif machine_spec.location['key_name']
|
581
587
|
key = get_private_key(machine_spec.location['key_name'])
|
582
588
|
if !key
|
583
589
|
raise "Server was created with key name '#{machine_spec.location['key_name']}', but the corresponding private key was not found locally. Check if the key is in Chef::Config.private_key_paths: #{Chef::Config.private_key_paths.join(', ')}"
|
584
590
|
end
|
585
|
-
|
591
|
+
key
|
586
592
|
elsif machine_options[:bootstrap_options][:key_path]
|
587
|
-
|
593
|
+
IO.read(machine_options[:bootstrap_options][:key_path])
|
588
594
|
elsif machine_options[:bootstrap_options][:key_name]
|
589
|
-
|
595
|
+
get_private_key(machine_options[:bootstrap_options][:key_name])
|
590
596
|
else
|
591
597
|
# TODO make a way to suggest other keys to try ...
|
592
598
|
raise "No key found to connect to #{machine_spec.name} (#{machine_spec.location.inspect})!"
|
593
599
|
end
|
600
|
+
end
|
601
|
+
|
602
|
+
def ssh_options_for(machine_spec, machine_options, server)
|
603
|
+
result = {
|
604
|
+
:auth_methods => [ 'publickey' ],
|
605
|
+
:keys_only => true,
|
606
|
+
:host_key_alias => "#{server.id}.#{provider}"
|
607
|
+
}.merge(machine_options[:ssh_options] || {})
|
608
|
+
result[:key_data] = [ private_key_for(machine_spec, server) ]
|
594
609
|
result
|
595
610
|
end
|
596
611
|
|
@@ -598,6 +613,10 @@ module FogDriver
|
|
598
613
|
'root'
|
599
614
|
end
|
600
615
|
|
616
|
+
def create_winrm_transport(machine_spec, machine_options, server)
|
617
|
+
fail "This provider doesn't know how to do that."
|
618
|
+
end
|
619
|
+
|
601
620
|
def create_ssh_transport(machine_spec, machine_options, server)
|
602
621
|
ssh_options = ssh_options_for(machine_spec, machine_options, server)
|
603
622
|
username = machine_spec.location['ssh_username'] || default_ssh_username
|
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'chef/log'
|
2
2
|
require 'fog/aws'
|
3
3
|
require 'uri'
|
4
|
+
require 'base64'
|
5
|
+
require 'openssl'
|
6
|
+
require 'pathname'
|
7
|
+
require 'chef/provisioning/transport/winrm'
|
4
8
|
|
5
9
|
# fog:AWS:<account_id>:<region>
|
6
10
|
# fog:AWS:<profile_name>
|
@@ -23,6 +27,45 @@ module FogDriver
|
|
23
27
|
'ubuntu'
|
24
28
|
end
|
25
29
|
|
30
|
+
# Create a WinRM transport for an AWS instance
|
31
|
+
# @param [Hash] machine_spec Machine-spec hash
|
32
|
+
# @param [Hash] machine_options Machine options (from the recipe)
|
33
|
+
# @param [Fog::Compute::Server] server A Fog mapping to the AWS instance
|
34
|
+
# @return [ChefMetal::Transport::WinRM] A WinRM Transport object to talk to the server
|
35
|
+
def create_winrm_transport(machine_spec, machine_options, server)
|
36
|
+
remote_host = if machine_spec.location['use_private_ip_for_ssh']
|
37
|
+
server.private_ip_address
|
38
|
+
elsif !server.public_ip_address
|
39
|
+
Chef::Log.warn("Server #{machine_spec.name} has no public ip address. Using private ip '#{server.private_ip_address}'. Set driver option 'use_private_ip_for_ssh' => true if this will always be the case ...")
|
40
|
+
server.private_ip_address
|
41
|
+
elsif server.public_ip_address
|
42
|
+
server.public_ip_address
|
43
|
+
else
|
44
|
+
fail "Server #{server.id} has no private or public IP address!"
|
45
|
+
end
|
46
|
+
|
47
|
+
port = machine_spec.location['winrm_port'] || 5985
|
48
|
+
endpoint = "http://#{remote_host}:#{port}/wsman"
|
49
|
+
type = :plaintext
|
50
|
+
pem_bytes = private_key_for(machine_spec, server)
|
51
|
+
encrypted_admin_password = wait_for_admin_password(machine_spec)
|
52
|
+
decoded = Base64.decode64(encrypted_admin_password)
|
53
|
+
private_key = OpenSSL::PKey::RSA.new(pem_bytes)
|
54
|
+
decrypted_password = private_key.private_decrypt decoded
|
55
|
+
|
56
|
+
# Use basic HTTP auth - this is required for the WinRM setup we
|
57
|
+
# are using
|
58
|
+
# TODO: Improve that.
|
59
|
+
options = {
|
60
|
+
:user => machine_spec.location['winrm.username'] || 'Administrator',
|
61
|
+
:pass => decrypted_password,
|
62
|
+
:disable_sspi => true,
|
63
|
+
:basic_auth_only => true
|
64
|
+
}
|
65
|
+
|
66
|
+
Chef::Provisioning::Transport::WinRM.new(endpoint, type, options, {})
|
67
|
+
end
|
68
|
+
|
26
69
|
def allocate_image(action_handler, image_spec, image_options, machine_spec)
|
27
70
|
if image_spec.location
|
28
71
|
image = compute.images.get(image_spec.location['image_id'])
|
@@ -87,6 +130,12 @@ module FogDriver
|
|
87
130
|
if !bootstrap_options[:key_name]
|
88
131
|
bootstrap_options[:key_name] = overwrite_default_key_willy_nilly(action_handler, machine_spec)
|
89
132
|
end
|
133
|
+
|
134
|
+
if machine_options[:is_windows]
|
135
|
+
Chef::Log.debug('Attaching WinRM data for user data.')
|
136
|
+
# Enable WinRM basic auth, HTTP and open the firewall
|
137
|
+
bootstrap_options[:user_data] = user_data
|
138
|
+
end
|
90
139
|
bootstrap_options.delete(:tags) # we handle these separately for performance reasons
|
91
140
|
bootstrap_options
|
92
141
|
end
|
@@ -351,6 +400,27 @@ module FogDriver
|
|
351
400
|
end
|
352
401
|
|
353
402
|
private
|
403
|
+
def user_data
|
404
|
+
# TODO: Make this use HTTPS at some point.
|
405
|
+
<<EOD
|
406
|
+
<powershell>
|
407
|
+
winrm quickconfig -q
|
408
|
+
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="300"}'
|
409
|
+
winrm set winrm/config '@{MaxTimeoutms="1800000"}'
|
410
|
+
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
|
411
|
+
winrm set winrm/config/service/auth '@{Basic="true"}'
|
412
|
+
|
413
|
+
netsh advfirewall firewall add rule name="WinRM 5985" protocol=TCP dir=in localport=5985 action=allow
|
414
|
+
netsh advfirewall firewall add rule name="WinRM 5986" protocol=TCP dir=in localport=5986 action=allow
|
415
|
+
|
416
|
+
net stop winrm
|
417
|
+
sc config winrm start=auto
|
418
|
+
net start winrm
|
419
|
+
</powershell>
|
420
|
+
|
421
|
+
EOD
|
422
|
+
end
|
423
|
+
|
354
424
|
def self.default_ami_for_region(region)
|
355
425
|
Chef::Log.debug("Choosing default AMI for region '#{region}'")
|
356
426
|
|
@@ -374,6 +444,33 @@ module FogDriver
|
|
374
444
|
end
|
375
445
|
end
|
376
446
|
|
447
|
+
# Wait for the Windows Admin password to become available
|
448
|
+
# @param [Hash] machine_spec Machine spec data
|
449
|
+
# @return [String] encrypted admin password
|
450
|
+
def wait_for_admin_password(machine_spec)
|
451
|
+
time_elapsed = 0
|
452
|
+
sleep_time = 10
|
453
|
+
max_wait_time = 900 # 15 minutes
|
454
|
+
encrypted_admin_password = nil
|
455
|
+
instance_id = machine_spec.location['server_id']
|
456
|
+
|
457
|
+
|
458
|
+
Chef::Log.info "waiting for #{machine_spec.name}'s admin password to be available..."
|
459
|
+
while time_elapsed < max_wait_time && encrypted_admin_password.nil?
|
460
|
+
response = compute.get_password_data(instance_id)
|
461
|
+
encrypted_admin_password = response.body['passwordData']
|
462
|
+
if encrypted_admin_password.nil?
|
463
|
+
Chef::Log.info "#{time_elapsed}/#{max_wait_time}s elapsed -- sleeping #{sleep_time} seconds for #{machine_spec.name}'s admin password."
|
464
|
+
sleep(sleep_time)
|
465
|
+
time_elapsed += sleep_time
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
Chef::Log.info "#{machine_spec.name}'s admin password is available!'"
|
470
|
+
|
471
|
+
encrypted_admin_password
|
472
|
+
end
|
473
|
+
|
377
474
|
end
|
378
475
|
end
|
379
476
|
end
|
@@ -28,7 +28,7 @@ class Chef::Resource::FogKeyPair < Chef::Resource::LWRPBase
|
|
28
28
|
end
|
29
29
|
|
30
30
|
# We are not interested in Chef's cloning behavior here.
|
31
|
-
def load_prior_resource
|
31
|
+
def load_prior_resource(*args)
|
32
32
|
Chef::Log.debug("Overloading #{resource_name}.load_prior_resource with NOOP")
|
33
33
|
end
|
34
34
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-provisioning-fog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.11'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Keiser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- Rakefile
|
108
108
|
- lib/chef/provider/fog_key_pair.rb
|
109
109
|
- lib/chef/provisioning/driver_init/fog.rb
|
110
|
+
- lib/chef/provisioning/fog_driver.rb
|
110
111
|
- lib/chef/provisioning/fog_driver/driver.rb
|
111
112
|
- lib/chef/provisioning/fog_driver/providers/aws.rb
|
112
113
|
- lib/chef/provisioning/fog_driver/providers/aws/credentials.rb
|