bosh-bootstrap 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build Status](https://travis-ci.org/StarkAndWayne/bosh-bootstrap.png?branch=master)](https://travis-ci.org/StarkAndWayne/bosh-bootstrap)
|
26
|
-
|
27
|
-
[![Code Climate](https://codeclimate.com/github/StarkAndWayne/bosh-bootstrap.png)](https://codeclimate.com/github/StarkAndWayne/bosh-bootstrap)
|
25
|
+
[![Gem Version](https://badge.fury.io/rb/bosh-bootstrap.png)](http://badge.fury.io/rb/bosh-bootstrap) [![Build Status](https://travis-ci.org/StarkAndWayne/bosh-bootstrap.png?branch=master)](https://travis-ci.org/StarkAndWayne/bosh-bootstrap) [![Code Climate](https://codeclimate.com/github/StarkAndWayne/bosh-bootstrap.png)](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
|