appfirst 0.0.1
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 +17 -0
- data/Gemfile +11 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/appfirst.gemspec +27 -0
- data/lib/appfirst.rb +14 -0
- data/lib/appfirst/client.rb +132 -0
- data/lib/appfirst/collection.rb +58 -0
- data/lib/appfirst/logger.rb +31 -0
- data/lib/appfirst/models/server.rb +20 -0
- data/lib/appfirst/models/server_tag.rb +19 -0
- data/lib/appfirst/models/server_tags.rb +10 -0
- data/lib/appfirst/requests/create_server_tag.rb +33 -0
- data/lib/appfirst/response.rb +41 -0
- data/lib/appfirst/version.rb +3 -0
- data/spec/server_tags_spec.rb +16 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/client_helper.rb +15 -0
- metadata +150 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Josh Lane & Thom Mahoney
|
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,29 @@
|
|
1
|
+
# Appfirst
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'appfirst'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install appfirst
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it ( http://github.com/<my-github-username>/appfirst/fork )
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/appfirst.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'appfirst/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "appfirst"
|
8
|
+
spec.version = Appfirst::VERSION
|
9
|
+
spec.authors = ["Josh Lane & Thom Mahoney"]
|
10
|
+
spec.email = ["jlane@engineyard.com"]
|
11
|
+
spec.summary = %q{A ruby client for the AppFirst API}
|
12
|
+
spec.description = ""
|
13
|
+
spec.homepage = "http://github.com/engineyard/appfirst"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "faraday", "~> 0.8.9"
|
22
|
+
spec.add_dependency "faraday_middleware"
|
23
|
+
spec.add_dependency "cistern", "~> 0.2.3"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
end
|
data/lib/appfirst.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "appfirst/version"
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'faraday'
|
5
|
+
require 'faraday_middleware'
|
6
|
+
require 'cistern'
|
7
|
+
|
8
|
+
module Appfirst
|
9
|
+
require 'appfirst/collection'
|
10
|
+
require 'appfirst/logger'
|
11
|
+
require 'appfirst/response'
|
12
|
+
|
13
|
+
require 'appfirst/client'
|
14
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
class Appfirst::Client < Cistern::Service
|
2
|
+
model_path "appfirst/models"
|
3
|
+
request_path "appfirst/requests"
|
4
|
+
|
5
|
+
#collection :servers
|
6
|
+
collection :server_tags
|
7
|
+
|
8
|
+
model :server
|
9
|
+
model :server_tag
|
10
|
+
|
11
|
+
request :create_server_tag
|
12
|
+
#request :get_server
|
13
|
+
#request :get_server_tags
|
14
|
+
#request :get_servers
|
15
|
+
#request :get_servers_tags
|
16
|
+
#request :get_tag_servers
|
17
|
+
#request :set_servers_tags
|
18
|
+
|
19
|
+
recognizes :url, :logger, :adapter, :connection_options, :user, :password, :path
|
20
|
+
|
21
|
+
module Shared
|
22
|
+
attr_reader :url, :user, :path
|
23
|
+
|
24
|
+
def setup(options)
|
25
|
+
@url = options[:url] || ENV["APPFIRST_URL"] || "https://engineyard.appfirst.com"
|
26
|
+
@path = options[:path] || "/api/v3"
|
27
|
+
|
28
|
+
# For auth
|
29
|
+
@user = options[:user]
|
30
|
+
@password = options[:password]
|
31
|
+
|
32
|
+
@logger = options[:logger] || Logger.new(nil)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Real
|
37
|
+
include Shared
|
38
|
+
|
39
|
+
def initialize(options={})
|
40
|
+
setup(options)
|
41
|
+
adapter = options[:adapter] || Faraday.default_adapter
|
42
|
+
connection_options = options[:connection_options] || {ssl: {verify: false}}
|
43
|
+
|
44
|
+
@connection = Faraday.new({url: @url}.merge(connection_options)) do |builder|
|
45
|
+
builder.basic_auth @user, @password
|
46
|
+
builder.request :url_encoded
|
47
|
+
builder.response :json, content_type: /\bjson$/
|
48
|
+
builder.adapter adapter
|
49
|
+
builder.request :retry, max: 10, interval: 0.05, interval_randomness: 0.5, backoff_factor: 2
|
50
|
+
|
51
|
+
builder.use Appfirst::Logger, @logger
|
52
|
+
|
53
|
+
builder.adapter *adapter
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def request(method, request_path, params = nil)
|
58
|
+
response = @connection.send(method) do |req|
|
59
|
+
req.url(File.join(@url, path, request_path, "/"))
|
60
|
+
req.params.merge!(params)
|
61
|
+
end
|
62
|
+
|
63
|
+
Appfirst::Response.new(response.status, response.headers, response.body).raise!
|
64
|
+
end
|
65
|
+
end # Real
|
66
|
+
|
67
|
+
class Mock
|
68
|
+
include Shared
|
69
|
+
|
70
|
+
def self.data
|
71
|
+
@data ||= Hash.new do |h,k|
|
72
|
+
{
|
73
|
+
:servers => {},
|
74
|
+
:server_tags => {},
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def data
|
80
|
+
self.class.data[self.url]
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.reset!
|
84
|
+
@data = nil
|
85
|
+
@serial_id = 0
|
86
|
+
end
|
87
|
+
|
88
|
+
def initialize(options={})
|
89
|
+
setup(options)
|
90
|
+
end
|
91
|
+
|
92
|
+
def response(options={})
|
93
|
+
status = options[:status] || 200
|
94
|
+
body = options[:body]
|
95
|
+
headers = {
|
96
|
+
"Content-Type" => "application/json; charset=utf-8"
|
97
|
+
}.merge(options[:headers] || {})
|
98
|
+
|
99
|
+
Appfirst::Response.new(status, headers, body).raise!
|
100
|
+
end
|
101
|
+
|
102
|
+
def url_for(path)
|
103
|
+
File.join(@url.to_s, path.to_s)
|
104
|
+
end
|
105
|
+
|
106
|
+
def stringify_keys(hash)
|
107
|
+
hash.is_a?(Hash) ? hash.inject({}){|r,(k,v)| r.merge(k.to_s => stringify_keys(v))} : hash
|
108
|
+
end
|
109
|
+
|
110
|
+
def resource_uri(fragment)
|
111
|
+
File.join(path, fragment)
|
112
|
+
end
|
113
|
+
|
114
|
+
def require_parameter(params, param, options={})
|
115
|
+
if value = params[param]
|
116
|
+
value
|
117
|
+
else
|
118
|
+
errors = [{"message" => (options[:message] || "Missing parameter: #{param}"), "code" => (options[:code] || -1)}]
|
119
|
+
|
120
|
+
response(
|
121
|
+
:body => {"errors" => errors},
|
122
|
+
:status => 400,
|
123
|
+
)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def serial_id
|
128
|
+
@@serial_id ||= 0
|
129
|
+
@@serial_id += 1
|
130
|
+
end
|
131
|
+
end # Mock
|
132
|
+
end # Appfirst::Client
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Appfirst::Collection
|
2
|
+
def self.included(klass)
|
3
|
+
klass.attribute :next_link
|
4
|
+
klass.attribute :prev_link
|
5
|
+
klass.attribute :last_link
|
6
|
+
klass.attribute :total_count
|
7
|
+
klass.attribute :url
|
8
|
+
klass.send(:extend, Appfirst::Collection::Attributes)
|
9
|
+
end
|
10
|
+
|
11
|
+
module Attributes
|
12
|
+
attr_accessor :model_root, :model_request, :collection_root, :collection_request
|
13
|
+
end
|
14
|
+
|
15
|
+
def create!(*args)
|
16
|
+
model = self.new(*args)
|
17
|
+
model.save!
|
18
|
+
end
|
19
|
+
|
20
|
+
def model_root
|
21
|
+
self.class.model_root
|
22
|
+
end
|
23
|
+
|
24
|
+
def model_request
|
25
|
+
self.class.model_request
|
26
|
+
end
|
27
|
+
|
28
|
+
def get(id)
|
29
|
+
if data = connection.send(self.model_request, "id" => id).body[self.model_root]
|
30
|
+
new(data)
|
31
|
+
else
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
rescue Appfirst::Response::NotFound
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def collection_root
|
39
|
+
self.class.instance_variable_get(:@collection_root)
|
40
|
+
end
|
41
|
+
|
42
|
+
def collection_request
|
43
|
+
self.class.instance_variable_get(:@collection_request)
|
44
|
+
end
|
45
|
+
|
46
|
+
def ==(comparison_object)
|
47
|
+
comparison_object.equal?(self) ||
|
48
|
+
(comparison_object.is_a?(self.class) &&
|
49
|
+
comparison_object.map(&:identity) == self.map(&:identity))
|
50
|
+
end
|
51
|
+
|
52
|
+
def all(params={})
|
53
|
+
params["url"] ||= self.url
|
54
|
+
|
55
|
+
response = self.connection.send(self.collection_request, params)
|
56
|
+
load_page(response)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Appfirst::Logger < Faraday::Response::Middleware
|
2
|
+
extend Forwardable
|
3
|
+
|
4
|
+
def initialize(app, logger = nil)
|
5
|
+
super(app)
|
6
|
+
@logger = logger || ::Logger.new(nil)
|
7
|
+
end
|
8
|
+
|
9
|
+
def_delegators :@logger, :debug, :info, :warn, :error, :fatal
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
info "REQUEST: #{env[:method].upcase} #{env[:url].to_s}"
|
13
|
+
info('request') { dump_headers env[:request_headers] }
|
14
|
+
info('request.body') { env[:body] } if (env[:request_headers]["Accept"] || "").match("application/json")
|
15
|
+
info('')
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_complete(env)
|
20
|
+
info "RESPONSE: #{env[:status]}"
|
21
|
+
info('response') { dump_headers env[:response_headers] }
|
22
|
+
info('response.body') { env[:body] } if (env[:response_headers]["Content-Type"] || "").match("application/json")
|
23
|
+
info('')
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def dump_headers(headers)
|
29
|
+
headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Appfirst::Client::Server < Cistern::Model
|
2
|
+
identity :id, type: :integer # (read-only) Unique server ID.
|
3
|
+
|
4
|
+
attribute :architecture, type: :string # (read-only) The architecture of the server.
|
5
|
+
attribute :capacity_cpu_freq, type: :integer # (read-only) The frequency of the CPU in MHz.
|
6
|
+
attribute :capacity_cpu_num, type: :integer # (read-only) The number of CPU cores on the system.
|
7
|
+
attribute :capacity_disks # (read-only) Mapping of the names of the disks (mount points) to their capacity in MB.
|
8
|
+
attribute :capacity_mem, type: :integer # (read-only) The total available memory on the server in bytes.
|
9
|
+
attribute :created, type: :integer # (read-only) The time the server was created in UTC seconds.
|
10
|
+
attribute :current_version, type: :string # (read-only) Version of AppFirst collector that’s running on the server.
|
11
|
+
attribute :description, type: :string # The user-defined description of the server.
|
12
|
+
attribute :distribution, type: :string # (read-only) The OS distribution e.g. Ubuntu, RedHat.
|
13
|
+
attribute :hostname, type: :string # (read-only) The hostname for this server.
|
14
|
+
attribute :kernel_version, type: :string # (read-only) The specific kernel version of the server’s OS.
|
15
|
+
attribute :location_ip, type: :string # (read-only) IP address that collector is uploading from.
|
16
|
+
attribute :nickname, type: :string # The user-defined nickname of the server.
|
17
|
+
attribute :os, type: :string # (read-only) The OS for this server, either Windows or Linux.
|
18
|
+
attribute :resource_uri, type: :string # (read-only) The URI to get more information about this item.
|
19
|
+
attribute :running, type: :boolean # (read-only) Boolean indicating whether the server is currently uploading data to AppFirst.
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Appfirst::Client::ServerTag < Cistern::Model
|
2
|
+
identity :id, type: :integer # (read-only) Unique server tag ID.
|
3
|
+
|
4
|
+
attribute :name, type: :string # The name of the server tag.
|
5
|
+
attribute :resource_uri, type: :string # (read-only) The URI to get more information about this item.
|
6
|
+
attribute :server_ids, type: :array, aliases: ['servers'] # IDs of servers that belong to this server tag.
|
7
|
+
|
8
|
+
def servers
|
9
|
+
self.server_ids.map { |server_id| self.connection.servers.get(server_id) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def save
|
13
|
+
if new_record?
|
14
|
+
self.collection.new(self.connection.create_server_tag(Cistern::Hash.slice(self.attributes, :name, :servers)).body)
|
15
|
+
else
|
16
|
+
raise NotImplementedError # update tag
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Appfirst::Client::ServerTags < Cistern::Collection
|
2
|
+
include Appfirst::Collection
|
3
|
+
|
4
|
+
model Appfirst::Client::ServerTag
|
5
|
+
|
6
|
+
self.model_root = "server_tags"
|
7
|
+
self.model_request = :get_server_tag
|
8
|
+
self.collection_root = "server_tags"
|
9
|
+
self.collection_request = :get_server_tags
|
10
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Appfirst::Client
|
2
|
+
class Real
|
3
|
+
def create_server_tag(params={})
|
4
|
+
request(:post, "/server_tags", params)
|
5
|
+
end
|
6
|
+
end # Real
|
7
|
+
|
8
|
+
class Mock
|
9
|
+
def create_server_tag(params={})
|
10
|
+
identity = self.serial_id
|
11
|
+
|
12
|
+
name = require_parameter(params, :name, code: 5, message: "Invalid server tag name, name must be provided") # {"errors"=>[{"message"=>"Invalid server tag name, name must be provided", "code"=>5}]}
|
13
|
+
servers = params[:servers] || []
|
14
|
+
|
15
|
+
response_hash = {
|
16
|
+
:id => identity,
|
17
|
+
:name => name,
|
18
|
+
:servers => servers,
|
19
|
+
:resource_uri => resource_uri("/server_tags/#{identity}")
|
20
|
+
}
|
21
|
+
|
22
|
+
self.data[:server_tags][identity] = response_hash
|
23
|
+
|
24
|
+
response(
|
25
|
+
:body => response_hash,
|
26
|
+
:status => 200,
|
27
|
+
:headers => {
|
28
|
+
"Content-Type" => "application/json; charset=utf8"
|
29
|
+
}
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end # Mock
|
33
|
+
end # Appfirst::Client
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Appfirst::Response
|
2
|
+
class Error < StandardError
|
3
|
+
attr_reader :response
|
4
|
+
|
5
|
+
def initialize(response)
|
6
|
+
@response = response
|
7
|
+
super({status: response.status, headers: response.headers, body: response.body}.inspect)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
BadRequest = Class.new(Error)
|
12
|
+
NotFound = Class.new(Error)
|
13
|
+
Unprocessable = Class.new(Error)
|
14
|
+
Conflict = Class.new(Error)
|
15
|
+
Unexpected = Class.new(Error)
|
16
|
+
|
17
|
+
EXCEPTION_MAPPING = {
|
18
|
+
400 => BadRequest,
|
19
|
+
404 => NotFound,
|
20
|
+
409 => Conflict,
|
21
|
+
422 => Unprocessable,
|
22
|
+
500 => Unexpected,
|
23
|
+
}
|
24
|
+
|
25
|
+
attr_reader :headers, :status, :body
|
26
|
+
|
27
|
+
def initialize(status, headers, body)
|
28
|
+
@status, @headers, @body = status, headers, body
|
29
|
+
end
|
30
|
+
|
31
|
+
def successful?
|
32
|
+
self.status < 300 && self.status > 199 || self.status == 304
|
33
|
+
end
|
34
|
+
|
35
|
+
def raise!
|
36
|
+
if !successful?
|
37
|
+
raise (EXCEPTION_MAPPING[self.status] || Error).new(self)
|
38
|
+
else self
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "server_tags" do
|
4
|
+
let!(:client) { create_client }
|
5
|
+
|
6
|
+
it "should create a server tag" do
|
7
|
+
name = "josh"
|
8
|
+
|
9
|
+
server_tag = client.server_tags.create(name: name)
|
10
|
+
server_tag.name.should == name
|
11
|
+
server_tag.resource_uri.should_not be_nil
|
12
|
+
server_tag.server_ids.should be_empty
|
13
|
+
|
14
|
+
server_tag.servers.should be_empty
|
15
|
+
end
|
16
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
ENV['MOCK_APPFIRST'] ||= 'true'
|
2
|
+
ENV['APPFIRST_URL'] ||= "http://appfirst.localdev.engineyard.com:3000"
|
3
|
+
|
4
|
+
Bundler.require(:test)
|
5
|
+
|
6
|
+
require File.expand_path("../../lib/appfirst", __FILE__)
|
7
|
+
Dir[File.expand_path("../{shared,support}/*.rb", __FILE__)].each{|f| require(f)}
|
8
|
+
|
9
|
+
Cistern.formatter = Cistern::Formatter::AwesomePrint
|
10
|
+
|
11
|
+
if ENV['MOCK_APPFIRST'] == 'true'
|
12
|
+
Cistern.timeout = 0
|
13
|
+
Appfirst::Client.mock!
|
14
|
+
else
|
15
|
+
Cistern.timeout = 10
|
16
|
+
end
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.order = :random
|
20
|
+
|
21
|
+
config.before(:each) do
|
22
|
+
Appfirst::Client.mocking? && Appfirst::Client.reset!
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ClientHelper
|
2
|
+
def create_client(attributes={})
|
3
|
+
user = ENV["APPFIRST_USER"] || attributes[:user] || "engineyard"
|
4
|
+
password = ENV["APPFIRST_PASSWORD"] || attributes[:password] || "dontworryaboutit"
|
5
|
+
|
6
|
+
merged_attributes = {user: user, password: password}
|
7
|
+
merged_attributes.merge!(logger: Logger.new(STDOUT)) if ENV['VERBOSE']
|
8
|
+
|
9
|
+
Appfirst::Client.new(merged_attributes)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.include(ClientHelper)
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: appfirst
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Josh Lane & Thom Mahoney
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-01-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: faraday
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.8.9
|
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.8.9
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: faraday_middleware
|
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: cistern
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.2.3
|
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: 0.2.3
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: bundler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.5'
|
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: '1.5'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rake
|
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
|
+
description: ''
|
95
|
+
email:
|
96
|
+
- jlane@engineyard.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- Gemfile
|
103
|
+
- Guardfile
|
104
|
+
- LICENSE.txt
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- appfirst.gemspec
|
108
|
+
- lib/appfirst.rb
|
109
|
+
- lib/appfirst/client.rb
|
110
|
+
- lib/appfirst/collection.rb
|
111
|
+
- lib/appfirst/logger.rb
|
112
|
+
- lib/appfirst/models/server.rb
|
113
|
+
- lib/appfirst/models/server_tag.rb
|
114
|
+
- lib/appfirst/models/server_tags.rb
|
115
|
+
- lib/appfirst/requests/create_server_tag.rb
|
116
|
+
- lib/appfirst/response.rb
|
117
|
+
- lib/appfirst/version.rb
|
118
|
+
- spec/server_tags_spec.rb
|
119
|
+
- spec/spec_helper.rb
|
120
|
+
- spec/support/client_helper.rb
|
121
|
+
homepage: http://github.com/engineyard/appfirst
|
122
|
+
licenses:
|
123
|
+
- MIT
|
124
|
+
post_install_message:
|
125
|
+
rdoc_options: []
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
requirements: []
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 1.8.23
|
143
|
+
signing_key:
|
144
|
+
specification_version: 3
|
145
|
+
summary: A ruby client for the AppFirst API
|
146
|
+
test_files:
|
147
|
+
- spec/server_tags_spec.rb
|
148
|
+
- spec/spec_helper.rb
|
149
|
+
- spec/support/client_helper.rb
|
150
|
+
has_rdoc:
|