vagrant-rackspace 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 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