fastly-deploy 0.0.1
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/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: []
|