bosh-bootstrap 0.6.0 → 0.7.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/spec/spec_helper.rb CHANGED
@@ -9,9 +9,14 @@ Bundler.setup(:default, :test)
9
9
  $:.unshift(File.expand_path("../../lib", __FILE__))
10
10
 
11
11
  require "rspec/core"
12
+ require "bosh/providers"
12
13
  require "bosh-bootstrap"
13
14
  require "bosh-bootstrap/cli"
14
15
 
16
+ # for the #sh helper
17
+ require "rake"
18
+ require "rake/file_utils"
19
+
15
20
  def spec_asset(filename)
16
21
  File.expand_path("../assets/#{filename}", __FILE__)
17
22
  end
@@ -22,9 +27,22 @@ def files_match(filename, expected_filename)
22
27
  file.should == expected_file
23
28
  end
24
29
 
30
+ def setup_home_dir
31
+ home_dir = File.expand_path("../../tmp/home", __FILE__)
32
+ FileUtils.mkdir_p(home_dir)
33
+ 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
+ end
42
+
25
43
  RSpec.configure do |c|
26
44
  c.before(:each) do
27
-
45
+ setup_home_dir
28
46
  end
29
47
 
30
48
  c.color_enabled = true
@@ -0,0 +1,137 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ require "active_support/core_ext/hash/keys"
4
+
5
+ describe "AWS deployment" do
6
+ include FileUtils
7
+ include Bosh::Bootstrap::Helpers::SettingsSetter
8
+
9
+ before do
10
+ Fog.mock!
11
+ Fog::Mock.reset
12
+ ENV['MANIFEST'] = File.expand_path("../../../tmp/test-manifest.yml", __FILE__)
13
+ rm_rf(ENV['MANIFEST'])
14
+ @cmd = Bosh::Bootstrap::Cli.new
15
+ @fog_credentials = {
16
+ :provider => 'AWS',
17
+ :aws_secret_access_key => 'XXX',
18
+ :aws_access_key_id => 'YYY'
19
+ }
20
+
21
+ setting "bosh_provider", "aws"
22
+ setting "region_code", "us-west-2"
23
+ setting "bosh_name", "test-bosh"
24
+ setting "inception.create_new", true
25
+ setting "bosh_username", "testuser"
26
+ setting "bosh_password", "testpass"
27
+ setting "bosh.password", "testpass"
28
+ setting "fog_credentials", @fog_credentials.stringify_keys
29
+ setting "bosh.salted_password", "pepper"
30
+ setting "bosh.persistent_disk", 16384
31
+ end
32
+
33
+ # used by +SettingsSetter+ to access the settings
34
+ def settings
35
+ @cmd.settings
36
+ end
37
+
38
+ def fog
39
+ @fog ||= connection = Fog::Compute.new(@fog_credentials.merge(:region => "us-west-2"))
40
+ end
41
+
42
+ def expected_manifest_content(filename, public_ip, subnet_id = nil)
43
+ file = File.read(filename)
44
+ file.gsub!('$MICROBOSH_IP$', public_ip)
45
+ file.gsub!('$SUBNET_ID$', subnet_id) if subnet_id
46
+ YAML.load(file)
47
+ end
48
+
49
+ it "creates a VPC inception/microbosh with the associated resources" do
50
+ # create a VPC
51
+ # create a BOSH subnet 10.10.0.0/24
52
+ # create BOSH security group
53
+ # create INCEPTION security group allowing only 22
54
+ # create NATS security group, allowing only 4222
55
+ # create DHCP options with 2 nameserver (1 amazon for public resolves, 1 for private resolves (.bosh)?)
56
+ # create Internet Gateway, attach to VPC
57
+ # create default route (0.0.0.0/0) to IG
58
+
59
+ # create inception VM (attaching elastic IP, sg of [BOSH, INCEPTION]) in BOSH subnet at 10.10.0.5
60
+ # create MB VM from inception VM (sg of [BOSH, NATS]) in BOSH subnet at 10.10.0.6
61
+
62
+ setting "use_vpc", true # TODO include in cli.rb
63
+
64
+ @cmd.should_receive(:provision_and_mount_volume)
65
+ @cmd.stub(:run_server).and_return(true)
66
+ @cmd.stub(:sleep)
67
+ @cmd.should_receive(:deploy_stage_6_setup_new_bosh)
68
+ @cmd.deploy
69
+
70
+ fog.addresses.should have(1).item # assigned to inception VM
71
+ inception_ip_address = fog.addresses.first
72
+
73
+ fog.vpcs.should have(1).item
74
+ vpc = fog.vpcs.first
75
+ vpc.cidr_block.should == "10.0.0.0/16"
76
+
77
+ fog.servers.should have(1).item
78
+ inception = fog.servers.first
79
+ inception_ip_address.domain.should == "vpc"
80
+
81
+ # TODO - fix fog so we can test public_ip_address
82
+ # inception.public_ip_address.should == inception_ip_address.public_ip
83
+
84
+ # TODO - fix fog so we can test private_ip_address
85
+ # inception.private_ip_address.should == "10.0.0.5"
86
+
87
+ fog.security_groups.should have(2).item
88
+
89
+ fog.internet_gateways.should have(1).item
90
+ ig = fog.internet_gateways.first
91
+
92
+ fog.subnets.should have(1).item
93
+ subnet = fog.subnets.first
94
+ subnet.vpc_id.should == vpc.id
95
+ subnet.cidr_block.should == "10.0.0.0/24"
96
+
97
+ # fog.route_tables.should have(1).item
98
+ # a IG that is assigned to the VPN
99
+ # a subnet (contains the inception VM; is included in micro_bosh_yml)
100
+
101
+ # TODO - fix fog so we can test private_ip_address
102
+ # settings["inception"]["ip_address"].should == "10.0.0.5"
103
+
104
+ inception_server = fog.servers.first
105
+ inception_server.dns_name.should == settings["inception"]["host"]
106
+
107
+ public_ip = settings["bosh"]["ip_address"]
108
+ public_ip.should == "10.0.0.6"
109
+
110
+ manifest_path = spec_asset("micro_bosh_yml/micro_bosh.aws_ec2.yml")
111
+ YAML.load(@cmd.micro_bosh_yml).should == expected_manifest_content(manifest_path, public_ip, subnet.subnet_id)
112
+ end
113
+
114
+ it "creates an EC2 inception/microbosh with the associated resources" do
115
+ setting "use_vpc", false
116
+
117
+ @cmd.should_receive(:provision_and_mount_volume)
118
+ @cmd.stub(:run_server).and_return(true)
119
+ @cmd.stub(:sleep)
120
+ @cmd.should_receive(:deploy_stage_6_setup_new_bosh)
121
+ @cmd.deploy
122
+
123
+ fog.addresses.should have(2).item
124
+ inception_ip_address = fog.addresses.first
125
+ inception_ip_address.domain.should == "standard"
126
+
127
+ fog.vpcs.should have(0).item
128
+ fog.servers.should have(1).item
129
+ fog.security_groups.should have(2).item
130
+
131
+ inception_server = fog.servers.first
132
+ inception_server.dns_name.should == settings["inception"]["host"]
133
+ public_ip = settings["bosh"]["ip_address"]
134
+ manifest_path = spec_asset("micro_bosh_yml/micro_bosh.aws_ec2.yml")
135
+ YAML.load(@cmd.micro_bosh_yml).should == expected_manifest_content(manifest_path, public_ip)
136
+ end
137
+ end
@@ -0,0 +1,160 @@
1
+ # Copyright (c) 2012-2013 Stark & Wayne, LLC
2
+
3
+ require File.expand_path("../../../../spec_helper", __FILE__)
4
+
5
+ # Specs for the aws provider
6
+ describe Bosh::Providers do
7
+ include FileUtils
8
+
9
+ describe "AWS" do
10
+ before do
11
+ Fog.mock!
12
+ @fog_compute = Fog::Compute.new(
13
+ :provider => 'AWS',
14
+ :aws_access_key_id => 'MOCK_AWS_ACCESS_KEY_ID',
15
+ :aws_secret_access_key => 'MOCK_AWS_SECRET_ACCESS_KEY')
16
+ @aws_provider = Bosh::Providers.for_bosh_provider_name("aws", @fog_compute)
17
+ end
18
+
19
+ describe "create security group" do
20
+ it "should open a single TCP port on a security group" do
21
+ ports = { ssh: 22 }
22
+ @aws_provider.create_security_group("sg1-name", "sg1-desc", ports)
23
+ created_sg = @fog_compute.security_groups.get("sg1-name")
24
+ created_sg.name.should == "sg1-name"
25
+ created_sg.description.should == "sg1-desc"
26
+ created_sg.ip_permissions.should == [
27
+ {
28
+ "ipProtocol"=>"tcp",
29
+ "fromPort"=>22,
30
+ "toPort"=>22,
31
+ "groups"=>[],
32
+ "ipRanges"=>[ { "cidrIp"=>"0.0.0.0/0" } ]
33
+ }
34
+ ]
35
+ end
36
+ it "should open a range of TCP ports" do
37
+ ports = { ssh: (22..30) }
38
+ @aws_provider.create_security_group("sg-range-name", "sg-range-desc", ports)
39
+ created_sg = @fog_compute.security_groups.get("sg-range-name")
40
+ created_sg.ip_permissions.should == [
41
+ {
42
+ "ipProtocol"=>"tcp",
43
+ "fromPort"=>22,
44
+ "toPort"=>30,
45
+ "groups"=>[],
46
+ "ipRanges"=>[ { "cidrIp"=>"0.0.0.0/0" } ]
47
+ }
48
+ ]
49
+ end
50
+ it "should open a range of UDP ports" do
51
+ ports = { ssh: { protocol: "udp", ports: (60000..600050) } }
52
+ @aws_provider.create_security_group("sg-range-udp-name", "sg-range-udp-name", ports)
53
+ created_sg = @fog_compute.security_groups.get("sg-range-udp-name")
54
+ created_sg.ip_permissions.should == [
55
+ {
56
+ "ipProtocol"=>"udp",
57
+ "fromPort"=>60000,
58
+ "toPort"=>600050,
59
+ "groups"=>[],
60
+ "ipRanges"=>[ { "cidrIp"=>"0.0.0.0/0" } ]
61
+ }
62
+ ]
63
+ end
64
+ it "should open not open ports if they are already open" do
65
+ @aws_provider.create_security_group("sg2", "", { ssh: { protocol: "udp", ports: (60000..600050) } })
66
+ @aws_provider.create_security_group("sg2", "", { ssh: { protocol: "udp", ports: (60010..600040) } })
67
+ @aws_provider.create_security_group("sg2", "", { ssh: { protocol: "udp", ports: (60000..600050) } })
68
+ created_sg = @fog_compute.security_groups.get("sg2")
69
+ created_sg.ip_permissions.should == [
70
+ {
71
+ "ipProtocol"=>"udp",
72
+ "fromPort"=>60000,
73
+ "toPort"=>600050,
74
+ "groups"=>[],
75
+ "ipRanges"=>[ { "cidrIp"=>"0.0.0.0/0" } ]
76
+ }
77
+ ]
78
+ end
79
+ it "should open ports even if they are already open for a different protocol" do
80
+ @aws_provider.create_security_group("sg3", "", { ssh: { protocol: "udp", ports: (60000..600050) } })
81
+ @aws_provider.create_security_group("sg3", "", { ssh: { protocol: "tcp", ports: (60000..600050) } })
82
+ created_sg = @fog_compute.security_groups.get("sg3")
83
+ created_sg.ip_permissions.should == [
84
+ {
85
+ "ipProtocol"=>"udp",
86
+ "fromPort"=>60000,
87
+ "toPort"=>600050,
88
+ "groups"=>[],
89
+ "ipRanges"=>[ { "cidrIp"=>"0.0.0.0/0" } ]
90
+ },
91
+ {
92
+ "ipProtocol"=>"tcp",
93
+ "fromPort"=>60000,
94
+ "toPort"=>600050,
95
+ "groups"=>[],
96
+ "ipRanges"=>[ { "cidrIp"=>"0.0.0.0/0" } ]
97
+ }
98
+ ]
99
+ end
100
+ it "should open ports even if they are already open for a different ip_range" do
101
+ default_ports = {
102
+ all_internal_tcp: { protocol: "tcp", ip_range: "1.1.1.1/32", ports: (0..65535) }
103
+ }
104
+ @aws_provider.create_security_group("sg6", "sg6", default_ports)
105
+ @aws_provider.create_security_group("sg6", "sg6", { mosh: { protocol: "tcp", ports: (15..30) } })
106
+ created_sg = @fog_compute.security_groups.get("sg6")
107
+ created_sg.ip_permissions.should == [
108
+ {
109
+ "ipProtocol"=>"tcp",
110
+ "fromPort"=>0,
111
+ "toPort"=>65535,
112
+ "groups"=>[],
113
+ "ipRanges"=>[ { "cidrIp"=>"1.1.1.1/32" } ]
114
+ },
115
+ {
116
+ "ipProtocol"=>"tcp",
117
+ "fromPort"=>15,
118
+ "toPort"=>30,
119
+ "groups"=>[],
120
+ "ipRanges"=>[ { "cidrIp"=>"0.0.0.0/0" } ]
121
+ }
122
+ ]
123
+ end
124
+ it "should open ports on the default sg" do
125
+ @aws_provider.create_security_group("default", "default", { mosh: { protocol: "tcp", ports: (15..30) } })
126
+ created_sg = @fog_compute.security_groups.get("default")
127
+ expected_rule = {
128
+ "ipProtocol"=>"tcp",
129
+ "fromPort"=>15,
130
+ "toPort"=>30,
131
+ "groups"=>[],
132
+ "ipRanges"=>[ { "cidrIp"=>"0.0.0.0/0" } ]
133
+ }
134
+ created_sg.ip_permissions.should include expected_rule
135
+ end
136
+ #AWS allows overlapping port ranges, and it makes it easier to see the separate "rules" that were added
137
+ it "should create overlapping port ranges" do
138
+ @aws_provider.create_security_group("sg4", "", { ssh: { protocol: "udp", ports: (10..20) } })
139
+ @aws_provider.create_security_group("sg4", "", { ssh: { protocol: "udp", ports: (15..30) } })
140
+ created_sg = @fog_compute.security_groups.get("sg4")
141
+ created_sg.ip_permissions.should == [
142
+ {
143
+ "ipProtocol"=>"udp",
144
+ "fromPort"=>10,
145
+ "toPort"=>20,
146
+ "groups"=>[],
147
+ "ipRanges"=>[ { "cidrIp"=>"0.0.0.0/0" } ]
148
+ },
149
+ {
150
+ "ipProtocol"=>"udp",
151
+ "fromPort"=>15,
152
+ "toPort"=>30,
153
+ "groups"=>[],
154
+ "ipRanges"=>[ { "cidrIp"=>"0.0.0.0/0" } ]
155
+ }
156
+ ]
157
+ end
158
+ end
159
+ end
160
+ end
@@ -56,6 +56,8 @@ describe Bosh::Bootstrap do
56
56
 
