inception-server 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/.chef/knife.rb +4 -0
  2. data/.gitignore +21 -0
  3. data/.kitchen.yml +47 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +18 -0
  6. data/Berksfile +8 -0
  7. data/Berksfile.lock +9 -0
  8. data/ChangeLog.md +20 -0
  9. data/Gemfile +27 -0
  10. data/Guardfile +6 -0
  11. data/LICENSE.txt +22 -0
  12. data/README.md +126 -0
  13. data/Rakefile +66 -0
  14. data/TODO.md +25 -0
  15. data/bin/inception +8 -0
  16. data/bin/inception-server +8 -0
  17. data/config/ssh/kitchen-aws +23 -0
  18. data/cookbooks/bosh_inception/README.md +15 -0
  19. data/cookbooks/bosh_inception/attributes/default.rb +25 -0
  20. data/cookbooks/bosh_inception/files/default/Gemfile.cf +5 -0
  21. data/cookbooks/bosh_inception/files/default/Gemfile.micro +5 -0
  22. data/cookbooks/bosh_inception/metadata.rb +32 -0
  23. data/cookbooks/bosh_inception/recipes/default.rb +16 -0
  24. data/cookbooks/bosh_inception/recipes/install_bosh.rb +37 -0
  25. data/cookbooks/bosh_inception/recipes/install_ruby.rb +10 -0
  26. data/cookbooks/bosh_inception/recipes/mount_store_volume.rb +24 -0
  27. data/cookbooks/bosh_inception/recipes/packages.rb +23 -0
  28. data/cookbooks/bosh_inception/recipes/setup_dotfog.rb +29 -0
  29. data/cookbooks/bosh_inception/recipes/setup_git.rb +34 -0
  30. data/cookbooks/bosh_inception/recipes/useful_dirs.rb +13 -0
  31. data/inception-server.gemspec +43 -0
  32. data/lib/inception/cli.rb +141 -0
  33. data/lib/inception/cli_helpers/display.rb +26 -0
  34. data/lib/inception/cli_helpers/interactions.rb +15 -0
  35. data/lib/inception/cli_helpers/prepare_deploy_settings.rb +89 -0
  36. data/lib/inception/cli_helpers/provider.rb +14 -0
  37. data/lib/inception/cli_helpers/settings.rb +53 -0
  38. data/lib/inception/inception_server.rb +304 -0
  39. data/lib/inception/inception_server_cookbook.rb +90 -0
  40. data/lib/inception/next_deploy_actions.rb +20 -0
  41. data/lib/inception/providers/README.md +5 -0
  42. data/lib/inception/providers/clients/aws_provider_client.rb +144 -0
  43. data/lib/inception/providers/clients/fog_provider_client.rb +185 -0
  44. data/lib/inception/providers/clients/openstack_provider_client.rb +84 -0
  45. data/lib/inception/providers/constants/aws_constants.rb +25 -0
  46. data/lib/inception/providers/constants/openstack_constants.rb +12 -0
  47. data/lib/inception/providers.rb +28 -0
  48. data/lib/inception/version.rb +3 -0
  49. data/lib/inception.rb +9 -0
  50. data/nodes/.gitkeep +0 -0
  51. data/spec/assets/.gitkeep +0 -0
  52. data/spec/assets/gitconfig +5 -0
  53. data/spec/assets/settings/aws-before-server.yml +14 -0
  54. data/spec/assets/settings/aws-created-server.yml +31 -0
  55. data/spec/integration/.gitkeep +0 -0
  56. data/spec/integration/aws/aws_basic_spec.rb +38 -0
  57. data/spec/spec_helper.rb +50 -0
  58. data/spec/support/aws/aws_helpers.rb +73 -0
  59. data/spec/support/settings_helper.rb +20 -0
  60. data/spec/support/stdout_capture.rb +17 -0
  61. data/spec/unit/.gitkeep +0 -0
  62. data/spec/unit/cli_delete_spec.rb +39 -0
  63. data/spec/unit/cli_deploy_aws_spec.rb +83 -0
  64. data/spec/unit/cli_ssh_spec.rb +80 -0
  65. data/spec/unit/inception_server_cookbook_spec.rb +62 -0
  66. data/spec/unit/inception_server_spec.rb +58 -0
  67. data/spec/unit/providers/aws_spec.rb +198 -0
  68. data/test/integration/default/bats/discover_user.bash +2 -0
  69. data/test/integration/default/bats/dotfog.bats +11 -0
  70. data/test/integration/default/bats/install_ruby.bats +8 -0
  71. data/test/integration/default/bats/useful_dirs.bats +8 -0
  72. data/test/integration/default/bats/user.bats +9 -0
  73. data/test/integration/default/bats/verify_bosh.bats +18 -0
  74. data/test/integration/default/bats/verify_git.bats +18 -0
  75. metadata +361 -0
