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