bosh-bootstrap 0.7.1 → 0.8.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.
- data/ChangeLog.md +6 -0
- data/README.md +1 -3
- data/bosh-bootstrap.gemspec +1 -1
- data/lib/bosh/providers/aws.rb +5 -9
- data/lib/bosh/providers/base_provider.rb +6 -0
- data/lib/bosh-bootstrap/cli.rb +91 -62
- data/lib/bosh-bootstrap/commander/remote_server.rb +11 -9
- data/lib/bosh-bootstrap/helpers/settings.rb +64 -2
- data/lib/bosh-bootstrap/stages/stage_prepare_inception_vm/install_bosh +1 -1
- data/lib/bosh-bootstrap/version.rb +1 -1
- data/spec/spec_helper.rb +1 -7
- data/spec/unit/aws_spec.rb +21 -5
- data/spec/unit/cli_spec.rb +12 -9
- data/spec/unit/cli_ssh_spec.rb +10 -5
- data/spec/unit/cli_upgrade_inception_spec.rb +0 -2
- metadata +7 -7
data/ChangeLog.md
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
`bosh-bootstrap` is a command line tool that you can run on your laptop and automatically get a microbosh (and an inception VM) deployed on either AWS or OpenStack.
|
4
4
|
|
5
|
+
## v0.8
|
6
|
+
|
7
|
+
* SSH keys used to access inception VM are now generated and stored within the `~/.bosh_bootstrap/ssh` folder. This fixes many issues that many people were having (their keys had passphrases, their fog_default keypair was old). It also allows a manifest file to be shared between people as it contains the private key contents, and the private key file will be recreated if it is missing.
|
8
|
+
* existing inception VMs' manifest.yml will be upgraded automatically and a backup file created (just in case)
|
9
|
+
* tightening of net-ssh & net-scp gems to ensure the bosh-bootstrap gem can be installed [thx @mmb]
|
10
|
+
|
5
11
|
## v0.7
|
6
12
|
|
7
13
|
Notable:
|
data/README.md
CHANGED
@@ -22,9 +22,7 @@ It is now very simple to bootstrap a micro BOSH from a single, local CLI. The bo
|
|
22
22
|
|
23
23
|
To be cute about it, the Stark & Wayne Bosh Bootstrapper aims to provide lifecycle management for the BOSH lifecycle manager. Zing! See the "Deep dive into deploy command" section below for greater understanding why the Stark & Wayne Bosh Bootstrapper is very useful.
|
24
24
|
|
25
|
-
[](https://travis-ci.org/StarkAndWayne/bosh-bootstrap)
|
26
|
-
|
27
|
-
[](https://codeclimate.com/github/StarkAndWayne/bosh-bootstrap)
|
25
|
+
[](http://badge.fury.io/rb/bosh-bootstrap) [](https://travis-ci.org/StarkAndWayne/bosh-bootstrap) [](https://codeclimate.com/github/StarkAndWayne/bosh-bootstrap)
|
28
26
|
|
29
27
|
## Installation
|
30
28
|
|
data/bosh-bootstrap.gemspec
CHANGED
@@ -28,7 +28,7 @@ EOS
|
|
28
28
|
gem.add_dependency "settingslogic"
|
29
29
|
gem.add_dependency "POpen4"
|
30
30
|
gem.add_dependency "net-ssh", "~> 2.2.2"
|
31
|
-
gem.add_dependency "net-scp"
|
31
|
+
gem.add_dependency "net-scp", "~> 1.0.4"
|
32
32
|
gem.add_dependency "fog", "~>1.8.0"
|
33
33
|
gem.add_dependency "escape"
|
34
34
|
gem.add_dependency "redcard"
|
data/lib/bosh/providers/aws.rb
CHANGED
@@ -187,14 +187,10 @@ class Bosh::Providers::AWS < Bosh::Providers::BaseProvider
|
|
187
187
|
server = fog_compute.servers.new(new_attributes)
|
188
188
|
|
189
189
|
unless new_attributes[:key_name]
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
:name => "fog_#{name}",
|
195
|
-
:public_key => server.public_key
|
196
|
-
)
|
197
|
-
end
|
190
|
+
raise "please provide :key_name attribute"
|
191
|
+
end
|
192
|
+
unless private_key_path = new_attributes.delete(:private_key_path)
|
193
|
+
raise "please provide :private_key_path attribute"
|
198
194
|
end
|
199
195
|
|
200
196
|
if vpc
|
@@ -215,7 +211,7 @@ class Bosh::Providers::AWS < Bosh::Providers::BaseProvider
|
|
215
211
|
|
216
212
|
server.save
|
217
213
|
server.wait_for { ready? }
|
218
|
-
server.setup(:
|
214
|
+
server.setup(:keys => [private_key_path])
|
219
215
|
server
|
220
216
|
end
|
221
217
|
|
@@ -12,4 +12,10 @@ class Bosh::Providers::BaseProvider
|
|
12
12
|
def create_key_pair(key_pair_name)
|
13
13
|
fog_compute.key_pairs.create(:name => key_pair_name)
|
14
14
|
end
|
15
|
+
|
16
|
+
def delete_key_pair_if_exists(key_pair_name)
|
17
|
+
if fog_key_pair = fog_compute.key_pairs.get(key_pair_name)
|
18
|
+
fog_key_pair.destroy
|
19
|
+
end
|
20
|
+
end
|
15
21
|
end
|
data/lib/bosh-bootstrap/cli.rb
CHANGED
@@ -23,13 +23,13 @@ module Bosh::Bootstrap
|
|
23
23
|
|
24
24
|
desc "deploy", "Bootstrap Micro BOSH, and optionally an Inception VM"
|
25
25
|
method_option :fog, :type => :string, :desc => "fog config file (default: ~/.fog)"
|
26
|
-
method_option :"private-key", :type => :string, :desc => "Local passphrase-less private key path"
|
27
26
|
method_option :"upgrade-deps", :type => :boolean, :desc => "Force upgrade dependencies, packages & gems"
|
28
27
|
method_option :"edge-deployer", :type => :boolean, :desc => "Install bosh deployer from git instead of rubygems"
|
29
28
|
method_option :"stable-stemcell", :type => :boolean, :desc => "Use recent stable microbosh stemcell"
|
30
29
|
method_option :"latest-stemcell", :type => :boolean, :desc => "Use latest microbosh stemcell; possibly not tagged stable [default]"
|
31
30
|
method_option :"edge-stemcell", :type => :boolean, :desc => "Create custom stemcell from BOSH git source"
|
32
31
|
def deploy
|
32
|
+
migrate_old_settings
|
33
33
|
load_deploy_options # from method_options above
|
34
34
|
|
35
35
|
deploy_stage_1_choose_infrastructure_provider
|
@@ -43,6 +43,7 @@ module Bosh::Bootstrap
|
|
43
43
|
desc "upgrade-inception", "Upgrade inception VM with latest packages, gems, security group ports"
|
44
44
|
method_option :"edge-deployer", :type => :boolean, :desc => "Install bosh deployer from git instead of rubygems"
|
45
45
|
def upgrade_inception
|
46
|
+
migrate_old_settings
|
46
47
|
load_deploy_options # from method_options above
|
47
48
|
|
48
49
|
setup_server
|
@@ -69,6 +70,7 @@ module Bosh::Bootstrap
|
|
69
70
|
opened.
|
70
71
|
DESC
|
71
72
|
def ssh(cmd=nil)
|
73
|
+
migrate_old_settings
|
72
74
|
run_ssh_command_or_open_tunnel(cmd)
|
73
75
|
end
|
74
76
|
|
@@ -78,6 +80,7 @@ module Bosh::Bootstrap
|
|
78
80
|
giving you persistance across disconnects.
|
79
81
|
DESC
|
80
82
|
def tmux
|
83
|
+
migrate_old_settings
|
81
84
|
run_ssh_command_or_open_tunnel(["-t", "tmux attach || tmux new-session"])
|
82
85
|
end
|
83
86
|
|
@@ -87,6 +90,7 @@ module Bosh::Bootstrap
|
|
87
90
|
Requires outgoing UDP port 60001 to the Inception VM
|
88
91
|
DESC
|
89
92
|
def mosh
|
93
|
+
migrate_old_settings
|
90
94
|
open_mosh_session
|
91
95
|
end
|
92
96
|
|
@@ -234,6 +238,10 @@ module Bosh::Bootstrap
|
|
234
238
|
save_settings!
|
235
239
|
|
236
240
|
if settings["inception"]["create_new"] && !settings["inception"]["host"]
|
241
|
+
unless settings["inception"]["key_pair"]
|
242
|
+
create_inception_key_pair
|
243
|
+
end
|
244
|
+
recreate_local_ssh_keys_for_inception_vm
|
237
245
|
aws? ? boot_aws_inception_vm : boot_openstack_inception_vm
|
238
246
|
end
|
239
247
|
# If successfully validate inception VM, then save those settings.
|
@@ -254,6 +262,8 @@ module Bosh::Bootstrap
|
|
254
262
|
def deploy_stage_4_prepare_inception_vm
|
255
263
|
unless settings["inception"] && settings["inception"]["prepared"] && !settings["upgrade_deps"]
|
256
264
|
header "Stage 4: Preparing the Inception VM"
|
265
|
+
recreate_local_ssh_keys_for_inception_vm
|
266
|
+
|
257
267
|
unless run_server(Bosh::Bootstrap::Stages::StagePrepareInceptionVm.new(settings).commands)
|
258
268
|
error "Failed to complete Stage 4: Preparing the Inception VM"
|
259
269
|
end
|
@@ -269,6 +279,8 @@ module Bosh::Bootstrap
|
|
269
279
|
|
270
280
|
def deploy_stage_5_deploy_micro_bosh
|
271
281
|
header "Stage 5: Deploying micro BOSH"
|
282
|
+
recreate_local_ssh_keys_for_inception_vm
|
283
|
+
|
272
284
|
unless run_server(Bosh::Bootstrap::Stages::MicroBoshDeploy.new(settings).commands)
|
273
285
|
error "Failed to complete Stage 5: Deploying micro BOSH"
|
274
286
|
end
|
@@ -329,7 +341,8 @@ module Bosh::Bootstrap
|
|
329
341
|
|
330
342
|
def setup_server
|
331
343
|
if settings["inception"]["host"]
|
332
|
-
|
344
|
+
private_key_path = settings["inception"]["local_private_key_path"]
|
345
|
+
@server = Commander::RemoteServer.new(settings.inception.host, private_key_path)
|
333
346
|
confirm "Using inception VM #{settings.inception.username}@#{settings.inception.host}"
|
334
347
|
else
|
335
348
|
@server = Commander::LocalServer.new
|
@@ -358,11 +371,11 @@ module Bosh::Bootstrap
|
|
358
371
|
def run_ssh_command_or_open_tunnel(cmd)
|
359
372
|
ensure_inception_vm
|
360
373
|
ensure_inception_vm_has_launched
|
374
|
+
recreate_local_ssh_keys_for_inception_vm
|
361
375
|
|
362
|
-
username =
|
363
|
-
host = settings
|
364
|
-
|
365
|
-
result = system Escape.shell_command(['ssh', "-i", "#{private_key_path}", "#{username}@#{host}", cmd].flatten.compact)
|
376
|
+
username = "vcap"
|
377
|
+
host = settings["inception"]["host"]
|
378
|
+
result = system Escape.shell_command(["ssh", "-i", inception_vm_private_key_path, "#{username}@#{host}", cmd].flatten.compact)
|
366
379
|
exit result
|
367
380
|
end
|
368
381
|
|
@@ -382,6 +395,7 @@ module Bosh::Bootstrap
|
|
382
395
|
ensure_mosh_installed
|
383
396
|
ensure_inception_vm
|
384
397
|
ensure_inception_vm_has_launched
|
398
|
+
recreate_local_ssh_keys_for_inception_vm
|
385
399
|
ensure_security_group_allows_mosh
|
386
400
|
|
387
401
|
username = 'vcap'
|
@@ -472,21 +486,6 @@ module Bosh::Bootstrap
|
|
472
486
|
# be uploaded with values such as:
|
473
487
|
# -> settings["micro_bosh_stemcell_name"] = "micro-bosh-stemcell-aws-0.8.1.tgz"
|
474
488
|
|
475
|
-
if options["private-key"]
|
476
|
-
private_key_path = File.expand_path(options["private-key"])
|
477
|
-
unless File.exists?(private_key_path)
|
478
|
-
error "Cannot find a file at #{private_key_path}"
|
479
|
-
end
|
480
|
-
public_key_path = "#{private_key_path}.pub"
|
481
|
-
unless File.exists?(public_key_path)
|
482
|
-
error "Cannot find a file at #{public_key_path}"
|
483
|
-
end
|
484
|
-
|
485
|
-
settings["local"] ||= {}
|
486
|
-
settings["local"]["private_key_path"] = private_key_path
|
487
|
-
settings["local"]["public_key_path"] = public_key_path
|
488
|
-
end
|
489
|
-
|
490
489
|
if options["upgrade-deps"]
|
491
490
|
settings["upgrade_deps"] = options["upgrade-deps"]
|
492
491
|
else
|
@@ -806,14 +805,53 @@ module Bosh::Bootstrap
|
|
806
805
|
end
|
807
806
|
end
|
808
807
|
|
808
|
+
# Creates a key pair with the provider for the inception VM.
|
809
|
+
# Stores the private & public key in settings manifest.
|
810
|
+
#
|
811
|
+
# If provider already has a key pair of the same name, it re-creates it.
|
812
|
+
#
|
813
|
+
# Adds settings:
|
814
|
+
# * inception.key_pair.name
|
815
|
+
# * inception.key_pair.public_key
|
816
|
+
# * inception.key_pair.private_key
|
817
|
+
# * inception.key_pair.fingerprint
|
818
|
+
def create_inception_key_pair
|
819
|
+
say "Creating ssh key pair for Inception VM..."
|
820
|
+
create_key_pair_store_in_settings("inception")
|
821
|
+
end
|
822
|
+
|
823
|
+
# Creates a key pair with the provider.
|
824
|
+
# Stores the private & public key in settings manifest.
|
825
|
+
#
|
826
|
+
# If provider already has a key pair of the same name, it re-creates it.
|
827
|
+
#
|
828
|
+
# Adds settings:
|
829
|
+
# * <settings_key>.key_pair.name # defaults to settings_key value
|
830
|
+
# * <settings_key>.key_pair.public_key
|
831
|
+
# * <settings_key>.key_pair.private_key
|
832
|
+
# * <settings_key>.key_pair.fingerprint
|
833
|
+
def create_key_pair_store_in_settings(settings_key, default_key_pair_name = settings_key)
|
834
|
+
settings[settings_key] ||= {}
|
835
|
+
settings[settings_key]["key_pair"] ||= {}
|
836
|
+
key_pair_settings = settings[settings_key]["key_pair"]
|
837
|
+
key_pair_settings["name"] ||= default_key_pair_name
|
838
|
+
key_pair_name = key_pair_settings["name"]
|
839
|
+
|
840
|
+
provider.delete_key_pair_if_exists(key_pair_name)
|
841
|
+
fog_key_pair = provider.create_key_pair(key_pair_name)
|
842
|
+
|
843
|
+
key_pair_settings["private_key"] = fog_key_pair.private_key
|
844
|
+
key_pair_settings["public_key"] = fog_key_pair.public_key
|
845
|
+
key_pair_settings["fingerprint"] = fog_key_pair.fingerprint
|
846
|
+
save_settings!
|
847
|
+
end
|
848
|
+
|
809
849
|
# Provisions an AWS m1.small VM as the inception VM
|
810
850
|
# Updates settings.inception.host/username
|
811
851
|
#
|
812
852
|
# NOTE: if any stage fails, when the CLI is re-run
|
813
853
|
# and "create new server" is selected again, the process should
|
814
854
|
# complete
|
815
|
-
#
|
816
|
-
# Assumes that local CLI user has public/private keys at ~/.ssh/id_rsa.pub
|
817
855
|
def boot_aws_inception_vm
|
818
856
|
say "" # glowing whitespace
|
819
857
|
|
@@ -823,15 +861,15 @@ module Bosh::Bootstrap
|
|
823
861
|
save_settings!
|
824
862
|
end
|
825
863
|
|
826
|
-
public_key_path, private_key_path = local_ssh_key_paths
|
827
864
|
unless settings["inception"] && settings["inception"]["server_id"]
|
828
865
|
username = "ubuntu"
|
829
866
|
size = "m1.small"
|
830
867
|
ip_address = settings["inception"]["ip_address"]
|
868
|
+
key_name = settings["inception"]["key_pair"]["name"]
|
831
869
|
say "Provisioning #{size} for inception VM..."
|
832
870
|
inception_vm_attributes = {
|
833
|
-
:
|
834
|
-
:private_key_path =>
|
871
|
+
:key_name => key_name,
|
872
|
+
:private_key_path => inception_vm_private_key_path,
|
835
873
|
:flavor_id => size,
|
836
874
|
:bits => 64,
|
837
875
|
:username => "ubuntu",
|
@@ -847,7 +885,7 @@ module Bosh::Bootstrap
|
|
847
885
|
error "Something mysteriously cloudy happened and fog could not provision a VM. Please check your limits."
|
848
886
|
end
|
849
887
|
|
850
|
-
settings["inception"]
|
888
|
+
settings["inception"].delete("create_new")
|
851
889
|
settings["inception"]["server_id"] = server.id
|
852
890
|
settings["inception"]["username"] = username
|
853
891
|
save_settings!
|
@@ -885,25 +923,9 @@ module Bosh::Bootstrap
|
|
885
923
|
# NOTE: if any stage fails, when the CLI is re-run
|
886
924
|
# and "create new server" is selected again, the process should
|
887
925
|
# complete
|
888
|
-
#
|
889
|
-
# Assumes that local CLI user has public/private keys at ~/.ssh/id_rsa.pub
|
890
926
|
def boot_openstack_inception_vm
|
891
927
|
say "" # glowing whitespace
|
892
928
|
|
893
|
-
public_key_path, private_key_path = local_ssh_key_paths
|
894
|
-
|
895
|
-
# make sure we've a fog key pair
|
896
|
-
key_pair_name = Fog.respond_to?(:credential) && Fog.credential || :default
|
897
|
-
unless key_pair = fog_compute.key_pairs.get("fog_#{key_pair_name}")
|
898
|
-
say "creating key pair fog_#{key_pair_name}..."
|
899
|
-
public_key = File.open(public_key_path, 'rb') { |f| f.read }
|
900
|
-
key_pair = fog_compute.key_pairs.create(
|
901
|
-
:name => "fog_#{key_pair_name}",
|
902
|
-
:public_key => public_key
|
903
|
-
)
|
904
|
-
end
|
905
|
-
confirm "Using key pair #{key_pair.name} for Inception VM"
|
906
|
-
|
907
929
|
unless settings["inception"] && settings["inception"]["server_id"]
|
908
930
|
username = "ubuntu"
|
909
931
|
say "Provisioning server for inception VM..."
|
@@ -951,12 +973,12 @@ module Bosh::Bootstrap
|
|
951
973
|
say ""
|
952
974
|
confirm "Using image #{inception_image.name} for Inception VM"
|
953
975
|
|
976
|
+
key_name = settings["inception"]["key_pair"]["name"]
|
977
|
+
|
954
978
|
# Boot OpenStack server
|
955
979
|
server = fog_compute.servers.create(
|
956
980
|
:name => "Inception VM",
|
957
|
-
:key_name =>
|
958
|
-
:public_key_path => public_key_path,
|
959
|
-
:private_key_path => private_key_path,
|
981
|
+
:key_name => key_name,
|
960
982
|
:flavor_ref => inception_flavor.id,
|
961
983
|
:image_ref => inception_image.id,
|
962
984
|
:username => username
|
@@ -1074,30 +1096,37 @@ module Bosh::Bootstrap
|
|
1074
1096
|
end
|
1075
1097
|
|
1076
1098
|
def display_inception_ssh_access
|
1077
|
-
|
1078
|
-
say "SSH access: ssh -i #{private_key_path} #{settings["inception"]["username"]}@#{settings["inception"]["host"]}"
|
1099
|
+
say "SSH access: ssh -i #{inception_vm_private_key_path} #{settings["inception"]["username"]}@#{settings["inception"]["host"]}"
|
1079
1100
|
end
|
1080
1101
|
|
1081
1102
|
def run_server(server_commands)
|
1082
1103
|
server.run(server_commands)
|
1083
1104
|
end
|
1084
1105
|
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
def local_ssh_key_paths
|
1090
|
-
unless settings["local"] && settings["local"]["private_key_path"]
|
1091
|
-
settings["local"] = {}
|
1092
|
-
public_key_path = File.expand_path("~/.ssh/id_rsa.pub")
|
1093
|
-
private_key_path = File.expand_path("~/.ssh/id_rsa")
|
1094
|
-
raise "Please create public keys at ~/.ssh/id_rsa.pub or use --private-key flag" unless File.exists?(public_key_path)
|
1095
|
-
|
1096
|
-
settings["local"]["public_key_path"] = public_key_path
|
1097
|
-
settings["local"]["private_key_path"] = private_key_path
|
1106
|
+
def inception_vm_private_key_path
|
1107
|
+
unless settings["inception"] && settings["inception"]["local_private_key_path"]
|
1108
|
+
settings["inception"] ||= {}
|
1109
|
+
settings["inception"]["local_private_key_path"] = File.join(settings_ssh_dir, "inception")
|
1098
1110
|
save_settings!
|
1099
1111
|
end
|
1100
|
-
[
|
1112
|
+
settings["inception"]["local_private_key_path"]
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
# The keys for the inception VM originate from the provider and are cached in
|
1116
|
+
# the manifest. The private key is stored locally; the public key is placed
|
1117
|
+
# on the inception VM.
|
1118
|
+
def recreate_local_ssh_keys_for_inception_vm
|
1119
|
+
unless settings["inception"] && (key_pair = settings["inception"]["key_pair"])
|
1120
|
+
raise "please run create_inception_key_pair first"
|
1121
|
+
end
|
1122
|
+
private_key_contents = key_pair["private_key"]
|
1123
|
+
unless File.exist?(inception_vm_private_key_path) && File.read(inception_vm_private_key_path) == private_key_contents
|
1124
|
+
say "Creating missing inception VM private key..."
|
1125
|
+
mkdir_p(File.dirname(inception_vm_private_key_path))
|
1126
|
+
File.chmod(0700, File.dirname(inception_vm_private_key_path))
|
1127
|
+
File.open(inception_vm_private_key_path, "w") { |file| file << private_key_contents }
|
1128
|
+
File.chmod(0600, inception_vm_private_key_path)
|
1129
|
+
end
|
1101
1130
|
end
|
1102
1131
|
|
1103
1132
|
def aws?
|
@@ -77,11 +77,13 @@ class Bosh::Bootstrap::Commander::RemoteServer
|
|
77
77
|
file << contents
|
78
78
|
file.flush
|
79
79
|
logfile.puts "uploading #{remote_path} to Inception VM"
|
80
|
-
Net::SCP.upload!(host, upload_as_user, file.path, remote_path, ssh: { keys:
|
80
|
+
Net::SCP.upload!(host, upload_as_user, file.path, remote_path, ssh: { keys: private_keys })
|
81
81
|
end
|
82
82
|
true
|
83
83
|
rescue StandardError => e
|
84
|
+
logfile.puts "ERROR running upload_file(#{command.class}, '#{remote_path}', ...)"
|
84
85
|
logfile.puts e.message
|
86
|
+
logfile.puts e.backtrace
|
85
87
|
false
|
86
88
|
end
|
87
89
|
|
@@ -102,7 +104,7 @@ class Bosh::Bootstrap::Commander::RemoteServer
|
|
102
104
|
"bash -lc 'sudo /usr/bin/env PATH=$PATH #{remote_path}'"
|
103
105
|
]
|
104
106
|
script_output = ""
|
105
|
-
results = Fog::SSH.new(host, username, keys:
|
107
|
+
results = Fog::SSH.new(host, username, keys: private_keys).run(commands) do |stdout, stderr|
|
106
108
|
[stdout, stderr].flatten.each do |data|
|
107
109
|
logfile << data
|
108
110
|
script_output << data
|
@@ -113,17 +115,17 @@ class Bosh::Bootstrap::Commander::RemoteServer
|
|
113
115
|
[script_output, result_success]
|
114
116
|
end
|
115
117
|
|
116
|
-
# Produce the :keys option for Net::SSH
|
117
|
-
def keys_array
|
118
|
-
# path to local private key being used
|
119
|
-
[private_key_path]
|
120
|
-
end
|
121
|
-
|
122
118
|
def run_remote_command(command, username)
|
123
|
-
Net::SSH.start(host, username, keys:
|
119
|
+
Net::SSH.start(host, username, keys: private_keys) do |ssh|
|
124
120
|
ssh.exec!("bash -lc '#{command}'") do |channel, stream, data|
|
125
121
|
logfile << data
|
126
122
|
end
|
127
123
|
end
|
128
124
|
end
|
125
|
+
|
126
|
+
# path to local private key being used
|
127
|
+
def private_keys
|
128
|
+
[private_key_path]
|
129
|
+
end
|
130
|
+
|
129
131
|
end
|
@@ -28,9 +28,71 @@ module Bosh::Bootstrap::Helpers::Settings
|
|
28
28
|
@settings = nil # force to reload & recreate helper methods
|
29
29
|
end
|
30
30
|
|
31
|
+
# the base directory for holding the manifest settings file
|
32
|
+
# and private keys
|
33
|
+
#
|
34
|
+
# Defaults to ~/.bosh_bootstrap; and can be overridden with either:
|
35
|
+
# * $SETTINGS - to a folder (supported method)
|
36
|
+
# * $MANIFEST - to a folder (unsupported)
|
37
|
+
# * $MANIFEST - to a specific file; but uses its parent dir (unsupported, backwards compatibility)
|
38
|
+
def settings_dir
|
39
|
+
@settings_dir ||= begin
|
40
|
+
settings_dir = ENV["SETTINGS"] if ENV["SETTINGS"]
|
41
|
+
settings_dir ||= ENV["MANIFEST"] if ENV["MANIFEST"]
|
42
|
+
settings_dir = File.dirname(settings_dir) if settings_dir && File.file?(settings_dir)
|
43
|
+
settings_dir ||= "~/.bosh_bootstrap"
|
44
|
+
File.expand_path(settings_dir)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
31
48
|
def settings_path
|
32
|
-
|
33
|
-
|
49
|
+
File.join(settings_dir, "manifest.yml")
|
50
|
+
end
|
51
|
+
|
52
|
+
def settings_ssh_dir
|
53
|
+
File.join(settings_dir, "ssh")
|
54
|
+
end
|
55
|
+
|
56
|
+
def backup_current_settings_file
|
57
|
+
backup_path = "#{settings_path}.bak"
|
58
|
+
FileUtils.cp_r(settings_path, backup_path)
|
59
|
+
end
|
60
|
+
|
61
|
+
def migrate_old_settings
|
62
|
+
if migrate_old_ssh_keys?
|
63
|
+
say "Upgrading settings manifest file:"
|
64
|
+
backup_current_settings_file
|
65
|
+
end
|
66
|
+
migrate_old_ssh_keys
|
67
|
+
end
|
68
|
+
|
69
|
+
# Do we need to migrate old ssh keys to new settings format?
|
70
|
+
def migrate_old_ssh_keys?
|
71
|
+
settings["local"] && settings["local"]["private_key_path"]
|
72
|
+
end
|
73
|
+
|
74
|
+
# Migrate this old data
|
75
|
+
# local:
|
76
|
+
# public_key_path: /Users/drnic/.ssh/id_rsa.pub
|
77
|
+
# private_key_path: /Users/drnic/.ssh/id_rsa
|
78
|
+
# into new format:
|
79
|
+
# inception:
|
80
|
+
# local_private_key_path: ~/.bosh_bootstrap/ssh/inception (copy of settings.local.private_key_path)
|
81
|
+
# key_pair:
|
82
|
+
# name: <name of provider key_pair used when provisioning inception VM>
|
83
|
+
# private_key: <contents of settings.local.private_key_path file>
|
84
|
+
# public_key: <contents of settings.local.public_key_path file>
|
85
|
+
def migrate_old_ssh_keys
|
86
|
+
if migrate_old_ssh_keys?
|
87
|
+
say "-> migrating to cache private key for inception VM..."
|
88
|
+
inception_vm_private_key_path # to setup the path in settings
|
89
|
+
settings["inception"]["key_pair"] ||= {}
|
90
|
+
settings["inception"]["key_pair"]["name"] = "fog_default"
|
91
|
+
settings["inception"]["key_pair"]["private_key"] = File.read(settings["local"]["private_key_path"]).strip
|
92
|
+
settings["inception"]["key_pair"]["public_key"] = File.read(settings["local"]["public_key_path"]).strip
|
93
|
+
settings.delete("local")
|
94
|
+
save_settings!
|
95
|
+
end
|
34
96
|
end
|
35
97
|
|
36
98
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -29,15 +29,9 @@ end
|
|
29
29
|
|
30
30
|
def setup_home_dir
|
31
31
|
home_dir = File.expand_path("../../tmp/home", __FILE__)
|
32
|
+
FileUtils.rm_rf(home_dir)
|
32
33
|
FileUtils.mkdir_p(home_dir)
|
33
34
|
ENV['HOME'] = home_dir
|
34
|
-
|
35
|
-
private_key = File.join(home_dir, ".ssh", "id_rsa")
|
36
|
-
unless File.exists?(private_key)
|
37
|
-
puts "Creating private keypair for inception VM specs..."
|
38
|
-
mkdir_p(File.dirname(private_key))
|
39
|
-
sh "ssh-keygen -f #{home_dir}/.ssh/id_rsa -N ''"
|
40
|
-
end
|
41
35
|
end
|
42
36
|
|
43
37
|
RSpec.configure do |c|
|
data/spec/unit/aws_spec.rb
CHANGED
@@ -9,8 +9,6 @@ describe "AWS deployment" do
|
|
9
9
|
before do
|
10
10
|
Fog.mock!
|
11
11
|
Fog::Mock.reset
|
12
|
-
ENV['MANIFEST'] = File.expand_path("../../../tmp/test-manifest.yml", __FILE__)
|
13
|
-
rm_rf(ENV['MANIFEST'])
|
14
12
|
@cmd = Bosh::Bootstrap::Cli.new
|
15
13
|
@fog_credentials = {
|
16
14
|
:provider => 'AWS',
|
@@ -18,8 +16,9 @@ describe "AWS deployment" do
|
|
18
16
|
:aws_access_key_id => 'YYY'
|
19
17
|
}
|
20
18
|
|
19
|
+
@region = "us-west-2"
|
21
20
|
setting "bosh_provider", "aws"
|
22
|
-
setting "region_code",
|
21
|
+
setting "region_code", @region
|
23
22
|
setting "bosh_name", "test-bosh"
|
24
23
|
setting "inception.create_new", true
|
25
24
|
setting "bosh_username", "testuser"
|
@@ -38,7 +37,7 @@ describe "AWS deployment" do
|
|
38
37
|
end
|
39
38
|
|
40
39
|
def fog
|
41
|
-
@fog ||= connection = Fog::Compute.new(@fog_credentials.merge(:region =>
|
40
|
+
@fog ||= connection = Fog::Compute.new(@fog_credentials.merge(:region => @region))
|
42
41
|
end
|
43
42
|
|
44
43
|
def expected_manifest_content(filename, public_ip, subnet_id = nil)
|
@@ -48,7 +47,7 @@ describe "AWS deployment" do
|
|
48
47
|
YAML.load(file)
|
49
48
|
end
|
50
49
|
|
51
|
-
|
50
|
+
xit "creates a VPC inception/microbosh with the associated resources" do
|
52
51
|
# create a VPC
|
53
52
|
# create a BOSH subnet 10.10.0.0/24
|
54
53
|
# create BOSH security group
|
@@ -121,11 +120,28 @@ describe "AWS deployment" do
|
|
121
120
|
@cmd.stub(:sleep)
|
122
121
|
@cmd.should_receive(:deploy_stage_6_setup_new_bosh)
|
123
122
|
@cmd.deploy
|
123
|
+
@settings = nil # reload settings file
|
124
124
|
|
125
125
|
fog.addresses.should have(2).item
|
126
126
|
inception_ip_address = fog.addresses.first
|
127
127
|
inception_ip_address.domain.should == "standard"
|
128
128
|
|
129
|
+
inception_kp = fog.key_pairs.find { |kp| kp.name == "inception" }
|
130
|
+
inception_kp.should_not be_nil
|
131
|
+
|
132
|
+
inception_kp = fog.key_pairs.find { |kp| kp.name == "fog_default" }
|
133
|
+
inception_kp.should be_nil
|
134
|
+
|
135
|
+
fog.key_pairs.should have(2).item
|
136
|
+
|
137
|
+
settings["inception"].should_not be_nil
|
138
|
+
p settings["inception"]
|
139
|
+
settings["inception"]["key_pair"].should_not be_nil
|
140
|
+
settings["inception"]["key_pair"]["name"].should_not be_nil
|
141
|
+
settings["inception"]["key_pair"]["private_key"].should_not be_nil
|
142
|
+
settings["inception"]["local_private_key_path"].should == File.join(ENV['HOME'], ".bosh_bootstrap", "ssh", "inception")
|
143
|
+
File.should_not be_world_readable(settings["inception"]["local_private_key_path"])
|
144
|
+
|
129
145
|
fog.vpcs.should have(0).item
|
130
146
|
fog.servers.should have(1).item
|
131
147
|
fog.security_groups.should have(2).item
|
data/spec/unit/cli_spec.rb
CHANGED
@@ -7,8 +7,6 @@ describe Bosh::Bootstrap do
|
|
7
7
|
include Bosh::Bootstrap::Helpers::SettingsSetter
|
8
8
|
|
9
9
|
before do
|
10
|
-
ENV['MANIFEST'] = File.expand_path("../../../tmp/test-manifest.yml", __FILE__)
|
11
|
-
rm_rf(ENV['MANIFEST'])
|
12
10
|
@cmd = Bosh::Bootstrap::Cli.new
|
13
11
|
setting "git.name", "Dr Nic Williams"
|
14
12
|
setting "git.email", "drnicwilliams@gmail.com"
|
@@ -48,16 +46,20 @@ describe Bosh::Bootstrap do
|
|
48
46
|
@cmd.deploy
|
49
47
|
end
|
50
48
|
|
51
|
-
it "stage 3 - create inception VM"
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
49
|
+
it "stage 3 - create inception VM" do
|
50
|
+
testing_stage(3)
|
51
|
+
setting "inception.username", "ubuntu"
|
52
|
+
setting "inception.key_pair.private_key", "INCEPTION_PRIVATE_KEY"
|
53
|
+
setting "inception.key_pair.public_key", "INCEPTION_PUBLIC_KEY"
|
54
|
+
setting "inception.key_pair.name", "inception"
|
55
|
+
setting "fog_credentials.provider", "AWS"
|
56
|
+
@cmd.should_receive(:run_server).and_return(true)
|
57
|
+
@cmd.deploy
|
58
|
+
end
|
58
59
|
|
59
60
|
it "stage 4 - prepare inception VM" do
|
60
61
|
testing_stage(4)
|
62
|
+
@cmd.should_receive(:recreate_local_ssh_keys_for_inception_vm)
|
61
63
|
setting "inception.username", "ubuntu"
|
62
64
|
setting "bosh.password", "UNSALTED"
|
63
65
|
@cmd.should_receive(:run_server).and_return(true)
|
@@ -66,6 +68,7 @@ describe Bosh::Bootstrap do
|
|
66
68
|
|
67
69
|
it "stage 5 - download stemcell and deploy microbosh" do
|
68
70
|
testing_stage(5)
|
71
|
+
@cmd.should_receive(:recreate_local_ssh_keys_for_inception_vm)
|
69
72
|
setting "bosh_provider", "aws"
|
70
73
|
setting "micro_bosh_stemcell_name", "micro-bosh-stemcell-aws-0.8.1.tgz"
|
71
74
|
setting "bosh_username", "drnic"
|
data/spec/unit/cli_ssh_spec.rb
CHANGED
@@ -8,18 +8,23 @@ require File.expand_path("../../spec_helper", __FILE__)
|
|
8
8
|
# * mosh
|
9
9
|
describe Bosh::Bootstrap do
|
10
10
|
include FileUtils
|
11
|
+
include Bosh::Bootstrap::Helpers::SettingsSetter
|
11
12
|
|
12
13
|
before do
|
13
|
-
ENV['MANIFEST'] = File.expand_path("../../../tmp/test-manifest.yml", __FILE__)
|
14
|
-
rm_rf(ENV['MANIFEST'])
|
15
14
|
@cmd = Bosh::Bootstrap::Cli.new
|
16
15
|
end
|
17
16
|
|
17
|
+
# used by +SettingsSetter+ to access the settings
|
18
|
+
def settings
|
19
|
+
@cmd.settings
|
20
|
+
end
|
21
|
+
|
18
22
|
describe "ssh" do
|
19
23
|
before do
|
20
|
-
|
21
|
-
|
22
|
-
|
24
|
+
setting "inception.host", "5.5.5.5"
|
25
|
+
setting "inception.key_pair.private_key", "PRIVATE"
|
26
|
+
setting "inception.key_pair.public_key", "PUBLIC"
|
27
|
+
@private_key_path = File.join(ENV['HOME'], ".bosh_bootstrap", "ssh", "inception")
|
23
28
|
end
|
24
29
|
|
25
30
|
describe "normal" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bosh-bootstrap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
@@ -96,17 +96,17 @@ dependencies:
|
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
97
97
|
none: false
|
98
98
|
requirements:
|
99
|
-
- -
|
99
|
+
- - ~>
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version:
|
101
|
+
version: 1.0.4
|
102
102
|
type: :runtime
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
|
-
- -
|
107
|
+
- - ~>
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
109
|
+
version: 1.0.4
|
110
110
|
- !ruby/object:Gem::Dependency
|
111
111
|
name: fog
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -313,7 +313,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
313
313
|
version: '0'
|
314
314
|
segments:
|
315
315
|
- 0
|
316
|
-
hash:
|
316
|
+
hash: -2834867507731150222
|
317
317
|
requirements: []
|
318
318
|
rubyforge_project:
|
319
319
|
rubygems_version: 1.8.25
|