ey-provisioner 1.0.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,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3-p448@ey-provisioner --create
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ script: bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ey-provisioner.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Dan Draper
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,60 @@
1
+ # Ey::Provisioner
2
+
3
+ [![Build Status](https://api.travis-ci.org/coderdan/ey-provisioner.png)](https://travis-ci.org/coderdan/ey-provisioner)
4
+ [![Code Climate](https://codeclimate.com/github/coderdan/ey-provisioner.png)](https://codeclimate.com/github/coderdan/ey-provisioner)
5
+
6
+ The EY Provisioner is a Ruby based client gem for interacting with the [EngineYard](http://www.engineyard.com) Instance Provisioning V2 API.
7
+ See [this blog post](https://support.cloud.engineyard.com/entries/22498973-use-the-instance-provisioning-api-with-engine-yard-cloud "Engine Yard Instance Provisioning")
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'ey-provisioner'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install ey-provisioner
22
+
23
+ ## Usage
24
+
25
+ To use the ey-provisioner start by creating a connection:
26
+
27
+ connection = Ey::Provisioner::Connection.new(token)
28
+
29
+ Via the connection, you get the relevant environment:
30
+
31
+ env = connection.environment(1234)
32
+
33
+ On the connection you can now add or remove instances:
34
+
35
+ env.add_instance(:name => "my-instance", :role => "util", :instance_size => 'xlarge')
36
+ env.remove_instances(:role => "util") # Will shutdown all util servers
37
+
38
+ ### Getting your token
39
+
40
+ See [the EY docs](https://support.cloud.engineyard.com/entries/22498973-use-the-instance-provisioning-api-with-engine-yard-cloud "Engine Yard Instance Provisioning") for instructions on how to get your token.
41
+
42
+ ### Getting the environment ID
43
+
44
+ Within the EngineYard interface, click on the deployment history link within the Environment. The page's URL will be of the form .../environments/x/deployments. X will be the environment ID.
45
+
46
+ ## Limitations
47
+
48
+ The Gem does not currently support retrieving provisioning status nor does it allow you to list all environments for the account.
49
+
50
+ ## Documentation
51
+
52
+ Full documentation can be found [here](http://rubydoc.info/github/coderdan/ey-provisioner/master/frames).
53
+
54
+ ## Contributing
55
+
56
+ 1. Fork it
57
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
58
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
59
+ 4. Push to the branch (`git push origin my-new-feature`)
60
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ * Ability to get provisioning Status
2
+ * List all environments for a connection
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/ey-provisioner/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Dan Draper"]
6
+ gem.email = ["daniel@codehire.com"]
7
+ gem.description = %q{Ruby based client gem for interacting with the EngineYard Instance Provisioning API}
8
+ gem.summary = %q{Ruby based client gem for interacting with the EngineYard Instance Provisioning API}
9
+ gem.homepage = "https://github.com/coderdan/ey-provisioner"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "ey-provisioner"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Ey::Provisioner::VERSION
17
+
18
+ gem.add_dependency 'excon', ">= 0.25"
19
+ gem.add_dependency 'json'
20
+ gem.add_dependency 'activemodel', '>= 3.2'
21
+
22
+ gem.add_development_dependency 'pry'
23
+ gem.add_development_dependency 'yard'
24
+ gem.add_development_dependency 'redcarpet'
25
+ gem.add_development_dependency 'rspec'
26
+ gem.add_development_dependency 'mocha'
27
+ gem.add_development_dependency 'shoulda'
28
+ gem.add_development_dependency 'activesupport'
29
+ end
@@ -0,0 +1,16 @@
1
+ require 'excon'
2
+ require 'json'
3
+ require 'active_model'
4
+ require "ey-provisioner/api_error"
5
+ require "ey-provisioner/connection"
6
+ require "ey-provisioner/environment"
7
+ require "ey-provisioner/instance"
8
+ require "ey-provisioner/invalid_request"
9
+ require "ey-provisioner/request"
10
+ require "ey-provisioner/version"
11
+
12
+ module Ey
13
+ module Provisioner
14
+ # Your code goes here...
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module Ey
2
+ module Provisioner
3
+ class APIError < RuntimeError
4
+ attr_reader :errors, :request, :status
5
+
6
+ def initialize(error)
7
+ @error = error
8
+ parse_error
9
+ end
10
+
11
+ def message
12
+ if @status
13
+ "#{@status}: #{error_message}"
14
+ else
15
+ @error.message
16
+ end
17
+ end
18
+
19
+ # Specific EngineYard API error
20
+ def error_message
21
+ if @errors
22
+ @errors.map { |(k,v)|
23
+ "#{k} #{v.join(',')}"
24
+ }.join("; ")
25
+ end
26
+ end
27
+
28
+ private
29
+ def parse_error
30
+ if @error.respond_to?(:response) && @error.response.body.present?
31
+ body_hash = JSON(@error.response.body)
32
+ @status = body_hash.fetch('status', 'unknown')
33
+ @errors = body_hash['errors']
34
+ @request = body_hash['request']
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,47 @@
1
+ module Ey
2
+ module Provisioner
3
+ # Maintains a connection representation (stateless) to the EY API
4
+ # Supports V2 of the API
5
+ class Connection
6
+ EY_API_CLOUD_URL = "https://cloud.engineyard.com:443/"
7
+
8
+ # Create a connection
9
+ # @param token [String] the EY token
10
+ def initialize(token)
11
+ @token = token
12
+ @http = Excon.new(EY_API_CLOUD_URL)
13
+ end
14
+
15
+ # Get an environment instance
16
+ #
17
+ # @param id [Integer] the environment ID
18
+ # @return [Environment]
19
+ def environment(id)
20
+ Environment.new(self, id)
21
+ end
22
+
23
+ # Perform an API POST to the path
24
+ #
25
+ # @param path [String] the partial path (ie; everything after /api/v2/)
26
+ # @param request [Request] a request object
27
+ # @return [Excon::Response]
28
+ def http_post(path, request)
29
+ @http.post(
30
+ :body => JSON(:request => request.to_hash),
31
+ :headers => headers,
32
+ :path => "/api/v2/#{path}",
33
+ :expects => [200, 201, 202]
34
+ )
35
+ end
36
+
37
+ private
38
+ def headers
39
+ {
40
+ 'Accept' => 'application/json',
41
+ 'X-EY-Cloud-Token' => @token,
42
+ 'Content-type' => 'application/json'
43
+ }
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,45 @@
1
+ module Ey
2
+ module Provisioner
3
+ class Environment
4
+ def initialize(connection, env_id)
5
+ @connection = connection
6
+ @env_id = env_id
7
+ end
8
+
9
+ # Remove instances from the environment
10
+ #
11
+ # @param options [Hash] attributes to define what to remove (eg; name, role). See EY docs
12
+ def remove_instances(options = {})
13
+ process_post(path_for(:remove_instances), options)
14
+ end
15
+
16
+ # Add an instance to the environment
17
+ #
18
+ # @param options [Hash] attributes to define the server to add (eg; name, role). See EY docs
19
+ def add_instance(options = {})
20
+ process_post(path_for(:add_instances), options)
21
+ end
22
+
23
+ private
24
+ def path_for(which)
25
+ "environments/#{@env_id}/#{which}"
26
+ end
27
+
28
+ def api_error_handler
29
+ begin
30
+ yield if block_given?
31
+ rescue Excon::Errors::Error => e
32
+ raise APIError.new(e)
33
+ end
34
+ end
35
+
36
+ def process_post(path, options)
37
+ api_error_handler do
38
+ request = Request.new(options)
39
+ response = @connection.http_post(path, request)
40
+ Instance.new(JSON(response.body)['instance'])
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,41 @@
1
+ module Ey
2
+ module Provisioner
3
+ # Represents an EY instance
4
+ class Instance
5
+ attr_accessor :id
6
+ attr_accessor :amazon_id
7
+ attr_accessor :bootstrapped_at
8
+ attr_accessor :chef_status
9
+ attr_accessor :name
10
+ attr_accessor :private_hostname
11
+ attr_accessor :public_hostname
12
+ attr_accessor :role
13
+ attr_accessor :status
14
+
15
+ TYPES = %w(
16
+ small
17
+ small_64
18
+ medium_ram
19
+ medium_ram_64
20
+ medium_cpu
21
+ medium_cpu_64
22
+ large
23
+ xlarge
24
+ xlarge_cpu
25
+ xlarge_ram
26
+ doublexlarge_ram
27
+ quadxlarge_ram
28
+ quadxlarge_io
29
+ )
30
+
31
+ # Create an Instance representation
32
+ #
33
+ # @param attrs [Hash]
34
+ def initialize(attrs)
35
+ attrs.each do |(attr, value)|
36
+ send("#{attr}=", value)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,12 @@
1
+ module Ey
2
+ module Provisioner
3
+ class InvalidRequest < StandardError
4
+ attr_reader :request
5
+ def initialize(request)
6
+ @request = request
7
+ errors = @request.errors.full_messages.join(", ")
8
+ super("Invalid Request: #{errors}")
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,48 @@
1
+ module Ey
2
+ module Provisioner
3
+ # Implement the presenter pattern for API requests
4
+ class Request
5
+ include ActiveModel::Validations
6
+
7
+ attr_accessor :role
8
+ attr_accessor :name
9
+ attr_accessor :instance_size
10
+ attr_accessor :snapshot_id
11
+ attr_accessor :availability_zone
12
+ attr_reader :volume_size
13
+
14
+ validates :role,
15
+ :presence => true,
16
+ :inclusion => { :in => %w(app util) }
17
+
18
+ validates :instance_size,
19
+ :inclusion => { :in => Instance::TYPES },
20
+ :allow_nil => true
21
+
22
+ # Create a new request
23
+ #
24
+ # @param options [Hash]
25
+ def initialize(options = {})
26
+ options.each do |(attr,value)|
27
+ send("#{attr}=", value)
28
+ end
29
+ self.role ||= 'util'
30
+ end
31
+
32
+ def volume_size=(arg)
33
+ @volume_size = arg.to_s
34
+ end
35
+
36
+ # A hash representation of the request
37
+ def to_hash
38
+ raise InvalidRequest.new(self) if !valid?
39
+ {}.tap do |request|
40
+ request[:role] = self.role
41
+ [ :name, :instance_size, :volume_size, :snapshot_id, :availability_zone ].each do |attr|
42
+ request[attr] = send(attr) unless send(attr).nil?
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,5 @@
1
+ module Ey
2
+ module Provisioner
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ey::Provisioner::APIError do
4
+ subject { Ey::Provisioner::APIError.new(error) }
5
+
6
+ describe "standard error" do
7
+ let(:error) { stub("error", :message => "message") }
8
+ its(:message) { should == "message" }
9
+ end
10
+
11
+ describe "an HTTP error with a response" do
12
+ context "with a state" do
13
+ let(:body_hash) do
14
+ {
15
+ 'request' => {"role"=>"util", "volume_size"=>"2000"},
16
+ 'status' => 'rejected',
17
+ 'errors' => errors
18
+ }
19
+ end
20
+
21
+ context "with errors" do
22
+ let(:errors) { {"name"=>["can't be blank"]} }
23
+ let(:response) { stub("response", :body => JSON(body_hash)) }
24
+ let(:error) { stub("error", :message => "message", :response => response) }
25
+ its(:message) { should == "rejected: name can't be blank" }
26
+ its(:error_message) { should == "name can't be blank" }
27
+ its(:errors) { should == errors }
28
+ end
29
+
30
+ context "with no errors" do
31
+ let(:errors) { nil }
32
+ let(:response) { stub("response", :body => JSON(body_hash)) }
33
+ let(:error) { stub("error", :message => "message", :response => response) }
34
+ its(:message) { should == "rejected: " }
35
+ its(:error_message) { should be_nil }
36
+ its(:errors) { should be_nil }
37
+ end
38
+ end
39
+
40
+ context "with a state" do
41
+ let(:body_hash) do
42
+ {
43
+ 'request' => {"role"=>"util", "volume_size"=>"2000"},
44
+ 'errors' => errors
45
+ }
46
+ end
47
+
48
+ context "with errors" do
49
+ let(:errors) { {"name"=>["can't be blank"]} }
50
+ let(:response) { stub("response", :body => JSON(body_hash)) }
51
+ let(:error) { stub("error", :message => "message", :response => response) }
52
+ its(:message) { should == "unknown: name can't be blank" }
53
+ its(:error_message) { "name can't be blank" }
54
+ its(:errors) { errors }
55
+ end
56
+ end
57
+
58
+ context "with an empty string body" do
59
+ let(:errors) { nil }
60
+ let(:response) { stub("response", :body => "") }
61
+ let(:error) { stub("error", :message => "message", :response => response) }
62
+
63
+ its(:message) { should == "message" }
64
+ its(:error_message) { should be_nil }
65
+ its(:errors) { should be_nil }
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ey::Provisioner::Connection do
4
+ subject { Ey::Provisioner::Connection.new("tokenabc") }
5
+ let(:http) { stub('http') }
6
+ before { Excon.expects(:new).with(Ey::Provisioner::Connection::EY_API_CLOUD_URL).returns(http) }
7
+
8
+ let(:headers) do
9
+ {
10
+ 'Accept' => 'application/json',
11
+ 'X-EY-Cloud-Token' => 'tokenabc',
12
+ 'Content-type' => 'application/json'
13
+ }
14
+ end
15
+
16
+ describe "http_post" do
17
+ let(:request) { stub('request') }
18
+ before { request.expects(:to_hash).returns(:test => 'data') }
19
+
20
+ it "should post via HTTP to the API" do
21
+ http.expects(:post).with(
22
+ :body => JSON(:request => { :test => 'data' }),
23
+ :headers => headers,
24
+ :path => "/api/v2/testpath",
25
+ :expects => [200, 201, 202]
26
+ )
27
+
28
+ subject.http_post("testpath", request)
29
+ end
30
+ end
31
+
32
+ describe "environment" do
33
+ it "should return an environment instance" do
34
+ subject.environment(1234).should be_a(Ey::Provisioner::Environment)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ey::Provisioner::Environment do
4
+ before(:all) { Excon.defaults[:mock] = true }
5
+ let(:connection) { Ey::Provisioner::Connection.new("123456789") }
6
+ subject { Ey::Provisioner::Environment.new(connection, "1") }
7
+
8
+ describe "Add instance" do
9
+ let(:path) { 'environments/1/add_instances' }
10
+
11
+ context "an invalid server response" do
12
+ before { Excon.stub({:method => :post}, {:status => 500}) }
13
+
14
+ it "will throw an error" do
15
+ expect { subject.add_instance }.to raise_error(Ey::Provisioner::APIError)
16
+ end
17
+ end
18
+
19
+ context "valid server response" do
20
+ let(:response) { stub('response') }
21
+ let(:request) { stub('request') }
22
+ before { response.stubs(:body).returns(JSON('instance' => { 'id' => 1234 })) }
23
+
24
+ context "with default options" do
25
+ before { Ey::Provisioner::Request.expects(:new).with({}).returns(request) }
26
+
27
+ it "should post the data" do
28
+ connection.expects(:http_post).with(path, request).returns(response)
29
+ subject.add_instance
30
+ end
31
+
32
+ it "should return the instance" do
33
+ connection.expects(:http_post).with(path, request).returns(response)
34
+ subject.add_instance.should be_a(Ey::Provisioner::Instance)
35
+ end
36
+ end
37
+
38
+ context "with custom options" do
39
+ let(:options) { stub('options') }
40
+ before { Ey::Provisioner::Request.expects(:new).with(options).returns(request) }
41
+
42
+ it "should post the data" do
43
+ connection.expects(:http_post).with(path, request).returns(response)
44
+ subject.add_instance(options)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "Remove instances" do
51
+ let(:path) { 'environments/1/remove_instances' }
52
+
53
+ context "an invalid server response" do
54
+ before { Excon.stub({:method => :post}, {:status => 500}) }
55
+
56
+ it "will throw an error" do
57
+ expect { subject.remove_instances }.to raise_error(Ey::Provisioner::APIError)
58
+ end
59
+ end
60
+
61
+ context "valid server response" do
62
+ let(:response) { stub('response') }
63
+ let(:request) { stub('request') }
64
+ before { response.stubs(:body).returns(JSON('instance' => { 'id' => 1234 })) }
65
+
66
+ context "with default options" do
67
+ before { Ey::Provisioner::Request.expects(:new).with({}).returns(request) }
68
+
69
+ it "should post the data" do
70
+ connection.expects(:http_post).with(path, request).returns(response)
71
+ subject.remove_instances
72
+ end
73
+
74
+ it "should return the instance" do
75
+ connection.expects(:http_post).with(path, request).returns(response)
76
+ subject.remove_instances.should be_a(Ey::Provisioner::Instance)
77
+ end
78
+ end
79
+
80
+ context "with custom options" do
81
+ let(:options) { stub('options') }
82
+ before { Ey::Provisioner::Request.expects(:new).with(options).returns(request) }
83
+
84
+ it "should post the data" do
85
+ connection.expects(:http_post).with(path, request).returns(response)
86
+ subject.remove_instances(options)
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ey::Provisioner::Instance do
4
+ describe "initialize" do
5
+ let(:instance_attrs) do
6
+ {
7
+ "amazon_id" => "1234",
8
+ "bootstrapped_at" => "2013-01-01 12:00",
9
+ "chef_status" => [{"message"=>"Processing memcached", "timestamp"=>"2013-08-09T01:25:25+00:00"}],
10
+ "id" => 260323,
11
+ "name" => "dantest",
12
+ "private_hostname" => "privatehostname",
13
+ "public_hostname" => "publichostname",
14
+ "role" => "util",
15
+ "status" => "starting"
16
+ }
17
+ end
18
+
19
+ subject { Ey::Provisioner::Instance.new(instance_attrs) }
20
+ its(:amazon_id) { should == "1234" }
21
+ its(:id) { should == 260323 }
22
+ its(:bootstrapped_at) { should == "2013-01-01 12:00" }
23
+ its(:chef_status) { [{"message"=>"Processing memcached", "timestamp"=>"2013-08-09T01:25:25+00:00"}] }
24
+ its(:name) { should == 'dantest' }
25
+ its(:private_hostname) { should == 'privatehostname' }
26
+ its(:public_hostname) { should == 'publichostname' }
27
+ its(:role) { should == 'util' }
28
+ its(:status) { should == 'starting' }
29
+ end
30
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ey::Provisioner::Request do
4
+ it { should validate_presence_of(:role) }
5
+
6
+ it { should allow_value('app').for(:role) }
7
+ it { should allow_value('util').for(:role) }
8
+ it { should_not allow_value('db').for(:role) }
9
+
10
+ Ey::Provisioner::Instance::TYPES.each do |instance_type|
11
+ it { should allow_value(instance_type).for(:instance_size) }
12
+ end
13
+ it { should_not allow_value('another').for(:instance_size) }
14
+ it { should allow_value(nil).for(:instance_size) }
15
+
16
+ describe "initialize" do
17
+ context "all available attrs" do
18
+ let(:request) { Ey::Provisioner::Request.new(:name => "My Name", :role => "app") }
19
+ subject { request }
20
+ its(:name) { should == "My Name" }
21
+ its(:role) { should == "app" }
22
+ end
23
+
24
+ context "an unknown attr" do
25
+ it "should throw an error" do
26
+ expect { Ey::Provisioner::Request.new(:foo => "bar") }.to raise_error
27
+ end
28
+ end
29
+
30
+ describe "defaults" do
31
+ let(:request) { Ey::Provisioner::Request.new }
32
+ subject { request }
33
+ its(:role) { should == "util" }
34
+ end
35
+ end
36
+
37
+ describe "to_hash" do
38
+ subject { request.to_hash }
39
+
40
+ context "with valid data" do
41
+ context "with only defaults" do
42
+ let(:request) { Ey::Provisioner::Request.new }
43
+ it { should == { :role => 'util' } }
44
+ end
45
+
46
+ context "with a role" do
47
+ let(:request) { Ey::Provisioner::Request.new(:role => 'app') }
48
+ it { should == { :role => 'app' } }
49
+ end
50
+
51
+ context "with a name provided" do
52
+ let(:request) { Ey::Provisioner::Request.new(:name => "My Name") }
53
+ it { should == { :name => "My Name", :role => 'util' } }
54
+ end
55
+
56
+ context "with an instance size" do
57
+ let(:request) { Ey::Provisioner::Request.new(:instance_size => "small") }
58
+ it { should == { :instance_size => "small", :role => 'util' } }
59
+ end
60
+
61
+ context "with a volume_size" do
62
+ let(:request) { Ey::Provisioner::Request.new(:volume_size => 100) }
63
+ it { should == { :volume_size => "100", :role => 'util' } }
64
+ end
65
+
66
+ context "with a snapshot_id" do
67
+ let(:request) { Ey::Provisioner::Request.new(:snapshot_id => "snap-99999999") }
68
+ it { should == { :snapshot_id => "snap-99999999", :role => 'util' } }
69
+ end
70
+
71
+ context "with a availability_zone" do
72
+ let(:request) { Ey::Provisioner::Request.new(:availability_zone => "us-east-1a") }
73
+ it { should == { :availability_zone => "us-east-1a", :role => 'util' } }
74
+ end
75
+ end
76
+ end
77
+
78
+ context "with invalid data" do
79
+ let(:request) { Ey::Provisioner::Request.new(:role => "invalid role") }
80
+
81
+ it "should raise an error" do
82
+ expect { request.to_hash }.to raise_error(Ey::Provisioner::InvalidRequest, "Invalid Request: Role is not included in the list")
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,15 @@
1
+ require File.expand_path("../../lib/ey-provisioner", __FILE__)
2
+
3
+ Dir[File.expand_path("../../spec/support/**/*.rb", __FILE__)].each {|f| require f}
4
+
5
+ require 'active_support'
6
+ require 'active_support/core_ext/array/wrap'
7
+
8
+ require 'pry'
9
+ require 'mocha/api'
10
+ require 'shoulda'
11
+ require 'shoulda/matchers'
12
+
13
+ RSpec.configure do |config|
14
+ config.mock_with :mocha
15
+ end
metadata ADDED
@@ -0,0 +1,237 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ey-provisioner
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dan Draper
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-08-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: excon
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0.25'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0.25'
30
+ - !ruby/object:Gem::Dependency
31
+ name: json
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: activemodel
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '3.2'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '3.2'
62
+ - !ruby/object:Gem::Dependency
63
+ name: pry
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: yard
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: redcarpet
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: mocha
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: shoulda
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: activesupport
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ description: Ruby based client gem for interacting with the EngineYard Instance Provisioning
175
+ API
176
+ email:
177
+ - daniel@codehire.com
178
+ executables: []
179
+ extensions: []
180
+ extra_rdoc_files: []
181
+ files:
182
+ - .gitignore
183
+ - .rvmrc
184
+ - .travis.yml
185
+ - Gemfile
186
+ - LICENSE
187
+ - README.md
188
+ - Rakefile
189
+ - TODO
190
+ - ey-provisioner.gemspec
191
+ - lib/ey-provisioner.rb
192
+ - lib/ey-provisioner/api_error.rb
193
+ - lib/ey-provisioner/connection.rb
194
+ - lib/ey-provisioner/environment.rb
195
+ - lib/ey-provisioner/instance.rb
196
+ - lib/ey-provisioner/invalid_request.rb
197
+ - lib/ey-provisioner/request.rb
198
+ - lib/ey-provisioner/version.rb
199
+ - spec/api_error_spec.rb
200
+ - spec/connection_spec.rb
201
+ - spec/environment_spec.rb
202
+ - spec/instance_spec.rb
203
+ - spec/request_spec.rb
204
+ - spec/spec_helper.rb
205
+ homepage: https://github.com/coderdan/ey-provisioner
206
+ licenses: []
207
+ post_install_message:
208
+ rdoc_options: []
209
+ require_paths:
210
+ - lib
211
+ required_ruby_version: !ruby/object:Gem::Requirement
212
+ none: false
213
+ requirements:
214
+ - - ! '>='
215
+ - !ruby/object:Gem::Version
216
+ version: '0'
217
+ required_rubygems_version: !ruby/object:Gem::Requirement
218
+ none: false
219
+ requirements:
220
+ - - ! '>='
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ requirements: []
224
+ rubyforge_project:
225
+ rubygems_version: 1.8.25
226
+ signing_key:
227
+ specification_version: 3
228
+ summary: Ruby based client gem for interacting with the EngineYard Instance Provisioning
229
+ API
230
+ test_files:
231
+ - spec/api_error_spec.rb
232
+ - spec/connection_spec.rb
233
+ - spec/environment_spec.rb
234
+ - spec/instance_spec.rb
235
+ - spec/request_spec.rb
236
+ - spec/spec_helper.rb
237
+ has_rdoc: