maestrano-ruby-test 0.8.3
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.
- checksums.yaml +7 -0
- data/.gitignore +34 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +45 -0
- data/LICENSE +21 -0
- data/README.md +794 -0
- data/Rakefile +40 -0
- data/bin/maestrano-console +9 -0
- data/lib/maestrano.rb +271 -0
- data/lib/maestrano/account/bill.rb +14 -0
- data/lib/maestrano/account/recurring_bill.rb +14 -0
- data/lib/maestrano/api/error/authentication_error.rb +8 -0
- data/lib/maestrano/api/error/base_error.rb +24 -0
- data/lib/maestrano/api/error/connection_error.rb +8 -0
- data/lib/maestrano/api/error/invalid_request_error.rb +14 -0
- data/lib/maestrano/api/list_object.rb +37 -0
- data/lib/maestrano/api/object.rb +187 -0
- data/lib/maestrano/api/operation/base.rb +215 -0
- data/lib/maestrano/api/operation/create.rb +18 -0
- data/lib/maestrano/api/operation/delete.rb +13 -0
- data/lib/maestrano/api/operation/list.rb +18 -0
- data/lib/maestrano/api/operation/update.rb +59 -0
- data/lib/maestrano/api/resource.rb +47 -0
- data/lib/maestrano/api/util.rb +122 -0
- data/lib/maestrano/open_struct.rb +11 -0
- data/lib/maestrano/saml/attribute_value.rb +15 -0
- data/lib/maestrano/saml/metadata.rb +64 -0
- data/lib/maestrano/saml/request.rb +93 -0
- data/lib/maestrano/saml/response.rb +201 -0
- data/lib/maestrano/saml/schemas/saml20assertion_schema.xsd +283 -0
- data/lib/maestrano/saml/schemas/saml20protocol_schema.xsd +302 -0
- data/lib/maestrano/saml/schemas/xenc_schema.xsd +146 -0
- data/lib/maestrano/saml/schemas/xmldsig_schema.xsd +318 -0
- data/lib/maestrano/saml/settings.rb +37 -0
- data/lib/maestrano/saml/validation_error.rb +7 -0
- data/lib/maestrano/sso.rb +86 -0
- data/lib/maestrano/sso/base_group.rb +31 -0
- data/lib/maestrano/sso/base_membership.rb +25 -0
- data/lib/maestrano/sso/base_user.rb +75 -0
- data/lib/maestrano/sso/group.rb +24 -0
- data/lib/maestrano/sso/session.rb +107 -0
- data/lib/maestrano/sso/user.rb +34 -0
- data/lib/maestrano/version.rb +3 -0
- data/lib/maestrano/xml_security/signed_document.rb +170 -0
- data/maestrano.gemspec +32 -0
- data/maestrano.png +0 -0
- data/test/helpers/api_helpers.rb +115 -0
- data/test/helpers/saml_helpers.rb +62 -0
- data/test/maestrano/account/bill_test.rb +48 -0
- data/test/maestrano/account/recurring_bill_test.rb +49 -0
- data/test/maestrano/api/list_object_test.rb +20 -0
- data/test/maestrano/api/object_test.rb +28 -0
- data/test/maestrano/api/resource_test.rb +343 -0
- data/test/maestrano/api/util_test.rb +31 -0
- data/test/maestrano/maestrano_test.rb +260 -0
- data/test/maestrano/open_struct_test.rb +10 -0
- data/test/maestrano/saml/request_test.rb +168 -0
- data/test/maestrano/saml/response_test.rb +290 -0
- data/test/maestrano/saml/settings_test.rb +51 -0
- data/test/maestrano/sso/base_group_test.rb +54 -0
- data/test/maestrano/sso/base_membership_test.rb +45 -0
- data/test/maestrano/sso/base_user_test.rb +114 -0
- data/test/maestrano/sso/group_test.rb +47 -0
- data/test/maestrano/sso/session_test.rb +161 -0
- data/test/maestrano/sso/user_test.rb +65 -0
- data/test/maestrano/sso_test.rb +105 -0
- data/test/maestrano/xml_security/signed_document.rb +163 -0
- data/test/support/saml/certificates/certificate1 +12 -0
- data/test/support/saml/certificates/r1_certificate2_base64 +1 -0
- data/test/support/saml/responses/adfs_response_sha1.xml +46 -0
- data/test/support/saml/responses/adfs_response_sha256.xml +46 -0
- data/test/support/saml/responses/adfs_response_sha384.xml +46 -0
- data/test/support/saml/responses/adfs_response_sha512.xml +46 -0
- data/test/support/saml/responses/no_signature_ns.xml +48 -0
- data/test/support/saml/responses/open_saml_response.xml +56 -0
- data/test/support/saml/responses/r1_response6.xml.base64 +1 -0
- data/test/support/saml/responses/response1.xml.base64 +1 -0
- data/test/support/saml/responses/response2.xml.base64 +79 -0
- data/test/support/saml/responses/response3.xml.base64 +66 -0
- data/test/support/saml/responses/response4.xml.base64 +93 -0
- data/test/support/saml/responses/response5.xml.base64 +102 -0
- data/test/support/saml/responses/response_with_ampersands.xml +139 -0
- data/test/support/saml/responses/response_with_ampersands.xml.base64 +93 -0
- data/test/support/saml/responses/response_with_multiple_attribute_values.xml +57 -0
- data/test/support/saml/responses/simple_saml_php.xml +71 -0
- data/test/support/saml/responses/starfield_response.xml.base64 +1 -0
- data/test/support/saml/responses/wrapped_response_2.xml.base64 +150 -0
- data/test/test_helper.rb +47 -0
- metadata +315 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
module Maestrano
|
|
2
|
+
module API
|
|
3
|
+
class Object
|
|
4
|
+
include Enumerable
|
|
5
|
+
|
|
6
|
+
attr_accessor :api_token
|
|
7
|
+
@@permanent_attributes = Set.new([:api_token, :id])
|
|
8
|
+
|
|
9
|
+
# The default :id method is deprecated and isn't useful to us
|
|
10
|
+
if method_defined?(:id)
|
|
11
|
+
undef :id
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(id=nil, api_token=nil)
|
|
15
|
+
# parameter overloading!
|
|
16
|
+
if id.kind_of?(Hash)
|
|
17
|
+
@retrieve_options = id.dup
|
|
18
|
+
@retrieve_options.delete(:id)
|
|
19
|
+
id = id[:id]
|
|
20
|
+
else
|
|
21
|
+
@retrieve_options = {}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
@api_token = api_token
|
|
25
|
+
@values = {}
|
|
26
|
+
# This really belongs in API::Resource, but not putting it there allows us
|
|
27
|
+
# to have a unified inspect method
|
|
28
|
+
@unsaved_values = Set.new
|
|
29
|
+
@transient_values = Set.new
|
|
30
|
+
@values[:id] = id if id
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.construct_from(values, api_token=nil)
|
|
34
|
+
obj = self.new(values[:id], api_token)
|
|
35
|
+
obj.refresh_from(values, api_token)
|
|
36
|
+
obj
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def to_s(*args)
|
|
40
|
+
JSON.pretty_generate(@values)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def inspect()
|
|
44
|
+
id_string = (self.respond_to?(:id) && !self.id.nil?) ? " id=#{self.id}" : ""
|
|
45
|
+
"#<#{self.class}:0x#{self.object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@values)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def refresh_from(values, api_token, partial=false)
|
|
49
|
+
@api_token = api_token
|
|
50
|
+
|
|
51
|
+
@previous_metadata = values[:metadata]
|
|
52
|
+
removed = partial ? Set.new : Set.new(@values.keys - values.keys)
|
|
53
|
+
added = Set.new(values.keys - @values.keys)
|
|
54
|
+
# Wipe old state before setting new.
|
|
55
|
+
|
|
56
|
+
instance_eval do
|
|
57
|
+
remove_accessors(removed)
|
|
58
|
+
add_accessors(added)
|
|
59
|
+
end
|
|
60
|
+
removed.each do |k|
|
|
61
|
+
@values.delete(k)
|
|
62
|
+
@transient_values.add(k)
|
|
63
|
+
@unsaved_values.delete(k)
|
|
64
|
+
end
|
|
65
|
+
values.each do |k, v|
|
|
66
|
+
@values[k] = Util.convert_to_maestrano_object(v, api_token)
|
|
67
|
+
@transient_values.delete(k)
|
|
68
|
+
@unsaved_values.delete(k)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def [](k)
|
|
73
|
+
@values[k.to_sym]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def []=(k, v)
|
|
77
|
+
send(:"#{k}=", v)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def keys
|
|
81
|
+
@values.keys
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def values
|
|
85
|
+
@values.values
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def to_json(*a)
|
|
89
|
+
JSON.generate(@values)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def as_json(*a)
|
|
93
|
+
@values.as_json(*a)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def to_hash
|
|
97
|
+
@values
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def each(&blk)
|
|
101
|
+
@values.each(&blk)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def _dump(level)
|
|
105
|
+
Marshal.dump([@values, @api_token])
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def self._load(args)
|
|
109
|
+
values, api_token = Marshal.load(args)
|
|
110
|
+
construct_from(values, api_token)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
if RUBY_VERSION < '1.9.2'
|
|
114
|
+
def respond_to?(symbol)
|
|
115
|
+
@values.has_key?(symbol) || super
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
protected
|
|
120
|
+
|
|
121
|
+
def metaclass
|
|
122
|
+
class << self; self; end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def remove_accessors(keys)
|
|
126
|
+
metaclass.instance_eval do
|
|
127
|
+
keys.each do |k|
|
|
128
|
+
next if @@permanent_attributes.include?(k)
|
|
129
|
+
k_eq = :"#{k}="
|
|
130
|
+
remove_method(k) if method_defined?(k)
|
|
131
|
+
remove_method(k_eq) if method_defined?(k_eq)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def add_accessors(keys)
|
|
137
|
+
metaclass.instance_eval do
|
|
138
|
+
keys.each do |k|
|
|
139
|
+
next if @@permanent_attributes.include?(k)
|
|
140
|
+
k_eq = :"#{k}="
|
|
141
|
+
define_method(k) { @values[k] }
|
|
142
|
+
define_method(k_eq) do |v|
|
|
143
|
+
if v == ""
|
|
144
|
+
raise ArgumentError.new(
|
|
145
|
+
"You cannot set #{k} to an empty string." +
|
|
146
|
+
"We interpret empty strings as nil in requests." +
|
|
147
|
+
"You may set #{self}.#{k} = nil to delete the property.")
|
|
148
|
+
end
|
|
149
|
+
@values[k] = v
|
|
150
|
+
@unsaved_values.add(k)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def method_missing(name, *args)
|
|
157
|
+
# TODO: only allow setting in updateable classes.
|
|
158
|
+
if name.to_s.end_with?('=')
|
|
159
|
+
attr = name.to_s[0...-1].to_sym
|
|
160
|
+
add_accessors([attr])
|
|
161
|
+
begin
|
|
162
|
+
mth = method(name)
|
|
163
|
+
rescue NameError
|
|
164
|
+
raise NoMethodError.new("Cannot set #{attr} on this object. HINT: you can't set: #{@@permanent_attributes.to_a.join(', ')}")
|
|
165
|
+
end
|
|
166
|
+
return mth.call(args[0])
|
|
167
|
+
else
|
|
168
|
+
return @values[name] if @values.has_key?(name)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
begin
|
|
172
|
+
super
|
|
173
|
+
rescue NoMethodError => e
|
|
174
|
+
if @transient_values.include?(name)
|
|
175
|
+
raise NoMethodError.new(e.message + ". HINT: The '#{name}' attribute was set in the past, however. It was then wiped when refreshing the object with the result returned by Maestrano's API, probably as a result of a save(). The attributes currently available on this object are: #{@values.keys.join(', ')}")
|
|
176
|
+
else
|
|
177
|
+
raise
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def respond_to_missing?(symbol, include_private = false)
|
|
183
|
+
@values.has_key?(symbol) || super
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
module Maestrano
|
|
2
|
+
module API
|
|
3
|
+
module Operation
|
|
4
|
+
module Base
|
|
5
|
+
# class << self
|
|
6
|
+
# attr_accessor :api_token, :api_base, :verify_ssl_certs, :api_version
|
|
7
|
+
# end
|
|
8
|
+
|
|
9
|
+
def self.api_url(url='')
|
|
10
|
+
Maestrano.param('api.host') + Maestrano.param('api.base') + url
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Perform remote request
|
|
14
|
+
def self.request(method, url, api_token, params={}, headers={})
|
|
15
|
+
unless api_token ||= Maestrano.param('api_token')
|
|
16
|
+
raise Maestrano::API::Error::AuthenticationError.new('No API key provided.')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
request_opts = { :verify_ssl => false }
|
|
20
|
+
|
|
21
|
+
if self.ssl_preflight_passed?
|
|
22
|
+
request_opts.update(
|
|
23
|
+
verify_ssl: OpenSSL::SSL::VERIFY_PEER,
|
|
24
|
+
ssl_ca_file: Maestrano.param('ssl_bundle_path')
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
params = Util.objects_to_ids(params)
|
|
29
|
+
url = api_url(url)
|
|
30
|
+
|
|
31
|
+
case method.to_s.downcase.to_sym
|
|
32
|
+
when :get, :head, :delete
|
|
33
|
+
# Make params into GET parameters
|
|
34
|
+
url += "#{URI.parse(url).query ? '&' : '?'}#{uri_encode(params)}" if params && params.any?
|
|
35
|
+
payload = nil
|
|
36
|
+
else
|
|
37
|
+
payload = uri_encode(params)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
request_opts.update(:headers => request_headers(api_token).update(headers),
|
|
41
|
+
:method => method, :open_timeout => 30,
|
|
42
|
+
:payload => payload, :url => url, :timeout => 80)
|
|
43
|
+
|
|
44
|
+
begin
|
|
45
|
+
response = execute_request(request_opts)
|
|
46
|
+
rescue SocketError => e
|
|
47
|
+
handle_restclient_error(e)
|
|
48
|
+
rescue NoMethodError => e
|
|
49
|
+
# Work around RestClient bug
|
|
50
|
+
if e.message =~ /\WRequestFailed\W/
|
|
51
|
+
e = APIConnectionError.new('Unexpected HTTP response code')
|
|
52
|
+
handle_restclient_error(e)
|
|
53
|
+
else
|
|
54
|
+
raise
|
|
55
|
+
end
|
|
56
|
+
rescue RestClient::ExceptionWithResponse => e
|
|
57
|
+
if rcode = e.http_code and rbody = e.http_body
|
|
58
|
+
handle_api_error(rcode, rbody)
|
|
59
|
+
else
|
|
60
|
+
handle_restclient_error(e)
|
|
61
|
+
end
|
|
62
|
+
rescue RestClient::Exception, Errno::ECONNREFUSED => e
|
|
63
|
+
handle_restclient_error(e)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
[parse(response), api_token]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def self.ssl_preflight_passed?
|
|
72
|
+
if !Maestrano.param('api.verify_ssl_certs')
|
|
73
|
+
#$stderr.puts "WARNING: Running without SSL cert verification. " +
|
|
74
|
+
# "Execute 'Maestrano.configure { |config| config.verify_ssl_certs = true' } to enable verification."
|
|
75
|
+
return false
|
|
76
|
+
elsif !Util.file_readable(Maestrano.param('ssl_bundle_path'))
|
|
77
|
+
$stderr.puts "WARNING: Running without SSL cert verification " +
|
|
78
|
+
"because #{Maestrano.param('ssl_bundle_path')} isn't readable"
|
|
79
|
+
|
|
80
|
+
return false
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
return true
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.user_agent
|
|
87
|
+
@uname ||= get_uname
|
|
88
|
+
|
|
89
|
+
{
|
|
90
|
+
:bindings_version => Maestrano.param('api.version'),
|
|
91
|
+
:lang => Maestrano.param('api.lang'),
|
|
92
|
+
:lang_version => Maestrano.param('api.lang_version'),
|
|
93
|
+
:platform => RUBY_PLATFORM,
|
|
94
|
+
:publisher => 'maestrano',
|
|
95
|
+
:uname => @uname
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def self.get_uname
|
|
101
|
+
`uname -a 2>/dev/null`.strip if RUBY_PLATFORM =~ /linux|darwin/i
|
|
102
|
+
rescue Errno::ENOMEM => ex # couldn't create subprocess
|
|
103
|
+
"uname lookup failed"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def self.uri_encode(params)
|
|
107
|
+
Util.flatten_params(params).
|
|
108
|
+
map { |k,v| "#{k}=#{Util.url_encode(v)}" }.join('&')
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.request_headers(api_token)
|
|
112
|
+
headers = {
|
|
113
|
+
:user_agent => "Maestrano/v1 RubyBindings/#{Maestrano.param('api.version')}",
|
|
114
|
+
:authorization => "Basic #{Base64.encode64(api_token)}",
|
|
115
|
+
:content_type => 'application/x-www-form-urlencoded'
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
api_version = Maestrano.param('api_version')
|
|
119
|
+
headers[:maestrano_version] = api_version if api_version
|
|
120
|
+
|
|
121
|
+
begin
|
|
122
|
+
headers.update(:x_maestrano_client_user_agent => JSON.generate(user_agent))
|
|
123
|
+
rescue => e
|
|
124
|
+
headers.update(:x_maestrano_client_raw_user_agent => user_agent.inspect,
|
|
125
|
+
:error => "#{e} (#{e.class})")
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def self.execute_request(opts)
|
|
130
|
+
RestClient::Request.execute(opts)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def self.parse(response)
|
|
134
|
+
begin
|
|
135
|
+
# Would use :symbolize_names => true, but apparently there is
|
|
136
|
+
# some library out there that makes symbolize_names not work.
|
|
137
|
+
response = JSON.parse(response.body)
|
|
138
|
+
rescue JSON::ParserError
|
|
139
|
+
raise general_api_error(response.code, response.body)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
response = Util.symbolize_names(response)
|
|
143
|
+
response[:data]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def self.general_api_error(rcode, rbody)
|
|
147
|
+
Maestrano::API::Error::BaseError.new("Invalid response object from API: #{rbody.inspect} " +
|
|
148
|
+
"(HTTP response code was #{rcode})", rcode, rbody)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def self.handle_api_error(rcode, rbody)
|
|
152
|
+
begin
|
|
153
|
+
error_obj = JSON.parse(rbody)
|
|
154
|
+
error_obj = Util.symbolize_names(error_obj)
|
|
155
|
+
errors = error_obj[:errors] or raise Maestrano::API::Error::BaseError.new # escape from parsing
|
|
156
|
+
|
|
157
|
+
rescue JSON::ParserError, Maestrano::API::Error::BaseError
|
|
158
|
+
raise general_api_error(rcode, rbody)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
case rcode
|
|
162
|
+
when 400, 404
|
|
163
|
+
raise invalid_request_error(errors, rcode, rbody, error_obj)
|
|
164
|
+
when 401
|
|
165
|
+
raise authentication_error(errors, rcode, rbody, error_obj)
|
|
166
|
+
else
|
|
167
|
+
raise api_error(errors, rcode, rbody, error_obj)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def self.invalid_request_error(errors, rcode, rbody, error_obj)
|
|
173
|
+
Maestrano::API::Error::InvalidRequestError.new(errors.first.join(" "), errors.keys.first.to_s, rcode,
|
|
174
|
+
rbody, error_obj)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def self.authentication_error(errors, rcode, rbody, error_obj)
|
|
178
|
+
Maestrano::API::Error::AuthenticationError.new(errors.first.join(" "), rcode, rbody, error_obj)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def self.api_error(errors, rcode, rbody, error_obj)
|
|
182
|
+
Maestrano::API::Error::BaseError.new(errors[:message], rcode, rbody, error_obj)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def self.handle_restclient_error(e)
|
|
186
|
+
case e
|
|
187
|
+
when RestClient::ServerBrokeConnection, RestClient::RequestTimeout
|
|
188
|
+
message = "Could not connect to Maestrano. " +
|
|
189
|
+
"Please check your internet connection and try again. " +
|
|
190
|
+
"If this problem persists, you should check Maestrano service status at " +
|
|
191
|
+
"https://twitter.com/maestrano, or let us know at support@maestrano.com."
|
|
192
|
+
|
|
193
|
+
when RestClient::SSLCertificateNotVerified
|
|
194
|
+
message = "Could not verify Maestrano's SSL certificate. " +
|
|
195
|
+
"Please make sure that your network is not intercepting certificates. " +
|
|
196
|
+
"(Try going to https://maestrano.com/api/v1/ping in your browser.) " +
|
|
197
|
+
"If this problem persists, let us know at support@maestrano.com."
|
|
198
|
+
|
|
199
|
+
when SocketError
|
|
200
|
+
message = "Unexpected error communicating when trying to connect to Maestrano. " +
|
|
201
|
+
"You may be seeing this message because your DNS is not working. " +
|
|
202
|
+
"To check, try running 'host maestrano.com' from the command line."
|
|
203
|
+
|
|
204
|
+
else
|
|
205
|
+
message = "Unexpected error communicating with Maestrano. " +
|
|
206
|
+
"If this problem persists, let us know at support@maestrano.com."
|
|
207
|
+
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
raise APIConnectionError.new(message + "\n\n(Network error: #{e.message})")
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Maestrano
|
|
2
|
+
module API
|
|
3
|
+
module Operation
|
|
4
|
+
module Create
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def create(params={}, api_token=nil)
|
|
7
|
+
response, api_token = Maestrano::API::Operation::Base.request(:post, self.url, api_token, params)
|
|
8
|
+
Util.convert_to_maestrano_object(response, api_token)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.included(base)
|
|
13
|
+
base.extend(ClassMethods)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Maestrano
|
|
2
|
+
module API
|
|
3
|
+
module Operation
|
|
4
|
+
module Delete
|
|
5
|
+
def delete(params = {})
|
|
6
|
+
response, api_token = Maestrano::API::Operation::Base.request(:delete, url, @api_token, params)
|
|
7
|
+
refresh_from(response, api_token)
|
|
8
|
+
self
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Maestrano
|
|
2
|
+
module API
|
|
3
|
+
module Operation
|
|
4
|
+
module List
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def all(filters={}, api_token=nil)
|
|
7
|
+
response, api_token = Maestrano::API::Operation::Base.request(:get, url, api_token, filters)
|
|
8
|
+
Util.convert_to_maestrano_object(response, api_token)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.included(base)
|
|
13
|
+
base.extend(ClassMethods)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|