ey-provisioner 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: