vagrant-rackspace 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .vagrant
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ Vagrantfile
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # 0.1.0 (March 14, 2013)
2
+
3
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ # We depend on Vagrant for development, but we don't add it as a
7
+ # gem dependency because we expect to be installed within the
8
+ # Vagrant environment itself using `vagrant plugin`.
9
+ gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git"
10
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Mitchell Hashimoto
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # Vagrant RackSpace Cloud Provider
2
+
3
+ This is a [Vagrant](http://www.vagrantup.com) 1.1+ plugin that adds a
4
+ [RackSpace Cloud](http://www.rackspace.com/cloud) provider to Vagrant,
5
+ allowing Vagrant to control and provision machines within RackSpace
6
+ cloud.
7
+
8
+ **Note:** This plugin requires Vagrant 1.1+.
9
+
10
+ ## Features
11
+
12
+ * Boot Rackspace Cloud instances.
13
+ * SSH into the instances.
14
+ * Provision the instances with any built-in Vagrant provisioner.
15
+ * Minimal synced folder support via `rsync`.
16
+
17
+ ## Usage
18
+
19
+ Install using standard Vagrant 1.1+ plugin installation methods. After
20
+ installing, `vagrant up` and specify the `rackspace` provider. An example is
21
+ shown below.
22
+
23
+ ```
24
+ $ vagrant plugin install vagrant-rackspace
25
+ ...
26
+ $ vagrant up --provider=rackspace
27
+ ...
28
+ ```
29
+
30
+ Of course prior to doing this, you'll need to obtain an Rackspace-compatible
31
+ box file for Vagrant.
32
+
33
+ ## Quick Start
34
+
35
+ After installing the plugin (instructions above), the quickest way to get
36
+ started is to actually use a dummy Rackspace box and specify all the details
37
+ manually within a `config.vm.provider` block. So first, add the dummy
38
+ box using any name you want:
39
+
40
+ ```
41
+ $ vagrant box add dummy https://github.com/mitchellh/vagrant-rackspace/raw/master/dummy.box
42
+ ...
43
+ ```
44
+
45
+ And then make a Vagrantfile that looks like the following, filling in
46
+ your information where necessary.
47
+
48
+ ```
49
+ Vagrant.configure("2") do |config|
50
+ config.vm.box = "dummy"
51
+
52
+ config.vm.provider :rackspace do |rs|
53
+ rs.username = "YOUR USERNAME"
54
+ rs.api_key = "YOUR API KEY"
55
+ rs.flavor = /512MB/
56
+ rs.image = /Ubuntu/
57
+ end
58
+ end
59
+ ```
60
+
61
+ And then run `vagrant up --provider=rackspace`.
62
+
63
+ This will start an Ubuntu 12.04 instance in the DFW datacenter region within
64
+ your account. And assuming your SSH information was filled in properly
65
+ within your Vagrantfile, SSH and provisioning will work as well.
66
+
67
+ Note that normally a lot of this boilerplate is encoded within the box
68
+ file, but the box file used for the quick start, the "dummy" box, has
69
+ no preconfigured defaults.
70
+
71
+ ## Box Format
72
+
73
+ Every provider in Vagrant must introduce a custom box format. This
74
+ provider introduces `rackspace` boxes. You can view an example box in
75
+ the [example_box/ directory](https://github.com/mitchellh/vagrant-rackspace/tree/master/example_box).
76
+ That directory also contains instructions on how to build a box.
77
+
78
+ The box format is basically just the required `metadata.json` file
79
+ along with a `Vagrantfile` that does default settings for the
80
+ provider-specific configuration for this provider.
81
+
82
+ ## Configuration
83
+
84
+ This provider exposes quite a few provider-specific configuration options:
85
+
86
+ * `api_key` - The API key for accessing Rackspace.
87
+ * `flavor` - The server flavor to boot. This can be a string matching
88
+ the exact ID or name of the server, or this can be a regular expression
89
+ to partially match some server flavor.
90
+ * `image` - The server image to boot. This can be a string matching the
91
+ exact ID or name of the image, or this can be a regular expression to
92
+ partially match some image.
93
+ * `endpoint` - The endpoint to hit. By default this is DFW.
94
+ * `public_key_path` - The path to a public key to initialize with the remote
95
+ server. This should be the matching pair for the private key configured
96
+ with `config.ssh.private_key_path` on Vagrant.
97
+ * `server_name` - The name of the server within RackSpace Cloud. This
98
+ defaults to the name of the Vagrant machine (via `config.vm.define`), but
99
+ can be overridden with this.
100
+ * `username` - The username with which to access Rackspace.
101
+
102
+ These can be set like typical provider-specific configuration:
103
+
104
+ ```ruby
105
+ Vagrant.configure("2") do |config|
106
+ # ... other stuff
107
+
108
+ config.vm.provider :rackspace do |rs|
109
+ rs.username = "mitchellh"
110
+ rs.api_key = "foobarbaz"
111
+ end
112
+ end
113
+ ```
114
+
115
+ ## Networks
116
+
117
+ Networking features in the form of `config.vm.network` are not
118
+ supported with `vagrant-rackspace`, currently. If any of these are
119
+ specified, Vagrant will emit a warning, but will otherwise boot
120
+ the Rackspace server.
121
+
122
+ ## Synced Folders
123
+
124
+ There is minimal support for synced folders. Upon `vagrant up`,
125
+ `vagrant reload`, and `vagrant provision`, the Rackspace provider will use
126
+ `rsync` (if available) to uni-directionally sync the folder to
127
+ the remote machine over SSH.
128
+
129
+ This is good enough for all built-in Vagrant provisioners (shell,
130
+ chef, and puppet) to work!
131
+
132
+ ## Development
133
+
134
+ To work on the `vagrant-rackspace` plugin, clone this repository out, and use
135
+ [Bundler](http://gembundler.com) to get the dependencies:
136
+
137
+ ```
138
+ $ bundle
139
+ ```
140
+
141
+ Once you have the dependencies, verify the unit tests pass with `rake`:
142
+
143
+ ```
144
+ $ bundle exec rake
145
+ ```
146
+
147
+ If those pass, you're ready to start developing the plugin. You can test
148
+ the plugin without installing it into your Vagrant environment by just
149
+ creating a `Vagrantfile` in the top level of this directory (it is gitignored)
150
+ that uses it, and uses bundler to execute Vagrant:
151
+
152
+ ```
153
+ $ bundle exec vagrant up --provider=rackspace
154
+ ```
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rspec/core/rake_task'
4
+
5
+ # Immediately sync all stdout so that tools like buildbot can
6
+ # immediately load in the output.
7
+ $stdout.sync = true
8
+ $stderr.sync = true
9
+
10
+ # Change to the directory of this file.
11
+ Dir.chdir(File.expand_path("../", __FILE__))
12
+
13
+ # This installs the tasks that help with gem creation and
14
+ # publishing.
15
+ Bundler::GemHelper.install_tasks
16
+
17
+ # Install the `spec` task so that we can run tests.
18
+ RSpec::Core::RakeTask.new
19
+
20
+ # Default task is to run the unit tests
21
+ task :default => "spec"
data/dummy.box ADDED
Binary file
@@ -0,0 +1,13 @@
1
+ # Vagrant RackSpace Cloud Example Box
2
+
3
+ Vagrant providers each require a custom provider-specific box format.
4
+ This folder shows the example contents of a box for the `rackspace` provider.
5
+ To turn this into a box:
6
+
7
+ ```
8
+ $ tar cvzf rackspace.box ./metadata.json ./Vagrantfile
9
+ ```
10
+
11
+ This box works by using Vagrant's built-in Vagrantfile merging to setup
12
+ defaults for RackSpace. These defaults can easily be overwritten by higher-level
13
+ Vagrantfiles (such as project root Vagrantfiles).
@@ -0,0 +1,3 @@
1
+ {
2
+ "provider": "rackspace"
3
+ }
@@ -0,0 +1,53 @@
1
+ require "pathname"
2
+
3
+ require "vagrant-rackspace/plugin"
4
+
5
+ module VagrantPlugins
6
+ module Rackspace
7
+ lib_path = Pathname.new(File.expand_path("../vagrant-rackspace", __FILE__))
8
+ autoload :Errors, lib_path.join("errors")
9
+
10
+ # This initializes the i18n load path so that the plugin-specific
11
+ # translations work.
12
+ def self.init_i18n
13
+ I18n.load_path << File.expand_path("locales/en.yml", source_root)
14
+ I18n.reload!
15
+ end
16
+
17
+ # This initializes the logging so that our logs are outputted at
18
+ # the same level as Vagrant core logs.
19
+ def self.init_logging
20
+ # Initialize logging
21
+ level = nil
22
+ begin
23
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
24
+ rescue NameError
25
+ # This means that the logging constant wasn't found,
26
+ # which is fine. We just keep `level` as `nil`. But
27
+ # we tell the user.
28
+ level = nil
29
+ end
30
+
31
+ # Some constants, such as "true" resolve to booleans, so the
32
+ # above error checking doesn't catch it. This will check to make
33
+ # sure that the log level is an integer, as Log4r requires.
34
+ level = nil if !level.is_a?(Integer)
35
+
36
+ # Set the logging level on all "vagrant" namespaced
37
+ # logs as long as we have a valid level.
38
+ if level
39
+ logger = Log4r::Logger.new("vagrant_rackspace")
40
+ logger.outputters = Log4r::Outputter.stderr
41
+ logger.level = level
42
+ logger = nil
43
+ end
44
+ end
45
+
46
+ # This returns the path to the source of this plugin.
47
+ #
48
+ # @return [Pathname]
49
+ def self.source_root
50
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,95 @@
1
+ require "pathname"
2
+
3
+ require "vagrant/action/builder"
4
+
5
+ module VagrantPlugins
6
+ module Rackspace
7
+ module Action
8
+ # Include the built-in modules so we can use them as top-level things.
9
+ include Vagrant::Action::Builtin
10
+
11
+ # This action is called to destroy the remote machine.
12
+ def self.action_destroy
13
+ Vagrant::Action::Builder.new.tap do |b|
14
+ b.use ConfigValidate
15
+ b.use Call, IsCreated do |env, b2|
16
+ if !env[:result]
17
+ b2.use MessageNotCreated
18
+ next
19
+ end
20
+
21
+ b2.use ConnectRackspace
22
+ b2.use DeleteServer
23
+ end
24
+ end
25
+ end
26
+
27
+ # This action is called to read the SSH info of the machine. The
28
+ # resulting state is expected to be put into the `:machine_ssh_info`
29
+ # key.
30
+ def self.action_read_ssh_info
31
+ Vagrant::Action::Builder.new.tap do |b|
32
+ b.use ConfigValidate
33
+ b.use ConnectRackspace
34
+ b.use ReadSSHInfo
35
+ end
36
+ end
37
+
38
+ # This action is called to read the state of the machine. The
39
+ # resulting state is expected to be put into the `:machine_state_id`
40
+ # key.
41
+ def self.action_read_state
42
+ Vagrant::Action::Builder.new.tap do |b|
43
+ b.use ConfigValidate
44
+ b.use ConnectRackspace
45
+ b.use ReadState
46
+ end
47
+ end
48
+
49
+ def self.action_ssh
50
+ Vagrant::Action::Builder.new.tap do |b|
51
+ b.use ConfigValidate
52
+ b.use Call, IsCreated do |env, b2|
53
+ if !env[:result]
54
+ b2.use MessageNotCreated
55
+ next
56
+ end
57
+
58
+ b2.use SSHExec
59
+ end
60
+ end
61
+ end
62
+
63
+ def self.action_up
64
+ Vagrant::Action::Builder.new.tap do |b|
65
+ b.use ConfigValidate
66
+ b.use Call, IsCreated do |env, b2|
67
+ if env[:result]
68
+ b2.use MessageAlreadyCreated
69
+ next
70
+ end
71
+
72
+ b2.use ConnectRackspace
73
+ b2.use Provision
74
+ b2.use SyncFolders
75
+ b2.use WarnNetworks
76
+ b2.use CreateServer
77
+ end
78
+ end
79
+ end
80
+
81
+ # The autoload farm
82
+ action_root = Pathname.new(File.expand_path("../action", __FILE__))
83
+ autoload :ConnectRackspace, action_root.join("connect_rackspace")
84
+ autoload :CreateServer, action_root.join("create_server")
85
+ autoload :DeleteServer, action_root.join("delete_server")
86
+ autoload :IsCreated, action_root.join("is_created")
87
+ autoload :MessageAlreadyCreated, action_root.join("message_already_created")
88
+ autoload :MessageNotCreated, action_root.join("message_not_created")
89
+ autoload :ReadSSHInfo, action_root.join("read_ssh_info")
90
+ autoload :ReadState, action_root.join("read_state")
91
+ autoload :SyncFolders, action_root.join("sync_folders")
92
+ autoload :WarnNetworks, action_root.join("warn_networks")
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,37 @@
1
+ require "fog"
2
+ require "log4r"
3
+
4
+ module VagrantPlugins
5
+ module Rackspace
6
+ module Action
7
+ # This action connects to Rackspace, verifies credentials work, and
8
+ # puts the Rackspace connection object into the `:rackspace_compute` key
9
+ # in the environment.
10
+ class ConnectRackspace
11
+ def initialize(app, env)
12
+ @app = app
13
+ @logger = Log4r::Logger.new("vagrant_rackspace::action::connect_rackspace")
14
+ end
15
+
16
+ def call(env)
17
+ # Get the configs
18
+ config = env[:machine].provider_config
19
+ api_key = config.api_key
20
+ endpoint = config.endpoint
21
+ username = config.username
22
+
23
+ @logger.info("Connecting to Rackspace...")
24
+ env[:rackspace_compute] = Fog::Compute.new({
25
+ :provider => :rackspace,
26
+ :version => :v2,
27
+ :rackspace_api_key => api_key,
28
+ :rackspace_endpoint => endpoint,
29
+ :rackspace_username => username
30
+ })
31
+
32
+ @app.call(env)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end