57
57
  it "stage 4 - prepare inception VM" do
58
58
  testing_stage(4)
59
+ setting "git.name", "Dr Nic Williams"
60
+ setting "git.email", "drnicwilliams@gmail.com"
59
61
  setting "inception.username", "ubuntu"
60
62
  setting "bosh.password", "UNSALTED"
61
63
  @cmd.should_receive(:run_server).and_return(true)
@@ -107,9 +109,7 @@ describe Bosh::Bootstrap do
107
109
  # get the Name field, reverse sort, and return the first item
108
110
  it "should return the latest stable stemcell by default for AWS" do
109
111
  @cmd.settings["bosh_provider"] = "aws"
110
- @cmd.should_receive(:`).
111
- with("bosh public stemcells --tags micro,aws").
112
- and_return(File.read(spec_asset("bosh/public_stemcells/aws_micro.out")))
112
+ @cmd.should_receive(:known_stable_micro_bosh_stemcell_version).and_return("0.8.1")
113
113
  @cmd.micro_bosh_stemcell_name.should == "micro-bosh-stemcell-aws-0.8.1.tgz"
114
114
  end
115
115
  end
@@ -5,6 +5,7 @@ require File.expand_path("../../spec_helper", __FILE__)
5
5
  # Specs for 'ssh' related behavior. Includes CLI commands:
6
6
  # * ssh
7
7
  # * tmux
8
+ # * mosh
8
9
  describe Bosh::Bootstrap do
9
10
  include FileUtils
10
11
 
@@ -43,5 +44,46 @@ describe Bosh::Bootstrap do
43
44
  @cmd.tmux
44
45
  end
45
46
  end
47
+
48
+ describe "mosh" do
49
+ before do
50
+ @cmd.settings['bosh_provider'] = 'aws'
51
+ Fog.mock!
52
+ fog_compute = Fog::Compute.new(
53
+ :provider => 'AWS',
54
+ :aws_access_key_id => 'MOCK_AWS_ACCESS_KEY_ID',
55
+ :aws_secret_access_key => 'MOCK_AWS_SECRET_ACCESS_KEY')
56
+ @cmd.stub!(:provider).and_return(Bosh::Providers.for_bosh_provider_name('aws', fog_compute))
57
+ @cmd.stub!(:fog_compute).and_return(fog_compute)
58
+ @cmd.fog_compute.stub!(:servers).and_return(double(:get => double(:groups => ['default'])))
59
+ end
60
+ after do
61
+ Fog.unmock!
62
+ end
63
+ it "should check whether mosh is installed" do
64
+ @cmd.should_receive(:system).
65
+ with("mosh --version")
66
+ @cmd.stub!(:exit)
67
+ @cmd.ensure_mosh_installed
68
+ end
69
+ it "launches mosh session" do
70
+ @cmd.stub!(:ensure_mosh_installed).and_return(true)
71
+ @cmd.should_receive(:exit)
72
+ @cmd.should_receive(:system).
73
+ with("mosh vcap@5.5.5.5")
74
+ @cmd.mosh
75
+ end
76
+ it "should ensure that the mosh ports are opened" do
77
+ expected_ports = {
78
+ mosh: {
79
+ protocol: "udp",
80
+ ports: (60000..60050)
81
+ }
82
+ }
83
+ @cmd.provider.stub!(:create_security_group)
84
+ .with('default','not used', expected_ports)
85
+ @cmd.ensure_security_group_allows_mosh
86
+ end
87
+ end
46
88
  end
47
89
  end
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2012-2013 Stark & Wayne, LLC
2
+
3
+ require File.expand_path("../../spec_helper", __FILE__)
4
+
5
+ # Specs for 'upgrade' command
6
+ describe Bosh::Bootstrap do
7
+ include FileUtils
8
+ include Bosh::Bootstrap::Helpers::SettingsSetter
9
+
10
+ # used by +SettingsSetter+ to access the settings
11
+ def settings
12
+ @cmd.settings
13
+ end
14
+
15
+ before do
16
+ ENV['MANIFEST'] = File.expand_path("../../../tmp/test-manifest.yml", __FILE__)
17
+ rm_rf(ENV['MANIFEST'])
18
+ @cmd = Bosh::Bootstrap::Cli.new
19
+ end
20
+
21
+ it "runs 'upgrade' command on an existing inception VM" do
22
+ setting "inception.prepared", true
23
+ setting "inception.username", "ubuntu"
24
+ setting "git.name", "Dr Nic Williams"
25
+ setting "git.email", "drnicwilliams@gmail.com"
26
+ setting "bosh.password", "UNSALTED"
27
+ setting "bosh.salted_password", "SALTED"
28
+ @cmd.should_receive(:run_server).and_return(true)
29
+ @cmd.upgrade_inception
30
+ end
31
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2012-2013 Stark & Wayne, LLC
2
+
3
+ require File.expand_path("../../spec_helper", __FILE__)
4
+
5
+ describe Bosh::Bootstrap::Helpers::SettingsSetter do
6
+ include Bosh::Bootstrap::Helpers::SettingsSetter
7
+
8
+ attr_reader :settings
9
+ before do
10
+ @settings = {}
11
+ end
12
+
13
+ def save_settings!
14
+ end
15
+
16
+ it "with_setting 'a'" do
17
+ with_setting "a" do |setting|
18
+ setting['value'] = "abc"
19
+ end
20
+ settings["a"]["value"].should == "abc"
21
+ end
22
+
23
+ it "with_setting 'a.b.c'" do
24
+ with_setting "a.b.c" do |setting|
25
+ setting['value'] = "abc"
26
+ end
27
+ settings["a"]["b"]["c"]["value"].should == "abc"
28
+ end
29
+ end