fastly-deploy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []