fastly 1.1.4 → 1.1.5
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 +4 -4
- data/HISTORY.md +7 -3
- data/README.md +0 -2
- data/bin/fastly_upload_vcl +18 -18
- data/fastly.gemspec +11 -11
- data/lib/ext/curb_fu/response/base.rb +20 -0
- data/lib/fastly.rb +69 -83
- data/lib/fastly/base.rb +9 -9
- data/lib/fastly/belongs_to_service_and_version.rb +9 -14
- data/lib/fastly/cache_setting.rb +32 -34
- data/lib/fastly/client.rb +55 -120
- data/lib/fastly/client/curl.rb +57 -0
- data/lib/fastly/condition.rb +32 -32
- data/lib/fastly/customer.rb +1 -1
- data/lib/fastly/director.rb +4 -4
- data/lib/fastly/fetcher.rb +10 -12
- data/lib/fastly/gem_version.rb +2 -2
- data/lib/fastly/gzip.rb +26 -27
- data/lib/fastly/header.rb +67 -68
- data/lib/fastly/invoice.rb +17 -16
- data/lib/fastly/origin.rb +4 -5
- data/lib/fastly/request_setting.rb +68 -69
- data/lib/fastly/response_object.rb +46 -47
- data/lib/fastly/s3_logging.rb +48 -50
- data/lib/fastly/service.rb +20 -26
- data/lib/fastly/settings.rb +10 -11
- data/lib/fastly/syslog.rb +53 -57
- data/lib/fastly/user.rb +4 -6
- data/lib/fastly/util.rb +1 -0
- data/lib/fastly/version.rb +25 -30
- data/test/admin_test.rb +8 -8
- data/test/api_key_test.rb +20 -39
- data/test/common.rb +64 -66
- data/test/fastly/util_test.rb +1 -0
- data/test/full_login_test.rb +77 -82
- data/test/helper.rb +15 -24
- data/test/missing_api_key_test.rb +1 -1
- data/test/stats_test.rb +42 -50
- metadata +17 -13
data/lib/fastly/base.rb
CHANGED
@@ -5,9 +5,9 @@ class Fastly
|
|
5
5
|
|
6
6
|
def initialize(opts, fetcher)
|
7
7
|
@keys = []
|
8
|
-
opts.each do |key,val|
|
8
|
+
opts.each do |key, val|
|
9
9
|
next unless self.respond_to? "#{key}="
|
10
|
-
|
10
|
+
send("#{key}=", val)
|
11
11
|
@keys.push(key)
|
12
12
|
end
|
13
13
|
self.fetcher = fetcher
|
@@ -28,7 +28,7 @@ class Fastly
|
|
28
28
|
def as_hash
|
29
29
|
ret = {}
|
30
30
|
@keys.each do |key|
|
31
|
-
ret[key] =
|
31
|
+
ret[key] = send("#{key}") unless key =~ /^_/
|
32
32
|
end
|
33
33
|
ret
|
34
34
|
end
|
@@ -45,20 +45,20 @@ class Fastly
|
|
45
45
|
"/#{path}/#{id}"
|
46
46
|
end
|
47
47
|
|
48
|
-
def self.post_path(
|
48
|
+
def self.post_path(_opts = {})
|
49
49
|
"/#{path}"
|
50
50
|
end
|
51
51
|
|
52
|
-
def self.list_path(opts={})
|
52
|
+
def self.list_path(opts = {})
|
53
53
|
post_path(opts)
|
54
54
|
end
|
55
55
|
|
56
|
-
def self.put_path(
|
57
|
-
get_path(
|
56
|
+
def self.put_path(object)
|
57
|
+
get_path(object.id)
|
58
58
|
end
|
59
59
|
|
60
|
-
def self.delete_path(
|
61
|
-
put_path(
|
60
|
+
def self.delete_path(object)
|
61
|
+
put_path(object)
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
@@ -1,13 +1,11 @@
|
|
1
1
|
class Fastly
|
2
|
+
# Encapsulates behavior of objects requiring both service and version
|
2
3
|
class BelongsToServiceAndVersion < Base
|
4
|
+
attr_writer :version
|
5
|
+
|
3
6
|
# Return the Service object this belongs to
|
4
7
|
def service
|
5
|
-
@service ||= fetcher.get(
|
6
|
-
end
|
7
|
-
|
8
|
-
# Set the Version object this belongs to
|
9
|
-
def version=(version)
|
10
|
-
@version = version
|
8
|
+
@service ||= fetcher.get(Service, service_id)
|
11
9
|
end
|
12
10
|
|
13
11
|
# Get the Version object this belongs to
|
@@ -16,18 +14,16 @@ class Fastly
|
|
16
14
|
end
|
17
15
|
|
18
16
|
# Get the number of the Version this belongs to
|
19
|
-
def version_number
|
17
|
+
def version_number # rubocop:disable all
|
20
18
|
@version
|
21
|
-
end
|
19
|
+
end # rubocop:enable all
|
22
20
|
|
23
21
|
# :nodoc:
|
24
22
|
def as_hash
|
25
|
-
super.delete_if { |var|
|
23
|
+
super.delete_if { |var| %w(service_id version).include?(var) }
|
26
24
|
end
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
def self.get_path(service, version, name, options={})
|
26
|
+
def self.get_path(service, version, name, _opts = {})
|
31
27
|
"/service/#{service}/version/#{version}/#{path}/#{name}"
|
32
28
|
end
|
33
29
|
|
@@ -36,12 +32,11 @@ class Fastly
|
|
36
32
|
end
|
37
33
|
|
38
34
|
def self.put_path(obj)
|
39
|
-
get_path(obj.service_id, obj.version_number,obj.name)
|
35
|
+
get_path(obj.service_id, obj.version_number, obj.name)
|
40
36
|
end
|
41
37
|
|
42
38
|
def self.delete_path(obj)
|
43
39
|
put_path(obj)
|
44
40
|
end
|
45
|
-
|
46
41
|
end
|
47
42
|
end
|
data/lib/fastly/cache_setting.rb
CHANGED
@@ -2,46 +2,44 @@ class Fastly
|
|
2
2
|
# customize cache handling. Best used with conditions.
|
3
3
|
class CacheSetting < BelongsToServiceAndVersion
|
4
4
|
attr_accessor :service_id, :name, :action, :cache_condition, :ttl, :stale_ttl
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
##
|
6
|
+
# :attr: service_id
|
7
|
+
#
|
8
|
+
# The id of the service this belongs to.
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
##
|
11
|
+
# :attr: version
|
12
|
+
#
|
13
|
+
# The number of the version this belongs to.
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
##
|
16
|
+
# :attr: name
|
17
|
+
#
|
18
|
+
# The name of the gzip setting
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
##
|
21
|
+
# :attr: action
|
22
|
+
#
|
23
|
+
# Allows for termination of execution and either cache, pass, or restart
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
##
|
26
|
+
# :attr: ttl
|
27
|
+
#
|
28
|
+
# Sets the time to live
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
##
|
31
|
+
# :attr: stale_ttl
|
32
|
+
#
|
33
|
+
# Sets the max time to live for stale (unreachable) objects
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
##
|
36
|
+
# :attr: cache_condition
|
37
|
+
#
|
38
|
+
# Name of the cache condition used to test whether this settings object
|
39
|
+
# should be used.
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
Util.class_to_path(self, true)
|
45
|
-
end
|
41
|
+
def self.path
|
42
|
+
Util.class_to_path(self, true)
|
43
|
+
end
|
46
44
|
end
|
47
45
|
end
|
data/lib/fastly/client.rb
CHANGED
@@ -1,40 +1,36 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
require 'net/https'
|
3
1
|
require 'json'
|
4
2
|
require 'cgi'
|
5
|
-
require 'pp'
|
6
3
|
require 'uri'
|
4
|
+
require 'fastly/client/curl'
|
7
5
|
|
8
6
|
class Fastly
|
9
7
|
# The UserAgent to communicate with the API
|
10
8
|
class Client #:nodoc: all
|
11
|
-
begin
|
12
|
-
require 'curb-fu'
|
13
|
-
CURB_FU=true
|
14
|
-
rescue LoadError
|
15
|
-
CURB_FU=false
|
16
|
-
end
|
17
|
-
|
18
9
|
attr_accessor :http, :api_key, :user, :password, :cookie, :customer
|
19
10
|
|
20
11
|
def initialize(opts)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
12
|
+
@api_key = opts.fetch(:api_key, nil)
|
13
|
+
@user = opts.fetch(:user, nil)
|
14
|
+
@password = opts.fetch(:password, nil)
|
15
|
+
@customer = opts.fetch(:customer, nil)
|
16
|
+
|
17
|
+
base = opts.fetch(:base_url, 'https://api.fastly.com')
|
25
18
|
uri = URI.parse(base)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
port = opts.has_key?(:base_port) ? opts[:base_port] : (scheme == "https") ? 443 : 80
|
30
|
-
self.http = curb ? Fastly::Client::Curl.new(host, port) : Net::HTTP.new(host, port)
|
31
|
-
self.http.use_ssl = (scheme == "https")
|
19
|
+
|
20
|
+
@http = Curl.new(uri)
|
21
|
+
|
32
22
|
return self unless fully_authed?
|
33
23
|
|
34
24
|
# If we're fully authed (i.e username and password ) then we need to log in
|
35
|
-
resp =
|
36
|
-
|
37
|
-
|
25
|
+
resp = http.post('/login', make_params(user: user, password: password))
|
26
|
+
|
27
|
+
if resp.success?
|
28
|
+
@cookie = resp['Set-Cookie']
|
29
|
+
else
|
30
|
+
fail Unauthorized
|
31
|
+
end
|
32
|
+
|
33
|
+
self
|
38
34
|
end
|
39
35
|
|
40
36
|
def require_key!
|
@@ -56,133 +52,72 @@ class Fastly
|
|
56
52
|
!(user.nil? || password.nil?)
|
57
53
|
end
|
58
54
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
def get(path, params={})
|
64
|
-
path += "?"+make_params(params) unless params.empty?
|
65
|
-
resp = self.http.get(path, headers)
|
55
|
+
def get(path, params = {})
|
56
|
+
path += "?#{make_params(params)}" unless params.empty?
|
57
|
+
resp = http.get(path, headers)
|
66
58
|
return nil if 404 == resp.status
|
67
|
-
|
59
|
+
fail Error, resp.message unless resp.success?
|
68
60
|
JSON.parse(resp.body)
|
69
61
|
end
|
70
62
|
|
71
|
-
def get_stats(path, params={})
|
63
|
+
def get_stats(path, params = {})
|
72
64
|
content = get(path, params)
|
73
|
-
|
74
|
-
content[
|
65
|
+
|
66
|
+
case content['status']
|
67
|
+
when 'success' then content['data']
|
68
|
+
else
|
69
|
+
fail Error, content['message']
|
70
|
+
end
|
75
71
|
end
|
76
72
|
|
77
|
-
def post(path, params={})
|
73
|
+
def post(path, params = {})
|
78
74
|
post_and_put(:post, path, params)
|
79
75
|
end
|
80
76
|
|
81
|
-
def put(path, params={})
|
77
|
+
def put(path, params = {})
|
82
78
|
post_and_put(:put, path, params)
|
83
79
|
end
|
84
80
|
|
85
81
|
def delete(path)
|
86
|
-
resp =
|
87
|
-
|
82
|
+
resp = http.delete(path, headers)
|
83
|
+
resp.success?
|
88
84
|
end
|
89
85
|
|
90
86
|
private
|
91
87
|
|
92
|
-
def post_and_put(method, path, params={})
|
88
|
+
def post_and_put(method, path, params = {})
|
93
89
|
query = make_params(params)
|
94
|
-
resp =
|
95
|
-
|
90
|
+
resp = http.send(method, path, query, headers.merge('Content-Type' => 'application/x-www-form-urlencoded'))
|
91
|
+
|
92
|
+
if resp.success?
|
93
|
+
JSON.parse(resp.body)
|
94
|
+
else
|
95
|
+
fail Error, resp.message
|
96
|
+
end
|
97
|
+
|
96
98
|
JSON.parse(resp.body)
|
97
99
|
end
|
98
100
|
|
99
101
|
def headers
|
100
|
-
headers =
|
101
|
-
|
102
|
-
else
|
103
|
-
fully_authed? ? { 'Cookie' => cookie } : api_key_header
|
104
|
-
end
|
105
|
-
headers.merge!('Fastly-Explicit-Customer' => customer) if customer
|
106
|
-
headers.merge!('Content-Accept' => 'application/json')
|
107
|
-
ensure
|
108
|
-
@require_key = nil
|
109
|
-
end
|
110
|
-
|
111
|
-
def api_key_header
|
112
|
-
{ 'X-Fastly-Key' => api_key }
|
102
|
+
headers = fully_authed? ? { 'Cookie' => cookie } : { 'Fastly-Key' => api_key }
|
103
|
+
headers.merge('Content-Accept' => 'application/json')
|
113
104
|
end
|
114
105
|
|
115
106
|
def make_params(params)
|
116
|
-
params.map
|
117
|
-
next if
|
118
|
-
|
119
|
-
|
107
|
+
param_ary = params.map do |key, value|
|
108
|
+
next if value.nil?
|
109
|
+
key = key.to_s
|
110
|
+
|
111
|
+
if value.is_a?(Hash)
|
112
|
+
value.map do |sub_key, sub_value|
|
113
|
+
"#{CGI.escape("#{key}[#{sub_key}]")}=#{CGI.escape(sub_value.to_s)}"
|
114
|
+
end
|
120
115
|
else
|
121
|
-
|
122
|
-
new_key = "#{key}[#{sub_key}]"
|
123
|
-
"#{CGI.escape(new_key)}=#{CGI.escape(sub_val.to_s)}"
|
124
|
-
}
|
116
|
+
"#{CGI.escape(key)}=#{CGI.escape(value.to_s)}"
|
125
117
|
end
|
126
|
-
}.flatten.delete_if { |v| v.nil? }.join("&")
|
127
|
-
end
|
128
|
-
|
129
|
-
# :nodoc: all
|
130
|
-
class Curl
|
131
|
-
attr_accessor :host, :port, :protocol
|
132
|
-
|
133
|
-
def initialize(host, port=443)
|
134
|
-
self.host = host
|
135
|
-
self.port = port
|
136
|
-
self.protocol = 'https'
|
137
118
|
end
|
138
119
|
|
139
|
-
|
140
|
-
CurbFu.get({ :host => host, :port => port, :path => path, :headers => headers, :protocol => protocol })
|
141
|
-
end
|
142
|
-
|
143
|
-
def post(path, params, headers={})
|
144
|
-
CurbFu.post({ :host => host, :port => port, :path => path, :headers => headers, :protocol => protocol }, params)
|
145
|
-
end
|
146
|
-
|
147
|
-
def put(path, params, headers={})
|
148
|
-
CurbFu.put({ :host => host, :port => port, :path => path, :headers => headers, :params => params, :protocol => protocol }, params)
|
149
|
-
end
|
150
|
-
|
151
|
-
def delete(path, headers={})
|
152
|
-
CurbFu.delete({ :host => host, :port => port, :path => path, :headers => headers, :protocol => protocol })
|
153
|
-
end
|
154
|
-
|
155
|
-
def use_ssl=(ssl)
|
156
|
-
self.protocol = ssl ? 'https' : 'http'
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
# :nodoc: all
|
163
|
-
class Net::HTTPResponse
|
164
|
-
def success?
|
165
|
-
return Net::HTTPSuccess === self
|
166
|
-
end
|
167
|
-
|
168
|
-
def status
|
169
|
-
return self.code.to_i
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
# :nodoc: all
|
176
|
-
class CurbFu::Response::Base
|
177
|
-
def get_fields(key)
|
178
|
-
if ( match = @headers.find{|k,v| k.downcase == key.downcase} )
|
179
|
-
[match.last].flatten
|
180
|
-
else
|
181
|
-
[]
|
120
|
+
param_ary.flatten.delete_if { |v| v.nil? }.join('&')
|
182
121
|
end
|
183
122
|
end
|
184
|
-
|
185
|
-
def [](key)
|
186
|
-
get_fields(key).last
|
187
|
-
end
|
188
123
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'curb-fu'
|
2
|
+
|
3
|
+
class Fastly
|
4
|
+
class Client
|
5
|
+
# :nodoc: all
|
6
|
+
class Curl
|
7
|
+
attr_accessor :uri, :host, :port, :protocol
|
8
|
+
|
9
|
+
def initialize(uri)
|
10
|
+
@uri = uri
|
11
|
+
@host = uri.host
|
12
|
+
@port = uri.port
|
13
|
+
@protocol = uri.scheme
|
14
|
+
end
|
15
|
+
|
16
|
+
def get(path, headers = {})
|
17
|
+
CurbFu.get({
|
18
|
+
host: host,
|
19
|
+
port: port,
|
20
|
+
path: path,
|
21
|
+
headers: headers,
|
22
|
+
protocol: protocol
|
23
|
+
})
|
24
|
+
end
|
25
|
+
|
26
|
+
def post(path, params, headers = {})
|
27
|
+
CurbFu.post({
|
28
|
+
host: host,
|
29
|
+
port: port,
|
30
|
+
path: path,
|
31
|
+
headers: headers,
|
32
|
+
protocol: protocol
|
33
|
+
}, params)
|
34
|
+
end
|
35
|
+
|
36
|
+
def put(path, params, headers = {})
|
37
|
+
CurbFu.put({
|
38
|
+
host: host,
|
39
|
+
port: port,
|
40
|
+
path: path,
|
41
|
+
headers: headers,
|
42
|
+
protocol: protocol
|
43
|
+
}, params)
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete(path, headers = {})
|
47
|
+
CurbFu.delete({
|
48
|
+
host: host,
|
49
|
+
port: port,
|
50
|
+
path: path,
|
51
|
+
headers: headers,
|
52
|
+
protocol: protocol
|
53
|
+
})
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|