fastly 0.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.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.md +59 -0
- data/Rakefile +1 -0
- data/bin/fastly_upload_vcl +67 -0
- data/fastly.gemspec +23 -0
- data/lib/fastly.rb +357 -0
- data/lib/fastly/backend.rb +99 -0
- data/lib/fastly/base.rb +62 -0
- data/lib/fastly/belongs_to_service_and_version.rb +42 -0
- data/lib/fastly/client.rb +160 -0
- data/lib/fastly/customer.rb +26 -0
- data/lib/fastly/director.rb +47 -0
- data/lib/fastly/domain.rb +29 -0
- data/lib/fastly/fetcher.rb +56 -0
- data/lib/fastly/invoice.rb +95 -0
- data/lib/fastly/match.rb +77 -0
- data/lib/fastly/origin.rb +23 -0
- data/lib/fastly/service.rb +112 -0
- data/lib/fastly/settings.rb +69 -0
- data/lib/fastly/user.rb +62 -0
- data/lib/fastly/vcl.rb +28 -0
- data/lib/fastly/version.rb +148 -0
- data/test/admin_test.rb +41 -0
- data/test/api_key_test.rb +52 -0
- data/test/common.rb +155 -0
- data/test/full_login_test.rb +98 -0
- data/test/helper.rb +24 -0
- metadata +157 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
Fastly - client library for interacting with the Fastly web acceleration service
|
2
|
+
|
3
|
+
# Example
|
4
|
+
|
5
|
+
fastly = Net::Fastly.new(%login_opts);
|
6
|
+
|
7
|
+
current_user = fastly.current_user;
|
8
|
+
current_customer = fastly.current_customer;
|
9
|
+
|
10
|
+
user = fastly.get_user(current_user.id);
|
11
|
+
customer = fastly.get_customer(current_customer.id);
|
12
|
+
|
13
|
+
puts "Name: #{user.name}"
|
14
|
+
puts "Works for #{user.customer.name}"
|
15
|
+
puts "Which is the same as #{customer.name}"
|
16
|
+
puts "Which has the owner #{customer.owner.name}"
|
17
|
+
|
18
|
+
# Let's see which services we have defined
|
19
|
+
customer.list_services.each do |service|
|
20
|
+
puts service.id
|
21
|
+
puts service.name
|
22
|
+
service.versions.each do |version
|
23
|
+
puts "\t#{version.number}"
|
24
|
+
end
|
25
|
+
|
26
|
+
service = fastly.create_service(:name => "MyFirstService");
|
27
|
+
latest_version = service.version;
|
28
|
+
|
29
|
+
# Create a domain and a backend for the service ...
|
30
|
+
domain = fastly.create_domain(:service_id => service.id, :version => latest_version.number, :name => "www.example.com");
|
31
|
+
backend = fastly.create_backend(:service_id => service.id, :version => latest_version.number, :ipv4 => "127.0.0.1", :port => 80);
|
32
|
+
|
33
|
+
# ... and activate it. You're now hosted on Fastly.
|
34
|
+
latest_version.activate
|
35
|
+
|
36
|
+
# Let's take a peek at the VCL that Fastly generated for us
|
37
|
+
vcl = latest_version.generated_vcl;
|
38
|
+
puts "Generated VCL file is:\n#{vcl.content}"
|
39
|
+
|
40
|
+
# Now let's create a new version ...
|
41
|
+
new_version = latest_version.clone;
|
42
|
+
# ... add a new backend ...
|
43
|
+
new_backend = fastly.create_backend(:service_id => service.id, :version => new_version.number, :ipv4 => "192.168.0.1", :port => 8080);
|
44
|
+
# ... and upload some custome vcl (presuming we have permissions)
|
45
|
+
new_version.upload_vcl(vcl_name, File.read(vcl_file));
|
46
|
+
|
47
|
+
new_version.activate;
|
48
|
+
|
49
|
+
# Copyright
|
50
|
+
|
51
|
+
Copyright 2011 - Fastly Inc
|
52
|
+
|
53
|
+
Mail support at fastly dot com if you have problems.
|
54
|
+
|
55
|
+
# Developers
|
56
|
+
|
57
|
+
http://github.com/fastly/fastly-ruby
|
58
|
+
|
59
|
+
http://www.fastly.com/documentation
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
|
3
|
+
##
|
4
|
+
# fastly_upload_vcl - upload raw VCL files to Fastly
|
5
|
+
#
|
6
|
+
# Author:: Fastly Inc <support@fastly.com>
|
7
|
+
# Copyright:: Copyright (c) 2011 Fastly Inc
|
8
|
+
# License:: Distributes under the same terms as Ruby
|
9
|
+
#
|
10
|
+
# = USAGE
|
11
|
+
#
|
12
|
+
# fastly_upload_vcl <options> <service id or name> <path to vcl file>
|
13
|
+
#
|
14
|
+
# = CONFIGURATION
|
15
|
+
#
|
16
|
+
# You can either have a config file in either ~/.fastly or /etc/fastly with
|
17
|
+
#
|
18
|
+
# api_key = <key>
|
19
|
+
#
|
20
|
+
# or a config file with
|
21
|
+
#
|
22
|
+
# user = <login>
|
23
|
+
# password = <password>
|
24
|
+
#
|
25
|
+
# Alternatively you can pass in any of those options on the command line
|
26
|
+
#
|
27
|
+
# fastly_upload_vcl --api_key <key> <service id or name> <path to vcl file>
|
28
|
+
# fastly_upload_vcl --user <login> --password <password> <service id or name> <path to vcl file>
|
29
|
+
#
|
30
|
+
|
31
|
+
require 'rubygems'
|
32
|
+
require 'fastly'
|
33
|
+
|
34
|
+
# :nodoc:
|
35
|
+
def die(message)
|
36
|
+
warn message
|
37
|
+
exit -1
|
38
|
+
end
|
39
|
+
|
40
|
+
params = Fastly.get_options("#{ENV['HOME']}/.fastly", "/etc/fastly")
|
41
|
+
|
42
|
+
service_id = ARGV.shift || die("You must pass in a service id")
|
43
|
+
vcl_file = ARGV.shift || die("You must pass in a vcl file")
|
44
|
+
|
45
|
+
die("Couldn't find any of the config files - #{configs.join(',')}") unless params.keys.size>0
|
46
|
+
die("Couldn't find vcl file #{vcl_file}") unless File.file?(vcl_file)
|
47
|
+
|
48
|
+
fastly = Fastly.new(params)
|
49
|
+
service = fastly.get_service(service_id) || die("Couldn't find service #{service_id}")
|
50
|
+
old = service.version
|
51
|
+
updated = old.clone
|
52
|
+
puts "Uploading #{vcl_file} and bumping version from #{old.number} to #{updated.number}"
|
53
|
+
begin
|
54
|
+
name = File.basename(vcl_file, ".vcl")
|
55
|
+
content = File.new(vcl_file, "r").read
|
56
|
+
vcl = updated.vcl(name)
|
57
|
+
if vcl
|
58
|
+
vcl.content = content
|
59
|
+
vcl.save!
|
60
|
+
else
|
61
|
+
updated.upload_vcl(name, content)
|
62
|
+
end
|
63
|
+
updated.activate!
|
64
|
+
rescue => e
|
65
|
+
die("Couldn't upload and activate vcl: #{e}")
|
66
|
+
end
|
67
|
+
puts "Done!"
|
data/fastly.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "fastly"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "fastly"
|
7
|
+
s.version = Fastly::VERSION
|
8
|
+
s.authors = ["Fastly Inc"]
|
9
|
+
s.email = ["support@fastly.com"]
|
10
|
+
s.homepage = "http://github.com/fastly/fastly-ruby"
|
11
|
+
s.summary = %q{Client library for the Fastly acceleration system}
|
12
|
+
s.description = %q{Client library for the Fastly acceleration system}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_dependency 'json'
|
20
|
+
s.add_dependency 'curb', '>=0.7.15'
|
21
|
+
s.add_dependency 'curb-fu', '>=0.6.1'
|
22
|
+
s.add_dependency 'rdoc', '>=3.11'
|
23
|
+
end
|
data/lib/fastly.rb
ADDED
@@ -0,0 +1,357 @@
|
|
1
|
+
# Author:: Fastly Inc <support@fastly.com>
|
2
|
+
# Copyright:: Copyright (c) 2011 Fastly Inc
|
3
|
+
# License:: Distributes under the same terms as Ruby
|
4
|
+
|
5
|
+
# A client library for interacting with the Fastly web acceleration service
|
6
|
+
class Fastly
|
7
|
+
# The current version of the library
|
8
|
+
VERSION = "0.5"
|
9
|
+
|
10
|
+
require 'fastly/fetcher'
|
11
|
+
require 'fastly/client'
|
12
|
+
|
13
|
+
require 'fastly/base'
|
14
|
+
require 'fastly/belongs_to_service_and_version'
|
15
|
+
require 'fastly/backend'
|
16
|
+
require 'fastly/customer'
|
17
|
+
require 'fastly/director'
|
18
|
+
require 'fastly/domain'
|
19
|
+
require 'fastly/invoice'
|
20
|
+
require 'fastly/match'
|
21
|
+
require 'fastly/origin'
|
22
|
+
require 'fastly/service'
|
23
|
+
require 'fastly/settings'
|
24
|
+
require 'fastly/user'
|
25
|
+
require 'fastly/vcl'
|
26
|
+
require 'fastly/version'
|
27
|
+
|
28
|
+
include Fastly::Fetcher
|
29
|
+
|
30
|
+
# Create a new Fastly client. Options are
|
31
|
+
#
|
32
|
+
# user:: your Fastly login
|
33
|
+
# password:: your Fastly password
|
34
|
+
# api_key:: your Fastly api key
|
35
|
+
#
|
36
|
+
# You only need to pass in C<api_key> OR C<user> and C<password>.
|
37
|
+
#
|
38
|
+
# Some methods require full username and password rather than just auth token.
|
39
|
+
def initialize(opts)
|
40
|
+
self.client(opts)
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
# Whether or not we're authed at all by either username & password or API key
|
45
|
+
def authed?
|
46
|
+
client.authed?
|
47
|
+
end
|
48
|
+
|
49
|
+
# Whether or not we're fully (username and password) authed
|
50
|
+
# Some methods require full username and password rather than just auth token
|
51
|
+
def fully_authed?
|
52
|
+
client.authed? # for now
|
53
|
+
#client.fully_authed?
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return a Customer object representing the customer of the current logged in user.
|
57
|
+
def current_customer
|
58
|
+
raise Fastly::FullAuthRequired unless self.fully_authed?
|
59
|
+
@current_customer ||= get(Customer)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Return a User object representing the current logged in user.
|
63
|
+
def current_user
|
64
|
+
raise Fastly::FullAuthRequired unless self.fully_authed?
|
65
|
+
@current_user ||= get(User)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Return a hash representing all commands available.
|
69
|
+
#
|
70
|
+
# Useful for information.
|
71
|
+
def commands
|
72
|
+
client.get('/commands')
|
73
|
+
end
|
74
|
+
|
75
|
+
# Purge the specified path from your cache.
|
76
|
+
def purge(path)
|
77
|
+
res = client.post("/purge/#{path}")
|
78
|
+
#res = client.post("/purge/", :path => path)
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
[User, Customer, Backend, Director, Domain, Match, Origin, Service, VCL, Version].each do |klass|
|
83
|
+
type = klass.to_s.downcase.split("::")[-1]
|
84
|
+
# self.send :define_method, "list_#{type}s".to_sym do
|
85
|
+
# list(klass)
|
86
|
+
# end
|
87
|
+
|
88
|
+
self.send :define_method, "get_#{type}".to_sym do |*args|
|
89
|
+
get(klass, *args)
|
90
|
+
end
|
91
|
+
|
92
|
+
self.send :define_method, "create_#{type}".to_sym do |obj|
|
93
|
+
create(klass, obj)
|
94
|
+
end
|
95
|
+
|
96
|
+
self.send :define_method, "update_#{type}".to_sym do |obj|
|
97
|
+
update(klass, obj)
|
98
|
+
end
|
99
|
+
|
100
|
+
self.send :define_method, "delete_#{type}".to_sym do |obj|
|
101
|
+
delete(klass, obj)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
# :method: create_version(opts)
|
107
|
+
# opts must contain a service_id param
|
108
|
+
|
109
|
+
##
|
110
|
+
# :method: create_backend(opts)
|
111
|
+
# opts must contain service_id, version and name params
|
112
|
+
|
113
|
+
##
|
114
|
+
# :method: create_director(opts)
|
115
|
+
# opts must contain service_id, version and name params
|
116
|
+
|
117
|
+
##
|
118
|
+
# :method: reate_domain(opts)
|
119
|
+
# opts must contain service_id, version and name params
|
120
|
+
|
121
|
+
##
|
122
|
+
# :method: create_match(opts)
|
123
|
+
# opts must contain service_id, version and name params
|
124
|
+
|
125
|
+
##
|
126
|
+
# :method: create_origin(opts)
|
127
|
+
# opts must contain service_id, version and name params
|
128
|
+
|
129
|
+
##
|
130
|
+
# :method: create_vcl(opts)
|
131
|
+
# opts must contain service_id, version and name params
|
132
|
+
|
133
|
+
##
|
134
|
+
# :method: get_user(id)
|
135
|
+
# Get a User
|
136
|
+
|
137
|
+
##
|
138
|
+
# :method: get_customer(id)
|
139
|
+
# Get a customer
|
140
|
+
|
141
|
+
##
|
142
|
+
# :method: get_service(id)
|
143
|
+
# Get a Service
|
144
|
+
|
145
|
+
##
|
146
|
+
# :method: get_version(service_id, number)
|
147
|
+
# Get a Version
|
148
|
+
|
149
|
+
##
|
150
|
+
# :method: get_backend(service_id, number, name)
|
151
|
+
# Get a backend
|
152
|
+
|
153
|
+
##
|
154
|
+
# :method: get_director(service_id, number, name)
|
155
|
+
# Get a Director
|
156
|
+
|
157
|
+
##
|
158
|
+
# :method: get_domain(service_id, number, name)
|
159
|
+
# Get a Domain
|
160
|
+
|
161
|
+
##
|
162
|
+
# :method: get_match(service_id, number, name)
|
163
|
+
# Get a Match
|
164
|
+
|
165
|
+
##
|
166
|
+
# :method: get_origin(service_id, number, name)
|
167
|
+
# Get an Origin
|
168
|
+
|
169
|
+
##
|
170
|
+
# :method: get_vcl(service_id, number, name)
|
171
|
+
# Get a VCL
|
172
|
+
|
173
|
+
##
|
174
|
+
# :method: get_version(service_id, number, name)
|
175
|
+
# Get a Version
|
176
|
+
|
177
|
+
##
|
178
|
+
# :method: get_settings(service_id, number, name)
|
179
|
+
# Get a Settings
|
180
|
+
|
181
|
+
##
|
182
|
+
# :method: update_user(user)
|
183
|
+
# You can also call
|
184
|
+
# user.save!
|
185
|
+
|
186
|
+
##
|
187
|
+
# :method: update_customer(customer)
|
188
|
+
# You can also call
|
189
|
+
# customer.save!
|
190
|
+
|
191
|
+
##
|
192
|
+
# :method: update_service(service)
|
193
|
+
# You can also call
|
194
|
+
# service.save!
|
195
|
+
|
196
|
+
##
|
197
|
+
# :method: update_version(version)
|
198
|
+
# You can also call
|
199
|
+
# version.save!
|
200
|
+
|
201
|
+
##
|
202
|
+
# :method: update_backend(backend)
|
203
|
+
# You can also call
|
204
|
+
# backend.save!
|
205
|
+
|
206
|
+
##
|
207
|
+
# :method: update_director(director)
|
208
|
+
# You can also call
|
209
|
+
# director.save!
|
210
|
+
|
211
|
+
##
|
212
|
+
# :method: update_domain(domain)
|
213
|
+
# You can also call
|
214
|
+
# domain.save!
|
215
|
+
|
216
|
+
##
|
217
|
+
# :method: update_match(match)
|
218
|
+
# You can also call
|
219
|
+
# match.save!
|
220
|
+
|
221
|
+
##
|
222
|
+
# :method: update_origin(origin)
|
223
|
+
# You can also call
|
224
|
+
# origin.save!
|
225
|
+
|
226
|
+
##
|
227
|
+
# :method: update_vcl(vcl)
|
228
|
+
# You can also call
|
229
|
+
# vcl.save!
|
230
|
+
|
231
|
+
##
|
232
|
+
# :method: update_version(version)
|
233
|
+
# You can also call
|
234
|
+
# version.save!
|
235
|
+
|
236
|
+
##
|
237
|
+
# :method: update_settings(settings)
|
238
|
+
# You can also call
|
239
|
+
# settings.save!
|
240
|
+
|
241
|
+
|
242
|
+
##
|
243
|
+
# :method: delete_user(user)
|
244
|
+
# You can also call
|
245
|
+
# user.delete!
|
246
|
+
|
247
|
+
##
|
248
|
+
# :method: delete_customer(customer)
|
249
|
+
# You can also call
|
250
|
+
# customer.delete!
|
251
|
+
|
252
|
+
##
|
253
|
+
# :method: delete_service(service)
|
254
|
+
# You can also call
|
255
|
+
# service.delete!
|
256
|
+
|
257
|
+
|
258
|
+
##
|
259
|
+
# :method: delete_version(version)
|
260
|
+
# You can also call
|
261
|
+
# version.delete!
|
262
|
+
|
263
|
+
|
264
|
+
##
|
265
|
+
# :method:delete_backend(backend)
|
266
|
+
# You can also call
|
267
|
+
# backend.delete!
|
268
|
+
|
269
|
+
|
270
|
+
##
|
271
|
+
# :method: delete_director(backend)
|
272
|
+
# You can also call
|
273
|
+
# backend.delete!
|
274
|
+
|
275
|
+
|
276
|
+
##
|
277
|
+
# :method: delete_domain(domain
|
278
|
+
# You can also call
|
279
|
+
# domain.delete!
|
280
|
+
|
281
|
+
|
282
|
+
##
|
283
|
+
# :method: delete_match(match)
|
284
|
+
# You can also call
|
285
|
+
# match.delete!(match)
|
286
|
+
|
287
|
+
|
288
|
+
##
|
289
|
+
# :method: delete_origin(origin)
|
290
|
+
# You can also call
|
291
|
+
# origin.delete!
|
292
|
+
|
293
|
+
|
294
|
+
##
|
295
|
+
# :method: delete_vcl(vcl)
|
296
|
+
# You can also call
|
297
|
+
# vcl.delete!
|
298
|
+
|
299
|
+
|
300
|
+
##
|
301
|
+
# :method: delete_version(version)
|
302
|
+
# You can also call
|
303
|
+
# version.delete!
|
304
|
+
|
305
|
+
|
306
|
+
|
307
|
+
##
|
308
|
+
# Attempts to load various config options in the form
|
309
|
+
#
|
310
|
+
# <key> = <value>
|
311
|
+
#
|
312
|
+
# From a file.
|
313
|
+
#
|
314
|
+
# Skips whitespace and lines starting with C<#>.
|
315
|
+
#
|
316
|
+
def self.load_config(file)
|
317
|
+
options = {}
|
318
|
+
return options unless File.exist?(file)
|
319
|
+
|
320
|
+
File.open(file, "r") do |infile|
|
321
|
+
while (line = infile.gets.chomp) do
|
322
|
+
next if line =~ /^#/;
|
323
|
+
next if line =~ /^\s*$/;
|
324
|
+
next unless line =~ /=/;
|
325
|
+
line.strip!
|
326
|
+
key, val = line.split(/\s*=\s*/, 2)
|
327
|
+
options[key] = val;
|
328
|
+
end
|
329
|
+
end
|
330
|
+
options;
|
331
|
+
end
|
332
|
+
|
333
|
+
##
|
334
|
+
# Tries to load options from the file[s] passed in using,
|
335
|
+
# C<load_options>, stopping when it finds the first one.
|
336
|
+
#
|
337
|
+
# Then it overrides those options with command line options
|
338
|
+
# of the form
|
339
|
+
#
|
340
|
+
# --<key>=<value>
|
341
|
+
#
|
342
|
+
def self.get_options(files)
|
343
|
+
options = {}
|
344
|
+
files.each do |file|
|
345
|
+
next unless File.exist?(file)
|
346
|
+
options = load_options(file)
|
347
|
+
break
|
348
|
+
end
|
349
|
+
|
350
|
+
while (ARGV.size>0 && ARGV[0] =~ /^-+(\w+)\=(\w+)$/) do
|
351
|
+
options[$1] = $2;
|
352
|
+
@ARGV.shift;
|
353
|
+
end
|
354
|
+
raise"Couldn't find options from command line arguments or #{files.join(', ')}" unless options.size>0
|
355
|
+
options;
|
356
|
+
end
|
357
|
+
end
|