@@ -0,0 +1,185 @@
1
+ # Copyright (c) 2012-2013 Stark & Wayne, LLC
2
+
3
+ require "fog"
4
+ module Inception; module Providers; module Clients; end; end; end
5
+
6
+ class Inception::Providers::Clients::FogProviderClient
7
+ attr_reader :fog_compute
8
+ attr_reader :attributes
9
+
10
+ def initialize(attributes)
11
+ @attributes = attributes.is_a?(Hash) ? ReadWriteSettings.new(attributes) : attributes
12
+ raise "@attributes must be ReadWriteSettings (or Hash)" unless @attributes.is_a?(ReadWriteSettings)
13
+ setup_fog_connection
14
+ end
15
+
16
+ def flavor_id(flavor_name)
17
+ if flavor = fog_compute.flavors.find { |fl| fl.name == flavor_name }
18
+ flavor.id
19
+ end
20
+ end
21
+
22
+ def setup_fog_connection
23
+ raise "must implement"
24
+ end
25
+
26
+ def create_key_pair(key_pair_name)
27
+ fog_compute.key_pairs.create(:name => key_pair_name)
28
+ end
29
+
30
+ # set_resource_name(fog_server, "inception")
31
+ # set_resource_name(volume, "inception-root")
32
+ # set_resource_name(volume, "inception-store")
33
+ def set_resource_name(resource, name)
34
+ fog_compute.tags.create :key => "Name", :value => name, :resource_id => resource.id
35
+ end
36
+
37
+ def delete_key_pair_if_exists(key_pair_name)
38
+ if fog_key_pair = fog_compute.key_pairs.get(key_pair_name)
39
+ fog_key_pair.destroy
40
+ end
41
+ end
42
+
43
+ def delete_servers_with_name(name)
44
+ fog_compute.servers.select {|s| s.tags["Name"] && (s.tags["Name"].downcase == name.downcase) }.each do |server|
45
+ puts "Destroying server #{server.id}... "
46
+ server.destroy
47
+ end
48
+ end
49
+
50
+ def delete_volumes_with_name(name)
51
+ fog_compute.volumes.select do |v|
52
+ volume_name = v.tags["Name"]
53
+ volume_name && volume_name.downcase == name.downcase
54
+ end.each do |volume|
55
+ puts "Destroying volume #{volume.id}... "
56
+ volume.destroy
57
+ end
58
+ end
59
+
60
+ # Destroy all IP addresses that aren't bound to a server
61
+ def cleanup_unused_ip_addresses
62
+ fog_compute.addresses.each do |a|
63
+ unless a.server
64
+ puts "Deleting unused IP address #{a.public_ip}... "
65
+ a.destroy
66
+ end
67
+ end
68
+ end
69
+
70
+ # Creates or reuses an security group and opens ports.
71
+ #
72
+ # +security_group_name+ is the name to be created or reused
73
+ # +ports+ is a hash of name/port for ports to open, for example:
74
+ # {
75
+ # ssh: 22,
76
+ # http: 80,
77
+ # https: 443
78
+ # }
79
+ # protocol defaults to TCP
80
+ # You can also use a more verbose +ports+ using the format:
81
+ # {
82
+ # ssh: 22,
83
+ # http: { ports: (80..82) },
84
+ # mosh: { protocol: "udp", ports: (60000..60050) }
85
+ # mosh: { protocol: "rdp", ports: (3398..3398), ip_ranges: [ { cidrIp: "196.212.12.34/32" } ] }
86
+ # }
87
+ # In this example,
88
+ # * TCP 22 will be opened for ssh from any ip_range,
89
+ # * TCP ports 80, 81, 82 for http from any ip_range,
90
+ # * UDP 60000 -> 60050 for mosh from any ip_range and
91
+ # * TCP 3398 for RDP from ip range: 96.212.12.34/32
92
+ def create_security_group(security_group_name, description, ports)
93
+ security_groups = fog_compute.security_groups
94
+ unless sg = security_groups.find { |s| s.name == security_group_name }
95
+ sg = fog_compute.security_groups.create(name: security_group_name, description: description)
96
+ puts "Created security group #{security_group_name}"
97
+ ip_permissions = ip_permissions(sg)
98
+ ports_opened = 0
99
+ ports.each do |name, port_defn|
100
+ (protocol, port_range, ip_range) = extract_port_definition(port_defn)
101
+ unless port_open?(ip_permissions, port_range, protocol, ip_range)
102
+ authorize_port_range(sg, port_range, protocol, ip_range)
103
+ puts " -> opened #{name} ports #{protocol.upcase} #{port_range.min}..#{port_range.max} from IP range #{ip_range}"
104
+ ports_opened += 1
105
+ end
106
+ end
107
+ else
108
+ puts "Reusing security group #{security_group_name}"
109
+ end
110
+ true
111
+ end
112
+
113
+ def port_open?(ip_permissions, port_range, protocol, ip_range)
114
+ ip_permissions && ip_permissions.find do |ip|
115
+ ip["ipProtocol"] == protocol \
116
+ && ip["ipRanges"].detect { |range| range["cidrIp"] == ip_range } \
117
+ && ip["fromPort"] <= port_range.min \
118
+ && ip["toPort"] >= port_range.max
119
+ end
120
+ end
121
+
122
+ def authorize_port_range(sg, port_range, protocol, ip_range)
123
+ sg.authorize_port_range(port_range, {:ip_protocol => protocol, :cidr_ip => ip_range})
124
+ end
125
+
126
+ def ip_permissions(sg)
127
+ sg.ip_permissions
128
+ end
129
+
130
+ # Any of the following +port_defn+ can be used:
131
+ # {
132
+ # ssh: 22,
133
+ # http: { ports: (80..82) },
134
+ # mosh: { protocol: "udp", ports: (60000..60050) }
135
+ # mosh: { protocol: "rdp", ports: (3398..3398), ip_range: "196.212.12.34/32" }
136
+ # }
137
+ # In this example,
138
+ # * TCP 22 will be opened for ssh from any ip_range,
139
+ # * TCP ports 80, 81, 82 for http from any ip_range,
140
+ # * UDP 60000 -> 60050 for mosh from any ip_range and
141
+ # * TCP 3398 for RDP from ip range: 96.212.12.34/32
142
+ def extract_port_definition(port_defn)
143
+ protocol = "tcp"
144
+ ip_range = "0.0.0.0/0"
145
+ if port_defn.is_a? Integer
146
+ port_range = (port_defn..port_defn)
147
+ elsif port_defn.is_a? Range
148
+ port_range = port_defn
149
+ elsif port_defn.is_a? Hash
150
+ protocol = port_defn[:protocol] if port_defn[:protocol]
151
+ port_range = port_defn[:ports] if port_defn[:ports]
152
+ ip_range = port_defn[:ip_range] if port_defn[:ip_range]
153
+ end
154
+ [protocol, port_range, ip_range]
155
+ end
156
+
157
+ def provision_or_reuse_public_ip_address(options={})
158
+ provision_public_ip_address(options) || find_unused_public_ip_address(options)
159
+ end
160
+
161
+ def find_unused_public_ip_address(options={})
162
+ if address = fog_compute.addresses.find { |s| s.server_id.nil? }
163
+ address.public_ip
164
+ end
165
+ end
166
+
167
+ def bootstrap(new_attributes)
168
+ server = fog_compute.servers.new(new_attributes)
169
+
170
+ unless new_attributes[:key_name]
171
+ raise "please provide :key_name attribute"
172
+ end
173
+ unless private_key_path = new_attributes.delete(:private_key_path)
174
+ raise "please provide :private_key_path attribute"
175
+ end
176
+
177
+ server.save
178
+ unless Fog.mocking?
179
+ server.wait_for { ready? }
180
+ server.setup(keys: [private_key_path])
181
+ end
182
+ server
183
+ end
184
+
185
+ end
@@ -0,0 +1,84 @@
1
+ # Copyright (c) 2012-2013 Stark & Wayne, LLC
2
+
3
+ module Inception; module Providers; module Clients; end; end; end
4
+
5
+ require "inception/providers/clients/fog_provider_client"
6
+ require "inception/providers/constants/openstack_constants"
7
+
8
+ class Inception::Providers::Clients::OpenStackProviderClient < Inception::Providers::Clients::FogProviderClient
9
+ # @return [String] provisions a new public IP address in target region
10
+ # TODO nil if none available
11
+ def provision_public_ip_address(options={})
12
+ address = fog_compute.addresses.create
13
+ address.ip
14
+ # TODO catch error and return nil
15
+ end
16
+
17
+ def associate_ip_address_with_server(ip_address, server)
18
+ address = fog_compute.addresses.find { |a| a.ip == ip_address }
19
+ address.server = server
20
+ end
21
+
22
+ # Hook method for FogProviderClient#create_security_group
23
+ def ip_permissions(sg)
24
+ sg.rules
25
+ end
26
+
27
+ # Hook method for FogProviderClient#create_security_group
28
+ def authorize_port_range(sg, port_range, protocol, ip_range)
29
+ sg.create_security_group_rule(port_range.min, port_range.max, protocol, ip_range)
30
+ end
31
+
32
+ def find_server_device(server, device)
33
+ va = fog_compute.get_server_volumes(server.id).body['volumeAttachments']
34
+ va.find { |v| v["device"] == device }
35
+ end
36
+
37
+ def create_and_attach_volume(name, disk_size, server, device)
38
+ volume = fog_compute.volumes.create(:name => name,
39
+ :description => "",
40
+ :size => disk_size,
41
+ :availability_zone => server.availability_zone)
42
+ volume.wait_for { volume.status == 'available' }
43
+ volume.attach(server.id, device)
44
+ volume.wait_for { volume.status == 'in-use' }
45
+ end
46
+
47
+ def image_id
48
+ raise "Not yet implemented"
49
+ end
50
+
51
+ # Construct a Fog::Compute object
52
+ # Uses +attributes+ which normally originates from +settings.provider+
53
+ def setup_fog_connection
54
+ configuration = Fog.symbolize_credentials(attributes.credentials)
55
+ configuration[:provider] = "OpenStack"
56
+ @fog_compute = Fog::Compute.new(configuration)
57
+ end
58
+
59
+ def fog_attributes(inception_server)
60
+ # :name => "Inception VM",
61
+ # :key_name => key_name,
62
+ # :private_key_path => inception_vm_private_key_path,
63
+ # :flavor_ref => inception_flavor.id,
64
+ # :image_ref => inception_image.id,
65
+ # :security_groups => [settings["inception"]["security_group"]],
66
+ # :username => username
67
+ {
68
+ name: inception_server.server_name,
69
+ key_name: inception_server.key_name,
70
+ private_key_path: inception_server.private_key_path,
71
+ image_ref: inception_server.image_id,
72
+ flavor_ref: flavor_id(inception_server.flavor),
73
+ security_groups: inception_server.security_groups,
74
+ public_key: inception_server.public_key,
75
+ public_ip_address: inception_server.ip_address,
76
+ bits: 64,
77
+ username: "ubuntu",
78
+ }
79
+ end
80
+
81
+ def openstack_constants
82
+ Inception::Providers::Constants::OpenStackConstants
83
+ end
84
+ end
@@ -0,0 +1,25 @@
1
+ # Copyright (c) 2012-2013 Stark & Wayne, LLC
2
+
3
+ module Inception; module Providers; module Constants; end; end; end
4
+
5
+ module Inception::Providers::Constants::AwsConstants
6
+ extend self
7
+
8
+ # http://docs.aws.amazon.com/general/latest/gr/rande.html#region
9
+ def region_labels
10
+ [
11
+ { label: "US East (Northern Virginia) Region", code: "us-east-1" },
12
+ { label: "US West (Oregon) Region", code: "us-west-2" },
13
+ { label: "US West (Northern California) Region", code: "us-west-1" },
14
+ { label: "EU (Ireland) Region", code: "eu-west-1" },
15
+ { label: "Asia Pacific (Singapore) Region", code: "ap-southeast-1" },
16
+ { label: "Asia Pacific (Sydney) Region", code: "ap-southeast-2" },
17
+ { label: "Asia Pacific (Tokyo) Region", code: "ap-northeast-1" },
18
+ { label: "South America (Sao Paulo) Region", code: "sa-east-1" },
19
+ ]
20
+ end
21
+
22
+ def default_region_code
23
+ "us-east-1"
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ # Copyright (c) 2012-2013 Stark & Wayne, LLC
2
+
3
+ module Inception; module Providers; module Constants; end; end; end
4
+
5
+ module Inception::Providers::Constants::OpenStackConstants
6
+ extend self
7
+
8
+ # explicit value representing "no region requested"
9
+ def no_region_code
10
+ "no-region-requested"
11
+ end
12
+ end
@@ -0,0 +1,28 @@
1
+ # Copyright (c) 2012-2013 Stark & Wayne, LLC
2
+
3
+ module Inception; end
4
+
5
+ module Inception::Providers
6
+ extend self
7
+
8
+ # returns a BOSH provider (CPI) specific object
9
+ # with helpers related to that provider
10
+ # returns nil if +provider_name+ is unknown
11
+ def provider_client(attributes)
12
+ attributes = attributes.is_a?(Hash) ? ReadWriteSettings.new(attributes) : attributes
13
+ case attributes.name.to_sym
14
+ when :aws
15
+ @aws_provider_client ||= begin
16
+ require "inception/providers/clients/aws_provider_client"
17
+ Inception::Providers::Clients::AwsProviderClient.new(attributes)
18
+ end
19
+ when :openstack
20
+ @openstack_provider_client ||= begin
21
+ require "inception/providers/clients/openstack_provider_client"
22
+ Inception::Providers::Clients::OpenStackProviderClient.new(attributes)
23
+ end
24
+ else
25
+ nil
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module Inception
2
+ VERSION = "0.2.1"
3
+ end
data/lib/inception.rb ADDED
@@ -0,0 +1,9 @@
1
+ require "inception/version"
2
+
3
+ module Inception
4
+ end
5
+
6
+ require "inception/providers"
7
+ require "inception/inception_server"
8
+ require "inception/inception_server_cookbook"
9
+ require "inception/next_deploy_actions"
data/nodes/.gitkeep ADDED
File without changes
File without changes
@@ -0,0 +1,5 @@
1
+ [user]
2
+ name = Dr Nic Williams
3
+ email = drnicwilliams@gmail.com
4
+ [github]
5
+ user = drnic
@@ -0,0 +1,14 @@
1
+ ---
2
+ provider:
3
+ name: aws
4
+ region: us-west-2
5
+ credentials:
6
+ aws_access_key_id: MOCK_AWS_ACCESS_KEY_ID
7
+ aws_secret_access_key: MOCK_AWS_SECRET_ACCESS_KEY
8
+ inception:
9
+ ip_address: 54.214.15.178
10
+ key_pair:
11
+ name: inception
12
+ private_key: private_key
13
+ extensions:
14
+ - mosh
@@ -0,0 +1,31 @@
1
+ ---
2
+ provider:
3
+ name: aws
4
+ region: us-west-2
5
+ credentials:
6
+ aws_access_key_id: MOCK_AWS_ACCESS_KEY_ID
7
+ aws_secret_access_key: MOCK_AWS_SECRET_ACCESS_KEY
8
+ git:
9
+ name: Dr Nic Williams
10
+ email: drnicwilliams@gmail.com
11
+ inception:
12
+ key_pair:
13
+ name: inception
14
+ private_key: private_key
15
+ extensions:
16
+ - mosh
17
+ size: m1.small
18
+ disk_size: 16
19
+ provisioned:
20
+ ip_address: 54.214.15.178
21
+ image_id: ami-123456
22
+ server_id: i-e7f005d2
23
+ security_groups:
24
+ - ssh
25
+ - mosh
26
+ username: vcap
27
+ disk_device:
28
+ volume_id: vol-123456
29
+ external: /dev/sdf
30
+ internal: /dev/xvdf
31
+ host: ec2-54-214-15-178.us-west-2.compute.amazonaws.com
File without changes
@@ -0,0 +1,38 @@
1
+ require File.expand_path("../../../support/aws/aws_helpers", __FILE__)
2
+
3
+ describe "AWS deployment without Chef run" do
4
+ include FileUtils
5
+ include AwsHelpers
6
+
7
+ if AwsHelpers.aws_credentials?
8
+ before do
9
+ prepare_aws("basic", aws_region, "next_deploy_actions.no_converge" => true)
10
+ end
11
+ after(:all) do
12
+ destroy_test_constructs unless keep_after_test?
13
+ end
14
+
15
+ def aws_region
16
+ ENV['AWS_REGION'] || "us-west-2"
17
+ end
18
+
19
+ it "creates an EC2 inception/microbosh with the associated resources" do
20
+ create_manifest
21
+
22
+ manifest_file = home_file(".inception_server", "settings.yml")
23
+ File.should be_exists(manifest_file)
24
+
25
+ cmd.deploy
26
+
27
+ inception_servers = fog.servers.select { |s| s.tags["Name"] == test_server_name && s.ready? }
28
+ inception_servers.size.should == 1
29
+
30
+ server = inception_servers.first
31
+ server.volumes.size.should == 2
32
+ named_volume = server.volumes.select { |s| s.tags["Name"] == test_server_name }
33
+ named_volume.should_not be_nil
34
+ end
35
+ else
36
+ it "no AWS integration specs run; missing $AWS_ACCESS_KEY_ID etc"
37
+ end
38
+ end
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2012-2013 Stark & Wayne, LLC
2
+
3
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
4
+
5
+ require "rubygems"
6
+ require "bundler"
7
+ Bundler.setup(:default, :test)
8
+
9
+ $:.unshift(File.expand_path("../../lib", __FILE__))
10
+
11
+ require "rspec/core"
12
+ require "inception/providers"
13
+ require "inception"
14
+ require "inception/cli"
15
+
16
+ # for the #sh helper
17
+ require "rake"
18
+ require "rake/file_utils"
19
+
20
+ # load all files in spec/support/* (but not lower down)
21
+ Dir[File.dirname(__FILE__) + '/support/*'].each do |path|
22
+ require path unless File.directory?(path)
23
+ end
24
+
25
+ def spec_asset(filename)
26
+ File.expand_path("../assets/#{filename}", __FILE__)
27
+ end
28
+
29
+ def setup_home_dir
30
+ home_dir = File.expand_path("../../tmp/home", __FILE__)
31
+ FileUtils.rm_rf(home_dir)
32
+ FileUtils.mkdir_p(home_dir)
33
+ ENV['HOME'] = home_dir
34
+ FileUtils.cp_r(spec_asset("gitconfig"), home_file(".gitconfig"))
35
+ end
36
+
37
+ # returns the file path to a file
38
+ # in the fake $HOME folder
39
+ def home_file(*path)
40
+ File.join(ENV['HOME'], *path)
41
+ end
42
+
43
+ RSpec.configure do |c|
44
+ c.before do
45
+ setup_home_dir
46
+ Fog::Mock.reset
47
+ end
48
+
49
+ c.color_enabled = true
50
+ end
@@ -0,0 +1,73 @@
1
+ require "active_support/core_ext/hash/keys"
2
+ module AwsHelpers
3
+ extend self
4
+ include SettingsHelper
5
+
6
+ def keep_after_test?
7
+ ENV['KEEP_AFTER_TEST']
8
+ end
9
+
10
+ def region
11
+ @region ||= "us-west-2"
12
+ end
13
+
14
+ def fog
15
+ @fog ||= Fog::Compute.new(fog_credentials.merge(:region => region))
16
+ end
17
+
18
+ def aws_credentials?
19
+ access_key = ENV['AWS_ACCESS_KEY_ID']
20
+ secret_key = ENV["AWS_SECRET_ACCESS_KEY"]
21
+ access_key && secret_key
22
+ end
23
+
24
+ def fog_credentials
25
+ @fog_credentials ||= begin
26
+ access_key = ENV['AWS_ACCESS_KEY_ID']
27
+ secret_key = ENV["AWS_SECRET_ACCESS_KEY"]
28
+ unless access_key && secret_key
29
+ raise "Please provided $AWS_ACCESS_KEY_ID and $AWS_SECRET_ACCESS_KEY"
30
+ end
31
+ credentials = {
32
+ :provider => 'AWS',
33
+ :aws_access_key_id => access_key,
34
+ :aws_secret_access_key => secret_key
35
+ }
36
+ end
37
+ end
38
+
39
+ def prepare_aws(spec_name, aws_region, options={})
40
+ setup_home_dir
41
+ @cmd = nil
42
+ @fog = nil
43
+ create_manifest(options)
44
+ destroy_test_constructs
45
+ end
46
+
47
+ def unique_number
48
+ ENV['UNIQUE_NUMBER'] || Random.rand(100000)
49
+ end
50
+
51
+ def test_server_name
52
+ "test-inception"
53
+ end
54
+
55
+ def create_manifest(options = {})
56
+ credentials = options.delete(:credentials) || fog_credentials
57
+ setting "provider.name", "aws"
58
+ setting "provider.credentials", credentials.stringify_keys
59
+ setting "provider.region", region
60
+ setting "inception.name", test_server_name
61
+ options.each { |key, value| setting(key, value) }
62
+ cmd.save_settings!
63
+ end
64
+
65
+ def destroy_test_constructs
66
+ puts "Destroying everything created by previous test... "
67
+ # destroy servers using inception-vm SG
68
+ provider.delete_servers_with_name(test_server_name)
69
+ provider.delete_volumes_with_name(test_server_name)
70
+ provider.delete_key_pair_if_exists(test_server_name)
71
+ provider.cleanup_unused_ip_addresses
72
+ end
73
+ end
@@ -0,0 +1,20 @@
1
+ # assumes @cmd is Inception::Cli instance
2
+ module SettingsHelper
3
+ def cmd
4
+ @cmd ||= Inception::Cli.new
5
+ end
6
+
7
+ def provider
8
+ cmd.provider_client
9
+ end
10
+
11
+ # Set a nested setting with "key1.key2.key3" notation
12
+ def setting(nested_key, value)
13
+ settings.set(nested_key, value)
14
+ end
15
+
16
+ # used by +SettingsSetter+ to access the settings
17
+ def settings
18
+ cmd.settings
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ module StdoutCapture
2
+ # Captures stdout within the block
3
+ # Usage:
4
+ #
5
+ # out = capture_stdout do
6
+ # puts "this will not be shown"
7
+ # end
8
+ # out.should == "this will not be shown"
9
+ def capture_stdout(&block)
10
+ out = StringIO.new
11
+ $stdout = out
12
+ yield
13
+ return out
14
+ ensure
15
+ $stdout = STDOUT
16
+ end
17
+ end
File without changes
@@ -0,0 +1,39 @@
1
+ require File.expand_path("../../support/aws/aws_helpers", __FILE__)
2
+
3
+ require "fog"
4
+
5
+ describe "AWS deployment deletion" do
6
+ include FileUtils
7
+ include StdoutCapture
8
+ include SettingsHelper
9
+ include AwsHelpers
10
+
11
+ before do
12
+ setup_home_dir
13
+ Fog.mock!
14
+ @cmd = Inception::Cli.new
15
+ setting "provider.name", "aws"
16
+ setting "provider.credentials.aws_access_key_id", "aws_access_key_id"
17
+ setting "provider.credentials.aws_secret_access_key", "aws_secret_access_key"
18
+ setting "provider.region", "us-west-2"
19
+ setting "next_deploy_actions.no_converge", true
20
+ capture_stdout { @cmd.deploy }
21
+ end
22
+
23
+ def perform_delete
24
+ config = { shell: Thor::Base.shell.new }
25
+ capture_stdout { @cmd.class.send(:dispatch, :delete, [], {:"non-interactive" => true}, config) }
26
+ end
27
+
28
+ it "clears out settings.yml" do
29
+ perform_delete
30
+ settings = ReadWriteSettings.new(File.expand_path("~/.inception_server/settings.yml"))
31
+ settings.exists?("provider").should_not be_nil
32
+ settings.exists?("git").should_not be_nil
33
+ settings.exists?("inception.provisioned.disk_device").should be_nil
34
+ settings.exists?("inception.provisioned.host").should be_nil
35
+ settings.exists?("inception.provisioned.ip_address").should be_nil
36
+ settings.exists?("inception.key_pair").should be_nil
37
+ settings.exists?("inception.provisioned.disk_device").should be_nil
38
+ end
39
+ end