migrant-boxes 0.1.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/.gitignore +5 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Guardfile +14 -0
- data/README.markdown +182 -0
- data/Rakefile +11 -0
- data/bin/.gitignore +16 -0
- data/bin/migrant +7 -0
- data/features/basic_configuration.feature +47 -0
- data/features/step_definitions/configuration_steps.rb +60 -0
- data/features/support/env.rb +2 -0
- data/lib/migrant/bootstrappers/base.rb +38 -0
- data/lib/migrant/bootstrappers/ruby_local_192.rb +33 -0
- data/lib/migrant/bootstrappers.rb +2 -0
- data/lib/migrant/boxes.rb +55 -0
- data/lib/migrant/cli.rb +39 -0
- data/lib/migrant/clouds/aws.rb +28 -0
- data/lib/migrant/clouds/base.rb +100 -0
- data/lib/migrant/clouds/rackspace.rb +25 -0
- data/lib/migrant/clouds.rb +3 -0
- data/lib/migrant/environment.rb +127 -0
- data/lib/migrant/provisioners/base.rb +33 -0
- data/lib/migrant/provisioners/chef_solo.rb +57 -0
- data/lib/migrant/provisioners.rb +2 -0
- data/lib/migrant/ui.rb +24 -0
- data/lib/migrant/util/template_renderer.rb +15 -0
- data/lib/migrant/util.rb +5 -0
- data/lib/migrant/version.rb +3 -0
- data/lib/migrant.rb +15 -0
- data/migrant.gemspec +34 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/aws_cloud_spec.rb +6 -0
- data/spec/unit/boxes_spec.rb +62 -0
- data/spec/unit/cloud_spec.rb +7 -0
- data/spec/unit/environment_spec.rb +45 -0
- data/spec/unit/rackspace_cloud_spec.rb +6 -0
- data/templates/chef/dna.json.erb +3 -0
- data/templates/chef/solo.rb.erb +5 -0
- metadata +225 -0
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', :version => 2 do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/migrant/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
end
|
9
|
+
|
10
|
+
guard 'cucumber' do
|
11
|
+
watch(%r{^features/.+\.feature$})
|
12
|
+
watch(%r{^features/support/.+$}) { 'features' }
|
13
|
+
watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
|
14
|
+
end
|
data/README.markdown
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
Migrant
|
2
|
+
=======
|
3
|
+
|
4
|
+
Migrant is a tool to take your Vagrant boxes to the 'cloud'.
|
5
|
+
|
6
|
+
Migrant is designed to be a simple, focused tool to take boxes that are
|
7
|
+
working locally with Vagrant and deploy them remotely. Migrant reads
|
8
|
+
most configuration and provisioning information from Vagrant's
|
9
|
+
configuration files and then applies the same approach to remote 'cloud'
|
10
|
+
servers.
|
11
|
+
|
12
|
+
Installation
|
13
|
+
------------
|
14
|
+
|
15
|
+
```
|
16
|
+
$ gem install migrant-boxes
|
17
|
+
```
|
18
|
+
|
19
|
+
Or in a `Gemfile`:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem 'migrant-boxes'
|
23
|
+
```
|
24
|
+
|
25
|
+
Examples
|
26
|
+
========
|
27
|
+
|
28
|
+
For single box configurations, the minimum that needs to be specified
|
29
|
+
are provider access credentials and the location of the SSH keys to use
|
30
|
+
to access the box.
|
31
|
+
|
32
|
+
Minimal AWS Configuration
|
33
|
+
-------------------------
|
34
|
+
|
35
|
+
This sets up a 'micro' sized aws box.
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
Configuration.for('migrant') {
|
39
|
+
provider {
|
40
|
+
name 'aws'
|
41
|
+
access_key ENV['AWS_ACCESS_KEY']
|
42
|
+
secret_key ENV['AWS_SECRET_KEY']
|
43
|
+
}
|
44
|
+
ssh {
|
45
|
+
public_key '~/.ssh/id_rsa.pub'
|
46
|
+
private_key '~/.ssh/id_rsa'
|
47
|
+
}
|
48
|
+
}
|
49
|
+
```
|
50
|
+
|
51
|
+
Minimal Rackspace Configuration
|
52
|
+
-------------------------------
|
53
|
+
|
54
|
+
This sets up an instance with 256MB ram
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
Configuration.for('migrant') {
|
58
|
+
provider {
|
59
|
+
name 'rackspace'
|
60
|
+
user_name ENV['RACKSPACE_ACCESS_KEY']
|
61
|
+
api_key ENV['AWS_SECRET_KEY']
|
62
|
+
}
|
63
|
+
ssh {
|
64
|
+
public_key '~/.ssh/id_rsa.pub'
|
65
|
+
private_key '~/.ssh/id_rsa'
|
66
|
+
}
|
67
|
+
}
|
68
|
+
```
|
69
|
+
|
70
|
+
This will create the smallest possible server instance and run the provisioners
|
71
|
+
that are defined in the Vagrantfile. It will use your ssh keys to
|
72
|
+
access the box, and write some state information about instances to
|
73
|
+
`config/migrant.yml`
|
74
|
+
|
75
|
+
Migrant is highly opinionated: it will use the latest LTS Ubuntu
|
76
|
+
release. It will also download and install Ruby 1.9 from source in
|
77
|
+
`/usr/local`.
|
78
|
+
|
79
|
+
Customizing AWS instances
|
80
|
+
-------------------------
|
81
|
+
|
82
|
+
It's also possible to specify the size of the box and the AMI to use
|
83
|
+
when provisioning. Keep in mind that as of right now all the
|
84
|
+
bootstrapping and provisioning code is designed to work with recent
|
85
|
+
flavors of Ubuntu.
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
|
89
|
+
Configuration.for('migrant') {
|
90
|
+
provider {
|
91
|
+
name 'aws'
|
92
|
+
access_key ENV['AWS_ACCESS_KEY']
|
93
|
+
secret_key ENV['AWS_SECRET_KEY']
|
94
|
+
ip_address '1.2.3.4' # <-- Elastic IP address
|
95
|
+
flavor 'c1.medium' # <-- Any instance size
|
96
|
+
image_id 'ami-81b275e8' # <-- AMI ID to use (Lucid 32-bit)
|
97
|
+
}
|
98
|
+
ssh {
|
99
|
+
public_key '~/.ssh/id_rsa.pub'
|
100
|
+
private_key '~/.ssh/id_rsa'
|
101
|
+
}
|
102
|
+
}
|
103
|
+
```
|
104
|
+
Customizing Rackspace Instances
|
105
|
+
-------------------------------
|
106
|
+
|
107
|
+
It's also possible to customize the server size with Rackspace.
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
Configuration.for('migrant') {
|
111
|
+
provider {
|
112
|
+
name 'rackspace'
|
113
|
+
user_name ENV['RACKSPACE_ACCESS_KEY']
|
114
|
+
api_key ENV['AWS_SECRET_KEY']
|
115
|
+
flavor_id 3 # <-- 1GB Server
|
116
|
+
}
|
117
|
+
ssh {
|
118
|
+
public_key '~/.ssh/id_rsa.pub'
|
119
|
+
private_key '~/.ssh/id_rsa'
|
120
|
+
}
|
121
|
+
}
|
122
|
+
```
|
123
|
+
|
124
|
+
Configuring Multiple Environments
|
125
|
+
---------------------------------
|
126
|
+
|
127
|
+
Most deployments have at least a staging and a production environment.
|
128
|
+
Migrant supports an arbitrary number of named environments.
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
Configuration.for('migrant') {
|
132
|
+
provider {
|
133
|
+
name 'rackspace'
|
134
|
+
user_name ENV['RACKSPACE_ACCESS_KEY']
|
135
|
+
api_key ENV['AWS_SECRET_KEY']
|
136
|
+
}
|
137
|
+
ssh {
|
138
|
+
public_key '~/.ssh/id_rsa.pub'
|
139
|
+
private_key '~/.ssh/id_rsa'
|
140
|
+
}
|
141
|
+
|
142
|
+
# Production environment settings. Defaults are inherited from above
|
143
|
+
production {
|
144
|
+
provider {
|
145
|
+
flavor_id 3 # <-- 1GB Server
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
# Staging environment settings. Defaults are inherited from above
|
150
|
+
staging {
|
151
|
+
provider {
|
152
|
+
flavor_id 1 # <-- 256MB Server
|
153
|
+
}
|
154
|
+
}
|
155
|
+
}
|
156
|
+
```
|
157
|
+
|
158
|
+
Usage
|
159
|
+
=====
|
160
|
+
```
|
161
|
+
$ gem install migrant
|
162
|
+
$ migrant init
|
163
|
+
$ migrant up
|
164
|
+
```
|
165
|
+
|
166
|
+
For a box in a particular 'environment':
|
167
|
+
|
168
|
+
```
|
169
|
+
$ migrant production up
|
170
|
+
$ migrant staging up
|
171
|
+
$ migrant staging destroy
|
172
|
+
```
|
173
|
+
|
174
|
+
Gotchas
|
175
|
+
=======
|
176
|
+
|
177
|
+
* Bootstrapping and provisioning only tested on Ubuntu 'Lucid Lynx'
|
178
|
+
* Chef-Solo provisioner the only one implemented
|
179
|
+
* Currently does not support multi-vm configurations. Eventually would
|
180
|
+
be nice to support load-balanced configurations, and have some ability
|
181
|
+
to start or stop any instances necessary to implement that
|
182
|
+
configuration (like PoolParty).
|
data/Rakefile
ADDED
data/bin/.gitignore
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application '.gitignore' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('vagrant', '.gitignore')
|
data/bin/migrant
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
Feature: Basic Configuration
|
2
|
+
In order to use Migrant to provision boxes remotely
|
3
|
+
I need to configure some minimal information
|
4
|
+
|
5
|
+
Scenario: Basic AWS Configuration
|
6
|
+
Given a Migrantfile with the body
|
7
|
+
"""
|
8
|
+
Configuration.for('migrant') {
|
9
|
+
provider {
|
10
|
+
name 'aws'
|
11
|
+
access_key 'my_access_key'
|
12
|
+
secret_key 'my_secret_key'
|
13
|
+
}
|
14
|
+
ssh {
|
15
|
+
public_key '~/.ssh/id_rsa.pub'
|
16
|
+
private_key '~/.ssh/id_rsa'
|
17
|
+
}
|
18
|
+
}
|
19
|
+
"""
|
20
|
+
Then the cloud should be "aws"
|
21
|
+
And my AWS access key should be "my_access_key"
|
22
|
+
And my AWS secret key should be "my_secret_key"
|
23
|
+
And my ssh public key should reside at "~/.ssh/id_rsa.pub"
|
24
|
+
And my ssh private key should reside at "~/.ssh/id_rsa"
|
25
|
+
And my AWS instance ID should be "t1.micro"
|
26
|
+
And my AWS AMI should be "Ubuntu Lucid Lynx" for the architecture "AMD64"
|
27
|
+
|
28
|
+
Scenario: Basic Rackspace Configuration
|
29
|
+
Given a Migrantfile with the body
|
30
|
+
"""
|
31
|
+
Configuration.for('migrant') {
|
32
|
+
provider {
|
33
|
+
name 'rackspace'
|
34
|
+
user_name 'my_user_name'
|
35
|
+
api_key 'my_api_key'
|
36
|
+
}
|
37
|
+
ssh {
|
38
|
+
public_key '~/.ssh/id_rsa.pub'
|
39
|
+
private_key '~/.ssh/id_rsa'
|
40
|
+
}
|
41
|
+
}
|
42
|
+
"""
|
43
|
+
Then the cloud should be "rackspace"
|
44
|
+
And my rackspace username should be "my_user_name"
|
45
|
+
And my rackspace api key should be "my_api_key"
|
46
|
+
And my image should be "Ubuntu Lucid Lynx"
|
47
|
+
And my flavor should be "256 MB Server"
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'configuration'
|
3
|
+
require 'pry'
|
4
|
+
require 'migrant'
|
5
|
+
|
6
|
+
Given /^a Migrantfile with the body$/ do |migrantfile_body|
|
7
|
+
tmpfile = Tempfile.open('migrant-config') do |f|
|
8
|
+
f.write migrantfile_body
|
9
|
+
f
|
10
|
+
end
|
11
|
+
Kernel.load(tmpfile.path)
|
12
|
+
@config = Configuration.for('migrant')
|
13
|
+
@environment = Migrant::Environment.new(nil,@config)
|
14
|
+
end
|
15
|
+
|
16
|
+
Then /^the cloud should be "([^"]*)"$/ do |cloud_provider_name|
|
17
|
+
# Make sure the environment is set up the right way
|
18
|
+
@environment.cloud.class.should == Migrant::Clouds::Base.registered(cloud_provider_name)
|
19
|
+
end
|
20
|
+
|
21
|
+
Then /^my AWS access key should be "([^"]*)"$/ do |arg1|
|
22
|
+
@config.provider.access_key.should == arg1
|
23
|
+
end
|
24
|
+
|
25
|
+
Then /^my AWS secret key should be "([^"]*)"$/ do |arg1|
|
26
|
+
@config.provider.secret_key.should == arg1
|
27
|
+
end
|
28
|
+
|
29
|
+
Then /^my ssh public key should reside at "([^"]*)"$/ do |arg1|
|
30
|
+
@config.ssh.public_key.should == arg1
|
31
|
+
end
|
32
|
+
|
33
|
+
Then /^my ssh private key should reside at "([^"]*)"$/ do |arg1|
|
34
|
+
@config.ssh.private_key.should == arg1
|
35
|
+
end
|
36
|
+
|
37
|
+
Then /^my AWS instance ID should be "([^"]*)"$/ do |arg1|
|
38
|
+
pending # express the regexp above with the code you wish you had
|
39
|
+
end
|
40
|
+
|
41
|
+
Then /^my AWS AMI should be "([^"]*)" for the architecture "([^"]*)"$/ do |arg1, arg2|
|
42
|
+
pending # express the regexp above with the code you wish you had
|
43
|
+
end
|
44
|
+
|
45
|
+
Then /^my rackspace username should be "([^"]*)"$/ do |arg1|
|
46
|
+
@config.provider.user_name.should == arg1
|
47
|
+
end
|
48
|
+
|
49
|
+
Then /^my rackspace api key should be "([^"]*)"$/ do |arg1|
|
50
|
+
@config.provider.api_key.should == arg1
|
51
|
+
end
|
52
|
+
|
53
|
+
Then /^my image should be "([^"]*)"$/ do |arg1|
|
54
|
+
pending # express the regexp above with the code you wish you had
|
55
|
+
end
|
56
|
+
|
57
|
+
Then /^my flavor should be "([^"]*)"$/ do |arg1|
|
58
|
+
pending # express the regexp above with the code you wish you had
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Migrant
|
2
|
+
module Bootstrappers
|
3
|
+
# Base class for all boostrappers.
|
4
|
+
class Base
|
5
|
+
|
6
|
+
def self.register(shortcut)
|
7
|
+
@@bootstrappers ||= Hash.new
|
8
|
+
@@bootstrappers[shortcut] = self
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.registered(shortcut)
|
12
|
+
@@bootstrappers[shortcut]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.default_bootstrapper
|
16
|
+
@@default = self
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.default
|
20
|
+
@@default
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(env)
|
24
|
+
@environment = env
|
25
|
+
end
|
26
|
+
|
27
|
+
# Run the bootstrapping process
|
28
|
+
def run
|
29
|
+
raise "Invalid Bootstrapper"
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns true if the box is already bootstrapped
|
33
|
+
def bootstrapped?
|
34
|
+
raise "Invalid Bootstrapper"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Migrant
|
2
|
+
module Bootstrappers
|
3
|
+
# Installs Ruby 1.9.2 into /usr/local
|
4
|
+
class RubyLocal192 < Base
|
5
|
+
register(:rbenv_192)
|
6
|
+
default_bootstrapper
|
7
|
+
|
8
|
+
def initialize(env)
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
commands = [
|
14
|
+
'sudo apt-get update',
|
15
|
+
'sudo apt-get install -y build-essential wget build-essential bison openssl libreadline5 libreadline-dev ' +
|
16
|
+
'curl git-core zlib1g zlib1g-dev libssl-dev vim libsqlite3-0 libsqlite3-dev ' +
|
17
|
+
'sqlite3 libreadline-dev libxml2-dev autoconf',
|
18
|
+
'rm -rf /tmp/ruby-build',
|
19
|
+
'git clone git://github.com/theaboutbox/ruby-build.git /tmp/ruby-build',
|
20
|
+
'cd /tmp/ruby-build && sudo ./install.sh',
|
21
|
+
'sudo ruby-build 1.9.2-p290 /usr/local',
|
22
|
+
'sudo gem install bundler chef'
|
23
|
+
]
|
24
|
+
@environment.cloud.execute commands
|
25
|
+
end
|
26
|
+
|
27
|
+
def bootstrapped?
|
28
|
+
result = @environment.server.ssh('/usr/local/bin/chef-solo --version')
|
29
|
+
result[0].status == 0
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Migrant
|
2
|
+
# Represents a box managed by Migrant. We save this object in YAML format
|
3
|
+
# so that subsequent runs of Migrant can find them.
|
4
|
+
class Box
|
5
|
+
attr_accessor :provider
|
6
|
+
attr_accessor :id
|
7
|
+
attr_accessor :name
|
8
|
+
|
9
|
+
def initialize(box_provider=nil,box_id=nil,box_name=nil)
|
10
|
+
@id = box_id
|
11
|
+
@provider = box_provider
|
12
|
+
@name = box_name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Loads and persists information about the boxes managed by this
|
17
|
+
# migrant configuration
|
18
|
+
class Boxes
|
19
|
+
# Returns an Boxes instance
|
20
|
+
def load
|
21
|
+
@boxes = YAML.load(File.read(@path)) if File.exists?(@path)
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(path)
|
26
|
+
@path = path
|
27
|
+
@boxes = {}
|
28
|
+
@boxes['file_version'] = Migrant::VERSION
|
29
|
+
@boxes['boxes'] = Hash.new
|
30
|
+
load
|
31
|
+
end
|
32
|
+
|
33
|
+
def save()
|
34
|
+
File.open(@path,'w') do |f|
|
35
|
+
f.write(YAML.dump(@boxes))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def [](environment)
|
40
|
+
environment = 'default' if environment.nil?
|
41
|
+
@boxes['boxes'][environment]
|
42
|
+
end
|
43
|
+
|
44
|
+
def []=(environment,box)
|
45
|
+
environment = 'default' if environment.nil?
|
46
|
+
@boxes['boxes'][environment] = box
|
47
|
+
end
|
48
|
+
|
49
|
+
def add(environment,provider,id)
|
50
|
+
environment = 'default' if environment.nil?
|
51
|
+
box = Box.new(provider,id)
|
52
|
+
self[environment] = box
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/migrant/cli.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'pp'
|
3
|
+
module Migrant
|
4
|
+
class CLI < Thor
|
5
|
+
desc 'init', 'Creates a Migrantfile with basic information'
|
6
|
+
def init
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'up', 'Starts the environment based on the information in the Migrantfile'
|
11
|
+
method_option :environment, :aliases => '-e', :desc => 'Specify an environment to launch boxes'
|
12
|
+
def up
|
13
|
+
load_config(options.environment)
|
14
|
+
@environment.up
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'destroy','Shut down the servers based on the information in this Migrantfile'
|
18
|
+
method_option :environment, :aliases => '-e', :desc => 'Specify an environment to destroy boxes'
|
19
|
+
def destroy
|
20
|
+
load_config(options.environment)
|
21
|
+
@environment.destroy
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'info','Describe any currently running instances'
|
25
|
+
method_option :environment, :aliases => '-e', :desc => 'Specify an environment to destroy boxes'
|
26
|
+
def info
|
27
|
+
load_config(options.environment)
|
28
|
+
@environment.info
|
29
|
+
end
|
30
|
+
|
31
|
+
no_tasks do
|
32
|
+
def load_config(environment_name)
|
33
|
+
@environment = Environment.new(environment_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Migrant
|
2
|
+
module Clouds
|
3
|
+
class AWS < Base
|
4
|
+
register 'aws'
|
5
|
+
|
6
|
+
def initialize(env)
|
7
|
+
super
|
8
|
+
@server_def[:username] = 'ubuntu'
|
9
|
+
@server_def[:groups] = ['d2-server']
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
def connect
|
14
|
+
@connection = Fog::Compute.new(:provider => 'AWS',
|
15
|
+
:aws_access_key_id => @environment.setting('provider.access_key'),
|
16
|
+
:aws_secret_access_key => @environment.setting('provider.secret_key'))
|
17
|
+
end
|
18
|
+
|
19
|
+
def log_server_info
|
20
|
+
super
|
21
|
+
@environment.ui.notice " Flavor: #{@environment.server.flavor.name}"
|
22
|
+
@environment.ui.notice "DNS Name: #{@environment.server.dns_name}"
|
23
|
+
@environment.ui.notice " Zone: #{@environment.server.availability_zone}"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'fog'
|
2
|
+
require 'pry'
|
3
|
+
module Migrant
|
4
|
+
module Clouds
|
5
|
+
|
6
|
+
# Base class for cloud service providers.
|
7
|
+
# All service providers use Fog to handle bootstrapping servers and running stuff
|
8
|
+
# Cloud service providers are responsible for starting up the server, setting up ssh
|
9
|
+
# access with the provided keypair, and (eventually) disabling the root user.
|
10
|
+
class Base
|
11
|
+
|
12
|
+
# Register a provider
|
13
|
+
def self.register(shortcut)
|
14
|
+
@@clouds ||= {}
|
15
|
+
@@clouds[shortcut] = self
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get a registered provider
|
19
|
+
def self.registered(shortcut)
|
20
|
+
@@clouds[shortcut]
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(env)
|
24
|
+
@environment = env
|
25
|
+
@server_def = {:private_key_path => @environment.setting('ssh.private_key'),
|
26
|
+
:public_key_path => @environment.setting('ssh.public_key')}
|
27
|
+
flavor_id = @environment.setting('provider.flavor_id')
|
28
|
+
@server_def[:flavor_id] = flavor_id unless flavor_id.nil?
|
29
|
+
image_id = @environment.setting('provider.image_id')
|
30
|
+
@server_def[:image_id] = image_id unless image_id.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_accessor :connection
|
34
|
+
|
35
|
+
def connect
|
36
|
+
raise "Invalid Action for Base Class"
|
37
|
+
end
|
38
|
+
|
39
|
+
def bootstrap_server
|
40
|
+
@environment.ui.info "Launching Server..."
|
41
|
+
@environment.server = @connection.servers.bootstrap(@server_def)
|
42
|
+
@environment.ui.notice "Server Launched!"
|
43
|
+
ip_address = @environment.setting('provider.ip_address')
|
44
|
+
unless ip_address.nil?
|
45
|
+
@connection.associate_address(@environment.server.id,ip_address)
|
46
|
+
end
|
47
|
+
log_server_info
|
48
|
+
end
|
49
|
+
|
50
|
+
def log_server_info
|
51
|
+
@environment.ui.notice " ID: #{@environment.server.id}"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Set up connection information for a server and set up SSH keypair access
|
55
|
+
#
|
56
|
+
# box - Migrant::Box object with information about the server to connect to
|
57
|
+
#
|
58
|
+
# Does not return anything but sets up @environment.server
|
59
|
+
def connect_to_server(box)
|
60
|
+
@environment.ui.notice "Connecting to #{box.provider.to_s} server: #{box.id}"
|
61
|
+
@environment.server = @connection.servers.get(box.id)
|
62
|
+
if (@environment.server.nil?)
|
63
|
+
@environment.ui.error "Cannot connect to server!"
|
64
|
+
raise "Cannot find server"
|
65
|
+
end
|
66
|
+
@environment.server.merge_attributes(@server_def)
|
67
|
+
end
|
68
|
+
|
69
|
+
def execute(commands)
|
70
|
+
server = @environment.server
|
71
|
+
commands.each do |cmd|
|
72
|
+
@environment.ui.info("$ #{cmd}")
|
73
|
+
result = server.ssh cmd
|
74
|
+
if (result[0].status != 0)
|
75
|
+
@environment.ui.info(result[0].stdout)
|
76
|
+
@environment.ui.error "Error executing command: #{cmd}\n#{result.inspect}"
|
77
|
+
raise "Remote Script Error"
|
78
|
+
end
|
79
|
+
@environment.ui.info(result[0].stdout)
|
80
|
+
@environment.ui.warn(result[0].stderr) if result[0].stderr
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Asks the user if they want to shut down a box
|
85
|
+
#
|
86
|
+
# box - A Migrant::Box with information about the box
|
87
|
+
#
|
88
|
+
# returns true if the user decided to shut down the box
|
89
|
+
def destroy(box)
|
90
|
+
if (@environment.ui.yes?("Are you sure you want to shut down box #{box.name}?",:red))
|
91
|
+
@environment.ui.notice "Shutting down box #{box.name} id: #{box.id}"
|
92
|
+
connect
|
93
|
+
@connection.servers.get(box.id).destroy
|
94
|
+
return true
|
95
|
+
end
|
96
|
+
return false
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Migrant
|
2
|
+
module Clouds
|
3
|
+
class Rackspace < Base
|
4
|
+
register 'rackspace'
|
5
|
+
|
6
|
+
def initialize(env)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def connect
|
11
|
+
@connection = Fog::Compute.new(:provider => 'Rackspace',
|
12
|
+
:rackspace_api_key => @environment.setting('provider.api_key'),
|
13
|
+
:rackspace_username => @environment.setting('provider.user_name'))
|
14
|
+
end
|
15
|
+
|
16
|
+
def log_server_info
|
17
|
+
super
|
18
|
+
@environment.ui.notice " Name: #{@environment.server.name}"
|
19
|
+
@environment.ui.notice " IP Address: #{@environment.server.addresses['public']}"
|
20
|
+
@environment.ui.notice " Image ID: #{@environment.server.image.name}"
|
21
|
+
@environment.ui.notice " Flavor: #{@environment.server.flavor.name}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|