fastly-deploy 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/deploy.rb +56 -0
- data/lib/detect_includes.rb +23 -0
- data/lib/methods.rb +129 -0
- metadata +47 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ee84ea69e9948befc15426b5f396918203466efe
|
4
|
+
data.tar.gz: 084e583ee631b036b43e04cca10f17ef55cbd3fa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0ed50d1aea45387acf64757076d8231b8aeb764dfb2c60842aff5f9164a454625cf91fbe869f03ad791ab9c133943a3560ff1053d0424e668ec361cde76623db
|
7
|
+
data.tar.gz: 5af1a824f78b66e81f59c386dc10ada73b4a6da527333e97363e0dd048461f9db8fa49afa070dbd0e08ddcce7e4c6a140a291a2596bc4a1cabf232eea759aeab
|
data/bin/deploy.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/methods'
|
4
|
+
require_relative '../lib/detect_includes'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
def deploy(argv)
|
8
|
+
options = {}
|
9
|
+
optparse = OptionParser.new do |opts|
|
10
|
+
opts.banner = "Usage: deploy.rb [options]"
|
11
|
+
opts.on("-k", "--api-key API_KEY", "Fastly API Key") do |api_key|
|
12
|
+
options[:api_key] = api_key
|
13
|
+
end
|
14
|
+
opts.on("-s", "--service-id SERVICE_ID", "Service ID") do |service_id|
|
15
|
+
options[:service_id] = service_id
|
16
|
+
end
|
17
|
+
opts.on("-v", "--vcl-path FILE", "VCL Path") do |vcl_path|
|
18
|
+
options[:vcl_path] = vcl_path
|
19
|
+
end
|
20
|
+
opts.on("-i", "--vcl-includes INCLUDES_DIR", "Includes Directory") do |includes_dir|
|
21
|
+
options[:includes_dir] = includes_dir
|
22
|
+
end
|
23
|
+
options[:purge_all] = false
|
24
|
+
opts.on("-p", "--purge-all", "Purge All") do |purge_all|
|
25
|
+
options[:purge_all] = true
|
26
|
+
end
|
27
|
+
opts.on('-h', '--help', 'Display this screen') do
|
28
|
+
puts opts
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
end
|
32
|
+
optparse.parse! argv
|
33
|
+
|
34
|
+
if options[:api_key].nil? ||
|
35
|
+
options[:service_id].nil? ||
|
36
|
+
options[:vcl_path].nil? then
|
37
|
+
puts optparse
|
38
|
+
exit 1
|
39
|
+
end
|
40
|
+
|
41
|
+
includes = get_includes options[:vcl_path], options[:includes_dir]
|
42
|
+
puts includes
|
43
|
+
|
44
|
+
deploy_vcl options[:api_key],
|
45
|
+
options[:service_id],
|
46
|
+
options[:vcl_path],
|
47
|
+
options[:purge_all],
|
48
|
+
includes
|
49
|
+
return options[:api_key]
|
50
|
+
end
|
51
|
+
|
52
|
+
# This is only run when run as a script. The FILE bit stops it
|
53
|
+
# from being run during the tests
|
54
|
+
if __FILE__ == $0
|
55
|
+
deploy ARGV
|
56
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
def get_includes(main_vcl_path, includes_dir)
|
2
|
+
includes_found = []
|
3
|
+
get_includes_for_vcl main_vcl_path, includes_dir, includes_found
|
4
|
+
return includes_found
|
5
|
+
end
|
6
|
+
|
7
|
+
def get_includes_for_vcl(vcl_path, includes_dir, includes_found)
|
8
|
+
direct_includes = get_includes_directly_in_vcl vcl_path, includes_dir
|
9
|
+
direct_includes_not_already_found = direct_includes - includes_found
|
10
|
+
|
11
|
+
direct_includes_not_already_found.map do |include_vcl|
|
12
|
+
includes_found.push include_vcl
|
13
|
+
get_includes_for_vcl include_vcl, includes_dir, includes_found
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_includes_directly_in_vcl(vcl_path, includes_dir)
|
18
|
+
# Using '$' for line ending is os dependent and fails w/windows line endings on linux
|
19
|
+
include_pattern = /^include "(.*)";?[\r\n]+/
|
20
|
+
return File.readlines(vcl_path).select { |line| include_pattern.match(line) }
|
21
|
+
.map{ |line| include_pattern.match(line)[1] }
|
22
|
+
.map{ |vcl_file_name| File.join(includes_dir, vcl_file_name + ".vcl")}
|
23
|
+
end
|
data/lib/methods.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'fastly'
|
2
|
+
require 'net/http'
|
3
|
+
require 'colorize'
|
4
|
+
|
5
|
+
def deploy_vcl(api_key, service_id, vcl_path, purge_all, include_files)
|
6
|
+
|
7
|
+
login_opts = { :api_key => api_key }
|
8
|
+
fastly = Fastly.new(login_opts)
|
9
|
+
service = fastly.get_service(service_id)
|
10
|
+
|
11
|
+
active_version = service.versions.find{|ver| ver.active?}
|
12
|
+
puts "Active Version: #{active_version.number}"
|
13
|
+
domain = fastly.list_domains(:service_id => service.id,
|
14
|
+
:version => active_version.number).first
|
15
|
+
puts "Domain Name: #{domain.name}"
|
16
|
+
|
17
|
+
new_version = active_version.clone
|
18
|
+
puts "New Version: #{new_version.number}"
|
19
|
+
|
20
|
+
fastly.list_vcls(:service_id => service.id,
|
21
|
+
:version => new_version.number)
|
22
|
+
.each { |vcl| vcl.delete! }
|
23
|
+
|
24
|
+
can_verify_deployment = upload_main_vcl new_version, vcl_path, service_id
|
25
|
+
|
26
|
+
if include_files != nil
|
27
|
+
include_files.each do | include_file |
|
28
|
+
upload_include_vcl new_version, include_file, service_id
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
puts "Validating..."
|
33
|
+
|
34
|
+
validate(new_version)
|
35
|
+
|
36
|
+
puts "Activating..."
|
37
|
+
new_version.activate!
|
38
|
+
|
39
|
+
if can_verify_deployment then
|
40
|
+
print "Waiting for changes to take effect."
|
41
|
+
attempts = 1
|
42
|
+
deployed_vcl_version_number = 0
|
43
|
+
|
44
|
+
while attempts < 150 && deployed_vcl_version_number != new_version.number.to_s do
|
45
|
+
sleep 2
|
46
|
+
url = URI.parse("http://#{domain.name}.global.prod.fastly.net/vcl_version")
|
47
|
+
req = Net::HTTP::Get.new(url.to_s)
|
48
|
+
res = Net::HTTP.start(url.host, url.port) {|http|
|
49
|
+
http.request(req)
|
50
|
+
}
|
51
|
+
deployed_vcl_version_number = res.body
|
52
|
+
print "."
|
53
|
+
attempts += 1
|
54
|
+
end
|
55
|
+
puts "done."
|
56
|
+
|
57
|
+
if deployed_vcl_version_number != new_version.number.to_s then
|
58
|
+
STDERR.puts "Verify failed. /vcl_version returned [#{deployed_vcl_version_number}].".red
|
59
|
+
exit 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
if purge_all then
|
64
|
+
puts "Purging all..."
|
65
|
+
service.purge_all
|
66
|
+
end
|
67
|
+
puts "Deployment complete.".green
|
68
|
+
end
|
69
|
+
|
70
|
+
def upload_main_vcl(version, vcl_path, service_id)
|
71
|
+
vcl_name = File.basename(vcl_path, ".vcl")
|
72
|
+
can_verify_deployment = upload_vcl version, vcl_path, vcl_name, service_id
|
73
|
+
version.vcl(vcl_name).set_main!
|
74
|
+
return can_verify_deployment
|
75
|
+
end
|
76
|
+
|
77
|
+
def upload_include_vcl(version, vcl_path, service_id)
|
78
|
+
vcl_name = File.basename(vcl_path, ".vcl")
|
79
|
+
upload_vcl version, vcl_path, vcl_name, service_id
|
80
|
+
end
|
81
|
+
|
82
|
+
def upload_vcl(version, vcl_path, name, service_id)
|
83
|
+
vcl_contents_from_file = File.read(vcl_path)
|
84
|
+
vcl_contents_with_service_id_injection = inject_service_id vcl_contents_from_file, service_id
|
85
|
+
vcl_contents_with_deploy_injection = inject_deploy_verify_code(vcl_contents_with_service_id_injection, version.number)
|
86
|
+
|
87
|
+
puts "Uploading #{name}"
|
88
|
+
version.upload_vcl name, vcl_contents_with_deploy_injection
|
89
|
+
|
90
|
+
return vcl_contents_with_deploy_injection != vcl_contents_with_service_id_injection
|
91
|
+
end
|
92
|
+
|
93
|
+
def inject_deploy_verify_code(vcl, version_num)
|
94
|
+
deploy_recv_vcl = <<-END
|
95
|
+
# --------- DEPLOY VERIFY CHECK START ---------
|
96
|
+
if (req.url == "/vcl_version") {
|
97
|
+
error 902;
|
98
|
+
}
|
99
|
+
# --------- DEPLOY VERIFY CHECK END ---------
|
100
|
+
END
|
101
|
+
|
102
|
+
deploy_error_vcl = <<-END
|
103
|
+
# --------- DEPLOY VERIFY CHECK START ---------
|
104
|
+
if (obj.status == 902) {
|
105
|
+
set obj.status = 200;
|
106
|
+
set obj.response = "OK";
|
107
|
+
synthetic "#{version_num}";
|
108
|
+
return(deliver);
|
109
|
+
}
|
110
|
+
# --------- DEPLOY VERIFY CHECK END ---------
|
111
|
+
END
|
112
|
+
|
113
|
+
vcl.gsub(/#7D_DEPLOY recv/, deploy_recv_vcl)
|
114
|
+
.gsub(/#7D_DEPLOY error/, deploy_error_vcl)
|
115
|
+
end
|
116
|
+
|
117
|
+
def inject_service_id(vcl_contents, service_id)
|
118
|
+
vcl_contents.gsub(/#7D_FASTLY_SERVICE_ID/, service_id)
|
119
|
+
end
|
120
|
+
|
121
|
+
def validate(version)
|
122
|
+
path = version.class.get_path(version.service_id, version.number)
|
123
|
+
response = version.fetcher.client.get("#{path}/validate")
|
124
|
+
status = response["status"]
|
125
|
+
if status!= "ok"
|
126
|
+
raise response["msg"]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fastly-deploy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- 7digital
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-07-06 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Automated deploys for Fastly vcl configs
|
14
|
+
email: developers@7digital.com
|
15
|
+
executables:
|
16
|
+
- deploy.rb
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/deploy.rb
|
21
|
+
- lib/detect_includes.rb
|
22
|
+
- lib/methods.rb
|
23
|
+
homepage: https://github.com/7digital/fastly-deploy
|
24
|
+
licenses:
|
25
|
+
- MIT
|
26
|
+
metadata: {}
|
27
|
+
post_install_message:
|
28
|
+
rdoc_options: []
|
29
|
+
require_paths:
|
30
|
+
- lib
|
31
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
requirements: []
|
42
|
+
rubyforge_project:
|
43
|
+
rubygems_version: 2.5.0
|
44
|
+
signing_key:
|
45
|
+
specification_version: 4
|
46
|
+
summary: Automated deploys for Fastly vcl configs
|
47
|
+
test_files: []
|