dyndrop 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1277 -0
- data/lib/dyndrop.rb +2 -0
- data/lib/dyndrop/auth_token.rb +63 -0
- data/lib/dyndrop/baseclient.rb +178 -0
- data/lib/dyndrop/client.rb +18 -0
- data/lib/dyndrop/errors.rb +152 -0
- data/lib/dyndrop/rest_client.rb +299 -0
- data/lib/dyndrop/trace_helpers.rb +40 -0
- data/lib/dyndrop/v1/base.rb +28 -0
- data/lib/dyndrop/v1/client.rb +114 -0
- data/lib/dyndrop/v1/model_magic.rb +129 -0
- data/lib/dyndrop/validator.rb +39 -0
- data/lib/dyndrop/version.rb +1 -1
- metadata +13 -1
@@ -0,0 +1,40 @@
|
|
1
|
+
require "net/https"
|
2
|
+
require "multi_json"
|
3
|
+
|
4
|
+
module Dyndrop
|
5
|
+
module TraceHelpers
|
6
|
+
|
7
|
+
def request_trace(request)
|
8
|
+
return nil unless request
|
9
|
+
info = ["REQUEST: #{request[:method]} #{request[:url]}"]
|
10
|
+
info << "REQUEST_HEADERS:"
|
11
|
+
info << header_trace(request[:headers])
|
12
|
+
info << "REQUEST_BODY: #{request[:body]}" if request[:body]
|
13
|
+
info.join("\n")
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def response_trace(response)
|
18
|
+
return nil unless response
|
19
|
+
info = ["RESPONSE: [#{response[:status]}]"]
|
20
|
+
info << "RESPONSE_HEADERS:"
|
21
|
+
info << header_trace(response[:headers])
|
22
|
+
info << "RESPONSE_BODY:"
|
23
|
+
begin
|
24
|
+
parsed_body = MultiJson.load(response[:body])
|
25
|
+
info << MultiJson.dump(parsed_body, :pretty => true)
|
26
|
+
rescue
|
27
|
+
info << "#{response[:body]}"
|
28
|
+
end
|
29
|
+
info.join("\n")
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def header_trace(headers)
|
35
|
+
headers.sort.map do |key, value|
|
36
|
+
" #{key} : #{value}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "multi_json"
|
2
|
+
require "tmpdir"
|
3
|
+
|
4
|
+
require "dyndrop/baseclient"
|
5
|
+
|
6
|
+
require "dyndrop/errors"
|
7
|
+
|
8
|
+
module Dyndrop::V1
|
9
|
+
class Base < Dyndrop::BaseClient
|
10
|
+
|
11
|
+
def get_token(email, payload)
|
12
|
+
post("1", "users", email, "tokens", :content => :json, :accept => :json, :payload => payload)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Users
|
16
|
+
def create_user(payload)
|
17
|
+
# no JSON response
|
18
|
+
post("users", :content => :json, :payload => payload)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Applications
|
22
|
+
def instances(name)
|
23
|
+
get("apps", name, "instances", :accept => :json)[:instances]
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Dyndrop::V1
|
2
|
+
# The primary API entrypoint. Wraps a BaseClient to provide nicer return
|
3
|
+
# values. Initialize with the target and, optionally, an auth token. These
|
4
|
+
# are the only two internal states.
|
5
|
+
class Client
|
6
|
+
|
7
|
+
attr_reader :base
|
8
|
+
|
9
|
+
# Create a new Client for interfacing with the given target.
|
10
|
+
#
|
11
|
+
# A token may also be provided to skip the login step.
|
12
|
+
def initialize(target = "http://api.dyndrop.com", token = nil)
|
13
|
+
@base = Base.new(target, token)
|
14
|
+
end
|
15
|
+
|
16
|
+
def version
|
17
|
+
1
|
18
|
+
end
|
19
|
+
|
20
|
+
# The current target URL of the client.
|
21
|
+
def target
|
22
|
+
@base.target
|
23
|
+
end
|
24
|
+
|
25
|
+
# Current authentication token.
|
26
|
+
def token
|
27
|
+
@base.token
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set the authentication token.
|
31
|
+
def token=(token)
|
32
|
+
@base.token = token
|
33
|
+
end
|
34
|
+
|
35
|
+
# Current proxy user. Usually nil.
|
36
|
+
def proxy
|
37
|
+
@base.proxy
|
38
|
+
end
|
39
|
+
|
40
|
+
# Set the proxy user for the client. Must be authorized as an
|
41
|
+
# administrator for this to have any effect.
|
42
|
+
def proxy=(email)
|
43
|
+
@base.proxy = email
|
44
|
+
end
|
45
|
+
|
46
|
+
# Is the client tracing API requests?
|
47
|
+
def trace
|
48
|
+
@base.trace
|
49
|
+
end
|
50
|
+
|
51
|
+
# Set the tracing flag; if true, API requests and responses will be
|
52
|
+
# printed out.
|
53
|
+
def trace=(bool)
|
54
|
+
@base.trace = bool
|
55
|
+
end
|
56
|
+
|
57
|
+
# The current log. See +log=+.
|
58
|
+
def log
|
59
|
+
@base.log
|
60
|
+
end
|
61
|
+
|
62
|
+
# Set the logging mode. Mode can be one of:
|
63
|
+
#
|
64
|
+
# [+String+] Name of a file to log the last 10 requests to.
|
65
|
+
# [+Array+] Array to append with log data (a Hash).
|
66
|
+
# [+IO+] An IO object to write to.
|
67
|
+
# [+false+] No logging.
|
68
|
+
def log=(mode)
|
69
|
+
@base.log = mode
|
70
|
+
end
|
71
|
+
|
72
|
+
# The currently authenticated user.
|
73
|
+
def current_user
|
74
|
+
if user = info[:user]
|
75
|
+
user(user)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def current_space
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def current_org
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
# Retrieve target metadata.
|
89
|
+
def info
|
90
|
+
@base.info
|
91
|
+
end
|
92
|
+
|
93
|
+
def login(username, password)
|
94
|
+
@base.token = Dyndrop::AuthToken.from_token_info(@base.get_token(username, {:password => password}))
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
# Create a user on the target and return a User object representing them.
|
99
|
+
def register(email, password)
|
100
|
+
@base.create_user(:email => email, :password => password)
|
101
|
+
user(email)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Clear client token. No requests are made for this.
|
105
|
+
def logout
|
106
|
+
@base.token = nil
|
107
|
+
end
|
108
|
+
|
109
|
+
# Is an authentication token set on the client?
|
110
|
+
def logged_in?
|
111
|
+
!!@base.token
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require "dyndrop/validator"
|
2
|
+
|
3
|
+
module Dyndrop::V1
|
4
|
+
module BaseClientMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClientMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module ModelMagic
|
11
|
+
attr_accessor :guid_name
|
12
|
+
|
13
|
+
def read_locations
|
14
|
+
@read_locations ||= {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def write_locations
|
18
|
+
@write_locations ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def read_only_attributes
|
22
|
+
@read_only_attributes ||= []
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_client(&blk)
|
26
|
+
ClientMethods.module_eval(&blk)
|
27
|
+
end
|
28
|
+
|
29
|
+
def on_base_client(&blk)
|
30
|
+
BaseClientMethods.module_eval(&blk)
|
31
|
+
end
|
32
|
+
|
33
|
+
def define_client_methods(klass = self)
|
34
|
+
singular = klass.object_name
|
35
|
+
plural = klass.plural_object_name
|
36
|
+
|
37
|
+
base_singular = klass.base_object_name
|
38
|
+
base_plural = klass.plural_base_object_name
|
39
|
+
|
40
|
+
on_base_client do
|
41
|
+
define_method(base_singular) do |guid|
|
42
|
+
get(base_plural, guid, :accept => :json)
|
43
|
+
end
|
44
|
+
|
45
|
+
define_method(:"create_#{base_singular}") do |payload|
|
46
|
+
post(base_plural, :content => :json, :accept => :json, :payload => payload)
|
47
|
+
end
|
48
|
+
|
49
|
+
define_method(:"delete_#{base_singular}") do |guid|
|
50
|
+
delete(base_plural, guid)
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
define_method(:"update_#{base_singular}") do |guid, payload|
|
55
|
+
put(base_plural, guid, :content => :json, :payload => payload)
|
56
|
+
end
|
57
|
+
|
58
|
+
define_method(base_plural) do |*args|
|
59
|
+
get(base_plural, :accept => :json)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
on_client do
|
64
|
+
if klass.guid_name
|
65
|
+
define_method(:"#{singular}_by_#{klass.guid_name}") do |guid|
|
66
|
+
obj = send(singular, guid)
|
67
|
+
obj if obj.exists?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
define_method(singular) do |*args|
|
72
|
+
guid, _ = args
|
73
|
+
klass.new(guid, self)
|
74
|
+
end
|
75
|
+
|
76
|
+
define_method(plural) do |*args|
|
77
|
+
options, _ = args
|
78
|
+
options ||= {}
|
79
|
+
|
80
|
+
@base.send(base_plural).collect do |json|
|
81
|
+
klass.new(json[klass.guid_name], self, json)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def attribute(name, type, opts = {})
|
88
|
+
default = opts[:default]
|
89
|
+
is_guid = opts[:guid]
|
90
|
+
read_only = opts[:read_only]
|
91
|
+
write_only = opts[:write_only]
|
92
|
+
has_default = opts.key?(:default)
|
93
|
+
|
94
|
+
read_locations[name] = Array(opts[:read] || opts[:at] || name) unless write_only
|
95
|
+
write_locations[name] = Array(opts[:write] || opts[:at] || name) unless read_only
|
96
|
+
|
97
|
+
read_only_attributes << name if read_only
|
98
|
+
|
99
|
+
self.guid_name = name if is_guid
|
100
|
+
|
101
|
+
define_method(name) do
|
102
|
+
return @guid if @guid && is_guid
|
103
|
+
|
104
|
+
read = read_manifest
|
105
|
+
read.key?(name) ? read[name] : default
|
106
|
+
end
|
107
|
+
|
108
|
+
define_method(:"#{name}=") do |val|
|
109
|
+
unless has_default && val == default
|
110
|
+
Dyndrop::Validator.validate_type(val, type)
|
111
|
+
end
|
112
|
+
|
113
|
+
@guid = val if is_guid
|
114
|
+
|
115
|
+
@manifest ||= {}
|
116
|
+
|
117
|
+
old = read_manifest[name]
|
118
|
+
@changes[name] = [old, val] if old != val
|
119
|
+
|
120
|
+
write_to = read_only ? self.class.read_locations : self.class.write_locations
|
121
|
+
|
122
|
+
put(val, @manifest, write_to[name])
|
123
|
+
end
|
124
|
+
|
125
|
+
private name if write_only
|
126
|
+
private :"#{name}=" if read_only
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Dyndrop
|
2
|
+
module Validator
|
3
|
+
class << self
|
4
|
+
def value_matches?(val, type)
|
5
|
+
case type
|
6
|
+
when Class
|
7
|
+
val.is_a?(type)
|
8
|
+
when Regexp
|
9
|
+
val.is_a?(String) && val =~ type
|
10
|
+
when :url
|
11
|
+
value_matches?(val, URI::regexp(%w(http https)))
|
12
|
+
when :https_url
|
13
|
+
value_matches?(val, URI::regexp("https"))
|
14
|
+
when :boolean
|
15
|
+
val.is_a?(TrueClass) || val.is_a?(FalseClass)
|
16
|
+
when Array
|
17
|
+
val.all? do |x|
|
18
|
+
value_matches?(x, type.first)
|
19
|
+
end
|
20
|
+
when Hash
|
21
|
+
val.is_a?(Hash) &&
|
22
|
+
type.all? { |name, subtype|
|
23
|
+
val.key?(name) && value_matches?(val[name], subtype)
|
24
|
+
}
|
25
|
+
when nil
|
26
|
+
true
|
27
|
+
else
|
28
|
+
val.is_a?(Object.const_get(type.to_s.capitalize))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate_type(val, type)
|
33
|
+
unless value_matches?(val, type)
|
34
|
+
raise Dyndrop::Mismatch.new(type, val)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/dyndrop/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dyndrop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -19,7 +19,19 @@ executables: []
|
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
|
+
- LICENSE
|
23
|
+
- lib/dyndrop.rb
|
24
|
+
- lib/dyndrop/baseclient.rb
|
22
25
|
- lib/dyndrop/version.rb
|
26
|
+
- lib/dyndrop/client.rb
|
27
|
+
- lib/dyndrop/auth_token.rb
|
28
|
+
- lib/dyndrop/errors.rb
|
29
|
+
- lib/dyndrop/rest_client.rb
|
30
|
+
- lib/dyndrop/validator.rb
|
31
|
+
- lib/dyndrop/trace_helpers.rb
|
32
|
+
- lib/dyndrop/v1/client.rb
|
33
|
+
- lib/dyndrop/v1/model_magic.rb
|
34
|
+
- lib/dyndrop/v1/base.rb
|
23
35
|
homepage: http://github.com/dyndrop/dyndrop
|
24
36
|
licenses: []
|
25
37
|
post_install_message:
|